UNPKG

sails-hook-blacksails

Version:
317 lines (285 loc) 8.78 kB
import _ from 'lodash'; import jwt from 'jsonwebtoken'; import crypto from 'crypto'; const AuthService = { isAuthenticated(req) { if (req.session.authenticated) { return true; } return false; }, async isActive(id) { const user = await User.findById(id); const isActive = user ? user.isActive : null; sails.log.info('--------- isActive ? --->', isActive); return isActive; }, getSessionUser(req) { if (req.session.passport !== undefined && req.session.passport.user) { return req.session.passport.user; } return null; }, async isAdmin(req) { const user = this.getSessionUser(req); const result = await this.checkRole(user.id, ['admin']); return result; }, async isSuperAdmin(req) { const user = this.getSessionUser(req); const result = await this.checkRole(user.id, ['super-admin']); return result; }, async checkRole(id, roleNames) { let authority = false; // console.log('id=>', id); const user = await User.findByIdWithRole(id); if (user && user.Roles) { user.Roles.forEach((role) => { // console.log('role=>', role); if (roleNames.some(e => e === role.authority)) { authority = true; } }); } if (authority) { sails.log(`---- check UserName "${user.username}" is "${roleNames}"--> ${authority}`); } else { sails.log.warn(`---- check UserName "${user.username}" is "${roleNames}"--> ${authority}`); } return authority; }, checkAdmin(user) { let authority = false; if (user && user.Roles) { user.Roles.forEach((role) => { if (role.authority === 'admin' || role.authority === 'super-admin') { authority = true; } }); } if (authority) { sails.log(`---- check "${user.username}" isAdmin=>', ${authority}`); } else { sails.log.warn(`---- check "${user.username}" isAdmin=>', ${authority}`); } return authority; }, isUser(req) { try { const user = this.getSessionUser(req); let authority = false; if (user && user.Roles) { user.Roles.forEach((role) => { if (role.authority === 'user') authority = true; }); } return authority; } catch (e) { sails.log.error('=== check isUser failed=>', e); return false; } }, async isRole(req, targetRole) { const session = this.getSessionUser(req); try { if (!session) { throw new Error(MESSAGE.ERROR.NO_USER_LOGIN); } const user = await User.findOne({ where: { id: session.id }, include: [Role], }); let isRole = false; if (user && user.Roles) { user.Roles.forEach((role) => { if (role.authority === targetRole) isRole = true; }); } return isRole; } catch (e) { sails.log.error(e); throw e; } }, isOnlyUser(req) { try { const user = this.getSessionUser(req); let authority = true; if (user && user.Roles) { user.Roles.forEach((role) => { if (role.authority !== 'user') authority = false; }); } else { authority = false; } return authority; } catch (e) { sails.log.error('=== check isOnlyUser failed=>', e); return false; } }, getJWTToken(user, deviceToken) { const jwtSecret = sails.config.session.secret; // FIXME: JWT expiresIn https://github.com/auth0/node-jsonwebtoken return jwt.sign( JSON.stringify({ id: user.id, deviceToken, }), jwtSecret, // { // expiresIn: '60d', // }, ); }, getSessionEncodeToJWT(req, deviceToken) { const user = this.getSessionUser(req); let jwtToken = ''; if (user) { const isWebView = this.isWebView(req.headers['user-agent']); if ((req.session.needJwt || isWebView) && user) { try { jwtToken = this.getJWTToken(user, deviceToken); } catch (e) { sails.log.error(e); throw new Error(e); } } req.session.needJwt = false; } return jwtToken; }, isWebView(userAgent) { return userAgent.indexOf('React-Native') !== -1; }, /** * 用來檢查 user 的 roles 是否符合給予的 roles 陣列。 * @method * @param {Request} * @param {String[]} targetRoles - role 的名稱。 * @param {User} user - 要檢查的使用者(不帶入會從 Request 找)。 * return {String[]} 符合的 roles 陣列 */ // matchedRoles(req, targetRoles, user) { // if (!user) { // user = this.getSessionUser(req); // sails.log('matchedRoles user=>', user); // } // let matched = []; // targetRoles = targetRoles.map(role => role.toLowerCase()); // if (user && user.Roles) { // return matched = user.Roles.filter(role => targetRoles.indexOf(role.authority.toLowerCase()) !== -1); // } // return []; // }, /** * 用來檢查 user 的 roles 是否符合給予的 roles 陣列。 * @method * @param {Request} * @param {String[]} targetRoles - role 的名稱。 * @param {User} user - 要檢查的使用者(不帶入會從 Request 找)。 * return {Boolean} user role 是否符合 targetRoles 陣列 */ isMatchedRoles(targetRoles, user) { return user.Roles ? user.Roles.some( role => targetRoles.some( targetRole => role.authority.toLowerCase() === targetRole.toLowerCase(), ), ) : false; }, getHexToken(length) { return crypto.randomBytes(length).toString('hex').substr(0, length); }, getNumberToken(length) { const range = Math.pow(10, (length + 1)); const num = Math.floor(Math.random() * range); const numString = Array(length).join('0') + num.toString(); return numString.substr(numString.length - length, length); }, async afterLogout(req, res, user) { console.log('authService after login'); }, async isStaff(id) { try { const user = await User.findOne({ where: { id, }, include: [{ model: Role, include: [Group], }], }); if (!user) { return false; } const checkStaff = role => role.Groups.some(g => (g.authority === 'staff' || g.authority === 'adminuser' || g.authority === 'maintainer')); const isStaff = user.Roles.some(role => checkStaff(role)); sails.log.info('--------- isStaff ? --->', isStaff); return isStaff; } catch (e) { sails.log.error(e); throw e; } }, verifyUser(user, url) { /* offAuth 是個早期還沒有 mockAdmin 的時候用的測試開關,可以拔掉了 */ if (!user) { return { success: false, reason: { message: 'no user' } }; } // console.log('verifyUser user=>', user); const policies = ConfigHelper.getAuthConfig(); const excludeRole = _.uniq((policies.ignoreRole) ? policies.ignoreRole : ['super-admin']); sails.log.info('Roles below will be skipping check.', excludeRole); const isExclude = this.isMatchedRoles(excludeRole, user); // console.log('isExclude=>', isExclude); if (isExclude) { sails.log('ignore all check'); return { success: true, reason: { message: 'inExcludeArray' } }; } const conditions = _.uniqBy(policies.verifyUser, 'name'); for (const condition of conditions) { if (condition.enable !== true) { // sails.log(`${condition.name} not enable`); continue; } const isLoginRoleMatch = ( condition.enableRole[0] === '*' || this.isMatchedRoles(condition.enableRole, user) ); if (isLoginRoleMatch !== true) { sails.log(`${condition.name} not enable for this user`); continue; } // console.log('condition=>', condition); // console.log('url=>', url); if (condition.skipPath && condition.skipPath.indexOf(url) >= 0) { sails.log(`${condition.name} not enable for this url: ${url}`); continue; } sails.log(`[!] Checking Rule "${condition.name}"...`); for (const field of condition.verifyField) { if (!user[field]) { return { success: false, reason: { message: 'someCheckFailed', condition, field }, }; } } } const expireCondition = policies; if (expireCondition || expireCondition.enable !== true) { return { success: true, reason: { message: 'allPassExcludeExpire' } }; } // write expiration check here return { success: true, reason: { message: 'allPass' } }; }, }; /** @module AuthService */ module.exports = AuthService;