import jwt from 'jsonwebtoken'; import { syllableRequired, parameterRequired, loginRequired } from '../../middlewares/index.mjs'; import { loadAccount } from './middlewares.mjs'; import { ACCOUNT_TYPE, Account } from './model.mjs'; import { isValidUUID } from '@og/uuid'; import * as config from '../../config.mjs'; import { ValidationErrorItem } from 'sequelize'; /** @typedef {import('koa').Context} Context */ /** @typedef {import('koa').Next} Next */ export const login_view = [ syllableRequired('handle', 'string'), syllableRequired('passwd', 'string'), /** * @param {Context} ctx * @param {Next} next */ async function(ctx, next) { /** @type {{handle: string, passwd: string}} */ const {handle, passwd} = ctx.request.body; const account = await Account.loadByHandle(handle); if (account == null || !account.checkPassword(passwd)) { ctx.status = 400; // Bad Request. ctx.body = { error: 'Authentication failed: handle or password is incorrect.', errno: 'EPASSWD' }; } else if (!account.canLogin()) { ctx.status = 400; // Bad Request. ctx.body = { error: 'Your account is banned or restricted.', errno: 'EBANNED' }; } else { const token = jwt.sign({ uid: account.uid.toString(), handle: account.handle, auth_step: 'done', }, config.secret, { expiresIn: config.jwt_expire }); ctx.status = 200; ctx.body = { uid: account.uid.toString(), token, auth_step: 'done' }; } } ]; export const whoami_view = [ loginRequired, loadAccount, /** * @param {Context} ctx * @param {Next} next */ async function(ctx, next) { const account = ctx.state.account; ctx.status = 200; ctx.body = { handle: account.handle, name: account.name }; } ]; export const refresh_token_view = [ loginRequired, /** * @param {Context} ctx * @param {Next} next */ async function(ctx, next) { /** @type {Account?} */ const old_token = ctx.state.user; const new_token = jwt.sign({ uid: old_token.uid, handle: old_token.handle, auth_step: 'done', }, config.secret, { expiresIn: config.jwt_expire }); ctx.status = 200; ctx.body = { uid: old_token.uid, token: new_token, auth_step: 'done'}; } ]; export const signup_view = [ syllableRequired('handle', 'string'), syllableRequired('passwd', 'string'), /** * @param {Context} ctx * @param {Next} next */ async function(ctx, next) { /** @type {{handle: string, passwd: string}} */ const {handle, passwd} = ctx.request.body; if (Account.loadByHandle(handle) != null) { ctx.status = 400; ctx.body = { error: 'handle is taken', errno: 'EUNIQUE' }; } let account = Account.createInstance({ handle, type: ACCOUNT_TYPE.normal, plaintext_password: passwd, }); await account.save(); ctx.status = 204; } ]; export const account_info_view = [ parameterRequired('uid', isValidUUID), /** * @param {Context} ctx * @param {Next} next */ async function(ctx, next) { /** @type {Account?} */ let account = await Account.findByPk(ctx.params.uid); if (account == null) { ctx.status = 404; // 404 Not Found ctx.body = { error: 'requested user is not found', errno: 'E404' }; } else { ctx.status = 200; ctx.body = account.asInfo(); } } ];