mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-20 01:38:19 +08:00
core: user: private and public projection (#507)
This commit is contained in:
1 parent
4fe734a6f3
commit
bd13c57d82
6 files changed
+44
-26
No files matched your search
@@ -0,0 +1,16 @@
|
|||||||
|
interface SerializeOptions {
|
||||||
|
showDisplayName: boolean;
|
||||||
|
currentSerializer?: (k: string, v: any) => any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function serializer(options: SerializeOptions, ignoreSerializeFunction = false) {
|
||||||
|
options.currentSerializer = (k: string, v: any) => {
|
||||||
|
if (typeof k.startsWith !== 'function') console.log(k, v);
|
||||||
|
if (k.startsWith('_') && k !== '_id') return undefined;
|
||||||
|
if (typeof v === 'bigint') return `BigInt::${v.toString()}`;
|
||||||
|
if (!ignoreSerializeFunction && v && typeof v === 'object'
|
||||||
|
&& 'serialize' in v && typeof v.serialize === 'function') return v.serialize(options);
|
||||||
|
return v;
|
||||||
|
};
|
||||||
|
return options.currentSerializer;
|
||||||
|
}
|
||||||
@@ -7,6 +7,7 @@ import {
|
|||||||
ownerInfo, Udict, Udoc, VUdoc,
|
ownerInfo, Udict, Udoc, VUdoc,
|
||||||
} from '../interface';
|
} from '../interface';
|
||||||
import pwhash from '../lib/hash.hydro';
|
import pwhash from '../lib/hash.hydro';
|
||||||
|
import serializer from '../lib/serializer';
|
||||||
import * as bus from '../service/bus';
|
import * as bus from '../service/bus';
|
||||||
import db from '../service/db';
|
import db from '../service/db';
|
||||||
import { Value } from '../typeutils';
|
import { Value } from '../typeutils';
|
||||||
@@ -47,6 +48,7 @@ bus.on('user/delcache', (content) => deleteUserCache(typeof content === 'string'
|
|||||||
|
|
||||||
export class User {
|
export class User {
|
||||||
_id: number;
|
_id: number;
|
||||||
|
_isPrivate = false;
|
||||||
|
|
||||||
_udoc: Udoc;
|
_udoc: Udoc;
|
||||||
_dudoc: any;
|
_dudoc: any;
|
||||||
@@ -149,6 +151,21 @@ export class User {
|
|||||||
UserModel.setPassword(this._id, password);
|
UserModel.setPassword(this._id, password);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async private() {
|
||||||
|
const user = await new User(this._udoc, this._dudoc, this.scope).init();
|
||||||
|
user._isPrivate = true;
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
serialize(options) {
|
||||||
|
if (!this._isPrivate) {
|
||||||
|
const fields = ['_id', 'uname', 'mail', 'perm', 'role', 'priv', 'regat', 'loginat', 'tfa', 'authn'];
|
||||||
|
if (options.showDisplayName) fields.push('displayName');
|
||||||
|
return pick(this, fields);
|
||||||
|
}
|
||||||
|
return JSON.stringify(this, serializer({ showDisplayName: options.showDisplayName }, true));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleMailLower(mail: string) {
|
function handleMailLower(mail: string) {
|
||||||
|
|||||||
@@ -1,17 +1,10 @@
|
|||||||
import { ObjectID } from 'mongodb';
|
import { ObjectID } from 'mongodb';
|
||||||
import avatar from '../../lib/avatar';
|
import avatar from '../../lib/avatar';
|
||||||
|
import serializer from '../../lib/serializer';
|
||||||
import { PERM } from '../../model/builtin';
|
import { PERM } from '../../model/builtin';
|
||||||
import * as system from '../../model/system';
|
import * as system from '../../model/system';
|
||||||
import { User } from '../../model/user';
|
|
||||||
import type { KoaContext } from '../server';
|
import type { KoaContext } from '../server';
|
||||||
|
|
||||||
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) => {
|
export default (router, logger) => async (ctx: KoaContext, next) => {
|
||||||
const { request, response } = ctx.HydroContext;
|
const { request, response } = ctx.HydroContext;
|
||||||
ctx.renderHTML = (templateName, args) => {
|
ctx.renderHTML = (templateName, args) => {
|
||||||
@@ -22,7 +15,9 @@ export default (router, logger) => async (ctx: KoaContext, next) => {
|
|||||||
viewLang: ctx.translate('__id'),
|
viewLang: ctx.translate('__id'),
|
||||||
};
|
};
|
||||||
const engine = global.Hydro.lib.template?.render
|
const engine = global.Hydro.lib.template?.render
|
||||||
|| (() => JSON.stringify(args, serializer(user?.hasPerm(PERM.PREM_VIEW_DISPLAYNAME))));
|
|| (() => JSON.stringify(args, serializer({
|
||||||
|
showDisplayName: user?.hasPerm(PERM.PREM_VIEW_DISPLAYNAME),
|
||||||
|
})));
|
||||||
return engine(templateName, {
|
return engine(templateName, {
|
||||||
handler: ctx.handler,
|
handler: ctx.handler,
|
||||||
UserContext,
|
UserContext,
|
||||||
|
|||||||
@@ -1,16 +1,9 @@
|
|||||||
import { errorMessage } from '@hydrooj/utils/lib/utils';
|
import { errorMessage } from '@hydrooj/utils/lib/utils';
|
||||||
import { SystemError, UserFacingError } from '../../error';
|
import { SystemError, UserFacingError } from '../../error';
|
||||||
|
import serializer from '../../lib/serializer';
|
||||||
import { PERM } from '../../model/builtin';
|
import { PERM } from '../../model/builtin';
|
||||||
import { User } from '../../model/user';
|
|
||||||
import type { KoaContext } from '../server';
|
import type { KoaContext } from '../server';
|
||||||
|
|
||||||
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) => {
|
export default (logger) => async (ctx: KoaContext, next) => {
|
||||||
const { request, response } = ctx.HydroContext;
|
const { request, response } = ctx.HydroContext;
|
||||||
try {
|
try {
|
||||||
@@ -34,7 +27,7 @@ export default (logger) => async (ctx: KoaContext, next) => {
|
|||||||
response.body.UiContext = UiContext;
|
response.body.UiContext = UiContext;
|
||||||
response.body.UserContext = user;
|
response.body.UserContext = user;
|
||||||
}
|
}
|
||||||
response.body = JSON.stringify(response.body, serializer(user?.hasPerm(PERM.PREM_VIEW_DISPLAYNAME)));
|
response.body = JSON.stringify(response.body, serializer({ showDisplayName: user?.hasPerm(PERM.PREM_VIEW_DISPLAYNAME) }));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
response.body = new SystemError('Serialize failure', e.message);
|
response.body = new SystemError('Serialize failure', e.message);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ export default async (ctx: KoaContext, next) => {
|
|||||||
}
|
}
|
||||||
if (user._id === 0) delete user.viewLang;
|
if (user._id === 0) delete user.viewLang;
|
||||||
user.avatarUrl = avatar(user.avatar, 128);
|
user.avatarUrl = avatar(user.avatar, 128);
|
||||||
ctx.HydroContext.user = user;
|
ctx.HydroContext.user = await user.private();
|
||||||
if (!domain) {
|
if (!domain) {
|
||||||
ctx.pendingError = new NotFoundError(args.domainId);
|
ctx.pendingError = new NotFoundError(args.domainId);
|
||||||
args.domainId = 'system';
|
args.domainId = 'system';
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import {
|
|||||||
PrivilegeError, UserFacingError,
|
PrivilegeError, UserFacingError,
|
||||||
} from '../error';
|
} from '../error';
|
||||||
import { DomainDoc } from '../interface';
|
import { DomainDoc } from '../interface';
|
||||||
|
import serializer from '../lib/serializer';
|
||||||
import { Types } from '../lib/validator';
|
import { Types } from '../lib/validator';
|
||||||
import { Logger } from '../logger';
|
import { Logger } from '../logger';
|
||||||
import { PERM, PRIV } from '../model/builtin';
|
import { PERM, PRIV } from '../model/builtin';
|
||||||
@@ -109,12 +110,6 @@ wsServer.on('error', (error) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const ignoredLimit = `,${argv.options.ignoredLimit},`;
|
const ignoredLimit = `,${argv.options.ignoredLimit},`;
|
||||||
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 class HandlerCommon {
|
export class HandlerCommon {
|
||||||
render: (name: string, args?: any) => Promise<void>;
|
render: (name: string, args?: any) => Promise<void>;
|
||||||
@@ -341,7 +336,9 @@ export class ConnectionHandler extends HandlerCommon {
|
|||||||
conn: WebSocket;
|
conn: WebSocket;
|
||||||
|
|
||||||
send(data: any) {
|
send(data: any) {
|
||||||
this.conn.send(JSON.stringify(data, serializer(this.user?.hasPerm(PERM.PREM_VIEW_DISPLAYNAME))));
|
this.conn.send(JSON.stringify(data, serializer({
|
||||||
|
showDisplayName: this.user?.hasPerm(PERM.PREM_VIEW_DISPLAYNAME),
|
||||||
|
})));
|
||||||
}
|
}
|
||||||
|
|
||||||
close(code: number, reason: string) {
|
close(code: number, reason: string) {
|
||||||
|
|||||||
Reference in new issue
Block a user