mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-14 04:29:36 +00:00
feat: updated folder, import, approvals and some more to projectid
This commit is contained in:
@@ -10,6 +10,8 @@ import { registerDepreciatedProjectMembershipRouter } from "./depreciated-projec
|
||||
import { registerDepreciatedProjectRouter } from "./depreciated-project-router";
|
||||
import { registerServiceTokenRouter } from "./service-token-router";
|
||||
import { registerUserRouter } from "./user-router";
|
||||
import { registerSecretFolderRouter } from "./secret-folder-router";
|
||||
import { registerSecretImportRouter } from "./secret-import-router";
|
||||
|
||||
export const registerV2Routes = async (server: FastifyZodProvider) => {
|
||||
await server.register(registerMfaRouter, { prefix: "/auth" });
|
||||
@@ -33,6 +35,9 @@ export const registerV2Routes = async (server: FastifyZodProvider) => {
|
||||
{ prefix: "/organizations" }
|
||||
);
|
||||
|
||||
await server.register(registerSecretFolderRouter, { prefix: "/folders" });
|
||||
await server.register(registerSecretImportRouter, { prefix: "/secret-imports" });
|
||||
|
||||
// moved to v1/projects
|
||||
await server.register(
|
||||
async (projectServer) => {
|
||||
|
||||
@@ -0,0 +1,393 @@
|
||||
import { z } from "zod";
|
||||
|
||||
import { SecretFoldersSchema } from "@app/db/schemas";
|
||||
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
|
||||
import { ApiDocsTags, FOLDERS } from "@app/lib/api-docs";
|
||||
import { prefixWithSlash, removeTrailingSlash } from "@app/lib/fn";
|
||||
import { isValidFolderName } from "@app/lib/validator";
|
||||
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";
|
||||
|
||||
import { booleanSchema } from "../sanitizedSchemas";
|
||||
|
||||
export const registerSecretFolderRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
url: "/",
|
||||
method: "POST",
|
||||
config: {
|
||||
rateLimit: secretsLimit
|
||||
},
|
||||
schema: {
|
||||
hide: false,
|
||||
tags: [ApiDocsTags.Folders],
|
||||
description: "Create folders",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: []
|
||||
}
|
||||
],
|
||||
body: z.object({
|
||||
projectId: z.string().trim().describe(FOLDERS.CREATE.projectId),
|
||||
environment: z.string().trim().describe(FOLDERS.CREATE.environment),
|
||||
name: z
|
||||
.string()
|
||||
.trim()
|
||||
.describe(FOLDERS.CREATE.name)
|
||||
.refine((name) => isValidFolderName(name), {
|
||||
message: "Invalid folder name. Only alphanumeric characters, dashes, and underscores are allowed."
|
||||
}),
|
||||
path: z
|
||||
.string()
|
||||
.trim()
|
||||
.default("/")
|
||||
.transform(prefixWithSlash) // Transformations get skipped if path is undefined
|
||||
.transform(removeTrailingSlash)
|
||||
.describe(FOLDERS.CREATE.path),
|
||||
description: z.string().optional().nullable().describe(FOLDERS.CREATE.description)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
folder: SecretFoldersSchema.extend({
|
||||
path: z.string()
|
||||
})
|
||||
})
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY, AuthMode.SERVICE_TOKEN, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
handler: async (req) => {
|
||||
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,
|
||||
description: req.body.description
|
||||
});
|
||||
await server.services.auditLog.createAuditLog({
|
||||
...req.auditLogInfo,
|
||||
projectId: req.body.projectId,
|
||||
event: {
|
||||
type: EventType.CREATE_FOLDER,
|
||||
metadata: {
|
||||
environment: req.body.environment,
|
||||
folderId: folder.id,
|
||||
folderName: folder.name,
|
||||
folderPath: req.body.path,
|
||||
...(req.body.description ? { description: req.body.description } : {})
|
||||
}
|
||||
}
|
||||
});
|
||||
return { folder };
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/:folderId",
|
||||
method: "PATCH",
|
||||
config: {
|
||||
rateLimit: secretsLimit
|
||||
},
|
||||
schema: {
|
||||
hide: false,
|
||||
tags: [ApiDocsTags.Folders],
|
||||
description: "Update folder",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: []
|
||||
}
|
||||
],
|
||||
params: z.object({
|
||||
// old way this was name
|
||||
folderId: z.string().describe(FOLDERS.UPDATE.folderId)
|
||||
}),
|
||||
body: z.object({
|
||||
projectId: z.string().trim().describe(FOLDERS.UPDATE.projectId),
|
||||
environment: z.string().trim().describe(FOLDERS.UPDATE.environment),
|
||||
name: z
|
||||
.string()
|
||||
.trim()
|
||||
.describe(FOLDERS.UPDATE.name)
|
||||
.refine((name) => isValidFolderName(name), {
|
||||
message: "Invalid folder name. Only alphanumeric characters, dashes, and underscores are allowed."
|
||||
}),
|
||||
path: z
|
||||
.string()
|
||||
.trim()
|
||||
.default("/")
|
||||
.transform(prefixWithSlash) // Transformations get skipped if path is undefined
|
||||
.transform(removeTrailingSlash)
|
||||
.describe(FOLDERS.UPDATE.path),
|
||||
description: z.string().optional().nullable().describe(FOLDERS.UPDATE.description)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
folder: SecretFoldersSchema.extend({
|
||||
path: z.string()
|
||||
})
|
||||
})
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY, AuthMode.SERVICE_TOKEN, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
handler: async (req) => {
|
||||
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,
|
||||
id: req.params.folderId
|
||||
});
|
||||
await server.services.auditLog.createAuditLog({
|
||||
...req.auditLogInfo,
|
||||
projectId: req.body.projectId,
|
||||
event: {
|
||||
type: EventType.UPDATE_FOLDER,
|
||||
metadata: {
|
||||
environment: req.body.environment,
|
||||
folderId: folder.id,
|
||||
folderPath: req.body.path,
|
||||
newFolderName: folder.name,
|
||||
oldFolderName: old.name
|
||||
}
|
||||
}
|
||||
});
|
||||
return { folder };
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/batch",
|
||||
method: "PATCH",
|
||||
config: {
|
||||
rateLimit: secretsLimit
|
||||
},
|
||||
schema: {
|
||||
hide: false,
|
||||
tags: [ApiDocsTags.Folders],
|
||||
description: "Update folders by batch",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: []
|
||||
}
|
||||
],
|
||||
body: z.object({
|
||||
projectId: z.string().trim().describe(FOLDERS.UPDATE.projectId),
|
||||
folders: z
|
||||
.object({
|
||||
id: z.string().describe(FOLDERS.UPDATE.folderId),
|
||||
environment: z.string().trim().describe(FOLDERS.UPDATE.environment),
|
||||
name: z
|
||||
.string()
|
||||
.trim()
|
||||
.describe(FOLDERS.UPDATE.name)
|
||||
.refine((name) => isValidFolderName(name), {
|
||||
message: "Invalid folder name. Only alphanumeric characters, dashes, and underscores are allowed."
|
||||
}),
|
||||
path: z
|
||||
.string()
|
||||
.trim()
|
||||
.default("/")
|
||||
.transform(prefixWithSlash)
|
||||
.transform(removeTrailingSlash)
|
||||
.describe(FOLDERS.UPDATE.path),
|
||||
description: z.string().optional().nullable().describe(FOLDERS.UPDATE.description)
|
||||
})
|
||||
.array()
|
||||
.min(1)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
folders: SecretFoldersSchema.array()
|
||||
})
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY, AuthMode.SERVICE_TOKEN, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
handler: async (req) => {
|
||||
const { newFolders, oldFolders, projectId } = await server.services.folder.updateManyFolders({
|
||||
...req.body,
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId
|
||||
});
|
||||
|
||||
await Promise.all(
|
||||
req.body.folders.map(async (folder, index) => {
|
||||
await server.services.auditLog.createAuditLog({
|
||||
...req.auditLogInfo,
|
||||
projectId,
|
||||
event: {
|
||||
type: EventType.UPDATE_FOLDER,
|
||||
metadata: {
|
||||
environment: oldFolders[index].envId,
|
||||
folderId: oldFolders[index].id,
|
||||
folderPath: folder.path,
|
||||
newFolderName: newFolders[index].name,
|
||||
oldFolderName: oldFolders[index].name
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
);
|
||||
|
||||
return { folders: newFolders };
|
||||
}
|
||||
});
|
||||
|
||||
// TODO(daniel): Expose this route in api reference and write docs for it.
|
||||
server.route({
|
||||
method: "DELETE",
|
||||
url: "/:folderIdOrName",
|
||||
config: {
|
||||
rateLimit: secretsLimit
|
||||
},
|
||||
schema: {
|
||||
hide: false,
|
||||
tags: [ApiDocsTags.Folders],
|
||||
description: "Delete a folder",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: []
|
||||
}
|
||||
],
|
||||
params: z.object({
|
||||
folderIdOrName: z.string().describe(FOLDERS.DELETE.folderIdOrName)
|
||||
}),
|
||||
body: z.object({
|
||||
projectId: z.string().trim().describe(FOLDERS.DELETE.projectId),
|
||||
environment: z.string().trim().describe(FOLDERS.DELETE.environment),
|
||||
path: z
|
||||
.string()
|
||||
.trim()
|
||||
.default("/")
|
||||
.transform(prefixWithSlash) // Transformations get skipped if path is undefined
|
||||
.transform(removeTrailingSlash)
|
||||
.describe(FOLDERS.DELETE.path)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
folder: SecretFoldersSchema
|
||||
})
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY, AuthMode.SERVICE_TOKEN, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
handler: async (req) => {
|
||||
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,
|
||||
idOrName: req.params.folderIdOrName
|
||||
});
|
||||
await server.services.auditLog.createAuditLog({
|
||||
...req.auditLogInfo,
|
||||
projectId: req.body.projectId,
|
||||
event: {
|
||||
type: EventType.DELETE_FOLDER,
|
||||
metadata: {
|
||||
environment: req.body.environment,
|
||||
folderId: folder.id,
|
||||
folderPath: req.body.path,
|
||||
folderName: folder.name
|
||||
}
|
||||
}
|
||||
});
|
||||
return { folder };
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
method: "GET",
|
||||
url: "/",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
schema: {
|
||||
hide: false,
|
||||
tags: [ApiDocsTags.Folders],
|
||||
description: "Get folders",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: []
|
||||
}
|
||||
],
|
||||
querystring: z.object({
|
||||
projectId: z.string().trim().describe(FOLDERS.LIST.projectId),
|
||||
environment: z.string().trim().describe(FOLDERS.LIST.environment),
|
||||
lastSecretModified: z.string().datetime().trim().optional().describe(FOLDERS.LIST.lastSecretModified),
|
||||
path: z
|
||||
.string()
|
||||
.trim()
|
||||
.transform(prefixWithSlash) // Transformations get skipped if path is undefined
|
||||
.transform(removeTrailingSlash)
|
||||
.describe(FOLDERS.LIST.path),
|
||||
recursive: booleanSchema.default(false).describe(FOLDERS.LIST.recursive)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
folders: SecretFoldersSchema.extend({
|
||||
relativePath: z.string().optional()
|
||||
}).array()
|
||||
})
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY, AuthMode.SERVICE_TOKEN, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
handler: async (req) => {
|
||||
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
|
||||
});
|
||||
return { folders };
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
method: "GET",
|
||||
url: "/:id",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
schema: {
|
||||
hide: false,
|
||||
tags: [ApiDocsTags.Folders],
|
||||
description: "Get folder by id",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: []
|
||||
}
|
||||
],
|
||||
params: z.object({
|
||||
id: z.string().trim().describe(FOLDERS.GET_BY_ID.folderId)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
folder: SecretFoldersSchema.extend({
|
||||
environment: z.object({
|
||||
envId: z.string(),
|
||||
envName: z.string(),
|
||||
envSlug: z.string()
|
||||
}),
|
||||
path: z.string(),
|
||||
projectId: z.string()
|
||||
})
|
||||
})
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY, AuthMode.SERVICE_TOKEN, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
handler: async (req) => {
|
||||
const folder = await server.services.folder.getFolderById({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
id: req.params.id
|
||||
});
|
||||
return { folder };
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,427 @@
|
||||
import { z } from "zod";
|
||||
|
||||
import { SecretImportsSchema } from "@app/db/schemas";
|
||||
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
|
||||
import { ApiDocsTags, 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";
|
||||
|
||||
import { secretRawSchema } from "../sanitizedSchemas";
|
||||
|
||||
export const registerSecretImportRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
method: "POST",
|
||||
url: "/",
|
||||
config: {
|
||||
rateLimit: secretsLimit
|
||||
},
|
||||
schema: {
|
||||
hide: false,
|
||||
tags: [ApiDocsTags.SecretImports],
|
||||
description: "Create secret imports",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: []
|
||||
}
|
||||
],
|
||||
body: z.object({
|
||||
projectId: z.string().trim().describe(SECRET_IMPORTS.CREATE.projectId),
|
||||
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().describe(SECRET_IMPORTS.CREATE.import.environment),
|
||||
path: z.string().trim().transform(removeTrailingSlash).describe(SECRET_IMPORTS.CREATE.import.path)
|
||||
}),
|
||||
isReplication: z.boolean().default(false).describe(SECRET_IMPORTS.CREATE.isReplication)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
message: z.string(),
|
||||
secretImport: SecretImportsSchema.omit({ importEnv: true }).merge(
|
||||
z.object({
|
||||
importEnv: z.object({ name: z.string(), slug: z.string(), id: z.string() })
|
||||
})
|
||||
)
|
||||
})
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY, AuthMode.SERVICE_TOKEN, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
handler: async (req) => {
|
||||
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.projectId,
|
||||
data: req.body.import
|
||||
});
|
||||
|
||||
await server.services.auditLog.createAuditLog({
|
||||
...req.auditLogInfo,
|
||||
projectId: req.body.projectId,
|
||||
event: {
|
||||
type: EventType.CREATE_SECRET_IMPORT,
|
||||
metadata: {
|
||||
secretImportId: secretImport.id,
|
||||
folderId: secretImport.folderId,
|
||||
importFromSecretPath: secretImport.importPath,
|
||||
importFromEnvironment: secretImport.importEnv.slug,
|
||||
importToEnvironment: req.body.environment,
|
||||
importToSecretPath: req.body.path
|
||||
}
|
||||
}
|
||||
});
|
||||
return { message: "Successfully created secret import", secretImport };
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
method: "PATCH",
|
||||
url: "/:secretImportId",
|
||||
config: {
|
||||
rateLimit: secretsLimit
|
||||
},
|
||||
schema: {
|
||||
hide: false,
|
||||
tags: [ApiDocsTags.SecretImports],
|
||||
description: "Update secret imports",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: []
|
||||
}
|
||||
],
|
||||
params: z.object({
|
||||
secretImportId: z.string().trim().describe(SECRET_IMPORTS.UPDATE.secretImportId)
|
||||
}),
|
||||
body: z.object({
|
||||
projectId: z.string().trim().describe(SECRET_IMPORTS.UPDATE.projectId),
|
||||
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().describe(SECRET_IMPORTS.UPDATE.import.environment),
|
||||
path: z
|
||||
.string()
|
||||
.trim()
|
||||
.optional()
|
||||
.transform((val) => (val ? removeTrailingSlash(val) : val))
|
||||
.describe(SECRET_IMPORTS.UPDATE.import.path),
|
||||
position: z.number().optional().describe(SECRET_IMPORTS.UPDATE.import.position)
|
||||
})
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
message: z.string(),
|
||||
secretImport: SecretImportsSchema.omit({ importEnv: true }).merge(
|
||||
z.object({
|
||||
importEnv: z.object({ name: z.string(), slug: z.string(), id: z.string() })
|
||||
})
|
||||
)
|
||||
})
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY, AuthMode.SERVICE_TOKEN, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
handler: async (req) => {
|
||||
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,
|
||||
projectId: req.body.projectId,
|
||||
data: req.body.import
|
||||
});
|
||||
|
||||
await server.services.auditLog.createAuditLog({
|
||||
...req.auditLogInfo,
|
||||
projectId: req.body.projectId,
|
||||
event: {
|
||||
type: EventType.UPDATE_SECRET_IMPORT,
|
||||
metadata: {
|
||||
secretImportId: secretImport.id,
|
||||
folderId: secretImport.folderId,
|
||||
position: secretImport.position,
|
||||
importToEnvironment: req.body.environment,
|
||||
importToSecretPath: req.body.path
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return { message: "Successfully updated secret import", secretImport };
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
method: "DELETE",
|
||||
url: "/:secretImportId",
|
||||
config: {
|
||||
rateLimit: secretsLimit
|
||||
},
|
||||
schema: {
|
||||
hide: false,
|
||||
tags: [ApiDocsTags.SecretImports],
|
||||
description: "Delete secret imports",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: []
|
||||
}
|
||||
],
|
||||
params: z.object({
|
||||
secretImportId: z.string().trim().describe(SECRET_IMPORTS.DELETE.secretImportId)
|
||||
}),
|
||||
body: z.object({
|
||||
projectId: z.string().trim().describe(SECRET_IMPORTS.DELETE.projectId),
|
||||
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({
|
||||
message: z.string(),
|
||||
secretImport: SecretImportsSchema.omit({ importEnv: true }).merge(
|
||||
z.object({
|
||||
importEnv: z.object({ name: z.string(), slug: z.string(), id: z.string() })
|
||||
})
|
||||
)
|
||||
})
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY, AuthMode.SERVICE_TOKEN, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
handler: async (req) => {
|
||||
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,
|
||||
projectId: req.body.projectId
|
||||
});
|
||||
|
||||
await server.services.auditLog.createAuditLog({
|
||||
...req.auditLogInfo,
|
||||
projectId: req.body.projectId,
|
||||
event: {
|
||||
type: EventType.DELETE_SECRET_IMPORT,
|
||||
metadata: {
|
||||
secretImportId: secretImport.id,
|
||||
folderId: secretImport.folderId,
|
||||
importFromEnvironment: secretImport.importEnv.slug,
|
||||
importFromSecretPath: secretImport.importPath,
|
||||
importToEnvironment: req.body.environment,
|
||||
importToSecretPath: req.body.path
|
||||
}
|
||||
}
|
||||
});
|
||||
return { message: "Successfully deleted secret import", secretImport };
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
method: "POST",
|
||||
url: "/:secretImportId/replication-resync",
|
||||
config: {
|
||||
rateLimit: secretsLimit
|
||||
},
|
||||
schema: {
|
||||
description: "Resync secret replication of secret imports",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: []
|
||||
}
|
||||
],
|
||||
params: z.object({
|
||||
secretImportId: z.string().trim().describe(SECRET_IMPORTS.UPDATE.secretImportId)
|
||||
}),
|
||||
body: z.object({
|
||||
projectId: z.string().trim().describe(SECRET_IMPORTS.UPDATE.projectId),
|
||||
environment: z.string().trim().describe(SECRET_IMPORTS.UPDATE.environment),
|
||||
path: z.string().trim().default("/").transform(removeTrailingSlash).describe(SECRET_IMPORTS.UPDATE.path)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
message: z.string()
|
||||
})
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT]),
|
||||
handler: async (req) => {
|
||||
const { message } = await server.services.secretImport.resyncSecretImportReplication({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
id: req.params.secretImportId,
|
||||
...req.body,
|
||||
projectId: req.body.projectId
|
||||
});
|
||||
|
||||
return { message };
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
method: "GET",
|
||||
url: "/",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
schema: {
|
||||
hide: false,
|
||||
tags: [ApiDocsTags.SecretImports],
|
||||
description: "Get secret imports",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: []
|
||||
}
|
||||
],
|
||||
querystring: z.object({
|
||||
projectId: z.string().trim().describe(SECRET_IMPORTS.LIST.projectId),
|
||||
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({
|
||||
message: z.string(),
|
||||
secretImports: SecretImportsSchema.omit({ importEnv: true })
|
||||
.extend({
|
||||
importEnv: z.object({ name: z.string(), slug: z.string(), id: z.string() })
|
||||
})
|
||||
.array()
|
||||
})
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY, AuthMode.SERVICE_TOKEN, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
handler: async (req) => {
|
||||
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.projectId
|
||||
});
|
||||
|
||||
await server.services.auditLog.createAuditLog({
|
||||
...req.auditLogInfo,
|
||||
projectId: req.query.projectId,
|
||||
event: {
|
||||
type: EventType.GET_SECRET_IMPORTS,
|
||||
metadata: {
|
||||
environment: req.query.environment,
|
||||
folderId: secretImports?.[0]?.folderId,
|
||||
numberOfImports: secretImports.length
|
||||
}
|
||||
}
|
||||
});
|
||||
return { message: "Successfully fetched secret imports", secretImports };
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/:secretImportId",
|
||||
method: "GET",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
schema: {
|
||||
hide: false,
|
||||
tags: [ApiDocsTags.SecretImports],
|
||||
description: "Get single secret import",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: []
|
||||
}
|
||||
],
|
||||
params: z.object({
|
||||
secretImportId: z.string().trim().describe(SECRET_IMPORTS.GET.secretImportId)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
secretImport: SecretImportsSchema.omit({ importEnv: true }).extend({
|
||||
environment: z.object({
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
slug: z.string()
|
||||
}),
|
||||
projectId: z.string(),
|
||||
importEnv: z.object({ name: z.string(), slug: z.string(), id: z.string() }),
|
||||
secretPath: z.string()
|
||||
})
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY, AuthMode.SERVICE_TOKEN, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
handler: async (req) => {
|
||||
const secretImport = await server.services.secretImport.getImportById({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
id: req.params.secretImportId
|
||||
});
|
||||
|
||||
await server.services.auditLog.createAuditLog({
|
||||
...req.auditLogInfo,
|
||||
projectId: secretImport.projectId,
|
||||
event: {
|
||||
type: EventType.GET_SECRET_IMPORT,
|
||||
metadata: {
|
||||
secretImportId: secretImport.id,
|
||||
folderId: secretImport.folderId
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return { secretImport };
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/secrets",
|
||||
method: "GET",
|
||||
config: {
|
||||
rateLimit: secretsLimit
|
||||
},
|
||||
schema: {
|
||||
hide: false,
|
||||
tags: [ApiDocsTags.SecretImports],
|
||||
querystring: z.object({
|
||||
projectId: z.string().trim(),
|
||||
environment: z.string().trim(),
|
||||
path: z.string().trim().default("/").transform(removeTrailingSlash)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
secrets: z
|
||||
.object({
|
||||
secretPath: z.string(),
|
||||
environment: z.string(),
|
||||
environmentInfo: z.object({
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
slug: z.string()
|
||||
}),
|
||||
folderId: z.string().optional(),
|
||||
secrets: secretRawSchema.array()
|
||||
})
|
||||
.array()
|
||||
})
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY, AuthMode.SERVICE_TOKEN, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
handler: async (req) => {
|
||||
const importedSecrets = await server.services.secretImport.getRawSecretsFromImports({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
...req.query
|
||||
});
|
||||
return { secrets: importedSecrets };
|
||||
}
|
||||
});
|
||||
};
|
||||
Reference in New Issue
Block a user