mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-20 01:38:19 +08:00
eslint: enable extra rules
no-implicit-coercion, no-extra-boolean-cast, no-invalid-this, logical-assignment-operators, no-unmodified-loop-condition
This commit is contained in:
1 parent
5ac9d930b2
commit
7f51df236a
34 files changed
+82
-78
No files matched your search
+15
-1
@@ -24,6 +24,7 @@ overrides:
|
|||||||
'@typescript-eslint/indent':
|
'@typescript-eslint/indent':
|
||||||
- warn
|
- warn
|
||||||
- 2
|
- 2
|
||||||
|
'@typescript-eslint/no-invalid-this': 0
|
||||||
env:
|
env:
|
||||||
browser: true
|
browser: true
|
||||||
es6: true
|
es6: true
|
||||||
@@ -44,7 +45,14 @@ rules:
|
|||||||
'@typescript-eslint/no-throw-literal': 0
|
'@typescript-eslint/no-throw-literal': 0
|
||||||
'@typescript-eslint/return-await': 0
|
'@typescript-eslint/return-await': 0
|
||||||
|
|
||||||
|
no-implicit-coercion:
|
||||||
|
- warn
|
||||||
|
- allow: ["!!", "+"]
|
||||||
|
no-extra-boolean-cast:
|
||||||
|
- warn
|
||||||
|
- enforceForLogicalOperands: true
|
||||||
no-multi-str: 0
|
no-multi-str: 0
|
||||||
|
'@typescript-eslint/no-invalid-this': 1
|
||||||
'@typescript-eslint/type-annotation-spacing': 1
|
'@typescript-eslint/type-annotation-spacing': 1
|
||||||
'@typescript-eslint/indent':
|
'@typescript-eslint/indent':
|
||||||
- warn
|
- warn
|
||||||
@@ -111,6 +119,10 @@ rules:
|
|||||||
import/no-extraneous-dependencies: 0
|
import/no-extraneous-dependencies: 0
|
||||||
import/no-named-as-default: 0
|
import/no-named-as-default: 0
|
||||||
import/prefer-default-export: 0
|
import/prefer-default-export: 0
|
||||||
|
logical-assignment-operators:
|
||||||
|
- warn
|
||||||
|
- always
|
||||||
|
- enforceForIfStatements: true
|
||||||
max-classes-per-file: 0
|
max-classes-per-file: 0
|
||||||
max-len:
|
max-len:
|
||||||
- warn
|
- warn
|
||||||
@@ -131,6 +143,7 @@ rules:
|
|||||||
no-return-await: 0
|
no-return-await: 0
|
||||||
no-shadow: 0
|
no-shadow: 0
|
||||||
no-underscore-dangle: 0
|
no-underscore-dangle: 0
|
||||||
|
no-unmodified-loop-condition: 1
|
||||||
prefer-destructuring: 0
|
prefer-destructuring: 0
|
||||||
function-paren-newline: 0
|
function-paren-newline: 0
|
||||||
simple-import-sort/imports:
|
simple-import-sort/imports:
|
||||||
@@ -153,7 +166,8 @@ settings:
|
|||||||
import/resolver:
|
import/resolver:
|
||||||
typescript:
|
typescript:
|
||||||
alwaysTryTypes: true
|
alwaysTryTypes: true
|
||||||
# parserOptions:
|
parserOptions:
|
||||||
|
sourceType: module
|
||||||
# project:
|
# project:
|
||||||
# - './tsconfig.json'
|
# - './tsconfig.json'
|
||||||
# - './packages/**/tsconfig.json'
|
# - './packages/**/tsconfig.json'
|
||||||
@@ -8,16 +8,10 @@ const client = new Client({ node: SystemModel.get('elastic-search.url') || 'http
|
|||||||
|
|
||||||
const indexOmit = ['_id', 'docType', 'data', 'additional_file', 'config', 'stats', 'assign'];
|
const indexOmit = ['_id', 'docType', 'data', 'additional_file', 'config', 'stats', 'assign'];
|
||||||
const processDocument = (doc: Partial<ProblemDoc>) => {
|
const processDocument = (doc: Partial<ProblemDoc>) => {
|
||||||
if (doc.content) {
|
doc.content &&= doc.content.replace(/[[\]【】()()]/g, ' ');
|
||||||
doc.content = doc.content.replace(/[[\]【】()()]/g, ' ');
|
doc.title &&= doc.title.replace(/[[\]【】()()]/g, ' ')
|
||||||
}
|
|
||||||
if (doc.title) {
|
|
||||||
doc.title = doc.title.replace(/[[\]【】()()]/g, ' ')
|
|
||||||
.replace(/([a-zA-Z]{2,})(\d+)/, '$1$2 $1 $2');
|
.replace(/([a-zA-Z]{2,})(\d+)/, '$1$2 $1 $2');
|
||||||
}
|
doc.pid &&= doc.pid.replace(/([a-zA-Z]{2,})(\d+)/, '$1$2 $1 $2');
|
||||||
if (doc.pid) {
|
|
||||||
doc.pid = doc.pid.replace(/([a-zA-Z]{2,})(\d+)/, '$1$2 $1 $2');
|
|
||||||
}
|
|
||||||
return _.omit(doc, indexOmit);
|
return _.omit(doc, indexOmit);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ async function daemon() {
|
|||||||
const queue = new PQueue({ concurrency: Infinity });
|
const queue = new PQueue({ concurrency: Infinity });
|
||||||
queue.on('error', (e) => log.error(e));
|
queue.on('error', (e) => log.error(e));
|
||||||
for (const i in _hosts) {
|
for (const i in _hosts) {
|
||||||
_hosts[i].host = _hosts[i].host || i;
|
_hosts[i].host ||= i;
|
||||||
hosts[i] = new HydroHost(_hosts[i]);
|
hosts[i] = new HydroHost(_hosts[i]);
|
||||||
await hosts[i].init();
|
await hosts[i].init();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,9 +24,9 @@ export default class Hydro {
|
|||||||
language: Record<string, LangConfig>;
|
language: Record<string, LangConfig>;
|
||||||
|
|
||||||
constructor(public config) {
|
constructor(public config) {
|
||||||
this.config.detail = this.config.detail ?? true;
|
this.config.detail ??= true;
|
||||||
this.config.cookie = this.config.cookie || '';
|
this.config.cookie ||= '';
|
||||||
this.config.last_update_at = this.config.last_update_at || 0;
|
this.config.last_update_at ||= 0;
|
||||||
if (!this.config.server_url.startsWith('http')) this.config.server_url = `http://${this.config.server_url}`;
|
if (!this.config.server_url.startsWith('http')) this.config.server_url = `http://${this.config.server_url}`;
|
||||||
if (!this.config.server_url.endsWith('/')) this.config.server_url = `${this.config.server_url}/`;
|
if (!this.config.server_url.endsWith('/')) this.config.server_url = `${this.config.server_url}/`;
|
||||||
this.getLang = this.getLang.bind(this);
|
this.getLang = this.getLang.bind(this);
|
||||||
@@ -91,11 +91,12 @@ export default class Hydro {
|
|||||||
files: filenames,
|
files: filenames,
|
||||||
});
|
});
|
||||||
if (!res.body.links) throw new FormatError('problem not exist');
|
if (!res.body.links) throw new FormatError('problem not exist');
|
||||||
|
const that = this;
|
||||||
// eslint-disable-next-line no-inner-declarations
|
// eslint-disable-next-line no-inner-declarations
|
||||||
async function download(name: string) {
|
async function download(name: string) {
|
||||||
if (name.includes('/')) await fs.ensureDir(path.join(filePath, name.split('/')[0]));
|
if (name.includes('/')) await fs.ensureDir(path.join(filePath, name.split('/')[0]));
|
||||||
const w = fs.createWriteStream(path.join(filePath, name));
|
const w = fs.createWriteStream(path.join(filePath, name));
|
||||||
this.get(res.body.links[name]).pipe(w);
|
that.get(res.body.links[name]).pipe(w);
|
||||||
await new Promise((resolve, reject) => {
|
await new Promise((resolve, reject) => {
|
||||||
const timeout = setTimeout(() => reject(new Error(`DownloadTimeout(${name}, 60s)`)), 60000);
|
const timeout = setTimeout(() => reject(new Error(`DownloadTimeout(${name}, 60s)`)), 60000);
|
||||||
w.on('error', (e) => {
|
w.on('error', (e) => {
|
||||||
@@ -111,7 +112,7 @@ export default class Hydro {
|
|||||||
const tasks = [];
|
const tasks = [];
|
||||||
const queue = new PQueue({ concurrency: 10 });
|
const queue = new PQueue({ concurrency: 10 });
|
||||||
for (const name in res.body.links) {
|
for (const name in res.body.links) {
|
||||||
tasks.push(queue.add(() => download.call(this, name)));
|
tasks.push(queue.add(() => download(name)));
|
||||||
}
|
}
|
||||||
queue.start();
|
queue.start();
|
||||||
await Promise.all(tasks);
|
await Promise.all(tasks);
|
||||||
|
|||||||
@@ -546,7 +546,7 @@ export class ContestManagementHandler extends ContestManagementBaseHandler {
|
|||||||
if (size >= system.get('limit.contest_files_size')) {
|
if (size >= system.get('limit.contest_files_size')) {
|
||||||
throw new FileLimitExceededError('size');
|
throw new FileLimitExceededError('size');
|
||||||
}
|
}
|
||||||
if (!filename) filename = file.originalFilename || String.random(16);
|
filename ||= file.originalFilename || String.random(16);
|
||||||
if (filename.includes('/') || filename.includes('..')) throw new ValidationError('filename', null, 'Bad filename');
|
if (filename.includes('/') || filename.includes('..')) throw new ValidationError('filename', null, 'Bad filename');
|
||||||
await storage.put(`contest/${domainId}/${tid}/${filename}`, file.filepath, this.user._id);
|
await storage.put(`contest/${domainId}/${tid}/${filename}`, file.filepath, this.user._id);
|
||||||
const meta = await storage.getMeta(`contest/${domainId}/${tid}/${filename}`);
|
const meta = await storage.getMeta(`contest/${domainId}/${tid}/${filename}`);
|
||||||
|
|||||||
@@ -65,8 +65,8 @@ class DiscussionHandler extends Handler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (this.ddoc) {
|
if (this.ddoc) {
|
||||||
this.ddoc.parentType = this.ddoc.parentType || this.vnode.type;
|
this.ddoc.parentType ||= this.vnode.type;
|
||||||
this.ddoc.parentId = this.ddoc.parentId || this.vnode.id;
|
this.ddoc.parentId ||= this.vnode.id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -375,13 +375,11 @@ class HomeMessagesHandler extends Handler {
|
|||||||
const parsed = {};
|
const parsed = {};
|
||||||
for (const m of messages) {
|
for (const m of messages) {
|
||||||
const target = m.from === this.user._id ? m.to : m.from;
|
const target = m.from === this.user._id ? m.to : m.from;
|
||||||
if (!parsed[target]) {
|
parsed[target] ||= {
|
||||||
parsed[target] = {
|
|
||||||
_id: target,
|
_id: target,
|
||||||
udoc: { ...udict[target], avatarUrl: avatar(udict[target].avatar) },
|
udoc: { ...udict[target], avatarUrl: avatar(udict[target].avatar) },
|
||||||
messages: [],
|
messages: [],
|
||||||
};
|
};
|
||||||
}
|
|
||||||
parsed[target].messages.push(m);
|
parsed[target].messages.push(m);
|
||||||
}
|
}
|
||||||
await user.setById(this.user._id, { unreadMsg: 0 });
|
await user.setById(this.user._id, { unreadMsg: 0 });
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ export async function postJudge(rdoc: RecordDoc) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function end(body: Partial<JudgeResultBody>) {
|
export async function end(body: Partial<JudgeResultBody>) {
|
||||||
if (body.rid) body.rid = new ObjectID(body.rid);
|
body.rid &&= new ObjectID(body.rid);
|
||||||
let rdoc = await record.get(body.rid);
|
let rdoc = await record.get(body.rid);
|
||||||
if (!rdoc) return;
|
if (!rdoc) return;
|
||||||
const $set: Partial<RecordDoc> = {};
|
const $set: Partial<RecordDoc> = {};
|
||||||
|
|||||||
@@ -242,7 +242,7 @@ class SystemUserImportHandler extends SystemHandler {
|
|||||||
try {
|
try {
|
||||||
const data = JSON.parse(extra);
|
const data = JSON.parse(extra);
|
||||||
if (data.group) {
|
if (data.group) {
|
||||||
if (!groups[data.group]) groups[data.group] = [];
|
groups[data.group] ||= [];
|
||||||
groups[data.group].push(email);
|
groups[data.group].push(email);
|
||||||
}
|
}
|
||||||
if (data.school) payload.school = data.school;
|
if (data.school) payload.school = data.school;
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ export class FilesHandler extends Handler {
|
|||||||
if (size >= system.get('limit.user_files_size')) {
|
if (size >= system.get('limit.user_files_size')) {
|
||||||
if (!this.user.hasPriv(PRIV.PRIV_UNLIMITED_QUOTA)) throw new FileLimitExceededError('size');
|
if (!this.user.hasPriv(PRIV.PRIV_UNLIMITED_QUOTA)) throw new FileLimitExceededError('size');
|
||||||
}
|
}
|
||||||
if (!filename) filename = file.originalFilename || String.random(16);
|
filename ||= file.originalFilename || String.random(16);
|
||||||
if (filename.includes('/') || filename.includes('..')) throw new ValidationError('filename', null, 'Bad filename');
|
if (filename.includes('/') || filename.includes('..')) throw new ValidationError('filename', null, 'Bad filename');
|
||||||
if (this.user._files.filter((i) => i.name === filename).length) throw new FileExistsError(filename);
|
if (this.user._files.filter((i) => i.name === filename).length) throw new FileExistsError(filename);
|
||||||
await storage.put(`user/${this.user._id}/${filename}`, file.filepath, this.user._id);
|
await storage.put(`user/${this.user._id}/${filename}`, file.filepath, this.user._id);
|
||||||
|
|||||||
@@ -161,7 +161,7 @@ export class ProblemMainHandler extends Handler {
|
|||||||
total = result.total;
|
total = result.total;
|
||||||
pcountRelation = result.countRelation;
|
pcountRelation = result.countRelation;
|
||||||
if (!result.hits.length) fail = true;
|
if (!result.hits.length) fail = true;
|
||||||
if (!query.$and) query.$and = [];
|
query.$and ||= [];
|
||||||
query.$and.push({
|
query.$and.push({
|
||||||
$or: result.hits.map((i) => {
|
$or: result.hits.map((i) => {
|
||||||
const [did, docId] = i.split('/');
|
const [did, docId] = i.split('/');
|
||||||
@@ -723,7 +723,7 @@ export class ProblemFilesHandler extends ProblemDetailHandler {
|
|||||||
async postUploadFile(domainId: string, filename: string, type = 'testdata') {
|
async postUploadFile(domainId: string, filename: string, type = 'testdata') {
|
||||||
if (this.pdoc.reference) throw new ProblemIsReferencedError('edit files');
|
if (this.pdoc.reference) throw new ProblemIsReferencedError('edit files');
|
||||||
if (!this.request.files.file) throw new ValidationError('file');
|
if (!this.request.files.file) throw new ValidationError('file');
|
||||||
if (!filename) filename = this.request.files.file.originalFilename || String.random(16);
|
filename ||= this.request.files.file.originalFilename || String.random(16);
|
||||||
if (filename.includes('/') || filename.includes('..')) throw new ValidationError('filename', null, 'Bad filename');
|
if (filename.includes('/') || filename.includes('..')) throw new ValidationError('filename', null, 'Bad filename');
|
||||||
if (!this.user.own(this.pdoc, PERM.PERM_EDIT_PROBLEM_SELF)) this.checkPerm(PERM.PERM_EDIT_PROBLEM);
|
if (!this.user.own(this.pdoc, PERM.PERM_EDIT_PROBLEM_SELF)) this.checkPerm(PERM.PERM_EDIT_PROBLEM);
|
||||||
const files = [];
|
const files = [];
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ async function getStatus() {
|
|||||||
let desc = '';
|
let desc = '';
|
||||||
const online = new Date(stat.updateAt).getTime() > new Date().getTime() - 300000;
|
const online = new Date(stat.updateAt).getTime() > new Date().getTime() - 300000;
|
||||||
if (!online) desc = 'Offline';
|
if (!online) desc = 'Offline';
|
||||||
desc = desc || 'Online';
|
desc ||= 'Online';
|
||||||
stat.isOnline = online;
|
stat.isOnline = online;
|
||||||
stat.status = desc;
|
stat.status = desc;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -268,7 +268,7 @@ export class TrainingFilesHandler extends Handler {
|
|||||||
if (size >= system.get('limit.contest_files_size')) {
|
if (size >= system.get('limit.contest_files_size')) {
|
||||||
throw new FileLimitExceededError('size');
|
throw new FileLimitExceededError('size');
|
||||||
}
|
}
|
||||||
if (!filename) filename = file.originalFilename || String.random(16);
|
filename ||= file.originalFilename || String.random(16);
|
||||||
if (filename.includes('/') || filename.includes('..')) throw new ValidationError('filename', null, 'Bad filename');
|
if (filename.includes('/') || filename.includes('..')) throw new ValidationError('filename', null, 'Bad filename');
|
||||||
await storage.put(`training/${domainId}/${tid}/${filename}`, file.filepath, this.user._id);
|
await storage.put(`training/${domainId}/${tid}/${filename}`, file.filepath, this.user._id);
|
||||||
const meta = await storage.getMeta(`training/${domainId}/${tid}/${filename}`);
|
const meta = await storage.getMeta(`training/${domainId}/${tid}/${filename}`);
|
||||||
|
|||||||
@@ -119,7 +119,7 @@ class UserLoginHandler extends Handler {
|
|||||||
async post(domainId: string, uname: string, password: string, rememberme = false, redirect = '', tfa = '') {
|
async post(domainId: string, uname: string, password: string, rememberme = false, redirect = '', tfa = '') {
|
||||||
if (!system.get('server.login')) throw new BuiltinLoginError();
|
if (!system.get('server.login')) throw new BuiltinLoginError();
|
||||||
let udoc = await user.getByEmail(domainId, uname);
|
let udoc = await user.getByEmail(domainId, uname);
|
||||||
if (!udoc) udoc = await user.getByUname(domainId, uname);
|
udoc ||= await user.getByUname(domainId, uname);
|
||||||
if (!udoc) throw new UserNotFoundError(uname);
|
if (!udoc) throw new UserNotFoundError(uname);
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
this.limitRate('user_login', 60, 30, false),
|
this.limitRate('user_login', 60, 30, false),
|
||||||
@@ -425,7 +425,7 @@ class OauthCallbackHandler extends Handler {
|
|||||||
}
|
}
|
||||||
this.checkPriv(PRIV.PRIV_REGISTER_USER);
|
this.checkPriv(PRIV.PRIV_REGISTER_USER);
|
||||||
let username = '';
|
let username = '';
|
||||||
r.uname = r.uname || [];
|
r.uname ||= [];
|
||||||
r.uname.push(String.random(16));
|
r.uname.push(String.random(16));
|
||||||
const mailDomain = r.email.split('@')[1];
|
const mailDomain = r.email.split('@')[1];
|
||||||
if (await BlackListModel.get(`mail::${mailDomain}`)) throw new BlacklistedError(mailDomain);
|
if (await BlackListModel.get(`mail::${mailDomain}`)) throw new BlacklistedError(mailDomain);
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ if (!global.Hydro) {
|
|||||||
lib: {},
|
lib: {},
|
||||||
module: new Proxy({} as any, {
|
module: new Proxy({} as any, {
|
||||||
get(self, key) {
|
get(self, key) {
|
||||||
if (!self[key]) self[key] = {};
|
self[key] ||= {};
|
||||||
return self[key];
|
return self[key];
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ export const providers: Record<string, AvatarProvider> = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function avatar(src: string, size = 64, fallback = '') {
|
function avatar(src: string, size = 64, fallback = '') {
|
||||||
src = src || fallback;
|
src ||= fallback;
|
||||||
let index = src.indexOf(':');
|
let index = src.indexOf(':');
|
||||||
if (index === -1) src = fallback;
|
if (index === -1) src = fallback;
|
||||||
index = src.indexOf(':');
|
index = src.indexOf(':');
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ class I18nService extends Service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
load(lang: string, content: Record<string, string>) {
|
load(lang: string, content: Record<string, string>) {
|
||||||
if (!translations[lang]) translations[lang] = [];
|
translations[lang] ||= [];
|
||||||
translations[lang].unshift(content);
|
translations[lang].unshift(content);
|
||||||
this.caller?.on('dispose', () => {
|
this.caller?.on('dispose', () => {
|
||||||
translations[lang] = translations[lang].filter((i) => i !== content);
|
translations[lang] = translations[lang].filter((i) => i !== content);
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ const buildChecker = (...permPrivChecker: PermPrivChecker) => {
|
|||||||
|
|
||||||
export const nodes = new Proxy({}, {
|
export const nodes = new Proxy({}, {
|
||||||
get(self, key) {
|
get(self, key) {
|
||||||
if (!self[key]) self[key] = [];
|
self[key] ||= [];
|
||||||
return self[key];
|
return self[key];
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -35,18 +35,17 @@ interface AcmDetail extends AcmJournal {
|
|||||||
|
|
||||||
function buildContestRule<T>(def: ContestRule<T>): ContestRule<T>;
|
function buildContestRule<T>(def: ContestRule<T>): ContestRule<T>;
|
||||||
function buildContestRule<T>(def: Partial<ContestRule<T>>, baseRule: ContestRule<T>): ContestRule<T>;
|
function buildContestRule<T>(def: Partial<ContestRule<T>>, baseRule: ContestRule<T>): ContestRule<T>;
|
||||||
function buildContestRule<T>(def: Partial<ContestRule<T>>, { _originalRule: base }: ContestRule<T> = { _originalRule: {} } as any) {
|
function buildContestRule<T>(def: Partial<ContestRule<T>>, baseRule: ContestRule<T> = {} as any) {
|
||||||
def._originalRule = {
|
const base = baseRule._originalRule || {};
|
||||||
scoreboard: def.scoreboard || base.scoreboard,
|
const funcs = ['scoreboard', 'scoreboardRow', 'scoreboardHeader', 'stat'];
|
||||||
scoreboardRow: def.scoreboardRow || base.scoreboardRow,
|
const f = {};
|
||||||
scoreboardHeader: def.scoreboardHeader || base.scoreboardHeader,
|
const rule = { ...baseRule, ...def };
|
||||||
stat: def.stat || base.stat,
|
for (const key of funcs) {
|
||||||
};
|
f[key] = def[key] || base[key];
|
||||||
def.scoreboard = (def.scoreboard || base.scoreboard).bind(def);
|
rule[key] = f[key].bind(rule);
|
||||||
def.scoreboardHeader = (def.scoreboardHeader || base.scoreboardHeader).bind(def);
|
}
|
||||||
def.scoreboardRow = (def.scoreboardRow || base.scoreboardRow).bind(def);
|
rule._originalRule = f;
|
||||||
def.stat = (def.stat || base.stat).bind(def);
|
return rule;
|
||||||
return def as ContestRule<T>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const acm = buildContestRule({
|
const acm = buildContestRule({
|
||||||
@@ -708,24 +707,24 @@ export async function unlockScoreboard(domainId: string, tid: ObjectID) {
|
|||||||
await edit(domainId, tid, { unlocked: true });
|
await edit(domainId, tid, { unlocked: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
export function canViewHiddenScoreboard(tdoc: Tdoc<30>) {
|
export function canViewHiddenScoreboard(this: Handler, tdoc: Tdoc<30>) {
|
||||||
if (tdoc.rule === 'homework') return this.user.hasPerm(PERM.PERM_VIEW_HOMEWORK_HIDDEN_SCOREBOARD);
|
if (tdoc.rule === 'homework') return this.user.hasPerm(PERM.PERM_VIEW_HOMEWORK_HIDDEN_SCOREBOARD);
|
||||||
return this.user.hasPerm(PERM.PERM_VIEW_CONTEST_HIDDEN_SCOREBOARD);
|
return this.user.hasPerm(PERM.PERM_VIEW_CONTEST_HIDDEN_SCOREBOARD);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function canShowRecord(tdoc: Tdoc<30>, allowPermOverride = true) {
|
export function canShowRecord(this: Handler, tdoc: Tdoc<30>, allowPermOverride = true) {
|
||||||
if (RULES[tdoc.rule].showRecord(tdoc, new Date())) return true;
|
if (RULES[tdoc.rule].showRecord(tdoc, new Date())) return true;
|
||||||
if (allowPermOverride && canViewHiddenScoreboard.call(this, tdoc)) return true;
|
if (allowPermOverride && canViewHiddenScoreboard.call(this, tdoc)) return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function canShowSelfRecord(tdoc: Tdoc<30>, allowPermOverride = true) {
|
export function canShowSelfRecord(this: Handler, tdoc: Tdoc<30>, allowPermOverride = true) {
|
||||||
if (RULES[tdoc.rule].showSelfRecord(tdoc, new Date())) return true;
|
if (RULES[tdoc.rule].showSelfRecord(tdoc, new Date())) return true;
|
||||||
if (allowPermOverride && canViewHiddenScoreboard.call(this, tdoc)) return true;
|
if (allowPermOverride && canViewHiddenScoreboard.call(this, tdoc)) return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function canShowScoreboard(tdoc: Tdoc<30>, allowPermOverride = true) {
|
export function canShowScoreboard(this: Handler, tdoc: Tdoc<30>, allowPermOverride = true) {
|
||||||
if (RULES[tdoc.rule].showScoreboard(tdoc, new Date())) return true;
|
if (RULES[tdoc.rule].showScoreboard(tdoc, new Date())) return true;
|
||||||
if (allowPermOverride && canViewHiddenScoreboard.call(this, tdoc)) return true;
|
if (allowPermOverride && canViewHiddenScoreboard.call(this, tdoc)) return true;
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -305,7 +305,7 @@ export async function getListVnodes(domainId: string, ddocs: any, getHidden = fa
|
|||||||
const res = {};
|
const res = {};
|
||||||
async function task(ddoc: DiscussionDoc) {
|
async function task(ddoc: DiscussionDoc) {
|
||||||
const vnode = await getVnode(domainId, ddoc.parentType, ddoc.parentId.toString());
|
const vnode = await getVnode(domainId, ddoc.parentType, ddoc.parentId.toString());
|
||||||
if (!res[ddoc.parentType]) res[ddoc.parentType] = {};
|
res[ddoc.parentType] ||= {};
|
||||||
if (!getHidden && vnode.hidden) return;
|
if (!getHidden && vnode.hidden) return;
|
||||||
if (vnode.assign?.length && Set.intersection(vnode.assign, assign).size) return;
|
if (vnode.assign?.length && Set.intersection(vnode.assign, assign).size) return;
|
||||||
res[ddoc.parentType][ddoc.parentId] = vnode;
|
res[ddoc.parentType][ddoc.parentId] = vnode;
|
||||||
|
|||||||
@@ -178,10 +178,10 @@ class DomainModel {
|
|||||||
|
|
||||||
static async getDomainUser(domainId: string, udoc: DomainUserArg) {
|
static async getDomainUser(domainId: string, udoc: DomainUserArg) {
|
||||||
let dudoc = await collUser.findOne({ domainId, uid: udoc._id });
|
let dudoc = await collUser.findOne({ domainId, uid: udoc._id });
|
||||||
dudoc = dudoc || {};
|
dudoc ||= {};
|
||||||
if (!(udoc.priv & PRIV.PRIV_USER_PROFILE)) dudoc.role = 'guest';
|
if (!(udoc.priv & PRIV.PRIV_USER_PROFILE)) dudoc.role = 'guest';
|
||||||
if (udoc.priv & PRIV.PRIV_MANAGE_ALL_DOMAIN) dudoc.role = 'root';
|
if (udoc.priv & PRIV.PRIV_MANAGE_ALL_DOMAIN) dudoc.role = 'root';
|
||||||
dudoc.role = dudoc.role || 'default';
|
dudoc.role ||= 'default';
|
||||||
const ddoc = await DomainModel.get(domainId);
|
const ddoc = await DomainModel.get(domainId);
|
||||||
dudoc.perm = ddoc?.roles[dudoc.role]
|
dudoc.perm = ddoc?.roles[dudoc.role]
|
||||||
? BigInt(ddoc?.roles[dudoc.role])
|
? BigInt(ddoc?.roles[dudoc.role])
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ const coll = db.collection('schedule');
|
|||||||
async function getFirst(query: FilterQuery<Schedule>) {
|
async function getFirst(query: FilterQuery<Schedule>) {
|
||||||
if (process.env.CI) return null;
|
if (process.env.CI) return null;
|
||||||
const q = { ...query };
|
const q = { ...query };
|
||||||
q.executeAfter = q.executeAfter || { $lt: new Date() };
|
q.executeAfter ||= { $lt: new Date() };
|
||||||
const res = await coll.findOneAndDelete(q);
|
const res = await coll.findOneAndDelete(q);
|
||||||
if (res.value) {
|
if (res.value) {
|
||||||
logger.debug('%o', res.value);
|
logger.debug('%o', res.value);
|
||||||
|
|||||||
@@ -209,7 +209,7 @@ class UserModel {
|
|||||||
const unameLower = uname.trim().toLowerCase();
|
const unameLower = uname.trim().toLowerCase();
|
||||||
if (cache.has(`name/${unameLower}/${domainId}`)) return cache.get(`name/${unameLower}/${domainId}`) || null;
|
if (cache.has(`name/${unameLower}/${domainId}`)) return cache.get(`name/${unameLower}/${domainId}`) || null;
|
||||||
let udoc = await coll.findOne({ unameLower });
|
let udoc = await coll.findOne({ unameLower });
|
||||||
if (!udoc) udoc = await collV.findOne({ unameLower });
|
udoc ||= await collV.findOne({ unameLower });
|
||||||
if (!udoc) return null;
|
if (!udoc) return null;
|
||||||
const dudoc = await domain.getDomainUser(domainId, udoc);
|
const dudoc = await domain.getDomainUser(domainId, udoc);
|
||||||
const res = await new UserModel.User(udoc, dudoc).init();
|
const res = await new UserModel.User(udoc, dudoc).init();
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ export async function calcLevel(domainId: string, report: Function) {
|
|||||||
let bulk = coll.initializeUnorderedBulkOp();
|
let bulk = coll.initializeUnorderedBulkOp();
|
||||||
for await (const dudoc of ducur) {
|
for await (const dudoc of ducur) {
|
||||||
count++;
|
count++;
|
||||||
if (!dudoc.rp) dudoc.rp = null;
|
dudoc.rp ||= null;
|
||||||
if (dudoc.rp !== last.rp) rank = count;
|
if (dudoc.rp !== last.rp) rank = count;
|
||||||
bulk.find({ _id: dudoc._id }).updateOne({ $set: { rank } });
|
bulk.find({ _id: dudoc._id }).updateOne({ $set: { rank } });
|
||||||
last = dudoc;
|
last = dudoc;
|
||||||
|
|||||||
@@ -166,8 +166,8 @@ function _buildParam(name: string, source: 'get' | 'post' | 'all' | 'route', ...
|
|||||||
|
|
||||||
function _descriptor(v: ParamOption) {
|
function _descriptor(v: ParamOption) {
|
||||||
return function desc(this: Handler, target: any, funcName: string, obj: any) {
|
return function desc(this: Handler, target: any, funcName: string, obj: any) {
|
||||||
if (!target.__param) target.__param = {};
|
target.__param ||= {};
|
||||||
if (!target.__param[target.constructor.name]) target.__param[target.constructor.name] = {};
|
target.__param[target.constructor.name] ||= {};
|
||||||
if (!target.__param[target.constructor.name][funcName]) {
|
if (!target.__param[target.constructor.name][funcName]) {
|
||||||
target.__param[target.constructor.name][funcName] = [{ name: 'domainId', type: 'string', source: 'route' }];
|
target.__param[target.constructor.name][funcName] = [{ name: 'domainId', type: 'string', source: 'route' }];
|
||||||
const originalMethod = obj.value;
|
const originalMethod = obj.value;
|
||||||
|
|||||||
@@ -194,7 +194,7 @@ export class Handler extends HandlerCommon {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async onerror(error: HydroError) {
|
async onerror(error: HydroError) {
|
||||||
if (!error.msg) error.msg = () => error.message;
|
error.msg ||= () => error.message;
|
||||||
if (error instanceof UserFacingError && !process.env.DEV) error.stack = '';
|
if (error instanceof UserFacingError && !process.env.DEV) error.stack = '';
|
||||||
if (!(error instanceof NotFoundError)) {
|
if (!(error instanceof NotFoundError)) {
|
||||||
// eslint-disable-next-line max-len
|
// eslint-disable-next-line max-len
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ export async function setConfig(key: string, value: any) {
|
|||||||
const t = path.pop();
|
const t = path.pop();
|
||||||
let cursor = systemConfig;
|
let cursor = systemConfig;
|
||||||
for (const p of path) {
|
for (const p of path) {
|
||||||
if (!cursor[p]) cursor[p] = {};
|
cursor[p] ||= {};
|
||||||
cursor = cursor[p];
|
cursor = cursor[p];
|
||||||
}
|
}
|
||||||
cursor[t] = value;
|
cursor[t] = value;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import {
|
import {
|
||||||
Context, ForbiddenError, superagent, SystemModel,
|
Context, ForbiddenError, Handler, superagent, SystemModel,
|
||||||
TokenModel, UserFacingError, ValidationError,
|
TokenModel, UserFacingError, ValidationError,
|
||||||
} from 'hydrooj';
|
} from 'hydrooj';
|
||||||
|
|
||||||
@@ -11,7 +11,7 @@ declare module 'hydrooj' {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function get() {
|
async function get(this: Handler) {
|
||||||
const [appid, [state]] = await Promise.all([
|
const [appid, [state]] = await Promise.all([
|
||||||
SystemModel.get('login-with-github.id'),
|
SystemModel.get('login-with-github.id'),
|
||||||
TokenModel.add(TokenModel.TYPE_OAUTH, 600, { redirect: this.request.referer }),
|
TokenModel.add(TokenModel.TYPE_OAUTH, 600, { redirect: this.request.referer }),
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import {
|
import {
|
||||||
Context, superagent, SystemModel, TokenModel, UserFacingError,
|
Context, Handler, superagent, SystemModel, TokenModel, UserFacingError,
|
||||||
} from 'hydrooj';
|
} from 'hydrooj';
|
||||||
|
|
||||||
declare module 'hydrooj' {
|
declare module 'hydrooj' {
|
||||||
@@ -9,7 +9,7 @@ declare module 'hydrooj' {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function get() {
|
async function get(this: Handler) {
|
||||||
const [appid, url, [state]] = await Promise.all([
|
const [appid, url, [state]] = await Promise.all([
|
||||||
SystemModel.get('login-with-google.id'),
|
SystemModel.get('login-with-google.id'),
|
||||||
SystemModel.get('server.url'),
|
SystemModel.get('server.url'),
|
||||||
@@ -42,7 +42,7 @@ function decodeJWT(idToken: string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function callback({
|
async function callback(this: Handler, {
|
||||||
state, code, error,
|
state, code, error,
|
||||||
}) {
|
}) {
|
||||||
if (error) throw new UserFacingError(error);
|
if (error) throw new UserFacingError(error);
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ export async function run({
|
|||||||
for (const udoc of udocs) {
|
for (const udoc of udocs) {
|
||||||
if (randomMail) delete udoc.email;
|
if (randomMail) delete udoc.email;
|
||||||
let current = await UserModel.getByEmail(domainId, udoc.email || `${udoc.user_id}@hustoj.local`);
|
let current = await UserModel.getByEmail(domainId, udoc.email || `${udoc.user_id}@hustoj.local`);
|
||||||
if (!current) current = await UserModel.getByUname(domainId, udoc.user_id);
|
current ||= await UserModel.getByUname(domainId, udoc.user_id);
|
||||||
if (current) {
|
if (current) {
|
||||||
report({ message: `duplicate user with email ${udoc.email}: ${current.uname},${udoc.user_id}` });
|
report({ message: `duplicate user with email ${udoc.email}: ${current.uname},${udoc.user_id}` });
|
||||||
uidMap[udoc.user_id] = current._id;
|
uidMap[udoc.user_id] = current._id;
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ export async function run({
|
|||||||
for (const udoc of udocs) {
|
for (const udoc of udocs) {
|
||||||
if (randomMail) delete udoc.email;
|
if (randomMail) delete udoc.email;
|
||||||
let current = await UserModel.getByEmail(domainId, udoc.email || `${udoc.username}@syzoj.local`);
|
let current = await UserModel.getByEmail(domainId, udoc.email || `${udoc.username}@syzoj.local`);
|
||||||
if (!current) current = await UserModel.getByUname(domainId, udoc.username);
|
current ||= await UserModel.getByUname(domainId, udoc.username);
|
||||||
if (current) {
|
if (current) {
|
||||||
report({ message: `duplicate user with email ${udoc.email}: ${current.uname},${udoc.username}` });
|
report({ message: `duplicate user with email ${udoc.email}: ${current.uname},${udoc.username}` });
|
||||||
uidMap[udoc.id] = current._id;
|
uidMap[udoc.id] = current._id;
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ export default async function readYamlCases(cfg: Record<string, any> = {}, check
|
|||||||
if (!cfg.checker.includes('.')) {
|
if (!cfg.checker.includes('.')) {
|
||||||
config.checker = findFileSync(`@hydrooj/hydrojudge/vendor/testlib/checkers/${cfg.checker}.cpp`, false);
|
config.checker = findFileSync(`@hydrooj/hydrojudge/vendor/testlib/checkers/${cfg.checker}.cpp`, false);
|
||||||
}
|
}
|
||||||
if (!config.checker) config.checker = checkFile(cfg.checker, 'Cannot find checker {0}.');
|
config.checker ||= checkFile(cfg.checker, 'Cannot find checker {0}.');
|
||||||
}
|
}
|
||||||
if (cfg.interactor) config.interactor = checkFile(cfg.interactor, 'Cannot find interactor {0}.');
|
if (cfg.interactor) config.interactor = checkFile(cfg.interactor, 'Cannot find interactor {0}.');
|
||||||
if (cfg.validator) config.validator = checkFile(cfg.validator, 'Cannot find validator {0}.');
|
if (cfg.validator) config.validator = checkFile(cfg.validator, 'Cannot find validator {0}.');
|
||||||
|
|||||||
@@ -28,8 +28,7 @@ String.random = function random(digit = 32, dict = defaultDict) {
|
|||||||
return str;
|
return str;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!String.prototype.format) {
|
String.prototype.format ||= function formatStr(...args) {
|
||||||
String.prototype.format = function formatStr(...args) {
|
|
||||||
let result = this;
|
let result = this;
|
||||||
if (args.length) {
|
if (args.length) {
|
||||||
if (args.length === 1 && typeof args[0] === 'object') {
|
if (args.length === 1 && typeof args[0] === 'object') {
|
||||||
@@ -44,7 +43,6 @@ if (!String.prototype.format) {
|
|||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
|
||||||
String.prototype.formatFromArray = function formatStr(args) {
|
String.prototype.formatFromArray = function formatStr(args) {
|
||||||
let result = this;
|
let result = this;
|
||||||
|
|||||||
@@ -34,13 +34,13 @@ export function parseLang(config: string): Record<string, LangConfig> {
|
|||||||
}
|
}
|
||||||
for (const key in file) {
|
for (const key in file) {
|
||||||
const entry = file[key];
|
const entry = file[key];
|
||||||
entry.highlight = entry.highlight || key;
|
entry.highlight ||= key;
|
||||||
entry.monaco = entry.monaco || entry.highlight;
|
entry.monaco ||= entry.highlight;
|
||||||
entry.time_limit_rate = entry.time_limit_rate || 1;
|
entry.time_limit_rate ||= 1;
|
||||||
entry.code_file = entry.code_file || `foo.${key}`;
|
entry.code_file ||= `foo.${key}`;
|
||||||
entry.execute = entry.execute || '/w/foo';
|
entry.execute ||= '/w/foo';
|
||||||
entry.key = key;
|
entry.key = key;
|
||||||
entry.hidden = entry.hidden || false;
|
entry.hidden ||= false;
|
||||||
}
|
}
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user