import { InternalSession } from "../sessions"; import { ApiKeysCrud } from "./crud/api-keys"; import { EmailTemplateCrud, EmailTemplateType } from "./crud/email-templates"; import { InternalEmailsCrud } from "./crud/emails"; import { ProjectPermissionDefinitionsCrud } from "./crud/project-permissions"; import { ProjectsCrud } from "./crud/projects"; import { SvixTokenCrud } from "./crud/svix-token"; import { TeamPermissionDefinitionsCrud } from "./crud/team-permissions"; import { ServerAuthApplicationOptions, StackServerInterface } from "./serverInterface"; export type AdminAuthApplicationOptions = ServerAuthApplicationOptions &( | { superSecretAdminKey: string, } | { projectOwnerSession: InternalSession, } ); export type ApiKeyCreateCrudRequest = { has_publishable_client_key: boolean, has_secret_server_key: boolean, has_super_secret_admin_key: boolean, expires_at_millis: number, description: string, }; export type ApiKeyCreateCrudResponse = ApiKeysCrud["Admin"]["Read"] & { publishable_client_key?: string, secret_server_key?: string, super_secret_admin_key?: string, }; export class StackAdminInterface extends StackServerInterface { constructor(public readonly options: AdminAuthApplicationOptions) { super(options); } public async sendAdminRequest(path: string, options: RequestInit, session: InternalSession | null, requestType: "admin" = "admin") { return await this.sendServerRequest( path, { ...options, headers: { "x-stack-super-secret-admin-key": "superSecretAdminKey" in this.options ? this.options.superSecretAdminKey : "", ...options.headers, }, }, session, requestType, ); } async getProject(): Promise { const response = await this.sendAdminRequest( "/projects/current", { method: "GET", }, null, ); return await response.json(); } async updateProject(update: ProjectsCrud["Admin"]["Update"]): Promise { const response = await this.sendAdminRequest( "/projects/current", { method: "PATCH", headers: { "content-type": "application/json", }, body: JSON.stringify(update), }, null, ); return await response.json(); } async createApiKey( options: ApiKeyCreateCrudRequest, ): Promise { const response = await this.sendAdminRequest( "/internal/api-keys", { method: "POST", headers: { "content-type": "application/json", }, body: JSON.stringify(options), }, null, ); return await response.json(); } async listApiKeys(): Promise { const response = await this.sendAdminRequest("/internal/api-keys", {}, null); const result = await response.json() as ApiKeysCrud["Admin"]["List"]; return result.items; } async revokeApiKeyById(id: string) { await this.sendAdminRequest( `/internal/api-keys/${id}`, { method: "PATCH", headers: { "content-type": "application/json", }, body: JSON.stringify({ revoked: true, }), }, null, ); } async getApiKey(id: string, session: InternalSession): Promise { const response = await this.sendAdminRequest(`/internal/api-keys/${id}`, {}, session); return await response.json(); } async listEmailTemplates(): Promise { const response = await this.sendAdminRequest(`/email-templates`, {}, null); const result = await response.json() as EmailTemplateCrud['Admin']['List']; return result.items; } async updateEmailTemplate(type: EmailTemplateType, data: EmailTemplateCrud['Admin']['Update']): Promise { const result = await this.sendAdminRequest( `/email-templates/${type}`, { method: "PATCH", headers: { "content-type": "application/json", }, body: JSON.stringify(data), }, null, ); return await result.json(); } async resetEmailTemplate(type: EmailTemplateType): Promise { await this.sendAdminRequest( `/email-templates/${type}`, { method: "DELETE" }, null ); } // Team permission definitions methods async listTeamPermissionDefinitions(): Promise { const response = await this.sendAdminRequest(`/team-permission-definitions`, {}, null); const result = await response.json() as TeamPermissionDefinitionsCrud['Admin']['List']; return result.items; } async createTeamPermissionDefinition(data: TeamPermissionDefinitionsCrud['Admin']['Create']): Promise { const response = await this.sendAdminRequest( "/team-permission-definitions", { method: "POST", headers: { "content-type": "application/json", }, body: JSON.stringify(data), }, null, ); return await response.json(); } async updateTeamPermissionDefinition(permissionId: string, data: TeamPermissionDefinitionsCrud['Admin']['Update']): Promise { const response = await this.sendAdminRequest( `/team-permission-definitions/${permissionId}`, { method: "PATCH", headers: { "content-type": "application/json", }, body: JSON.stringify(data), }, null, ); return await response.json(); } async deleteTeamPermissionDefinition(permissionId: string): Promise { await this.sendAdminRequest( `/team-permission-definitions/${permissionId}`, { method: "DELETE" }, null, ); } async listProjectPermissionDefinitions(): Promise { const response = await this.sendAdminRequest(`/project-permission-definitions`, {}, null); const result = await response.json() as ProjectPermissionDefinitionsCrud['Admin']['List']; return result.items; } async createProjectPermissionDefinition(data: ProjectPermissionDefinitionsCrud['Admin']['Create']): Promise { const response = await this.sendAdminRequest( "/project-permission-definitions", { method: "POST", headers: { "content-type": "application/json", }, body: JSON.stringify(data), }, null, ); return await response.json(); } async updateProjectPermissionDefinition(permissionId: string, data: ProjectPermissionDefinitionsCrud['Admin']['Update']): Promise { const response = await this.sendAdminRequest( `/project-permission-definitions/${permissionId}`, { method: "PATCH", headers: { "content-type": "application/json", }, body: JSON.stringify(data), }, null, ); return await response.json(); } async deleteProjectPermissionDefinition(permissionId: string): Promise { await this.sendAdminRequest( `/project-permission-definitions/${permissionId}`, { method: "DELETE" }, null, ); } async getSvixToken(): Promise { const response = await this.sendAdminRequest( "/webhooks/svix-token", { method: "POST", headers: { "content-type": "application/json", }, body: JSON.stringify({}), }, null, ); return await response.json(); } async deleteProject(): Promise { await this.sendAdminRequest( "/projects/current", { method: "DELETE", }, null, ); } async getMetrics(): Promise { const response = await this.sendAdminRequest( "/internal/metrics", { method: "GET", }, null, ); return await response.json(); } async sendTestEmail(data: { recipient_email: string, email_config: { host: string, port: number, username: string, password: string, sender_email: string, sender_name: string, }, }): Promise<{ success: boolean, error_message?: string }> { const response = await this.sendAdminRequest(`/internal/send-test-email`, { method: "POST", headers: { "content-type": "application/json", }, body: JSON.stringify(data), }, null); return await response.json(); } async listSentEmails(): Promise { const response = await this.sendAdminRequest("/internal/emails", { method: "GET", }, null); return await response.json(); } }