lrf402788946 4 anos atrás
pai
commit
3d1f6efcaa

+ 52 - 0
app/controller/user/.user.js

@@ -0,0 +1,52 @@
+module.exports = {
+  create: {
+    requestBody: [
+      "!name",
+      "!login_id",
+      "role",
+      "!password",
+      "status",
+      "params",
+    ],
+  },
+  destroy: {
+    params: ["!id"],
+    service: "delete",
+  },
+  update: {
+    params: ["!id"],
+    requestBody: [
+      "!name",
+      "!login_id",
+      "role",
+      "!password",
+      "status",
+      "params",
+      "_tenant",
+    ],
+  },
+  show: {
+    parameters: {
+      params: ["!id"],
+    },
+    service: "fetch",
+  },
+  index: {
+    parameters: {
+      query: {
+        tenant: "_tenant",
+        name: "name",
+        login_id: "login_id",
+        role: "role",
+        status: "status",
+      },
+    },
+    service: "query",
+    options: {
+      query: ["skip", "limit"],
+      sort: ["sort"],
+      desc: true,
+      count: true,
+    },
+  },
+};

+ 23 - 0
app/controller/user/login.js

@@ -0,0 +1,23 @@
+'use strict';
+
+const _ = require('lodash');
+const Controller = require('egg').Controller;
+
+// 用户controller
+class LoginController extends Controller {
+  constructor(ctx) {
+    super(ctx);
+    this.service = this.ctx.service.user.login;
+  }
+  async login() {
+    const data = await this.service.login(this.ctx.request.body);
+    this.ctx.ok({ data });
+  }
+
+  async token() {
+    const res = await this.service.token(this.ctx.request.body);
+    this.ctx.ok({ data: res });
+  }
+}
+
+module.exports = LoginController;

+ 17 - 0
app/controller/user/user.js

@@ -0,0 +1,17 @@
+'use strict';
+
+const _ = require('lodash');
+const meta = require('./.user.js');
+const Controller = require('egg').Controller;
+const { CrudController } = require('naf-framework-mongoose/lib/controller');
+
+// 用户controller
+class UserController extends Controller {
+  constructor(ctx) {
+    super(ctx);
+    this.service = this.ctx.service.user.user;
+  }
+
+}
+
+module.exports = CrudController(UserController, meta);

+ 24 - 0
app/model/user/user.js

@@ -0,0 +1,24 @@
+'use strict';
+const Schema = require('mongoose').Schema;
+const metaPlugin = require('naf-framework-mongoose/lib/model/meta-plugin');
+const { Secret } = require('naf-framework-mongoose/lib/model/schema');
+
+const User = {
+  name: { type: String, required: true, maxLength: 200 }, // 用户名
+  login_id: { type: String, required: true, maxLength: 200 }, // 登陆id
+  role: { type: String, required: false, maxLength: 200 }, // 角色
+  password: { type: Secret, select: false },
+  status: { type: String, default: '0' }, // 使用状态: 0=>使用中;1=>冻结;2=>异常
+  params: { type: Object }, // 参数字段,需要就用,不需要就不用
+};
+const schema = new Schema(User, { 'multi-tenancy': true, toJSON: { virtuals: true } });
+schema.index({ id: 1 });
+schema.plugin(metaPlugin);
+schema.index({ _tenant: 1 });
+schema.index({ name: 1 });
+schema.index({ login_id: 1 });
+
+module.exports = app => {
+  const { mongoose } = app;
+  return mongoose.model('Users', schema, 'user');
+};

+ 8 - 6
app/router.js

