snapshot of https://github.com/RocketChat/Rocket.Chat.git (develop, 2026-09-16; blobs > 131072B omitted)
Some checks failed
Create issues from TODOs / todos (push) Failing after 3s
Close inactive issues / close-issues (push) Has been cancelled
Deploy GitHub Pages / deploy-preview (push) Has been cancelled
CI / ⚙️ Variables Setup (push) Has been cancelled
CI / ⚙️ Test Guard (push) Has been cancelled
CI / 🚀 Notify external services - draft (push) Has been cancelled
CI / 📦 Build Packages (push) Has been cancelled
CI / 📦 Meteor Build (coverage) (push) Has been cancelled
CI / 📦 Meteor Build (production) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], fips) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Publish Docker Images (ghcr.io) (push) Has been cancelled
CI / 📦 Track Image Sizes (push) Has been cancelled
CI / 🔎 Code Check - Action Lint (push) Has been cancelled
CI / 🔎 Code Check (push) Has been cancelled
CI / 🔨 Test Storybook (push) Has been cancelled
CI / 🔨 Test Unit (push) Has been cancelled
CI / 🔨 Test API (CE) (push) Has been cancelled
CI / 🔨 Test API Livechat (CE) (push) Has been cancelled
CI / 🔨 Test UI (CE) (push) Has been cancelled
CI / 🔨 Test API (EE) (push) Has been cancelled
CI / 🔨 Test API Livechat (EE) (push) Has been cancelled
CI / 🔨 Test API Apps (deno-runtime - EE) (push) Has been cancelled
CI / 🔨 Test UI (EE) (push) Has been cancelled
CI / 🔨 Test API (FIPS) (push) Has been cancelled
CI / 🔨 Test API Livechat (FIPS) (push) Has been cancelled
CI / 🔨 Test UI (FIPS) (push) Has been cancelled
CI / 🔨 Test Federation Matrix (push) Has been cancelled
CI / 📊 Report Coverage (push) Has been cancelled
CI / ✅ Tests Done (push) Has been cancelled
CI / 🚀 Publish build assets (push) Has been cancelled
CI / 🚀 Publish Docker Images (DockerHub) (push) Has been cancelled
CI / 🚀 Notify external services (push) Has been cancelled
CI / Update Version Durability (push) Has been cancelled
Release / Release (push) Has been cancelled
Auto-close duplicate issues / auto-close-duplicates (push) Failing after 1s
Code scanning - action / CodeQL-Build (push) Failing after 1s
Some checks failed
Create issues from TODOs / todos (push) Failing after 3s
Close inactive issues / close-issues (push) Has been cancelled
Deploy GitHub Pages / deploy-preview (push) Has been cancelled
CI / ⚙️ Variables Setup (push) Has been cancelled
CI / ⚙️ Test Guard (push) Has been cancelled
CI / 🚀 Notify external services - draft (push) Has been cancelled
CI / 📦 Build Packages (push) Has been cancelled
CI / 📦 Meteor Build (coverage) (push) Has been cancelled
CI / 📦 Meteor Build (production) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], fips) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Publish Docker Images (ghcr.io) (push) Has been cancelled
CI / 📦 Track Image Sizes (push) Has been cancelled
CI / 🔎 Code Check - Action Lint (push) Has been cancelled
CI / 🔎 Code Check (push) Has been cancelled
CI / 🔨 Test Storybook (push) Has been cancelled
CI / 🔨 Test Unit (push) Has been cancelled
CI / 🔨 Test API (CE) (push) Has been cancelled
CI / 🔨 Test API Livechat (CE) (push) Has been cancelled
CI / 🔨 Test UI (CE) (push) Has been cancelled
CI / 🔨 Test API (EE) (push) Has been cancelled
CI / 🔨 Test API Livechat (EE) (push) Has been cancelled
CI / 🔨 Test API Apps (deno-runtime - EE) (push) Has been cancelled
CI / 🔨 Test UI (EE) (push) Has been cancelled
CI / 🔨 Test API (FIPS) (push) Has been cancelled
CI / 🔨 Test API Livechat (FIPS) (push) Has been cancelled
CI / 🔨 Test UI (FIPS) (push) Has been cancelled
CI / 🔨 Test Federation Matrix (push) Has been cancelled
CI / 📊 Report Coverage (push) Has been cancelled
CI / ✅ Tests Done (push) Has been cancelled
CI / 🚀 Publish build assets (push) Has been cancelled
CI / 🚀 Publish Docker Images (DockerHub) (push) Has been cancelled
CI / 🚀 Notify external services (push) Has been cancelled
CI / Update Version Durability (push) Has been cancelled
Release / Release (push) Has been cancelled
Auto-close duplicate issues / auto-close-duplicates (push) Failing after 1s
Code scanning - action / CodeQL-Build (push) Failing after 1s
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
import type { IRoom, IUser } from '@rocket.chat/core-typings';
|
||||
|
||||
import { Callbacks } from './callbacksBase';
|
||||
|
||||
export const afterBanFromRoomCallback =
|
||||
Callbacks.create<(data: { bannedUser: IUser; userWhoBanned: IUser }, room: IRoom) => void>('afterBanFromRoom');
|
||||
@@ -0,0 +1,5 @@
|
||||
import type { IUser, IRoom } from '@rocket.chat/core-typings';
|
||||
|
||||
import { Callbacks } from './callbacksBase';
|
||||
|
||||
export const afterLeaveRoomCallback = Callbacks.create<(data: { user: IUser; kicker?: IUser }, room: IRoom) => void>('afterLeaveRoom');
|
||||
@@ -0,0 +1,4 @@
|
||||
import { Callbacks } from './callbacksBase';
|
||||
|
||||
/** @deprecated - replace with UserProvider onLogout callback */
|
||||
export const afterLogoutCleanUpCallback = Callbacks.create('afterLogoutCleanUp');
|
||||
@@ -0,0 +1,6 @@
|
||||
import type { IRoom, IUser } from '@rocket.chat/core-typings';
|
||||
|
||||
import { Callbacks } from './callbacksBase';
|
||||
|
||||
export const afterRemoveFromRoomCallback =
|
||||
Callbacks.create<(data: { removedUser: IUser; userWhoRemoved: IUser }, room: IRoom) => void>('afterRemoveFromRoom');
|
||||
@@ -0,0 +1,6 @@
|
||||
import type { IRoom, IUser } from '@rocket.chat/core-typings';
|
||||
|
||||
import { Callbacks } from './callbacksBase';
|
||||
|
||||
export const afterUnbanFromRoomCallback =
|
||||
Callbacks.create<(data: { unbannedUser: IUser; userWhoUnbanned: IUser }, room: IRoom) => void>('afterUnbanFromRoom');
|
||||
7
apps/meteor/server/lib/callbacks/beforeAddUserToRoom.ts
Normal file
7
apps/meteor/server/lib/callbacks/beforeAddUserToRoom.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import type { IUser, IRoom } from '@rocket.chat/core-typings';
|
||||
|
||||
import { Callbacks } from './callbacksBase';
|
||||
|
||||
export const beforeAddUserToRoom = Callbacks.create<(args: { user: IUser; inviter?: IUser }, room: IRoom) => void>('beforeAddUserToRoom');
|
||||
export const beforeAddUsersToRoom =
|
||||
Callbacks.create<(args: { usernames: string[]; inviter?: IUser }, room: IRoom) => void>('beforeAddUsersToRoom');
|
||||
8
apps/meteor/server/lib/callbacks/beforeChangeRoomRole.ts
Normal file
8
apps/meteor/server/lib/callbacks/beforeChangeRoomRole.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import type { IRoom } from '@rocket.chat/core-typings';
|
||||
|
||||
import { Callbacks } from './callbacksBase';
|
||||
|
||||
export const beforeChangeRoomRole =
|
||||
Callbacks.create<(args: { fromUserId: string; userId: string; room: IRoom; role: 'moderator' | 'owner' | 'leader' | 'user' }) => void>(
|
||||
'beforeChangeRoomRole',
|
||||
);
|
||||
@@ -0,0 +1,9 @@
|
||||
import type { IRoom, IUser } from '@rocket.chat/core-typings';
|
||||
|
||||
import { Callbacks } from './callbacksBase';
|
||||
|
||||
export const beforeCreateRoomCallback =
|
||||
Callbacks.create<(data: { owner: IUser; room: Omit<IRoom, '_id' | '_updatedAt'> }) => void>('beforeCreateRoom');
|
||||
|
||||
export const prepareCreateRoomCallback =
|
||||
Callbacks.create<(data: { type: IRoom['t']; extraData: Partial<IRoom> }) => void>('prepareCreateRoom');
|
||||
@@ -0,0 +1,3 @@
|
||||
import { Callbacks } from './callbacksBase';
|
||||
|
||||
export const beforeCreateUserCallback = Callbacks.create('beforeCreateUser');
|
||||
@@ -0,0 +1,5 @@
|
||||
import type { IRoom, IUser } from '@rocket.chat/core-typings';
|
||||
|
||||
import { Callbacks } from './callbacksBase';
|
||||
|
||||
export const beforeLeaveRoomCallback = Callbacks.create<(user: IUser, room: IRoom) => void>('beforeLeaveRoom');
|
||||
248
apps/meteor/server/lib/callbacks/callbacksBase.ts
Normal file
248
apps/meteor/server/lib/callbacks/callbacksBase.ts
Normal file
@@ -0,0 +1,248 @@
|
||||
import type { Logger } from '@rocket.chat/logger';
|
||||
import { Random } from '@rocket.chat/random';
|
||||
|
||||
import { compareByRanking } from '../../../lib/utils/comparisons';
|
||||
|
||||
enum CallbackPriority {
|
||||
HIGH = -1000,
|
||||
MEDIUM = 0,
|
||||
LOW = 1000,
|
||||
}
|
||||
|
||||
type Callback<H> = {
|
||||
(item: unknown, constant?: unknown): Promise<unknown>;
|
||||
hook: H;
|
||||
id: string;
|
||||
priority: CallbackPriority;
|
||||
stack: string;
|
||||
};
|
||||
|
||||
type CallbackTracker<H> = (callback: Callback<H>) => () => void;
|
||||
|
||||
type HookTracker<H> = (params: { hook: H; length: number }) => () => void;
|
||||
|
||||
export class Callbacks<
|
||||
TChainedCallbackSignatures extends {
|
||||
[key: string]: (item: any, constant?: any) => any;
|
||||
},
|
||||
TEventLikeCallbackSignatures extends {
|
||||
[key: string]: (item: any, constant?: any) => any;
|
||||
},
|
||||
THook extends string = keyof TChainedCallbackSignatures & keyof TEventLikeCallbackSignatures & string,
|
||||
> {
|
||||
private logger: Logger | undefined = undefined;
|
||||
|
||||
private trackCallback: CallbackTracker<THook> | undefined = undefined;
|
||||
|
||||
private trackHook: HookTracker<THook> | undefined = undefined;
|
||||
|
||||
private callbacks = new Map<THook, Callback<THook>[]>();
|
||||
|
||||
private sequentialRunners = new Map<THook, (item: unknown, constant?: unknown) => Promise<unknown>>();
|
||||
|
||||
private asyncRunners = new Map<THook, (item: unknown, constant?: unknown) => unknown>();
|
||||
|
||||
readonly priority = CallbackPriority;
|
||||
|
||||
setLogger(logger: Logger): void {
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
setMetricsTrackers({ trackCallback, trackHook }: { trackCallback?: CallbackTracker<THook>; trackHook?: HookTracker<THook> }): void {
|
||||
this.trackCallback = trackCallback;
|
||||
this.trackHook = trackHook;
|
||||
}
|
||||
|
||||
private runOne(callback: Callback<THook>, item: unknown, constant: unknown): Promise<unknown> {
|
||||
const stopTracking = this.trackCallback?.(callback);
|
||||
|
||||
return Promise.resolve(callback(item, constant)).finally(stopTracking);
|
||||
}
|
||||
|
||||
private createSequentialRunner(hook: THook, callbacks: Callback<THook>[]): (item: unknown, constant?: unknown) => Promise<unknown> {
|
||||
const wrapCallback =
|
||||
(callback: Callback<THook>) =>
|
||||
async (item: unknown, constant?: unknown): Promise<unknown> => {
|
||||
this.logger?.debug({ msg: 'Executing callback', id: callback.id, hook: callback.hook });
|
||||
|
||||
return (await this.runOne(callback, item, constant)) ?? item;
|
||||
};
|
||||
|
||||
const identity = <TItem>(item: TItem): Promise<TItem> => Promise.resolve(item);
|
||||
|
||||
const pipe =
|
||||
(curr: (item: unknown, constant?: unknown) => Promise<unknown>, next: (item: unknown, constant?: unknown) => Promise<unknown>) =>
|
||||
async (item: unknown, constant?: unknown): Promise<unknown> =>
|
||||
next(await curr(item, constant), constant);
|
||||
|
||||
const fn = callbacks.map(wrapCallback).reduce(pipe, identity);
|
||||
|
||||
return async (item: unknown, constant?: unknown): Promise<unknown> => {
|
||||
const stopTracking = this.trackHook?.({ hook, length: callbacks.length });
|
||||
|
||||
return fn(item, constant).finally(() => stopTracking?.());
|
||||
};
|
||||
}
|
||||
|
||||
private createAsyncRunner(_: THook, callbacks: Callback<THook>[]) {
|
||||
return (item: unknown, constant?: unknown): unknown => {
|
||||
if (typeof window !== 'undefined') {
|
||||
throw new Error('callbacks.runAsync on client server not allowed');
|
||||
}
|
||||
|
||||
for (const callback of callbacks) {
|
||||
setTimeout(() => {
|
||||
void this.runOne(callback, item, constant);
|
||||
}, 0);
|
||||
}
|
||||
|
||||
return item;
|
||||
};
|
||||
}
|
||||
|
||||
getCallbacks(hook: THook): Callback<THook>[] {
|
||||
return this.callbacks.get(hook) ?? [];
|
||||
}
|
||||
|
||||
setCallbacks(hook: THook, callbacks: Callback<THook>[]): void {
|
||||
this.callbacks.set(hook, callbacks);
|
||||
this.sequentialRunners.set(hook, this.createSequentialRunner(hook, callbacks));
|
||||
this.asyncRunners.set(hook, this.createAsyncRunner(hook, callbacks));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a callback function to a hook
|
||||
*
|
||||
* @param hook the name of the hook
|
||||
* @param callback the callback function
|
||||
* @param priority the callback run priority (order)
|
||||
* @param id human friendly name for this callback
|
||||
*/
|
||||
add<Hook extends keyof TEventLikeCallbackSignatures>(
|
||||
hook: Hook,
|
||||
callback: TEventLikeCallbackSignatures[Hook],
|
||||
priority?: CallbackPriority,
|
||||
id?: string,
|
||||
): () => void;
|
||||
|
||||
add<Hook extends keyof TChainedCallbackSignatures>(
|
||||
hook: Hook,
|
||||
callback: TChainedCallbackSignatures[Hook],
|
||||
priority?: CallbackPriority,
|
||||
id?: string,
|
||||
): () => void;
|
||||
|
||||
add<TItem, TConstant, TNextItem = TItem>(
|
||||
hook: THook,
|
||||
callback: (item: TItem, constant?: TConstant) => TNextItem,
|
||||
priority?: CallbackPriority,
|
||||
id?: string,
|
||||
): () => void;
|
||||
|
||||
add(
|
||||
hook: THook,
|
||||
callback: (item: unknown, constant?: unknown) => unknown,
|
||||
priority = this.priority.MEDIUM,
|
||||
id = Random.id(),
|
||||
): () => void {
|
||||
const callbacks = this.getCallbacks(hook);
|
||||
|
||||
if (callbacks.some((cb) => cb.id === id)) {
|
||||
return () => {
|
||||
this.remove(hook, id);
|
||||
};
|
||||
}
|
||||
|
||||
callbacks.push(
|
||||
Object.assign(callback as Callback<THook>, {
|
||||
hook,
|
||||
priority,
|
||||
id,
|
||||
stack: new Error().stack,
|
||||
}),
|
||||
);
|
||||
callbacks.sort(compareByRanking((callback: Callback<THook>): number => callback.priority ?? this.priority.MEDIUM));
|
||||
|
||||
this.setCallbacks(hook, callbacks);
|
||||
|
||||
return () => {
|
||||
this.remove(hook, id);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a callback from a hook
|
||||
*
|
||||
* @param hook the name of the hook
|
||||
* @param id the callback's id
|
||||
*/
|
||||
remove(hook: THook, id: string): void {
|
||||
const hooks = this.getCallbacks(hook).filter((callback) => callback.id !== id);
|
||||
this.setCallbacks(hook, hooks);
|
||||
}
|
||||
|
||||
run<Hook extends keyof TEventLikeCallbackSignatures>(hook: Hook, ...args: Parameters<TEventLikeCallbackSignatures[Hook]>): Promise<void>;
|
||||
|
||||
run<Hook extends keyof TChainedCallbackSignatures>(
|
||||
hook: Hook,
|
||||
...args: Parameters<TChainedCallbackSignatures[Hook]>
|
||||
): Promise<ReturnType<TChainedCallbackSignatures[Hook]>>;
|
||||
|
||||
run<TItem, TConstant, TNextItem = TItem>(hook: THook, item: TItem, constant?: TConstant): Promise<TNextItem>;
|
||||
|
||||
/**
|
||||
* Successively run all of a hook's callbacks on an item
|
||||
*
|
||||
* @param hook the name of the hook
|
||||
* @param item the post, comment, modifier, etc. on which to run the callbacks
|
||||
* @param constant an optional constant that will be passed along to each callback
|
||||
* @returns returns the item after it's been through all the callbacks for this hook
|
||||
*/
|
||||
run(hook: THook, item: unknown, constant?: unknown): Promise<unknown> {
|
||||
const runner = this.sequentialRunners.get(hook) ?? (async (item: unknown, _constant?: unknown): Promise<unknown> => item);
|
||||
return runner(item, constant);
|
||||
}
|
||||
|
||||
runAsync<Hook extends keyof TEventLikeCallbackSignatures>(hook: Hook, ...args: Parameters<TEventLikeCallbackSignatures[Hook]>): void;
|
||||
|
||||
/**
|
||||
* Successively run all of a hook's callbacks on an item, in async mode (only works on server)
|
||||
*
|
||||
* @param hook the name of the hook
|
||||
* @param item the post, comment, modifier, etc. on which to run the callbacks
|
||||
* @param constant an optional constant that will be passed along to each callback
|
||||
* @returns the post, comment, modifier, etc. on which to run the callbacks
|
||||
*/
|
||||
runAsync(hook: THook, item: unknown, constant?: unknown): unknown {
|
||||
const runner = this.asyncRunners.get(hook) ?? ((item: unknown, _constant?: unknown): unknown => item);
|
||||
return runner(item, constant);
|
||||
}
|
||||
|
||||
static create<F extends (item: any, constant?: any) => any | Promise<any>>(
|
||||
hook: string,
|
||||
): Cb<Parameters<F>[0], ReturnType<F>, Parameters<F>[1]>;
|
||||
|
||||
static create<I, R, C = undefined>(hook: string): Cb<I, R, C> {
|
||||
const callbacks = new Callbacks();
|
||||
|
||||
return {
|
||||
add: (callback, priority, id) => callbacks.add(hook as any, callback, priority, id),
|
||||
remove: (id) => callbacks.remove(hook as any, id),
|
||||
run: (item, constant) => callbacks.run(hook as any, item, constant) as any,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback hooks provide an easy way to add extra steps to common operations.
|
||||
* @deprecated
|
||||
*/
|
||||
type Cb<I, R, C = undefined> = {
|
||||
add: (
|
||||
callback: (item: I, constant: C) => Promise<R | undefined | void> | R | undefined | void,
|
||||
priority?: CallbackPriority,
|
||||
id?: string,
|
||||
) => void;
|
||||
remove: (id: string) => void;
|
||||
run: (item: I, constant?: C) => Promise<R>;
|
||||
};
|
||||
@@ -0,0 +1,17 @@
|
||||
import { Callbacks } from './callbacksBase';
|
||||
|
||||
/**
|
||||
* Discriminates what kind of handle is being validated, so handlers can check the right
|
||||
* namespace: `user` for a person's username, `room` for a room/team name. Rooms, teams
|
||||
* and users share one local handle namespace.
|
||||
*/
|
||||
export type UsernameAvailabilityCheckType = 'user' | 'room';
|
||||
|
||||
/**
|
||||
* Runs while validating whether a handle may be used (user creation, SSO/LDAP assignment and
|
||||
* renames, plus room renames and team creation, all funnel through `checkUsernameAvailability`).
|
||||
* Handlers should throw to reject the handle. The `type` tells the handler whether a user or
|
||||
* a room/team is being validated. With no handler registered this is a no-op.
|
||||
*/
|
||||
export const checkUsernameAvailabilityCallback =
|
||||
Callbacks.create<(username: string, type: UsernameAvailabilityCheckType) => void>('checkUsernameAvailability');
|
||||
Reference in New Issue
Block a user