feat: api keys management (EE) (#1665)

* feat: api keys (EE)

* improvements

* fix table

* fix route

* remove token suffix

* api settings

* Fix

* fix

* fix

* fix
This commit is contained in:
Philip Okugbe
2025-10-07 21:05:13 +01:00
committed by GitHub
parent 16c1e864af
commit 3164b6981c
36 changed files with 1176 additions and 23 deletions
@@ -0,0 +1,30 @@
import { Kysely, sql } from 'kysely';
export async function up(db: Kysely<any>): Promise<void> {
await db.schema
.createTable('api_keys')
.addColumn('id', 'uuid', (col) =>
col.primaryKey().defaultTo(sql`gen_uuid_v7()`),
)
.addColumn('name', 'text', (col) => col)
.addColumn('creator_id', 'uuid', (col) =>
col.notNull().references('users.id').onDelete('cascade'),
)
.addColumn('workspace_id', 'uuid', (col) =>
col.notNull().references('workspaces.id').onDelete('cascade'),
)
.addColumn('expires_at', 'timestamptz')
.addColumn('last_used_at', 'timestamptz')
.addColumn('created_at', 'timestamptz', (col) =>
col.notNull().defaultTo(sql`now()`),
)
.addColumn('updated_at', 'timestamptz', (col) =>
col.notNull().defaultTo(sql`now()`),
)
.addColumn('deleted_at', 'timestamptz', (col) => col)
.execute();
}
export async function down(db: Kysely<any>): Promise<void> {
await db.schema.dropTable('api_keys').execute();
}
@@ -1,4 +1,5 @@
import {
IsBoolean,
IsNumber,
IsOptional,
IsPositive,
@@ -23,4 +24,8 @@ export class PaginationOptions {
@IsOptional()
@IsString()
query: string;
@IsOptional()
@IsBoolean()
adminView: boolean;
}
@@ -157,4 +157,22 @@ export class WorkspaceRepo {
return activeUsers.length;
}
async updateApiSettings(
workspaceId: string,
prefKey: string,
prefValue: string | boolean,
) {
return this.db
.updateTable('workspaces')
.set({
settings: sql`COALESCE(settings, '{}'::jsonb)
|| jsonb_build_object('api', COALESCE(settings->'api', '{}'::jsonb)
|| jsonb_build_object('${sql.raw(prefKey)}', ${sql.lit(prefValue)}))`,
updatedAt: new Date(),
})
.where('id', '=', workspaceId)
.returning(this.baseFields)
.executeTakeFirst();
}
}
+23 -5
View File
@@ -3,13 +3,18 @@
* Please do not edit it manually.
*/
import type { ColumnType } from "kysely";
import type { ColumnType } from 'kysely';
export type Generated<T> = T extends ColumnType<infer S, infer I, infer U>
? ColumnType<S, I | undefined, U>
: ColumnType<T, T | undefined, T>;
export type Generated<T> =
T extends ColumnType<infer S, infer I, infer U>
? ColumnType<S, I | undefined, U>
: ColumnType<T, T | undefined, T>;
export type Int8 = ColumnType<string, bigint | number | string, bigint | number | string>;
export type Int8 = ColumnType<
string,
bigint | number | string,
bigint | number | string
>;
export type Json = JsonValue;
@@ -25,6 +30,18 @@ export type JsonValue = JsonArray | JsonObject | JsonPrimitive;
export type Timestamp = ColumnType<Date, Date | string, Date | string>;
export interface ApiKeys {
createdAt: Generated<Timestamp>;
deletedAt: Timestamp | null;
expiresAt: Timestamp | null;
id: Generated<string>;
lastUsedAt: Timestamp | null;
name: string | null;
updatedAt: Generated<Timestamp>;
creatorId: string;
workspaceId: string;
}
export interface Attachments {
createdAt: Generated<Timestamp>;
creatorId: string;
@@ -344,6 +361,7 @@ export interface Workspaces {
}
export interface DB {
apiKeys: ApiKeys;
attachments: Attachments;
authAccounts: AuthAccounts;
authProviders: AuthProviders;
@@ -19,6 +19,7 @@ import {
Shares,
FileTasks,
UserMfa as _UserMFA,
ApiKeys,
} from './db';
// Workspace
@@ -119,3 +120,8 @@ export type UpdatableFileTask = Updateable<Omit<FileTasks, 'id'>>;
export type UserMFA = Selectable<_UserMFA>;
export type InsertableUserMFA = Insertable<_UserMFA>;
export type UpdatableUserMFA = Updateable<Omit<_UserMFA, 'id'>>;
// Api Keys
export type ApiKey = Selectable<ApiKeys>;
export type InsertableApiKey = Insertable<ApiKeys>;
export type UpdatableApiKey = Updateable<Omit<ApiKeys, 'id'>>;