mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-20 01:38:19 +08:00
framework&ui: add serialize guard [skip-cache]
This commit is contained in:
5 files changed
+24
-14
No files matched your search
@@ -47,7 +47,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
git config --global user.name undefined
|
git config --global user.name undefined
|
||||||
git config --global user.email i@undefined.moe
|
git config --global user.email i@undefined.moe
|
||||||
yarn set version stable
|
yarn set version 4.13.0
|
||||||
yarn
|
yarn
|
||||||
yarn dedupe
|
yarn dedupe
|
||||||
node build/prepare.js
|
node build/prepare.js
|
||||||
|
|||||||
@@ -90,6 +90,8 @@ const UIConfig = {
|
|||||||
'packages/ui-default/backendlib/misc.ts',
|
'packages/ui-default/backendlib/misc.ts',
|
||||||
'packages/ui-default/backendlib/template.ts',
|
'packages/ui-default/backendlib/template.ts',
|
||||||
'packages/ui-default/backendlib/markdown.js',
|
'packages/ui-default/backendlib/markdown.js',
|
||||||
|
'packages/ui-default/service-worker.ts',
|
||||||
|
'packages/ui-default/components/message/worker.ts',
|
||||||
'**/node_modules',
|
'**/node_modules',
|
||||||
],
|
],
|
||||||
include: ['ts', 'tsx', 'vue', 'json']
|
include: ['ts', 'tsx', 'vue', 'json']
|
||||||
|
|||||||
@@ -75,19 +75,22 @@ type Projection<T, S> = S extends ProjectionSchemaId
|
|||||||
[K in keyof T & keyof S]: K extends keyof AsKeys<S> ? Projection<T[K], AsKeys<S>[K]> : never
|
[K in keyof T & keyof S]: K extends keyof AsKeys<S> ? Projection<T[K], AsKeys<S>[K]> : never
|
||||||
};
|
};
|
||||||
|
|
||||||
export const projection = <T, S extends ProjectionSchema<T>>(input: T, schema: S): Projection<T, S> => {
|
export const projection = <T, S extends ProjectionSchema<T>>(input: T, schema: S, serializeCtx?: any): Projection<T, S> => {
|
||||||
if (typeof input !== 'object' || input === null) throw new Error('Input must be an object.');
|
if (typeof input !== 'object' || input === null) throw new Error('Input must be an object.');
|
||||||
type R = Projection<T, S>;
|
type R = Projection<T, S>;
|
||||||
|
if ('serialize' in input && typeof (input as any).serialize === 'function') {
|
||||||
|
input = (input as any).serialize(serializeCtx);
|
||||||
|
}
|
||||||
if (Array.isArray(schema)) schema = Object.fromEntries(schema.map((s) => [s, 1])) as S;
|
if (Array.isArray(schema)) schema = Object.fromEntries(schema.map((s) => [s, 1])) as S;
|
||||||
if (Array.isArray(input)) {
|
if (Array.isArray(input)) {
|
||||||
return input.map((item) => projection(item, schema)) as R;
|
return input.map((item) => projection(item, schema, serializeCtx)) as R;
|
||||||
}
|
}
|
||||||
const result = {} as R;
|
const result = {} as R;
|
||||||
for (const key of Reflect.ownKeys(input)) {
|
for (const key of Reflect.ownKeys(input as any)) {
|
||||||
const schemaIt = schema[key];
|
const schemaIt = schema[key];
|
||||||
if (!schemaIt) continue;
|
if (!schemaIt) continue;
|
||||||
if (schemaIt === 1 || !input[key]) result[key] = input[key];
|
if (schemaIt === 1 || !input[key]) result[key] = input[key];
|
||||||
else result[key] = projection(input[key], schemaIt);
|
else result[key] = projection(input[key], schemaIt, serializeCtx);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
@@ -174,7 +177,7 @@ export class ApiService extends Service {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (project && typeof result === 'object' && result !== null) ? projection(result, project) : result;
|
return (project && typeof result === 'object' && result !== null) ? projection(result, project, context) : result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { escapeRegExp, omit, pick, uniq } from 'lodash';
|
import { escapeRegExp, omit, pick, uniq } from 'lodash';
|
||||||
import { LRUCache } from 'lru-cache';
|
import { LRUCache } from 'lru-cache';
|
||||||
import { Collection, Filter, ObjectId } from 'mongodb';
|
import { Collection, Filter, ObjectId } from 'mongodb';
|
||||||
import { serializer } from '@hydrooj/framework';
|
|
||||||
import { LoginError, UserAlreadyExistError, UserNotFoundError } from '../error';
|
import { LoginError, UserAlreadyExistError, UserNotFoundError } from '../error';
|
||||||
import {
|
import {
|
||||||
Authenticator, BaseUserDict, FileInfo, GDoc,
|
Authenticator, BaseUserDict, FileInfo, GDoc,
|
||||||
@@ -167,11 +166,16 @@ export class User {
|
|||||||
return type === 'public' ? fields : fields.concat(this._privateFields);
|
return type === 'public' ? fields : fields.concat(this._privateFields);
|
||||||
}
|
}
|
||||||
|
|
||||||
serialize(h) {
|
serialize(h?) {
|
||||||
if (!this._isPrivate) {
|
if (this._isPrivate) {
|
||||||
return pick(this, this.getFields(h?.user?.hasPerm(PERM.PERM_VIEW_USER_PRIVATE_INFO) ? 'private' : 'public'));
|
const result: any = {};
|
||||||
|
for (const key of Object.keys(this)) {
|
||||||
|
if (key.startsWith('_') && key !== '_id') continue;
|
||||||
|
result[key] = this[key];
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
return JSON.stringify(this, serializer(true, h));
|
return pick(this, this.getFields(h?.user?.hasPerm(PERM.PERM_VIEW_USER_PRIVATE_INFO) ? 'private' : 'public'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,9 +18,10 @@ let { template } = argv.options;
|
|||||||
if (!template || typeof template !== 'string') template = findFileSync('@hydrooj/ui-default/templates');
|
if (!template || typeof template !== 'string') template = findFileSync('@hydrooj/ui-default/templates');
|
||||||
else template = findFileSync(template);
|
else template = findFileSync(template);
|
||||||
|
|
||||||
const replacer = (k, v) => {
|
const replacer = (s) => (k, v) => {
|
||||||
if (k.startsWith('_') && k !== '_id') return undefined;
|
if (k.startsWith('_') && k !== '_id') return undefined;
|
||||||
if (typeof v === 'bigint') return `BigInt::${v.toString()}`;
|
if (typeof v === 'bigint') return `BigInt::${v.toString()}`;
|
||||||
|
if (v && typeof v === 'object' && 'serialize' in v && typeof v.serialize === 'function') return v.serialize(s);
|
||||||
return v;
|
return v;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -68,7 +69,7 @@ class Nunjucks extends nunjucks.Environment {
|
|||||||
callback(error);
|
callback(error);
|
||||||
}
|
}
|
||||||
}, true);
|
}, true);
|
||||||
this.addFilter('json', (self) => (self ? JSON.stringify(self, replacer) : ''));
|
this.addFilter('json', (self, s) => (self ? JSON.stringify(self, replacer(s)) : ''));
|
||||||
this.addFilter('parseYaml', (self) => yaml.load(self));
|
this.addFilter('parseYaml', (self) => yaml.load(self));
|
||||||
this.addFilter('dumpYaml', (self) => yaml.dump(self));
|
this.addFilter('dumpYaml', (self) => yaml.dump(self));
|
||||||
this.addFilter('assign', (self, data) => Object.assign(self, data));
|
this.addFilter('assign', (self, data) => Object.assign(self, data));
|
||||||
@@ -79,7 +80,7 @@ class Nunjucks extends nunjucks.Environment {
|
|||||||
this.addFilter('base64_decode', (s) => Buffer.from(s, 'base64').toString());
|
this.addFilter('base64_decode', (s) => Buffer.from(s, 'base64').toString());
|
||||||
this.addFilter('jsesc', (self) => jsesc(self, { isScriptContext: true }));
|
this.addFilter('jsesc', (self) => jsesc(self, { isScriptContext: true }));
|
||||||
this.addFilter('bitand', (self, val) => self & val);
|
this.addFilter('bitand', (self, val) => self & val);
|
||||||
this.addFilter('toString', (self) => (typeof self === 'string' ? self : JSON.stringify(self, replacer)));
|
this.addFilter('toString', (self, s) => (typeof self === 'string' ? self : JSON.stringify(self, replacer(s))));
|
||||||
this.addFilter('content', (content, language, html) => {
|
this.addFilter('content', (content, language, html) => {
|
||||||
let s: any = '';
|
let s: any = '';
|
||||||
try {
|
try {
|
||||||
|
|||||||
Reference in new issue
Block a user