@@ -5,19 +5,21 @@
  */
 module.exports = app => {
   const { router, controller } = app;
+  router.get('/', controller.home.index);
   const prefix = '/api/role/auth';
   // 工具
   router.get(`${prefix}/model/:model`, controller.util.findModel);
-
-
-  router.get('/', controller.home.index);
-  router.get('menu', `${prefix}/menu/project/:project`, controller.menu.findProject);
-  router.resources('menu', `${prefix}/menu`, controller.menu); // index、create、show、destroy
-  router.post('menu', `${prefix}/menu/update/:id`, controller.menu.update);
+  // menu
+  require('./router/menu')(app);
+  // user
+  require('./router/user')(app);
+  require('./router/login')(app);
   router.get('role', `${prefix}/role/menu/tree`, controller.role.roleMenuTree); // index、create、show、destroy
   router.resources('role', `${prefix}/role`, controller.role); // index、create、show、destroy
   router.post('role', `${prefix}/role/update/:id`, controller.role.update);
   router.get('usermenu', `${prefix}/usermenu/menu`, controller.userMenu.getUserMenu);
   router.resources('usermenu', `${prefix}/usermenu`, controller.userMenu); // index、create、show、destroy
   router.post('usermenu', `${prefix}/usermenu/update/:id`, controller.userMenu.update);
+
+
 };

+ 10 - 0
app/router/login.js

@@ -0,0 +1,10 @@
+'use strict';
+/**
+ * @param {Egg.Application} app - egg application
+ */
+module.exports = app => {
+  const { router, controller } = app;
+  const prefix = '/api/role/auth';
+  router.post(`${prefix}/login`, controller.user.login.login);
+  router.post(`${prefix}/token`, controller.user.login.token);
+};

+ 11 - 0
app/router/menu.js

@@ -0,0 +1,11 @@
+'use strict';
+/**
+ * @param {Egg.Application} app - egg application
+ */
+module.exports = app => {
+  const { router, controller } = app;
+  const prefix = '/api/role/auth';
+  router.get('menu', `${prefix}/menu/project/:project`, controller.menu.findProject);
+  router.resources('menu', `${prefix}/menu`, controller.menu); // index、create、show、destroy
+  router.post('menu', `${prefix}/menu/update/:id`, controller.menu.update);
+};

+ 10 - 0
app/router/user.js

@@ -0,0 +1,10 @@
+'use strict';
+/**
+ * @param {Egg.Application} app - egg application
+ */
+module.exports = app => {
+  const { router, controller } = app;
+  const prefix = '/api/role/auth';
+  router.resources('user', `${prefix}/user`, controller.user.user); // index、create、show、destroy
+  router.post('user', `${prefix}/user/update/:id`, controller.user.user.update);
+};

+ 0 - 1
app/service/user-menu.js

@@ -55,7 +55,6 @@ class UserMenuService extends CrudService {
         menuids.push(...uMenuids);
       }
     }
-
     // 找到所有菜单的父级,下面过滤用,把父级目录拿出来(不单纯是根目录)
     const parentIdsRes = await this.Menumodel.find({ _id: menuids.map(i => ObjectId(i)) }, 'pid');
     let parentIds = parentIdsRes.map(i => i.pid);

+ 67 - 0
app/service/user/login.js

@@ -0,0 +1,67 @@
+'use strict';
+
+const assert = require('assert');
+const _ = require('lodash');
+const moment = require('moment');
+const { ObjectId } = require('mongoose').Types;
+const { CrudService } = require('naf-framework-mongoose/lib/service');
+const { BusinessError, ErrorCode } = require('naf-core').Error;
+const jwt = require('jsonwebtoken');
+const uuid = require('uuid');
+
+class LoginService extends CrudService {
+  constructor(ctx) {
+    super(ctx, 'login');
+    this.model = this.ctx.model.User;
+  }
+  async login({ login_id, password }) {
+    assert(login_id, '请输入登录用户名');
+    assert(password, '请输入密码');
+    const user = await this.checkUser(login_id, password);
+    const jwt_user = await this.createJwt(user);
+    const state = uuid();
+    const key = `free:auth:state:${state}`;
+    await this.app.redis.set(key, jwt_user, 'EX', 60 * 60 * 24);
+    return { key };
+  }
+
+  async checkUser(login_id, password) {
+    const user = await this.model.findOne({ login_id }, '+password');
+    if (!user) throw new BusinessError(ErrorCode.USER_NOT_EXIST, '用户不存在');
+    if (user.password.secret !== password) {
+      throw new BusinessError(ErrorCode.BAD_PASSWORD, '用户密码错误');
+    }
+    return JSON.parse(JSON.stringify(user));
+  }
+
+  // 创建登录Token
+  async createJwt({ id, login_id, ...info }) {
+    info = _.omit(info, [ '_v', 'meta' ]);
+    const { secret, expiresIn = '1d' } = this.config.jwt;
+    const subject = login_id;
+    const res = { id, login_id, ...info };
+    const token = await jwt.sign(res, secret, { expiresIn, subject });
+    return token;
+  }
+
+  // 取得redis内token信息
+  async token({ key }) {
+    assert(key, 'key不能为空');
+    const token = await this.app.redis.get(key);
+    if (!token) {
+      throw new BusinessError(ErrorCode.SERVICE_FAULT, 'token已经过期');
+    }
+    // 转换成用户信息,给过去
+    let res = jwt.decode(token);
+    res = _.pick(res, [ 'login_id', '_tenant', 'id', 'name', 'role', 'status' ]);
+    return res;
+  }
+
+  // 删除操作
+  async destroy({ key }) {
+    const res = await this.app.redis.del(key);
+    return res;
+  }
+}
+
+module.exports = LoginService;

