(refactor) move /api/admin/authenticators/:id to own file and improve its typings

This commit is contained in:
Valentyne Stigloher 2025-07-04 17:25:46 +02:00
parent aa54bdd647
commit 57f376e5ee
5 changed files with 44 additions and 30 deletions

View File

@ -14,6 +14,7 @@ import { sleep } from '~/src/helpers.ts';
import opinions from '~/src/opinions.ts';
import { applyProfileVisibilityRules } from '~/src/profile.ts';
import type { UserWithProfiles, Profile } from '~/src/profile.ts';
import type { Authenticator } from '~/src/user.ts';
definePageMeta({
translatedPaths: (config) => {
@ -96,7 +97,7 @@ const cardsEnabled = ref(true);
const contentWarningDismissed = ref(false);
const authenticators = ref<any[] | undefined>();
const authenticators = ref<Omit<Authenticator, 'userId'>[] | undefined>();
const showExpiredAuthenticators = ref(false);
const allProfiles = computed((): Record<string, LocaleDescription> => {

View File

@ -0,0 +1,33 @@
import SQL from 'sql-template-strings';
import type { AuthenticatorRow } from '~/server/express/user.ts';
import { filterObjectKeys } from '~/src/helpers.ts';
import type { Authenticator } from '~/src/user.ts';
export default defineEventHandler(async (event) => {
const { isGranted } = await useAuthentication(event);
if (!isGranted('community') && !isGranted('*')) {
throw createError({
status: 401,
statusMessage: 'Unauthorised',
});
}
const db = useDatabase();
const id = getRouterParam(event, 'id');
return (await db.all<AuthenticatorRow>(SQL`
SELECT * FROM authenticators
WHERE userId = ${id}
ORDER BY id DESC
`)).map((authenticatorRow): Omit<Authenticator, 'userId'> => {
const payload = JSON.parse(authenticatorRow.payload);
return {
id: authenticatorRow.id,
type: authenticatorRow.type,
payload: typeof payload === 'string'
? ''
: filterObjectKeys(payload, ['id', 'email', 'name', 'instance', 'username']),
validUntil: authenticatorRow.validUntil,
};
});
});

View File

@ -498,28 +498,4 @@ router.get('/admin/audit-log/:username/:id', handleErrorAsync(async (req, res) =
return res.json(await fetchAuditLog(req.params.username, req.params.id, req.params.id));
}));
router.get('/admin/authenticators/:id', handleErrorAsync(async (req, res) => {
if (!req.isGranted('community') && !req.isGranted('*')) {
return res.status(401).json({ error: 'Unauthorised' });
}
const authenticators = (await req.db.all<Partial<AuthenticatorRow>>(SQL`
SELECT * FROM authenticators
WHERE userId = ${req.params.id}
ORDER BY id DESC
`)).map((auth) => {
delete auth.userId;
const payload = JSON.parse(auth.payload!);
// @ts-expect-error This error really doesn't need to exist as the code handles this correctly
auth.payload = typeof payload === 'string'
? undefined
: filterObjectKeys(payload, ['id', 'email', 'name', 'instance', 'username']);
return auth;
});
return res.json(authenticators);
}));
export default router;

View File

@ -17,7 +17,7 @@ import {
obfuscateEmail,
newDate,
} from '../../src/helpers.ts';
import type { User } from '../../src/user.ts';
import type { Authenticator, User } from '../../src/user.ts';
import { usernameRegex, usernameUnsafeRegex } from '../../src/username.ts';
import { auditLog } from '../audit.ts';
import avatar from '../avatar.ts';
@ -69,10 +69,6 @@ export interface AuthenticatorRow {
validUntil: number | null;
}
interface Authenticator extends Omit<AuthenticatorRow, 'payload'> {
payload: string | Record<string, string>;
}
export const normalise = (s: string): string => s.trim().toLowerCase();
const isSpam = (email: string): boolean => {

View File

@ -39,3 +39,11 @@ export interface Admin {
credentialsLevel: number | null;
credentialsName: string | null;
}
export interface Authenticator {
id: string;
userId: string | null;
type: string;
payload: string | Record<string, string>;
validUntil: number | null;
}