UNPKG

lin-cms-test

Version:

The core library of Lin CMS, this package is just for test!

220 lines (219 loc) 7.09 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = require("tslib"); const jsonwebtoken_1 = tslib_1.__importStar(require("jsonwebtoken")); const exception_1 = require("./exception"); const lodash_1 = require("lodash"); const core_1 = require("./core"); const enums_1 = require("./enums"); const config_1 = require("./config"); class Token { constructor(secret, accessExp, refreshExp) { this.accessExp = Math.floor(Date.now() / 1000) + 60 * 60; // 1h; this.refreshExp = Math.floor(Date.now() / 1000) + 60 * 60 * 24 * 30 * 3; // 3 months secret && (this.secret = secret); refreshExp && (this.refreshExp = refreshExp); accessExp && (this.accessExp = accessExp); } /** * initApp */ initApp(app, secret, accessExp, refreshExp) { // 将jwt实例挂到app的context上 app.context.jwt = this; secret && (this.secret = secret); refreshExp && (this.refreshExp = refreshExp); accessExp && (this.accessExp = accessExp); } /** * 生成access_token * @param identity 标识位 */ createAccessToken(identity) { if (!this.secret) { throw new Error("密匙不可为空"); } return jsonwebtoken_1.default.sign({ exp: this.accessExp, identity: identity, type: enums_1.TokenType.ACCESS }, this.secret); } /** * 生成refresh_token * @param identity 标识位 */ createRefreshToken(identity) { if (!this.secret) { throw new Error("密匙不可为空"); } return jsonwebtoken_1.default.sign({ exp: this.refreshExp, identity: identity, type: enums_1.TokenType.REFRESH }, this.secret); } /** * verifyToken 验证token * 若过期,抛出ExpiredTokenException * 若失效,抛出InvalidTokenException */ verifyToken(token) { if (!this.secret) { throw new Error("密匙不可为空"); } // NotBeforeError // TokenExpiredError let decode; try { decode = jsonwebtoken_1.default.verify(token, this.secret); } catch (error) { if (error instanceof jsonwebtoken_1.TokenExpiredError) { throw new exception_1.ExpiredTokenException(); } else { throw new exception_1.InvalidTokenException(); } } return decode; } } exports.Token = Token; /** * jwt 的实例 */ const jwt = new Token(config_1.config.getItem("secret"), config_1.config.getItem("accessExp"), config_1.config.getItem("refreshExp")); exports.jwt = jwt; /** * 颁发令牌 * @param user 用户 */ function getTokens(user) { const accessToken = jwt.createAccessToken(user.id); const refreshToken = jwt.createRefreshToken(user.id); return { accessToken, refreshToken }; } exports.getTokens = getTokens; async function parseHeader(ctx, type = enums_1.TokenType.ACCESS) { // 此处借鉴了koa-jwt if (!ctx.header || !ctx.header.authorization) { ctx.throw(new exception_1.AuthFailed({ msg: "认证失败,请检查请求令牌是否正确" })); } const parts = ctx.header.authorization.split(" "); if (parts.length === 2) { // Bearer 字段 const scheme = parts[0]; // token 字段 const token = parts[1]; if (/^Bearer$/i.test(scheme)) { const obj = ctx.jwt.verifyToken(token); if (!lodash_1.get(obj, "type") || lodash_1.get(obj, "type") !== type) { ctx.throw(new exception_1.AuthFailed({ msg: "请使用正确类型的令牌" })); } const user = await ctx.manager.userModel.findById(lodash_1.get(obj, "identity")); if (!user) { ctx.throw(new exception_1.NotFound({ msg: "用户不存在" })); } // 将user挂在ctx上 ctx.currentUser = user; } } else { ctx.throw(new exception_1.AuthFailed()); } } /** * 守卫函数,用户登陆即可访问 */ async function loginRequired(ctx, next) { if (ctx.request.method !== "OPTIONS") { await parseHeader(ctx); // 一定要await,否则这个守卫函数没有作用 await next(); } else { await next(); } } exports.loginRequired = loginRequired; /** * 守卫函数,用户刷新令牌 */ async function refreshTokenRequired(ctx, next) { // 添加access 和 refresh 的标识位 if (ctx.request.method !== "OPTIONS") { await parseHeader(ctx, enums_1.TokenType.REFRESH); await next(); } else { await next(); } } exports.refreshTokenRequired = refreshTokenRequired; /** * 守卫函数,用于权限组鉴权 */ async function groupRequired(ctx, next) { if (ctx.request.method !== "OPTIONS") { await parseHeader(ctx); const currentUser = ctx.currentUser; // 用户处于未激活状态 if (!currentUser || !currentUser.isActive) { throw new exception_1.AuthFailed({ msg: "您目前处于未激活状态,请联系超级管理员" }); } // 超级管理员 if (currentUser && currentUser.isAdmin) { await next(); } else { const groupId = currentUser.group_id; if (!groupId) { throw new exception_1.AuthFailed({ msg: "您还不属于任何权限组,请联系超级管理员获得权限" }); } if (ctx.matched) { const routeName = ctx._matchedRouteName || ctx.routerName; const endpoint = `${ctx.method} ${routeName}`; const { auth, module } = core_1.routeMetaInfo.get(endpoint); const item = await ctx.manager.authModel.findOne({ where: { auth, module } }); // console.log(item); if (item) { await next(); } else { throw new exception_1.AuthFailed({ msg: "权限不够,请联系超级管理员获得权限" }); } } else { throw new exception_1.AuthFailed({ msg: "权限不够,请联系超级管理员获得权限" }); } } } else { await next(); } } exports.groupRequired = groupRequired; /** * 守卫函数,非超级管理员不可访问 */ async function adminRequired(ctx, next) { if (ctx.request.method !== "OPTIONS") { await parseHeader(ctx); const currentUser = ctx.currentUser; if (currentUser && currentUser.isAdmin) { await next(); } else { throw new exception_1.AuthFailed({ msg: "只有超级管理员可操作" }); } } else { await next(); } } exports.adminRequired = adminRequired;