masquitos

Backend Node.js + Inversify

Jan 29th, 2021 (edited)
102
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // controller
  2. @controller("/public/auth")
  3. export class AuthController implements interfaces.Controller {
  4.   constructor(
  5.     @inject(TYPES.AuthService) private authService: AuthService,
  6.     @inject(TYPES.Logger)
  7.     private logger: ILogger
  8.   ) {}
  9.  
  10.   @httpPost("/", TYPES.AuthMiddleWare)
  11.   private async index(req, res) {
  12.     const dto: IAuthDto = req.body;
  13.  
  14.     try {
  15.       const token = await this.authService.getToken(dto);
  16.       this.logger.log("success auth");
  17.       return res.json(Requester.createBody({ token }));
  18.     } catch (e) {
  19.       return res.json(Requester.createError(e));
  20.     }
  21.   }
  22. }
  23. // middleware
  24. @injectable()
  25. export class AuthMiddleware extends BaseMiddleware {
  26.   public handler(
  27.     req: express.Request,
  28.     res: express.Response,
  29.     next: express.NextFunction
  30.   ) {
  31.     const dto: IAuthDto = req.body;
  32.     if (!AuthValidator.isValid(dto)) {
  33.       throw new InvalidDataError();
  34.     }
  35.     next();
  36.   }
  37. }
  38. // validator
  39. export class AuthValidator {
  40.   public static isValid(data: IAuthDto): boolean {
  41.     const isEmailValid = EmailValidator.isValid(data.email);
  42.     try {
  43.       const isPasswordLength = validator.isLength(data.password, {
  44.         min: MIN_PASSWORD_LENGTH,
  45.         max: MAX_PASSWORD_LENGTH,
  46.       });
  47.       return isEmailValid && isPasswordLength;
  48.     } catch (e) {
  49.       return false;
  50.     }
  51.   }
  52. }
  53.  
  54. // service
  55. @injectable()
  56. export class AuthService implements IAuthService {
  57.   constructor(
  58.     @inject(TYPES.UserRepository) private repository: IUserRepository,
  59.     @inject(TYPES.Logger) private logger: ILogger
  60.   ) {}
  61.  
  62.   public async getToken(dto: IAuthDto): Promise<string> {
  63.     this.logger.log("Try auth", dto.email);
  64.     const user: User = await this.getUser(dto.email);
  65.     this.checkRole(user.role);
  66.     await this.comparePassword(dto.password, user.passwordHash);
  67.     const updatedUser = await this.updateLastEnter(user);
  68.     return TokenGenerator.getToken(updatedUser);
  69.   }
  70.  
  71.   private async getUser(email: string): Promise<User> {
  72.     const user = await this.repository.getUserByEmail(email);
  73.     if (user) {
  74.       return user;
  75.     }
  76.     this.logger.log("User not exist", email);
  77.     throw new InvalidUserOrPasswordError();
  78.   }
  79.  
  80.   private checkRole(role: string) {
  81.     if (role !== UserRole.USER) {
  82.       this.logger.log("Wrong role!");
  83.       throw new InvalidUserRoleError();
  84.     }
  85.   }
  86.  
  87.   private async comparePassword(password: string, hash: string) {
  88.     const isSuccess = await bcrypt.compare(password, hash);
  89.  
  90.     if (!isSuccess) {
  91.       this.logger.log("Wrong password");
  92.       throw new InvalidUserOrPasswordError();
  93.     }
  94.   }
  95.  
  96.   private async updateLastEnter(user: User): Promise<User> {
  97.     return await this.repository.updateUserIdentity(user.id);
  98.   }
  99. }
  100.  
  101. // controller test
  102. describe("AuthController", function () {
  103.   it("/auth При верном логине/пароле возращается токен", async () => {
  104.     await request(app)
  105.       .post("/public/auth")
  106.       .send(environment.test.auth)
  107.       .expect((res) => {
  108.         assert.strictEqual(validator.isJWT(res.body.data.token), true);
  109.       });
  110.   });
  111.  
  112.   it("/auth При не верном логине/пароле возращается ошибка", async () => {
  113.     await request(app)
  114.       .post("/public/auth")
  115.       .send({
  116.         email: "masquitos@mail.ru",
  117.         password: "123456",
  118.       })
  119.       .expect((res) => {
  120.         const e = new InvalidUserOrPasswordError();
  121.         assert.strictEqual(res.body.error.code, e.code);
  122.       });
  123.   });
  124.  
  125.   it("/auth При не валидных данных код 22", async () => {
  126.     await request(app)
  127.       .post("/public/auth")
  128.       .send({
  129.         email: "mail",
  130.         password: null,
  131.       })
  132.       .expect((res) => {
  133.         const err = new InvalidDataError();
  134.         assert.strictEqual(res.body.error.code, err.code);
  135.       });
  136.   });
  137. });
  138.  
  139. // service test
  140. describe("AuthService", function () {
  141.   it("При не верной роли ошибка", async () => {
  142.     const getUser = () => Promise.resolve<User>(new User(
  143.           null,
  144.           null,
  145.           null,
  146.           null,
  147.           null,
  148.           UserRole.SERVICE_SUPPORT,
  149.           null,
  150.           null
  151.       ));
  152.  
  153.     const stub = sinon.stub(AuthService.prototype, <any>"getUser");
  154.     stub.callsFake(getUser);
  155.  
  156.     const service = diContainer.get<IAuthService>(TYPES.AuthService);
  157.     await assert.rejects(
  158.       () => service.getToken({ email: "asda", password: " 123" }),
  159.       new InvalidUserRoleError()
  160.     );
  161.   });
  162. });
  163.  
Add Comment
Please, Sign In to add comment