From efc7e2863d532c2e65d04cd2b1c737f833b14417 Mon Sep 17 00:00:00 2001 From: undefined Date: Tue, 6 Oct 2020 18:16:39 +0800 Subject: [PATCH] core: add perm scopes --- package.json | 2 +- packages/hydrooj/src/handler/user.ts | 10 ++++++++-- packages/hydrooj/src/interface.ts | 1 + packages/hydrooj/src/model/user.ts | 13 ++++++++----- packages/hydrooj/src/service/server.ts | 6 ++++-- 5 files changed, 22 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index 6c8cfc5f8..07ac4a925 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "jest": "node build/jest", "debug": "node --async-stack-traces --trace-deprecation --enable-source-maps build/start --debug", "start": "node build/start", - "clean": "zsh -c \"rm -rf tsconfig.build.tsbuildinfo ./packages/*/tsconfig.tsbuildinfo ./packages/*/dist ./.coverage\"" + "clean": "zsh -c \"rm -rf tsconfig.build.tsbuildinfo ./packages/*/tsconfig.tsbuildinfo ./packages/*/dist ./**/tscofig.json ./.coverage\"" }, "version": "1.0.0", "license": "AGPL-3.0-only", diff --git a/packages/hydrooj/src/handler/user.ts b/packages/hydrooj/src/handler/user.ts index 46198dba9..150fa1440 100644 --- a/packages/hydrooj/src/handler/user.ts +++ b/packages/hydrooj/src/handler/user.ts @@ -36,6 +36,7 @@ class UserLoginHandler extends Handler { await user.setById(udoc._id, { loginat: new Date(), loginip: this.request.ip }); if (udoc.priv === PRIV.PRIV_NONE) throw new BlacklistedError(uname); this.session.uid = udoc._id; + this.session.scope = PERM.PERM_ALL; this.session.save = rememberme; this.response.redirect = this.request.referer.endsWith('/login') ? '/' : this.request.referer; } @@ -48,6 +49,7 @@ class UserLogoutHandler extends Handler { async post() { this.session.uid = 0; + this.session.scope = PERM.PERM_ALL; } } @@ -101,6 +103,7 @@ class UserRegisterWithCodeHandler extends Handler { const uid = await user.create(mail, uname, password, undefined, this.request.ip); await token.del(code, token.TYPE_REGISTRATION); this.session.uid = uid; + this.session.scpoe = PERM.PERM_ALL; this.response.redirect = this.url('homepage'); } } @@ -229,8 +232,10 @@ class OauthCallbackHandler extends Handler { if (global.Hydro.lib[`oauth_${args.type}`]) r = await global.Hydro.lib[`oauth_${args.type}`].callback.call(this, args); else throw new UserFacingError('Oauth type'); const uid = await oauth.get(r._id); - if (uid) this.session.uid = uid; - else { + if (uid) { + this.session.uid = uid; + this.session.scope = PERM.PERM_ALL; + } else { this.checkPriv(PRIV.PRIV_REGISTER_USER); let username = ''; r.uname = r.uname || []; @@ -257,6 +262,7 @@ class OauthCallbackHandler extends Handler { oauth.set(r.email, _id), ]); this.session.uid = _id; + this.session.scope = PERM.PERM_ALL; } } } diff --git a/packages/hydrooj/src/interface.ts b/packages/hydrooj/src/interface.ts index 86bbb3ff5..b486e675c 100644 --- a/packages/hydrooj/src/interface.ts +++ b/packages/hydrooj/src/interface.ts @@ -74,6 +74,7 @@ export interface User extends Dictionary { regat: Date, loginat: Date, perm: () => bigint, + scope: () => bigint, role: string, regip: () => string, loginip: () => string, diff --git a/packages/hydrooj/src/model/user.ts b/packages/hydrooj/src/model/user.ts index eae7341fd..11663b795 100644 --- a/packages/hydrooj/src/model/user.ts +++ b/packages/hydrooj/src/model/user.ts @@ -3,7 +3,7 @@ import * as system from './system'; import * as token from './token'; import * as setting from './setting'; import * as domain from './domain'; -import { BUILTIN_USERS, PRIV } from './builtin'; +import { BUILTIN_USERS, PERM, PRIV } from './builtin'; import { UserNotFoundError, UserAlreadyExistError, LoginError } from '../error'; import { User as _User, Udoc, Udict } from '../interface'; import { Value } from '../typeutils'; @@ -73,9 +73,11 @@ export class User implements _User { loginip: () => string; + scope: () => bigint; + [key: string]: any; - constructor(udoc: Udoc, dudoc) { + constructor(udoc: Udoc, dudoc, scope = PERM.PERM_ALL) { this.udoc = () => udoc; this.dudoc = () => dudoc; this._id = udoc._id; @@ -90,6 +92,7 @@ export class User implements _User { this.loginat = udoc.loginat; this.loginip = () => udoc.loginip; this.perm = () => dudoc.perm; + this.scope = () => scope; this.role = dudoc.role || 'default'; for (const key in setting.SETTINGS_BY_KEY) { @@ -111,7 +114,7 @@ export class User implements _User { hasPerm(...perm: bigint[]) { for (const i in perm) { - if ((this.perm() & perm[i]) === perm[i]) return true; + if ((this.perm() * this.scope() & perm[i]) === perm[i]) return true; } return false; } @@ -134,13 +137,13 @@ export class User implements _User { } } -export async function getById(domainId: string, _id: number): Promise { +export async function getById(domainId: string, _id: number, scope = PERM.PERM_ALL): Promise { const udoc = _id === 0 || _id === 1 ? BUILTIN_USERS[_id] : await coll.findOne({ _id }); if (!udoc) return null; const dudoc = await domain.getDomainUser(domainId, udoc); - return new User(udoc, dudoc); + return new User(udoc, dudoc, scope); } export async function getList(domainId: string, uids: number[]): Promise { diff --git a/packages/hydrooj/src/service/server.ts b/packages/hydrooj/src/service/server.ts index 544721ec0..c865059a8 100644 --- a/packages/hydrooj/src/service/server.ts +++ b/packages/hydrooj/src/service/server.ts @@ -32,6 +32,7 @@ import * as system from '../model/system'; import * as blacklist from '../model/blacklist'; import * as token from '../model/token'; import * as opcount from '../model/opcount'; +import { PERM } from '../model/builtin'; const logger = new Logger('server'); export const app = new Koa(); @@ -479,9 +480,10 @@ export class Handler { if (!this.user) this.user = await user.getById('system', 0); throw new NotFoundError(domainId); } - this.user = await user.getById(domainId, this.session.uid); + this.user = await user.getById(domainId, this.session.uid, this.session.scope); if (!this.user) { this.session.uid = 0; + this.session.scope = PERM.PERM_ALL; this.user = await user.getById(domainId, this.session.uid); } this.csrfToken = this.getCsrfToken(this.session._id || String.random(32)); @@ -818,7 +820,7 @@ export class ConnectionHandler { ]); const bdoc = await blacklist.get(this.request.ip); if (bdoc) throw new BlacklistedError(this.request.ip); - this.user = await user.getById(domainId, this.session.uid); + this.user = await user.getById(domainId, this.session.uid, this.session.scope); if (!this.user) throw new UserNotFoundError(this.session.uid); } }