diff --git a/packages/hydrooj/package.json b/packages/hydrooj/package.json index 6bfd813e5..1b350afc2 100644 --- a/packages/hydrooj/package.json +++ b/packages/hydrooj/package.json @@ -1,6 +1,6 @@ { "name": "hydrooj", - "version": "3.15.16", + "version": "3.15.17", "bin": "bin/hydrooj.js", "main": "src/loader", "module": "src/loader", diff --git a/packages/hydrooj/src/model/builtin.ts b/packages/hydrooj/src/model/builtin.ts index 1612dc915..a404bce8a 100644 --- a/packages/hydrooj/src/model/builtin.ts +++ b/packages/hydrooj/src/model/builtin.ts @@ -12,6 +12,7 @@ export const PERM = { // Domain Settings PERM_VIEW: 1n << 0n, PERM_EDIT_DOMAIN: 1n << 1n, + PREM_VIEW_DISPLAYNAME: 1n << 67n, PERM_MOD_BADGE: 1n << 2n, // Problem @@ -101,6 +102,7 @@ export const Permission = (family: string, key: BigInt, desc: string) => ({ fami export const PERMS = [ Permission('perm_general', PERM.PERM_VIEW, 'View this domain'), + Permission('perm_general', PERM.PREM_VIEW_DISPLAYNAME, 'View domain user displayname'), Permission('perm_general', PERM.PERM_EDIT_DOMAIN, 'Edit domain settings'), Permission('perm_general', PERM.PERM_MOD_BADGE, 'Show MOD badge'), Permission('perm_problem', PERM.PERM_CREATE_PROBLEM, 'Create problems'), @@ -182,6 +184,7 @@ PERM.PERM_BASIC = PERM.PERM_VIEW | PERM.PERM_VIEW_RANKING; PERM.PERM_DEFAULT = PERM.PERM_VIEW + | PERM.PREM_VIEW_DISPLAYNAME | PERM.PERM_VIEW_PROBLEM | PERM.PERM_EDIT_PROBLEM_SELF | PERM.PERM_SUBMIT_PROBLEM diff --git a/packages/hydrooj/src/service/layers/renderer.ts b/packages/hydrooj/src/service/layers/renderer.ts index e0f9d0388..95ee09609 100644 --- a/packages/hydrooj/src/service/layers/renderer.ts +++ b/packages/hydrooj/src/service/layers/renderer.ts @@ -1,23 +1,27 @@ import { ObjectID } from 'mongodb'; import avatar from 'hydrooj/src/lib/avatar'; +import { PERM } from 'hydrooj/src/model/builtin'; import * as system from 'hydrooj/src/model/system'; +import { User } from 'hydrooj/src/model/user'; import type { KoaContext } from '../server'; -function serializer(k: string, v: any) { +const serializer = (showDisplayName = false) => (k: string, v: any) => { if (k.startsWith('_') && k !== '_id') return undefined; if (typeof v === 'bigint') return `BigInt::${v.toString()}`; + if (v instanceof User && !showDisplayName) delete v.displayName; return v; -} +}; export default (router, logger) => async (ctx: KoaContext, next) => { - const { request, response } = ctx.HydroContext; + const { request, response, user } = ctx.HydroContext; ctx.renderHTML = (templateName, args) => { const UserContext: any = { - ...(ctx.HydroContext.user || {}), - avatar: avatar(ctx.HydroContext.user?.avatar || '', 128), + ...(user || {}), + avatar: avatar(user?.avatar || '', 128), viewLang: ctx.translate('__id'), }; - const engine = global.Hydro.lib.template?.render || (() => JSON.stringify(args, serializer)); + const engine = global.Hydro.lib.template?.render + || (() => JSON.stringify(args, serializer(user?.hasPerm(PERM.PREM_VIEW_DISPLAYNAME)))); return engine(templateName, { handler: ctx.handler, UserContext, diff --git a/packages/hydrooj/src/service/layers/response.ts b/packages/hydrooj/src/service/layers/response.ts index 31d986d33..c7b72ead4 100644 --- a/packages/hydrooj/src/service/layers/response.ts +++ b/packages/hydrooj/src/service/layers/response.ts @@ -1,12 +1,15 @@ import { errorMessage } from '@hydrooj/utils/lib/utils'; import { SystemError, UserFacingError } from 'hydrooj/src/error'; +import { PERM } from 'hydrooj/src/model/builtin'; +import { User } from 'hydrooj/src/model/user'; import type { KoaContext } from '../server'; -function serializer(k: string, v: any) { +const serializer = (showDisplayName = false) => (k: string, v: any) => { if (k.startsWith('_') && k !== '_id') return undefined; if (typeof v === 'bigint') return `BigInt::${v.toString()}`; + if (v instanceof User && !showDisplayName) delete v.displayName; return v; -} +}; export default (logger) => async (ctx: KoaContext, next) => { const { @@ -28,7 +31,7 @@ export default (logger) => async (ctx: KoaContext, next) => { response.body.UiContext = UiContext; response.body.UserContext = user; } - response.body = JSON.stringify(response.body, serializer); + response.body = JSON.stringify(response.body, serializer(user?.hasPerm(PERM.PREM_VIEW_DISPLAYNAME))); } catch (e) { response.body = new SystemError('Serialize failure', e.message); } diff --git a/packages/hydrooj/src/service/server.ts b/packages/hydrooj/src/service/server.ts index 820ec72ca..369c2b49c 100644 --- a/packages/hydrooj/src/service/server.ts +++ b/packages/hydrooj/src/service/server.ts @@ -14,11 +14,12 @@ import { NotFoundError, PermissionError, PrivilegeError, UserFacingError, } from '../error'; -import { DomainDoc, User } from '../interface'; +import { DomainDoc } from '../interface'; import { Logger } from '../logger'; import { PERM, PRIV } from '../model/builtin'; import * as opcount from '../model/opcount'; import * as system from '../model/system'; +import { User } from '../model/user'; import { errorMessage } from '../utils'; import * as bus from './bus'; import * as decorators from './decorators'; @@ -99,11 +100,12 @@ wsServer.on('error', (error) => { }); const ignoredLimit = `,${argv.options.ignoredLimit},`; -function serializer(k: string, v: any) { +const serializer = (showDisplayName = false) => (k: string, v: any) => { if (k.startsWith('_') && k !== '_id') return undefined; if (typeof v === 'bigint') return `BigInt::${v.toString()}`; + if (v instanceof User && !showDisplayName) delete v.displayName; return v; -} +}; export async function prepare() { app.keys = system.get('session.keys') as unknown as string[]; @@ -366,7 +368,7 @@ export class ConnectionHandler extends HandlerCommon { conn: WebSocket; send(data: any) { - this.conn.send(JSON.stringify(data, serializer)); + this.conn.send(JSON.stringify(data, serializer(this.user?.hasPerm(PERM.PREM_VIEW_DISPLAYNAME)))); } close(code: number, reason: string) { diff --git a/packages/hydrooj/src/upgrade.ts b/packages/hydrooj/src/upgrade.ts index 1f563cf29..45b16ed94 100644 --- a/packages/hydrooj/src/upgrade.ts +++ b/packages/hydrooj/src/upgrade.ts @@ -12,7 +12,7 @@ import { convertIniConfig } from '@hydrooj/utils/lib/cases'; import { size } from '@hydrooj/utils/lib/utils'; import { buildContent } from './lib/content'; import { Logger } from './logger'; -import { PRIV, STATUS } from './model/builtin'; +import { PERM, PRIV, STATUS } from './model/builtin'; import * as contest from './model/contest'; import * as discussion from './model/discussion'; import * as document from './model/document'; @@ -792,6 +792,16 @@ const scripts: UpgradeScript[] = [ await system.set('server.center', 'https://hydro.ac/center'); return true; }, + async function _65_66() { + await iterateAllDomain(async (ddoc) => { + Object.keys(ddoc.roles).forEach((role) => { + if (['guest', 'root'].includes(role)) return; + ddoc.roles[role] = (BigInt(ddoc.roles[role]) | PERM.PREM_VIEW_DISPLAYNAME).toString(); + }); + await domain.setRoles(ddoc._id, ddoc.roles); + }); + return true; + }, ]; export default scripts; diff --git a/packages/ui-default/package.json b/packages/ui-default/package.json index 2a91551ae..8d7ce8585 100644 --- a/packages/ui-default/package.json +++ b/packages/ui-default/package.json @@ -1,6 +1,6 @@ { "name": "@hydrooj/ui-default", - "version": "4.39.6", + "version": "4.39.7", "author": "undefined ", "license": "AGPL-3.0", "main": "hydro.js", diff --git a/packages/ui-default/templates/components/user.html b/packages/ui-default/templates/components/user.html index f702e466a..9e70f1cb7 100644 --- a/packages/ui-default/templates/components/user.html +++ b/packages/ui-default/templates/components/user.html @@ -5,7 +5,7 @@ {% endif %} - {% if udoc.displayName and udoc.displayName != udoc.uname %} + {% if handler.user.hasPerm(perm.PREM_VIEW_DISPLAYNAME) and udoc.displayName and udoc.displayName != udoc.uname %} {{ udoc.displayName }} ({{ udoc.uname }}) {% else %} {{ udoc.uname }} diff --git a/packages/ui-default/templates/record_main_tr.html b/packages/ui-default/templates/record_main_tr.html index 5e0f758ca..f699de6f1 100644 --- a/packages/ui-default/templates/record_main_tr.html +++ b/packages/ui-default/templates/record_main_tr.html @@ -24,7 +24,7 @@ - {% if udoc.displayName %} + {% if handler.user.hasPerm(perm.PREM_VIEW_DISPLAYNAME) and udoc.displayName %} {{ udoc.displayName }} ({{ udoc.uname }}) {% else %} {{ udoc.uname }}