This commit is contained in:
Maieul BOYER 2025-12-01 19:26:22 +01:00
parent e5b71a5cc1
commit c898fe8d32
No known key found for this signature in database
30 changed files with 1148 additions and 95 deletions

View file

@ -38,6 +38,32 @@
}
}
},
"400": {
"description": "Default Response",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"kind",
"msg"
],
"properties": {
"kind": {
"enum": [
"failure"
]
},
"msg": {
"enum": [
"disableOtp.failure.guest"
]
}
}
}
}
}
},
"401": {
"description": "Default Response",
"content": {
@ -139,6 +165,32 @@
}
}
},
"400": {
"description": "Default Response",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"kind",
"msg"
],
"properties": {
"kind": {
"enum": [
"failure"
]
},
"msg": {
"enum": [
"enableOtp.failure.guest"
]
}
}
}
}
}
},
"401": {
"description": "Default Response",
"content": {
@ -846,12 +898,12 @@
"payload": {
"type": "object",
"required": [
"url"
"secret"
],
"properties": {
"url": {
"secret": {
"type": "string",
"description": "The otp url to feed into a 2fa app"
"description": "The otp secret"
}
}
}

View file

@ -7,6 +7,7 @@ import { typeResponse, isNullish } from '@shared/utils';
export const DisableOtpRes = {
'200': typeResponse('success', 'disableOtp.success'),
'500': typeResponse('failure', 'disableOtp.failure.generic'),
'400': typeResponse('failure', 'disableOtp.failure.guest'),
};
@ -18,6 +19,13 @@ const route: FastifyPluginAsync = async (fastify, _opts): Promise<void> => {
async function(req, res) {
void res;
if (isNullish(req.authUser)) { return res.makeResponse(500, 'failure', 'disableOtp.failure.generic'); }
if (req.authUser.guest) {
return res.makeResponse(
400,
'failure',
'disableOtp.failure.guest',
);
}
this.db.deleteUserOtpSecret(req.authUser.id);
return res.makeResponse(200, 'success', 'disableOtp.success');
},

View file

@ -10,6 +10,7 @@ export const EnableOtpRes = {
url: Type.String({ description: 'The otp url to feed into a 2fa app' }),
}),
'401': typeResponse('failure', ['enableOtp.failure.noUser', 'enableOtp.failure.noSecret']),
'400': typeResponse('failure', ['enableOtp.failure.guest']),
};
export type EnableOtpRes = MakeStaticResponse<typeof EnableOtpRes>;
@ -21,6 +22,13 @@ const route: FastifyPluginAsync = async (fastify, _opts): Promise<void> => {
{ schema: { response: EnableOtpRes, operationId: 'enableOtp' }, config: { requireAuth: true } },
async function(req, res) {
if (isNullish(req.authUser)) { return res.makeResponse(403, 'failure', 'enableOtp.failure.noUser'); }
if (req.authUser.guest) {
return res.makeResponse(
400,
'failure',
'enableOtp.failure.guest',
);
}
const otpSecret = this.db.ensureUserOtpSecret(req.authUser!.id);
if (isNullish(otpSecret)) { return res.makeResponse(403, 'failure', 'enableOtp.failure.noSecret'); }

View file

@ -2,12 +2,12 @@ import { FastifyPluginAsync } from 'fastify';
import { Type } from 'typebox';
import { isNullish, MakeStaticResponse, typeResponse } from '@shared/utils';
import { Otp } from '@shared/auth';
export const StatusOtpRes = {
200: Type.Union([
typeResponse('success', 'statusOtp.success.enabled', { url: Type.String({ description: 'The otp url to feed into a 2fa app' }) }),
typeResponse('success', 'statusOtp.success.enabled', {
secret: Type.String({ description: 'The otp secret' }),
}),
typeResponse('success', 'statusOtp.success.disabled'),
]),
500: typeResponse('failure', 'statusOtp.failure.generic'),
@ -19,13 +19,32 @@ const route: FastifyPluginAsync = async (fastify, _opts): Promise<void> => {
void _opts;
fastify.get(
'/api/auth/statusOtp',
{ schema: { response: StatusOtpRes, operationId: 'statusOtp' }, config: { requireAuth: true } },
{
schema: { response: StatusOtpRes, operationId: 'statusOtp' },
config: { requireAuth: true },
},
async function(req, res) {
if (isNullish(req.authUser)) { return res.makeResponse(500, 'failure', 'statusOtp.failure.generic'); }
if (isNullish(req.authUser)) {
return res.makeResponse(
500,
'failure',
'statusOtp.failure.generic',
);
}
const otpSecret = this.db.getUserOtpSecret(req.authUser.id);
if (isNullish(otpSecret)) { return res.makeResponse(200, 'success', 'statusOtp.success.disabled'); }
const otp = new Otp({ secret: otpSecret });
return res.makeResponse(200, 'success', 'statusOtp.success.enabled', { url: otp.totpURL });
if (isNullish(otpSecret)) {
return res.makeResponse(
200,
'success',
'statusOtp.success.disabled',
);
}
return res.makeResponse(
200,
'success',
'statusOtp.success.enabled',
{ secret: otpSecret },
);
},
);
};