fix ci issues

This commit is contained in:
undefined committed 2025-04-02 00:35:45 +08:00
1 parent 466bc984bd
commit 8af621222c
26 files changed
+108 -85

No files matched your search

+3 -6
View File
@@ -123,9 +123,7 @@ export async function load(ctx: Context) {
ctx.loader.reloadPlugin(require.resolve('../service/server'), 'server'),
]);
require('../lib/index');
await Promise.all([
service(pending, fail, ctx),
]);
await service(pending, fail, ctx);
await builtinModel(ctx);
await model(pending, fail, ctx);
ctx = await new Promise((resolve) => {
@@ -135,8 +133,7 @@ export async function load(ctx: Context) {
});
await addon(pending, fail, ctx);
const scriptDir = path.resolve(__dirname, '..', 'script');
for (const h of await fs.readdir(scriptDir)) {
ctx.loader.reloadPlugin(path.resolve(scriptDir, h), '');
}
await Promise.all((await fs.readdir(scriptDir))
.map((h) => ctx.loader.reloadPlugin(path.resolve(scriptDir, h), '')));
await cli();
}
+6 -11
View File
@@ -49,7 +49,7 @@ export async function apply(ctx: Context) {
resolve(c);
});
});
await require('../service/api').apply(ctx);
await ctx.plugin(require('../service/api'));
require('../lib/index');
ctx.plugin(require('../service/monitor'));
@@ -62,17 +62,12 @@ export async function apply(ctx: Context) {
resolve(c);
});
});
const handlerDir = path.resolve(__dirname, '..', 'handler');
const handlers = await fs.readdir(handlerDir);
for (const h of handlers.filter((i) => i.endsWith('.ts'))) {
ctx.loader.reloadPlugin(path.resolve(handlerDir, h), '');
}
ctx.plugin(require('../service/migration').default);
const loadDir = async (dir: string) => Promise.all((await fs.readdir(dir)).filter((i) => i.endsWith('.ts'))
.map((h) => ctx.loader.reloadPlugin(path.resolve(dir, h), '')));
await loadDir(path.resolve(__dirname, '..', 'handler'));
await ctx.plugin(require('../service/migration').default);
await addon(pending, fail, ctx);
const scriptDir = path.resolve(__dirname, '..', 'script');
for (const h of await fs.readdir(scriptDir)) {
ctx.loader.reloadPlugin(path.resolve(scriptDir, h), '');
}
await loadDir(path.resolve(__dirname, '..', 'script'));
await ctx.parallel('app/started');
if (process.env.NODE_APP_INSTANCE === '0') {
await new Promise((resolve, reject) => {
+2 -2
View File
@@ -254,9 +254,9 @@ class HomeSecurityHandler extends Handler {
@param('platform', Types.String)
async postLinkAccount({ }, platform: string) {
if (!global.Hydro.module.oauth[platform]) throw new ValidationError('platform');
if (!this.ctx.oauth.providers[platform]) throw new ValidationError('platform');
this.session.oauthBind = platform;
await global.Hydro.module.oauth[platform].get.call(this);
await this.ctx.oauth.providers[platform].get.call(this);
}
@param('tokenDigest', Types.String)
+4 -4
View File
@@ -115,7 +115,7 @@ export class JudgeResultCallbackContext {
return this.operationPromise;
}
static async postJudge(rdoc: RecordDoc) {
static async postJudge(rdoc: RecordDoc, context?: JudgeResultCallbackContext) {
if (rdoc.contest?.toString().startsWith('0'.repeat(23))) return;
const accept = rdoc.status === builtin.STATUS.STATUS_ACCEPTED;
const updated = await problem.updateStatus(rdoc.domainId, rdoc.pid, rdoc.uid, rdoc._id, rdoc.status, rdoc.score);
@@ -134,7 +134,7 @@ export class JudgeResultCallbackContext {
problem.inc(pdoc.domainId, pdoc.docId, `stats.s${Math.floor(rdoc.score)}`, 1),
]);
}
await app.parallel('record/judge', rdoc, updated, pdoc, this);
await app.parallel('record/judge', rdoc, updated, pdoc, context);
}
async _end(body: Partial<JudgeResultBody>) {
@@ -155,7 +155,7 @@ export class JudgeResultCallbackContext {
const rdoc = await record.update(this.task.domainId, new ObjectId(this.task.rid as string), $set, $push, $unset);
if (rdoc) bus.broadcast('record/change', rdoc, null, null, body); // trigger a full update
await JudgeResultCallbackContext.postJudge(rdoc);
await JudgeResultCallbackContext.postJudge(rdoc, this);
this.resolve(rdoc);
}
@@ -357,7 +357,7 @@ export async function apply(ctx: Context) {
const priority = await record.submissionPriority(rdoc.uid, -5000 - rdocs.length * 5 - 50);
await record.judge(rdoc.domainId, rdocs.map((r) => r._id), priority, {}, { hackRejudge: input });
} catch (e) {
t.next({
t?.next?.({
rid: rdoc._id.toString(),
domainId: rdoc.domainId,
key: 'next',
+19 -7
View File
@@ -4,7 +4,8 @@ import moment from 'moment-timezone';
import type { Binary } from 'mongodb';
import type { Context } from '../context';
import {
AuthOperationError, BadRequestError, BlacklistedError, BuiltinLoginError, ForbiddenError, InvalidTokenError,
AuthOperationError, BadRequestError, BlacklistedError, BuiltinLoginError,
ForbiddenError, InvalidTokenError, NotFoundError,
SystemError, UserAlreadyExistError, UserFacingError,
UserNotFoundError, ValidationError, VerifyPasswordError,
} from '../error';
@@ -279,9 +280,9 @@ class UserRegisterWithCodeHandler extends Handler {
domainId: string, password: string, verify: string,
uname = '', code: string,
) {
if (global.Hydro.module.oauth[this.tdoc.identity.provider].lockUsername) {
uname = this.tdoc.identity.username;
}
const provider = this.ctx.oauth.providers[this.tdoc.identity.provider];
if (!provider) throw new SystemError(`OAuth provider ${this.tdoc.identity.provider} not found`);
if (provider.lockUsername) uname = this.tdoc.identity.username;
if (!Types.Username[1](uname)) throw new ValidationError('uname');
if (password !== verify) throw new VerifyPasswordError();
const randomEmail = `${String.random(12)}@invalid.local`; // some random email to remove in the future
@@ -428,7 +429,7 @@ class OauthHandler extends Handler {
@param('type', Types.Key)
async get(domainId: string, type: string) {
await global.Hydro.module.oauth[type]?.get.call(this);
await this.ctx.oauth.providers[type]?.get.call(this);
}
}
@@ -436,8 +437,8 @@ class OauthCallbackHandler extends Handler {
noCheckPermView = true;
async get(args: any) {
if (!global.Hydro.module.oauth[args.type]) throw new UserFacingError('Oauth type');
const r = await global.Hydro.module.oauth[args.type].callback.call(this, args);
if (!this.ctx.oauth.providers[args.type]) throw new UserFacingError('Oauth type');
const r = await this.ctx.oauth.providers[args.type].callback.call(this, args);
if (this.session.oauthBind === args.type) {
delete this.session.oauthBind;
const existing = await this.ctx.oauth.get(args.type, r._id);
@@ -529,6 +530,17 @@ export async function apply(ctx: Context) {
if (system.get('server.contestmode')) {
ctx.Route('contest_mode', '/contestmode', ContestModeHandler, PRIV.PRIV_EDIT_SYSTEM);
}
ctx.oauth.provide('mail', {
text: 'Mail',
name: 'mail',
hidden: true,
async get() {
throw new NotFoundError();
},
async callback() {
throw new NotFoundError();
},
});
ctx.inject(['api'], ({ api }) => {
api.value('User', [
['_id', 'Int!'],
+1 -21
View File
@@ -10,7 +10,6 @@ import type { Context } from './context';
import type { DocStatusType } from './model/document';
import type { OauthMap } from './model/oauth';
import type { ProblemDoc } from './model/problem';
import type { Handler } from './service/server';
export * from '@hydrooj/common/types';
@@ -56,17 +55,6 @@ export interface Setting {
flag: number,
}
export interface OAuthUserResponse {
_id: string;
email: string;
avatar?: string;
bio?: string;
uname?: string[];
viewLang?: string;
set?: Record<string, any>;
setInDomain?: Record<string, any>;
}
export interface Authenticator {
name: string;
regat: number;
@@ -506,7 +494,7 @@ export interface OpCountDoc {
opcount: number;
}
export type { OauthMap } from './model/oauth';
export type { OauthMap, OAuthProvider, OAuthUserResponse } from './model/oauth';
export interface DiscussionHistoryDoc {
title?: string;
@@ -622,14 +610,6 @@ export interface UI {
}
export interface ModuleInterfaces {
oauth: {
text: string;
name: string;
icon?: string;
get: (this: Handler) => Promise<void>;
callback: (this: Handler, args: Record<string, any>) => Promise<OAuthUserResponse>;
lockUsername?: boolean;
};
hash: (password: string, salt: string, user: User) => boolean | string | Promise<string>;
problemSearch: ProblemSearch;
}
+33 -1
View File
@@ -1,5 +1,6 @@
import { Collection } from 'mongodb';
import { Context, Service } from '../context';
import type { Handler } from '../service/server';
export interface OauthMap {
platform: string;
@@ -15,9 +16,31 @@ declare module '../context' {
}
}
export interface OAuthUserResponse {
_id: string;
email: string;
avatar?: string;
bio?: string;
uname?: string[];
viewLang?: string;
set?: Record<string, any>;
setInDomain?: Record<string, any>;
}
export interface OAuthProvider {
text: string;
name: string;
icon?: string;
hidden?: boolean;
get: (this: Handler) => Promise<void>;
callback: (this: Handler, args: Record<string, any>) => Promise<OAuthUserResponse>;
lockUsername?: boolean;
}
export default class OauthModel extends Service {
static inject = ['db'];
coll: Collection<OauthMap>;
providers: Record<string, OAuthProvider> = Object.create(null);
constructor(ctx: Context) {
super(ctx, 'oauth');
@@ -29,7 +52,6 @@ export default class OauthModel extends Service {
// { key: { platform: 1, id: 1 }, name: 'platform_id', unique: true },
{ key: { uid: 1, platform: 1 }, name: 'uid_platform' },
);
console.log('oauth init');
}
async get(platform: string, id: string) {
@@ -54,4 +76,14 @@ export default class OauthModel extends Service {
async list(uid: number) {
return this.coll.find({ uid }).toArray();
}
async provide(name: string, provider: OAuthProvider) {
if (this.providers[name]) throw new Error(`OAuth provider ${name} already exists`);
this.ctx.effect(() => {
this.providers[name] = provider;
return () => {
delete this.providers[name];
};
});
}
}
+1 -1
View File
@@ -194,7 +194,7 @@ class ApiService extends Service {
}
export const sideEffect = true;
export const inject = ['server'];
export const inject = ['server', 'setting'];
export function apply(ctx: Context) {
ctx.plugin(ApiService);
+1 -1
View File
@@ -90,7 +90,7 @@ export interface EventMap {
'training/get': (tdoc: TrainingDoc, handler: any) => VoidReturn
'record/change': (rdoc: RecordDoc, $set?: any, $push?: any, body?: any) => void
'record/judge': (rdoc: RecordDoc, updated: boolean, pdoc: ProblemDoc, updater: any) => VoidReturn
'record/judge': (rdoc: RecordDoc, updated: boolean, pdoc?: ProblemDoc, updater?: any) => VoidReturn
}
export function apply(ctx: Context) {
+9 -9
View File
@@ -90,7 +90,7 @@ export async function apply(ctx: Context) {
xhost: system.get('server.xhost'),
});
if (process.env.HYDRO_CLI) return;
ctx.inject(['server'], ({ server, on }) => {
ctx.inject(['server', 'oauth'], ({ server, on, oauth }) => {
server.addHandlerLayer('init', async (c, next) => {
const init = Date.now();
try {
@@ -119,7 +119,7 @@ export async function apply(ctx: Context) {
server.addLayer('base', baseLayer);
server.addLayer('user', userLayer);
let cachedTranslate = null;
const cachedTranslate = ctx.i18n.translate;
server.handlerMixin({
url(name: string, ...kwargsList: Record<string, any>[]) {
@@ -164,7 +164,6 @@ export async function apply(ctx: Context) {
const langs = lang
? [lang, ...this.context.acceptsLanguages()]
: [...this.context.acceptsLanguages(), system.get('server.language')];
cachedTranslate ||= ctx.i18n.translate;
return cachedTranslate(str.toString(), langs);
},
paginate<T>(cursor: FindCursor<T>, page: number, key: string | number) {
@@ -259,12 +258,13 @@ export async function apply(ctx: Context) {
});
on('handler/create/http', async (h) => {
if (!argv.options.benchmark && !h.notUsage) await h.limitRate('global', 5, 100);
h.loginMethods = Object.keys(global.Hydro.module.oauth)
.map((key) => ({
id: key,
icon: global.Hydro.module.oauth[key].icon,
text: global.Hydro.module.oauth[key].text,
name: global.Hydro.module.oauth[key].name,
h.loginMethods = Object.entries(oauth.providers)
.filter(([_, v]) => !v.hidden)
.map(([k, v]) => ({
id: k,
icon: v.icon,
text: v.text,
name: v.name,
}));
if (!h.noCheckPermView && !h.user.hasPriv(PRIV.PRIV_VIEW_ALL_DOMAIN)) h.checkPerm(PERM.PERM_VIEW);
if (h.context.pendingError) throw h.context.pendingError;