+ 30 - 0
app/service/user/user.js

@@ -0,0 +1,30 @@
+'use strict';
+
+const assert = require('assert');
+const _ = require('lodash');
+const moment = require('moment');
+const { ObjectId } = require('mongoose').Types;
+const { CrudService } = require('naf-framework-mongoose/lib/service');
+const { BusinessError, ErrorCode } = require('naf-core').Error;
+
+class UserService extends CrudService {
+  constructor(ctx) {
+    super(ctx, 'user');
+    this.model = this.ctx.model.User;
+  }
+  async create(data) {
+    const { password } = data;
+    data.password = { secret: password };
+    const res = await this.model.create(data);
+    return res;
+  }
+
+  async update(data) {
+    const { id, password } = data;
+    if (password) data.passwd = { secret: password };
+    const res = await this.model.update({ id: ObjectId(id) }, data);
+    return res;
+  }
+}
+
+module.exports = UserService;

+ 10 - 3
config/config.default.js

@@ -5,12 +5,13 @@
 /**
  * @param {Egg.EggAppInfo} appInfo app info
  */
+const { jwt } = require('./config.secret');
 module.exports = appInfo => {
   /**
    * built-in config
    * @type {Egg.EggAppConfig}
    **/
-  const config = exports = {};
+  const config = (exports = {});
 
   // use for cookie sign key, should change to your own and keep security
   config.keys = appInfo.name + '_1604310853516_4870';
@@ -56,8 +57,8 @@ module.exports = appInfo => {
       // user: 'admin',
       // pass: 'admin',
       // authSource: 'admin',
-      // useNewUrlParser: true,
-      // useCreateIndex: true,
+      useNewUrlParser: true,
+      useCreateIndex: true,
     },
   };
 
@@ -73,6 +74,12 @@ module.exports = appInfo => {
     },
   };
 
+  config.jwt = {
+    ...jwt,
+    expiresIn: '1d',
+    issuer: 'servicezhwl',
+  };
+
   return {
     ...config,
     ...userConfig,

+ 7 - 0
config/config.secret.js

@@ -0,0 +1,7 @@
+'use strict';
+
+module.exports = {
+  jwt: {
+    secret: 'Ziyouyanfa!@#',
+  },
+};

+ 4 - 0
config/plugin.js

@@ -10,3 +10,7 @@ exports.redis = {
   enable: true,
   package: 'egg-redis',
 };
+
+exports.multiTenancy = {
+  enable: true,
+};

+ 2 - 1
package.json

@@ -8,9 +8,10 @@
   },
   "dependencies": {
     "egg": "^2.15.1",
-    "egg-scripts": "^2.11.0",
     "egg-naf-amqp": "0.0.13",
     "egg-redis": "^2.4.0",
+    "egg-scripts": "^2.11.0",
+    "jsonwebtoken": "^8.5.1",
     "lodash": "^4.17.15",
     "moment": "^2.27.0",
     "naf-framework-mongoose": "^0.6.11"