Преглед на файлове

增加用户与登录服务

liuyu преди 5 години
родител
ревизия
dd3ea6111b
променени са 8 файла, в които са добавени 268 реда и са изтрити 6 реда
  1. 51 0
      app/controller/.user.js
  2. 25 0
      app/controller/login.js
  3. 22 0
      app/controller/user.js
  4. 26 0
      app/model/user.js
  5. 65 0
      app/service/login.js
  6. 23 5
      app/service/school.js
  7. 41 0
      app/service/user.js
  8. 15 1
      config/config.default.js

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

@@ -0,0 +1,51 @@
+module.exports = {
+  create: {
+    requestBody: [
+      'name',
+      '!mobile',
+      '!passwd',
+      'openid',
+      'remark',
+      'type',
+      'uid'
+    ]
+  },
+  destroy: {
+    params: ['!id'],
+    service: 'delete'
+  },
+  update: {
+    params: ['!id'],
+    requestBody: [
+      'name',
+      'mobile',
+      'passwd',
+      'openid',
+      'remark',
+      'type',
+      'uid'
+    ]
+  },
+  show: {
+    parameters: {
+      params: ['!id']
+    },
+    service: 'fetch'
+  },
+  index: {
+    parameters: {
+      query: {
+        name: 'name',
+        mobile: 'mobile',
+        openid: 'openid'
+      }
+    },
+    service: 'query',
+    options: {
+      query: ['skip', 'limit'],
+      sort: ['meta.createdAt'],
+      desc: true,
+      count: true
+    }
+  },
+};

+ 25 - 0
app/controller/login.js

@@ -0,0 +1,25 @@
+'use strict';
+
+const _ = require('lodash');
+const Controller = require('egg').Controller;
+
+// 登录管理
+class LoginController extends Controller {
+
+  constructor(ctx) {
+    super(ctx);
+    this.service = this.ctx.service.login;
+  }
+
+  async login() {
+    const res = await this.service.login(this.ctx.request.body);
+    this.ctx.ok({ data: res });
+  }
+
+  async wxlogin() {
+    const res = await this.service.wxlogin(this.ctx.request.body);
+    this.ctx.ok({ data: res });
+  }
+}
+
+module.exports = LoginController;

+ 22 - 0
app/controller/user.js

@@ -0,0 +1,22 @@
+'use strict';
+
+const _ = require('lodash');
+const meta = require('./.user.js');
+const Controller = require('egg').Controller;
+const { CrudController } = require('naf-framework-mongoose/lib/controller');
+
+// 管理
+class UserController extends Controller {
+
+  constructor(ctx) {
+    super(ctx);
+    this.service = this.ctx.service.user;
+  }
+
+  async create() {
+    const res = await this.service.create(this.ctx.request.body);
+    this.ctx.ok({ data: res });
+  }
+}
+
+module.exports = CrudController(UserController, meta);

+ 26 - 0
app/model/user.js

@@ -0,0 +1,26 @@
+'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 UserSchema = {
+  name: { type: String, required: false, maxLength: 200 }, // 名称
+  mobile: { type: String, required: true, maxLength: 64 }, // 手机
+  passwd: { type: Secret, select: false }, // 注册密码
+  openid: { type: String, required: false }, // 微信openid
+  remark: { type: String, required: false }, // 备注
+  type: { type: String, required: false, maxLength: 200 }, // 身份,0、中心管理元1、班主任用户2、学校用户3、教师4、学生
+  uid: { type: String, required: false, maxLength: 200 }, // 关联用户信息id
+};
+
+
+const schema = new Schema(UserSchema, { toJSON: { virtuals: true } });
+schema.index({ openid: 1 });
+schema.index({ mobile: 1 });
+schema.plugin(metaPlugin);
+
+module.exports = app => {
+  const { mongoose } = app;
+  return mongoose.model('User', schema, 'user');
+};

+ 65 - 0
app/service/login.js

@@ -0,0 +1,65 @@
+'use strict';
+
+const assert = require('assert');
+const _ = require('lodash');
+const { ObjectId } = require('mongoose').Types;
+const { CrudService } = require('naf-framework-mongoose/lib/service');
+const { BusinessError, ErrorCode } = require('naf-core').Error;
+const jwt = require('jsonwebtoken');
+
+class LoginService extends CrudService {
+  constructor(ctx) {
+    super(ctx, 'login');
+    this.uModel = this.ctx.model.User;
+    this.stuModel = this.ctx.model.Student;
+    this.tModel = this.ctx.model.Teacher;
+    this.schModel = this.ctx.model.School;
+    this.hModel = this.ctx.model.Headteacher;
+  }
+
+  async login(data) {
+    const { mobile, passwd } = data;
+    assert(mobile, 'mobile不能为空');
+    assert(/^\d{11}$/i.test(mobile), 'mobile无效');
+    assert(passwd, 'passwd不能为空');
+    const res = await this.uModel.findOne({ mobile }, '+passwd');
+    if (!res) {
+      throw new BusinessError(ErrorCode.USER_NOT_EXIST);
+    }
+    // 验证密码
+    console.log(res.passwd.secret);
+    console.log(passwd);
+    if (res.passwd.secret !== passwd) {
+      throw new BusinessError(ErrorCode.BAD_PASSWORD);
+    }
+    return await this.createJwt(res);
+  }
+
+  // 创建登录Token
+  async createJwt({ _id, name, mobile, openid, type, uid }) {
+    const { secret, expiresIn = '1d', issuer = type } = this.config.jwt;
+    const subject = mobile;
+    let _userid = '';
+    if (type === '0') {
+      _userid = _id.toString();
+    } else {
+      _userid = uid.toString();
+    }
+    const token = await jwt.sign({ userid: _userid, name, openid, type }, secret, { expiresIn, issuer, subject });
+    return token;
+  }
+
+  async wxlogin(data) {
+    const { openid } = data;
+    assert(openid, 'openid不能为空');
+    const res = await this.uModel.findOne({ openid });
+    let newdata = {};
+    if (!res) {
+      throw new BusinessError(ErrorCode.USER_NOT_EXIST);
+    } else {
+      newdata = { id: res.id, name: res.name, openid: res.openid, type: res.type };
+    }
+    return await newdata;
+  }
+}
+module.exports = LoginService;

+ 23 - 5
app/service/school.js

@@ -16,6 +16,9 @@ class SchoolService extends CrudService {
 
 
   async stuimport(data) {
   async stuimport(data) {
     const { filepath, termid, schid } = data;
     const { filepath, termid, schid } = data;
+    assert(filepath, 'filepath不能为空');
+    assert(termid, 'termid不能为空');
+    assert(schid, 'schid不能为空');
     // 取得excle中数据
     // 取得excle中数据
     const studatas = await this.getImportXLSXData(filepath, termid, schid);
     const studatas = await this.getImportXLSXData(filepath, termid, schid);
     // 将得到的数据校验
     // 将得到的数据校验
@@ -75,24 +78,39 @@ class SchoolService extends CrudService {
   // 获取导入的XLSX文件中的数据
   // 获取导入的XLSX文件中的数据
   async datacheck(studatas) {
   async datacheck(studatas) {
     let errorcode = '0';
     let errorcode = '0';
-    let errormsg = '';
+    const errormsg = [];
     for (const data of studatas) {
     for (const data of studatas) {
       // 判断是否为空
       // 判断是否为空
       if (!data.name) {
       if (!data.name) {
         errorcode = '1';
         errorcode = '1';
-        errormsg = errormsg + '姓名不允许为空,';
+        data.msg = '姓名不允许为空';
+        errormsg.push(data);
       }
       }
       if (!data.id_number) {
       if (!data.id_number) {
         errorcode = '1';
         errorcode = '1';
-        errormsg = errormsg + '身份证号不允许为空,';
+        data.msg = '身份证号不允许为空';
+        errormsg.push(data);
       }
       }
       if (!data.school_name) {
       if (!data.school_name) {
         errorcode = '1';
         errorcode = '1';
-        errormsg = errormsg + '学校名称不允许为空,';
+        data.msg = '姓学校名称不允许为空';
+        errormsg.push(data);
       }
       }
       if (!data.phone) {
       if (!data.phone) {
         errorcode = '1';
         errorcode = '1';
-        errormsg = errormsg + '手机号不允许为空,';
+        data.msg = '手机号不允许为空';
+        errormsg.push(data);
+      }
+      if (!/^\d{11}$/i.test(data.phone)) {
+        errorcode = '1';
+        data.msg = '手机号不正确';
+        errormsg.push(data);
+      }
+      const res = await this.model.findOne({ id_number: data.id_number });
+      if (res) {
+        errorcode = '1';
+        data.msg = '学生已经存在请检查';
+        errormsg.push(data);
       }
       }
     }
     }
     return { errorcode, errormsg };
     return { errorcode, errormsg };

+ 41 - 0
app/service/user.js

@@ -0,0 +1,41 @@
+'use strict';
+
+
+const assert = require('assert');
+const _ = require('lodash');
+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;
+    this.stuModel = this.ctx.model.Student;
+    this.tModel = this.ctx.model.Teacher;
+    this.schModel = this.ctx.model.School;
+    this.hModel = this.ctx.model.Headteacher;
+  }
+
+  // 重写创建方法
+  async create(data) {
+    const { name, mobile, passwd, type, gender } = data;
+    assert(name && mobile && passwd && type, '缺少部分信息项');
+    assert(/^\d{11}$/i.test(mobile), 'mobile无效');
+    const newdata = data;
+    newdata.passwd = { secret: passwd };
+    const res = await this.model.create(newdata);
+    if (res) {
+      // 如果是班主任的时候将用户信息填入班主任表
+      if (type === '1') {
+        const headt = { name, phone: mobile, gender };
+        await this.hModel.create(headt);
+      }
+    }
+    return res;
+  }
+
+
+}
+
+module.exports = UserService;

+ 15 - 1
config/config.default.js

@@ -1,7 +1,7 @@
 /* eslint valid-jsdoc: "off" */
 /* eslint valid-jsdoc: "off" */
 
 
 'use strict';
 'use strict';
-
+const { jwt } = require('./config.secret');
 /**
 /**
  * @param {Egg.EggAppInfo} appInfo app info
  * @param {Egg.EggAppInfo} appInfo app info
  */
  */
@@ -60,6 +60,20 @@ module.exports = appInfo => {
     },
     },
   };
   };
 
 
+  // 安全配置
+  config.security = {
+    csrf: {
+      // ignoreJSON: true, // 默认为 false,当设置为 true 时,将会放过所有 content-type 为 `application/json` 的请求
+      enable: false,
+    },
+  };
+  // // JWT config
+  config.jwt = {
+    ...jwt,
+    expiresIn: '1d',
+    issuer: 'train',
+  };
+
   return {
   return {
     ...config,
     ...config,
     ...userConfig,
     ...userConfig,