mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-14 15:40:47 +00:00
Merge remote-tracking branch 'origin/main' into feat-secret-input-autocomplete
This commit is contained in:
@@ -24,6 +24,7 @@ import { fastifyErrHandler } from "./plugins/error-handler";
|
||||
import { registerExternalNextjs } from "./plugins/external-nextjs";
|
||||
import { serializerCompiler, validatorCompiler, ZodTypeProvider } from "./plugins/fastify-zod";
|
||||
import { fastifyIp } from "./plugins/ip";
|
||||
import { maintenanceMode } from "./plugins/maintenanceMode";
|
||||
import { fastifySwagger } from "./plugins/swagger";
|
||||
import { registerRoutes } from "./routes";
|
||||
|
||||
@@ -72,6 +73,8 @@ export const main = async ({ db, smtp, logger, queue, keyStore }: TMain) => {
|
||||
}
|
||||
await server.register(helmet, { contentSecurityPolicy: false });
|
||||
|
||||
await server.register(maintenanceMode);
|
||||
|
||||
await server.register(registerRoutes, { smtp, queue, db, keyStore });
|
||||
|
||||
if (appCfg.isProductionMode) {
|
||||
|
||||
@@ -18,14 +18,43 @@ export const globalRateLimiterCfg = (): RateLimitPluginOptions => {
|
||||
};
|
||||
};
|
||||
|
||||
export const authRateLimit: RateLimitOptions = {
|
||||
// GET endpoints
|
||||
export const readLimit: RateLimitOptions = {
|
||||
timeWindow: 60 * 1000,
|
||||
max: 600,
|
||||
keyGenerator: (req) => req.realIp
|
||||
};
|
||||
|
||||
export const passwordRateLimit: RateLimitOptions = {
|
||||
// POST, PATCH, PUT, DELETE endpoints
|
||||
export const writeLimit: RateLimitOptions = {
|
||||
timeWindow: 60 * 1000,
|
||||
max: 50,
|
||||
keyGenerator: (req) => req.realIp
|
||||
};
|
||||
|
||||
// special endpoints
|
||||
export const secretsLimit: RateLimitOptions = {
|
||||
// secrets, folders, secret imports
|
||||
timeWindow: 60 * 1000,
|
||||
max: 600,
|
||||
keyGenerator: (req) => req.realIp
|
||||
};
|
||||
|
||||
export const authRateLimit: RateLimitOptions = {
|
||||
timeWindow: 60 * 1000,
|
||||
max: 60,
|
||||
keyGenerator: (req) => req.realIp
|
||||
};
|
||||
|
||||
export const inviteUserRateLimit: RateLimitOptions = {
|
||||
timeWindow: 60 * 1000,
|
||||
max: 30,
|
||||
keyGenerator: (req) => req.realIp
|
||||
};
|
||||
|
||||
export const creationLimit: RateLimitOptions = {
|
||||
// identity, project, org
|
||||
timeWindow: 60 * 1000,
|
||||
max: 30,
|
||||
keyGenerator: (req) => req.realIp
|
||||
};
|
||||
|
||||
@@ -6,42 +6,49 @@ import { TServiceTokens, TUsers } from "@app/db/schemas";
|
||||
import { TScimTokenJwtPayload } from "@app/ee/services/scim/scim-types";
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import { UnauthorizedError } from "@app/lib/errors";
|
||||
import { ActorType, AuthMode, AuthModeJwtTokenPayload, AuthTokenType } from "@app/services/auth/auth-type";
|
||||
import { ActorType, AuthMethod, AuthMode, AuthModeJwtTokenPayload, AuthTokenType } from "@app/services/auth/auth-type";
|
||||
import { TIdentityAccessTokenJwtPayload } from "@app/services/identity-access-token/identity-access-token-types";
|
||||
|
||||
export type TAuthMode =
|
||||
| {
|
||||
orgId?: string;
|
||||
authMode: AuthMode.JWT;
|
||||
actor: ActorType.USER;
|
||||
userId: string;
|
||||
tokenVersionId: string; // the session id of token used
|
||||
user: TUsers;
|
||||
orgId: string;
|
||||
authMethod: AuthMethod;
|
||||
}
|
||||
| {
|
||||
authMode: AuthMode.API_KEY;
|
||||
authMethod: null;
|
||||
actor: ActorType.USER;
|
||||
userId: string;
|
||||
user: TUsers;
|
||||
orgId?: string;
|
||||
orgId: string;
|
||||
}
|
||||
| {
|
||||
authMode: AuthMode.SERVICE_TOKEN;
|
||||
serviceToken: TServiceTokens & { createdByEmail: string };
|
||||
actor: ActorType.SERVICE;
|
||||
serviceTokenId: string;
|
||||
orgId: string;
|
||||
authMethod: null;
|
||||
}
|
||||
| {
|
||||
authMode: AuthMode.IDENTITY_ACCESS_TOKEN;
|
||||
actor: ActorType.IDENTITY;
|
||||
identityId: string;
|
||||
identityName: string;
|
||||
orgId: string;
|
||||
authMethod: null;
|
||||
}
|
||||
| {
|
||||
authMode: AuthMode.SCIM_TOKEN;
|
||||
actor: ActorType.SCIM_CLIENT;
|
||||
scimTokenId: string;
|
||||
orgId: string;
|
||||
authMethod: null;
|
||||
};
|
||||
|
||||
const extractAuth = async (req: FastifyRequest, jwtSecret: string) => {
|
||||
@@ -50,6 +57,7 @@ const extractAuth = async (req: FastifyRequest, jwtSecret: string) => {
|
||||
return { authMode: AuthMode.API_KEY, token: apiKey, actor: ActorType.USER } as const;
|
||||
}
|
||||
const authHeader = req.headers?.authorization;
|
||||
|
||||
if (!authHeader) return { authMode: null, token: null };
|
||||
|
||||
const authTokenValue = authHeader.slice(7); // slice of after Bearer
|
||||
@@ -71,6 +79,7 @@ const extractAuth = async (req: FastifyRequest, jwtSecret: string) => {
|
||||
actor: ActorType.USER
|
||||
} as const;
|
||||
case AuthTokenType.API_KEY:
|
||||
// throw new Error("API Key auth is no longer supported.");
|
||||
return { authMode: AuthMode.API_KEY, token: decodedToken, actor: ActorType.USER } as const;
|
||||
case AuthTokenType.IDENTITY_ACCESS_TOKEN:
|
||||
return {
|
||||
@@ -89,17 +98,30 @@ const extractAuth = async (req: FastifyRequest, jwtSecret: string) => {
|
||||
}
|
||||
};
|
||||
|
||||
// ! Important: You can only 100% count on the `req.permission.orgId` field being present when the auth method is Identity Access Token (Machine Identity).
|
||||
export const injectIdentity = fp(async (server: FastifyZodProvider) => {
|
||||
server.decorateRequest("auth", null);
|
||||
server.addHook("onRequest", async (req) => {
|
||||
const appCfg = getConfig();
|
||||
const { authMode, token, actor } = await extractAuth(req, appCfg.AUTH_SECRET);
|
||||
|
||||
if (req.url.includes("/api/v3/auth/")) {
|
||||
return;
|
||||
}
|
||||
if (!authMode) return;
|
||||
|
||||
switch (authMode) {
|
||||
case AuthMode.JWT: {
|
||||
const { user, tokenVersionId, orgId } = await server.services.authToken.fnValidateJwtIdentity(token);
|
||||
req.auth = { authMode: AuthMode.JWT, user, userId: user.id, tokenVersionId, actor, orgId };
|
||||
req.auth = {
|
||||
authMode: AuthMode.JWT,
|
||||
user,
|
||||
userId: user.id,
|
||||
tokenVersionId,
|
||||
actor,
|
||||
orgId: orgId as string,
|
||||
authMethod: token.authMethod
|
||||
};
|
||||
break;
|
||||
}
|
||||
case AuthMode.IDENTITY_ACCESS_TOKEN: {
|
||||
@@ -107,29 +129,40 @@ export const injectIdentity = fp(async (server: FastifyZodProvider) => {
|
||||
req.auth = {
|
||||
authMode: AuthMode.IDENTITY_ACCESS_TOKEN,
|
||||
actor,
|
||||
orgId: identity.orgId,
|
||||
identityId: identity.identityId,
|
||||
identityName: identity.name
|
||||
identityName: identity.name,
|
||||
authMethod: null
|
||||
};
|
||||
break;
|
||||
}
|
||||
case AuthMode.SERVICE_TOKEN: {
|
||||
const serviceToken = await server.services.serviceToken.fnValidateServiceToken(token);
|
||||
req.auth = {
|
||||
orgId: serviceToken.orgId,
|
||||
authMode: AuthMode.SERVICE_TOKEN as const,
|
||||
serviceToken,
|
||||
serviceTokenId: serviceToken.id,
|
||||
actor
|
||||
actor,
|
||||
authMethod: null
|
||||
};
|
||||
break;
|
||||
}
|
||||
case AuthMode.API_KEY: {
|
||||
const user = await server.services.apiKey.fnValidateApiKey(token as string);
|
||||
req.auth = { authMode: AuthMode.API_KEY as const, userId: user.id, actor, user };
|
||||
req.auth = {
|
||||
authMode: AuthMode.API_KEY as const,
|
||||
userId: user.id,
|
||||
actor,
|
||||
user,
|
||||
orgId: "API_KEY", // We set the orgId to an arbitrary value, since we can't link an API key to a specific org. We have to deprecate API keys soon!
|
||||
authMethod: null
|
||||
};
|
||||
break;
|
||||
}
|
||||
case AuthMode.SCIM_TOKEN: {
|
||||
const { orgId, scimTokenId } = await server.services.scim.fnValidateScimToken(token);
|
||||
req.auth = { authMode: AuthMode.SCIM_TOKEN, actor, scimTokenId, orgId };
|
||||
req.auth = { authMode: AuthMode.SCIM_TOKEN, actor, scimTokenId, orgId, authMethod: null };
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
||||
@@ -9,13 +9,33 @@ export const injectPermission = fp(async (server) => {
|
||||
if (!req.auth) return;
|
||||
|
||||
if (req.auth.actor === ActorType.USER) {
|
||||
req.permission = { type: ActorType.USER, id: req.auth.userId, orgId: req.auth?.orgId };
|
||||
req.permission = {
|
||||
type: ActorType.USER,
|
||||
id: req.auth.userId,
|
||||
orgId: req.auth.orgId, // if the req.auth.authMode is AuthMode.API_KEY, the orgId will be "API_KEY"
|
||||
authMethod: req.auth.authMethod // if the req.auth.authMode is AuthMode.API_KEY, the authMethod will be null
|
||||
};
|
||||
} else if (req.auth.actor === ActorType.IDENTITY) {
|
||||
req.permission = { type: ActorType.IDENTITY, id: req.auth.identityId };
|
||||
req.permission = {
|
||||
type: ActorType.IDENTITY,
|
||||
id: req.auth.identityId,
|
||||
orgId: req.auth.orgId,
|
||||
authMethod: null
|
||||
};
|
||||
} else if (req.auth.actor === ActorType.SERVICE) {
|
||||
req.permission = { type: ActorType.SERVICE, id: req.auth.serviceTokenId };
|
||||
req.permission = {
|
||||
type: ActorType.SERVICE,
|
||||
id: req.auth.serviceTokenId,
|
||||
orgId: req.auth.orgId,
|
||||
authMethod: null
|
||||
};
|
||||
} else if (req.auth.actor === ActorType.SCIM_CLIENT) {
|
||||
req.permission = { type: ActorType.SCIM_CLIENT, id: req.auth.scimTokenId, orgId: req.auth.orgId };
|
||||
req.permission = {
|
||||
type: ActorType.SCIM_CLIENT,
|
||||
id: req.auth.scimTokenId,
|
||||
orgId: req.auth.orgId,
|
||||
authMethod: null
|
||||
};
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -3,15 +3,26 @@ import { FastifyReply, FastifyRequest, HookHandlerDoneFunction } from "fastify";
|
||||
import { UnauthorizedError } from "@app/lib/errors";
|
||||
import { AuthMode } from "@app/services/auth/auth-type";
|
||||
|
||||
interface TAuthOptions {
|
||||
requireOrg: boolean;
|
||||
}
|
||||
|
||||
export const verifyAuth =
|
||||
<T extends FastifyRequest>(authStrats: AuthMode[]) =>
|
||||
<T extends FastifyRequest>(authStrategies: AuthMode[], options: TAuthOptions = { requireOrg: true }) =>
|
||||
(req: T, _res: FastifyReply, done: HookHandlerDoneFunction) => {
|
||||
if (!Array.isArray(authStrats)) throw new Error("Auth strategy must be array");
|
||||
if (!Array.isArray(authStrategies)) throw new Error("Auth strategy must be array");
|
||||
if (!req.auth) throw new UnauthorizedError({ name: "Unauthorized access", message: "Token missing" });
|
||||
|
||||
const isAccessAllowed = authStrats.some((strat) => strat === req.auth.authMode);
|
||||
const isAccessAllowed = authStrategies.some((strategy) => strategy === req.auth.authMode);
|
||||
if (!isAccessAllowed) {
|
||||
throw new UnauthorizedError({ name: `${req.url} Unauthorized Access` });
|
||||
}
|
||||
|
||||
// New optional option. There are some routes which do not require an organization ID to be present on the request.
|
||||
// An example of this is the /v1 auth routes.
|
||||
if (req.auth.authMode === AuthMode.JWT && options.requireOrg === true && !req.permission.orgId) {
|
||||
throw new UnauthorizedError({ name: `${req.url} Unauthorized Access, no organization found in request` });
|
||||
}
|
||||
|
||||
done();
|
||||
};
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
import fp from "fastify-plugin";
|
||||
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
|
||||
export const maintenanceMode = fp(async (fastify) => {
|
||||
fastify.addHook("onRequest", async (req) => {
|
||||
const serverEnvs = getConfig();
|
||||
if (req.url !== "/api/v1/auth/checkAuth" && req.method !== "GET" && serverEnvs.MAINTENANCE_MODE) {
|
||||
throw new Error("Infisical is in maintenance mode. Please try again later.");
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -4,6 +4,7 @@ import SmeeClient from "smee-client";
|
||||
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import { logger } from "@app/lib/logger";
|
||||
import { writeLimit } from "@app/server/config/rateLimiter";
|
||||
|
||||
export const registerSecretScannerGhApp = async (server: FastifyZodProvider) => {
|
||||
const probotApp = (app: Probot) => {
|
||||
@@ -49,6 +50,9 @@ export const registerSecretScannerGhApp = async (server: FastifyZodProvider) =>
|
||||
server.route({
|
||||
method: "POST",
|
||||
url: "/",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
handler: async (req, res) => {
|
||||
const eventName = req.headers["x-github-event"];
|
||||
const signatureSHA256 = req.headers["x-hub-signature-256"] as string;
|
||||
|
||||
@@ -14,13 +14,13 @@ export const fastifySwagger = fp(async (fastify) => {
|
||||
version: "0.0.1"
|
||||
},
|
||||
servers: [
|
||||
{
|
||||
url: "http://localhost:8080",
|
||||
description: "Local server"
|
||||
},
|
||||
{
|
||||
url: "https://app.infisical.com",
|
||||
description: "Production server"
|
||||
},
|
||||
{
|
||||
url: "http://localhost:8080",
|
||||
description: "Local server"
|
||||
}
|
||||
],
|
||||
components: {
|
||||
@@ -30,12 +30,6 @@ export const fastifySwagger = fp(async (fastify) => {
|
||||
scheme: "bearer",
|
||||
bearerFormat: "JWT",
|
||||
description: "An access token in Infisical"
|
||||
},
|
||||
apiKeyAuth: {
|
||||
type: "apiKey",
|
||||
in: "header",
|
||||
name: "X-API-Key",
|
||||
description: "An API Key in Infisical"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,12 +5,25 @@ import { registerV1EERoutes } from "@app/ee/routes/v1";
|
||||
import { auditLogDALFactory } from "@app/ee/services/audit-log/audit-log-dal";
|
||||
import { auditLogQueueServiceFactory } from "@app/ee/services/audit-log/audit-log-queue";
|
||||
import { auditLogServiceFactory } from "@app/ee/services/audit-log/audit-log-service";
|
||||
import { dynamicSecretDALFactory } from "@app/ee/services/dynamic-secret/dynamic-secret-dal";
|
||||
import { dynamicSecretServiceFactory } from "@app/ee/services/dynamic-secret/dynamic-secret-service";
|
||||
import { buildDynamicSecretProviders } from "@app/ee/services/dynamic-secret/providers";
|
||||
import { dynamicSecretLeaseDALFactory } from "@app/ee/services/dynamic-secret-lease/dynamic-secret-lease-dal";
|
||||
import { dynamicSecretLeaseQueueServiceFactory } from "@app/ee/services/dynamic-secret-lease/dynamic-secret-lease-queue";
|
||||
import { dynamicSecretLeaseServiceFactory } from "@app/ee/services/dynamic-secret-lease/dynamic-secret-lease-service";
|
||||
import { groupDALFactory } from "@app/ee/services/group/group-dal";
|
||||
import { groupServiceFactory } from "@app/ee/services/group/group-service";
|
||||
import { userGroupMembershipDALFactory } from "@app/ee/services/group/user-group-membership-dal";
|
||||
import { identityProjectAdditionalPrivilegeDALFactory } from "@app/ee/services/identity-project-additional-privilege/identity-project-additional-privilege-dal";
|
||||
import { identityProjectAdditionalPrivilegeServiceFactory } from "@app/ee/services/identity-project-additional-privilege/identity-project-additional-privilege-service";
|
||||
import { ldapConfigDALFactory } from "@app/ee/services/ldap-config/ldap-config-dal";
|
||||
import { ldapConfigServiceFactory } from "@app/ee/services/ldap-config/ldap-config-service";
|
||||
import { licenseDALFactory } from "@app/ee/services/license/license-dal";
|
||||
import { licenseServiceFactory } from "@app/ee/services/license/license-service";
|
||||
import { permissionDALFactory } from "@app/ee/services/permission/permission-dal";
|
||||
import { permissionServiceFactory } from "@app/ee/services/permission/permission-service";
|
||||
import { projectUserAdditionalPrivilegeDALFactory } from "@app/ee/services/project-user-additional-privilege/project-user-additional-privilege-dal";
|
||||
import { projectUserAdditionalPrivilegeServiceFactory } from "@app/ee/services/project-user-additional-privilege/project-user-additional-privilege-service";
|
||||
import { samlConfigDALFactory } from "@app/ee/services/saml-config/saml-config-dal";
|
||||
import { samlConfigServiceFactory } from "@app/ee/services/saml-config/saml-config-service";
|
||||
import { scimDALFactory } from "@app/ee/services/scim/scim-dal";
|
||||
@@ -39,6 +52,7 @@ import { trustedIpServiceFactory } from "@app/ee/services/trusted-ip/trusted-ip-
|
||||
import { TKeyStoreFactory } from "@app/keystore/keystore";
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import { TQueueServiceFactory } from "@app/queue";
|
||||
import { readLimit } from "@app/server/config/rateLimiter";
|
||||
import { apiKeyDALFactory } from "@app/services/api-key/api-key-dal";
|
||||
import { apiKeyServiceFactory } from "@app/services/api-key/api-key-service";
|
||||
import { authDALFactory } from "@app/services/auth/auth-dal";
|
||||
@@ -47,6 +61,9 @@ import { authPaswordServiceFactory } from "@app/services/auth/auth-password-serv
|
||||
import { authSignupServiceFactory } from "@app/services/auth/auth-signup-service";
|
||||
import { tokenDALFactory } from "@app/services/auth-token/auth-token-dal";
|
||||
import { tokenServiceFactory } from "@app/services/auth-token/auth-token-service";
|
||||
import { groupProjectDALFactory } from "@app/services/group-project/group-project-dal";
|
||||
import { groupProjectMembershipRoleDALFactory } from "@app/services/group-project/group-project-membership-role-dal";
|
||||
import { groupProjectServiceFactory } from "@app/services/group-project/group-project-service";
|
||||
import { identityDALFactory } from "@app/services/identity/identity-dal";
|
||||
import { identityOrgDALFactory } from "@app/services/identity/identity-org-dal";
|
||||
import { identityServiceFactory } from "@app/services/identity/identity-service";
|
||||
@@ -143,6 +160,7 @@ export const registerRoutes = async (
|
||||
|
||||
const projectDAL = projectDALFactory(db);
|
||||
const projectMembershipDAL = projectMembershipDALFactory(db);
|
||||
const projectUserAdditionalPrivilegeDAL = projectUserAdditionalPrivilegeDALFactory(db);
|
||||
const projectUserMembershipRoleDAL = projectUserMembershipRoleDALFactory(db);
|
||||
const projectRoleDAL = projectRoleDALFactory(db);
|
||||
const projectEnvDAL = projectEnvDALFactory(db);
|
||||
@@ -168,6 +186,7 @@ export const registerRoutes = async (
|
||||
const identityOrgMembershipDAL = identityOrgDALFactory(db);
|
||||
const identityProjectDAL = identityProjectDALFactory(db);
|
||||
const identityProjectMembershipRoleDAL = identityProjectMembershipRoleDALFactory(db);
|
||||
const identityProjectAdditionalPrivilegeDAL = identityProjectAdditionalPrivilegeDALFactory(db);
|
||||
|
||||
const identityUaDAL = identityUaDALFactory(db);
|
||||
const identityUaClientSecretDAL = identityUaClientSecretDALFactory(db);
|
||||
@@ -194,14 +213,21 @@ export const registerRoutes = async (
|
||||
|
||||
const gitAppInstallSessionDAL = gitAppInstallSessionDALFactory(db);
|
||||
const gitAppOrgDAL = gitAppDALFactory(db);
|
||||
const groupDAL = groupDALFactory(db);
|
||||
const groupProjectDAL = groupProjectDALFactory(db);
|
||||
const groupProjectMembershipRoleDAL = groupProjectMembershipRoleDALFactory(db);
|
||||
const userGroupMembershipDAL = userGroupMembershipDALFactory(db);
|
||||
const secretScanningDAL = secretScanningDALFactory(db);
|
||||
const licenseDAL = licenseDALFactory(db);
|
||||
const dynamicSecretDAL = dynamicSecretDALFactory(db);
|
||||
const dynamicSecretLeaseDAL = dynamicSecretLeaseDALFactory(db);
|
||||
|
||||
const permissionService = permissionServiceFactory({
|
||||
permissionDAL,
|
||||
orgRoleDAL,
|
||||
projectRoleDAL,
|
||||
serviceTokenDAL
|
||||
serviceTokenDAL,
|
||||
projectDAL
|
||||
});
|
||||
const licenseService = licenseServiceFactory({ permissionService, orgDAL, licenseDAL, keyStore });
|
||||
const trustedIpService = trustedIpServiceFactory({
|
||||
@@ -233,6 +259,29 @@ export const registerRoutes = async (
|
||||
samlConfigDAL,
|
||||
licenseService
|
||||
});
|
||||
const groupService = groupServiceFactory({
|
||||
userDAL,
|
||||
groupDAL,
|
||||
groupProjectDAL,
|
||||
orgDAL,
|
||||
userGroupMembershipDAL,
|
||||
projectDAL,
|
||||
projectBotDAL,
|
||||
projectKeyDAL,
|
||||
permissionService,
|
||||
licenseService
|
||||
});
|
||||
const groupProjectService = groupProjectServiceFactory({
|
||||
groupDAL,
|
||||
groupProjectDAL,
|
||||
groupProjectMembershipRoleDAL,
|
||||
userGroupMembershipDAL,
|
||||
projectDAL,
|
||||
projectKeyDAL,
|
||||
projectBotDAL,
|
||||
projectRoleDAL,
|
||||
permissionService
|
||||
});
|
||||
const scimService = scimServiceFactory({
|
||||
licenseService,
|
||||
scimDAL,
|
||||
@@ -240,6 +289,7 @@ export const registerRoutes = async (
|
||||
orgDAL,
|
||||
projectDAL,
|
||||
projectMembershipDAL,
|
||||
groupDAL,
|
||||
permissionService,
|
||||
smtpService
|
||||
});
|
||||
@@ -266,7 +316,7 @@ export const registerRoutes = async (
|
||||
|
||||
const tokenService = tokenServiceFactory({ tokenDAL: authTokenDAL, userDAL });
|
||||
const userService = userServiceFactory({ userDAL });
|
||||
const loginService = authLoginServiceFactory({ userDAL, smtpService, tokenService });
|
||||
const loginService = authLoginServiceFactory({ userDAL, smtpService, tokenService, orgDAL, tokenDAL: authTokenDAL });
|
||||
const passwordService = authPaswordServiceFactory({
|
||||
tokenService,
|
||||
smtpService,
|
||||
@@ -286,6 +336,7 @@ export const registerRoutes = async (
|
||||
projectKeyDAL,
|
||||
smtpService,
|
||||
userDAL,
|
||||
groupDAL,
|
||||
orgBotDAL
|
||||
});
|
||||
const signupService = authSignupServiceFactory({
|
||||
@@ -331,11 +382,17 @@ export const registerRoutes = async (
|
||||
projectBotDAL,
|
||||
orgDAL,
|
||||
userDAL,
|
||||
userGroupMembershipDAL,
|
||||
smtpService,
|
||||
projectKeyDAL,
|
||||
projectRoleDAL,
|
||||
licenseService
|
||||
});
|
||||
const projectUserAdditionalPrivilegeService = projectUserAdditionalPrivilegeServiceFactory({
|
||||
permissionService,
|
||||
projectMembershipDAL,
|
||||
projectUserAdditionalPrivilegeDAL
|
||||
});
|
||||
const projectKeyService = projectKeyServiceFactory({
|
||||
permissionService,
|
||||
projectKeyDAL,
|
||||
@@ -372,12 +429,14 @@ export const registerRoutes = async (
|
||||
projectKeyDAL,
|
||||
userDAL,
|
||||
projectEnvDAL,
|
||||
orgDAL,
|
||||
orgService,
|
||||
projectMembershipDAL,
|
||||
folderDAL,
|
||||
licenseService,
|
||||
projectUserMembershipRoleDAL,
|
||||
identityProjectMembershipRoleDAL
|
||||
identityProjectMembershipRoleDAL,
|
||||
keyStore
|
||||
});
|
||||
|
||||
const projectEnvService = projectEnvServiceFactory({
|
||||
@@ -388,7 +447,12 @@ export const registerRoutes = async (
|
||||
folderDAL
|
||||
});
|
||||
|
||||
const projectRoleService = projectRoleServiceFactory({ permissionService, projectRoleDAL });
|
||||
const projectRoleService = projectRoleServiceFactory({
|
||||
permissionService,
|
||||
projectRoleDAL,
|
||||
projectUserMembershipRoleDAL,
|
||||
identityProjectMembershipRoleDAL
|
||||
});
|
||||
|
||||
const snapshotService = secretSnapshotServiceFactory({
|
||||
permissionService,
|
||||
@@ -417,14 +481,6 @@ export const registerRoutes = async (
|
||||
projectEnvDAL,
|
||||
snapshotService
|
||||
});
|
||||
const secretImportService = secretImportServiceFactory({
|
||||
projectEnvDAL,
|
||||
folderDAL,
|
||||
permissionService,
|
||||
secretImportDAL,
|
||||
projectDAL,
|
||||
secretDAL
|
||||
});
|
||||
const integrationAuthService = integrationAuthServiceFactory({
|
||||
integrationAuthDAL,
|
||||
integrationDAL,
|
||||
@@ -452,6 +508,15 @@ export const registerRoutes = async (
|
||||
secretTagDAL,
|
||||
secretVersionTagDAL
|
||||
});
|
||||
const secretImportService = secretImportServiceFactory({
|
||||
projectEnvDAL,
|
||||
folderDAL,
|
||||
permissionService,
|
||||
secretImportDAL,
|
||||
projectDAL,
|
||||
secretDAL,
|
||||
secretQueueService
|
||||
});
|
||||
const secretBlindIndexService = secretBlindIndexServiceFactory({
|
||||
permissionService,
|
||||
secretDAL,
|
||||
@@ -469,6 +534,7 @@ export const registerRoutes = async (
|
||||
snapshotService,
|
||||
secretQueueService,
|
||||
secretImportDAL,
|
||||
projectEnvDAL,
|
||||
projectBotService
|
||||
});
|
||||
const sarService = secretApprovalRequestServiceFactory({
|
||||
@@ -517,7 +583,8 @@ export const registerRoutes = async (
|
||||
projectEnvDAL,
|
||||
serviceTokenDAL,
|
||||
userDAL,
|
||||
permissionService
|
||||
permissionService,
|
||||
projectDAL
|
||||
});
|
||||
|
||||
const identityService = identityServiceFactory({
|
||||
@@ -525,7 +592,10 @@ export const registerRoutes = async (
|
||||
identityDAL,
|
||||
identityOrgMembershipDAL
|
||||
});
|
||||
const identityAccessTokenService = identityAccessTokenServiceFactory({ identityAccessTokenDAL });
|
||||
const identityAccessTokenService = identityAccessTokenServiceFactory({
|
||||
identityAccessTokenDAL,
|
||||
identityOrgMembershipDAL
|
||||
});
|
||||
const identityProjectService = identityProjectServiceFactory({
|
||||
permissionService,
|
||||
projectDAL,
|
||||
@@ -534,6 +604,12 @@ export const registerRoutes = async (
|
||||
identityProjectMembershipRoleDAL,
|
||||
projectRoleDAL
|
||||
});
|
||||
const identityProjectAdditionalPrivilegeService = identityProjectAdditionalPrivilegeServiceFactory({
|
||||
projectDAL,
|
||||
identityProjectAdditionalPrivilegeDAL,
|
||||
permissionService,
|
||||
identityProjectDAL
|
||||
});
|
||||
const identityUaService = identityUaServiceFactory({
|
||||
identityOrgMembershipDAL,
|
||||
permissionService,
|
||||
@@ -544,6 +620,34 @@ export const registerRoutes = async (
|
||||
licenseService
|
||||
});
|
||||
|
||||
const dynamicSecretProviders = buildDynamicSecretProviders();
|
||||
const dynamicSecretQueueService = dynamicSecretLeaseQueueServiceFactory({
|
||||
queueService,
|
||||
dynamicSecretLeaseDAL,
|
||||
dynamicSecretProviders,
|
||||
dynamicSecretDAL
|
||||
});
|
||||
const dynamicSecretService = dynamicSecretServiceFactory({
|
||||
projectDAL,
|
||||
dynamicSecretQueueService,
|
||||
dynamicSecretDAL,
|
||||
dynamicSecretLeaseDAL,
|
||||
dynamicSecretProviders,
|
||||
folderDAL,
|
||||
permissionService,
|
||||
licenseService
|
||||
});
|
||||
const dynamicSecretLeaseService = dynamicSecretLeaseServiceFactory({
|
||||
projectDAL,
|
||||
permissionService,
|
||||
dynamicSecretQueueService,
|
||||
dynamicSecretDAL,
|
||||
dynamicSecretLeaseDAL,
|
||||
dynamicSecretProviders,
|
||||
folderDAL,
|
||||
licenseService
|
||||
});
|
||||
|
||||
await superAdminService.initServerCfg();
|
||||
//
|
||||
// setup the communication with license key server
|
||||
@@ -558,6 +662,8 @@ export const registerRoutes = async (
|
||||
password: passwordService,
|
||||
signup: signupService,
|
||||
user: userService,
|
||||
group: groupService,
|
||||
groupProject: groupProjectService,
|
||||
permission: permissionService,
|
||||
org: orgService,
|
||||
orgRole: orgRoleService,
|
||||
@@ -585,6 +691,8 @@ export const registerRoutes = async (
|
||||
secretApprovalPolicy: sapService,
|
||||
secretApprovalRequest: sarService,
|
||||
secretRotation: secretRotationService,
|
||||
dynamicSecret: dynamicSecretService,
|
||||
dynamicSecretLease: dynamicSecretLeaseService,
|
||||
snapshot: snapshotService,
|
||||
saml: samlService,
|
||||
ldap: ldapService,
|
||||
@@ -594,7 +702,9 @@ export const registerRoutes = async (
|
||||
trustedIp: trustedIpService,
|
||||
scim: scimService,
|
||||
secretBlindIndex: secretBlindIndexService,
|
||||
telemetry: telemetryService
|
||||
telemetry: telemetryService,
|
||||
projectUserAdditionalPrivilege: projectUserAdditionalPrivilegeService,
|
||||
identityProjectAdditionalPrivilege: identityProjectAdditionalPrivilegeService
|
||||
});
|
||||
|
||||
server.decorate<FastifyZodProvider["store"]>("store", {
|
||||
@@ -606,8 +716,11 @@ export const registerRoutes = async (
|
||||
await server.register(injectAuditLogInfo);
|
||||
|
||||
server.route({
|
||||
url: "/api/status",
|
||||
method: "GET",
|
||||
url: "/api/status",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
schema: {
|
||||
response: {
|
||||
200: z.object({
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
import { z } from "zod";
|
||||
|
||||
import { IntegrationAuthsSchema, SecretApprovalPoliciesSchema, UsersSchema } from "@app/db/schemas";
|
||||
import {
|
||||
DynamicSecretsSchema,
|
||||
IntegrationAuthsSchema,
|
||||
SecretApprovalPoliciesSchema,
|
||||
UsersSchema
|
||||
} from "@app/db/schemas";
|
||||
|
||||
// sometimes the return data must be santizied to avoid leaking important values
|
||||
// always prefer pick over omit in zod
|
||||
@@ -56,3 +61,11 @@ export const secretRawSchema = z.object({
|
||||
secretValue: z.string(),
|
||||
secretComment: z.string().optional()
|
||||
});
|
||||
|
||||
export const SanitizedDynamicSecretSchema = DynamicSecretsSchema.omit({
|
||||
inputIV: true,
|
||||
inputTag: true,
|
||||
inputCiphertext: true,
|
||||
keyEncoding: true,
|
||||
algorithm: true
|
||||
});
|
||||
|
||||
@@ -3,6 +3,7 @@ import { z } from "zod";
|
||||
import { OrganizationsSchema, SuperAdminSchema, UsersSchema } from "@app/db/schemas";
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import { UnauthorizedError } from "@app/lib/errors";
|
||||
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||
import { verifySuperAdmin } from "@app/server/plugins/auth/superAdmin";
|
||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||
import { AuthMode } from "@app/services/auth/auth-type";
|
||||
@@ -11,24 +12,33 @@ import { PostHogEventTypes } from "@app/services/telemetry/telemetry-types";
|
||||
|
||||
export const registerAdminRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
url: "/config",
|
||||
method: "GET",
|
||||
url: "/config",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
schema: {
|
||||
response: {
|
||||
200: z.object({
|
||||
config: SuperAdminSchema.omit({ createdAt: true, updatedAt: true })
|
||||
config: SuperAdminSchema.omit({ createdAt: true, updatedAt: true }).merge(
|
||||
z.object({ isMigrationModeOn: z.boolean() })
|
||||
)
|
||||
})
|
||||
}
|
||||
},
|
||||
handler: async () => {
|
||||
const config = await getServerCfg();
|
||||
return { config };
|
||||
const serverEnvs = getConfig();
|
||||
return { config: { ...config, isMigrationModeOn: serverEnvs.MAINTENANCE_MODE } };
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/config",
|
||||
method: "PATCH",
|
||||
url: "/config",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
schema: {
|
||||
body: z.object({
|
||||
allowSignUp: z.boolean().optional(),
|
||||
@@ -52,8 +62,11 @@ export const registerAdminRouter = async (server: FastifyZodProvider) => {
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/signup",
|
||||
method: "POST",
|
||||
url: "/signup",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
schema: {
|
||||
body: z.object({
|
||||
email: z.string().email().trim(),
|
||||
|
||||
@@ -3,7 +3,7 @@ import { z } from "zod";
|
||||
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import { BadRequestError, UnauthorizedError } from "@app/lib/errors";
|
||||
import { authRateLimit } from "@app/server/config/rateLimiter";
|
||||
import { authRateLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||
import { AuthMode, AuthModeRefreshJwtTokenPayload, AuthTokenType } from "@app/services/auth/auth-type";
|
||||
|
||||
@@ -21,7 +21,7 @@ export const registerAuthRoutes = async (server: FastifyZodProvider) => {
|
||||
})
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT]),
|
||||
onRequest: verifyAuth([AuthMode.JWT], { requireOrg: false }),
|
||||
handler: async (req, res) => {
|
||||
const appCfg = getConfig();
|
||||
if (req.auth.authMode === AuthMode.JWT) {
|
||||
@@ -38,8 +38,11 @@ export const registerAuthRoutes = async (server: FastifyZodProvider) => {
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/checkAuth",
|
||||
method: "POST",
|
||||
url: "/checkAuth",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
schema: {
|
||||
response: {
|
||||
200: z.object({
|
||||
@@ -52,8 +55,11 @@ export const registerAuthRoutes = async (server: FastifyZodProvider) => {
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/token",
|
||||
method: "POST",
|
||||
url: "/token",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
schema: {
|
||||
response: {
|
||||
200: z.object({
|
||||
@@ -85,6 +91,7 @@ export const registerAuthRoutes = async (server: FastifyZodProvider) => {
|
||||
|
||||
const token = jwt.sign(
|
||||
{
|
||||
authMethod: decodedToken.authMethod,
|
||||
authTokenType: AuthTokenType.ACCESS_TOKEN,
|
||||
userId: decodedToken.userId,
|
||||
tokenVersionId: tokenVersion.id,
|
||||
|
||||
@@ -1,13 +1,17 @@
|
||||
import { z } from "zod";
|
||||
|
||||
import { ProjectBotsSchema } from "@app/db/schemas";
|
||||
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||
import { AuthMode } from "@app/services/auth/auth-type";
|
||||
|
||||
export const registerProjectBotRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
url: "/:projectId",
|
||||
method: "GET",
|
||||
url: "/:projectId",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
schema: {
|
||||
params: z.object({
|
||||
projectId: z.string().trim()
|
||||
@@ -30,6 +34,7 @@ export const registerProjectBotRouter = async (server: FastifyZodProvider) => {
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
actorOrgId: req.permission.orgId,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
projectId: req.params.projectId
|
||||
});
|
||||
return { bot };
|
||||
@@ -37,8 +42,11 @@ export const registerProjectBotRouter = async (server: FastifyZodProvider) => {
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/:botId/active",
|
||||
method: "PATCH",
|
||||
url: "/:botId/active",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
schema: {
|
||||
body: z.object({
|
||||
isActive: z.boolean(),
|
||||
@@ -70,6 +78,7 @@ export const registerProjectBotRouter = async (server: FastifyZodProvider) => {
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
actorOrgId: req.permission.orgId,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
botId: req.params.botId,
|
||||
botKey: req.body.botKey,
|
||||
isActive: req.body.isActive
|
||||
|
||||
@@ -1,13 +1,19 @@
|
||||
import { z } from "zod";
|
||||
|
||||
import { UNIVERSAL_AUTH } from "@app/lib/api-docs";
|
||||
import { writeLimit } from "@app/server/config/rateLimiter";
|
||||
|
||||
export const registerIdentityAccessTokenRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
url: "/token/renew",
|
||||
method: "POST",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
schema: {
|
||||
description: "Renew access token",
|
||||
body: z.object({
|
||||
accessToken: z.string().trim()
|
||||
accessToken: z.string().trim().describe(UNIVERSAL_AUTH.RENEW_ACCESS_TOKEN.accessToken)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
|
||||
@@ -2,6 +2,8 @@ import { z } from "zod";
|
||||
|
||||
import { IdentitiesSchema, OrgMembershipRole } from "@app/db/schemas";
|
||||
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
|
||||
import { IDENTITIES } from "@app/lib/api-docs";
|
||||
import { creationLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||
import { getTelemetryDistinctId } from "@app/server/lib/telemetry";
|
||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||
import { AuthMode } from "@app/services/auth/auth-type";
|
||||
@@ -11,6 +13,9 @@ export const registerIdentityRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
method: "POST",
|
||||
url: "/",
|
||||
config: {
|
||||
rateLimit: creationLimit
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
schema: {
|
||||
description: "Create identity",
|
||||
@@ -20,9 +25,9 @@ export const registerIdentityRouter = async (server: FastifyZodProvider) => {
|
||||
}
|
||||
],
|
||||
body: z.object({
|
||||
name: z.string().trim(),
|
||||
organizationId: z.string().trim(),
|
||||
role: z.string().trim().min(1).default(OrgMembershipRole.NoAccess)
|
||||
name: z.string().trim().describe(IDENTITIES.CREATE.name),
|
||||
organizationId: z.string().trim().describe(IDENTITIES.CREATE.organizationId),
|
||||
role: z.string().trim().min(1).default(OrgMembershipRole.NoAccess).describe(IDENTITIES.CREATE.role)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
@@ -34,6 +39,7 @@ export const registerIdentityRouter = async (server: FastifyZodProvider) => {
|
||||
const identity = await server.services.identity.createIdentity({
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
...req.body,
|
||||
orgId: req.body.organizationId
|
||||
@@ -69,6 +75,9 @@ export const registerIdentityRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
method: "PATCH",
|
||||
url: "/:identityId",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
schema: {
|
||||
description: "Update identity",
|
||||
@@ -78,11 +87,11 @@ export const registerIdentityRouter = async (server: FastifyZodProvider) => {
|
||||
}
|
||||
],
|
||||
params: z.object({
|
||||
identityId: z.string()
|
||||
identityId: z.string().describe(IDENTITIES.UPDATE.identityId)
|
||||
}),
|
||||
body: z.object({
|
||||
name: z.string().trim().optional(),
|
||||
role: z.string().trim().min(1).optional()
|
||||
name: z.string().trim().optional().describe(IDENTITIES.UPDATE.name),
|
||||
role: z.string().trim().min(1).optional().describe(IDENTITIES.UPDATE.role)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
@@ -94,6 +103,7 @@ export const registerIdentityRouter = async (server: FastifyZodProvider) => {
|
||||
const identity = await server.services.identity.updateIdentity({
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
id: req.params.identityId,
|
||||
...req.body
|
||||
@@ -118,6 +128,9 @@ export const registerIdentityRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
method: "DELETE",
|
||||
url: "/:identityId",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
schema: {
|
||||
description: "Delete identity",
|
||||
@@ -127,7 +140,7 @@ export const registerIdentityRouter = async (server: FastifyZodProvider) => {
|
||||
}
|
||||
],
|
||||
params: z.object({
|
||||
identityId: z.string()
|
||||
identityId: z.string().describe(IDENTITIES.DELETE.identityId)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
@@ -139,6 +152,7 @@ export const registerIdentityRouter = async (server: FastifyZodProvider) => {
|
||||
const identity = await server.services.identity.deleteIdentity({
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
id: req.params.identityId
|
||||
});
|
||||
|
||||
@@ -2,6 +2,8 @@ import { z } from "zod";
|
||||
|
||||
import { IdentityUaClientSecretsSchema, IdentityUniversalAuthsSchema } from "@app/db/schemas";
|
||||
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
|
||||
import { UNIVERSAL_AUTH } from "@app/lib/api-docs";
|
||||
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||
import { AuthMode } from "@app/services/auth/auth-type";
|
||||
import { TIdentityTrustedIp } from "@app/services/identity/identity-types";
|
||||
@@ -21,13 +23,16 @@ export const sanitizedClientSecretSchema = IdentityUaClientSecretsSchema.pick({
|
||||
|
||||
export const registerIdentityUaRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
url: "/universal-auth/login",
|
||||
method: "POST",
|
||||
url: "/universal-auth/login",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
schema: {
|
||||
description: "Login with Universal Auth",
|
||||
body: z.object({
|
||||
clientId: z.string().trim(),
|
||||
clientSecret: z.string().trim()
|
||||
clientId: z.string().trim().describe(UNIVERSAL_AUTH.LOGIN.clientId),
|
||||
clientSecret: z.string().trim().describe(UNIVERSAL_AUTH.LOGIN.clientSecret)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
@@ -65,8 +70,11 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => {
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/universal-auth/identities/:identityId",
|
||||
method: "POST",
|
||||
url: "/universal-auth/identities/:identityId",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
schema: {
|
||||
description: "Attach Universal Auth configuration onto identity",
|
||||
@@ -76,7 +84,7 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => {
|
||||
}
|
||||
],
|
||||
params: z.object({
|
||||
identityId: z.string().trim()
|
||||
identityId: z.string().trim().describe(UNIVERSAL_AUTH.ATTACH.identityId)
|
||||
}),
|
||||
body: z.object({
|
||||
clientSecretTrustedIps: z
|
||||
@@ -85,14 +93,16 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => {
|
||||
})
|
||||
.array()
|
||||
.min(1)
|
||||
.default([{ ipAddress: "0.0.0.0/0" }, { ipAddress: "::/0" }]),
|
||||
.default([{ ipAddress: "0.0.0.0/0" }, { ipAddress: "::/0" }])
|
||||
.describe(UNIVERSAL_AUTH.ATTACH.clientSecretTrustedIps),
|
||||
accessTokenTrustedIps: z
|
||||
.object({
|
||||
ipAddress: z.string().trim()
|
||||
})
|
||||
.array()
|
||||
.min(1)
|
||||
.default([{ ipAddress: "0.0.0.0/0" }, { ipAddress: "::/0" }]),
|
||||
.default([{ ipAddress: "0.0.0.0/0" }, { ipAddress: "::/0" }])
|
||||
.describe(UNIVERSAL_AUTH.ATTACH.accessTokenTrustedIps),
|
||||
accessTokenTTL: z
|
||||
.number()
|
||||
.int()
|
||||
@@ -100,15 +110,22 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => {
|
||||
.refine((value) => value !== 0, {
|
||||
message: "accessTokenTTL must have a non zero number"
|
||||
})
|
||||
.default(2592000),
|
||||
.default(2592000)
|
||||
.describe(UNIVERSAL_AUTH.ATTACH.accessTokenTTL), // 30 days
|
||||
accessTokenMaxTTL: z
|
||||
.number()
|
||||
.int()
|
||||
.refine((value) => value !== 0, {
|
||||
message: "accessTokenMaxTTL must have a non zero number"
|
||||
})
|
||||
.default(2592000), // 30 days
|
||||
accessTokenNumUsesLimit: z.number().int().min(0).default(0)
|
||||
.default(2592000)
|
||||
.describe(UNIVERSAL_AUTH.ATTACH.accessTokenMaxTTL), // 30 days
|
||||
accessTokenNumUsesLimit: z
|
||||
.number()
|
||||
.int()
|
||||
.min(0)
|
||||
.default(0)
|
||||
.describe(UNIVERSAL_AUTH.ATTACH.accessTokenNumUsesLimit)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
@@ -121,6 +138,7 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => {
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
actorOrgId: req.permission.orgId,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
...req.body,
|
||||
identityId: req.params.identityId
|
||||
});
|
||||
@@ -145,8 +163,11 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => {
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/universal-auth/identities/:identityId",
|
||||
method: "PATCH",
|
||||
url: "/universal-auth/identities/:identityId",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
schema: {
|
||||
description: "Update Universal Auth configuration on identity",
|
||||
@@ -156,7 +177,7 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => {
|
||||
}
|
||||
],
|
||||
params: z.object({
|
||||
identityId: z.string()
|
||||
identityId: z.string().describe(UNIVERSAL_AUTH.UPDATE.identityId)
|
||||
}),
|
||||
body: z.object({
|
||||
clientSecretTrustedIps: z
|
||||
@@ -165,16 +186,23 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => {
|
||||
})
|
||||
.array()
|
||||
.min(1)
|
||||
.optional(),
|
||||
.optional()
|
||||
.describe(UNIVERSAL_AUTH.UPDATE.clientSecretTrustedIps),
|
||||
accessTokenTrustedIps: z
|
||||
.object({
|
||||
ipAddress: z.string().trim()
|
||||
})
|
||||
.array()
|
||||
.min(1)
|
||||
.optional(),
|
||||
accessTokenTTL: z.number().int().min(0).optional(),
|
||||
accessTokenNumUsesLimit: z.number().int().min(0).optional(),
|
||||
.optional()
|
||||
.describe(UNIVERSAL_AUTH.UPDATE.accessTokenTrustedIps),
|
||||
accessTokenTTL: z.number().int().min(0).optional().describe(UNIVERSAL_AUTH.UPDATE.accessTokenTTL),
|
||||
accessTokenNumUsesLimit: z
|
||||
.number()
|
||||
.int()
|
||||
.min(0)
|
||||
.optional()
|
||||
.describe(UNIVERSAL_AUTH.UPDATE.accessTokenNumUsesLimit),
|
||||
accessTokenMaxTTL: z
|
||||
.number()
|
||||
.int()
|
||||
@@ -182,6 +210,7 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => {
|
||||
message: "accessTokenMaxTTL must have a non zero number"
|
||||
})
|
||||
.optional()
|
||||
.describe(UNIVERSAL_AUTH.UPDATE.accessTokenMaxTTL)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
@@ -194,6 +223,7 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => {
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
actorOrgId: req.permission.orgId,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
...req.body,
|
||||
identityId: req.params.identityId
|
||||
});
|
||||
@@ -219,8 +249,11 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => {
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/universal-auth/identities/:identityId",
|
||||
method: "GET",
|
||||
url: "/universal-auth/identities/:identityId",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
schema: {
|
||||
description: "Retrieve Universal Auth configuration on identity",
|
||||
@@ -230,7 +263,7 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => {
|
||||
}
|
||||
],
|
||||
params: z.object({
|
||||
identityId: z.string()
|
||||
identityId: z.string().describe(UNIVERSAL_AUTH.RETRIEVE.identityId)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
@@ -242,6 +275,7 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => {
|
||||
const identityUniversalAuth = await server.services.identityUa.getIdentityUa({
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
identityId: req.params.identityId
|
||||
});
|
||||
@@ -262,8 +296,11 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => {
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/universal-auth/identities/:identityId/client-secrets",
|
||||
method: "POST",
|
||||
url: "/universal-auth/identities/:identityId/client-secrets",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
schema: {
|
||||
description: "Create Universal Auth Client Secret for identity",
|
||||
@@ -273,12 +310,12 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => {
|
||||
}
|
||||
],
|
||||
params: z.object({
|
||||
identityId: z.string()
|
||||
identityId: z.string().describe(UNIVERSAL_AUTH.CREATE_CLIENT_SECRET.identityId)
|
||||
}),
|
||||
body: z.object({
|
||||
description: z.string().trim().default(""),
|
||||
numUsesLimit: z.number().min(0).default(0),
|
||||
ttl: z.number().min(0).default(0)
|
||||
description: z.string().trim().default("").describe(UNIVERSAL_AUTH.CREATE_CLIENT_SECRET.description),
|
||||
numUsesLimit: z.number().min(0).default(0).describe(UNIVERSAL_AUTH.CREATE_CLIENT_SECRET.numUsesLimit),
|
||||
ttl: z.number().min(0).default(0).describe(UNIVERSAL_AUTH.CREATE_CLIENT_SECRET.ttl)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
@@ -291,6 +328,7 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => {
|
||||
const { clientSecret, clientSecretData, orgId } = await server.services.identityUa.createUaClientSecret({
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
identityId: req.params.identityId,
|
||||
...req.body
|
||||
@@ -313,8 +351,11 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => {
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/universal-auth/identities/:identityId/client-secrets",
|
||||
method: "GET",
|
||||
url: "/universal-auth/identities/:identityId/client-secrets",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
schema: {
|
||||
description: "List Universal Auth Client Secrets for identity",
|
||||
@@ -324,7 +365,7 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => {
|
||||
}
|
||||
],
|
||||
params: z.object({
|
||||
identityId: z.string()
|
||||
identityId: z.string().describe(UNIVERSAL_AUTH.LIST_CLIENT_SECRETS.identityId)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
@@ -336,6 +377,7 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => {
|
||||
const { clientSecrets: clientSecretData, orgId } = await server.services.identityUa.getUaClientSecrets({
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
identityId: req.params.identityId
|
||||
});
|
||||
@@ -355,8 +397,11 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => {
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/universal-auth/identities/:identityId/client-secrets/:clientSecretId/revoke",
|
||||
method: "POST",
|
||||
url: "/universal-auth/identities/:identityId/client-secrets/:clientSecretId/revoke",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
schema: {
|
||||
description: "Revoke Universal Auth Client Secrets for identity",
|
||||
@@ -366,8 +411,8 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => {
|
||||
}
|
||||
],
|
||||
params: z.object({
|
||||
identityId: z.string(),
|
||||
clientSecretId: z.string()
|
||||
identityId: z.string().describe(UNIVERSAL_AUTH.REVOKE_CLIENT_SECRET.identityId),
|
||||
clientSecretId: z.string().describe(UNIVERSAL_AUTH.REVOKE_CLIENT_SECRET.clientSecretId)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
@@ -379,6 +424,7 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => {
|
||||
const clientSecretData = await server.services.identityUa.revokeUaClientSecret({
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
identityId: req.params.identityId,
|
||||
clientSecretId: req.params.clientSecretId
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { z } from "zod";
|
||||
|
||||
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
|
||||
import { INTEGRATION_AUTH } from "@app/lib/api-docs";
|
||||
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||
import { AuthMode } from "@app/services/auth/auth-type";
|
||||
|
||||
@@ -8,10 +10,19 @@ import { integrationAuthPubSchema } from "../sanitizedSchemas";
|
||||
|
||||
export const registerIntegrationAuthRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
url: "/integration-options",
|
||||
method: "GET",
|
||||
onRequest: verifyAuth([AuthMode.JWT]),
|
||||
url: "/integration-options",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
schema: {
|
||||
description: "List of integrations available.",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: []
|
||||
}
|
||||
],
|
||||
response: {
|
||||
200: z.object({
|
||||
integrationOptions: z
|
||||
@@ -36,12 +47,21 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/:integrationAuthId",
|
||||
method: "GET",
|
||||
onRequest: verifyAuth([AuthMode.JWT]),
|
||||
url: "/:integrationAuthId",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
schema: {
|
||||
description: "Get details of an integration authorization by auth object id.",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: []
|
||||
}
|
||||
],
|
||||
params: z.object({
|
||||
integrationAuthId: z.string().trim()
|
||||
integrationAuthId: z.string().trim().describe(INTEGRATION_AUTH.GET.integrationAuthId)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
@@ -53,6 +73,7 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
|
||||
const integrationAuth = await server.services.integrationAuth.getIntegrationAuth({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
id: req.params.integrationAuthId
|
||||
});
|
||||
@@ -61,13 +82,22 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/",
|
||||
method: "DELETE",
|
||||
onRequest: verifyAuth([AuthMode.JWT]),
|
||||
url: "/",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
schema: {
|
||||
description: "Remove all integration's auth object from the project.",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: []
|
||||
}
|
||||
],
|
||||
querystring: z.object({
|
||||
integration: z.string().trim(),
|
||||
projectId: z.string().trim()
|
||||
integration: z.string().trim().describe(INTEGRATION_AUTH.DELETE.integration),
|
||||
projectId: z.string().trim().describe(INTEGRATION_AUTH.DELETE.projectId)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
@@ -80,6 +110,7 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorOrgId: req.permission.orgId,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
integration: req.query.integration,
|
||||
projectId: req.query.projectId
|
||||
});
|
||||
@@ -100,12 +131,21 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/:integrationAuthId",
|
||||
method: "DELETE",
|
||||
onRequest: verifyAuth([AuthMode.JWT]),
|
||||
url: "/:integrationAuthId",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
schema: {
|
||||
description: "Remove an integration auth object by object id.",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: []
|
||||
}
|
||||
],
|
||||
params: z.object({
|
||||
integrationAuthId: z.string().trim()
|
||||
integrationAuthId: z.string().trim().describe(INTEGRATION_AUTH.DELETE_BY_ID.integrationAuthId)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
@@ -117,6 +157,7 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
|
||||
const integrationAuth = await server.services.integrationAuth.deleteIntegrationAuthById({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
id: req.params.integrationAuthId
|
||||
});
|
||||
@@ -137,8 +178,11 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/oauth-token",
|
||||
method: "POST",
|
||||
url: "/oauth-token",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT]),
|
||||
schema: {
|
||||
body: z.object({
|
||||
@@ -157,6 +201,7 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
|
||||
const integrationAuth = await server.services.integrationAuth.oauthExchange({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
projectId: req.body.workspaceId,
|
||||
...req.body
|
||||
@@ -177,18 +222,27 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/access-token",
|
||||
method: "POST",
|
||||
onRequest: verifyAuth([AuthMode.JWT]),
|
||||
url: "/access-token",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
schema: {
|
||||
description: "Create the integration authentication object required for syncing secrets.",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: []
|
||||
}
|
||||
],
|
||||
body: z.object({
|
||||
workspaceId: z.string().trim(),
|
||||
integration: z.string().trim(),
|
||||
accessId: z.string().trim().optional(),
|
||||
accessToken: z.string().trim().optional(),
|
||||
url: z.string().url().trim().optional(),
|
||||
namespace: z.string().trim().optional(),
|
||||
refreshToken: z.string().trim().optional()
|
||||
workspaceId: z.string().trim().describe(INTEGRATION_AUTH.CREATE_ACCESS_TOKEN.workspaceId),
|
||||
integration: z.string().trim().describe(INTEGRATION_AUTH.CREATE_ACCESS_TOKEN.integration),
|
||||
accessId: z.string().trim().optional().describe(INTEGRATION_AUTH.CREATE_ACCESS_TOKEN.accessId),
|
||||
accessToken: z.string().trim().optional().describe(INTEGRATION_AUTH.CREATE_ACCESS_TOKEN.accessToken),
|
||||
url: z.string().url().trim().optional().describe(INTEGRATION_AUTH.CREATE_ACCESS_TOKEN.url),
|
||||
namespace: z.string().trim().optional().describe(INTEGRATION_AUTH.CREATE_ACCESS_TOKEN.namespace),
|
||||
refreshToken: z.string().trim().optional().describe(INTEGRATION_AUTH.CREATE_ACCESS_TOKEN.refreshToken)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
@@ -200,6 +254,7 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
|
||||
const integrationAuth = await server.services.integrationAuth.saveIntegrationToken({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
projectId: req.body.workspaceId,
|
||||
...req.body
|
||||
@@ -220,8 +275,11 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/:integrationAuthId/apps",
|
||||
method: "GET",
|
||||
url: "/:integrationAuthId/apps",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT]),
|
||||
schema: {
|
||||
params: z.object({
|
||||
@@ -247,6 +305,7 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
|
||||
const apps = await server.services.integrationAuth.getIntegrationApps({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
id: req.params.integrationAuthId,
|
||||
...req.query
|
||||
@@ -256,8 +315,11 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/:integrationAuthId/teams",
|
||||
method: "GET",
|
||||
url: "/:integrationAuthId/teams",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT]),
|
||||
schema: {
|
||||
params: z.object({
|
||||
@@ -278,6 +340,7 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
|
||||
const teams = await server.services.integrationAuth.getIntegrationAuthTeams({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
id: req.params.integrationAuthId
|
||||
});
|
||||
@@ -286,8 +349,11 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/:integrationAuthId/vercel/branches",
|
||||
method: "GET",
|
||||
url: "/:integrationAuthId/vercel/branches",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT]),
|
||||
schema: {
|
||||
params: z.object({
|
||||
@@ -306,6 +372,7 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
|
||||
const branches = await server.services.integrationAuth.getVercelBranches({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
id: req.params.integrationAuthId,
|
||||
appId: req.query.appId
|
||||
@@ -315,8 +382,11 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/:integrationAuthId/checkly/groups",
|
||||
method: "GET",
|
||||
url: "/:integrationAuthId/checkly/groups",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT]),
|
||||
schema: {
|
||||
params: z.object({
|
||||
@@ -335,6 +405,7 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
|
||||
const groups = await server.services.integrationAuth.getChecklyGroups({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
id: req.params.integrationAuthId,
|
||||
accountId: req.query.accountId
|
||||
@@ -344,8 +415,79 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/:integrationAuthId/qovery/orgs",
|
||||
method: "GET",
|
||||
url: "/:integrationAuthId/github/orgs",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT]),
|
||||
schema: {
|
||||
params: z.object({
|
||||
integrationAuthId: z.string().trim()
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
orgs: z.object({ name: z.string(), orgId: z.string() }).array()
|
||||
})
|
||||
}
|
||||
},
|
||||
handler: async (req) => {
|
||||
const orgs = await server.services.integrationAuth.getGithubOrgs({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorOrgId: req.permission.orgId,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
id: req.params.integrationAuthId
|
||||
});
|
||||
if (!orgs) throw new Error("No organization found.");
|
||||
|
||||
return { orgs };
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
method: "GET",
|
||||
url: "/:integrationAuthId/github/envs",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT]),
|
||||
schema: {
|
||||
params: z.object({
|
||||
integrationAuthId: z.string().trim()
|
||||
}),
|
||||
querystring: z.object({
|
||||
repoOwner: z.string().trim(),
|
||||
repoName: z.string().trim()
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
envs: z.object({ name: z.string(), envId: z.string() }).array()
|
||||
})
|
||||
}
|
||||
},
|
||||
handler: async (req) => {
|
||||
const envs = await server.services.integrationAuth.getGithubEnvs({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorOrgId: req.permission.orgId,
|
||||
id: req.params.integrationAuthId,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
repoName: req.query.repoName,
|
||||
repoOwner: req.query.repoOwner
|
||||
});
|
||||
if (!envs) throw new Error("No organization found.");
|
||||
|
||||
return { envs };
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
method: "GET",
|
||||
url: "/:integrationAuthId/qovery/orgs",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT]),
|
||||
schema: {
|
||||
params: z.object({
|
||||
@@ -361,6 +503,7 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
|
||||
const orgs = await server.services.integrationAuth.getQoveryOrgs({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
id: req.params.integrationAuthId
|
||||
});
|
||||
@@ -369,8 +512,44 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/:integrationAuthId/qovery/projects",
|
||||
method: "GET",
|
||||
url: "/:integrationAuthId/aws-secrets-manager/kms-keys",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT]),
|
||||
schema: {
|
||||
params: z.object({
|
||||
integrationAuthId: z.string().trim()
|
||||
}),
|
||||
querystring: z.object({
|
||||
region: z.string().trim()
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
kmsKeys: z.object({ id: z.string(), alias: z.string() }).array()
|
||||
})
|
||||
}
|
||||
},
|
||||
handler: async (req) => {
|
||||
const kmsKeys = await server.services.integrationAuth.getAwsKmsKeys({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
id: req.params.integrationAuthId,
|
||||
region: req.query.region
|
||||
});
|
||||
return { kmsKeys };
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
method: "GET",
|
||||
url: "/:integrationAuthId/qovery/projects",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT]),
|
||||
schema: {
|
||||
params: z.object({
|
||||
@@ -389,6 +568,7 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
|
||||
const projects = await server.services.integrationAuth.getQoveryProjects({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
id: req.params.integrationAuthId,
|
||||
orgId: req.query.orgId
|
||||
@@ -398,8 +578,11 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/:integrationAuthId/qovery/environments",
|
||||
method: "GET",
|
||||
url: "/:integrationAuthId/qovery/environments",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT]),
|
||||
schema: {
|
||||
params: z.object({
|
||||
@@ -418,6 +601,7 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
|
||||
const environments = await server.services.integrationAuth.getQoveryEnvs({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
id: req.params.integrationAuthId,
|
||||
projectId: req.query.projectId
|
||||
@@ -427,8 +611,11 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/:integrationAuthId/qovery/apps",
|
||||
method: "GET",
|
||||
url: "/:integrationAuthId/qovery/apps",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT]),
|
||||
schema: {
|
||||
params: z.object({
|
||||
@@ -447,6 +634,7 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
|
||||
const apps = await server.services.integrationAuth.getQoveryApps({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
id: req.params.integrationAuthId,
|
||||
environmentId: req.query.environmentId
|
||||
@@ -456,8 +644,11 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/:integrationAuthId/qovery/containers",
|
||||
method: "GET",
|
||||
url: "/:integrationAuthId/qovery/containers",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT]),
|
||||
schema: {
|
||||
params: z.object({
|
||||
@@ -476,6 +667,7 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
|
||||
const containers = await server.services.integrationAuth.getQoveryContainers({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
id: req.params.integrationAuthId,
|
||||
environmentId: req.query.environmentId
|
||||
@@ -485,8 +677,11 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/:integrationAuthId/qovery/jobs",
|
||||
method: "GET",
|
||||
url: "/:integrationAuthId/qovery/jobs",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT]),
|
||||
schema: {
|
||||
params: z.object({
|
||||
@@ -505,6 +700,7 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
|
||||
const jobs = await server.services.integrationAuth.getQoveryJobs({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
id: req.params.integrationAuthId,
|
||||
environmentId: req.query.environmentId
|
||||
@@ -514,8 +710,11 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/:integrationAuthId/heroku/pipelines",
|
||||
method: "GET",
|
||||
url: "/:integrationAuthId/heroku/pipelines",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT]),
|
||||
schema: {
|
||||
params: z.object({
|
||||
@@ -537,6 +736,7 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
|
||||
const pipelines = await server.services.integrationAuth.getHerokuPipelines({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
id: req.params.integrationAuthId
|
||||
});
|
||||
@@ -545,8 +745,11 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/:integrationAuthId/railway/environments",
|
||||
method: "GET",
|
||||
url: "/:integrationAuthId/railway/environments",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT]),
|
||||
schema: {
|
||||
params: z.object({
|
||||
@@ -565,6 +768,7 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
|
||||
const environments = await server.services.integrationAuth.getRailwayEnvironments({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
id: req.params.integrationAuthId,
|
||||
appId: req.query.appId
|
||||
@@ -574,8 +778,11 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/:integrationAuthId/railway/services",
|
||||
method: "GET",
|
||||
url: "/:integrationAuthId/railway/services",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT]),
|
||||
schema: {
|
||||
params: z.object({
|
||||
@@ -594,6 +801,7 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
|
||||
const services = await server.services.integrationAuth.getRailwayServices({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
id: req.params.integrationAuthId,
|
||||
appId: req.query.appId
|
||||
@@ -603,8 +811,11 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/:integrationAuthId/bitbucket/workspaces",
|
||||
method: "GET",
|
||||
url: "/:integrationAuthId/bitbucket/workspaces",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT]),
|
||||
schema: {
|
||||
params: z.object({
|
||||
@@ -630,6 +841,7 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
|
||||
const workspaces = await server.services.integrationAuth.getBitbucketWorkspaces({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
id: req.params.integrationAuthId
|
||||
});
|
||||
@@ -638,8 +850,11 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/:integrationAuthId/northflank/secret-groups",
|
||||
method: "GET",
|
||||
url: "/:integrationAuthId/northflank/secret-groups",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT]),
|
||||
schema: {
|
||||
params: z.object({
|
||||
@@ -663,6 +878,7 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
|
||||
const secretGroups = await server.services.integrationAuth.getNorthFlankSecretGroups({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
id: req.params.integrationAuthId,
|
||||
appId: req.query.appId
|
||||
@@ -672,8 +888,11 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/:integrationAuthId/teamcity/build-configs",
|
||||
method: "GET",
|
||||
url: "/:integrationAuthId/teamcity/build-configs",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT]),
|
||||
schema: {
|
||||
params: z.object({
|
||||
@@ -697,6 +916,7 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
|
||||
const buildConfigs = await server.services.integrationAuth.getTeamcityBuildConfigs({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
id: req.params.integrationAuthId,
|
||||
appId: req.query.appId
|
||||
|
||||
@@ -2,7 +2,9 @@ import { z } from "zod";
|
||||
|
||||
import { IntegrationsSchema } from "@app/db/schemas";
|
||||
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
|
||||
import { INTEGRATION } from "@app/lib/api-docs";
|
||||
import { removeTrailingSlash, shake } from "@app/lib/fn";
|
||||
import { writeLimit } from "@app/server/config/rateLimiter";
|
||||
import { getTelemetryDistinctId } from "@app/server/lib/telemetry";
|
||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||
import { AuthMode } from "@app/services/auth/auth-type";
|
||||
@@ -10,37 +12,63 @@ import { PostHogEventTypes, TIntegrationCreatedEvent } from "@app/services/telem
|
||||
|
||||
export const registerIntegrationRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
url: "/",
|
||||
method: "POST",
|
||||
url: "/",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
schema: {
|
||||
description: "Create an integration to sync secrets.",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: []
|
||||
}
|
||||
],
|
||||
body: z.object({
|
||||
integrationAuthId: z.string().trim(),
|
||||
app: z.string().trim().optional(),
|
||||
isActive: z.boolean(),
|
||||
appId: z.string().trim().optional(),
|
||||
secretPath: z.string().trim().default("/").transform(removeTrailingSlash),
|
||||
sourceEnvironment: z.string().trim(),
|
||||
targetEnvironment: z.string().trim().optional(),
|
||||
targetEnvironmentId: z.string().trim().optional(),
|
||||
targetService: z.string().trim().optional(),
|
||||
targetServiceId: z.string().trim().optional(),
|
||||
owner: z.string().trim().optional(),
|
||||
path: z.string().trim().optional(),
|
||||
region: z.string().trim().optional(),
|
||||
scope: z.string().trim().optional(),
|
||||
integrationAuthId: z.string().trim().describe(INTEGRATION.CREATE.integrationAuthId),
|
||||
app: z.string().trim().optional().describe(INTEGRATION.CREATE.app),
|
||||
isActive: z.boolean().describe(INTEGRATION.CREATE.isActive).default(true),
|
||||
appId: z.string().trim().optional().describe(INTEGRATION.CREATE.appId),
|
||||
secretPath: z
|
||||
.string()
|
||||
.trim()
|
||||
.default("/")
|
||||
.transform(removeTrailingSlash)
|
||||
.describe(INTEGRATION.CREATE.secretPath),
|
||||
sourceEnvironment: z.string().trim().describe(INTEGRATION.CREATE.sourceEnvironment),
|
||||
targetEnvironment: z.string().trim().optional().describe(INTEGRATION.CREATE.targetEnvironment),
|
||||
targetEnvironmentId: z.string().trim().optional().describe(INTEGRATION.CREATE.targetEnvironmentId),
|
||||
targetService: z.string().trim().optional().describe(INTEGRATION.CREATE.targetService),
|
||||
targetServiceId: z.string().trim().optional().describe(INTEGRATION.CREATE.targetServiceId),
|
||||
owner: z.string().trim().optional().describe(INTEGRATION.CREATE.owner),
|
||||
path: z.string().trim().optional().describe(INTEGRATION.CREATE.path),
|
||||
region: z.string().trim().optional().describe(INTEGRATION.CREATE.region),
|
||||
scope: z.string().trim().optional().describe(INTEGRATION.CREATE.scope),
|
||||
metadata: z
|
||||
.object({
|
||||
secretPrefix: z.string().optional(),
|
||||
secretSuffix: z.string().optional(),
|
||||
initialSyncBehavior: z.string().optional(),
|
||||
secretPrefix: z.string().optional().describe(INTEGRATION.CREATE.metadata.secretPrefix),
|
||||
secretSuffix: z.string().optional().describe(INTEGRATION.CREATE.metadata.secretSuffix),
|
||||
initialSyncBehavior: z.string().optional().describe(INTEGRATION.CREATE.metadata.initialSyncBehavoir),
|
||||
shouldAutoRedeploy: z.boolean().optional().describe(INTEGRATION.CREATE.metadata.shouldAutoRedeploy),
|
||||
secretGCPLabel: z
|
||||
.object({
|
||||
labelName: z.string(),
|
||||
labelValue: z.string()
|
||||
})
|
||||
.optional()
|
||||
.describe(INTEGRATION.CREATE.metadata.secretGCPLabel),
|
||||
secretAWSTag: z
|
||||
.array(
|
||||
z.object({
|
||||
key: z.string(),
|
||||
value: z.string()
|
||||
})
|
||||
)
|
||||
.optional()
|
||||
.describe(INTEGRATION.CREATE.metadata.secretAWSTag),
|
||||
kmsKeyId: z.string().optional().describe(INTEGRATION.CREATE.metadata.kmsKeyId)
|
||||
})
|
||||
.optional()
|
||||
.default({})
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
@@ -48,11 +76,12 @@ export const registerIntegrationRouter = async (server: FastifyZodProvider) => {
|
||||
})
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT]),
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
handler: async (req) => {
|
||||
const { integration, integrationAuth } = await server.services.integration.createIntegration({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
...req.body
|
||||
});
|
||||
@@ -97,20 +126,34 @@ export const registerIntegrationRouter = async (server: FastifyZodProvider) => {
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/:integrationId",
|
||||
method: "PATCH",
|
||||
url: "/:integrationId",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
schema: {
|
||||
description: "Update an integration by integration id",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: []
|
||||
}
|
||||
],
|
||||
params: z.object({
|
||||
integrationId: z.string().trim()
|
||||
integrationId: z.string().trim().describe(INTEGRATION.UPDATE.integrationId)
|
||||
}),
|
||||
body: z.object({
|
||||
app: z.string().trim(),
|
||||
appId: z.string().trim(),
|
||||
isActive: z.boolean(),
|
||||
secretPath: z.string().trim().default("/").transform(removeTrailingSlash),
|
||||
targetEnvironment: z.string().trim(),
|
||||
owner: z.string().trim(),
|
||||
environment: z.string().trim()
|
||||
app: z.string().trim().describe(INTEGRATION.UPDATE.app),
|
||||
appId: z.string().trim().describe(INTEGRATION.UPDATE.appId),
|
||||
isActive: z.boolean().describe(INTEGRATION.UPDATE.isActive),
|
||||
secretPath: z
|
||||
.string()
|
||||
.trim()
|
||||
.default("/")
|
||||
.transform(removeTrailingSlash)
|
||||
.describe(INTEGRATION.UPDATE.secretPath),
|
||||
targetEnvironment: z.string().trim().describe(INTEGRATION.UPDATE.targetEnvironment),
|
||||
owner: z.string().trim().describe(INTEGRATION.UPDATE.owner),
|
||||
environment: z.string().trim().describe(INTEGRATION.UPDATE.environment)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
@@ -118,11 +161,12 @@ export const registerIntegrationRouter = async (server: FastifyZodProvider) => {
|
||||
})
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT]),
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
handler: async (req) => {
|
||||
const integration = await server.services.integration.updateIntegration({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
id: req.params.integrationId,
|
||||
...req.body
|
||||
@@ -132,11 +176,20 @@ export const registerIntegrationRouter = async (server: FastifyZodProvider) => {
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/:integrationId",
|
||||
method: "DELETE",
|
||||
url: "/:integrationId",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
schema: {
|
||||
description: "Remove an integration using the integration object ID",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: []
|
||||
}
|
||||
],
|
||||
params: z.object({
|
||||
integrationId: z.string().trim()
|
||||
integrationId: z.string().trim().describe(INTEGRATION.DELETE.integrationId)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
@@ -144,10 +197,11 @@ export const registerIntegrationRouter = async (server: FastifyZodProvider) => {
|
||||
})
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT]),
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
handler: async (req) => {
|
||||
const integration = await server.services.integration.deleteIntegration({
|
||||
actorId: req.permission.id,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actor: req.permission.type,
|
||||
actorOrgId: req.permission.orgId,
|
||||
id: req.params.integrationId
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { z } from "zod";
|
||||
|
||||
import { UsersSchema } from "@app/db/schemas";
|
||||
import { inviteUserRateLimit } from "@app/server/config/rateLimiter";
|
||||
import { getTelemetryDistinctId } from "@app/server/lib/telemetry";
|
||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||
import { ActorType, AuthMode } from "@app/services/auth/auth-type";
|
||||
@@ -9,6 +10,9 @@ import { PostHogEventTypes } from "@app/services/telemetry/telemetry-types";
|
||||
export const registerInviteOrgRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
url: "/signup",
|
||||
config: {
|
||||
rateLimit: inviteUserRateLimit
|
||||
},
|
||||
method: "POST",
|
||||
schema: {
|
||||
body: z.object({
|
||||
@@ -29,6 +33,7 @@ export const registerInviteOrgRouter = async (server: FastifyZodProvider) => {
|
||||
orgId: req.body.organizationId,
|
||||
userId: req.permission.id,
|
||||
inviteeEmail: req.body.inviteeEmail,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId
|
||||
});
|
||||
|
||||
@@ -51,6 +56,9 @@ export const registerInviteOrgRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
url: "/verify",
|
||||
method: "POST",
|
||||
config: {
|
||||
rateLimit: inviteUserRateLimit
|
||||
},
|
||||
schema: {
|
||||
body: z.object({
|
||||
email: z.string().trim().email(),
|
||||
|
||||
@@ -1,6 +1,15 @@
|
||||
import { z } from "zod";
|
||||
|
||||
import { IncidentContactsSchema, OrganizationsSchema, OrgMembershipsSchema, UsersSchema } from "@app/db/schemas";
|
||||
import {
|
||||
GroupsSchema,
|
||||
IncidentContactsSchema,
|
||||
OrganizationsSchema,
|
||||
OrgMembershipsSchema,
|
||||
OrgRolesSchema,
|
||||
UsersSchema
|
||||
} from "@app/db/schemas";
|
||||
import { ORGANIZATIONS } from "@app/lib/api-docs";
|
||||
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||
import { AuthMode } from "@app/services/auth/auth-type";
|
||||
|
||||
@@ -8,6 +17,9 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
method: "GET",
|
||||
url: "/",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
schema: {
|
||||
response: {
|
||||
200: z.object({
|
||||
@@ -15,7 +27,7 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
|
||||
})
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT]),
|
||||
onRequest: verifyAuth([AuthMode.JWT], { requireOrg: false }),
|
||||
handler: async (req) => {
|
||||
const organizations = await server.services.org.findAllOrganizationOfUser(req.permission.id);
|
||||
return { organizations };
|
||||
@@ -25,6 +37,9 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
method: "GET",
|
||||
url: "/:organizationId",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
schema: {
|
||||
params: z.object({
|
||||
organizationId: z.string().trim()
|
||||
@@ -40,6 +55,7 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
|
||||
const organization = await server.services.org.findOrganizationById(
|
||||
req.permission.id,
|
||||
req.params.organizationId,
|
||||
req.permission.authMethod,
|
||||
req.permission.orgId
|
||||
);
|
||||
return { organization };
|
||||
@@ -49,6 +65,9 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
method: "GET",
|
||||
url: "/:organizationId/users",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
schema: {
|
||||
params: z.object({
|
||||
organizationId: z.string().trim()
|
||||
@@ -76,6 +95,7 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
|
||||
const users = await server.services.org.findAllOrgMembers(
|
||||
req.permission.id,
|
||||
req.params.organizationId,
|
||||
req.permission.authMethod,
|
||||
req.permission.orgId
|
||||
);
|
||||
return { users };
|
||||
@@ -85,6 +105,9 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
method: "PATCH",
|
||||
url: "/:organizationId",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
schema: {
|
||||
params: z.object({ organizationId: z.string().trim() }),
|
||||
body: z.object({
|
||||
@@ -111,6 +134,7 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
actorOrgId: req.permission.orgId,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
orgId: req.params.organizationId,
|
||||
data: req.body
|
||||
});
|
||||
@@ -125,6 +149,9 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
method: "GET",
|
||||
url: "/:organizationId/incidentContactOrg",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
schema: {
|
||||
params: z.object({ organizationId: z.string().trim() }),
|
||||
response: {
|
||||
@@ -138,6 +165,7 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
|
||||
const incidentContactsOrg = await req.server.services.org.findIncidentContacts(
|
||||
req.permission.id,
|
||||
req.params.organizationId,
|
||||
req.permission.authMethod,
|
||||
req.permission.orgId
|
||||
);
|
||||
return { incidentContactsOrg };
|
||||
@@ -147,6 +175,9 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
method: "POST",
|
||||
url: "/:organizationId/incidentContactOrg",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
schema: {
|
||||
params: z.object({ organizationId: z.string().trim() }),
|
||||
body: z.object({ email: z.string().email().trim() }),
|
||||
@@ -162,6 +193,7 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
|
||||
req.permission.id,
|
||||
req.params.organizationId,
|
||||
req.body.email,
|
||||
req.permission.authMethod,
|
||||
req.permission.orgId
|
||||
);
|
||||
return { incidentContactsOrg };
|
||||
@@ -171,6 +203,9 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
method: "DELETE",
|
||||
url: "/:organizationId/incidentContactOrg/:incidentContactId",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
schema: {
|
||||
params: z.object({ organizationId: z.string().trim(), incidentContactId: z.string().trim() }),
|
||||
response: {
|
||||
@@ -185,9 +220,47 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
|
||||
req.permission.id,
|
||||
req.params.organizationId,
|
||||
req.params.incidentContactId,
|
||||
req.permission.authMethod,
|
||||
req.permission.orgId
|
||||
);
|
||||
return { incidentContactsOrg };
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
method: "GET",
|
||||
url: "/:organizationId/groups",
|
||||
schema: {
|
||||
params: z.object({
|
||||
organizationId: z.string().trim().describe(ORGANIZATIONS.LIST_GROUPS.organizationId)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
groups: GroupsSchema.merge(
|
||||
z.object({
|
||||
customRole: OrgRolesSchema.pick({
|
||||
id: true,
|
||||
name: true,
|
||||
slug: true,
|
||||
permissions: true,
|
||||
description: true
|
||||
}).optional()
|
||||
})
|
||||
).array()
|
||||
})
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT]),
|
||||
handler: async (req) => {
|
||||
const groups = await server.services.org.getOrgGroups({
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
orgId: req.params.organizationId,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId
|
||||
});
|
||||
|
||||
return { groups };
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@@ -2,7 +2,7 @@ import { z } from "zod";
|
||||
|
||||
import { BackupPrivateKeySchema, UsersSchema } from "@app/db/schemas";
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import { passwordRateLimit } from "@app/server/config/rateLimiter";
|
||||
import { authRateLimit } from "@app/server/config/rateLimiter";
|
||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||
import { validateSignUpAuthorization } from "@app/services/auth/auth-fns";
|
||||
import { AuthMode } from "@app/services/auth/auth-type";
|
||||
@@ -12,7 +12,7 @@ export const registerPasswordRouter = async (server: FastifyZodProvider) => {
|
||||
method: "POST",
|
||||
url: "/srp1",
|
||||
config: {
|
||||
rateLimit: passwordRateLimit
|
||||
rateLimit: authRateLimit
|
||||
},
|
||||
schema: {
|
||||
body: z.object({
|
||||
@@ -39,7 +39,7 @@ export const registerPasswordRouter = async (server: FastifyZodProvider) => {
|
||||
method: "POST",
|
||||
url: "/change-password",
|
||||
config: {
|
||||
rateLimit: passwordRateLimit
|
||||
rateLimit: authRateLimit
|
||||
},
|
||||
schema: {
|
||||
body: z.object({
|
||||
@@ -78,7 +78,7 @@ export const registerPasswordRouter = async (server: FastifyZodProvider) => {
|
||||
method: "POST",
|
||||
url: "/email/password-reset",
|
||||
config: {
|
||||
rateLimit: passwordRateLimit
|
||||
rateLimit: authRateLimit
|
||||
},
|
||||
schema: {
|
||||
body: z.object({
|
||||
@@ -103,7 +103,7 @@ export const registerPasswordRouter = async (server: FastifyZodProvider) => {
|
||||
method: "POST",
|
||||
url: "/email/password-reset-verify",
|
||||
config: {
|
||||
rateLimit: passwordRateLimit
|
||||
rateLimit: authRateLimit
|
||||
},
|
||||
schema: {
|
||||
body: z.object({
|
||||
@@ -133,7 +133,7 @@ export const registerPasswordRouter = async (server: FastifyZodProvider) => {
|
||||
method: "POST",
|
||||
url: "/backup-private-key",
|
||||
config: {
|
||||
rateLimit: passwordRateLimit
|
||||
rateLimit: authRateLimit
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT]),
|
||||
schema: {
|
||||
@@ -168,7 +168,7 @@ export const registerPasswordRouter = async (server: FastifyZodProvider) => {
|
||||
method: "GET",
|
||||
url: "/backup-private-key",
|
||||
config: {
|
||||
rateLimit: passwordRateLimit
|
||||
rateLimit: authRateLimit
|
||||
},
|
||||
schema: {
|
||||
response: {
|
||||
@@ -190,6 +190,9 @@ export const registerPasswordRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
method: "POST",
|
||||
url: "/password-reset",
|
||||
config: {
|
||||
rateLimit: authRateLimit
|
||||
},
|
||||
schema: {
|
||||
body: z.object({
|
||||
protectedKey: z.string().trim(),
|
||||
|
||||
@@ -3,32 +3,37 @@ import { z } from "zod";
|
||||
|
||||
import { ProjectEnvironmentsSchema } from "@app/db/schemas";
|
||||
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
|
||||
import { ENVIRONMENTS } from "@app/lib/api-docs";
|
||||
import { writeLimit } from "@app/server/config/rateLimiter";
|
||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||
import { AuthMode } from "@app/services/auth/auth-type";
|
||||
|
||||
export const registerProjectEnvRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
url: "/:workspaceId/environments",
|
||||
method: "POST",
|
||||
url: "/:workspaceId/environments",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
schema: {
|
||||
description: "Create environment",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: [],
|
||||
apiKeyAuth: []
|
||||
bearerAuth: []
|
||||
}
|
||||
],
|
||||
params: z.object({
|
||||
workspaceId: z.string().trim()
|
||||
workspaceId: z.string().trim().describe(ENVIRONMENTS.CREATE.workspaceId)
|
||||
}),
|
||||
body: z.object({
|
||||
name: z.string().trim(),
|
||||
name: z.string().trim().describe(ENVIRONMENTS.CREATE.name),
|
||||
slug: z
|
||||
.string()
|
||||
.trim()
|
||||
.refine((v) => slugify(v) === v, {
|
||||
message: "Slug must be a valid slug"
|
||||
})
|
||||
.describe(ENVIRONMENTS.CREATE.slug)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
@@ -44,6 +49,7 @@ export const registerProjectEnvRouter = async (server: FastifyZodProvider) => {
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorOrgId: req.permission.orgId,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
projectId: req.params.workspaceId,
|
||||
...req.body
|
||||
});
|
||||
@@ -68,28 +74,33 @@ export const registerProjectEnvRouter = async (server: FastifyZodProvider) => {
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/:workspaceId/environments/:id",
|
||||
method: "PATCH",
|
||||
url: "/:workspaceId/environments/:id",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
schema: {
|
||||
description: "Update environment",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: [],
|
||||
apiKeyAuth: []
|
||||
bearerAuth: []
|
||||
}
|
||||
],
|
||||
params: z.object({
|
||||
workspaceId: z.string().trim(),
|
||||
id: z.string().trim()
|
||||
workspaceId: z.string().trim().describe(ENVIRONMENTS.UPDATE.workspaceId),
|
||||
id: z.string().trim().describe(ENVIRONMENTS.UPDATE.id)
|
||||
}),
|
||||
body: z.object({
|
||||
slug: z
|
||||
.string()
|
||||
.regex(/^[^./]*$/g)
|
||||
.trim()
|
||||
.optional(),
|
||||
name: z.string().trim().optional(),
|
||||
position: z.number().optional()
|
||||
.optional()
|
||||
.refine((v) => !v || slugify(v) === v, {
|
||||
message: "Slug must be a valid slug"
|
||||
})
|
||||
.describe(ENVIRONMENTS.UPDATE.slug),
|
||||
name: z.string().trim().optional().describe(ENVIRONMENTS.UPDATE.name),
|
||||
position: z.number().optional().describe(ENVIRONMENTS.UPDATE.position)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
@@ -104,6 +115,7 @@ export const registerProjectEnvRouter = async (server: FastifyZodProvider) => {
|
||||
const { environment, old } = await server.services.projectEnv.updateEnvironment({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
projectId: req.params.workspaceId,
|
||||
id: req.params.id,
|
||||
@@ -135,19 +147,21 @@ export const registerProjectEnvRouter = async (server: FastifyZodProvider) => {
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/:workspaceId/environments/:id",
|
||||
method: "DELETE",
|
||||
url: "/:workspaceId/environments/:id",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
schema: {
|
||||
description: "Delete environment",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: [],
|
||||
apiKeyAuth: []
|
||||
bearerAuth: []
|
||||
}
|
||||
],
|
||||
params: z.object({
|
||||
workspaceId: z.string().trim(),
|
||||
id: z.string().trim()
|
||||
workspaceId: z.string().trim().describe(ENVIRONMENTS.DELETE.workspaceId),
|
||||
id: z.string().trim().describe(ENVIRONMENTS.DELETE.id)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
@@ -162,6 +176,7 @@ export const registerProjectEnvRouter = async (server: FastifyZodProvider) => {
|
||||
const environment = await server.services.projectEnv.deleteEnvironment({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
projectId: req.params.workspaceId,
|
||||
id: req.params.id
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { z } from "zod";
|
||||
|
||||
import { writeLimit } from "@app/server/config/rateLimiter";
|
||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||
import { AuthMode } from "@app/services/auth/auth-type";
|
||||
|
||||
@@ -7,6 +8,9 @@ export const registerProjectKeyRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
url: "/:workspaceId/key",
|
||||
method: "POST",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
schema: {
|
||||
params: z.object({
|
||||
workspaceId: z.string().trim()
|
||||
@@ -30,6 +34,7 @@ export const registerProjectKeyRouter = async (server: FastifyZodProvider) => {
|
||||
projectId: req.params.workspaceId,
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
nonce: req.body.key.nonce,
|
||||
receiverId: req.body.key.userId,
|
||||
|
||||
@@ -9,52 +9,53 @@ import {
|
||||
UsersSchema
|
||||
} from "@app/db/schemas";
|
||||
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
|
||||
import { PROJECTS } from "@app/lib/api-docs";
|
||||
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||
import { AuthMode } from "@app/services/auth/auth-type";
|
||||
import { ProjectUserMembershipTemporaryMode } from "@app/services/project-membership/project-membership-types";
|
||||
|
||||
export const registerProjectMembershipRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
url: "/:workspaceId/memberships",
|
||||
method: "GET",
|
||||
url: "/:workspaceId/memberships",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
schema: {
|
||||
description: "Return project user memberships",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: [],
|
||||
apiKeyAuth: []
|
||||
bearerAuth: []
|
||||
}
|
||||
],
|
||||
params: z.object({
|
||||
workspaceId: z.string().trim()
|
||||
workspaceId: z.string().trim().describe(PROJECTS.GET_USER_MEMBERSHIPS.workspaceId)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
memberships: ProjectMembershipsSchema.omit({ role: true })
|
||||
.merge(
|
||||
memberships: ProjectMembershipsSchema.extend({
|
||||
user: UsersSchema.pick({
|
||||
email: true,
|
||||
firstName: true,
|
||||
lastName: true,
|
||||
id: true
|
||||
}).merge(UserEncryptionKeysSchema.pick({ publicKey: true })),
|
||||
roles: z.array(
|
||||
z.object({
|
||||
user: UsersSchema.pick({
|
||||
email: true,
|
||||
firstName: true,
|
||||
lastName: true,
|
||||
id: true
|
||||
}).merge(UserEncryptionKeysSchema.pick({ publicKey: true })),
|
||||
roles: z.array(
|
||||
z.object({
|
||||
id: z.string(),
|
||||
role: z.string(),
|
||||
customRoleId: z.string().optional().nullable(),
|
||||
customRoleName: z.string().optional().nullable(),
|
||||
customRoleSlug: z.string().optional().nullable(),
|
||||
isTemporary: z.boolean(),
|
||||
temporaryMode: z.string().optional().nullable(),
|
||||
temporaryRange: z.string().nullable().optional(),
|
||||
temporaryAccessStartTime: z.date().nullable().optional(),
|
||||
temporaryAccessEndTime: z.date().nullable().optional()
|
||||
})
|
||||
)
|
||||
id: z.string(),
|
||||
role: z.string(),
|
||||
customRoleId: z.string().optional().nullable(),
|
||||
customRoleName: z.string().optional().nullable(),
|
||||
customRoleSlug: z.string().optional().nullable(),
|
||||
isTemporary: z.boolean(),
|
||||
temporaryMode: z.string().optional().nullable(),
|
||||
temporaryRange: z.string().nullable().optional(),
|
||||
temporaryAccessStartTime: z.date().nullable().optional(),
|
||||
temporaryAccessEndTime: z.date().nullable().optional()
|
||||
})
|
||||
)
|
||||
})
|
||||
.omit({ createdAt: true, updatedAt: true })
|
||||
.array()
|
||||
})
|
||||
@@ -65,6 +66,7 @@ export const registerProjectMembershipRouter = async (server: FastifyZodProvider
|
||||
const memberships = await server.services.projectMembership.getProjectMemberships({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
projectId: req.params.workspaceId
|
||||
});
|
||||
@@ -73,8 +75,11 @@ export const registerProjectMembershipRouter = async (server: FastifyZodProvider
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/:workspaceId/memberships",
|
||||
method: "POST",
|
||||
url: "/:workspaceId/memberships",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
schema: {
|
||||
params: z.object({
|
||||
workspaceId: z.string().trim()
|
||||
@@ -101,6 +106,7 @@ export const registerProjectMembershipRouter = async (server: FastifyZodProvider
|
||||
const data = await server.services.projectMembership.addUsersToProject({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
projectId: req.params.workspaceId,
|
||||
members: req.body.members
|
||||
@@ -123,19 +129,21 @@ export const registerProjectMembershipRouter = async (server: FastifyZodProvider
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/:workspaceId/memberships/:membershipId",
|
||||
method: "PATCH",
|
||||
url: "/:workspaceId/memberships/:membershipId",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
schema: {
|
||||
description: "Update project user membership",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: [],
|
||||
apiKeyAuth: []
|
||||
bearerAuth: []
|
||||
}
|
||||
],
|
||||
params: z.object({
|
||||
workspaceId: z.string().trim(),
|
||||
membershipId: z.string().trim()
|
||||
workspaceId: z.string().trim().describe(PROJECTS.UPDATE_USER_MEMBERSHIP.workspaceId),
|
||||
membershipId: z.string().trim().describe(PROJECTS.UPDATE_USER_MEMBERSHIP.membershipId)
|
||||
}),
|
||||
body: z.object({
|
||||
roles: z
|
||||
@@ -155,7 +163,8 @@ export const registerProjectMembershipRouter = async (server: FastifyZodProvider
|
||||
])
|
||||
)
|
||||
.min(1)
|
||||
.refine((data) => data.some(({ isTemporary }) => !isTemporary), "At least long lived role is required")
|
||||
.refine((data) => data.some(({ isTemporary }) => !isTemporary), "At least one long lived role is required")
|
||||
.describe(PROJECTS.UPDATE_USER_MEMBERSHIP.roles)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
@@ -168,6 +177,7 @@ export const registerProjectMembershipRouter = async (server: FastifyZodProvider
|
||||
const roles = await server.services.projectMembership.updateProjectMembership({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
projectId: req.params.workspaceId,
|
||||
membershipId: req.params.membershipId,
|
||||
@@ -192,14 +202,16 @@ export const registerProjectMembershipRouter = async (server: FastifyZodProvider
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/:workspaceId/memberships/:membershipId",
|
||||
method: "DELETE",
|
||||
url: "/:workspaceId/memberships/:membershipId",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
schema: {
|
||||
description: "Delete project user membership",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: [],
|
||||
apiKeyAuth: []
|
||||
bearerAuth: []
|
||||
}
|
||||
],
|
||||
params: z.object({
|
||||
@@ -217,6 +229,7 @@ export const registerProjectMembershipRouter = async (server: FastifyZodProvider
|
||||
const membership = await server.services.projectMembership.deleteProjectMembership({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
projectId: req.params.workspaceId,
|
||||
membershipId: req.params.membershipId
|
||||
|
||||
@@ -7,8 +7,11 @@ import {
|
||||
UserEncryptionKeysSchema,
|
||||
UsersSchema
|
||||
} from "@app/db/schemas";
|
||||
import { PROJECTS } from "@app/lib/api-docs";
|
||||
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||
import { AuthMode } from "@app/services/auth/auth-type";
|
||||
import { ProjectFilterType } from "@app/services/project/project-types";
|
||||
|
||||
import { integrationAuthPubSchema } from "../sanitizedSchemas";
|
||||
import { sanitizedServiceTokenSchema } from "../v2/service-token-router";
|
||||
@@ -22,8 +25,11 @@ const projectWithEnv = ProjectsSchema.merge(
|
||||
|
||||
export const registerProjectRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
url: "/:workspaceId/keys",
|
||||
method: "GET",
|
||||
url: "/:workspaceId/keys",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
schema: {
|
||||
params: z.object({
|
||||
workspaceId: z.string().trim()
|
||||
@@ -44,6 +50,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
|
||||
const publicKeys = await server.services.projectKey.getProjectPublicKeys({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
projectId: req.params.workspaceId
|
||||
});
|
||||
@@ -52,40 +59,40 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/:workspaceId/users",
|
||||
method: "GET",
|
||||
url: "/:workspaceId/users",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
schema: {
|
||||
params: z.object({
|
||||
workspaceId: z.string().trim()
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
users: ProjectMembershipsSchema.omit({ role: true })
|
||||
.merge(
|
||||
users: ProjectMembershipsSchema.extend({
|
||||
user: UsersSchema.pick({
|
||||
email: true,
|
||||
username: true,
|
||||
firstName: true,
|
||||
lastName: true,
|
||||
id: true
|
||||
}).merge(UserEncryptionKeysSchema.pick({ publicKey: true })),
|
||||
roles: z.array(
|
||||
z.object({
|
||||
user: UsersSchema.pick({
|
||||
username: true,
|
||||
email: true,
|
||||
firstName: true,
|
||||
lastName: true,
|
||||
id: true
|
||||
}).merge(UserEncryptionKeysSchema.pick({ publicKey: true })),
|
||||
roles: z.array(
|
||||
z.object({
|
||||
id: z.string(),
|
||||
role: z.string(),
|
||||
customRoleId: z.string().optional().nullable(),
|
||||
customRoleName: z.string().optional().nullable(),
|
||||
customRoleSlug: z.string().optional().nullable(),
|
||||
isTemporary: z.boolean(),
|
||||
temporaryMode: z.string().optional().nullable(),
|
||||
temporaryRange: z.string().nullable().optional(),
|
||||
temporaryAccessStartTime: z.date().nullable().optional(),
|
||||
temporaryAccessEndTime: z.date().nullable().optional()
|
||||
})
|
||||
)
|
||||
id: z.string(),
|
||||
role: z.string(),
|
||||
customRoleId: z.string().optional().nullable(),
|
||||
customRoleName: z.string().optional().nullable(),
|
||||
customRoleSlug: z.string().optional().nullable(),
|
||||
isTemporary: z.boolean(),
|
||||
temporaryMode: z.string().optional().nullable(),
|
||||
temporaryRange: z.string().nullable().optional(),
|
||||
temporaryAccessStartTime: z.date().nullable().optional(),
|
||||
temporaryAccessEndTime: z.date().nullable().optional()
|
||||
})
|
||||
)
|
||||
})
|
||||
.omit({ createdAt: true, updatedAt: true })
|
||||
.array()
|
||||
})
|
||||
@@ -96,6 +103,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
|
||||
const users = await server.services.projectMembership.getProjectMemberships({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
projectId: req.params.workspaceId,
|
||||
actorOrgId: req.permission.orgId
|
||||
});
|
||||
@@ -104,8 +112,11 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/",
|
||||
method: "GET",
|
||||
url: "/",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
schema: {
|
||||
response: {
|
||||
200: z.object({
|
||||
@@ -121,11 +132,20 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/:workspaceId",
|
||||
method: "GET",
|
||||
url: "/:workspaceId",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
schema: {
|
||||
description: "Get project",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: []
|
||||
}
|
||||
],
|
||||
params: z.object({
|
||||
workspaceId: z.string().trim()
|
||||
workspaceId: z.string().trim().describe(PROJECTS.GET.workspaceId)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
@@ -136,48 +156,34 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.SERVICE_TOKEN, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
handler: async (req) => {
|
||||
const workspace = await server.services.project.getAProject({
|
||||
filter: {
|
||||
type: ProjectFilterType.ID,
|
||||
projectId: req.params.workspaceId
|
||||
},
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorOrgId: req.permission.orgId,
|
||||
projectId: req.params.workspaceId
|
||||
actorOrgId: req.permission.orgId
|
||||
});
|
||||
return { workspace };
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/",
|
||||
method: "POST",
|
||||
schema: {
|
||||
body: z.object({
|
||||
workspaceName: z.string().trim(),
|
||||
organizationId: z.string().trim()
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
workspace: projectWithEnv
|
||||
})
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT]),
|
||||
handler: async (req) => {
|
||||
const workspace = await server.services.project.createProject({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
orgId: req.body.organizationId,
|
||||
actorOrgId: req.permission.orgId,
|
||||
workspaceName: req.body.workspaceName
|
||||
});
|
||||
return { workspace };
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/:workspaceId",
|
||||
method: "DELETE",
|
||||
url: "/:workspaceId",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
schema: {
|
||||
description: "Delete project",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: []
|
||||
}
|
||||
],
|
||||
params: z.object({
|
||||
workspaceId: z.string().trim()
|
||||
workspaceId: z.string().trim().describe(PROJECTS.DELETE.workspaceId)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
@@ -188,10 +194,14 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
handler: async (req) => {
|
||||
const workspace = await server.services.project.deleteProject({
|
||||
filter: {
|
||||
type: ProjectFilterType.ID,
|
||||
projectId: req.params.workspaceId
|
||||
},
|
||||
actorId: req.permission.id,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actor: req.permission.type,
|
||||
actorOrgId: req.permission.orgId,
|
||||
projectId: req.params.workspaceId
|
||||
actorOrgId: req.permission.orgId
|
||||
});
|
||||
return { workspace };
|
||||
}
|
||||
@@ -200,6 +210,9 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
url: "/:workspaceId/name",
|
||||
method: "POST",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
schema: {
|
||||
params: z.object({
|
||||
workspaceId: z.string().trim()
|
||||
@@ -219,6 +232,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
|
||||
const workspace = await server.services.project.updateName({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
projectId: req.params.workspaceId,
|
||||
name: req.body.name
|
||||
@@ -231,15 +245,29 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/:workspaceId",
|
||||
method: "PATCH",
|
||||
url: "/:workspaceId",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
schema: {
|
||||
description: "Update project",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: []
|
||||
}
|
||||
],
|
||||
params: z.object({
|
||||
workspaceId: z.string().trim()
|
||||
workspaceId: z.string().trim().describe(PROJECTS.UPDATE.workspaceId)
|
||||
}),
|
||||
body: z.object({
|
||||
name: z.string().trim().max(64, { message: "Name must be 64 or fewer characters" }).optional(),
|
||||
autoCapitalization: z.boolean().optional()
|
||||
name: z
|
||||
.string()
|
||||
.trim()
|
||||
.max(64, { message: "Name must be 64 or fewer characters" })
|
||||
.optional()
|
||||
.describe(PROJECTS.UPDATE.name),
|
||||
autoCapitalization: z.boolean().optional().describe(PROJECTS.UPDATE.autoCapitalization)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
@@ -247,17 +275,21 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
|
||||
})
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT]),
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
handler: async (req) => {
|
||||
const workspace = await server.services.project.updateProject({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorOrgId: req.permission.orgId,
|
||||
projectId: req.params.workspaceId,
|
||||
filter: {
|
||||
type: ProjectFilterType.ID,
|
||||
projectId: req.params.workspaceId
|
||||
},
|
||||
update: {
|
||||
name: req.body.name,
|
||||
autoCapitalization: req.body.autoCapitalization
|
||||
}
|
||||
},
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorOrgId: req.permission.orgId
|
||||
});
|
||||
return {
|
||||
workspace
|
||||
@@ -266,8 +298,11 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/:workspaceId/auto-capitalization",
|
||||
method: "POST",
|
||||
url: "/:workspaceId/auto-capitalization",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
schema: {
|
||||
params: z.object({
|
||||
workspaceId: z.string().trim()
|
||||
@@ -287,6 +322,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
|
||||
const workspace = await server.services.project.toggleAutoCapitalization({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
projectId: req.params.workspaceId,
|
||||
autoCapitalization: req.body.autoCapitalization
|
||||
@@ -299,11 +335,20 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/:workspaceId/integrations",
|
||||
method: "GET",
|
||||
url: "/:workspaceId/integrations",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
schema: {
|
||||
description: "List integrations for a project.",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: []
|
||||
}
|
||||
],
|
||||
params: z.object({
|
||||
workspaceId: z.string().trim()
|
||||
workspaceId: z.string().trim().describe(PROJECTS.LIST_INTEGRATION.workspaceId)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
@@ -319,10 +364,11 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
|
||||
})
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT]),
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
handler: async (req) => {
|
||||
const integrations = await server.services.integration.listIntegrationByProject({
|
||||
actorId: req.permission.id,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actor: req.permission.type,
|
||||
actorOrgId: req.permission.orgId,
|
||||
projectId: req.params.workspaceId
|
||||
@@ -332,11 +378,20 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/:workspaceId/authorizations",
|
||||
method: "GET",
|
||||
url: "/:workspaceId/authorizations",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
schema: {
|
||||
description: "List integration auth objects for a workspace.",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: []
|
||||
}
|
||||
],
|
||||
params: z.object({
|
||||
workspaceId: z.string().trim()
|
||||
workspaceId: z.string().trim().describe(PROJECTS.LIST_INTEGRATION_AUTHORIZATION.workspaceId)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
@@ -344,10 +399,11 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
|
||||
})
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT]),
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
handler: async (req) => {
|
||||
const authorizations = await server.services.integrationAuth.listIntegrationAuthByProjectId({
|
||||
actorId: req.permission.id,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actor: req.permission.type,
|
||||
actorOrgId: req.permission.orgId,
|
||||
projectId: req.params.workspaceId
|
||||
@@ -357,8 +413,11 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/:workspaceId/service-token-data",
|
||||
method: "GET",
|
||||
url: "/:workspaceId/service-token-data",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
schema: {
|
||||
params: z.object({
|
||||
workspaceId: z.string().trim()
|
||||
@@ -373,6 +432,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
|
||||
handler: async (req) => {
|
||||
const serviceTokenData = await server.services.serviceToken.getProjectServiceTokens({
|
||||
actorId: req.permission.id,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actor: req.permission.type,
|
||||
actorOrgId: req.permission.orgId,
|
||||
projectId: req.params.workspaceId
|
||||
|
||||
@@ -2,7 +2,9 @@ import { z } from "zod";
|
||||
|
||||
import { SecretFoldersSchema } from "@app/db/schemas";
|
||||
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
|
||||
import { FOLDERS } from "@app/lib/api-docs";
|
||||
import { removeTrailingSlash } from "@app/lib/fn";
|
||||
import { readLimit, secretsLimit } from "@app/server/config/rateLimiter";
|
||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||
import { AuthMode } from "@app/services/auth/auth-type";
|
||||
|
||||
@@ -10,21 +12,23 @@ export const registerSecretFolderRouter = async (server: FastifyZodProvider) =>
|
||||
server.route({
|
||||
url: "/",
|
||||
method: "POST",
|
||||
config: {
|
||||
rateLimit: secretsLimit
|
||||
},
|
||||
schema: {
|
||||
description: "Create folders",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: [],
|
||||
apiKeyAuth: []
|
||||
bearerAuth: []
|
||||
}
|
||||
],
|
||||
body: z.object({
|
||||
workspaceId: z.string().trim(),
|
||||
environment: z.string().trim(),
|
||||
name: z.string().trim(),
|
||||
path: z.string().trim().default("/").transform(removeTrailingSlash),
|
||||
workspaceId: z.string().trim().describe(FOLDERS.CREATE.workspaceId),
|
||||
environment: z.string().trim().describe(FOLDERS.CREATE.environment),
|
||||
name: z.string().trim().describe(FOLDERS.CREATE.name),
|
||||
path: z.string().trim().default("/").transform(removeTrailingSlash).describe(FOLDERS.CREATE.path),
|
||||
// backward compatiability with cli
|
||||
directory: z.string().trim().default("/").transform(removeTrailingSlash)
|
||||
directory: z.string().trim().default("/").transform(removeTrailingSlash).describe(FOLDERS.CREATE.directory)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
@@ -38,6 +42,7 @@ export const registerSecretFolderRouter = async (server: FastifyZodProvider) =>
|
||||
const folder = await server.services.folder.createFolder({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
...req.body,
|
||||
projectId: req.body.workspaceId,
|
||||
@@ -63,25 +68,27 @@ export const registerSecretFolderRouter = async (server: FastifyZodProvider) =>
|
||||
server.route({
|
||||
url: "/:folderId",
|
||||
method: "PATCH",
|
||||
config: {
|
||||
rateLimit: secretsLimit
|
||||
},
|
||||
schema: {
|
||||
description: "Update folder",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: [],
|
||||
apiKeyAuth: []
|
||||
bearerAuth: []
|
||||
}
|
||||
],
|
||||
params: z.object({
|
||||
// old way this was name
|
||||
folderId: z.string()
|
||||
folderId: z.string().describe(FOLDERS.UPDATE.folderId)
|
||||
}),
|
||||
body: z.object({
|
||||
workspaceId: z.string().trim(),
|
||||
environment: z.string().trim(),
|
||||
name: z.string().trim(),
|
||||
path: z.string().trim().default("/").transform(removeTrailingSlash),
|
||||
workspaceId: z.string().trim().describe(FOLDERS.UPDATE.workspaceId),
|
||||
environment: z.string().trim().describe(FOLDERS.UPDATE.environment),
|
||||
name: z.string().trim().describe(FOLDERS.UPDATE.name),
|
||||
path: z.string().trim().default("/").transform(removeTrailingSlash).describe(FOLDERS.UPDATE.path),
|
||||
// backward compatiability with cli
|
||||
directory: z.string().trim().default("/").transform(removeTrailingSlash)
|
||||
directory: z.string().trim().default("/").transform(removeTrailingSlash).describe(FOLDERS.UPDATE.directory)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
@@ -95,6 +102,7 @@ export const registerSecretFolderRouter = async (server: FastifyZodProvider) =>
|
||||
const { folder, old } = await server.services.folder.updateFolder({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
...req.body,
|
||||
projectId: req.body.workspaceId,
|
||||
@@ -119,26 +127,29 @@ export const registerSecretFolderRouter = async (server: FastifyZodProvider) =>
|
||||
}
|
||||
});
|
||||
|
||||
// TODO(daniel): Expose this route in api reference and write docs for it.
|
||||
server.route({
|
||||
url: "/:folderIdOrName",
|
||||
method: "DELETE",
|
||||
url: "/:folderIdOrName",
|
||||
config: {
|
||||
rateLimit: secretsLimit
|
||||
},
|
||||
schema: {
|
||||
description: "Delete a folder",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: [],
|
||||
apiKeyAuth: []
|
||||
bearerAuth: []
|
||||
}
|
||||
],
|
||||
params: z.object({
|
||||
folderIdOrName: z.string()
|
||||
folderIdOrName: z.string().describe(FOLDERS.DELETE.folderIdOrName)
|
||||
}),
|
||||
body: z.object({
|
||||
workspaceId: z.string().trim(),
|
||||
environment: z.string().trim(),
|
||||
path: z.string().trim().default("/").transform(removeTrailingSlash),
|
||||
workspaceId: z.string().trim().describe(FOLDERS.DELETE.workspaceId),
|
||||
environment: z.string().trim().describe(FOLDERS.DELETE.environment),
|
||||
path: z.string().trim().default("/").transform(removeTrailingSlash).describe(FOLDERS.DELETE.path),
|
||||
// keep this here as cli need directory
|
||||
directory: z.string().trim().default("/").transform(removeTrailingSlash)
|
||||
directory: z.string().trim().default("/").transform(removeTrailingSlash).describe(FOLDERS.DELETE.directory)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
@@ -152,6 +163,7 @@ export const registerSecretFolderRouter = async (server: FastifyZodProvider) =>
|
||||
const folder = await server.services.folder.deleteFolder({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
...req.body,
|
||||
projectId: req.body.workspaceId,
|
||||
@@ -176,22 +188,24 @@ export const registerSecretFolderRouter = async (server: FastifyZodProvider) =>
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/",
|
||||
method: "GET",
|
||||
url: "/",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
schema: {
|
||||
description: "Get folders",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: [],
|
||||
apiKeyAuth: []
|
||||
bearerAuth: []
|
||||
}
|
||||
],
|
||||
querystring: z.object({
|
||||
workspaceId: z.string().trim(),
|
||||
environment: z.string().trim(),
|
||||
path: z.string().trim().default("/").transform(removeTrailingSlash),
|
||||
workspaceId: z.string().trim().describe(FOLDERS.LIST.workspaceId),
|
||||
environment: z.string().trim().describe(FOLDERS.LIST.environment),
|
||||
path: z.string().trim().default("/").transform(removeTrailingSlash).describe(FOLDERS.LIST.path),
|
||||
// backward compatiability with cli
|
||||
directory: z.string().trim().default("/").transform(removeTrailingSlash)
|
||||
directory: z.string().trim().default("/").transform(removeTrailingSlash).describe(FOLDERS.LIST.directory)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
@@ -205,6 +219,7 @@ export const registerSecretFolderRouter = async (server: FastifyZodProvider) =>
|
||||
const folders = await server.services.folder.getFolders({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
...req.query,
|
||||
projectId: req.query.workspaceId,
|
||||
|
||||
@@ -2,29 +2,33 @@ import { z } from "zod";
|
||||
|
||||
import { SecretImportsSchema, SecretsSchema } from "@app/db/schemas";
|
||||
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
|
||||
import { SECRET_IMPORTS } from "@app/lib/api-docs";
|
||||
import { removeTrailingSlash } from "@app/lib/fn";
|
||||
import { readLimit, secretsLimit } from "@app/server/config/rateLimiter";
|
||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||
import { AuthMode } from "@app/services/auth/auth-type";
|
||||
|
||||
export const registerSecretImportRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
url: "/",
|
||||
method: "POST",
|
||||
url: "/",
|
||||
config: {
|
||||
rateLimit: secretsLimit
|
||||
},
|
||||
schema: {
|
||||
description: "Create secret imports",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: [],
|
||||
apiKeyAuth: []
|
||||
bearerAuth: []
|
||||
}
|
||||
],
|
||||
body: z.object({
|
||||
workspaceId: z.string().trim(),
|
||||
environment: z.string().trim(),
|
||||
path: z.string().trim().default("/").transform(removeTrailingSlash),
|
||||
workspaceId: z.string().trim().describe(SECRET_IMPORTS.CREATE.workspaceId),
|
||||
environment: z.string().trim().describe(SECRET_IMPORTS.CREATE.environment),
|
||||
path: z.string().trim().default("/").transform(removeTrailingSlash).describe(SECRET_IMPORTS.CREATE.path),
|
||||
import: z.object({
|
||||
environment: z.string().trim(),
|
||||
path: z.string().trim().transform(removeTrailingSlash)
|
||||
environment: z.string().trim().describe(SECRET_IMPORTS.CREATE.import.environment),
|
||||
path: z.string().trim().transform(removeTrailingSlash).describe(SECRET_IMPORTS.CREATE.import.path)
|
||||
})
|
||||
}),
|
||||
response: {
|
||||
@@ -43,6 +47,7 @@ export const registerSecretImportRouter = async (server: FastifyZodProvider) =>
|
||||
const secretImport = await server.services.secretImport.createImport({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
...req.body,
|
||||
projectId: req.body.workspaceId,
|
||||
@@ -69,31 +74,34 @@ export const registerSecretImportRouter = async (server: FastifyZodProvider) =>
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/:secretImportId",
|
||||
method: "PATCH",
|
||||
url: "/:secretImportId",
|
||||
config: {
|
||||
rateLimit: secretsLimit
|
||||
},
|
||||
schema: {
|
||||
description: "Update secret imports",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: [],
|
||||
apiKeyAuth: []
|
||||
bearerAuth: []
|
||||
}
|
||||
],
|
||||
params: z.object({
|
||||
secretImportId: z.string().trim()
|
||||
secretImportId: z.string().trim().describe(SECRET_IMPORTS.UPDATE.secretImportId)
|
||||
}),
|
||||
body: z.object({
|
||||
workspaceId: z.string().trim(),
|
||||
environment: z.string().trim(),
|
||||
path: z.string().trim().default("/").transform(removeTrailingSlash),
|
||||
workspaceId: z.string().trim().describe(SECRET_IMPORTS.UPDATE.workspaceId),
|
||||
environment: z.string().trim().describe(SECRET_IMPORTS.UPDATE.environment),
|
||||
path: z.string().trim().default("/").transform(removeTrailingSlash).describe(SECRET_IMPORTS.UPDATE.path),
|
||||
import: z.object({
|
||||
environment: z.string().trim().optional(),
|
||||
environment: z.string().trim().optional().describe(SECRET_IMPORTS.UPDATE.import.environment),
|
||||
path: z
|
||||
.string()
|
||||
.trim()
|
||||
.optional()
|
||||
.transform((val) => (val ? removeTrailingSlash(val) : val)),
|
||||
position: z.number().optional()
|
||||
.transform((val) => (val ? removeTrailingSlash(val) : val))
|
||||
.describe(SECRET_IMPORTS.UPDATE.import.path),
|
||||
position: z.number().optional().describe(SECRET_IMPORTS.UPDATE.import.position)
|
||||
})
|
||||
}),
|
||||
response: {
|
||||
@@ -112,6 +120,7 @@ export const registerSecretImportRouter = async (server: FastifyZodProvider) =>
|
||||
const secretImport = await server.services.secretImport.updateImport({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
id: req.params.secretImportId,
|
||||
...req.body,
|
||||
@@ -139,23 +148,25 @@ export const registerSecretImportRouter = async (server: FastifyZodProvider) =>
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/:secretImportId",
|
||||
method: "DELETE",
|
||||
url: "/:secretImportId",
|
||||
config: {
|
||||
rateLimit: secretsLimit
|
||||
},
|
||||
schema: {
|
||||
description: "Delete secret imports",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: [],
|
||||
apiKeyAuth: []
|
||||
bearerAuth: []
|
||||
}
|
||||
],
|
||||
params: z.object({
|
||||
secretImportId: z.string().trim()
|
||||
secretImportId: z.string().trim().describe(SECRET_IMPORTS.DELETE.secretImportId)
|
||||
}),
|
||||
body: z.object({
|
||||
workspaceId: z.string().trim(),
|
||||
environment: z.string().trim(),
|
||||
path: z.string().trim().default("/").transform(removeTrailingSlash)
|
||||
workspaceId: z.string().trim().describe(SECRET_IMPORTS.DELETE.workspaceId),
|
||||
environment: z.string().trim().describe(SECRET_IMPORTS.DELETE.environment),
|
||||
path: z.string().trim().default("/").transform(removeTrailingSlash).describe(SECRET_IMPORTS.DELETE.path)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
@@ -173,6 +184,7 @@ export const registerSecretImportRouter = async (server: FastifyZodProvider) =>
|
||||
const secretImport = await server.services.secretImport.deleteImport({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
id: req.params.secretImportId,
|
||||
...req.body,
|
||||
@@ -199,20 +211,22 @@ export const registerSecretImportRouter = async (server: FastifyZodProvider) =>
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/",
|
||||
method: "GET",
|
||||
url: "/",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
schema: {
|
||||
description: "Get secret imports",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: [],
|
||||
apiKeyAuth: []
|
||||
bearerAuth: []
|
||||
}
|
||||
],
|
||||
querystring: z.object({
|
||||
workspaceId: z.string().trim(),
|
||||
environment: z.string().trim(),
|
||||
path: z.string().trim().default("/").transform(removeTrailingSlash)
|
||||
workspaceId: z.string().trim().describe(SECRET_IMPORTS.LIST.workspaceId),
|
||||
environment: z.string().trim().describe(SECRET_IMPORTS.LIST.environment),
|
||||
path: z.string().trim().default("/").transform(removeTrailingSlash).describe(SECRET_IMPORTS.LIST.path)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
@@ -232,6 +246,7 @@ export const registerSecretImportRouter = async (server: FastifyZodProvider) =>
|
||||
const secretImports = await server.services.secretImport.getImports({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
...req.query,
|
||||
projectId: req.query.workspaceId
|
||||
@@ -256,6 +271,9 @@ export const registerSecretImportRouter = async (server: FastifyZodProvider) =>
|
||||
server.route({
|
||||
url: "/secrets",
|
||||
method: "GET",
|
||||
config: {
|
||||
rateLimit: secretsLimit
|
||||
},
|
||||
schema: {
|
||||
querystring: z.object({
|
||||
workspaceId: z.string().trim(),
|
||||
@@ -285,6 +303,7 @@ export const registerSecretImportRouter = async (server: FastifyZodProvider) =>
|
||||
const importedSecrets = await server.services.secretImport.getSecretsFromImports({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
...req.query,
|
||||
projectId: req.query.workspaceId
|
||||
|
||||
@@ -1,16 +1,21 @@
|
||||
import { z } from "zod";
|
||||
|
||||
import { SecretTagsSchema } from "@app/db/schemas";
|
||||
import { SECRET_TAGS } from "@app/lib/api-docs";
|
||||
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||
import { AuthMode } from "@app/services/auth/auth-type";
|
||||
|
||||
export const registerSecretTagRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
url: "/:projectId/tags",
|
||||
method: "GET",
|
||||
url: "/:projectId/tags",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
schema: {
|
||||
params: z.object({
|
||||
projectId: z.string().trim()
|
||||
projectId: z.string().trim().describe(SECRET_TAGS.LIST.projectId)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
@@ -23,6 +28,7 @@ export const registerSecretTagRouter = async (server: FastifyZodProvider) => {
|
||||
const workspaceTags = await server.services.secretTag.getProjectTags({
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
projectId: req.params.projectId
|
||||
});
|
||||
@@ -31,16 +37,19 @@ export const registerSecretTagRouter = async (server: FastifyZodProvider) => {
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/:projectId/tags",
|
||||
method: "POST",
|
||||
url: "/:projectId/tags",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
schema: {
|
||||
params: z.object({
|
||||
projectId: z.string().trim()
|
||||
projectId: z.string().trim().describe(SECRET_TAGS.CREATE.projectId)
|
||||
}),
|
||||
body: z.object({
|
||||
name: z.string().trim(),
|
||||
slug: z.string().trim(),
|
||||
color: z.string()
|
||||
name: z.string().trim().describe(SECRET_TAGS.CREATE.name),
|
||||
slug: z.string().trim().describe(SECRET_TAGS.CREATE.slug),
|
||||
color: z.string().trim().describe(SECRET_TAGS.CREATE.color)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
@@ -53,6 +62,7 @@ export const registerSecretTagRouter = async (server: FastifyZodProvider) => {
|
||||
const workspaceTag = await server.services.secretTag.createTag({
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
projectId: req.params.projectId,
|
||||
...req.body
|
||||
@@ -62,12 +72,15 @@ export const registerSecretTagRouter = async (server: FastifyZodProvider) => {
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/:projectId/tags/:tagId",
|
||||
method: "DELETE",
|
||||
url: "/:projectId/tags/:tagId",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
schema: {
|
||||
params: z.object({
|
||||
projectId: z.string().trim(),
|
||||
tagId: z.string().trim()
|
||||
projectId: z.string().trim().describe(SECRET_TAGS.DELETE.projectId),
|
||||
tagId: z.string().trim().describe(SECRET_TAGS.DELETE.tagId)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
@@ -80,6 +93,7 @@ export const registerSecretTagRouter = async (server: FastifyZodProvider) => {
|
||||
const workspaceTag = await server.services.secretTag.deleteTag({
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
id: req.params.tagId
|
||||
});
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { z } from "zod";
|
||||
|
||||
import { UserActionsSchema } from "@app/db/schemas";
|
||||
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||
import { AuthMode } from "@app/services/auth/auth-type";
|
||||
|
||||
@@ -8,6 +9,9 @@ export const registerUserActionRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
url: "/",
|
||||
method: "POST",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
schema: {
|
||||
body: z.object({
|
||||
action: z.string().trim()
|
||||
@@ -29,6 +33,9 @@ export const registerUserActionRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
url: "/",
|
||||
method: "GET",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
schema: {
|
||||
querystring: z.object({
|
||||
action: z.string().trim()
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { z } from "zod";
|
||||
|
||||
import { UserEncryptionKeysSchema, UsersSchema } from "@app/db/schemas";
|
||||
import { readLimit } from "@app/server/config/rateLimiter";
|
||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||
import { AuthMode } from "@app/services/auth/auth-type";
|
||||
|
||||
@@ -8,6 +9,9 @@ export const registerUserRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
method: "GET",
|
||||
url: "/",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
schema: {
|
||||
response: {
|
||||
200: z.object({
|
||||
@@ -15,7 +19,7 @@ export const registerUserRouter = async (server: FastifyZodProvider) => {
|
||||
})
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT]),
|
||||
onRequest: verifyAuth([AuthMode.JWT], { requireOrg: false }),
|
||||
handler: async (req) => {
|
||||
const user = await server.services.user.getMe(req.permission.id);
|
||||
return { user };
|
||||
|
||||
@@ -3,6 +3,7 @@ import { z } from "zod";
|
||||
import { WebhooksSchema } from "@app/db/schemas";
|
||||
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
|
||||
import { removeTrailingSlash } from "@app/lib/fn";
|
||||
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||
import { AuthMode } from "@app/services/auth/auth-type";
|
||||
|
||||
@@ -27,6 +28,9 @@ export const registerWebhookRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
method: "POST",
|
||||
url: "/",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT]),
|
||||
schema: {
|
||||
body: z.object({
|
||||
@@ -47,6 +51,7 @@ export const registerWebhookRouter = async (server: FastifyZodProvider) => {
|
||||
const webhook = await server.services.webhook.createWebhook({
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
projectId: req.body.workspaceId,
|
||||
...req.body
|
||||
@@ -74,6 +79,9 @@ export const registerWebhookRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
method: "PATCH",
|
||||
url: "/:webhookId",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT]),
|
||||
schema: {
|
||||
params: z.object({
|
||||
@@ -93,6 +101,7 @@ export const registerWebhookRouter = async (server: FastifyZodProvider) => {
|
||||
const webhook = await server.services.webhook.updateWebhook({
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
id: req.params.webhookId,
|
||||
isDisabled: req.body.isDisabled
|
||||
@@ -120,6 +129,9 @@ export const registerWebhookRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
method: "DELETE",
|
||||
url: "/:webhookId",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT]),
|
||||
schema: {
|
||||
params: z.object({
|
||||
@@ -130,6 +142,7 @@ export const registerWebhookRouter = async (server: FastifyZodProvider) => {
|
||||
const webhook = await server.services.webhook.deleteWebhook({
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
id: req.params.webhookId
|
||||
});
|
||||
@@ -156,6 +169,9 @@ export const registerWebhookRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
method: "POST",
|
||||
url: "/:webhookId/test",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT]),
|
||||
schema: {
|
||||
params: z.object({
|
||||
@@ -172,6 +188,7 @@ export const registerWebhookRouter = async (server: FastifyZodProvider) => {
|
||||
const webhook = await server.services.webhook.testWebhook({
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
id: req.params.webhookId
|
||||
});
|
||||
@@ -182,6 +199,9 @@ export const registerWebhookRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
method: "GET",
|
||||
url: "/",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT]),
|
||||
schema: {
|
||||
querystring: z.object({
|
||||
@@ -204,6 +224,7 @@ export const registerWebhookRouter = async (server: FastifyZodProvider) => {
|
||||
const webhooks = await server.services.webhook.listWebhooks({
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
...req.query,
|
||||
projectId: req.query.workspaceId
|
||||
|
||||
@@ -0,0 +1,201 @@
|
||||
import ms from "ms";
|
||||
import { z } from "zod";
|
||||
|
||||
import {
|
||||
GroupProjectMembershipsSchema,
|
||||
GroupsSchema,
|
||||
ProjectMembershipRole,
|
||||
ProjectUserMembershipRolesSchema
|
||||
} from "@app/db/schemas";
|
||||
import { PROJECTS } from "@app/lib/api-docs";
|
||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||
import { AuthMode } from "@app/services/auth/auth-type";
|
||||
import { ProjectUserMembershipTemporaryMode } from "@app/services/project-membership/project-membership-types";
|
||||
|
||||
export const registerGroupProjectRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
method: "POST",
|
||||
url: "/:projectSlug/groups/:groupSlug",
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
schema: {
|
||||
description: "Add group to project",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: []
|
||||
}
|
||||
],
|
||||
params: z.object({
|
||||
projectSlug: z.string().trim().describe(PROJECTS.ADD_GROUP_TO_PROJECT.projectSlug),
|
||||
groupSlug: z.string().trim().describe(PROJECTS.ADD_GROUP_TO_PROJECT.groupSlug)
|
||||
}),
|
||||
body: z.object({
|
||||
role: z
|
||||
.string()
|
||||
.trim()
|
||||
.min(1)
|
||||
.default(ProjectMembershipRole.NoAccess)
|
||||
.describe(PROJECTS.ADD_GROUP_TO_PROJECT.role)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
groupMembership: GroupProjectMembershipsSchema
|
||||
})
|
||||
}
|
||||
},
|
||||
handler: async (req) => {
|
||||
const groupMembership = await server.services.groupProject.addGroupToProject({
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
groupSlug: req.params.groupSlug,
|
||||
projectSlug: req.params.projectSlug,
|
||||
role: req.body.role
|
||||
});
|
||||
return { groupMembership };
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
method: "PATCH",
|
||||
url: "/:projectSlug/groups/:groupSlug",
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
schema: {
|
||||
description: "Update group in project",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: []
|
||||
}
|
||||
],
|
||||
params: z.object({
|
||||
projectSlug: z.string().trim().describe(PROJECTS.UPDATE_GROUP_IN_PROJECT.projectSlug),
|
||||
groupSlug: z.string().trim().describe(PROJECTS.UPDATE_GROUP_IN_PROJECT.groupSlug)
|
||||
}),
|
||||
body: z.object({
|
||||
roles: z
|
||||
.array(
|
||||
z.union([
|
||||
z.object({
|
||||
role: z.string(),
|
||||
isTemporary: z.literal(false).default(false)
|
||||
}),
|
||||
z.object({
|
||||
role: z.string(),
|
||||
isTemporary: z.literal(true),
|
||||
temporaryMode: z.nativeEnum(ProjectUserMembershipTemporaryMode),
|
||||
temporaryRange: z.string().refine((val) => ms(val) > 0, "Temporary range must be a positive number"),
|
||||
temporaryAccessStartTime: z.string().datetime()
|
||||
})
|
||||
])
|
||||
)
|
||||
.min(1)
|
||||
.describe(PROJECTS.UPDATE_GROUP_IN_PROJECT.roles)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
roles: ProjectUserMembershipRolesSchema.array()
|
||||
})
|
||||
}
|
||||
},
|
||||
handler: async (req) => {
|
||||
const roles = await server.services.groupProject.updateGroupInProject({
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
groupSlug: req.params.groupSlug,
|
||||
projectSlug: req.params.projectSlug,
|
||||
roles: req.body.roles
|
||||
});
|
||||
return { roles };
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
method: "DELETE",
|
||||
url: "/:projectSlug/groups/:groupSlug",
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
schema: {
|
||||
description: "Remove group from project",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: []
|
||||
}
|
||||
],
|
||||
params: z.object({
|
||||
projectSlug: z.string().trim().describe(PROJECTS.REMOVE_GROUP_FROM_PROJECT.projectSlug),
|
||||
groupSlug: z.string().trim().describe(PROJECTS.REMOVE_GROUP_FROM_PROJECT.groupSlug)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
groupMembership: GroupProjectMembershipsSchema
|
||||
})
|
||||
}
|
||||
},
|
||||
handler: async (req) => {
|
||||
const groupMembership = await server.services.groupProject.removeGroupFromProject({
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
groupSlug: req.params.groupSlug,
|
||||
projectSlug: req.params.projectSlug
|
||||
});
|
||||
return { groupMembership };
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
method: "GET",
|
||||
url: "/:projectSlug/groups",
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
schema: {
|
||||
description: "Return list of groups in project",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: []
|
||||
}
|
||||
],
|
||||
params: z.object({
|
||||
projectSlug: z.string().trim().describe(PROJECTS.LIST_GROUPS_IN_PROJECT.projectSlug)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
groupMemberships: z
|
||||
.object({
|
||||
id: z.string(),
|
||||
groupId: z.string(),
|
||||
createdAt: z.date(),
|
||||
updatedAt: z.date(),
|
||||
roles: z.array(
|
||||
z.object({
|
||||
id: z.string(),
|
||||
role: z.string(),
|
||||
customRoleId: z.string().optional().nullable(),
|
||||
customRoleName: z.string().optional().nullable(),
|
||||
customRoleSlug: z.string().optional().nullable(),
|
||||
isTemporary: z.boolean(),
|
||||
temporaryMode: z.string().optional().nullable(),
|
||||
temporaryRange: z.string().nullable().optional(),
|
||||
temporaryAccessStartTime: z.date().nullable().optional(),
|
||||
temporaryAccessEndTime: z.date().nullable().optional()
|
||||
})
|
||||
),
|
||||
group: GroupsSchema.pick({ name: true, id: true, slug: true })
|
||||
})
|
||||
.array()
|
||||
})
|
||||
}
|
||||
},
|
||||
handler: async (req) => {
|
||||
const groupMemberships = await server.services.groupProject.listGroupsInProject({
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
projectSlug: req.params.projectSlug
|
||||
});
|
||||
return { groupMemberships };
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -1,6 +1,8 @@
|
||||
import { z } from "zod";
|
||||
|
||||
import { IdentitiesSchema, IdentityOrgMembershipsSchema, OrgRolesSchema } from "@app/db/schemas";
|
||||
import { ORGANIZATIONS } from "@app/lib/api-docs";
|
||||
import { readLimit } from "@app/server/config/rateLimiter";
|
||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||
import { AuthMode } from "@app/services/auth/auth-type";
|
||||
|
||||
@@ -8,17 +10,19 @@ export const registerIdentityOrgRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
method: "GET",
|
||||
url: "/:orgId/identity-memberships",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
schema: {
|
||||
description: "Return organization identity memberships",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: [],
|
||||
apiKeyAuth: []
|
||||
bearerAuth: []
|
||||
}
|
||||
],
|
||||
params: z.object({
|
||||
orgId: z.string().trim()
|
||||
orgId: z.string().trim().describe(ORGANIZATIONS.LIST_IDENTITY_MEMBERSHIPS.orgId)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
@@ -41,9 +45,11 @@ export const registerIdentityOrgRouter = async (server: FastifyZodProvider) => {
|
||||
const identityMemberships = await server.services.identity.listOrgIdentities({
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
orgId: req.params.orgId
|
||||
});
|
||||
|
||||
return { identityMemberships };
|
||||
}
|
||||
});
|
||||
|
||||
@@ -7,6 +7,8 @@ import {
|
||||
ProjectMembershipRole,
|
||||
ProjectUserMembershipRolesSchema
|
||||
} from "@app/db/schemas";
|
||||
import { PROJECTS } from "@app/lib/api-docs";
|
||||
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||
import { AuthMode } from "@app/services/auth/auth-type";
|
||||
import { ProjectUserMembershipTemporaryMode } from "@app/services/project-membership/project-membership-types";
|
||||
@@ -15,6 +17,9 @@ export const registerIdentityProjectRouter = async (server: FastifyZodProvider)
|
||||
server.route({
|
||||
method: "POST",
|
||||
url: "/:projectId/identity-memberships/:identityId",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
schema: {
|
||||
params: z.object({
|
||||
@@ -34,6 +39,7 @@ export const registerIdentityProjectRouter = async (server: FastifyZodProvider)
|
||||
const identityMembership = await server.services.identityProject.createProjectIdentity({
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
identityId: req.params.identityId,
|
||||
projectId: req.params.projectId,
|
||||
@@ -46,6 +52,9 @@ export const registerIdentityProjectRouter = async (server: FastifyZodProvider)
|
||||
server.route({
|
||||
method: "PATCH",
|
||||
url: "/:projectId/identity-memberships/:identityId",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
schema: {
|
||||
description: "Update project identity memberships",
|
||||
@@ -55,8 +64,8 @@ export const registerIdentityProjectRouter = async (server: FastifyZodProvider)
|
||||
}
|
||||
],
|
||||
params: z.object({
|
||||
projectId: z.string().trim(),
|
||||
identityId: z.string().trim()
|
||||
projectId: z.string().trim().describe(PROJECTS.UPDATE_IDENTITY_MEMBERSHIP.projectId),
|
||||
identityId: z.string().trim().describe(PROJECTS.UPDATE_IDENTITY_MEMBERSHIP.identityId)
|
||||
}),
|
||||
body: z.object({
|
||||
roles: z
|
||||
@@ -76,6 +85,7 @@ export const registerIdentityProjectRouter = async (server: FastifyZodProvider)
|
||||
])
|
||||
)
|
||||
.min(1)
|
||||
.describe(PROJECTS.UPDATE_IDENTITY_MEMBERSHIP.roles)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
@@ -87,6 +97,7 @@ export const registerIdentityProjectRouter = async (server: FastifyZodProvider)
|
||||
const roles = await server.services.identityProject.updateProjectIdentity({
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
identityId: req.params.identityId,
|
||||
projectId: req.params.projectId,
|
||||
@@ -99,6 +110,9 @@ export const registerIdentityProjectRouter = async (server: FastifyZodProvider)
|
||||
server.route({
|
||||
method: "DELETE",
|
||||
url: "/:projectId/identity-memberships/:identityId",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
schema: {
|
||||
description: "Delete project identity memberships",
|
||||
@@ -108,8 +122,8 @@ export const registerIdentityProjectRouter = async (server: FastifyZodProvider)
|
||||
}
|
||||
],
|
||||
params: z.object({
|
||||
projectId: z.string().trim(),
|
||||
identityId: z.string().trim()
|
||||
projectId: z.string().trim().describe(PROJECTS.DELETE_IDENTITY_MEMBERSHIP.projectId),
|
||||
identityId: z.string().trim().describe(PROJECTS.DELETE_IDENTITY_MEMBERSHIP.identityId)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
@@ -121,6 +135,7 @@ export const registerIdentityProjectRouter = async (server: FastifyZodProvider)
|
||||
const identityMembership = await server.services.identityProject.deleteProjectIdentity({
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
identityId: req.params.identityId,
|
||||
projectId: req.params.projectId
|
||||
@@ -132,6 +147,9 @@ export const registerIdentityProjectRouter = async (server: FastifyZodProvider)
|
||||
server.route({
|
||||
method: "GET",
|
||||
url: "/:projectId/identity-memberships",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
schema: {
|
||||
description: "Return project identity memberships",
|
||||
@@ -141,7 +159,7 @@ export const registerIdentityProjectRouter = async (server: FastifyZodProvider)
|
||||
}
|
||||
],
|
||||
params: z.object({
|
||||
projectId: z.string().trim()
|
||||
projectId: z.string().trim().describe(PROJECTS.LIST_IDENTITY_MEMBERSHIPS.projectId)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
@@ -175,6 +193,7 @@ export const registerIdentityProjectRouter = async (server: FastifyZodProvider)
|
||||
const identityMemberships = await server.services.identityProject.listProjectIdentities({
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
projectId: req.params.projectId
|
||||
});
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { registerGroupProjectRouter } from "./group-project-router";
|
||||
import { registerIdentityOrgRouter } from "./identity-org-router";
|
||||
import { registerIdentityProjectRouter } from "./identity-project-router";
|
||||
import { registerMfaRouter } from "./mfa-router";
|
||||
@@ -22,6 +23,7 @@ export const registerV2Routes = async (server: FastifyZodProvider) => {
|
||||
async (projectServer) => {
|
||||
await projectServer.register(registerProjectRouter);
|
||||
await projectServer.register(registerIdentityProjectRouter);
|
||||
await projectServer.register(registerGroupProjectRouter);
|
||||
await projectServer.register(registerProjectMembershipRouter);
|
||||
},
|
||||
{ prefix: "/workspace" }
|
||||
|
||||
@@ -2,6 +2,7 @@ import jwt from "jsonwebtoken";
|
||||
import { z } from "zod";
|
||||
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import { writeLimit } from "@app/server/config/rateLimiter";
|
||||
import { AuthModeMfaJwtTokenPayload, AuthTokenType } from "@app/services/auth/auth-type";
|
||||
|
||||
export const registerMfaRouter = async (server: FastifyZodProvider) => {
|
||||
@@ -30,8 +31,11 @@ export const registerMfaRouter = async (server: FastifyZodProvider) => {
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/mfa/send",
|
||||
method: "POST",
|
||||
url: "/mfa/send",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
schema: {
|
||||
response: {
|
||||
200: z.object({
|
||||
@@ -48,6 +52,9 @@ export const registerMfaRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
url: "/mfa/verify",
|
||||
method: "POST",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
schema: {
|
||||
body: z.object({
|
||||
mfaToken: z.string().trim()
|
||||
@@ -68,11 +75,14 @@ export const registerMfaRouter = async (server: FastifyZodProvider) => {
|
||||
},
|
||||
handler: async (req, res) => {
|
||||
const userAgent = req.headers["user-agent"];
|
||||
const mfaJwtToken = req.headers.authorization?.replace("Bearer ", "");
|
||||
if (!userAgent) throw new Error("user agent header is required");
|
||||
if (!mfaJwtToken) throw new Error("authorization header is required");
|
||||
const appCfg = getConfig();
|
||||
|
||||
const { user, token } = await server.services.login.verifyMfaToken({
|
||||
userAgent,
|
||||
mfaJwtToken,
|
||||
ip: req.realIp,
|
||||
userId: req.mfa.userId,
|
||||
orgId: req.mfa.orgId,
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { z } from "zod";
|
||||
|
||||
import { OrganizationsSchema, OrgMembershipsSchema, UserEncryptionKeysSchema, UsersSchema } from "@app/db/schemas";
|
||||
import { ORGANIZATIONS } from "@app/lib/api-docs";
|
||||
import { creationLimit, readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||
import { ActorType, AuthMode } from "@app/services/auth/auth-type";
|
||||
|
||||
@@ -8,16 +10,18 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
method: "GET",
|
||||
url: "/:organizationId/memberships",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
schema: {
|
||||
description: "Return organization user memberships",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: [],
|
||||
apiKeyAuth: []
|
||||
bearerAuth: []
|
||||
}
|
||||
],
|
||||
params: z.object({
|
||||
organizationId: z.string().trim()
|
||||
organizationId: z.string().trim().describe(ORGANIZATIONS.LIST_USER_MEMBERSHIPS.organizationId)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
@@ -44,6 +48,7 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
|
||||
const users = await server.services.org.findAllOrgMembers(
|
||||
req.permission.id,
|
||||
req.params.organizationId,
|
||||
req.permission.authMethod,
|
||||
req.permission.orgId
|
||||
);
|
||||
return { users };
|
||||
@@ -53,16 +58,18 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
method: "GET",
|
||||
url: "/:organizationId/workspaces",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
schema: {
|
||||
description: "Return projects in organization that user is part of",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: [],
|
||||
apiKeyAuth: []
|
||||
bearerAuth: []
|
||||
}
|
||||
],
|
||||
params: z.object({
|
||||
organizationId: z.string().trim()
|
||||
organizationId: z.string().trim().describe(ORGANIZATIONS.GET_PROJECTS.organizationId)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
@@ -88,6 +95,7 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
actorOrgId: req.permission.orgId,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
orgId: req.params.organizationId
|
||||
});
|
||||
|
||||
@@ -98,17 +106,22 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
method: "PATCH",
|
||||
url: "/:organizationId/memberships/:membershipId",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
schema: {
|
||||
description: "Update organization user memberships",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: [],
|
||||
apiKeyAuth: []
|
||||
bearerAuth: []
|
||||
}
|
||||
],
|
||||
params: z.object({ organizationId: z.string().trim(), membershipId: z.string().trim() }),
|
||||
params: z.object({
|
||||
organizationId: z.string().trim().describe(ORGANIZATIONS.UPDATE_USER_MEMBERSHIP.organizationId),
|
||||
membershipId: z.string().trim().describe(ORGANIZATIONS.UPDATE_USER_MEMBERSHIP.membershipId)
|
||||
}),
|
||||
body: z.object({
|
||||
role: z.string().trim()
|
||||
role: z.string().trim().describe(ORGANIZATIONS.UPDATE_USER_MEMBERSHIP.role)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
@@ -123,6 +136,7 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
|
||||
const membership = await server.services.org.updateOrgMembership({
|
||||
userId: req.permission.id,
|
||||
role: req.body.role,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
orgId: req.params.organizationId,
|
||||
membershipId: req.params.membershipId,
|
||||
actorOrgId: req.permission.orgId
|
||||
@@ -134,15 +148,20 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
method: "DELETE",
|
||||
url: "/:organizationId/memberships/:membershipId",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
schema: {
|
||||
description: "Delete organization user memberships",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: [],
|
||||
apiKeyAuth: []
|
||||
bearerAuth: []
|
||||
}
|
||||
],
|
||||
params: z.object({ organizationId: z.string().trim(), membershipId: z.string().trim() }),
|
||||
params: z.object({
|
||||
organizationId: z.string().trim().describe(ORGANIZATIONS.DELETE_USER_MEMBERSHIP.organizationId),
|
||||
membershipId: z.string().trim().describe(ORGANIZATIONS.DELETE_USER_MEMBERSHIP.membershipId)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
membership: OrgMembershipsSchema
|
||||
@@ -155,6 +174,7 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
|
||||
|
||||
const membership = await server.services.org.deleteOrgMembership({
|
||||
userId: req.permission.id,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
orgId: req.params.organizationId,
|
||||
membershipId: req.params.membershipId,
|
||||
actorOrgId: req.permission.orgId
|
||||
@@ -166,6 +186,9 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
method: "POST",
|
||||
url: "/",
|
||||
config: {
|
||||
rateLimit: creationLimit
|
||||
},
|
||||
schema: {
|
||||
body: z.object({
|
||||
name: z.string().trim()
|
||||
@@ -176,7 +199,7 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
|
||||
})
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY]),
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY], { requireOrg: false }),
|
||||
handler: async (req) => {
|
||||
if (req.auth.actor !== ActorType.USER) return;
|
||||
|
||||
@@ -193,6 +216,9 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
method: "DELETE",
|
||||
url: "/:organizationId",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
schema: {
|
||||
params: z.object({
|
||||
organizationId: z.string().trim()
|
||||
@@ -210,6 +236,7 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
|
||||
const organization = await server.services.org.deleteOrganizationById(
|
||||
req.permission.id,
|
||||
req.params.organizationId,
|
||||
req.permission.authMethod,
|
||||
req.permission.orgId
|
||||
);
|
||||
return { organization };
|
||||
|
||||
@@ -2,6 +2,8 @@ import { z } from "zod";
|
||||
|
||||
import { ProjectMembershipsSchema } from "@app/db/schemas";
|
||||
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
|
||||
import { PROJECTS } from "@app/lib/api-docs";
|
||||
import { writeLimit } from "@app/server/config/rateLimiter";
|
||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||
import { AuthMode } from "@app/services/auth/auth-type";
|
||||
|
||||
@@ -9,13 +11,22 @@ export const registerProjectMembershipRouter = async (server: FastifyZodProvider
|
||||
server.route({
|
||||
method: "POST",
|
||||
url: "/:projectId/memberships",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
schema: {
|
||||
description: "Invite members to project",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: []
|
||||
}
|
||||
],
|
||||
params: z.object({
|
||||
projectId: z.string().describe("The ID of the project.")
|
||||
projectId: z.string().describe(PROJECTS.INVITE_MEMBER.projectId)
|
||||
}),
|
||||
body: z.object({
|
||||
emails: z.string().email().array().default([]).describe("Emails of the users to add to the project."),
|
||||
usernames: z.string().array().default([]).describe("Usernames of the users to add to the project.")
|
||||
emails: z.string().email().array().default([]).describe(PROJECTS.INVITE_MEMBER.emails),
|
||||
usernames: z.string().array().default([]).describe(PROJECTS.INVITE_MEMBER.usernames)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
@@ -27,7 +38,9 @@ export const registerProjectMembershipRouter = async (server: FastifyZodProvider
|
||||
handler: async (req) => {
|
||||
const memberships = await server.services.projectMembership.addUsersToProjectNonE2EE({
|
||||
projectId: req.params.projectId,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorId: req.permission.id,
|
||||
actorOrgId: req.permission.orgId,
|
||||
actor: req.permission.type,
|
||||
emails: req.body.emails,
|
||||
usernames: req.body.usernames
|
||||
@@ -53,14 +66,22 @@ export const registerProjectMembershipRouter = async (server: FastifyZodProvider
|
||||
server.route({
|
||||
method: "DELETE",
|
||||
url: "/:projectId/memberships",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
schema: {
|
||||
description: "Remove members from project",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: []
|
||||
}
|
||||
],
|
||||
params: z.object({
|
||||
projectId: z.string().describe("The ID of the project.")
|
||||
projectId: z.string().describe(PROJECTS.REMOVE_MEMBER.projectId)
|
||||
}),
|
||||
|
||||
body: z.object({
|
||||
emails: z.string().email().array().default([]).describe("Emails of the users to remove from the project."),
|
||||
usernames: z.string().array().default([]).describe("Usernames of the users to remove from the project.")
|
||||
emails: z.string().email().array().default([]).describe(PROJECTS.REMOVE_MEMBER.emails),
|
||||
usernames: z.string().array().default([]).describe(PROJECTS.REMOVE_MEMBER.usernames)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
@@ -73,6 +94,7 @@ export const registerProjectMembershipRouter = async (server: FastifyZodProvider
|
||||
const memberships = await server.services.projectMembership.deleteProjectMemberships({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
projectId: req.params.projectId,
|
||||
emails: req.body.emails,
|
||||
|
||||
@@ -3,10 +3,12 @@ import { z } from "zod";
|
||||
|
||||
import { ProjectKeysSchema, ProjectsSchema } from "@app/db/schemas";
|
||||
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
|
||||
import { authRateLimit } from "@app/server/config/rateLimiter";
|
||||
import { PROJECTS } from "@app/lib/api-docs";
|
||||
import { creationLimit, readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||
import { getTelemetryDistinctId } from "@app/server/lib/telemetry";
|
||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||
import { AuthMode } from "@app/services/auth/auth-type";
|
||||
import { ProjectFilterType } from "@app/services/project/project-types";
|
||||
import { PostHogEventTypes } from "@app/services/telemetry/telemetry-types";
|
||||
|
||||
const projectWithEnv = ProjectsSchema.merge(
|
||||
@@ -16,20 +18,26 @@ const projectWithEnv = ProjectsSchema.merge(
|
||||
})
|
||||
);
|
||||
|
||||
const slugSchema = z
|
||||
.string()
|
||||
.min(5)
|
||||
.max(36)
|
||||
.refine((v) => slugify(v) === v, {
|
||||
message: "Slug must be at least 5 character but no more than 36"
|
||||
});
|
||||
|
||||
export const registerProjectRouter = async (server: FastifyZodProvider) => {
|
||||
/* Get project key */
|
||||
server.route({
|
||||
url: "/:workspaceId/encrypted-key",
|
||||
method: "GET",
|
||||
url: "/:workspaceId/encrypted-key",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
schema: {
|
||||
description: "Return encrypted project key",
|
||||
security: [
|
||||
{
|
||||
apiKeyAuth: []
|
||||
}
|
||||
],
|
||||
params: z.object({
|
||||
workspaceId: z.string().trim()
|
||||
workspaceId: z.string().trim().describe(PROJECTS.GET_KEY.workspaceId)
|
||||
}),
|
||||
response: {
|
||||
200: ProjectKeysSchema.merge(
|
||||
@@ -46,6 +54,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
|
||||
const key = await server.services.projectKey.getLatestProjectKey({
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
projectId: req.params.workspaceId
|
||||
});
|
||||
@@ -67,13 +76,15 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
|
||||
|
||||
/* Start upgrade of a project */
|
||||
server.route({
|
||||
url: "/:projectId/upgrade",
|
||||
method: "POST",
|
||||
url: "/:projectId/upgrade",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
schema: {
|
||||
params: z.object({
|
||||
projectId: z.string().trim()
|
||||
}),
|
||||
|
||||
body: z.object({
|
||||
userPrivateKey: z.string().trim()
|
||||
}),
|
||||
@@ -81,11 +92,13 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
|
||||
200: z.void()
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY]),
|
||||
onRequest: verifyAuth([AuthMode.JWT]),
|
||||
handler: async (req) => {
|
||||
await server.services.project.upgradeProject({
|
||||
actorId: req.permission.id,
|
||||
actorOrgId: req.permission.orgId,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
projectId: req.params.projectId,
|
||||
userPrivateKey: req.body.userPrivateKey
|
||||
});
|
||||
@@ -96,6 +109,9 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
url: "/:projectId/upgrade/status",
|
||||
method: "GET",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
schema: {
|
||||
params: z.object({
|
||||
projectId: z.string().trim()
|
||||
@@ -106,9 +122,11 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
|
||||
})
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY]),
|
||||
onRequest: verifyAuth([AuthMode.JWT]),
|
||||
handler: async (req) => {
|
||||
const status = await server.services.project.getProjectUpgradeStatus({
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
projectId: req.params.projectId,
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id
|
||||
@@ -123,11 +141,17 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
|
||||
method: "POST",
|
||||
url: "/",
|
||||
config: {
|
||||
rateLimit: authRateLimit
|
||||
rateLimit: creationLimit
|
||||
},
|
||||
schema: {
|
||||
description: "Create a new project",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: []
|
||||
}
|
||||
],
|
||||
body: z.object({
|
||||
projectName: z.string().trim(),
|
||||
projectName: z.string().trim().describe(PROJECTS.CREATE.projectName),
|
||||
slug: z
|
||||
.string()
|
||||
.min(5)
|
||||
@@ -135,8 +159,8 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
|
||||
.refine((v) => slugify(v) === v, {
|
||||
message: "Slug must be a valid slug"
|
||||
})
|
||||
.optional(),
|
||||
organizationId: z.string().trim()
|
||||
.optional()
|
||||
.describe(PROJECTS.CREATE.slug)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
@@ -144,12 +168,13 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
|
||||
})
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
handler: async (req) => {
|
||||
const project = await server.services.project.createProject({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
orgId: req.body.organizationId,
|
||||
actorOrgId: req.permission.orgId,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
workspaceName: req.body.projectName,
|
||||
slug: req.body.slug
|
||||
});
|
||||
@@ -158,7 +183,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
|
||||
event: PostHogEventTypes.ProjectCreated,
|
||||
distinctId: getTelemetryDistinctId(req),
|
||||
properties: {
|
||||
orgId: req.body.organizationId,
|
||||
orgId: project.orgId,
|
||||
name: project.name,
|
||||
...req.auditLogInfo
|
||||
}
|
||||
@@ -167,4 +192,119 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
|
||||
return { project };
|
||||
}
|
||||
});
|
||||
|
||||
/* Delete a project by slug */
|
||||
server.route({
|
||||
method: "DELETE",
|
||||
url: "/:slug",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
schema: {
|
||||
description: "Delete project",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: []
|
||||
}
|
||||
],
|
||||
params: z.object({
|
||||
slug: slugSchema.describe("The slug of the project to delete.")
|
||||
}),
|
||||
response: {
|
||||
200: ProjectsSchema
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
|
||||
handler: async (req) => {
|
||||
const project = await server.services.project.deleteProject({
|
||||
filter: {
|
||||
type: ProjectFilterType.SLUG,
|
||||
slug: req.params.slug,
|
||||
orgId: req.permission.orgId
|
||||
},
|
||||
actorId: req.permission.id,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
actor: req.permission.type
|
||||
});
|
||||
|
||||
return project;
|
||||
}
|
||||
});
|
||||
|
||||
/* Get a project by slug */
|
||||
server.route({
|
||||
method: "GET",
|
||||
url: "/:slug",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
schema: {
|
||||
params: z.object({
|
||||
slug: slugSchema.describe("The slug of the project to get.")
|
||||
}),
|
||||
response: {
|
||||
200: projectWithEnv
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
handler: async (req) => {
|
||||
const project = await server.services.project.getAProject({
|
||||
filter: {
|
||||
slug: req.params.slug,
|
||||
orgId: req.permission.orgId,
|
||||
type: ProjectFilterType.SLUG
|
||||
},
|
||||
actorId: req.permission.id,
|
||||
actorOrgId: req.permission.orgId,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actor: req.permission.type
|
||||
});
|
||||
|
||||
return project;
|
||||
}
|
||||
});
|
||||
|
||||
/* Update a project by slug */
|
||||
server.route({
|
||||
method: "PATCH",
|
||||
url: "/:slug",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
schema: {
|
||||
params: z.object({
|
||||
slug: slugSchema.describe("The slug of the project to update.")
|
||||
}),
|
||||
body: z.object({
|
||||
name: z.string().trim().optional().describe("The new name of the project."),
|
||||
autoCapitalization: z.boolean().optional().describe("The new auto-capitalization setting.")
|
||||
}),
|
||||
response: {
|
||||
200: ProjectsSchema
|
||||
}
|
||||
},
|
||||
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
handler: async (req) => {
|
||||
const project = await server.services.project.updateProject({
|
||||
filter: {
|
||||
type: ProjectFilterType.SLUG,
|
||||
slug: req.params.slug,
|
||||
orgId: req.permission.orgId
|
||||
},
|
||||
update: {
|
||||
name: req.body.name,
|
||||
autoCapitalization: req.body.autoCapitalization
|
||||
},
|
||||
actorId: req.permission.id,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actor: req.permission.type,
|
||||
actorOrgId: req.permission.orgId
|
||||
});
|
||||
|
||||
return project;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@@ -3,6 +3,7 @@ import { z } from "zod";
|
||||
import { ServiceTokensSchema } from "@app/db/schemas";
|
||||
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
|
||||
import { removeTrailingSlash } from "@app/lib/fn";
|
||||
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||
import { AuthMode } from "@app/services/auth/auth-type";
|
||||
|
||||
@@ -17,8 +18,11 @@ export const sanitizedServiceTokenSchema = ServiceTokensSchema.omit({
|
||||
|
||||
export const registerServiceTokenRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
url: "/",
|
||||
method: "GET",
|
||||
url: "/",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.SERVICE_TOKEN]),
|
||||
schema: {
|
||||
description: "Return Infisical Token data",
|
||||
@@ -46,6 +50,8 @@ export const registerServiceTokenRouter = async (server: FastifyZodProvider) =>
|
||||
handler: async (req) => {
|
||||
const { serviceToken, user } = await server.services.serviceToken.getServiceToken({
|
||||
actorId: req.permission.id,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
actor: req.permission.type
|
||||
});
|
||||
|
||||
@@ -67,8 +73,11 @@ export const registerServiceTokenRouter = async (server: FastifyZodProvider) =>
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/",
|
||||
method: "POST",
|
||||
url: "/",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT]),
|
||||
schema: {
|
||||
body: z.object({
|
||||
@@ -98,6 +107,7 @@ export const registerServiceTokenRouter = async (server: FastifyZodProvider) =>
|
||||
const { serviceToken, token } = await server.services.serviceToken.createServiceToken({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
...req.body,
|
||||
projectId: req.body.workspaceId
|
||||
@@ -119,8 +129,11 @@ export const registerServiceTokenRouter = async (server: FastifyZodProvider) =>
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/:serviceTokenId",
|
||||
method: "DELETE",
|
||||
url: "/:serviceTokenId",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT]),
|
||||
schema: {
|
||||
params: z.object({
|
||||
@@ -136,6 +149,7 @@ export const registerServiceTokenRouter = async (server: FastifyZodProvider) =>
|
||||
const serviceTokenData = await server.services.serviceToken.deleteServiceToken({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
id: req.params.serviceTokenId
|
||||
});
|
||||
|
||||
@@ -2,13 +2,17 @@ import { z } from "zod";
|
||||
|
||||
import { AuthTokenSessionsSchema, OrganizationsSchema, UserEncryptionKeysSchema, UsersSchema } from "@app/db/schemas";
|
||||
import { ApiKeysSchema } from "@app/db/schemas/api-keys";
|
||||
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||
import { AuthMethod, AuthMode } from "@app/services/auth/auth-type";
|
||||
|
||||
export const registerUserRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
url: "/me/mfa",
|
||||
method: "PATCH",
|
||||
url: "/me/mfa",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
schema: {
|
||||
body: z.object({
|
||||
isMfaEnabled: z.boolean()
|
||||
@@ -27,8 +31,11 @@ export const registerUserRouter = async (server: FastifyZodProvider) => {
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/me/name",
|
||||
method: "PATCH",
|
||||
url: "/me/name",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
schema: {
|
||||
body: z.object({
|
||||
firstName: z.string().trim(),
|
||||
@@ -48,8 +55,11 @@ export const registerUserRouter = async (server: FastifyZodProvider) => {
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/me/auth-methods",
|
||||
method: "PUT",
|
||||
url: "/me/auth-methods",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
schema: {
|
||||
body: z.object({
|
||||
authMethods: z.nativeEnum(AuthMethod).array().min(1)
|
||||
@@ -60,7 +70,7 @@ export const registerUserRouter = async (server: FastifyZodProvider) => {
|
||||
})
|
||||
}
|
||||
},
|
||||
preHandler: verifyAuth([AuthMode.JWT, AuthMode.API_KEY]),
|
||||
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 };
|
||||
@@ -70,13 +80,11 @@ export const registerUserRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
method: "GET",
|
||||
url: "/me/organizations",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
schema: {
|
||||
description: "Return organizations that current user is part of",
|
||||
security: [
|
||||
{
|
||||
apiKeyAuth: []
|
||||
}
|
||||
],
|
||||
response: {
|
||||
200: z.object({
|
||||
organizations: OrganizationsSchema.array()
|
||||
@@ -93,6 +101,9 @@ export const registerUserRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
method: "GET",
|
||||
url: "/me/api-keys",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
schema: {
|
||||
response: {
|
||||
200: ApiKeysSchema.omit({ secretHash: true }).array()
|
||||
@@ -108,6 +119,9 @@ export const registerUserRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
method: "POST",
|
||||
url: "/me/api-keys",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
schema: {
|
||||
body: z.object({
|
||||
name: z.string().trim(),
|
||||
@@ -130,6 +144,9 @@ export const registerUserRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
method: "DELETE",
|
||||
url: "/me/api-keys/:apiKeyDataId",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
schema: {
|
||||
params: z.object({
|
||||
apiKeyDataId: z.string().trim()
|
||||
@@ -150,6 +167,9 @@ export const registerUserRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
method: "GET",
|
||||
url: "/me/sessions",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
schema: {
|
||||
response: {
|
||||
200: AuthTokenSessionsSchema.array()
|
||||
@@ -165,6 +185,9 @@ export const registerUserRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
method: "DELETE",
|
||||
url: "/me/sessions",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
schema: {
|
||||
response: {
|
||||
200: z.object({
|
||||
@@ -184,13 +207,11 @@ export const registerUserRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
method: "GET",
|
||||
url: "/me",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
schema: {
|
||||
description: "Retrieve the current user on the request",
|
||||
security: [
|
||||
{
|
||||
apiKeyAuth: []
|
||||
}
|
||||
],
|
||||
response: {
|
||||
200: z.object({
|
||||
user: UsersSchema.merge(UserEncryptionKeysSchema.omit({ verifier: true }))
|
||||
@@ -207,6 +228,9 @@ export const registerUserRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
method: "DELETE",
|
||||
url: "/me",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
schema: {
|
||||
response: {
|
||||
200: z.object({
|
||||
|
||||
@@ -34,6 +34,42 @@ export const registerLoginRouter = async (server: FastifyZodProvider) => {
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
method: "POST",
|
||||
url: "/select-organization",
|
||||
config: {
|
||||
rateLimit: authRateLimit
|
||||
},
|
||||
schema: {
|
||||
body: z.object({
|
||||
organizationId: z.string().trim()
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
token: z.string()
|
||||
})
|
||||
}
|
||||
},
|
||||
handler: async (req, res) => {
|
||||
const cfg = getConfig();
|
||||
const tokens = await server.services.login.selectOrganization({
|
||||
userAgent: req.headers["user-agent"],
|
||||
authJwtToken: req.headers.authorization,
|
||||
organizationId: req.body.organizationId,
|
||||
ipAddress: req.realIp
|
||||
});
|
||||
|
||||
void res.setCookie("jid", tokens.refresh, {
|
||||
httpOnly: true,
|
||||
path: "/",
|
||||
sameSite: "strict",
|
||||
secure: cfg.HTTPS_ENABLED
|
||||
});
|
||||
|
||||
return { token: tokens.access };
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
method: "POST",
|
||||
url: "/login2",
|
||||
|
||||
@@ -1,13 +1,17 @@
|
||||
import { z } from "zod";
|
||||
|
||||
import { SecretsSchema } from "@app/db/schemas";
|
||||
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||
import { AuthMode } from "@app/services/auth/auth-type";
|
||||
|
||||
export const registerSecretBlindIndexRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
url: "/:projectId/secrets/blind-index-status",
|
||||
method: "GET",
|
||||
url: "/:projectId/secrets/blind-index-status",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
schema: {
|
||||
params: z.object({
|
||||
projectId: z.string().trim()
|
||||
@@ -20,6 +24,7 @@ export const registerSecretBlindIndexRouter = async (server: FastifyZodProvider)
|
||||
handler: async (req) => {
|
||||
const count = await server.services.secretBlindIndex.getSecretBlindIndexStatus({
|
||||
projectId: req.params.projectId,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorOrgId: req.permission.orgId
|
||||
@@ -29,8 +34,11 @@ export const registerSecretBlindIndexRouter = async (server: FastifyZodProvider)
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/:projectId/secrets",
|
||||
method: "GET",
|
||||
url: "/:projectId/secrets",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
schema: {
|
||||
params: z.object({
|
||||
projectId: z.string().trim()
|
||||
@@ -52,6 +60,7 @@ export const registerSecretBlindIndexRouter = async (server: FastifyZodProvider)
|
||||
handler: async (req) => {
|
||||
const secrets = await server.services.secretBlindIndex.getProjectSecrets({
|
||||
projectId: req.params.projectId,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorOrgId: req.permission.orgId
|
||||
@@ -61,8 +70,11 @@ export const registerSecretBlindIndexRouter = async (server: FastifyZodProvider)
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/:projectId/secrets/names",
|
||||
method: "POST",
|
||||
url: "/:projectId/secrets/names",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
schema: {
|
||||
params: z.object({
|
||||
projectId: z.string().trim()
|
||||
@@ -86,6 +98,7 @@ export const registerSecretBlindIndexRouter = async (server: FastifyZodProvider)
|
||||
await server.services.secretBlindIndex.updateProjectSecretName({
|
||||
projectId: req.params.projectId,
|
||||
secretsToUpdate: req.body.secretsToUpdate,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorOrgId: req.permission.orgId
|
||||
|
||||
@@ -10,40 +10,180 @@ import {
|
||||
} from "@app/db/schemas";
|
||||
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
|
||||
import { CommitType } from "@app/ee/services/secret-approval-request/secret-approval-request-types";
|
||||
import { RAW_SECRETS, SECRETS } from "@app/lib/api-docs";
|
||||
import { BadRequestError } from "@app/lib/errors";
|
||||
import { removeTrailingSlash } from "@app/lib/fn";
|
||||
import { secretsLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||
import { getTelemetryDistinctId } from "@app/server/lib/telemetry";
|
||||
import { getUserAgentType } from "@app/server/plugins/audit-log";
|
||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||
import { ActorType, AuthMode } from "@app/services/auth/auth-type";
|
||||
import { ProjectFilterType } from "@app/services/project/project-types";
|
||||
import { PostHogEventTypes } from "@app/services/telemetry/telemetry-types";
|
||||
|
||||
import { secretRawSchema } from "../sanitizedSchemas";
|
||||
|
||||
export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
url: "/raw",
|
||||
method: "POST",
|
||||
url: "/tags/:secretName",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
schema: {
|
||||
description: "Attach tags to a secret",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: []
|
||||
}
|
||||
],
|
||||
params: z.object({
|
||||
secretName: z.string().trim().describe(SECRETS.ATTACH_TAGS.secretName)
|
||||
}),
|
||||
body: z.object({
|
||||
projectSlug: z.string().trim().describe(SECRETS.ATTACH_TAGS.projectSlug),
|
||||
environment: z.string().trim().describe(SECRETS.ATTACH_TAGS.environment),
|
||||
secretPath: z
|
||||
.string()
|
||||
.trim()
|
||||
.default("/")
|
||||
.transform(removeTrailingSlash)
|
||||
.describe(SECRETS.ATTACH_TAGS.secretPath),
|
||||
type: z.nativeEnum(SecretType).default(SecretType.Shared).describe(SECRETS.ATTACH_TAGS.type),
|
||||
tagSlugs: z.string().array().min(1).describe(SECRETS.ATTACH_TAGS.tagSlugs)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
secret: SecretsSchema.omit({ secretBlindIndex: true }).merge(
|
||||
z.object({
|
||||
tags: SecretTagsSchema.pick({
|
||||
id: true,
|
||||
slug: true,
|
||||
name: true,
|
||||
color: true
|
||||
}).array()
|
||||
})
|
||||
)
|
||||
})
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
handler: async (req) => {
|
||||
const secret = await server.services.secret.attachTags({
|
||||
secretName: req.params.secretName,
|
||||
tagSlugs: req.body.tagSlugs,
|
||||
path: req.body.secretPath,
|
||||
environment: req.body.environment,
|
||||
type: req.body.type,
|
||||
projectSlug: req.body.projectSlug,
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId
|
||||
});
|
||||
|
||||
return { secret };
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
method: "DELETE",
|
||||
url: "/tags/:secretName",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
schema: {
|
||||
description: "Detach tags from a secret",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: []
|
||||
}
|
||||
],
|
||||
params: z.object({
|
||||
secretName: z.string().trim().describe(SECRETS.DETACH_TAGS.secretName)
|
||||
}),
|
||||
body: z.object({
|
||||
projectSlug: z.string().trim().describe(SECRETS.DETACH_TAGS.projectSlug),
|
||||
environment: z.string().trim().describe(SECRETS.DETACH_TAGS.environment),
|
||||
secretPath: z
|
||||
.string()
|
||||
.trim()
|
||||
.default("/")
|
||||
.transform(removeTrailingSlash)
|
||||
.describe(SECRETS.DETACH_TAGS.secretPath),
|
||||
type: z.nativeEnum(SecretType).default(SecretType.Shared).describe(SECRETS.DETACH_TAGS.type),
|
||||
tagSlugs: z.string().array().min(1).describe(SECRETS.DETACH_TAGS.tagSlugs)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
secret: SecretsSchema.omit({ secretBlindIndex: true }).merge(
|
||||
z.object({
|
||||
tags: SecretTagsSchema.pick({
|
||||
id: true,
|
||||
slug: true,
|
||||
name: true,
|
||||
color: true
|
||||
}).array()
|
||||
})
|
||||
)
|
||||
})
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
handler: async (req) => {
|
||||
const secret = await server.services.secret.detachTags({
|
||||
secretName: req.params.secretName,
|
||||
tagSlugs: req.body.tagSlugs,
|
||||
path: req.body.secretPath,
|
||||
environment: req.body.environment,
|
||||
type: req.body.type,
|
||||
projectSlug: req.body.projectSlug,
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId
|
||||
});
|
||||
|
||||
return { secret };
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
method: "GET",
|
||||
url: "/raw",
|
||||
config: {
|
||||
rateLimit: secretsLimit
|
||||
},
|
||||
schema: {
|
||||
description: "List secrets",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: [],
|
||||
apiKeyAuth: []
|
||||
bearerAuth: []
|
||||
}
|
||||
],
|
||||
querystring: z.object({
|
||||
workspaceId: z.string().trim().optional(),
|
||||
environment: z.string().trim().optional(),
|
||||
secretPath: z.string().trim().default("/").transform(removeTrailingSlash),
|
||||
workspaceId: z.string().trim().optional().describe(RAW_SECRETS.LIST.workspaceId),
|
||||
workspaceSlug: z.string().trim().optional().describe(RAW_SECRETS.LIST.workspaceSlug),
|
||||
environment: z.string().trim().optional().describe(RAW_SECRETS.LIST.environment),
|
||||
secretPath: z.string().trim().default("/").transform(removeTrailingSlash).describe(RAW_SECRETS.LIST.secretPath),
|
||||
recursive: z
|
||||
.enum(["true", "false"])
|
||||
.default("false")
|
||||
.transform((value) => value === "true")
|
||||
.describe(RAW_SECRETS.LIST.recursive),
|
||||
include_imports: z
|
||||
.enum(["true", "false"])
|
||||
.default("false")
|
||||
.transform((value) => value === "true")
|
||||
.describe(RAW_SECRETS.LIST.includeImports)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
secrets: secretRawSchema.array(),
|
||||
secrets: secretRawSchema
|
||||
.extend({
|
||||
secretPath: z.string().optional()
|
||||
})
|
||||
.array(),
|
||||
imports: z
|
||||
.object({
|
||||
secretPath: z.string(),
|
||||
@@ -68,6 +208,22 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
||||
environment = scope[0].environment;
|
||||
workspaceId = req.auth.serviceToken.projectId;
|
||||
}
|
||||
} else if (req.permission.type === ActorType.IDENTITY && req.query.workspaceSlug && !workspaceId) {
|
||||
const workspace = await server.services.project.getAProject({
|
||||
filter: {
|
||||
type: ProjectFilterType.SLUG,
|
||||
orgId: req.permission.orgId,
|
||||
slug: req.query.workspaceSlug
|
||||
},
|
||||
actorId: req.permission.id,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actor: req.permission.type,
|
||||
actorOrgId: req.permission.orgId
|
||||
});
|
||||
|
||||
if (!workspace) throw new BadRequestError({ message: `No project found with slug ${req.query.workspaceSlug}` });
|
||||
|
||||
workspaceId = workspace.id;
|
||||
}
|
||||
|
||||
if (!workspaceId || !environment) throw new BadRequestError({ message: "Missing workspace id or environment" });
|
||||
@@ -77,13 +233,15 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
||||
actor: req.permission.type,
|
||||
actorOrgId: req.permission.orgId,
|
||||
environment,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
projectId: workspaceId,
|
||||
path: secretPath,
|
||||
includeImports: req.query.include_imports
|
||||
includeImports: req.query.include_imports,
|
||||
recursive: req.query.recursive
|
||||
});
|
||||
|
||||
await server.services.auditLog.createAuditLog({
|
||||
projectId: req.query.workspaceId,
|
||||
projectId: workspaceId,
|
||||
...req.auditLogInfo,
|
||||
event: {
|
||||
type: EventType.GET_SECRETS,
|
||||
@@ -112,29 +270,32 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/raw/:secretName",
|
||||
method: "GET",
|
||||
url: "/raw/:secretName",
|
||||
config: {
|
||||
rateLimit: secretsLimit
|
||||
},
|
||||
schema: {
|
||||
description: "Get a secret by name",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: [],
|
||||
apiKeyAuth: []
|
||||
bearerAuth: []
|
||||
}
|
||||
],
|
||||
params: z.object({
|
||||
secretName: z.string().trim()
|
||||
secretName: z.string().trim().describe(RAW_SECRETS.GET.secretName)
|
||||
}),
|
||||
querystring: z.object({
|
||||
workspaceId: z.string().trim().optional(),
|
||||
environment: z.string().trim().optional(),
|
||||
secretPath: z.string().trim().default("/").transform(removeTrailingSlash),
|
||||
version: z.coerce.number().optional(),
|
||||
type: z.nativeEnum(SecretType).default(SecretType.Shared),
|
||||
workspaceId: z.string().trim().optional().describe(RAW_SECRETS.GET.workspaceId),
|
||||
environment: z.string().trim().optional().describe(RAW_SECRETS.GET.environment),
|
||||
secretPath: z.string().trim().default("/").transform(removeTrailingSlash).describe(RAW_SECRETS.GET.secretPath),
|
||||
version: z.coerce.number().optional().describe(RAW_SECRETS.GET.version),
|
||||
type: z.nativeEnum(SecretType).default(SecretType.Shared).describe(RAW_SECRETS.GET.type),
|
||||
include_imports: z
|
||||
.enum(["true", "false"])
|
||||
.default("false")
|
||||
.transform((value) => value === "true")
|
||||
.describe(RAW_SECRETS.GET.includeImports)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
@@ -160,6 +321,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
||||
const secret = await server.services.secret.getSecretByNameRaw({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
environment,
|
||||
projectId: workspaceId,
|
||||
@@ -202,27 +364,37 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/raw/:secretName",
|
||||
method: "POST",
|
||||
url: "/raw/:secretName",
|
||||
config: {
|
||||
rateLimit: secretsLimit
|
||||
},
|
||||
schema: {
|
||||
description: "Create secret",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: [],
|
||||
apiKeyAuth: []
|
||||
bearerAuth: []
|
||||
}
|
||||
],
|
||||
params: z.object({
|
||||
secretName: z.string().trim()
|
||||
secretName: z.string().trim().describe(RAW_SECRETS.CREATE.secretName)
|
||||
}),
|
||||
body: z.object({
|
||||
workspaceId: z.string().trim(),
|
||||
environment: z.string().trim(),
|
||||
secretPath: z.string().trim().default("/").transform(removeTrailingSlash),
|
||||
secretValue: z.string().transform((val) => (val.at(-1) === "\n" ? `${val.trim()}\n` : val.trim())),
|
||||
secretComment: z.string().trim().optional().default(""),
|
||||
skipMultilineEncoding: z.boolean().optional(),
|
||||
type: z.nativeEnum(SecretType).default(SecretType.Shared)
|
||||
workspaceId: z.string().trim().describe(RAW_SECRETS.CREATE.workspaceId),
|
||||
environment: z.string().trim().describe(RAW_SECRETS.CREATE.environment),
|
||||
secretPath: z
|
||||
.string()
|
||||
.trim()
|
||||
.default("/")
|
||||
.transform(removeTrailingSlash)
|
||||
.describe(RAW_SECRETS.CREATE.secretPath),
|
||||
secretValue: z
|
||||
.string()
|
||||
.transform((val) => (val.at(-1) === "\n" ? `${val.trim()}\n` : val.trim()))
|
||||
.describe(RAW_SECRETS.CREATE.secretValue),
|
||||
secretComment: z.string().trim().optional().default("").describe(RAW_SECRETS.CREATE.secretComment),
|
||||
skipMultilineEncoding: z.boolean().optional().describe(RAW_SECRETS.CREATE.skipMultilineEncoding),
|
||||
type: z.nativeEnum(SecretType).default(SecretType.Shared).describe(RAW_SECRETS.CREATE.type)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
@@ -237,6 +409,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
||||
actor: req.permission.type,
|
||||
actorOrgId: req.permission.orgId,
|
||||
environment: req.body.environment,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
projectId: req.body.workspaceId,
|
||||
secretPath: req.body.secretPath,
|
||||
secretName: req.params.secretName,
|
||||
@@ -279,26 +452,36 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/raw/:secretName",
|
||||
method: "PATCH",
|
||||
url: "/raw/:secretName",
|
||||
config: {
|
||||
rateLimit: secretsLimit
|
||||
},
|
||||
schema: {
|
||||
description: "Update secret",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: [],
|
||||
apiKeyAuth: []
|
||||
bearerAuth: []
|
||||
}
|
||||
],
|
||||
params: z.object({
|
||||
secretName: z.string().trim()
|
||||
secretName: z.string().trim().describe(RAW_SECRETS.UPDATE.secretName)
|
||||
}),
|
||||
body: z.object({
|
||||
workspaceId: z.string().trim(),
|
||||
environment: z.string().trim(),
|
||||
secretValue: z.string().transform((val) => (val.at(-1) === "\n" ? `${val.trim()}\n` : val.trim())),
|
||||
secretPath: z.string().trim().default("/").transform(removeTrailingSlash),
|
||||
skipMultilineEncoding: z.boolean().optional(),
|
||||
type: z.nativeEnum(SecretType).default(SecretType.Shared)
|
||||
workspaceId: z.string().trim().describe(RAW_SECRETS.UPDATE.workspaceId),
|
||||
environment: z.string().trim().describe(RAW_SECRETS.UPDATE.environment),
|
||||
secretValue: z
|
||||
.string()
|
||||
.transform((val) => (val.at(-1) === "\n" ? `${val.trim()}\n` : val.trim()))
|
||||
.describe(RAW_SECRETS.UPDATE.secretValue),
|
||||
secretPath: z
|
||||
.string()
|
||||
.trim()
|
||||
.default("/")
|
||||
.transform(removeTrailingSlash)
|
||||
.describe(RAW_SECRETS.UPDATE.secretPath),
|
||||
skipMultilineEncoding: z.boolean().optional().describe(RAW_SECRETS.UPDATE.skipMultilineEncoding),
|
||||
type: z.nativeEnum(SecretType).default(SecretType.Shared).describe(RAW_SECRETS.UPDATE.type)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
@@ -312,6 +495,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorOrgId: req.permission.orgId,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
environment: req.body.environment,
|
||||
projectId: req.body.workspaceId,
|
||||
secretPath: req.body.secretPath,
|
||||
@@ -353,24 +537,31 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/raw/:secretName",
|
||||
method: "DELETE",
|
||||
url: "/raw/:secretName",
|
||||
config: {
|
||||
rateLimit: secretsLimit
|
||||
},
|
||||
schema: {
|
||||
description: "Delete secret",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: [],
|
||||
apiKeyAuth: []
|
||||
bearerAuth: []
|
||||
}
|
||||
],
|
||||
params: z.object({
|
||||
secretName: z.string().trim()
|
||||
secretName: z.string().trim().describe(RAW_SECRETS.DELETE.secretName)
|
||||
}),
|
||||
body: z.object({
|
||||
workspaceId: z.string().trim(),
|
||||
environment: z.string().trim(),
|
||||
secretPath: z.string().trim().default("/").transform(removeTrailingSlash),
|
||||
type: z.nativeEnum(SecretType).default(SecretType.Shared)
|
||||
workspaceId: z.string().trim().describe(RAW_SECRETS.DELETE.workspaceId),
|
||||
environment: z.string().trim().describe(RAW_SECRETS.DELETE.environment),
|
||||
secretPath: z
|
||||
.string()
|
||||
.trim()
|
||||
.default("/")
|
||||
.transform(removeTrailingSlash)
|
||||
.describe(RAW_SECRETS.DELETE.secretPath),
|
||||
type: z.nativeEnum(SecretType).default(SecretType.Shared).describe(RAW_SECRETS.DELETE.type)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
@@ -383,6 +574,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
||||
const secret = await server.services.secret.deleteSecretRaw({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
environment: req.body.environment,
|
||||
projectId: req.body.workspaceId,
|
||||
@@ -424,13 +616,20 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/",
|
||||
method: "GET",
|
||||
url: "/",
|
||||
config: {
|
||||
rateLimit: secretsLimit
|
||||
},
|
||||
schema: {
|
||||
querystring: z.object({
|
||||
workspaceId: z.string().trim(),
|
||||
environment: z.string().trim(),
|
||||
secretPath: z.string().trim().default("/").transform(removeTrailingSlash),
|
||||
recursive: z
|
||||
.enum(["true", "false"])
|
||||
.default("false")
|
||||
.transform((value) => value === "true"),
|
||||
include_imports: z
|
||||
.enum(["true", "false"])
|
||||
.default("false")
|
||||
@@ -439,19 +638,18 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
||||
response: {
|
||||
200: z.object({
|
||||
secrets: SecretsSchema.omit({ secretBlindIndex: true })
|
||||
.merge(
|
||||
z.object({
|
||||
_id: z.string(),
|
||||
workspace: z.string(),
|
||||
environment: z.string(),
|
||||
tags: SecretTagsSchema.pick({
|
||||
id: true,
|
||||
slug: true,
|
||||
name: true,
|
||||
color: true
|
||||
}).array()
|
||||
})
|
||||
)
|
||||
.extend({
|
||||
_id: z.string(),
|
||||
workspace: z.string(),
|
||||
environment: z.string(),
|
||||
secretPath: z.string().optional(),
|
||||
tags: SecretTagsSchema.pick({
|
||||
id: true,
|
||||
slug: true,
|
||||
name: true,
|
||||
color: true
|
||||
}).array()
|
||||
})
|
||||
.array(),
|
||||
imports: z
|
||||
.object({
|
||||
@@ -478,11 +676,13 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
||||
const { secrets, imports } = await server.services.secret.getSecrets({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
environment: req.query.environment,
|
||||
projectId: req.query.workspaceId,
|
||||
path: req.query.secretPath,
|
||||
includeImports: req.query.include_imports
|
||||
includeImports: req.query.include_imports,
|
||||
recursive: req.query.recursive
|
||||
});
|
||||
|
||||
await server.services.auditLog.createAuditLog({
|
||||
@@ -531,8 +731,11 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/:secretName",
|
||||
method: "GET",
|
||||
url: "/:secretName",
|
||||
config: {
|
||||
rateLimit: secretsLimit
|
||||
},
|
||||
schema: {
|
||||
params: z.object({
|
||||
secretName: z.string().trim()
|
||||
@@ -564,6 +767,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
||||
const secret = await server.services.secret.getSecretByName({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
environment: req.query.environment,
|
||||
projectId: req.query.workspaceId,
|
||||
@@ -608,6 +812,9 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
url: "/:secretName",
|
||||
method: "POST",
|
||||
config: {
|
||||
rateLimit: secretsLimit
|
||||
},
|
||||
schema: {
|
||||
body: z.object({
|
||||
workspaceId: z.string().trim(),
|
||||
@@ -666,6 +873,8 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
||||
if (req.body.type !== SecretType.Personal && req.permission.type === ActorType.USER) {
|
||||
const policy = await server.services.secretApprovalPolicy.getSecretApprovalPolicyOfFolder({
|
||||
actorId: req.permission.id,
|
||||
actorOrgId: req.permission.orgId,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actor: req.permission.type,
|
||||
secretPath,
|
||||
environment,
|
||||
@@ -675,6 +884,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
||||
const approval = await server.services.secretApprovalRequest.generateSecretApprovalRequest({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
secretPath,
|
||||
environment,
|
||||
@@ -718,6 +928,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
||||
const secret = await server.services.secret.createSecret({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
path: secretPath,
|
||||
type,
|
||||
@@ -770,8 +981,11 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/:secretName",
|
||||
method: "PATCH",
|
||||
url: "/:secretName",
|
||||
config: {
|
||||
rateLimit: secretsLimit
|
||||
},
|
||||
schema: {
|
||||
params: z.object({
|
||||
secretName: z.string()
|
||||
@@ -842,6 +1056,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
||||
const policy = await server.services.secretApprovalPolicy.getSecretApprovalPolicyOfFolder({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
secretPath,
|
||||
environment,
|
||||
@@ -851,6 +1066,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
||||
const approval = await server.services.secretApprovalRequest.generateSecretApprovalRequest({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
secretPath,
|
||||
environment,
|
||||
@@ -896,6 +1112,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
||||
const secret = await server.services.secret.updateSecret({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
path: secretPath,
|
||||
type,
|
||||
@@ -951,8 +1168,11 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/:secretName",
|
||||
method: "DELETE",
|
||||
url: "/:secretName",
|
||||
config: {
|
||||
rateLimit: secretsLimit
|
||||
},
|
||||
schema: {
|
||||
params: z.object({
|
||||
secretName: z.string()
|
||||
@@ -986,6 +1206,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
||||
const policy = await server.services.secretApprovalPolicy.getSecretApprovalPolicyOfFolder({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
secretPath,
|
||||
environment,
|
||||
@@ -995,6 +1216,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
||||
const approval = await server.services.secretApprovalRequest.generateSecretApprovalRequest({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
secretPath,
|
||||
environment,
|
||||
@@ -1028,6 +1250,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
||||
const secret = await server.services.secret.deleteSecret({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
path: secretPath,
|
||||
type,
|
||||
@@ -1069,8 +1292,11 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/batch",
|
||||
method: "POST",
|
||||
url: "/batch",
|
||||
config: {
|
||||
rateLimit: secretsLimit
|
||||
},
|
||||
schema: {
|
||||
body: z.object({
|
||||
workspaceId: z.string().trim(),
|
||||
@@ -1110,6 +1336,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
||||
const policy = await server.services.secretApprovalPolicy.getSecretApprovalPolicyOfFolder({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
secretPath,
|
||||
environment,
|
||||
@@ -1119,6 +1346,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
||||
const approval = await server.services.secretApprovalRequest.generateSecretApprovalRequest({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
secretPath,
|
||||
environment,
|
||||
@@ -1148,6 +1376,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
||||
const secrets = await server.services.secret.createManySecret({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
path: secretPath,
|
||||
environment,
|
||||
@@ -1189,8 +1418,11 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/batch",
|
||||
method: "PATCH",
|
||||
url: "/batch",
|
||||
config: {
|
||||
rateLimit: secretsLimit
|
||||
},
|
||||
schema: {
|
||||
body: z.object({
|
||||
workspaceId: z.string().trim(),
|
||||
@@ -1231,6 +1463,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
||||
const policy = await server.services.secretApprovalPolicy.getSecretApprovalPolicyOfFolder({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
secretPath,
|
||||
environment,
|
||||
@@ -1240,6 +1473,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
||||
const approval = await server.services.secretApprovalRequest.generateSecretApprovalRequest({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
secretPath,
|
||||
environment,
|
||||
@@ -1268,6 +1502,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
||||
const secrets = await server.services.secret.updateManySecret({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
path: secretPath,
|
||||
environment,
|
||||
@@ -1309,8 +1544,11 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/batch",
|
||||
method: "DELETE",
|
||||
url: "/batch",
|
||||
config: {
|
||||
rateLimit: secretsLimit
|
||||
},
|
||||
schema: {
|
||||
body: z.object({
|
||||
workspaceId: z.string().trim(),
|
||||
@@ -1340,6 +1578,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
||||
const policy = await server.services.secretApprovalPolicy.getSecretApprovalPolicyOfFolder({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
secretPath,
|
||||
environment,
|
||||
@@ -1349,6 +1588,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
||||
const approval = await server.services.secretApprovalRequest.generateSecretApprovalRequest({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
secretPath,
|
||||
environment,
|
||||
@@ -1376,6 +1616,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
||||
const secrets = await server.services.secret.deleteManySecret({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
path: req.body.secretPath,
|
||||
environment,
|
||||
|
||||
@@ -108,7 +108,8 @@ export const registerSignupRouter = async (server: FastifyZodProvider) => {
|
||||
200: z.object({
|
||||
message: z.string(),
|
||||
user: UsersSchema,
|
||||
token: z.string()
|
||||
token: z.string(),
|
||||
organizationId: z.string().nullish()
|
||||
})
|
||||
}
|
||||
},
|
||||
@@ -124,12 +125,13 @@ export const registerSignupRouter = async (server: FastifyZodProvider) => {
|
||||
});
|
||||
}
|
||||
|
||||
const { user, accessToken, refreshToken } = await server.services.signup.completeEmailAccountSignup({
|
||||
...req.body,
|
||||
ip: req.realIp,
|
||||
userAgent,
|
||||
authorization: req.headers.authorization as string
|
||||
});
|
||||
const { user, accessToken, refreshToken, organizationId } =
|
||||
await server.services.signup.completeEmailAccountSignup({
|
||||
...req.body,
|
||||
ip: req.realIp,
|
||||
userAgent,
|
||||
authorization: req.headers.authorization as string
|
||||
});
|
||||
|
||||
if (user.email) {
|
||||
void server.services.telemetry.sendLoopsEvent(user.email, user.firstName || "", user.lastName || "");
|
||||
@@ -152,7 +154,7 @@ export const registerSignupRouter = async (server: FastifyZodProvider) => {
|
||||
secure: appCfg.HTTPS_ENABLED
|
||||
});
|
||||
|
||||
return { message: "Successfully set up account", user, token: accessToken };
|
||||
return { message: "Successfully set up account", user, token: accessToken, organizationId };
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { z } from "zod";
|
||||
|
||||
import { ApiKeysSchema } from "@app/db/schemas/api-keys";
|
||||
import { readLimit } from "@app/server/config/rateLimiter";
|
||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||
import { AuthMode } from "@app/services/auth/auth-type";
|
||||
|
||||
@@ -8,6 +9,9 @@ export const registerUserRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
method: "GET",
|
||||
url: "/me/api-keys",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
schema: {
|
||||
response: {
|
||||
200: z.object({
|
||||
|
||||
Reference in New Issue
Block a user