import * as plugins from '../../plugins.ts'; import type { OpsServer } from '../classes.opsserver.ts'; import * as interfaces from '../../../ts_interfaces/index.ts'; import { requireAdminIdentity, requireValidIdentity } from '../helpers/guards.ts'; const getStorageErrorCode = (error: unknown): string | undefined => { if (!(error instanceof Error)) { return undefined; } return (error as Error & { Code?: string }).Code || error.name; }; export class BucketsHandler { public typedrouter = new plugins.typedrequest.TypedRouter(); constructor(private opsServerRef: OpsServer) { this.opsServerRef.typedrouter.addTypedRouter(this.typedrouter); this.registerHandlers(); } private registerHandlers(): void { // List buckets this.typedrouter.addTypedHandler( new plugins.typedrequest.TypedHandler( 'listBuckets', async (dataArg) => { await requireValidIdentity(this.opsServerRef.adminHandler, dataArg); const buckets = await this.opsServerRef.objectStorageRef.listBuckets(); return { buckets }; }, ), ); // Create bucket this.typedrouter.addTypedHandler( new plugins.typedrequest.TypedHandler( 'createBucket', async (dataArg) => { await requireAdminIdentity(this.opsServerRef.adminHandler, dataArg); try { await this.opsServerRef.objectStorageRef.createBucket(dataArg.bucketName); await this.opsServerRef.objectStorageRef.auditLogger.log({ actorUserId: dataArg.identity.userId, action: 'bucket.create', targetType: 'bucket', targetId: dataArg.bucketName, success: true, }); } catch (error) { await this.opsServerRef.objectStorageRef.auditLogger.log({ actorUserId: dataArg.identity.userId, action: 'bucket.create', targetType: 'bucket', targetId: dataArg.bucketName, success: false, message: error instanceof Error ? error.message : String(error), }); throw error; } return { ok: true }; }, ), ); // Delete bucket this.typedrouter.addTypedHandler( new plugins.typedrequest.TypedHandler( 'deleteBucket', async (dataArg) => { await requireAdminIdentity(this.opsServerRef.adminHandler, dataArg); try { await this.opsServerRef.objectStorageRef.deleteBucket(dataArg.bucketName); } catch (error) { if (getStorageErrorCode(error) === 'NoSuchBucket') { throw new plugins.typedrequest.TypedResponseError('Bucket not found'); } throw error; } await this.opsServerRef.objectStorageRef.policyManager.onBucketDeleted( dataArg.bucketName, ); await this.opsServerRef.objectStorageRef.auditLogger.log({ actorUserId: dataArg.identity.userId, action: 'bucket.delete', targetType: 'bucket', targetId: dataArg.bucketName, success: true, }); return { ok: true }; }, ), ); // Get bucket policy this.typedrouter.addTypedHandler( new plugins.typedrequest.TypedHandler( 'getBucketPolicy', async (dataArg) => { await requireAdminIdentity(this.opsServerRef.adminHandler, dataArg); let policy: string | null; try { policy = await this.opsServerRef.objectStorageRef.getBucketPolicy(dataArg.bucketName); } catch (error) { if (getStorageErrorCode(error) === 'NoSuchBucket') { throw new plugins.typedrequest.TypedResponseError('Bucket not found'); } throw error; } return { policy }; }, ), ); // Put bucket policy this.typedrouter.addTypedHandler( new plugins.typedrequest.TypedHandler( 'putBucketPolicy', async (dataArg) => { await requireAdminIdentity(this.opsServerRef.adminHandler, dataArg); // Validate JSON try { JSON.parse(dataArg.policy); } catch { throw new plugins.typedrequest.TypedResponseError('Invalid JSON policy document'); } try { await this.opsServerRef.objectStorageRef.putBucketPolicy( dataArg.bucketName, dataArg.policy, ); } catch (error) { if (getStorageErrorCode(error) === 'NoSuchBucket') { throw new plugins.typedrequest.TypedResponseError('Bucket not found'); } throw error; } return { ok: true }; }, ), ); // Delete bucket policy this.typedrouter.addTypedHandler( new plugins.typedrequest.TypedHandler( 'deleteBucketPolicy', async (dataArg) => { await requireAdminIdentity(this.opsServerRef.adminHandler, dataArg); try { await this.opsServerRef.objectStorageRef.deleteBucketPolicy(dataArg.bucketName); } catch (error) { if (getStorageErrorCode(error) === 'NoSuchBucket') { throw new plugins.typedrequest.TypedResponseError('Bucket not found'); } throw error; } return { ok: true }; }, ), ); } }