From 388fff9175d937ab5c1f055e699275a2bf330005 Mon Sep 17 00:00:00 2001 From: Abdul Rahman Reza Date: Sat, 30 Nov 2024 12:56:44 +0700 Subject: [PATCH] update entity type and reset password --- assets/reset_password.html | 73 +++++++++++++++++++++++++ config/default.json | 6 ++- config/stag.json | 6 ++- package.json | 8 +-- src/controllers/auth.ts | 30 +++++++++-- src/controllers/user.ts | 4 +- src/controllers/user_activity.ts | 6 +-- src/controllers/user_refresh_token.ts | 4 +- src/controllers/user_roles.ts | 8 +-- src/entity/user_activity.ts | 64 ---------------------- src/entity/user_refresh_token.ts | 64 ---------------------- src/entity/users.ts | 76 --------------------------- src/entity/users_roles.ts | 41 --------------- src/helpers/common.ts | 10 ++++ src/helpers/express/return.ts | 2 +- src/helpers/orm.ts | 5 +- src/types/action.ts | 7 --- src/types/error.ts | 3 -- src/types/paging.ts | 8 --- src/types/role.ts | 23 -------- src/types/status.ts | 4 -- 21 files changed, 137 insertions(+), 315 deletions(-) create mode 100644 assets/reset_password.html delete mode 100644 src/entity/user_activity.ts delete mode 100644 src/entity/user_refresh_token.ts delete mode 100644 src/entity/users.ts delete mode 100644 src/entity/users_roles.ts delete mode 100644 src/types/action.ts delete mode 100644 src/types/error.ts delete mode 100644 src/types/paging.ts delete mode 100644 src/types/role.ts delete mode 100644 src/types/status.ts diff --git a/assets/reset_password.html b/assets/reset_password.html new file mode 100644 index 0000000..36cc156 --- /dev/null +++ b/assets/reset_password.html @@ -0,0 +1,73 @@ + + + + + + Reset Password BRI TL + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + +
 
 
+ + + + + + + + + + +
 
+

+ Hi {NAME}, You have requested to reset your password

+ +

+ We cannot simply send you your old password. A unique link to reset your + password has been generated for you. To reset your password, click the + following link and follow the instructions. +

+ Reset + Password +
 
