You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
189 lines
7.7 KiB
JavaScript
189 lines
7.7 KiB
JavaScript
const
|
|
{ GET, POST } = require('../service/server.js'),
|
|
user = require('../model/user'),
|
|
token = require('../model/token'),
|
|
system = require('../model/system'),
|
|
mail = require('../lib/mail'),
|
|
validator = require('../lib/validator'),
|
|
options = require('../options'),
|
|
{ PERM_REGISTER_USER, PERM_LOGGEDIN } = require('../permission'),
|
|
{ requirePerm, limitRate } = require('./tools'),
|
|
{ UserAlreadyExistError, InvalidTokenError, VerifyPasswordError, UserNotFoundError, LoginError } = require('../error');
|
|
|
|
GET('/user', async ctx => {
|
|
let udoc = await user.getById(ctx.session.uid);
|
|
ctx.templateName = 'user_detail.html';
|
|
ctx.body = { udoc };
|
|
});
|
|
GET('/login', async ctx => {
|
|
ctx.templateName = 'user_login.html';
|
|
});
|
|
POST('/login', async ctx => {
|
|
let { uname, password, rememberme = false } = ctx.request.body;
|
|
let udoc = await user.getByUname(uname);
|
|
if (!udoc) throw new LoginError(uname);
|
|
if (udoc) udoc.checkPassword(password);
|
|
await user.setById(udoc._id, { loginat: new Date(), loginip: ctx.request.ip });
|
|
udoc.salt = '';
|
|
udoc.password = '';
|
|
console.log(udoc);
|
|
ctx.session.uid = udoc._id;
|
|
ctx.session.rememberme = rememberme;
|
|
ctx.body = {};
|
|
let referer = ctx.request.headers.referer || '/';
|
|
ctx.setRedirect = referer.endsWith('/login') ? '/' : referer;
|
|
});
|
|
POST('/logout', requirePerm(PERM_LOGGEDIN), async ctx => {
|
|
ctx.session = { uid: 1 };
|
|
ctx.body = {};
|
|
});
|
|
GET('/register/:code', requirePerm(PERM_REGISTER_USER), async ctx => {
|
|
let code = ctx.request.body.code;
|
|
let { mail } = await token.get(code, token.TYPE_REGISTRATION);
|
|
if (!mail) throw new InvalidTokenError(token.TYPE_REGISTRATION, code);
|
|
ctx.body = { mail };
|
|
});
|
|
GET('/register/:code', requirePerm(PERM_REGISTER_USER), async ctx => {
|
|
let { code, password, verify_password, uname } = ctx.request.body;
|
|
let { mail } = await token.get(code, token.TYPE_REGISTRATION);
|
|
if (!mail) throw new InvalidTokenError(token.TYPE_REGISTRATION, code);
|
|
if (password != verify_password) throw new VerifyPasswordError();
|
|
let uid = await system.incUserCounter();
|
|
await user.add(uid, uname, password, mail, ctx.remote_ip);
|
|
await token.delete(code, token.TYPE_REGISTRATION);
|
|
ctx.session.uid = uid;
|
|
ctx.body = {};
|
|
});
|
|
|
|
if (options.smtp.user) {
|
|
POST('/register', requirePerm(PERM_REGISTER_USER), limitRate('send_mail', 3600, 30), async ctx => {
|
|
let email = ctx.request.body.email;
|
|
validator.check_mail(email);
|
|
if (await user.get_by_mail(email)) throw new UserAlreadyExistError(email);
|
|
let rid = await token.add(token.TYPE_REGISTRATION, options.registration_token_expire_seconds, { mail: email });
|
|
let m = await ctx.render('user_register_mail', { url: `/register/${rid}` }, true);
|
|
await mail.send_mail(email, 'Sign Up', 'user_register_mail', m);
|
|
ctx.body = {};
|
|
});
|
|
POST('/lostpass', limitRate('send_mail', 3600, 30), async ctx => {
|
|
let email = ctx.request.body.mail;
|
|
validator.check_mail(email);
|
|
let udoc = await user.getByEmail(email);
|
|
if (!udoc) throw new UserNotFoundError(email);
|
|
let tid = await token.add(
|
|
token.TYPE_LOSTPASS,
|
|
options.lostpass_token_expire_seconds,
|
|
{ uid: udoc._id }
|
|
);
|
|
let m = await ctx.render('user_lostpass_mail', { url: `/lostpass/${tid}`, uname: udoc.uname }, true);
|
|
await mail.send_mail(email, 'Lost Password', 'user_lostpass_mail', m);
|
|
ctx.body = {};
|
|
});
|
|
GET('/lostpass/:code', async ctx => {
|
|
let code = ctx.params.code;
|
|
let tdoc = await token.get(code, token.TYPE_LOSTPASS);
|
|
if (!tdoc) throw new InvalidTokenError(token.TYPE_LOSTPASS, code);
|
|
let udoc = await user.getById(tdoc.uid);
|
|
ctx.body = { uname: udoc.uname };
|
|
});
|
|
POST('/lostpass/:code', async ctx => {
|
|
let code = ctx.params.code;
|
|
let password = ctx.request.body.password;
|
|
let verify_password = ctx.request.body.verify_password;
|
|
let tdoc = await token.get(code, token.TYPE_LOSTPASS);
|
|
if (!tdoc) throw new InvalidTokenError(token.TYPE_LOSTPASS, code);
|
|
if (password != verify_password) throw new VerifyPasswordError();
|
|
await user.set_password(tdoc.uid, password);
|
|
await token.delete(code, token.TYPE_LOSTPASS);
|
|
ctx.redirect('/');
|
|
});
|
|
} else
|
|
POST('/register', requirePerm(PERM_REGISTER_USER), async ctx => {
|
|
let email = ctx.request.body.email;
|
|
validator.check_mail(email);
|
|
if (await user.get_by_mail(email)) throw new UserAlreadyExistError(email);
|
|
let token = await token.add(token.TYPE_REGISTRATION, options.registration_token_expire_seconds, { mail: email });
|
|
ctx.body = { token };
|
|
});
|
|
|
|
/*
|
|
|
|
@app.route('/user/{uid:-?\d+}', 'user_detail')
|
|
class UserDetailHandler(base.Handler, UserSettingsMixin):
|
|
@base.route_argument
|
|
@base.sanitize
|
|
async def get(self, *, uid: int):
|
|
is_self_profile = self.has_priv(builtin.PRIV_USER_PROFILE) and self.user['_id'] == uid
|
|
udoc = await user.get_by_uid(uid)
|
|
if not udoc:
|
|
raise error.UserNotFoundError(uid)
|
|
dudoc, sdoc = await asyncio.gather(domain.get_user(self.domainId, udoc['_id']),
|
|
token.get_most_recent_session_by_uid(udoc['_id']))
|
|
|
|
rdocs = record.get_multi(get_hidden=self.has_priv(builtin.PRIV_VIEW_HIDDEN_RECORD),
|
|
uid=uid).sort([('_id', -1)])
|
|
rdocs = await rdocs.limit(10).to_list()
|
|
pdict = await problem.get_dict_multi_domain((rdoc['domainId'], rdoc['pid']) for rdoc in rdocs)
|
|
# check hidden problem
|
|
if not self.has_perm(builtin.PERM_VIEW_PROBLEM_HIDDEN):
|
|
f = {'hidden': False}
|
|
else:
|
|
f = {}
|
|
pdocs = problem.get_multi(domainId=self.domainId, owner_uid=uid, **f).sort([('_id', -1)])
|
|
pcount = await pdocs.count()
|
|
pdocs = await pdocs.limit(10).to_list()
|
|
|
|
psdocs = problem.get_multi_solution_by_uid(self.domainId, uid)
|
|
psdocs_hot = problem.get_multi_solution_by_uid(self.domainId, uid)
|
|
pscount = await psdocs.count()
|
|
psdocs = await psdocs.limit(10).to_list()
|
|
psdocs_hot = await psdocs_hot.sort([('vote', -1), ('doc_id', -1)]).limit(10).to_list()
|
|
|
|
if self.has_perm(builtin.PERM_VIEW_DISCUSSION):
|
|
ddocs = discussion.get_multi(self.domainId, owner_uid=uid)
|
|
dcount = await ddocs.count()
|
|
ddocs = await ddocs.limit(10).to_list()
|
|
vndict = await discussion.get_dict_vnodes(self.domainId, map(discussion.node_id, ddocs))
|
|
else:
|
|
ddocs = []
|
|
vndict = {}
|
|
dcount = 0
|
|
|
|
self.render('user_detail.html', is_self_profile=is_self_profile,
|
|
udoc=udoc, dudoc=dudoc, sdoc=sdoc,
|
|
rdocs=rdocs, pdict=pdict, pdocs=pdocs, pcount=pcount,
|
|
psdocs=psdocs, pscount=pscount, psdocs_hot=psdocs_hot,
|
|
ddocs=ddocs, dcount=dcount, vndict=vndict)
|
|
|
|
|
|
@app.route('/user/search', 'user_search')
|
|
class UserSearchHandler(base.Handler):
|
|
def modify_udoc(self, udict, key):
|
|
udoc = udict[key]
|
|
gravatar_url = misc.gravatar_url(udoc.get('gravatar'))
|
|
if 'gravatar' in udoc and udoc['gravatar']:
|
|
udict[key] = {**udoc,
|
|
'gravatar_url': gravatar_url,
|
|
'gravatar': ''}
|
|
|
|
@base.requirePriv(builtin.PRIV_USER_PROFILE)
|
|
@base.get_argument
|
|
@base.route_argument
|
|
@base.sanitize
|
|
async def get(self, *, q: str, exact_match: bool=False):
|
|
if exact_match:
|
|
udocs = []
|
|
else:
|
|
udocs = await user.get_prefix_list(q, user.PROJECTION_PUBLIC, 20)
|
|
try:
|
|
udoc = await user.get_by_uid(int(q), user.PROJECTION_PUBLIC)
|
|
if udoc:
|
|
udocs.insert(0, udoc)
|
|
except ValueError as e:
|
|
pass
|
|
for i in range(len(udocs)):
|
|
self.modify_udoc(udocs, i)
|
|
self.json(udocs)
|
|
|
|
*/
|