# Authorization
# Introduction
In addition to enabling you build a secured application, ExpressWebJs also provides a simple way to authorize user actions against a given resource. For example, even though a user is authenticated, they may not be authorized to update or delete certain records in the database. ExpressWebJs authorization features provide an easy, organized way of managing these types of authorization checks.
# Prerequisites
Before we continue with ExpressWebJS Identity Manager, you should make sure the following models and schemas does not exist in the system.
- Permissions_model.ts
- Role_permissions_model.ts
- Roles_model.ts
- User_roles_model.ts
If you are using SQL database, you should also make sure the above mentioned model schemas does not exist in your Database/Migrations directory.
We can now run the following maker command to generate our database models and schemas(for SQL database) needed for authorization operations.
ts-node maker make-identity
Copied!
Once that is done, we can now create a ManyToMany relationship with Roles_model and our already existing User_model.
For SQL Model, we will do this:
"use strict"; import { Model } from "Elucidate/Database/Model"; import Roles_mode from "./Roles_model"; class User extends Model { // Model attributes id!: number; first_name!: string; last_name!: string; email!: string; password!: string; // Table name static tableName = "users"; static relationMappings = { roles: { relation: Model.ManyToManyRelation, modelClass: Roles_mode, join: { from: "users.id", through: { from: "user_roles.user_id", to: "user_roles.role_id", }, to: "roles.id", }, }, }; } export default User;
Copied!
You can now run your migration with the following Maker command.
ts-node maker run-sql-migration
Copied!
Or with the short hand
ts-node maker rsqlm
Copied!
For NOSQL Model, we will do this:
"use strict"; import { mongoose, Schema, Document } from "Elucidate/Database/NoSQLModel"; import Roles from "./Roles_model"; import uniqueValidator from "mongoose-unique-validator"; export interface UserInterface extends Document { username: string; email: string; password: string; } const UserSchema: Schema = new Schema({ username: { type: String, required: true }, email: { type: String, required: true, unique: true }, role: [{ type: mongoose.Schema.Types.ObjectId, ref: Roles }], password: { type: String, required: true }, }); UserSchema.set("timestamps", true); UserSchema.plugin(uniqueValidator); const User = mongoose.model<UserInterface>("User", UserSchema); export default User;
Copied!
Next register Identity Manager in the AppServiceProvider in App/Providers/AppServiceProvider.ts register method.
import ServiceProvider from "Elucidate/Support/ServiceProvider"; import IdentityManager from "Elucidate/IdentityManager"; class AppServiceProvicer extends ServiceProvider { /** * Register any application services. * @return void */ public register() { this.app.register("IdentityManager", IdentityManager, "class"); } /** * Bootstrap any application services. * @return void */ public async boot() { // } } export default AppServiceProvicer;
Copied!
Once that is done, we can now inject it in our Controllers class or Services class or any other class we want to use it with. Let's use it in our UserController class in App/Http/Controller/UserController.ts
"use strict"; import { Request, Response, NextFunction } from "Elucidate/HttpContext"; import HttpResponse from "Elucidate/HttpContext/ResponseType"; import IdentityManager from "Elucidate/IdentityManager"; //this is the IdentityManger type class UserController { protected identityManager: IdentityManager; constructor(IdentityManager: IdentityManager) { this.identityManager = IdentityManager; } getSystemRoles = async (req: Request, res: Response, next: NextFunction) => { try { let roles = await this.identityManager.getRoles(); return HttpResponse.OK(res, roles); } catch (error) { return next(error); } }; /** * Display a listing of the resource. */ checkUserRole = async (req: Request, res: Response, next: NextFunction) => { try { return await this.identityManager .hasRole(req.user["id"], req.params["role"]) .then((result) => { return HttpResponse.OK(res, result); }) .catch((err) => { return HttpResponse.EXPECTATION_FAILED(res, err); }); } catch (error) { return next(error); } }; /** * Show the form for creating a new resource. * * @return Response */ createRole = async (req: Request, res: Response, next: NextFunction) => { try { let { name, description } = req.body; return await this.identityManager .createRole(name, description) .then((createdRole) => { return HttpResponse.OK(res, createdRole); }) .catch((err) => { return HttpResponse.EXPECTATION_FAILED(res, err); }); } catch (error) { return next(error); } }; /** * Store a newly created resource in storage. * @param Request * @return Response */ addUserToRole = async (req: Request, res: Response, next: NextFunction) => { try { let { role_id, user_id } = req.body; return await this.identityManager .assignRoleToUser(role_id, user_id) .then((result) => { return HttpResponse.OK(res, result); }) .catch((err) => { return HttpResponse.EXPECTATION_FAILED(res, err); }); } catch (error) { return next(error); } }; } export default UserController;
Copied!
# Basic Usage
//Creating a new role let roleName = "Admin"; let roleDescription = "System Admin"; IdentityManager.createRole(roleName, roleDescription); //Creating a new permission let permissionName = "edit articles"; let permissionDescription = "This permission can only edit articles"; IdentityManager.createPermission(permissionName, permissionDescription);
Copied!
A permission or multiple permissions can be synced to a role:
let roleId = "2"; let permissionIds = ["1", "2", "3", "4", "5"]; IdentityManager.giveRolePermission(roleId, permissionIds);
Copied!
A permission or multiple permissions can be removed from a role:
let roleId = "2"; let permissionIds = ["1", "2", "3", "4", "5"]; IdentityManager.revokeRolePermissions(roleId, permissionIds);
Copied!