UNPKG

auth-center

Version:
436 lines (393 loc) 8.85 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.checkLogin = checkLogin; exports.searchUser = searchUser; exports.userList = userList; exports.clientList = clientList; exports.sendTotp = sendTotp; exports.addClient = addClient; exports.generateSecret = generateSecret; exports.roleList = roleList; exports.addRole = addRole; exports.deleteRole = deleteRole; var _querystring = _interopRequireDefault(require("querystring")); var _util = require("../util"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } async function checkLogin(ctx, next) { if (ctx.session.user) { if (ctx.session.user.is_admin) { ctx.state.user = ctx.session.user; await next(); } else { ctx.redirect(ctx._routes.home); } } else { ctx.session.returnTo = ctx.url; ctx.redirect(ctx._routes.login); } } async function searchUser(ctx) { const { User, Op } = ctx.orm(); const q = ctx.request.body.q || ''; const users = await User.findAll({ attributes: ['email'], where: { enable: 1, email: { [Op.like]: q + '%' } }, offset: 0, limit: 15 }); ctx.body = users.map(u => u.email); } async function userList(ctx) { const { User, Op } = ctx.orm(); const page = parseInt(ctx.query.p, 10) || 1; const query = ctx.query.q || ''; const limit = 20; const offset = (page - 1) * limit; const where = { enable: 1 }; if (query) { where.email = { [Op.like]: `%${query}%` }; } const users = await User.findAndCountAll({ where, limit, offset, order: [['email', 'ASC']], attributes: { exclude: ['pass_hash', 'pass_salt'] } }); await ctx.render('admin/users', { page, users, query, navUsers: 'active', total: Math.ceil(users.count / limit), link: p => `?${_querystring.default.stringify({ q: query, p })}` }); } async function clientList(ctx) { const { Client, Op } = ctx.orm(); const page = parseInt(ctx.query.p, 10) || 1; const query = ctx.query.q || ''; const limit = 20; const offset = (page - 1) * limit; const where = {}; if (query) { where.name = { [Op.like]: `%${query}%` }; } const clients = await Client.findAndCountAll({ where, limit, offset, order: [['name', 'ASC']], attributes: ['id', 'secret', 'redirect_uri', 'name', 'name_cn'] }); await ctx.render('admin/clients', { page, query, clients, navClients: 'active', total: Math.ceil(clients.count / limit), link: p => `?${_querystring.default.stringify({ q: query, p })}` }); } async function sendTotp(ctx) { const { User } = ctx.orm(); const { id } = ctx.request.body; if (!id) { ctx.flash('error', 'ID is required'); ctx.redirect(ctx._routes.admin.users); return; } try { // generate new totp key const res = await User.update({ totp_key: (0, _util.generateId)() }, { where: { id } }); // send email if (res[0]) { const user = await User.findByPk(id); await ctx.sendMail(user.email, 'send_totp', { username: user.email, cid: 'key', email: user.email, key: (0, _util.encodeKey)(user.totp_key) }, [{ filename: 'key.png', content: (0, _util.totpImage)(user.email, user.totp_key), cid: 'key' }]); } else { ctx.flash('error', 'Update failed'); ctx.redirect(ctx._routes.admin.users); return; } ctx.flash('success', 'Reset and send TOTP key successfully'); ctx.redirect(ctx._routes.admin.users); } catch (e) { console.error(e.stack); ctx.flash('error', 'Reset and send key failed'); ctx.redirect(ctx._routes.admin.users); } } async function addClient(ctx) { const { Client } = ctx.orm(); const { name, name_cn, redirect_uri } = ctx.request.body; if (!name) { ctx.flash('error', 'Name is required'); ctx.redirect(ctx._routes.admin.clients); return; } if (!name_cn) { ctx.flash('error', 'Name CN is required'); ctx.redirect(ctx._routes.admin.clients); return; } if (!redirect_uri) { ctx.flash('error', 'Redirect URI is required'); ctx.redirect(ctx._routes.admin.clients); return; } try { // add one new await Client.create({ secret: (0, _util.generateId)(), name: name, name_cn: name_cn, redirect_uri: redirect_uri }); ctx.flash('success', 'Add new client successfully'); ctx.redirect(ctx._routes.admin.clients); } catch (e) { console.error(e.stack); ctx.flash('error', 'Add new client failed'); ctx.redirect(ctx._routes.admin.clients); } } async function generateSecret(ctx) { const { Client } = ctx.orm(); const { id } = ctx.request.body; if (!id) { ctx.flash('error', 'ID is required'); ctx.redirect(ctx._routes.admin.clients); return; } try { // generate new secret const res = await Client.update({ secret: (0, _util.generateId)() }, { where: { id } }); if (res[0]) { ctx.flash('success', 'Generate new secret successfully'); ctx.redirect(ctx._routes.admin.clients); } else { ctx.flash('error', 'Update failed'); ctx.redirect(ctx._routes.admin.clients); return; } } catch (e) { console.error(e.stack); ctx.flash('error', 'Generate new secret failed'); ctx.redirect(ctx._routes.admin.clients); } } async function roleList(ctx) { const { User, Role, Client, DicRole, Op } = ctx.orm(); const page = parseInt(ctx.query.p, 10) || 1; const query = ctx.query.q || ''; const client = ctx.query.client; const where = {}; if (query) { const temp = await User.findAll({ offset: 0, limit: 100, attributes: ['id'], where: { email: { [Op.like]: `%${query}%` } } }); where.user_id = { [Op.in]: temp.map(v => v.id) }; } if (client) { where.client_id = client; } const limit = 20; const offset = (page - 1) * limit; const roles = await Role.findAndCountAll({ where, limit, offset, order: [['user_id', 'ASC']], attributes: ['id', 'user_id', 'client_id', 'role'] }); const users = await User.findAll({ attributes: ['id', 'email'], where: { id: { [Op.in]: roles.rows.map(v => v.user_id) } } }); const userMap = users.reduce((o, c) => { o[c.id] = c.email; return o; }, {}); const clients = await Client.findAll(); const dics = await DicRole.findAll(); const clientMap = clients.reduce((o, c) => { o[c.id] = c.name; return o; }, {}); await ctx.render('admin/roles', { dics, page, query, client, roles, clients, userMap, clientMap, navRoles: 'active', total: Math.ceil(roles.count / limit), link: p => `?${_querystring.default.stringify({ q: query, p })}` }); } async function addRole(ctx) { const { Role, User } = ctx.orm(); const { email, client, role } = ctx.request.body; if (!email) { ctx.flash('error', 'Email is required'); ctx.redirect(ctx._routes.admin.roles); return; } if (!client) { ctx.flash('error', 'Client is required'); ctx.redirect(ctx._routes.admin.roles); return; } if (!role) { ctx.flash('error', 'Role is required'); ctx.redirect(ctx._routes.admin.roles); return; } const user = await User.findOne({ attributes: ['id'], where: { email, enable: 1 } }); if (!user) { ctx.flash('error', 'User is not existed'); ctx.redirect(ctx._routes.admin.roles); return; } try { // add one new await Role.create({ user_id: user.id, client_id: client, role: role }); ctx.flash('success', 'Add new role successfully'); ctx.redirect(ctx._routes.admin.roles); } catch (e) { console.error(e.stack); ctx.flash('error', 'Add new role failed, maybe it is existed'); ctx.redirect(ctx._routes.admin.roles); } } async function deleteRole(ctx) { const { Role } = ctx.orm(); const { id } = ctx.request.body; if (!id) { ctx.flash('error', 'Id is required'); ctx.redirect(ctx._routes.admin.roles); return; } // Delete role const num = await Role.destroy({ where: { id } }); if (num <= 0) { ctx.flash('error', 'Delete role failed, maybe it is not existed'); ctx.redirect(ctx._routes.admin.roles); return; } ctx.flash('success', 'Delete role successfully'); ctx.redirect(ctx._routes.admin.roles); }