122 lines
3.1 KiB
JavaScript
122 lines
3.1 KiB
JavaScript
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';
|
|
|
|
/** @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.' };
|
|
} else if (!account.canLogin()) {
|
|
ctx.status = 400; // Bad Request.
|
|
ctx.body = { error: 'Your account is banned or restricted.' };
|
|
} 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('name', 'string'),
|
|
syllableRequired('passwd', 'string'),
|
|
/**
|
|
* @param {Context} ctx
|
|
* @param {Next} next
|
|
*/
|
|
async function(ctx, next) {
|
|
/** @type {{handle: string, name: string, passwd: string}} */
|
|
const {handle, name, passwd} = ctx.request.body;
|
|
let account = Account.create({
|
|
handle, name,
|
|
type: ACCOUNT_TYPE.normal,
|
|
plaintext_password: passwd,
|
|
});
|
|
|
|
if (!await account.canCreate()) {
|
|
ctx.status = 400;
|
|
ctx.body = { error: 'Handle is taken or cannot be used.' };
|
|
return;
|
|
}
|
|
|
|
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.load(ctx.params.uid);
|
|
if (account == null) {
|
|
ctx.status = 404; // 404 Not Found
|
|
ctx.body = { error: 'requested user is not found' };
|
|
} else {
|
|
ctx.status = 200;
|
|
ctx.body = account.asInfo();
|
|
}
|
|
}
|
|
];
|