UNPKG

alepha

Version:

Easy-to-use modern TypeScript framework for building many kind of applications.

453 lines 21.8 kB
import { Alepha, Static } from "alepha"; import { IssuerResolver, UserInfo } from "alepha/security"; import { DateTimeProvider } from "alepha/datetime"; //#region ../../src/api/keys/entities/apiKeyEntity.d.ts declare const apiKeyEntity: import("alepha/orm").EntityPrimitive<import("zod").ZodObject<{ id: import("alepha/orm").PgAttr<import("alepha/orm").PgAttr<import("zod").ZodString, typeof import("alepha/orm").PG_PRIMARY_KEY>, typeof import("alepha/orm").PG_DEFAULT>; createdAt: import("alepha/orm").PgAttr<import("alepha/orm").PgAttr<import("zod").ZodString, typeof import("alepha/orm").PG_CREATED_AT>, typeof import("alepha/orm").PG_DEFAULT>; updatedAt: import("alepha/orm").PgAttr<import("alepha/orm").PgAttr<import("zod").ZodString, typeof import("alepha/orm").PG_UPDATED_AT>, typeof import("alepha/orm").PG_DEFAULT>; organizationId: import("alepha/orm").PgAttr<import("zod").ZodOptional<import("zod").ZodString> | import("zod").ZodString, typeof import("alepha/orm").PG_ORGANIZATION>; userId: import("zod").ZodString; name: import("zod").ZodString; description: import("zod").ZodOptional<import("zod").ZodString>; tokenHash: import("zod").ZodString; tokenPrefix: import("zod").ZodString; tokenSuffix: import("zod").ZodString; roles: import("alepha/orm").PgAttr<import("zod").ZodArray<import("zod").ZodString>, typeof import("alepha/orm").PG_DEFAULT>; lastUsedAt: import("zod").ZodOptional<import("zod").ZodString>; lastUsedIp: import("zod").ZodOptional<import("zod").ZodString>; usageCount: import("alepha/orm").PgAttr<import("zod").ZodInt, typeof import("alepha/orm").PG_DEFAULT>; expiresAt: import("zod").ZodOptional<import("zod").ZodString>; revokedAt: import("zod").ZodOptional<import("zod").ZodString>; }, import("zod/v4/core").$strip>>; type ApiKeyEntity = Static<typeof apiKeyEntity.schema>; //#endregion //#region ../../src/api/keys/services/ApiKeyService.d.ts declare class ApiKeyService { protected readonly alepha: Alepha; protected readonly dateTimeProvider: DateTimeProvider; protected readonly log: import("alepha/logger").Logger; protected readonly repo: import("alepha/orm").Repository<import("zod").ZodObject<{ id: import("alepha/orm").PgAttr<import("alepha/orm").PgAttr<import("zod").ZodString, typeof import("alepha/orm").PG_PRIMARY_KEY>, typeof import("alepha/orm").PG_DEFAULT>; createdAt: import("alepha/orm").PgAttr<import("alepha/orm").PgAttr<import("zod").ZodString, typeof import("alepha/orm").PG_CREATED_AT>, typeof import("alepha/orm").PG_DEFAULT>; updatedAt: import("alepha/orm").PgAttr<import("alepha/orm").PgAttr<import("zod").ZodString, typeof import("alepha/orm").PG_UPDATED_AT>, typeof import("alepha/orm").PG_DEFAULT>; organizationId: import("alepha/orm").PgAttr<import("zod").ZodOptional<import("zod").ZodString> | import("zod").ZodString, typeof import("alepha/orm").PG_ORGANIZATION>; userId: import("zod").ZodString; name: import("zod").ZodString; description: import("zod").ZodOptional<import("zod").ZodString>; tokenHash: import("zod").ZodString; tokenPrefix: import("zod").ZodString; tokenSuffix: import("zod").ZodString; roles: import("alepha/orm").PgAttr<import("zod").ZodArray<import("zod").ZodString>, typeof import("alepha/orm").PG_DEFAULT>; lastUsedAt: import("zod").ZodOptional<import("zod").ZodString>; lastUsedIp: import("zod").ZodOptional<import("zod").ZodString>; usageCount: import("alepha/orm").PgAttr<import("zod").ZodInt, typeof import("alepha/orm").PG_DEFAULT>; expiresAt: import("zod").ZodOptional<import("zod").ZodString>; revokedAt: import("zod").ZodOptional<import("zod").ZodString>; }, import("zod/v4/core").$strip>>; /** * Cache validated API keys for 15 minutes. * * Pinned to per-isolate memory: * - The cache replaces a single indexed SELECT on `api_keys`. Routing it * through a distributed K/V (KV/Redis) buys little — the SELECT is * already cheap — and pinning to DB would actively trade one SQL read * for another. * - Cold-start gives a fresh DB read on every new isolate, which is * *better* for revocation visibility than a distributed cache that * keeps serving stale entries until its own TTL. * - Avoids provisioning KV/Redis just for this one cache. Users who need * cross-isolate sharing for high-throughput API auth can override * globally via `alepha.with({ provide: CacheProvider, use: ... })`. */ protected readonly validationCache: import("alepha/cache").CacheMiddlewareFn<{ id: string; createdAt: string; updatedAt: string; organizationId: string | undefined; userId: string; name: string; description?: string | undefined; tokenHash: string; tokenPrefix: string; tokenSuffix: string; roles: string[]; lastUsedAt?: string | undefined; lastUsedIp?: string | undefined; usageCount: number; expiresAt?: string | undefined; revokedAt?: string | undefined; } | null>; /** * Create an issuer resolver for API key authentication. * Lower priority means it runs before JWT resolver. * * @param options.priority - Priority of this resolver (default: 50, JWT is 100) * @param options.prefix - API key prefix to match in Bearer header (default: "ak") */ createResolver(options?: { priority?: number; prefix?: string; }): IssuerResolver; /** * Create a new API key for a user. * Returns both the API key entity and the plain token (which is only available once). */ create(options: { userId: string; name: string; roles: string[]; description?: string; expiresAt?: Date; prefix?: string; }): Promise<{ apiKey: ApiKeyEntity; token: string; }>; /** * List all non-revoked API keys for a user. */ list(userId: string): Promise<ApiKeyEntity[]>; /** * Find all API keys with optional filtering (admin only). */ findAll(query: { userId?: string; includeRevoked?: boolean; page?: number; size?: number; sort?: string; }): Promise<import("alepha").Page<import("alepha/orm").PgStatic<import("zod").ZodObject<{ id: import("alepha/orm").PgAttr<import("alepha/orm").PgAttr<import("zod").ZodString, typeof import("alepha/orm").PG_PRIMARY_KEY>, typeof import("alepha/orm").PG_DEFAULT>; createdAt: import("alepha/orm").PgAttr<import("alepha/orm").PgAttr<import("zod").ZodString, typeof import("alepha/orm").PG_CREATED_AT>, typeof import("alepha/orm").PG_DEFAULT>; updatedAt: import("alepha/orm").PgAttr<import("alepha/orm").PgAttr<import("zod").ZodString, typeof import("alepha/orm").PG_UPDATED_AT>, typeof import("alepha/orm").PG_DEFAULT>; organizationId: import("alepha/orm").PgAttr<import("zod").ZodOptional<import("zod").ZodString> | import("zod").ZodString, typeof import("alepha/orm").PG_ORGANIZATION>; userId: import("zod").ZodString; name: import("zod").ZodString; description: import("zod").ZodOptional<import("zod").ZodString>; tokenHash: import("zod").ZodString; tokenPrefix: import("zod").ZodString; tokenSuffix: import("zod").ZodString; roles: import("alepha/orm").PgAttr<import("zod").ZodArray<import("zod").ZodString>, typeof import("alepha/orm").PG_DEFAULT>; lastUsedAt: import("zod").ZodOptional<import("zod").ZodString>; lastUsedIp: import("zod").ZodOptional<import("zod").ZodString>; usageCount: import("alepha/orm").PgAttr<import("zod").ZodInt, typeof import("alepha/orm").PG_DEFAULT>; expiresAt: import("zod").ZodOptional<import("zod").ZodString>; revokedAt: import("zod").ZodOptional<import("zod").ZodString>; }, import("zod/v4/core").$strip>, import("alepha/orm").PgRelationMap<import("zod").ZodObject<{ id: import("alepha/orm").PgAttr<import("alepha/orm").PgAttr<import("zod").ZodString, typeof import("alepha/orm").PG_PRIMARY_KEY>, typeof import("alepha/orm").PG_DEFAULT>; createdAt: import("alepha/orm").PgAttr<import("alepha/orm").PgAttr<import("zod").ZodString, typeof import("alepha/orm").PG_CREATED_AT>, typeof import("alepha/orm").PG_DEFAULT>; updatedAt: import("alepha/orm").PgAttr<import("alepha/orm").PgAttr<import("zod").ZodString, typeof import("alepha/orm").PG_UPDATED_AT>, typeof import("alepha/orm").PG_DEFAULT>; organizationId: import("alepha/orm").PgAttr<import("zod").ZodOptional<import("zod").ZodString> | import("zod").ZodString, typeof import("alepha/orm").PG_ORGANIZATION>; userId: import("zod").ZodString; name: import("zod").ZodString; description: import("zod").ZodOptional<import("zod").ZodString>; tokenHash: import("zod").ZodString; tokenPrefix: import("zod").ZodString; tokenSuffix: import("zod").ZodString; roles: import("alepha/orm").PgAttr<import("zod").ZodArray<import("zod").ZodString>, typeof import("alepha/orm").PG_DEFAULT>; lastUsedAt: import("zod").ZodOptional<import("zod").ZodString>; lastUsedIp: import("zod").ZodOptional<import("zod").ZodString>; usageCount: import("alepha/orm").PgAttr<import("zod").ZodInt, typeof import("alepha/orm").PG_DEFAULT>; expiresAt: import("zod").ZodOptional<import("zod").ZodString>; revokedAt: import("zod").ZodOptional<import("zod").ZodString>; }, import("zod/v4/core").$strip>>>>>; /** * Get an API key by ID (admin only). */ getById(id: string): Promise<ApiKeyEntity>; /** * Revoke any API key (admin only). */ revokeByAdmin(id: string): Promise<void>; /** * Revoke many API keys in one repository call (admin only). Already-revoked * keys are silently skipped. Returns the ids that were actually revoked. */ revokeManyByAdmin(ids: string[]): Promise<string[]>; /** * Revoke an API key. Only the owner can revoke their own keys. */ revoke(id: string, userId: string): Promise<void>; /** * Validate an API key token and return user info if valid. */ validate(token: string): Promise<UserInfo | null>; /** * Update usage statistics for an API key. */ protected updateUsage(id: string): Promise<void>; /** * Hash a token using SHA-256. */ protected hashToken(token: string): string; } //#endregion //#region ../../src/api/keys/controllers/AdminApiKeyController.d.ts /** * REST API controller for admin API key management. * Admins can list, view, and revoke any API key. */ declare class AdminApiKeyController { protected readonly url = "/admin/api-keys"; protected readonly group = "admin:api-keys"; protected readonly apiKeyService: ApiKeyService; /** * Find all API keys with optional filtering. */ readonly findApiKeys: import("alepha/server").ActionPrimitiveFn<{ query: import("zod").ZodObject<{ page: import("zod").ZodOptional<import("zod").ZodDefault<import("zod").ZodInt>>; size: import("zod").ZodOptional<import("zod").ZodDefault<import("zod").ZodInt>>; sort: import("zod").ZodOptional<import("zod").ZodString>; userId: import("zod").ZodOptional<import("zod").ZodString>; includeRevoked: import("zod").ZodOptional<import("zod").ZodBoolean>; }, import("zod/v4/core").$strip>; response: import("zod").ZodObject<{ content: import("zod").ZodArray<import("zod").ZodObject<{ id: import("zod").ZodString; userId: import("zod").ZodString; name: import("zod").ZodString; description: import("zod").ZodOptional<import("zod").ZodString>; tokenPrefix: import("zod").ZodString; tokenSuffix: import("zod").ZodString; roles: import("zod").ZodArray<import("zod").ZodString>; createdAt: import("zod").ZodString; lastUsedAt: import("zod").ZodOptional<import("zod").ZodString>; lastUsedIp: import("zod").ZodOptional<import("zod").ZodString>; expiresAt: import("zod").ZodOptional<import("zod").ZodString>; revokedAt: import("zod").ZodOptional<import("zod").ZodString>; usageCount: import("zod").ZodInt; }, import("zod/v4/core").$strip>>; page: import("zod").ZodObject<{ number: import("zod").ZodInt; size: import("zod").ZodInt; offset: import("zod").ZodInt; numberOfElements: import("zod").ZodInt; totalElements: import("zod").ZodOptional<import("zod").ZodInt>; totalPages: import("zod").ZodOptional<import("zod").ZodInt>; isEmpty: import("zod").ZodBoolean; isFirst: import("zod").ZodBoolean; isLast: import("zod").ZodBoolean; }, import("zod/v4/core").$strip>; }, import("zod/v4/core").$strip>; }>; /** * Get an API key by ID. */ readonly getApiKey: import("alepha/server").ActionPrimitiveFn<{ params: import("zod").ZodObject<{ id: import("zod").ZodString; }, import("zod/v4/core").$strip>; response: import("zod").ZodObject<{ id: import("zod").ZodString; userId: import("zod").ZodString; name: import("zod").ZodString; description: import("zod").ZodOptional<import("zod").ZodString>; tokenPrefix: import("zod").ZodString; tokenSuffix: import("zod").ZodString; roles: import("zod").ZodArray<import("zod").ZodString>; createdAt: import("zod").ZodString; lastUsedAt: import("zod").ZodOptional<import("zod").ZodString>; lastUsedIp: import("zod").ZodOptional<import("zod").ZodString>; expiresAt: import("zod").ZodOptional<import("zod").ZodString>; revokedAt: import("zod").ZodOptional<import("zod").ZodString>; usageCount: import("zod").ZodInt; }, import("zod/v4/core").$strip>; }>; /** * Revoke any API key. */ readonly revokeApiKey: import("alepha/server").ActionPrimitiveFn<{ params: import("zod").ZodObject<{ id: import("zod").ZodString; }, import("zod/v4/core").$strip>; response: import("zod").ZodObject<{ ok: import("zod").ZodBoolean; id: import("zod").ZodOptional<import("zod").ZodUnion<readonly [import("zod").ZodString, import("zod").ZodInt]>>; count: import("zod").ZodOptional<import("zod").ZodNumber>; }, import("zod/v4/core").$strip>; }>; /** * Revoke many API keys in one request. */ readonly revokeApiKeys: import("alepha/server").ActionPrimitiveFn<{ body: import("zod").ZodObject<{ ids: import("zod").ZodArray<import("zod").ZodString>; }, import("zod/v4/core").$strip>; response: import("zod").ZodObject<{ revoked: import("zod").ZodArray<import("zod").ZodString>; }, import("zod/v4/core").$strip>; }>; } //#endregion //#region ../../src/api/keys/controllers/ApiKeyController.d.ts /** * REST API controller for user's own API key management. * Users can create, list, and revoke their own API keys. */ declare class ApiKeyController { protected readonly url = "/api-keys"; protected readonly group = "api-keys"; protected readonly apiKeyService: ApiKeyService; /** * Create a new API key for the authenticated user. * The token is only returned once upon creation. */ readonly createApiKey: import("alepha/server").ActionPrimitiveFn<{ body: import("zod").ZodObject<{ name: import("zod").ZodString; description: import("zod").ZodOptional<import("zod").ZodString>; expiresAt: import("zod").ZodOptional<import("zod").ZodString>; }, import("zod/v4/core").$strip>; response: import("zod").ZodObject<{ id: import("zod").ZodString; name: import("zod").ZodString; token: import("zod").ZodString; tokenSuffix: import("zod").ZodString; roles: import("zod").ZodArray<import("zod").ZodString>; createdAt: import("zod").ZodString; expiresAt: import("zod").ZodOptional<import("zod").ZodString>; }, import("zod/v4/core").$strip>; }>; /** * List all active API keys for the authenticated user. * Does not return the actual tokens. */ readonly listApiKeys: import("alepha/server").ActionPrimitiveFn<{ response: import("zod").ZodArray<import("zod").ZodObject<{ id: import("zod").ZodString; name: import("zod").ZodString; tokenPrefix: import("zod").ZodString; tokenSuffix: import("zod").ZodString; roles: import("zod").ZodArray<import("zod").ZodString>; createdAt: import("zod").ZodString; lastUsedAt: import("zod").ZodOptional<import("zod").ZodString>; lastUsedIp: import("zod").ZodOptional<import("zod").ZodString>; expiresAt: import("zod").ZodOptional<import("zod").ZodString>; usageCount: import("zod").ZodInt; }, import("zod/v4/core").$strip>>; }>; /** * Revoke an API key. Only the owner can revoke their own keys. */ readonly revokeMyApiKey: import("alepha/server").ActionPrimitiveFn<{ params: import("zod").ZodObject<{ id: import("zod").ZodString; }, import("zod/v4/core").$strip>; response: import("zod").ZodObject<{ ok: import("zod").ZodBoolean; }, import("zod/v4/core").$strip>; }>; } //#endregion //#region ../../src/api/keys/schemas/adminApiKeyQuerySchema.d.ts declare const adminApiKeyQuerySchema: import("zod").ZodObject<{ page: import("zod").ZodOptional<import("zod").ZodDefault<import("zod").ZodInt>>; size: import("zod").ZodOptional<import("zod").ZodDefault<import("zod").ZodInt>>; sort: import("zod").ZodOptional<import("zod").ZodString>; userId: import("zod").ZodOptional<import("zod").ZodString>; includeRevoked: import("zod").ZodOptional<import("zod").ZodBoolean>; }, import("zod/v4/core").$strip>; //#endregion //#region ../../src/api/keys/schemas/adminApiKeyResourceSchema.d.ts declare const adminApiKeyResourceSchema: import("zod").ZodObject<{ id: import("zod").ZodString; userId: import("zod").ZodString; name: import("zod").ZodString; description: import("zod").ZodOptional<import("zod").ZodString>; tokenPrefix: import("zod").ZodString; tokenSuffix: import("zod").ZodString; roles: import("zod").ZodArray<import("zod").ZodString>; createdAt: import("zod").ZodString; lastUsedAt: import("zod").ZodOptional<import("zod").ZodString>; lastUsedIp: import("zod").ZodOptional<import("zod").ZodString>; expiresAt: import("zod").ZodOptional<import("zod").ZodString>; revokedAt: import("zod").ZodOptional<import("zod").ZodString>; usageCount: import("zod").ZodInt; }, import("zod/v4/core").$strip>; type AdminApiKeyResource = Static<typeof adminApiKeyResourceSchema>; //#endregion //#region ../../src/api/keys/schemas/createApiKeyBodySchema.d.ts declare const createApiKeyBodySchema: import("zod").ZodObject<{ name: import("zod").ZodString; description: import("zod").ZodOptional<import("zod").ZodString>; expiresAt: import("zod").ZodOptional<import("zod").ZodString>; }, import("zod/v4/core").$strip>; //#endregion //#region ../../src/api/keys/schemas/createApiKeyResponseSchema.d.ts declare const createApiKeyResponseSchema: import("zod").ZodObject<{ id: import("zod").ZodString; name: import("zod").ZodString; token: import("zod").ZodString; tokenSuffix: import("zod").ZodString; roles: import("zod").ZodArray<import("zod").ZodString>; createdAt: import("zod").ZodString; expiresAt: import("zod").ZodOptional<import("zod").ZodString>; }, import("zod/v4/core").$strip>; //#endregion //#region ../../src/api/keys/schemas/listApiKeyResponseSchema.d.ts declare const listApiKeyItemSchema: import("zod").ZodObject<{ id: import("zod").ZodString; name: import("zod").ZodString; tokenPrefix: import("zod").ZodString; tokenSuffix: import("zod").ZodString; roles: import("zod").ZodArray<import("zod").ZodString>; createdAt: import("zod").ZodString; lastUsedAt: import("zod").ZodOptional<import("zod").ZodString>; lastUsedIp: import("zod").ZodOptional<import("zod").ZodString>; expiresAt: import("zod").ZodOptional<import("zod").ZodString>; usageCount: import("zod").ZodInt; }, import("zod/v4/core").$strip>; declare const listApiKeyResponseSchema: import("zod").ZodArray<import("zod").ZodObject<{ id: import("zod").ZodString; name: import("zod").ZodString; tokenPrefix: import("zod").ZodString; tokenSuffix: import("zod").ZodString; roles: import("zod").ZodArray<import("zod").ZodString>; createdAt: import("zod").ZodString; lastUsedAt: import("zod").ZodOptional<import("zod").ZodString>; lastUsedIp: import("zod").ZodOptional<import("zod").ZodString>; expiresAt: import("zod").ZodOptional<import("zod").ZodString>; usageCount: import("zod").ZodInt; }, import("zod/v4/core").$strip>>; //#endregion //#region ../../src/api/keys/schemas/revokeApiKeyParamsSchema.d.ts declare const revokeApiKeyParamsSchema: import("zod").ZodObject<{ id: import("zod").ZodString; }, import("zod/v4/core").$strip>; //#endregion //#region ../../src/api/keys/schemas/revokeApiKeyResponseSchema.d.ts declare const revokeApiKeyResponseSchema: import("zod").ZodObject<{ ok: import("zod").ZodBoolean; }, import("zod/v4/core").$strip>; //#endregion //#region ../../src/api/keys/index.d.ts /** * API key management module for programmatic access. * * **Features:** * - Create API keys with role snapshots * - List and revoke API keys * - 15-minute validation caching * - Query param (?api_key=) and Bearer header support * * **Integration:** * To enable API key authentication for an issuer, register the resolver: * * ```ts * class MyApp { * apiKeyService = $inject(ApiKeyService); * issuer = $issuer({ * secret: env.APP_SECRET, * resolvers: [this.apiKeyService.createResolver()], * }); * } * ``` * * @module alepha.api.keys */ declare const AlephaApiKeys: import("alepha").Service<import("alepha").Module>; //#endregion export { AdminApiKeyController, AdminApiKeyResource, AlephaApiKeys, ApiKeyController, ApiKeyEntity, ApiKeyService, adminApiKeyQuerySchema, adminApiKeyResourceSchema, apiKeyEntity, createApiKeyBodySchema, createApiKeyResponseSchema, listApiKeyItemSchema, listApiKeyResponseSchema, revokeApiKeyParamsSchema, revokeApiKeyResponseSchema }; //# sourceMappingURL=index.d.ts.map