diff --git a/packages/toolkits/pro/template/server/eggJs/app/controller/user.ts b/packages/toolkits/pro/template/server/eggJs/app/controller/user.ts new file mode 100644 index 00000000..d89e4b6a --- /dev/null +++ b/packages/toolkits/pro/template/server/eggJs/app/controller/user.ts @@ -0,0 +1,104 @@ +import { Controller } from 'egg'; +import BcryptUtils from '../utils/bcrypt-utils'; + +export default class UserController extends Controller { + // 注册用户 + public async registerUser() { + const { ctx, app } = this; + const payload = ctx.request.body || {}; + const transaction = await ctx.model.transaction(); + try { + this.logger.info('[ controller | user ] registerUser : 进入registerUser方法'); + // 校验参数 + const registerUserRule = { + user_name: { type: 'email' }, + password: { + type: 'string', + format: /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d]{8,}$/, + }, + }; + const err = app.validator.validate(registerUserRule, payload); + if (err?.length) { + ctx.helper.commonJson(ctx, {}, 500, 'InvalidParameter'); + return; + } + const { user_name, password } = payload; + // 判断用户是否已经存在 + const user = await ctx.service.user.getUserByName(user_name); + if (user) { + ctx.helper.commonJson(ctx, {}, 500, 'UserAlreadyExist'); + return; + } + const hash = BcryptUtils.genHash(password); + // 创建用户 + const { id } = await ctx.service.user.createUser({ user_name, password: hash }, { transaction }); + const userInfo = await ctx.service.user.createUserInfo({ user_name, user_id: id }, { transaction }); + await transaction.commit(); + ctx.helper.commonJson(ctx, userInfo, 200); + } catch (error) { + await transaction.rollback(); + ctx.helper.commonJson(ctx, {}, 500, 'InterError'); + } + } + + // 获取用户信息 + public async getUserInfo() { + const { ctx } = this; + const { id } = ctx.params; + + try { + this.logger.info('[ controller | user ] getUserInfo : 进入getUserInfo方法'); + const userInfo = await ctx.service.user.getUserInfoById(id); + if (!userInfo) { + ctx.helper.commonJson(ctx, {}, 500, 'UserNotFound'); + return; + } + ctx.helper.commonJson(ctx, userInfo, 200); + } catch (error) { + ctx.helper.commonJson(ctx, {}, 500, 'InterError'); + } + } + + // 登录 + public async login() { + const { ctx, app } = this; + const payload = ctx.request.body || {}; + try { + this.logger.info('[ controller | user ] login : 进入login方法'); + // 校验参数格式 + const err = app.validator.validate( + { + user_name: { type: 'email' }, + password: { type: 'string' }, + }, + payload, + ); + if (err?.length) { + ctx.helper.commonJson(ctx, {}, 500, 'InvalidParameter'); + return; + } + + // 用户是否存在 + const user = await ctx.service.user.getUserByName(payload.user_name); + if (!user) { + ctx.helper.commonJson(ctx, {}, 500, 'UserNotFound'); + return; + } + + // 密码是否正确 + const match = BcryptUtils.compare(payload.password, user.password); + if (!match) { + ctx.helper.commonJson(ctx, {}, 500, 'ErrorPassword'); + return; + } + + // 生成Token + const { secret, sign } = this.app.config.jwt; + const userInfo = await ctx.service.user.getUserInfoById(user.id); + const token = this.app.jwt.sign(userInfo, secret, sign); + ctx.helper.commonJson(ctx, { token }, 200); + } catch (error) { + ctx.helper.commonJson(ctx, {}, 500, 'InterError'); + } + } +} diff --git a/packages/toolkits/pro/template/server/eggJs/app/model/registerUser.ts b/packages/toolkits/pro/template/server/eggJs/app/model/registerUser.ts new file mode 100644 index 00000000..79563106 --- /dev/null +++ b/packages/toolkits/pro/template/server/eggJs/app/model/registerUser.ts @@ -0,0 +1,40 @@ +/* indent size: 4 */ + +module.exports = (app: any) => { + const DataTypes = app.Sequelize; + + const RegisterUser = app.model.define( + 'RegisterUser', + { + id: { + type: DataTypes.INTEGER(20).UNSIGNED, + allowNull: false, + primaryKey: true, + autoIncrement: true, + }, + user_name: { + type: DataTypes.STRING(32), + allowNull: false, + }, + password: { + type: DataTypes.STRING(60), + allowNull: false, + }, + register_type: { + type: DataTypes.ENUM('email'), + allowNull: false, + defaultValue: 'email', + }, + }, + { + tableName: 'registeruser', + underscored: false, + freezeTableName: true, + omitNull: false, + timestamps: false, + paranoid: false, + }, + ); + + return RegisterUser; +}; diff --git a/packages/toolkits/pro/template/server/eggJs/app/model/userInfo.ts b/packages/toolkits/pro/template/server/eggJs/app/model/userInfo.ts new file mode 100644 index 00000000..24d0bea5 --- /dev/null +++ b/packages/toolkits/pro/template/server/eggJs/app/model/userInfo.ts @@ -0,0 +1,76 @@ +/* indent size: 4 */ + +module.exports = (app: any) => { + const DataTypes = app.Sequelize; + + const UserInfo = app.model.define( + 'UserInfo', + { + id: { + type: DataTypes.INTEGER(20).UNSIGNED, + allowNull: false, + primaryKey: true, + autoIncrement: true, + }, + user_name: { + type: DataTypes.STRING(32), + allowNull: false, + }, + user_id: { + type: DataTypes.INTEGER(20), + allowNull: false, + }, + department: { + type: DataTypes.STRING(32), + allowNull: false, + defaultValue: '', + }, + employee_type: { + type: DataTypes.STRING(32), + defaultValue: null, + }, + roles: { + type: DataTypes.STRING(32), + defaultValue: null, + }, + probation_start: { + type: DataTypes.DATE, + defaultValue: null, + }, + probation_end: { + type: DataTypes.DATE, + defaultValue: null, + }, + probation_duration: { + type: DataTypes.INTEGER(11).UNSIGNED, + defaultValue: null, + }, + protocol_start: { + type: DataTypes.DATE, + defaultValue: null, + }, + protocol_end: { + type: DataTypes.DATE, + defaultValue: null, + }, + address: { + type: DataTypes.STRING(32), + defaultValue: null, + }, + status: { + type: DataTypes.STRING(32), + defaultValue: null, + }, + }, + { + tableName: 'userinfo', + underscored: false, + freezeTableName: true, + omitNull: false, + timestamps: false, + paranoid: false, + }, + ); + + return UserInfo; +}; diff --git a/packages/toolkits/pro/template/server/eggJs/app/router.ts b/packages/toolkits/pro/template/server/eggJs/app/router.ts index 59c7b228..9f6105b3 100644 --- a/packages/toolkits/pro/template/server/eggJs/app/router.ts +++ b/packages/toolkits/pro/template/server/eggJs/app/router.ts @@ -11,4 +11,9 @@ export default (app: Application) => { router.post('/v1/employee/getEmployee', controller.employee.getEmployee); + router.post('/v1/user/register', controller.user.registerUser); + + router.get('/v1/user/userInfo/:id', controller.user.getUserInfo); + + router.post('/v1/user/login', controller.user.login); }; diff --git a/packages/toolkits/pro/template/server/eggJs/app/service/user.ts b/packages/toolkits/pro/template/server/eggJs/app/service/user.ts new file mode 100644 index 00000000..87ce9270 --- /dev/null +++ b/packages/toolkits/pro/template/server/eggJs/app/service/user.ts @@ -0,0 +1,19 @@ +import { Service } from 'egg'; + +export default class User extends Service { + public async getUserInfoById(user_id: string): Promise { + return this.ctx.model.UserInfo.findOne({ where: { user_id }, raw: true }); + } + + public async getUserByName(user_name: string): Promise { + return this.ctx.model.RegisterUser.findOne({ where: { user_name } }); + } + + public async createUser(params: { user_name: string; password: string }, options?): Promise { + return this.ctx.model.RegisterUser.create(params, options); + } + + public async createUserInfo(info, options?): Promise { + return this.ctx.model.UserInfo.create(info, options); + } +} diff --git a/packages/toolkits/pro/template/server/eggJs/app/utils/bcrypt-utils.ts b/packages/toolkits/pro/template/server/eggJs/app/utils/bcrypt-utils.ts new file mode 100644 index 00000000..7d8402c2 --- /dev/null +++ b/packages/toolkits/pro/template/server/eggJs/app/utils/bcrypt-utils.ts @@ -0,0 +1,11 @@ +import * as bcrypt from 'bcrypt'; + +export default class BcryptUtils { + private static saltRounds = 10; + public static genHash(password: string): string { + return bcrypt.hashSync(password, this.saltRounds); + } + public static compare(password: string, encrypted: string): boolean { + return bcrypt.compareSync(password, encrypted); + } +} diff --git a/packages/toolkits/pro/template/server/eggJs/config/config.default.ts b/packages/toolkits/pro/template/server/eggJs/config/config.default.ts index 0d15788e..e171277a 100644 --- a/packages/toolkits/pro/template/server/eggJs/config/config.default.ts +++ b/packages/toolkits/pro/template/server/eggJs/config/config.default.ts @@ -17,18 +17,26 @@ export default (appInfo: EggAppInfo) => { username: 'root', password: '123456', define: { - timestamps: true, - freezeTableName: true, - underscored: false, - createdAt: 'created_at', - updatedAt: 'updated_at', + timestamps: true, + freezeTableName: true, + underscored: false, + createdAt: 'created_at', + updatedAt: 'updated_at', }, timezone: '+08:00', - database: 'tiny_server_test' + database: 'tiny_pro_server', }; + config.jwt = { + enable: true, + ignore: /user\/(login|register)/, + secret: 'tiny_pro_server', + sign: { + expiresIn: 60 * 60 * 24, + }, + }; // the return config will combines to EggAppConfig return { - ...config + ...config, }; }; diff --git a/packages/toolkits/pro/template/server/eggJs/config/plugin.ts b/packages/toolkits/pro/template/server/eggJs/config/plugin.ts index 3231533b..339fc53e 100644 --- a/packages/toolkits/pro/template/server/eggJs/config/plugin.ts +++ b/packages/toolkits/pro/template/server/eggJs/config/plugin.ts @@ -5,6 +5,14 @@ const plugin: EggPlugin = { enable: true, package: 'egg-sequelize', }, + validate: { + enable: true, + package: 'egg-validate', + }, + jwt: { + enable: true, + package: 'egg-jwt', + }, }; export default plugin; diff --git a/packages/toolkits/pro/template/server/eggJs/package.json b/packages/toolkits/pro/template/server/eggJs/package.json index a7222f4b..b9a8ed7f 100644 --- a/packages/toolkits/pro/template/server/eggJs/package.json +++ b/packages/toolkits/pro/template/server/eggJs/package.json @@ -21,9 +21,12 @@ "clean": "ets clean" }, "dependencies": { + "bcrypt": "^5.1.0", "egg": "^2.6.1", + "egg-jwt": "^3.1.7", "egg-scripts": "^2.6.0", "egg-sequelize": "^5.2.2", + "egg-validate": "^2.0.2", "mysql2": "^2.1.0" }, "devDependencies": { diff --git a/packages/toolkits/pro/template/server/eggJs/typings/app/controller/index.d.ts b/packages/toolkits/pro/template/server/eggJs/typings/app/controller/index.d.ts index 300fc60b..0f64d8a4 100644 --- a/packages/toolkits/pro/template/server/eggJs/typings/app/controller/index.d.ts +++ b/packages/toolkits/pro/template/server/eggJs/typings/app/controller/index.d.ts @@ -3,10 +3,14 @@ /* eslint-disable */ import 'egg'; +import ExportCsrf from '../../../app/controller/csrf'; import ExportEmployee from '../../../app/controller/employee'; +import ExportUser from '../../../app/controller/user'; declare module 'egg' { interface IController { + csrf: ExportCsrf; employee: ExportEmployee; + user: ExportUser; } } diff --git a/packages/toolkits/pro/template/server/eggJs/typings/app/model/index.d.ts b/packages/toolkits/pro/template/server/eggJs/typings/app/model/index.d.ts index 13833dec..64e03fb6 100644 --- a/packages/toolkits/pro/template/server/eggJs/typings/app/model/index.d.ts +++ b/packages/toolkits/pro/template/server/eggJs/typings/app/model/index.d.ts @@ -4,9 +4,13 @@ import 'egg'; import ExportEmployee from '../../../app/model/employee'; +import ExportRegisterUser from '../../../app/model/registerUser'; +import ExportUserInfo from '../../../app/model/userInfo'; declare module 'egg' { interface IModel { Employee: ReturnType; + RegisterUser: ReturnType; + UserInfo: ReturnType; } } diff --git a/packages/toolkits/pro/template/server/eggJs/typings/app/service/index.d.ts b/packages/toolkits/pro/template/server/eggJs/typings/app/service/index.d.ts index 567c6c80..2b4b63c3 100644 --- a/packages/toolkits/pro/template/server/eggJs/typings/app/service/index.d.ts +++ b/packages/toolkits/pro/template/server/eggJs/typings/app/service/index.d.ts @@ -6,11 +6,15 @@ import 'egg'; type AnyClass = new (...args: any[]) => any; type AnyFunc = (...args: any[]) => T; type CanExportFunc = AnyFunc> | AnyFunc>; -type AutoInstanceType : T> = U extends AnyClass ? InstanceType : U; +type AutoInstanceType : T> = U extends AnyClass + ? InstanceType + : U; import ExportEmployee from '../../../app/service/employee'; +import ExportUser from '../../../app/service/user'; declare module 'egg' { interface IService { employee: AutoInstanceType; + user: AutoInstanceType; } } diff --git a/packages/toolkits/pro/template/server/eggJs/typings/config/plugin.d.ts b/packages/toolkits/pro/template/server/eggJs/typings/config/plugin.d.ts index c8f1c015..c69277df 100644 --- a/packages/toolkits/pro/template/server/eggJs/typings/config/plugin.d.ts +++ b/packages/toolkits/pro/template/server/eggJs/typings/config/plugin.d.ts @@ -16,6 +16,8 @@ import 'egg-static'; import 'egg-jsonp'; import 'egg-view'; import 'egg-sequelize'; +import 'egg-validate'; +import 'egg-jwt'; import { EggPluginItem } from 'egg'; declare module 'egg' { interface EggPlugin { @@ -32,5 +34,7 @@ declare module 'egg' { jsonp?: EggPluginItem; view?: EggPluginItem; sequelize?: EggPluginItem; + validate?: EggPluginItem; + jwt?: EggPluginItem; } -} \ No newline at end of file +}