Ground-Zerro / Phobos Public
Code Issues Pull requests Actions Releases View on GitHub ↗
1.5 KB typescript
import { Secret, TOTP } from 'otpauth';
import { UserUpdateTotpSchema } from '#db/repositories/user/types';

type Response =
  | {
      success: boolean;
      type: 'setup';
      key: string;
      uri: string;
    }
  | { success: boolean; type: 'created' }
  | { success: boolean; type: 'deleted' };

export default definePermissionEventHandler(
  'me',
  'update',
  async ({ event, user, checkPermissions }) => {
    const body = await readValidatedBody(
      event,
      validateZod(UserUpdateTotpSchema, event)
    );

    checkPermissions(user);

    if (body.type === 'setup') {
      const key = new Secret({ size: 20 });

      const totp = new TOTP({
        issuer: TOTP_ISSUER,
        label: user.username,
        algorithm: 'SHA1',
        digits: 6,
        period: 30,
        secret: key,
      });

      await Database.users.updateTotpKey(user.id, key.base32);

      return {
        success: true,
        type: 'setup',
        key: key.base32,
        uri: totp.toString(),
      } as Response;
    } else if (body.type === 'create') {
      await Database.users.verifyTotp(user.id, body.code);

      return {
        success: true,
        type: 'created',
      } as Response;
    } else if (body.type === 'delete') {
      await Database.users.deleteTotpKey(user.id, body.currentPassword);

      return {
        success: true,
        type: 'deleted',
      } as Response;
    }
    throw createError({
      statusCode: 400,
      statusMessage: 'Invalid request',
    });
  }
);