mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-15 14:27:23 +00:00
339 lines
8.2 KiB
TypeScript
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 };
|
|
}
|
|
});
|
|
};
|