Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Rachel
Rachel

Posted on

     

Part 2: User Roles and Management - FeathersJS

The Backend - FeathersJS

This article focuses on the backend, which leverages theFeathersJS framework and several complementary libraries in the FeatherJS Ecosystem:feathers-authentication-management andfeathers-permissions.

Getting Started With FeatherJS

Getting started with FeathersJS is pretty easy. There's a CLI that generates an application based on several configurable options.

Note: I would advise against copying/pasting any code snippets and instead go directly to the repository to view the code. Due to the amount of code involved, I've omitted lines of code in this article for brevity. As this is not written as a tutorial, please view the repository if you want to create a similar project.

FeathersJS Overview

Feathers has a greatgetting started guide, so I'd highly recommend reviewing their guide for a more in-depth overview. I'll highlight a few features that are customized for this starter.

Configuration

With Feathers,configuration is fairly straightforward. It takes theNODE_ENV environment variable to determine which configuration to use. For example, ifNODE_ENV=prod, then it will merge thedefault.json withprod.json configuration settings. We'll add some settings to the configuration file to ensure services have the necessary values to run properly.

On Login

I wanted to store a timestamp for when a user logs in, so I used theapp.on('login'...) connection event.

app.on('login',(data)=>{data.user['lastLoggedIn']=newDate();app.service('users').patch(data.user._id,data.user);});
Enter fullscreen modeExit fullscreen mode

Feathers Services

Feathers services can be generated using the command line generator withfeathers generate service. This will begin a prompt sequence that configures the service to your needs.Services in feathers consist of a class, hooks, and a service definition.

Feathers Mailer

To send emails, the server uses thefeathers-mailer library, which is a wrapper fornodemailer. For this starter, I configured it forAWS SES, but you can use anysupported transport. To configure for AWS, the following configuration keys will be needed from your AWS account:

{"smtp_user":"aws_smtp_user","smtp_pw":"aws_smtp_pw","smtp_host":"aws_smtp_host"}
Enter fullscreen modeExit fullscreen mode

You can add these to the${env}.json configuration file ordefault.json configuration file.

I created a custom service using the feathers cli and configured it for the AWS SES Transport. Theemail service shows how this is set up.

module.exports=function(app){app.use('/email',Mailer(smtpTransport({host:app.get('smtp_host'),secure:true,auth:{user:app.get('smtp_user'),pass:app.get('smtp_pw'),},})));};
Enter fullscreen modeExit fullscreen mode

Once the email service is configured, it can be used to verify emails on sign up with the feathers-authentication-management library.

Coming Soon: I'll be writing a separate article about creating beautiful templated emails to send out using this service.

Feathers Authentication Management

Feathers Authentication Management is a library that enables several useful features during the user signup process:

  • email verification
  • password reset
  • update password
  • update to new email with verification

To add it to the user workflow, I created anauth-management service.

constauthManagement=require('feathers-authentication-management');consthooks=require('./auth-management.hooks');constnotifier=require('./notifier');module.exports=function(app){app.configure(authManagement(notifier(app)));// Get our initialized service so that we can register hooksconstservice=app.service('authManagement');service.hooks(hooks);};
Enter fullscreen modeExit fullscreen mode

Thenotifier processes the incoming request and handles the case accordingly based on theaction received from the request. TheresendVerifySignup case will resend the verification email to the user.

functionsendEmail(email){returnapp.service('email').create(email).catch((err)=>{console.log('Error sending email',err);});}switch(type){case'resendVerifySignup'://sending the user the verification emailtokenLink=getLink('verify',user.verifyToken);email={from:FROM_EMAIL,to:user.email,subject:'Verify Email',html:tokenLink,};returnsendEmail(email);}
Enter fullscreen modeExit fullscreen mode

To ensure this service has all the necessary information to generate the correct email, the following configuration keys were also added to the${env}.json file.

{"from_email":"no-reply@test.com","client_url":"http://localhost:8080","api_url":"http://localhost:3030/"}
Enter fullscreen modeExit fullscreen mode

Hooks are used to update the user record before and after various actions.

module.exports={before:{create:[// after user is created, add verification fields to user recordverifyHooks.addVerification(),],patch:[authenticate('jwt'),iff(// if request is from external providerisProvider('external'),// do not allow the following fields to be updatingpreventChanges(true,'email','isVerified','verifyToken','verifyShortToken','verifyExpires','verifyChanges','resetToken','resetShortToken','resetExpires'),),],// don't allow external requests to delete the userremove:[disallow('external')],},after:{all:[// prevent leak of these user information fieldsprotect('password','verifyToken','updatedAt','createdAt','verifyShortToken','verifyExpires','resetToken','resetExpires','verifyChanges','__v'),],create:[// after a user is created, send the user an email to verify email(context)=>{accountService(context.app).notifier('resendVerifySignup',context.data);},// remove the user verification fields before returning user as part of requestverifyHooks.removeVerification(),],},};
Enter fullscreen modeExit fullscreen mode

After a user is created, the verification fields are added to the user (and later removed before being return as part of a request). For security purposes, fields also should not be directly updated by external requests. After a user is created, another hook sends the user a verification email before removing the verification fields from the user.

Feathers Permissions

Finally, the backend implements the role concept usingfeathers-permissions, using a manually created admin account. Accounts default to a 'guest' role defined in the mongoose model (covered in the next article).

The admin role can update users into other roles. This starter defines 4 roles: 'guest' (default role), 'user', 'admin', 'inactive'. If an admin deactivates a user, it will update their role to 'inactive'.

Hooks are used to control and limit access to specific admin functions, such as updating a user role.

iff(checkPermissions({roles:['super_admin','admin'],field:'permissions',error:false,}),validate.mongoose(adminUpdateSchema,joiOptions)),iff((context)=>!context.params.permitted,[// ensure user only updates their own recordsetField({from:'params.user._id',as:'params.query._id',}),validate.mongoose(updateSchema,joiOptions),]),
Enter fullscreen modeExit fullscreen mode

The hooks above check if the user is an admin, and if so, check the data against the approved admin schema (which allows more fields to be updated). If the user isn't an admin, make sure the user only updates their own record with the approved user schema.

The permissions can be refined even further. Check thedocumentation for details. I kept it simple for this starter.

Additional Resources

Special shoutout to these authors who wrote tutorials for setting up email verification.

Did I miss anything?

This wraps up the backend code. Let me know if you have any questions, comments or suggestions. In the next article, I'll be reviewing the MongoDB setup!

Top comments(0)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

I am a Creative Software Engineer/Tech Lead and a former PropTech Co-founder. I work remotely on innovative tech solutions.
  • Location
    Houston, TX
  • Joined

More fromRachel

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp