mirror of
https://github.com/cool-team-official/cool-admin-midway.git
synced 2026-02-07 18:45:33 +00:00
完善了权限管理功能
This commit is contained in:
parent
832dd68f30
commit
046940e2e8
5
.vscode/middleware.code-snippets
vendored
5
.vscode/middleware.code-snippets
vendored
@ -3,7 +3,8 @@
|
||||
"prefix": "middleware",
|
||||
"body": [
|
||||
"import { Provide } from '@midwayjs/decorator';",
|
||||
"import { IWebMiddleware, IMidwayWebNext, IMidwayWebContext } from '@midwayjs/web';",
|
||||
"import { IWebMiddleware, IMidwayWebNext } from '@midwayjs/web';",
|
||||
"import { Context } from 'egg';",
|
||||
"",
|
||||
"/**",
|
||||
" * 描述",
|
||||
@ -12,7 +13,7 @@
|
||||
"export class XxxMiddleware implements IWebMiddleware {",
|
||||
"",
|
||||
" resolve() {",
|
||||
" return async (ctx: IMidwayWebContext, next: IMidwayWebNext) => {",
|
||||
" return async (ctx: Context, next: IMidwayWebNext) => {",
|
||||
" // 控制器前执行的逻辑",
|
||||
" const startTime = Date.now();",
|
||||
" // 执行下一个 Web 中间件,最后执行到控制器",
|
||||
|
||||
@ -1,32 +1,31 @@
|
||||
import { Provide } from '@midwayjs/decorator';
|
||||
import * as ipdb from 'ipip-ipdb';
|
||||
import * as _ from 'lodash';
|
||||
import { Context } from 'egg';
|
||||
|
||||
/**
|
||||
* 帮助类
|
||||
*/
|
||||
export default class Helper {
|
||||
/**
|
||||
* 获得请求IP
|
||||
*/
|
||||
public static async getReqIP() {
|
||||
// @ts-ignore
|
||||
const req = this.ctx.req;
|
||||
return (req.headers['x-forwarded-for'] || // 判断是否有反向代理 IP
|
||||
req.connection.remoteAddress || // 判断 connection 的远程 IP
|
||||
req.socket.remoteAddress || // 判断后端的 socket 的 IP
|
||||
req.connection.socket.remoteAddress).replace('::ffff:', '');
|
||||
@Provide()
|
||||
export class Helper {
|
||||
/**
|
||||
* 获得请求IP
|
||||
*/
|
||||
public async getReqIP(ctx: Context) {
|
||||
const req = ctx.req;
|
||||
return req.headers['x-forwarded-for'] || req.socket.remoteAddress
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据IP获得请求地址
|
||||
* @param ip 为空时则为当前请求的IP地址
|
||||
*/
|
||||
public static async getIpAddr(ip?: string) {
|
||||
public async getIpAddr(ctx: Context, ip?: string | string[]) {
|
||||
try {
|
||||
if (!ip) {
|
||||
ip = await this.getReqIP();
|
||||
ip = await this.getReqIP(ctx);
|
||||
}
|
||||
const bst = new ipdb.BaseStation('app/resource/ipip/ipipfree.ipdb');
|
||||
const bst = new ipdb.BaseStation('./ipipfree.ipdb');
|
||||
const result = bst.findInfo(ip, 'CN');
|
||||
const addArr: any = [];
|
||||
if (result) {
|
||||
@ -35,7 +34,7 @@ export default class Helper {
|
||||
addArr.push(result.cityName);
|
||||
return _.uniq(addArr).join('');
|
||||
}
|
||||
// @ts-ignore
|
||||
// @ts-ignore
|
||||
} catch (err) {
|
||||
return '无法获取地址信息';
|
||||
}
|
||||
@ -45,7 +44,7 @@ export default class Helper {
|
||||
* 去除对象的空值属性
|
||||
* @param obj
|
||||
*/
|
||||
public static async removeEmptyP (obj) {
|
||||
public async removeEmptyP(obj) {
|
||||
Object.keys(obj).forEach(key => {
|
||||
if (obj[key] === null || obj[key] === '' || obj[key] === 'undefined') {
|
||||
delete obj[key];
|
||||
@ -57,7 +56,7 @@ export default class Helper {
|
||||
* 线程阻塞毫秒数
|
||||
* @param ms
|
||||
*/
|
||||
public static sleep(ms) {
|
||||
public sleep(ms) {
|
||||
return new Promise(resolve => setTimeout(resolve, ms));
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,6 +11,6 @@ export default (app: Application) => {
|
||||
// 模块描述
|
||||
describe: '基础的权限管理功能,包括登录,权限校验',
|
||||
// 中间件
|
||||
middlewares: ['baseLogsMiddleware'],
|
||||
middlewares: ['baseLogMiddleware', 'baseAuthorityMiddleware'],
|
||||
} as ModuleConfig;
|
||||
};
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
import { Body, Provide, ALL, Inject, Post, Get, Query } from '@midwayjs/decorator';
|
||||
import { Provide, Inject, Get } from '@midwayjs/decorator';
|
||||
import { Context } from 'egg';
|
||||
import { CoolController, BaseController } from 'midwayjs-cool-core';
|
||||
import { LoginDTO } from '../../dto/login';
|
||||
import { BaseSysLoginService } from '../../service/sys/login';
|
||||
import { BaseSysPermsService } from '../../service/sys/perms';
|
||||
import { BaseSysUserService } from '../../service/sys/user';
|
||||
|
||||
/**
|
||||
* Base 通用接口 一般写不需要权限过滤的接口
|
||||
@ -11,23 +12,28 @@ import { BaseSysLoginService } from '../../service/sys/login';
|
||||
export class BaseCommController extends BaseController {
|
||||
|
||||
@Inject()
|
||||
baseSysLoginService: BaseSysLoginService;
|
||||
baseSysUserService: BaseSysUserService;
|
||||
|
||||
@Inject()
|
||||
baseSysPermsService: BaseSysPermsService;
|
||||
|
||||
@Inject()
|
||||
ctx: Context;
|
||||
|
||||
/**
|
||||
* 登录
|
||||
* @param login
|
||||
* 获得个人信息
|
||||
*/
|
||||
@Post('/login')
|
||||
async login(@Body(ALL) login: LoginDTO) {
|
||||
return this.ok(await this.baseSysLoginService.login(login))
|
||||
@Get('/person')
|
||||
public async person() {
|
||||
return this.ok(await this.baseSysUserService.person());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得验证码
|
||||
* 权限菜单
|
||||
*/
|
||||
@Get('/captcha')
|
||||
async captcha(@Query() type: string, @Query() width: number, @Query() height: number) {
|
||||
return this.ok(await this.baseSysLoginService.captcha(type, width, height));
|
||||
@Get('/permmenu')
|
||||
public async permmenu() {
|
||||
return this.ok(await this.baseSysPermsService.permmenu(this.ctx.admin.roleIds));
|
||||
}
|
||||
|
||||
}
|
||||
40
src/app/modules/base/controller/admin/open.ts
Normal file
40
src/app/modules/base/controller/admin/open.ts
Normal file
@ -0,0 +1,40 @@
|
||||
import { Provide, Body, ALL, Inject, Post, Get, Query } from '@midwayjs/decorator';
|
||||
import { CoolController, BaseController } from 'midwayjs-cool-core';
|
||||
import { LoginDTO } from '../../dto/login';
|
||||
import { BaseSysLoginService } from '../../service/sys/login';
|
||||
|
||||
/**
|
||||
* 不需要登录的后台接口
|
||||
*/
|
||||
@Provide()
|
||||
@CoolController()
|
||||
export class BaseSysOpenController extends BaseController {
|
||||
|
||||
@Inject()
|
||||
baseSysLoginService: BaseSysLoginService;
|
||||
|
||||
/**
|
||||
* 登录
|
||||
* @param login
|
||||
*/
|
||||
@Post('/login')
|
||||
async login(@Body(ALL) login: LoginDTO) {
|
||||
return this.ok(await this.baseSysLoginService.login(login))
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得验证码
|
||||
*/
|
||||
@Get('/captcha')
|
||||
async captcha(@Query() type: string, @Query() width: number, @Query() height: number) {
|
||||
return this.ok(await this.baseSysLoginService.captcha(type, width, height));
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新token
|
||||
*/
|
||||
@Get('/refreshToken')
|
||||
async refreshToken(@Query() refreshToken: string) {
|
||||
return this.ok(await this.baseSysLoginService.refreshToken(refreshToken))
|
||||
}
|
||||
}
|
||||
29
src/app/modules/base/controller/admin/sys/department.ts
Normal file
29
src/app/modules/base/controller/admin/sys/department.ts
Normal file
@ -0,0 +1,29 @@
|
||||
import { ALL, Body, Inject, Post, Provide } from '@midwayjs/decorator';
|
||||
import { CoolController, BaseController } from 'midwayjs-cool-core';
|
||||
import { BaseSysDepartmentEntity } from '../../../entity/sys/department';
|
||||
import { BaseSysDepartmentService } from '../../../service/sys/department';
|
||||
|
||||
/**
|
||||
* 部门
|
||||
*/
|
||||
@Provide()
|
||||
@CoolController({
|
||||
api: ['add', 'delete', 'update', 'list'],
|
||||
entity: BaseSysDepartmentEntity,
|
||||
service: BaseSysDepartmentService
|
||||
})
|
||||
export class BaseDepartmentController extends BaseController {
|
||||
|
||||
@Inject()
|
||||
baseDepartmentService: BaseSysDepartmentService;
|
||||
|
||||
/**
|
||||
* 部门排序
|
||||
*/
|
||||
@Post('/order')
|
||||
async order(@Body(ALL) params: Object) {
|
||||
await this.baseDepartmentService.order(params);
|
||||
this.ok();
|
||||
}
|
||||
|
||||
}
|
||||
20
src/app/modules/base/controller/admin/sys/menu.ts
Normal file
20
src/app/modules/base/controller/admin/sys/menu.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import { Inject, Provide } from '@midwayjs/decorator';
|
||||
import { CoolController, BaseController } from 'midwayjs-cool-core';
|
||||
import { BaseSysMenuEntity } from '../../../entity/sys/menu';
|
||||
import { BaseSysMenuService } from '../../../service/sys/menu';
|
||||
|
||||
/**
|
||||
* 菜单
|
||||
*/
|
||||
@Provide()
|
||||
@CoolController({
|
||||
api: ['add', 'delete', 'update', 'list', 'page'],
|
||||
entity: BaseSysMenuEntity,
|
||||
service: BaseSysMenuService
|
||||
})
|
||||
export class BaseSysMenuController extends BaseController {
|
||||
|
||||
@Inject()
|
||||
baseSysMenuService: BaseSysMenuService;
|
||||
|
||||
}
|
||||
@ -26,4 +26,8 @@ export class BaseSysLogEntity extends BaseEntity {
|
||||
|
||||
@Column({ comment: '参数', nullable: true, type: 'text' })
|
||||
params: string;
|
||||
|
||||
@Column({ comment: '响应毫秒数, 值为-1则响应不成功', default: -1 })
|
||||
ms: number;
|
||||
|
||||
}
|
||||
|
||||
105
src/app/modules/base/middleware/authority.ts
Normal file
105
src/app/modules/base/middleware/authority.ts
Normal file
@ -0,0 +1,105 @@
|
||||
import { Config, Inject, Provide } from '@midwayjs/decorator';
|
||||
import { IWebMiddleware, IMidwayWebNext } from '@midwayjs/web';
|
||||
import * as _ from 'lodash';
|
||||
import { CoolCache, CoolConfig, RESCODE } from 'midwayjs-cool-core';
|
||||
import * as jwt from 'jsonwebtoken';
|
||||
import { Context } from 'egg';
|
||||
|
||||
/**
|
||||
* 描述
|
||||
*/
|
||||
@Provide()
|
||||
export class BaseAuthorityMiddleware implements IWebMiddleware {
|
||||
|
||||
@Config('cool')
|
||||
coolConfig: CoolConfig;
|
||||
|
||||
@Inject('cool:cache')
|
||||
coolCache: CoolCache;
|
||||
|
||||
resolve() {
|
||||
return async (ctx: Context, next: IMidwayWebNext) => {
|
||||
let statusCode = 200;
|
||||
const { url } = ctx;
|
||||
const token = ctx.get('Authorization');
|
||||
let { prefix } = this.coolConfig.router;
|
||||
const adminUrl = prefix ? `${prefix}/admin/` : '/admin/';
|
||||
// 只要登录每个人都有权限的接口
|
||||
const commUrl = prefix ? `${prefix}/admin/comm/` : '/admin/comm/';
|
||||
// 不需要登录的接口
|
||||
const openUrl = prefix ? `${prefix}/admin/open/` : '/admin/open/';
|
||||
// 路由地址为 admin前缀的 需要权限校验
|
||||
if (_.startsWith(url, adminUrl)) {
|
||||
try {
|
||||
ctx.admin = jwt.verify(token, this.coolConfig.jwt.secret);
|
||||
} catch (err) { }
|
||||
// comm 不需要登录 无需权限校验
|
||||
if (_.startsWith(url, openUrl)) {
|
||||
await next();
|
||||
return;
|
||||
}
|
||||
if (ctx.admin) {
|
||||
if (_.startsWith(url, commUrl)) {
|
||||
await next();
|
||||
return;
|
||||
}
|
||||
// 如果传的token是refreshToken则校验失败
|
||||
if (ctx.admin.isRefresh) {
|
||||
ctx.status = 401;
|
||||
ctx.body = {
|
||||
code: RESCODE.COMMFAIL,
|
||||
message: '登录失效~',
|
||||
};
|
||||
return;
|
||||
}
|
||||
// 判断密码版本是否正确
|
||||
const passwordV = await this.coolCache.get(`admin:passwordVersion:${ctx.admin.userId}`);
|
||||
if (passwordV !== ctx.admin.passwordVersion) {
|
||||
ctx.status = 401;
|
||||
ctx.body = {
|
||||
code: RESCODE.COMMFAIL,
|
||||
message: '登录失效~',
|
||||
};
|
||||
return;
|
||||
}
|
||||
const rToken = await this.coolCache.get(`admin:token:${ctx.admin.userId}`);
|
||||
if (!rToken) {
|
||||
ctx.status = 401;
|
||||
ctx.body = {
|
||||
code: RESCODE.COMMFAIL,
|
||||
message: '登录失效或无权限访问~',
|
||||
};
|
||||
return;
|
||||
}
|
||||
if (rToken !== token && this.coolConfig.sso) {
|
||||
statusCode = 401;
|
||||
} else {
|
||||
let perms = await this.coolCache.get(`admin:perms:${ctx.admin.userId}`);
|
||||
if (!_.isEmpty(perms)) {
|
||||
perms = JSON.parse(perms).map(e => {
|
||||
return e.replace(/:/g, '/');
|
||||
});
|
||||
if (!perms.includes(url.split('?')[0].replace('/admin/', ''))) {
|
||||
statusCode = 403;
|
||||
}
|
||||
} else {
|
||||
statusCode = 403;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
statusCode = 401;
|
||||
}
|
||||
if (statusCode > 200) {
|
||||
ctx.status = statusCode;
|
||||
ctx.body = {
|
||||
code: RESCODE.COMMFAIL,
|
||||
message: '登录失效或无权限访问~',
|
||||
};
|
||||
return;
|
||||
}
|
||||
}
|
||||
await next();
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,21 +1,21 @@
|
||||
import { Provide } from '@midwayjs/decorator';
|
||||
import { IWebMiddleware, IMidwayWebNext, IMidwayWebContext } from '@midwayjs/web';
|
||||
import { Inject, Provide } from '@midwayjs/decorator';
|
||||
import { IWebMiddleware, IMidwayWebNext } from '@midwayjs/web';
|
||||
import { BaseSysLogService } from '../service/sys/log';
|
||||
import { Context } from 'egg';
|
||||
|
||||
/**
|
||||
* 日志中间件
|
||||
*/
|
||||
@Provide()
|
||||
export class BaseLogsMiddleware implements IWebMiddleware {
|
||||
export class BaseLogMiddleware implements IWebMiddleware {
|
||||
|
||||
@Inject()
|
||||
baseSysLogService: BaseSysLogService;
|
||||
|
||||
resolve() {
|
||||
return async (ctx: IMidwayWebContext, next: IMidwayWebNext) => {
|
||||
console.log('日志')
|
||||
// 控制器前执行的逻辑
|
||||
const startTime = Date.now();
|
||||
// 执行下一个 Web 中间件,最后执行到控制器
|
||||
return async (ctx: Context, next: IMidwayWebNext) => {
|
||||
this.baseSysLogService.record(ctx.url.split('?')[0], ctx.req.method === 'GET' ? ctx.request.query : ctx.request.body, ctx.admin ? ctx.admin.userId : null);
|
||||
await next();
|
||||
// 控制器之后执行的逻辑
|
||||
console.log(Date.now() - startTime);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -1,10 +1,12 @@
|
||||
import { Provide } from '@midwayjs/decorator';
|
||||
import { Inject, Provide } from '@midwayjs/decorator';
|
||||
import { BaseService } from 'midwayjs-cool-core';
|
||||
import { InjectEntityModel } from '@midwayjs/orm';
|
||||
import { Repository } from 'typeorm';
|
||||
import { BaseSysDepartmentEntity } from '../../entity/sys/department';
|
||||
import * as _ from 'lodash';
|
||||
import { BaseSysRoleDepartmentEntity } from '../../entity/sys/role_department';
|
||||
import { Context } from 'egg';
|
||||
import { BaseSysPermsService } from './perms';
|
||||
|
||||
/**
|
||||
* 描述
|
||||
@ -18,6 +20,42 @@ export class BaseSysDepartmentService extends BaseService {
|
||||
@InjectEntityModel(BaseSysRoleDepartmentEntity)
|
||||
baseSysRoleDepartmentEntity: Repository<BaseSysRoleDepartmentEntity>;
|
||||
|
||||
@Inject()
|
||||
baseSysPremsService: BaseSysPermsService;
|
||||
|
||||
@Inject()
|
||||
ctx: Context;
|
||||
|
||||
/**
|
||||
* 获得部门菜单
|
||||
*/
|
||||
async list () {
|
||||
const permsDepartmentArr = await this.baseSysPremsService.departmentIds(this.ctx.admin.userId); // 部门权限
|
||||
const departments = await this.nativeQuery(`
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
base_sys_department a
|
||||
WHERE
|
||||
1 = 1
|
||||
${ this.setSql(this.ctx.decoded.userId !== '1', 'and a.id in (?)', [ !_.isEmpty(permsDepartmentArr) ? permsDepartmentArr : [ null ] ]) }
|
||||
ORDER BY
|
||||
a.orderNum ASC`);
|
||||
if (!_.isEmpty(departments)) {
|
||||
departments.forEach(e => {
|
||||
const parentMenu = departments.filter(m => {
|
||||
if (e.parentId === m.id) {
|
||||
return m.name;
|
||||
}
|
||||
});
|
||||
if (!_.isEmpty(parentMenu)) {
|
||||
e.parentName = parentMenu[0].name;
|
||||
}
|
||||
});
|
||||
}
|
||||
return departments;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据多个ID获得部门权限信息
|
||||
* @param {[]} roleIds 数组
|
||||
@ -40,4 +78,31 @@ export class BaseSysDepartmentService extends BaseService {
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* 部门排序
|
||||
* @param params
|
||||
*/
|
||||
async order (params) {
|
||||
for (const e of params) {
|
||||
await this.baseSysDepartmentEntity.update(e.id, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除
|
||||
*/
|
||||
async delete (ids: number[]) {
|
||||
let { deleteUser } = this.ctx.request.body;
|
||||
await this.baseSysDepartmentEntity.delete(ids);
|
||||
if (deleteUser) {
|
||||
await this.nativeQuery('delete from base_sys_user where departmentId in (?)', [ ids ]);
|
||||
} else {
|
||||
const topDepartment = await this.baseSysDepartmentEntity.createQueryBuilder().where('parentId is null').getOne();
|
||||
if (topDepartment) {
|
||||
await this.nativeQuery('update base_sys_user a set a.departmentId = ? where a.departmentId in (?)', [ topDepartment.id, ids ]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -6,6 +6,7 @@ import { Context } from 'egg';
|
||||
import * as _ from 'lodash';
|
||||
import { BaseSysLogEntity } from '../../entity/sys/log';
|
||||
import * as moment from 'moment';
|
||||
import { Helper } from '../../../../extend/helper';
|
||||
|
||||
/**
|
||||
* 描述
|
||||
@ -16,6 +17,9 @@ export class BaseSysLogService extends BaseService {
|
||||
@Inject()
|
||||
ctx: Context;
|
||||
|
||||
// @Inject()
|
||||
// helper: Helper;
|
||||
|
||||
@InjectEntityModel(BaseSysLogEntity)
|
||||
baseSysLogEntity: Repository<BaseSysLogEntity>;
|
||||
|
||||
@ -26,18 +30,18 @@ export class BaseSysLogService extends BaseService {
|
||||
* @param userId 用户ID
|
||||
*/
|
||||
async record(url, params, userId) {
|
||||
const ip = await this.ctx.helper.getReqIP();
|
||||
const sysLog = new BaseSysLogEntity();
|
||||
sysLog.userId = userId;
|
||||
sysLog.ip = ip;
|
||||
const ipAddrArr = new Array();
|
||||
for (const e of ip.split(',')) ipAddrArr.push(await this.ctx.helper.getIpAddr(e));
|
||||
sysLog.ipAddr = ipAddrArr.join(',');
|
||||
sysLog.action = url;
|
||||
if (!_.isEmpty(params)) {
|
||||
sysLog.params = JSON.stringify(params);
|
||||
}
|
||||
await this.baseSysLogEntity.insert(sysLog);
|
||||
// const ip = await this.helper.getReqIP(this.ctx);
|
||||
// const sysLog = new BaseSysLogEntity();
|
||||
// sysLog.userId = userId;
|
||||
// sysLog.ip = ip;
|
||||
// const ipAddrArr = new Array();
|
||||
// for (const e of ip.split(',')) ipAddrArr.push(await this.ctx.helper.getIpAddr(e));
|
||||
// sysLog.ipAddr = ipAddrArr.join(',');
|
||||
// sysLog.action = url;
|
||||
// if (!_.isEmpty(params)) {
|
||||
// sysLog.params = JSON.stringify(params);
|
||||
// }
|
||||
// await this.baseSysLogEntity.insert(sysLog);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { Inject, Provide, Config } from '@midwayjs/decorator';
|
||||
import { BaseService, CoolCache, CoolCommException } from 'midwayjs-cool-core';
|
||||
import { BaseService, CoolCache, CoolCommException, CoolConfig, RESCODE } from 'midwayjs-cool-core';
|
||||
import { LoginDTO } from '../../dto/login';
|
||||
import * as svgCaptcha from 'svg-captcha';
|
||||
import * as svgToDataURL from 'svg-to-dataurl';
|
||||
@ -13,6 +13,7 @@ import * as _ from 'lodash';
|
||||
import { BaseSysMenuService } from './menu';
|
||||
import { BaseSysDepartmentService } from './department';
|
||||
import * as jwt from 'jsonwebtoken';
|
||||
import { Context } from 'egg';
|
||||
|
||||
/**
|
||||
* 登录
|
||||
@ -24,7 +25,7 @@ export class BaseSysLoginService extends BaseService {
|
||||
coolCache: CoolCache;
|
||||
|
||||
@InjectEntityModel(BaseSysUserEntity)
|
||||
baseSysLogEntity: Repository<BaseSysUserEntity>;
|
||||
baseSysUserEntity: Repository<BaseSysUserEntity>;
|
||||
|
||||
@Inject()
|
||||
baseSysRoleService: BaseSysRoleService;
|
||||
@ -35,8 +36,11 @@ export class BaseSysLoginService extends BaseService {
|
||||
@Inject()
|
||||
baseSysDepartmentService: BaseSysDepartmentService;
|
||||
|
||||
@Inject()
|
||||
ctx: Context;
|
||||
|
||||
@Config('cool')
|
||||
coolConfig;
|
||||
coolConfig: CoolConfig;
|
||||
|
||||
/**
|
||||
* 登录
|
||||
@ -46,7 +50,7 @@ export class BaseSysLoginService extends BaseService {
|
||||
const { username, captchaId, verifyCode, password } = login;
|
||||
const checkV = await this.captchaCheck(captchaId, verifyCode);
|
||||
if (checkV) {
|
||||
const user = await this.baseSysLogEntity.findOne({ username });
|
||||
const user = await this.baseSysUserEntity.findOne({ username });
|
||||
if (user) {
|
||||
if (user.status === 0 || user.password !== md5(password)) {
|
||||
throw new CoolCommException('账户或密码不正确~');
|
||||
@ -59,12 +63,12 @@ export class BaseSysLoginService extends BaseService {
|
||||
throw new CoolCommException('该用户未设置任何角色,无法登录~');
|
||||
}
|
||||
|
||||
const { expire, refreshExpire } = this.coolConfig.token.jwt;
|
||||
const { expire, refreshExpire } = this.coolConfig.jwt.token;
|
||||
const result = {
|
||||
expire,
|
||||
token: await this.generateToken(user, roleIds, expire),
|
||||
refreshExpire,
|
||||
refreshToken: await this.generateToken(user, roleIds, refreshExpire),
|
||||
refreshToken: await this.generateToken(user, roleIds, refreshExpire, true),
|
||||
};
|
||||
|
||||
const perms = await this.baseSysMenuService.getPerms(roleIds);
|
||||
@ -111,11 +115,11 @@ export class BaseSysLoginService extends BaseService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 检验图片验证码
|
||||
* @param captchaId 验证码ID
|
||||
* @param value 验证码
|
||||
*/
|
||||
public async captchaCheck(captchaId, value) {
|
||||
* 检验图片验证码
|
||||
* @param captchaId 验证码ID
|
||||
* @param value 验证码
|
||||
*/
|
||||
async captchaCheck(captchaId, value) {
|
||||
const rv = await this.coolCache.get(`verify:img:${captchaId}`);
|
||||
if (!rv || !value || value.toLowerCase() !== rv) {
|
||||
return false;
|
||||
@ -137,16 +141,40 @@ export class BaseSysLoginService extends BaseService {
|
||||
const tokenInfo = {
|
||||
isRefresh: false,
|
||||
roleIds,
|
||||
username: user.username,
|
||||
userId: user.id,
|
||||
passwordVersion: user.passwordV,
|
||||
};
|
||||
if (isRefresh) {
|
||||
delete tokenInfo.roleIds;
|
||||
tokenInfo.isRefresh = true;
|
||||
}
|
||||
return jwt.sign(tokenInfo,
|
||||
this.coolConfig.token.jwt.secret, {
|
||||
this.coolConfig.jwt.secret, {
|
||||
expiresIn: expire,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新token
|
||||
* @param token
|
||||
*/
|
||||
async refreshToken(token: string) {
|
||||
try {
|
||||
const decoded = jwt.verify(token, this.coolConfig.jwt.secret);
|
||||
if (decoded && decoded['isRefresh']) {
|
||||
return jwt.sign(decoded,
|
||||
this.coolConfig.jwt.secret, {
|
||||
expiresIn: this.coolConfig.jwt.token.expire,
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
this.ctx.status = 401;
|
||||
this.ctx.body = {
|
||||
code: RESCODE.COMMFAIL,
|
||||
message: '登录失效~',
|
||||
};
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@ -22,7 +22,7 @@ export class BaseSysMenuService extends BaseService {
|
||||
* 获得所有菜单
|
||||
*/
|
||||
async list() {
|
||||
const menus = await this.getMenus(this.ctx.admin.roleIds);
|
||||
const menus = await this.getMenus(this.ctx.admin.roleIds, this.ctx.admin.username === 'admin');
|
||||
if (!_.isEmpty(menus)) {
|
||||
menus.forEach(e => {
|
||||
const parentMenu = menus.filter(m => {
|
||||
@ -46,8 +46,8 @@ export class BaseSysMenuService extends BaseService {
|
||||
let perms = [];
|
||||
if (!_.isEmpty(roleIds)) {
|
||||
const result = await this.nativeQuery(`
|
||||
SELECT a.perms FROM sys_menu a ${this.setSql(!roleIds.includes('1'),
|
||||
'JOIN sys_role_menu b on a.id = b.menuId AND b.roleId in (?)', [roleIds])}
|
||||
SELECT a.perms FROM base_sys_menu a ${this.setSql(!roleIds.includes('1'),
|
||||
'JOIN base_sys_role_menu b on a.id = b.menuId AND b.roleId in (?)', [roleIds])}
|
||||
where 1=1 and a.perms is not NULL
|
||||
`, [roleIds]);
|
||||
if (result) {
|
||||
@ -68,14 +68,15 @@ export class BaseSysMenuService extends BaseService {
|
||||
/**
|
||||
* 获得用户菜单信息
|
||||
* @param roleIds
|
||||
* @param isAdmin 是否是超管
|
||||
*/
|
||||
async getMenus(roleIds) {
|
||||
async getMenus(roleIds, isAdmin) {
|
||||
return await this.nativeQuery(`
|
||||
SELECT
|
||||
a.*
|
||||
FROM
|
||||
sys_menu a
|
||||
${this.setSql(!roleIds.includes('1'), 'JOIN sys_role_menu b on a.id = b.menuId AND b.roleId in (?)', [roleIds])}
|
||||
base_sys_menu a
|
||||
${this.setSql(!isAdmin, 'JOIN base_sys_role_menu b on a.id = b.menuId AND b.roleId in (?)', [roleIds])}
|
||||
GROUP BY a.id
|
||||
ORDER BY
|
||||
orderNum ASC`);
|
||||
@ -122,7 +123,7 @@ export class BaseSysMenuService extends BaseService {
|
||||
* @param menuId
|
||||
*/
|
||||
async refreshPerms(menuId) {
|
||||
const users = await this.nativeQuery('select b.userId from sys_role_menu a left join sys_user_role b on a.roleId = b.roleId where a.menuId = ? group by b.userId', [menuId]);
|
||||
const users = await this.nativeQuery('select b.userId from base_sys_role_menu a left join base_sys_user_role b on a.roleId = b.roleId where a.menuId = ? group by b.userId', [menuId]);
|
||||
// 刷新admin权限
|
||||
await this.ctx.service.sys.perms.refreshPerms(1);
|
||||
if (!_.isEmpty(users)) {
|
||||
|
||||
62
src/app/modules/base/service/sys/perms.ts
Normal file
62
src/app/modules/base/service/sys/perms.ts
Normal file
@ -0,0 +1,62 @@
|
||||
import { Inject, Provide } from '@midwayjs/decorator';
|
||||
import { BaseService, CoolCache } from 'midwayjs-cool-core';
|
||||
import { BaseSysMenuService } from './menu';
|
||||
import { BaseSysRoleService } from './role';
|
||||
import { BaseSysDepartmentService } from './department';
|
||||
|
||||
/**
|
||||
* 描述
|
||||
*/
|
||||
@Provide()
|
||||
export class BaseSysPermsService extends BaseService {
|
||||
|
||||
@Inject('cool:cache')
|
||||
coolCache: CoolCache;
|
||||
|
||||
@Inject()
|
||||
baseSysMenuService: BaseSysMenuService;
|
||||
|
||||
@Inject()
|
||||
baseSysRoleService: BaseSysRoleService;
|
||||
|
||||
@Inject()
|
||||
baseSysDepartmentService: BaseSysDepartmentService;
|
||||
|
||||
|
||||
/**
|
||||
* 刷新权限
|
||||
* @param userId 用户ID
|
||||
*/
|
||||
async refreshPerms(userId) {
|
||||
const roleIds = await this.baseSysRoleService.getByUser(userId);
|
||||
const perms = await this.ctx.service.sys.menu.getPerms(roleIds);
|
||||
await this.coolCache.set(`admin:perms:${userId}`, JSON.stringify(perms), this.app.config.token.expires);
|
||||
// 更新部门权限
|
||||
const departments = await this.baseSysDepartmentService.getByRoleIds(roleIds, this.ctx.admin.username === 'admin');
|
||||
await this.coolCache.set(`admin:department:${userId}`, JSON.stringify(departments), this.app.config.token.expires);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得权限菜单
|
||||
* @param roleIds
|
||||
*/
|
||||
async permmenu(roleIds: number[]) {
|
||||
const perms = await this.baseSysMenuService.getPerms(roleIds);
|
||||
const menus = await this.baseSysMenuService.getMenus(roleIds, this.ctx.admin.username === 'admin');
|
||||
return { perms, menus };
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据用户ID获得部门权限
|
||||
* @param userId
|
||||
* @return 部门ID数组
|
||||
*/
|
||||
async departmentIds(userId: number) {
|
||||
const department = await this.coolCache.get(`admin:department:${userId}`);
|
||||
if (department) {
|
||||
return JSON.parse(department);
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -25,8 +25,10 @@ export class BaseSysUserService extends BaseService {
|
||||
.execute();
|
||||
}
|
||||
|
||||
async test(){
|
||||
// const a = await this.adminSysUserEntity.find();
|
||||
// console.log(a);
|
||||
/**
|
||||
* 获得个人信息
|
||||
*/
|
||||
async person() {
|
||||
return await this.baseSysUserEntity.findOne({ id: this.ctx.admin.userId })
|
||||
}
|
||||
}
|
||||
@ -53,6 +53,8 @@ export default (appInfo: EggAppInfo) => {
|
||||
router: {
|
||||
prefix: ''
|
||||
},
|
||||
// 单点登录
|
||||
sso: false,
|
||||
// jwt 生成解密token的
|
||||
jwt: {
|
||||
// 注意: 最好重新修改,防止破解
|
||||
|
||||
@ -7,10 +7,10 @@ export default (appInfo: EggAppInfo) => {
|
||||
|
||||
config.orm = {
|
||||
type: 'mysql',
|
||||
host: '127.0.0.1',
|
||||
host: '139.196.196.203',
|
||||
port: 3306,
|
||||
username: 'root',
|
||||
password: '123123',
|
||||
username: 'cool-admin-next',
|
||||
password: 'Rr4bktexbMNTPmyJ',
|
||||
database: 'cool-admin-next',
|
||||
// 自动建表 注意:线上部署的时候不要使用,有可能导致数据丢失
|
||||
synchronize: true,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user