From 31ac0fb6669363f8a41d6e6a8e33f6967d7b5e2a Mon Sep 17 00:00:00 2001 From: undefined Date: Sun, 22 Jun 2025 02:50:09 +0800 Subject: [PATCH] core: move message notification to home handler --- framework/framework/server.ts | 1 - packages/hydrooj/src/handler/connection.ts | 38 +--------------- packages/hydrooj/src/handler/home.ts | 51 +++++++++++++++------- packages/hydrooj/src/plugin-api.ts | 1 + packages/hydrooj/src/service/server.ts | 2 +- 5 files changed, 39 insertions(+), 54 deletions(-) diff --git a/framework/framework/server.ts b/framework/framework/server.ts index 67e5b1469..aee61b47f 100644 --- a/framework/framework/server.ts +++ b/framework/framework/server.ts @@ -214,7 +214,6 @@ export class Handler extends HandlerCommon { static [kHandler] = 'Handler'; loginMethods: any; - noCheckPermView = false; notUsage = false; allowCors = false; __param: Record[]>; diff --git a/packages/hydrooj/src/handler/connection.ts b/packages/hydrooj/src/handler/connection.ts index a3b792319..1074468d3 100644 --- a/packages/hydrooj/src/handler/connection.ts +++ b/packages/hydrooj/src/handler/connection.ts @@ -1,7 +1,5 @@ import { Context } from '../context'; import { ForbiddenError } from '../error'; -import avatar from '../lib/avatar'; -import { PRIV } from '../model/builtin'; import * as SystemModel from '../model/system'; import TokenModel from '../model/token'; import UserModel from '../model/user'; @@ -43,7 +41,6 @@ class WebsocketEventsConnectionManagerHandler extends ConnectionHandler { } async message(payload: any) { - console.log(payload); try { if (['resume', 'subscribe'].includes(payload.operation)) await this.subscribe(payload); if (payload.operation === 'unsubscribe') await this.unsubscribe(payload); @@ -98,6 +95,7 @@ class WebsocketEventsConnectionManagerHandler extends ConnectionHandler { operation: 'verify', accept, reject, + request_id: payload.request_id, subscription_id: payload.subscription_id, }); } @@ -112,38 +110,4 @@ class WebsocketEventsConnectionManagerHandler extends ConnectionHandler { export function apply(ctx: Context) { ctx.Connection('websocket_gateway', '/websocket', WebsocketEventsConnectionManagerHandler); - - async function notifyMessage(uid: number[], mdoc: any, h) { - const udoc = (await UserModel.getById('system', mdoc.from))!; - return { - operation: 'event', - channels: uid.map((u) => `message:${u}`), - payload: { udoc: { ...udoc.serialize(h) as any, avatarUrl: avatar(udoc.avatar, 128) }, mdoc }, - }; - } - - ctx.on('subscription/init', (h, privileged) => { - if (!privileged) return; - h.ctx.on('user/message', async (uid, mdoc) => { - h.send(await notifyMessage(uid, mdoc, h)); - }); - }); - - ctx.on('subscription/enable', (channel, h, privileged) => { - if (!channel.startsWith('message:') || privileged) return; - const uid = +channel.split(':')[1]; - h.ctx.on('user/message', async (uids, mdoc) => { - if (!uids.includes(uid)) return; - h.send(await notifyMessage([uid], mdoc, h)); - }); - }); - - ctx.on('subscription/subscribe', (channel, user) => { // eslint-disable-line consistent-return - if (channel === 'message' && user.hasPriv(PRIV.PRIV_USER_PROFILE)) { - return { - ok: true, - channel: `message:${user._id}`, - }; - } - }); } diff --git a/packages/hydrooj/src/handler/home.ts b/packages/hydrooj/src/handler/home.ts index 892b5ff10..c4d9f8262 100644 --- a/packages/hydrooj/src/handler/home.ts +++ b/packages/hydrooj/src/handler/home.ts @@ -11,7 +11,7 @@ import { NotFoundError, PermissionError, UserAlreadyExistError, UserNotFoundError, ValidationError, VerifyPasswordError, } from '../error'; -import { DomainDoc, MessageDoc, Setting } from '../interface'; +import { DomainDoc, Setting } from '../interface'; import avatar, { validate } from '../lib/avatar'; import * as mail from '../lib/mail'; import { verifyTFA } from '../lib/verifyTFA'; @@ -29,7 +29,7 @@ import token from '../model/token'; import * as training from '../model/training'; import user from '../model/user'; import { - ConnectionHandler, Handler, param, query, requireSudo, subscribe, Types, + Handler, param, query, requireSudo, Types, } from '../service/server'; import { camelCase, md5 } from '../utils'; @@ -608,18 +608,6 @@ class HomeMessagesHandler extends Handler { } } -class HomeMessagesConnectionHandler extends ConnectionHandler { - category = '#message'; - - @subscribe('user/message') - async onMessageReceived(uid: number, mdoc: MessageDoc) { - if (uid !== this.user._id) return; - const udoc = (await user.getById(this.args.domainId, mdoc.from))!; - udoc.avatarUrl = avatar(udoc.avatar, 64); - this.send({ udoc, mdoc }); - } -} - export const inject = { geoip: { required: false }, oauth: {} }; export function apply(ctx: Context) { ctx.Route('homepage', '/', HomeHandler); @@ -630,5 +618,38 @@ export function apply(ctx: Context) { ctx.Route('home_domain', '/home/domain', HomeDomainHandler, PRIV.PRIV_USER_PROFILE); ctx.Route('home_domain_create', '/home/domain/create', HomeDomainCreateHandler, PRIV.PRIV_CREATE_DOMAIN); ctx.Route('home_messages', '/home/messages', HomeMessagesHandler, PRIV.PRIV_USER_PROFILE); - ctx.Connection('home_messages_conn', '/home/messages-conn', HomeMessagesConnectionHandler, PRIV.PRIV_USER_PROFILE); + + async function notifyMessage(uid: number[], mdoc: any, h) { + const udoc = (await user.getById('system', mdoc.from))!; + return { + operation: 'event', + channels: uid.map((u) => `message:${u}`), + payload: { udoc: { ...udoc.serialize(h) as any, avatarUrl: avatar(udoc.avatar, 128) }, mdoc }, + }; + } + + ctx.on('subscription/init', (h, privileged) => { + if (!privileged) return; + h.ctx.on('user/message', async (uid, mdoc) => { + h.send(await notifyMessage(uid, mdoc, h)); + }); + }); + + ctx.on('subscription/enable', (channel, h, privileged) => { + if (!channel.startsWith('message:') || privileged) return; + const uid = +channel.split(':')[1]; + h.ctx.on('user/message', async (uids, mdoc) => { + if (!uids.includes(uid)) return; + h.send(await notifyMessage([uid], mdoc, h)); + }); + }); + + ctx.on('subscription/subscribe', (channel, udoc) => { // eslint-disable-line consistent-return + if (channel === 'message' && udoc.hasPriv(PRIV.PRIV_USER_PROFILE)) { + return { + ok: true, + channel: `message:${udoc._id}`, + }; + } + }); } diff --git a/packages/hydrooj/src/plugin-api.ts b/packages/hydrooj/src/plugin-api.ts index 3cc4ea6a6..58cebb39d 100644 --- a/packages/hydrooj/src/plugin-api.ts +++ b/packages/hydrooj/src/plugin-api.ts @@ -6,6 +6,7 @@ export { default as moment, isMoment } from 'moment-timezone'; export { WebService, Router, HandlerCommon, httpServer, + Query, Mutation, Subscription, Apis, } from '@hydrooj/framework'; export * from './pipelineUtils'; diff --git a/packages/hydrooj/src/service/server.ts b/packages/hydrooj/src/service/server.ts index 089ca369a..354076ade 100644 --- a/packages/hydrooj/src/service/server.ts +++ b/packages/hydrooj/src/service/server.ts @@ -271,7 +271,7 @@ export async function apply(ctx: Context) { text: v.text, name: v.name, })); - if (!h.noCheckPermView && !h.user.hasPriv(PRIV.PRIV_VIEW_ALL_DOMAIN)) h.checkPerm(PERM.PERM_VIEW); + if ((!('noCheckPermView' in h) || !h.noCheckPermView) && !h.user.hasPriv(PRIV.PRIV_VIEW_ALL_DOMAIN)) h.checkPerm(PERM.PERM_VIEW); if (h.context.pendingError) throw h.context.pendingError; }); on('handler/create/ws', async (h) => {