Files
infisical/backend/src/server/routes/v2/user-router.ts
T

339 lines
8.2 KiB
TypeScript

import { z } from "zod";
import { AuthTokenSessionsSchema, UserEncryptionKeysSchema, UsersSchema } from "@app/db/schemas";
import { ApiKeysSchema } from "@app/db/schemas/api-keys";
import { authRateLimit, readLimit, smtpRateLimit, writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMethod, AuthMode, MfaMethod } from "@app/services/auth/auth-type";
import { sanitizedOrganizationSchema } from "@app/services/org/org-schema";
export const registerUserRouter = async (server: FastifyZodProvider) => {
server.route({
method: "POST",
url: "/me/emails/code",
config: {
rateLimit: smtpRateLimit({
keyGenerator: (req) => (req.body as { username?: string })?.username?.trim().substring(0, 100) ?? req.realIp
})
},
schema: {
body: z.object({
username: z.string().trim()
}),
response: {
200: z.object({})
}
},
handler: async (req) => {
await server.services.user.sendEmailVerificationCode(req.body.username);
return {};
}
});
server.route({
method: "POST",
url: "/me/emails/verify",
config: {
rateLimit: authRateLimit
},
schema: {
body: z.object({
username: z.string().trim(),
code: z.string().trim()
}),
response: {
200: z.object({})
}
},
handler: async (req) => {
await server.services.user.verifyEmailVerificationCode(req.body.username, req.body.code);
return {};
}
});
server.route({
method: "PATCH",
url: "/me/mfa",
config: {
rateLimit: writeLimit
},
schema: {
body: z.object({
isMfaEnabled: z.boolean().optional(),
selectedMfaMethod: z.nativeEnum(MfaMethod).optional()
}),
response: {
200: z.object({
user: UsersSchema
})
}
},
preHandler: verifyAuth([AuthMode.JWT, AuthMode.API_KEY]),
handler: async (req) => {
const user = await server.services.user.updateUserMfa({
userId: req.permission.id,
isMfaEnabled: req.body.isMfaEnabled,
selectedMfaMethod: req.body.selectedMfaMethod
});
return { user };
}
});
server.route({
method: "PATCH",
url: "/me/name",
config: {
rateLimit: writeLimit
},
schema: {
body: z.object({
firstName: z.string().trim(),
lastName: z.string().trim()
}),
response: {
200: z.object({
user: UsersSchema
})
}
},
preHandler: verifyAuth([AuthMode.JWT, AuthMode.API_KEY]),
handler: async (req) => {
const user = await server.services.user.updateUserName(req.permission.id, req.body.firstName, req.body.lastName);
return { user };
}
});
server.route({
method: "PUT",
url: "/me/auth-methods",
config: {
rateLimit: writeLimit
},
schema: {
body: z.object({
authMethods: z.nativeEnum(AuthMethod).array().min(1)
}),
response: {
200: z.object({
user: UsersSchema
})
}
},
preHandler: verifyAuth([AuthMode.JWT, AuthMode.API_KEY], { requireOrg: false }),
handler: async (req) => {
const user = await server.services.user.updateAuthMethods(req.permission.id, req.body.authMethods);
return { user };
}
});
server.route({
method: "GET",
url: "/me/organizations",
config: {
rateLimit: readLimit
},
schema: {
description: "Return organizations that current user is part of",
response: {
200: z.object({
organizations: sanitizedOrganizationSchema.array()
})
}
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY]),
handler: async (req) => {
const organizations = await server.services.org.findAllOrganizationOfUser(req.permission.id);
return { organizations };
}
});
server.route({
method: "GET",
url: "/me/api-keys",
config: {
rateLimit: readLimit
},
schema: {
response: {
200: ApiKeysSchema.omit({ secretHash: true }).array()
}
},
onRequest: verifyAuth([AuthMode.JWT]),
handler: async (req) => {
const apiKeys = await server.services.apiKey.getMyApiKeys(req.permission.id);
return apiKeys;
}
});
server.route({
method: "POST",
url: "/me/api-keys",
config: {
rateLimit: writeLimit
},
schema: {
body: z.object({
name: z.string().trim(),
expiresIn: z.number()
}),
response: {
200: z.object({
apiKey: z.string(),
apiKeyData: ApiKeysSchema.omit({ secretHash: true })
})
}
},
onRequest: verifyAuth([AuthMode.JWT]),
handler: async (req) => {
const apiKeys = await server.services.apiKey.createApiKey(req.permission.id, req.body.name, req.body.expiresIn);
return apiKeys;
}
});
server.route({
method: "DELETE",
url: "/me/api-keys/:apiKeyDataId",
config: {
rateLimit: writeLimit
},
schema: {
params: z.object({
apiKeyDataId: z.string().trim()
}),
response: {
200: z.object({
apiKeyData: ApiKeysSchema.omit({ secretHash: true })
})
}
},
onRequest: verifyAuth([AuthMode.JWT]),
handler: async (req) => {
const apiKeyData = await server.services.apiKey.deleteApiKey(req.permission.id, req.params.apiKeyDataId);
return { apiKeyData };
}
});
server.route({
method: "GET",
url: "/me/sessions",
config: {
rateLimit: readLimit
},
schema: {
response: {
200: AuthTokenSessionsSchema.array()
}
},
onRequest: verifyAuth([AuthMode.JWT]),
handler: async (req) => {
const sessions = await server.services.authToken.getTokenSessionByUser(req.permission.id);
return sessions;
}
});
server.route({
method: "DELETE",
url: "/me/sessions",
config: {
rateLimit: writeLimit
},
schema: {
response: {
200: z.object({
message: z.string()
})
}
},
onRequest: verifyAuth([AuthMode.JWT]),
handler: async (req) => {
await server.services.authToken.revokeAllMySessions(req.permission.id);
return {
message: "Successfully revoked all sessions"
};
}
});
server.route({
method: "DELETE",
url: "/me/sessions/:sessionId",
config: {
rateLimit: writeLimit
},
schema: {
params: z.object({
sessionId: z.string().trim()
}),
response: {
200: z.object({
message: z.string()
})
}
},
onRequest: verifyAuth([AuthMode.JWT]),
handler: async (req) => {
await server.services.authToken.revokeMySessionById(req.permission.id, req.params.sessionId);
return {
message: "Successfully revoked session"
};
}
});
server.route({
method: "GET",
url: "/me",
config: {
rateLimit: readLimit
},
schema: {
description: "Retrieve the current user on the request",
response: {
200: z.object({
user: UsersSchema.merge(
UserEncryptionKeysSchema.pick({
clientPublicKey: true,
serverPrivateKey: true,
encryptionVersion: true,
protectedKey: true,
protectedKeyIV: true,
protectedKeyTag: true,
publicKey: true,
encryptedPrivateKey: true,
iv: true,
tag: true,
salt: true,
verifier: true,
userId: true
})
)
})
}
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY]),
handler: async (req) => {
const user = await server.services.user.getMe(req.permission.id);
return { user };
}
});
server.route({
method: "DELETE",
url: "/me",
config: {
rateLimit: writeLimit
},
schema: {
response: {
200: z.object({
user: UsersSchema
})
}
},
onRequest: verifyAuth([AuthMode.JWT]),
handler: async (req) => {
const user = await server.services.user.deleteUser(req.permission.id);
return { user };
}
});
};