11import { createAdminSqlClient } from './db/client' ;
2+ import { postgateAdminClient , TENANT_PERMISSIONS } from './postgate' ;
23import * as db from './db/databases' ;
34import type { IDatabase , IDatabaseCreateInput } from '../types' ;
45
@@ -7,35 +8,23 @@ const adminSql = createAdminSqlClient();
78
89interface PostgateDatabaseRow {
910 id : string ;
10- name : string ;
11- schema_name : string | null ;
1211}
1312
1413export class DatabasesService {
1514 /**
1615 * Create a new tenant database
1716 * 1. Create entry in postgate_databases (via admin sql)
1817 * 2. Create entry in openworkers databases table
18+ * Token is created later via POST /databases/:id/token
1919 */
2020 async create ( userId : string , input : IDatabaseCreateInput ) : Promise < IDatabase > {
21- const { name, allowed_operations , max_rows, timeout_seconds } = input ;
21+ const { name, desc , max_rows } = input ;
2222
23- // Generate schema name
24- const schemaName = `tenant_${ userId . substring ( 0 , 8 ) } _${ name } ` ;
25-
26- // Build rules JSON
27- const rules = {
28- allowed_operations : allowed_operations || [ 'SELECT' , 'INSERT' , 'UPDATE' , 'DELETE' ] ,
29- max_rows : max_rows || 1000 ,
30- timeout_seconds : timeout_seconds || 30
31- } ;
32-
33- // Create in postgate
23+ // Create tenant database using PL/pgSQL function (creates schema + entry)
24+ // Pass random name to postgate - user's display name stays in openworkers only
3425 const postgateResult = await adminSql < PostgateDatabaseRow > (
35- `INSERT INTO postgate_databases (name, backend_type, schema_name, rules)
36- VALUES ($1, 'schema', $2, $3::jsonb)
37- RETURNING id, name, schema_name` ,
38- [ name , schemaName , JSON . stringify ( rules ) ]
26+ `SELECT id FROM create_tenant_database($1, $2::integer)` ,
27+ [ crypto . randomUUID ( ) , max_rows || 1000 ]
3928 ) ;
4029
4130 if ( postgateResult . length === 0 ) {
@@ -44,14 +33,13 @@ export class DatabasesService {
4433
4534 const postgateDb = postgateResult [ 0 ] ! ;
4635
47- // Create in openworkers
48- const owDb = await db . createDatabase ( userId , name , postgateDb . id , postgateDb . schema_name ) ;
36+ // Create in openworkers (no token yet)
37+ const owDb = await db . createDatabase ( userId , name , postgateDb . id , desc ) ;
4938
5039 return {
5140 id : owDb . id ,
5241 name : owDb . name ,
53- desc : null ,
54- schemaName : owDb . schemaName ?? undefined ,
42+ desc : owDb . desc ,
5543 createdAt : owDb . createdAt ,
5644 updatedAt : owDb . updatedAt
5745 } ;
@@ -66,8 +54,7 @@ export class DatabasesService {
6654 return rows . map ( ( row ) => ( {
6755 id : row . id ,
6856 name : row . name ,
69- desc : null ,
70- schemaName : row . schemaName ?? undefined ,
57+ desc : row . desc ,
7158 createdAt : row . createdAt ,
7259 updatedAt : row . updatedAt
7360 } ) ) ;
@@ -86,8 +73,7 @@ export class DatabasesService {
8673 return {
8774 id : row . id ,
8875 name : row . name ,
89- desc : null ,
90- schemaName : row . schemaName ?? undefined ,
76+ desc : row . desc ,
9177 createdAt : row . createdAt ,
9278 updatedAt : row . updatedAt
9379 } ;
@@ -106,17 +92,49 @@ export class DatabasesService {
10692 return false ;
10793 }
10894
109- // Delete from postgate
110- await adminSql (
111- `DELETE FROM postgate_databases WHERE id = $1::uuid` ,
112- [ owDb . postgateId ]
113- ) ;
95+ // Delete from postgate using PL/pgSQL function (drops schema + deletes entry)
96+ await adminSql ( `SELECT delete_tenant_database($1::uuid)` , [ owDb . postgateId ] ) ;
11497
11598 // Delete from openworkers
11699 const deleted = await db . deleteDatabase ( userId , id ) ;
117100
118101 return deleted > 0 ;
119102 }
103+
104+ /**
105+ * Regenerate token for a database
106+ * 1. Delete existing token (if any)
107+ * 2. Create new token via postgate API
108+ * 3. Update token_id in openworkers
109+ * Returns the new token (shown only once)
110+ */
111+ async regenerateToken ( userId : string , id : string ) : Promise < { token : string ; tokenId : string } | null > {
112+ // Get openworkers entry
113+ const owDb = await db . findDatabaseById ( userId , id ) ;
114+ if ( ! owDb ) {
115+ return null ;
116+ }
117+
118+ // Delete existing token if there is one
119+ if ( owDb . tokenId ) {
120+ try {
121+ await postgateAdminClient . deleteToken ( owDb . tokenId ) ;
122+ } catch {
123+ // Token might already be deleted, continue
124+ }
125+ }
126+
127+ // Create new token with tenant permissions (DML + DDL)
128+ const tokenResponse = await postgateAdminClient . createToken ( owDb . postgateId , 'default' , TENANT_PERMISSIONS ) ;
129+
130+ // Update token_id in openworkers
131+ await db . updateTokenId ( userId , id , tokenResponse . id ) ;
132+
133+ return {
134+ token : tokenResponse . token ,
135+ tokenId : tokenResponse . id
136+ } ;
137+ }
120138}
121139
122140export const databasesService = new DatabasesService ( ) ;
0 commit comments