+
 
 
+
+ + + + \ No newline at end of file diff --git a/config/default.json b/config/default.json index 2346631..695e002 100644 --- a/config/default.json +++ b/config/default.json @@ -29,6 +29,10 @@ }, "auth": { "refresh_token_lifetime_day": 30, - "access_token_lifetime": 300 + "access_token_lifetime": 300, + "reset_password_url": "https://bri-dev.shiblysolution.id/reset-password/" + }, + "service": { + "notification": "http://127.0.0.1:4008/" } } diff --git a/config/stag.json b/config/stag.json index 483342c..86e54ee 100644 --- a/config/stag.json +++ b/config/stag.json @@ -29,6 +29,10 @@ }, "auth": { "refresh_token_lifetime_day": 30, - "access_token_lifetime": 300 + "access_token_lifetime": 300, + "reset_password_url": "https://bri-dev.shiblysolution.id/reset-password/" + }, + "service": { + "notification": "http://127.0.0.1:4008/" } } diff --git a/package.json b/package.json index 5a02340..6b9175b 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,11 @@ { - "name": "boilerplate-bri", + "name": "Service user", "version": "1.0.0", - "description": "This kind of project was built to present base application regarding BRI ERP Project", + "description": "Purpose of this service is to provide authorization, roles, user activity and etc", "main": "src/index.ts", "scripts": { "dev": "nodemon", - "build": "rimraf dist && tsc", + "build": "tsc", "swagger": "node src/swagger/builder.js" }, "keywords": [ @@ -14,11 +14,13 @@ "author": "STS", "license": "ISC", "dependencies": { + "axios": "^1.7.8", "bcryptjs": "^2.4.3", "compression": "^1.7.5", "config": "^3.3.12", "cors": "^2.8.5", "dayjs": "^1.11.13", + "Entity": "file:../entity", "express": "^4.21.1", "express-jwt": "^8.4.1", "fast-csv": "^5.0.2", diff --git a/src/controllers/auth.ts b/src/controllers/auth.ts index 719dff2..3c8f68e 100644 --- a/src/controllers/auth.ts +++ b/src/controllers/auth.ts @@ -2,18 +2,18 @@ import { Response, NextFunction, Application } from "express"; import { Request } from 'express-jwt' import { ReturnHelper } from "../helpers/express/return"; import { OrmHelper } from "../helpers/orm"; -import { User } from "../entity/users"; import Joi from "joi"; import config from "config"; import { ILogObj, Logger } from "tslog"; import { Language } from "../langs/lang"; -import { UserRefreshToken } from "../entity/user_refresh_token"; import { UAParser } from 'ua-parser-js'; import dayjs from 'dayjs' import jwt from 'jsonwebtoken'; import fs from 'fs'; -import { UserRole } from "../entity/users_roles"; import { v4 as uuidv4 } from 'uuid'; +import { EmailBody, User, UserRefreshToken, UserRole } from "Entity"; +import axios from 'axios'; +import CommonHelper from "../helpers/common"; const log: Logger = new Logger({ name: '[UserController]', type: 'pretty' }); @@ -170,8 +170,30 @@ export class AuthController { await userRepository.save(user); //send email reset password + const url = config.get("service.notification") + "api/email/send"; - return ReturnHelper.successResponseAny(res, 200, Language.lang.success, {}); + console.log(url, 'url') + + const template_raw = fs.readFileSync('assets/reset_password.html').toString(); + + const pairMap = { + 'LINK': config.get('auth.reset_password_url') + user.reset_token, + 'NAME': user.name + } + + const template = CommonHelper.generateTemplate(template_raw, pairMap); + + const email: EmailBody = { + subject: "Reset Password", + to: [user.email], + cc: [], + bcc: [], + html: template + } + + const { data } = await axios.post(url, email); + + return ReturnHelper.successResponseAny(res, 200, Language.lang.success, data); // return ReturnHelper.errorResponse(res, 403, 401, Language.lang.failed_access); diff --git a/src/controllers/user.ts b/src/controllers/user.ts index 2c5d520..ed492f5 100644 --- a/src/controllers/user.ts +++ b/src/controllers/user.ts @@ -2,11 +2,11 @@ import { Response, NextFunction, Application } from "express"; import { Request } from "express-jwt"; import { ReturnHelper } from "../helpers/express/return"; import { OrmHelper } from "../helpers/orm"; -import { User } from "../entity/users"; +import { User } from "Entity"; import Joi from "joi"; import { ILogObj, Logger } from "tslog"; import { Language } from "../langs/lang"; -import { Paging } from "../types/paging"; +import { Paging } from "Entity"; import CommonHelper from "../helpers/common"; import * as fastcsv from 'fast-csv'; import dayjs from "dayjs"; diff --git a/src/controllers/user_activity.ts b/src/controllers/user_activity.ts index 1da94a7..f6cfe3e 100644 --- a/src/controllers/user_activity.ts +++ b/src/controllers/user_activity.ts @@ -5,12 +5,12 @@ import { OrmHelper } from "../helpers/orm"; import Joi from "joi"; import { ILogObj, Logger } from "tslog"; import { Language } from "../langs/lang"; -import { Paging } from "../types/paging"; +import { Paging } from "Entity"; import CommonHelper from "../helpers/common"; -import { ActivityType } from "../types/action"; -import { UserActivity } from "../entity/user_activity"; +import { ActivityType } from "Entity"; import * as fastcsv from 'fast-csv'; import dayjs from "dayjs"; +import { UserActivity } from "Entity"; const log: Logger = new Logger({ name: '[UserActivityController]', type: 'pretty' }); diff --git a/src/controllers/user_refresh_token.ts b/src/controllers/user_refresh_token.ts index 27fbdfe..d6c439b 100644 --- a/src/controllers/user_refresh_token.ts +++ b/src/controllers/user_refresh_token.ts @@ -5,9 +5,9 @@ import { OrmHelper } from "../helpers/orm"; import Joi from "joi"; import { ILogObj, Logger } from "tslog"; import { Language } from "../langs/lang"; -import { Paging } from "../types/paging"; +import { Paging } from "Entity"; import CommonHelper from "../helpers/common"; -import { UserRefreshToken } from "../entity/user_refresh_token"; +import { UserRefreshToken } from "Entity"; const log: Logger = new Logger({ name: '[UserRefreshTokenController]', type: 'pretty' }); diff --git a/src/controllers/user_roles.ts b/src/controllers/user_roles.ts index 787ca44..30d41ab 100644 --- a/src/controllers/user_roles.ts +++ b/src/controllers/user_roles.ts @@ -4,13 +4,13 @@ import { OrmHelper } from "../helpers/orm"; import Joi from "joi"; import { ILogObj, Logger } from "tslog"; import { Language } from "../langs/lang"; -import { Paging } from "../types/paging"; +import { Paging } from "Entity"; import CommonHelper from "../helpers/common"; -import { Status } from "../types/status"; -import { UserRole } from "../entity/users_roles"; -import { RoleList } from "../types/role"; +import { Status } from "Entity"; +import { RoleList } from "Entity"; import * as fastcsv from 'fast-csv'; import dayjs from "dayjs"; +import { UserRole } from "Entity"; const log: Logger = new Logger({ name: '[UserRoleController]', type: 'pretty' }); diff --git a/src/entity/user_activity.ts b/src/entity/user_activity.ts deleted file mode 100644 index 31fd37d..0000000 --- a/src/entity/user_activity.ts +++ /dev/null @@ -1,64 +0,0 @@ -import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn, DeleteDateColumn, Index } from 'typeorm'; - -import { ActivityType } from '../types/action'; - -@Entity('user_activities') -export class UserActivity { - @PrimaryGeneratedColumn('uuid') - id: string; - - @Index() - @Column({ - type: 'uuid' - }) - id_user: string; - - @Index() - @Column({ - type: 'uuid' - }) - refresh_token: string; - - @Index() - @Column({ - nullable: false, - length: 512 - }) - module: string; - - @Column({ - nullable: false, - length: 2048 - }) - description: string; - - @Column({ - nullable: true, - length: 1 - }) - action: ActivityType; - - @Column({ - nullable: false, - length: 2048, - }) - url: String; - - @Column({ - type: 'text', - nullable: true, - }) - data_body: String; - - @Column() - @CreateDateColumn() - created_at: Date; - - @Column({ nullable: true }) - @UpdateDateColumn() - updated_at: Date; - - @Column({ nullable: true }) - @DeleteDateColumn() - deleted_at: Date; -} \ No newline at end of file diff --git a/src/entity/user_refresh_token.ts b/src/entity/user_refresh_token.ts deleted file mode 100644 index cc3181e..0000000 --- a/src/entity/user_refresh_token.ts +++ /dev/null @@ -1,64 +0,0 @@ -import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn, DeleteDateColumn, Index } from 'typeorm'; - -@Entity('user_refresh_tokens') -export class UserRefreshToken { - @PrimaryGeneratedColumn('uuid') - refresh_token: string; - - @Index() - @Column({ - type: 'uuid' - }) - id_user: string; - - @Column({ - nullable: false, - length: 4096, - }) - user_agent: string; - - @Column({ - nullable: true, - length: 128 - }) - os: string; - - @Column({ - nullable: true, - length: 256 - }) - device: string; - - @Column({ - nullable: true, - length: 64 - }) - platform: string; - - @Column({ - nullable: true, - length: 64 - }) - browser: string; - - @Column({ - nullable: true, - length: 32 - }) - remote_addr: string; - - @Column('timestamp') - expired_at: Date; - - @Column() - @CreateDateColumn() - created_at: Date; - - @Column({ nullable: true }) - @UpdateDateColumn() - updated_at: Date; - - @Column({ nullable: true }) - @DeleteDateColumn() - deleted_at: Date; -} \ No newline at end of file diff --git a/src/entity/users.ts b/src/entity/users.ts deleted file mode 100644 index 295e9b2..0000000 --- a/src/entity/users.ts +++ /dev/null @@ -1,76 +0,0 @@ -import bcrypt from 'bcryptjs'; -import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn, DeleteDateColumn, Index } from 'typeorm'; - -import { Status } from '../types/status'; - -@Entity('users') -export class User { - @PrimaryGeneratedColumn('uuid') - id: string; - - @Column({ - nullable: false, - unique: true, - length: 64 - }) - email: string; - - @Column({ - nullable: false, - length: 64, - select: false - }) - password: string; - - @Column({ - nullable: false, - unique: true, - length: 64 - }) - username: string; - - @Column({ - nullable: true, - length: 64 - }) - name: string; - - @Column({ - nullable: true, - type: 'uuid' - }) - id_role: string; - - @Index() - @Column({ - nullable: true, - type: 'uuid' - }) - reset_token: string; - - @Column({ - nullable: false, - length: 64 - }) - status: Status; - - @Column() - @CreateDateColumn() - created_at: Date; - - @Column({ nullable: true }) - @UpdateDateColumn() - updated_at: Date; - - @Column({ nullable: true }) - @DeleteDateColumn() - deleted_at: Date; - - hashPassword() { - this.password = bcrypt.hashSync(this.password, 8); - } - - checkIfPasswordMatch(unencryptedPassword: string) { - return bcrypt.compareSync(unencryptedPassword, this.password); - } -} \ No newline at end of file diff --git a/src/entity/users_roles.ts b/src/entity/users_roles.ts deleted file mode 100644 index 19dc98d..0000000 --- a/src/entity/users_roles.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn, DeleteDateColumn } from 'typeorm'; - -import { Status } from '../types/status'; -import { RoleList } from '../types/role'; - -@Entity('user_roles') -export class UserRole { - @PrimaryGeneratedColumn('uuid') - id: string; - - @Column({ - nullable: false, - unique: true, - length: 128 - }) - name: string; - - @Column({ - nullable: false, - type: 'jsonb' - }) - roles: RoleList[]; - - @Column({ - nullable: false, - length: 64 - }) - status: Status; - - @Column() - @CreateDateColumn() - created_at: Date; - - @Column({ nullable: true }) - @UpdateDateColumn() - updated_at: Date; - - @Column({ nullable: true }) - @DeleteDateColumn() - deleted_at: Date; -} \ No newline at end of file diff --git a/src/helpers/common.ts b/src/helpers/common.ts index 9af05a2..3075b15 100644 --- a/src/helpers/common.ts +++ b/src/helpers/common.ts @@ -81,4 +81,14 @@ export default class CommonHelper { return ''; } } + + static generateTemplate(template: string, pairMap: any): string { + for (let p in pairMap) { + let v = pairMap[p]; + + template = template.split('{' + p + '}').join(v); + } + + return template + } } \ No newline at end of file diff --git a/src/helpers/express/return.ts b/src/helpers/express/return.ts index 92e9473..f14d74a 100644 --- a/src/helpers/express/return.ts +++ b/src/helpers/express/return.ts @@ -1,5 +1,5 @@ import { Response } from 'express'; -import { ErrorType, ErrorValidation } from '../../types/error'; +import { ErrorType, ErrorValidation } from 'Entity'; export class ReturnHelper { static successResponseAny( diff --git a/src/helpers/orm.ts b/src/helpers/orm.ts index 395e79d..cf2bb7e 100644 --- a/src/helpers/orm.ts +++ b/src/helpers/orm.ts @@ -1,10 +1,7 @@ import config from 'config'; import { DataSource } from "typeorm"; -import { User } from "../entity/users"; +import { User, UserActivity, UserRefreshToken, UserRole } from "Entity"; import { ILogObj, Logger } from 'tslog'; -import { UserActivity } from '../entity/user_activity'; -import { UserRefreshToken } from '../entity/user_refresh_token'; -import { UserRole } from '../entity/users_roles'; export class OrmHelper { static DB: DataSource = null diff --git a/src/types/action.ts b/src/types/action.ts deleted file mode 100644 index 314bcad..0000000 --- a/src/types/action.ts +++ /dev/null @@ -1,7 +0,0 @@ -export enum ActivityType { - "Create" = "C", - "View" = "V", - "Update" = "U", - "Delete" = "D", - "Restore" = "T", -}; \ No newline at end of file diff --git a/src/types/error.ts b/src/types/error.ts deleted file mode 100644 index 1415969..0000000 --- a/src/types/error.ts +++ /dev/null @@ -1,3 +0,0 @@ -export type ErrorType = 'General' | 'Raw' | 'Validation' | 'Unauthorized'; - -export type ErrorValidation = { [key: string]: string }; \ No newline at end of file diff --git a/src/types/paging.ts b/src/types/paging.ts deleted file mode 100644 index ee83de9..0000000 --- a/src/types/paging.ts +++ /dev/null @@ -1,8 +0,0 @@ -export interface Paging { - page: number, - limit: number, - filter: any, - with_deleted: boolean, - order_field: string, - order_direction: 'ASC' | 'DESC' -} \ No newline at end of file diff --git a/src/types/role.ts b/src/types/role.ts deleted file mode 100644 index 18edd28..0000000 --- a/src/types/role.ts +++ /dev/null @@ -1,23 +0,0 @@ -export enum RoleList { - "Dashboard" = "dashboard", - "Kinerja UKLN" = "ukln", - "Dana Pihak Ketiga" = "dpk", - "Posisi Outstanding Pinjaman" = "outstanding_loan", - "Presentasi NPL" = "npl", - "PPAP Amount NPL" = "ppap_amount", - "Report Regulator Bulanan" = "regulator_bulanan", - "Report Regulator Triwulan" = "regulator_triwulan", - "Report Regulator Publikasi" = "regulator_publikasi", - "Perhitungan Simulasi Perpajakan Per Bulan" = "pajak_per_bulan", - "Perhitungan Simulasi Perpajakan Per Tahun" = "pajak_per_tahun", - "Data Nasabah Potensial" = "nasabah_potensial", - "Master Data User" = "master_user", - "Master Data Product" = "master_product", - "Master Data Tier" = "master_tier", - "Master Klasifikasi Ekonomi" = "master_klasifikasi_ekonomi", - "Master District" = "master_district", - "Master Munisipu" = "master_munisipu", - "Master Administrativu" = "master_administrativu", - "Master Suco" = "master_suco", - "Master Aldeia" = "master_aldeia", -} \ No newline at end of file diff --git a/src/types/status.ts b/src/types/status.ts deleted file mode 100644 index 7408c75..0000000 --- a/src/types/status.ts +++ /dev/null @@ -1,4 +0,0 @@ -export enum Status { - "Active" = "Y", - "Not Active" = "N" -}; \ No newline at end of file