mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-12 13:38:31 +09:00
61 lines
2.4 KiB
TypeScript
61 lines
2.4 KiB
TypeScript
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
|
|
import type {ApiContext} from '@app/api/ApiContext';
|
|
import {mapUserToAdminResponse} from '@app/api/admin/models/UserTypes';
|
|
import {createUserID} from '@app/api/BrandedTypes';
|
|
import {isSyntheticUserId} from '@app/api/constants/Core';
|
|
import {usesUniqueUsernames} from '@app/api/instance/AccountIdentityModeCache';
|
|
import {Logger} from '@app/api/Logger';
|
|
import type {User} from '@app/api/models/User';
|
|
import {findPersonByLoginHandle, parseLoginHandle} from '@app/api/user/UniqueUsernames';
|
|
import type {LookupUserRequest} from '@fluxer/schema/src/domains/admin/AdminUserSchemas';
|
|
|
|
interface AdminUserLookupServiceDeps {
|
|
apiContext: ApiContext;
|
|
}
|
|
|
|
export class AdminUserLookupService {
|
|
constructor(private readonly deps: AdminUserLookupServiceDeps) {}
|
|
|
|
async lookupUser(data: LookupUserRequest, acls: ReadonlySet<string>) {
|
|
const {users: userRepository, cache: cacheService} = this.deps.apiContext.services;
|
|
if ('user_ids' in data) {
|
|
const userIds = data.user_ids.map((id) => createUserID(id));
|
|
const users = await userRepository.listUsers(userIds);
|
|
return {
|
|
users: await Promise.all(users.map((user) => mapUserToAdminResponse(user, cacheService, acls))),
|
|
};
|
|
}
|
|
let user = null;
|
|
const query = data.query.trim();
|
|
const fluxerTagMatch = query.match(/^(.+)#(\d{1,4})$/);
|
|
if (fluxerTagMatch) {
|
|
const username = fluxerTagMatch[1];
|
|
const discriminator = parseInt(fluxerTagMatch[2], 10);
|
|
user = await userRepository.findByUsernameDiscriminator(username, discriminator);
|
|
} else if (/^\d+$/.test(query)) {
|
|
try {
|
|
const userId = createUserID(BigInt(query));
|
|
user = isSyntheticUserId(userId) ? null : await userRepository.findUnique(userId);
|
|
} catch (error) {
|
|
Logger.debug({query, error}, 'Failed to lookup user by numeric ID, invalid ID format');
|
|
user = null;
|
|
}
|
|
} else if (query.includes('@')) {
|
|
user = await userRepository.findByEmail(query);
|
|
} else {
|
|
user = (await this.findPersonByBareUsername(query)) ?? (await userRepository.findByStripeSubscriptionId(query));
|
|
}
|
|
return {
|
|
users: user ? [await mapUserToAdminResponse(user, cacheService, acls)] : [],
|
|
};
|
|
}
|
|
|
|
private async findPersonByBareUsername(query: string): Promise<User | null> {
|
|
if (!usesUniqueUsernames()) return null;
|
|
const handle = parseLoginHandle(query);
|
|
if (!handle || handle.discriminator !== null) return null;
|
|
return await findPersonByLoginHandle(this.deps.apiContext.services.users, handle);
|
|
}
|
|
}
|