From 4b993fc6b3b46cabf76b7f6c7511c609fa7f2556 Mon Sep 17 00:00:00 2001 From: Philipp Kunz Date: Sat, 21 Dec 2024 20:21:54 +0100 Subject: [PATCH] fix(secret-management): Refactor secret management to use distinct secret bundle and group APIs. Introduce API client classes for secret bundles and groups. --- changelog.md | 7 ++ pnpm-lock.yaml | 2 + ts/00_commitinfo_data.ts | 2 +- ts/manager.secret/classes.secretmanager.ts | 136 ++++++++++++++------- ts_apiclient/classes.secretbundle.ts | 96 +++++++++++++++ ts_apiclient/classes.secretgroup.ts | 103 ++++++++++++++++ ts_apiclient/classes.secretmanager.ts | 27 ++++ ts_apiclient/plugins.ts | 2 + ts_interfaces/requests/admin.ts | 16 +++ ts_interfaces/requests/index.ts | 8 +- ts_interfaces/requests/secret.ts | 94 -------------- ts_interfaces/requests/secretbundle.ts | 79 ++++++++++++ ts_interfaces/requests/secretgroup.ts | 74 +++++++++++ ts_web/00_commitinfo_data.ts | 2 +- ts_web/appstate.ts | 42 ++++--- 15 files changed, 533 insertions(+), 157 deletions(-) create mode 100644 ts_apiclient/classes.secretmanager.ts create mode 100644 ts_interfaces/requests/admin.ts delete mode 100644 ts_interfaces/requests/secret.ts create mode 100644 ts_interfaces/requests/secretbundle.ts create mode 100644 ts_interfaces/requests/secretgroup.ts diff --git a/changelog.md b/changelog.md index 31475d4..9fc3b62 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,12 @@ # Changelog +## 2024-12-21 - 4.5.3 - fix(secret-management) +Refactor secret management to use distinct secret bundle and group APIs. Introduce API client classes for secret bundles and groups. + +- Updated secret management logic to separate secret bundle and group APIs. +- Implemented new API client classes for managing secret bundles and groups. +- Fixed incorrect method usages for secret-related actions. + ## 2024-12-20 - 4.5.2 - fix(apiclient) Implemented IService interface in Service class and improved secret bundle documentation. diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 160cbd3..dc4fbde 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -6569,7 +6569,9 @@ snapshots: '@push.rocks/smartshell': 3.2.2 '@push.rocks/taskbuffer': 3.1.7 transitivePeerDependencies: + - bufferutil - supports-color + - utf-8-validate '@hapi/bourne@3.0.0': {} diff --git a/ts/00_commitinfo_data.ts b/ts/00_commitinfo_data.ts index 2fa7b58..a46e3b1 100644 --- a/ts/00_commitinfo_data.ts +++ b/ts/00_commitinfo_data.ts @@ -3,6 +3,6 @@ */ export const commitinfo = { name: '@serve.zone/cloudly', - version: '4.5.2', + version: '4.5.3', description: 'A comprehensive tool for managing containerized applications across multiple cloud providers using Docker Swarmkit, featuring web, CLI, and API interfaces.' } diff --git a/ts/manager.secret/classes.secretmanager.ts b/ts/manager.secret/classes.secretmanager.ts index 386e7bf..487b155 100644 --- a/ts/manager.secret/classes.secretmanager.ts +++ b/ts/manager.secret/classes.secretmanager.ts @@ -35,20 +35,71 @@ export class CloudlySecretManager { this.typedrouter = new plugins.typedrequest.TypedRouter(); this.cloudlyRef.typedrouter.addTypedRouter(this.typedrouter); - this.typedrouter.addTypedHandler( - new plugins.typedrequest.TypedHandler( - 'adminGetConfigBundlesAndSecretGroups', + // secretbundle routes + this.typedrouter.addTypedHandler( + new plugins.typedrequest.TypedHandler( + 'getSecretBundles', async (dataArg, toolsArg) => { await toolsArg.passGuards([this.cloudlyRef.authManager.adminIdentityGuard], dataArg); dataArg.identity.jwt; const secretBundles = await SecretBundle.getInstances({}); - const secretGroups = await SecretGroup.getInstances({}); return { secretBundles: [ ...(await Promise.all( secretBundles.map((configBundle) => configBundle.createSavableObject()), )), ], + }; + }, + ), + ); + + this.typedrouter.addTypedHandler( + new plugins.typedrequest.TypedHandler('createSecretBundle', async (dataArg) => { + const secretBundle = new SecretBundle(); + secretBundle.id = plugins.smartunique.shortId(8); + secretBundle.data = dataArg.secretBundle.data; + await secretBundle.save(); + return { + resultSecretBundle: await secretBundle.createSavableObject(), + }; + }), + ); + + this.typedrouter.addTypedHandler( + new plugins.typedrequest.TypedHandler('updateSecretBundle', async (dataArg) => { + const secretBundle = await SecretBundle.getInstance({ + id: dataArg.secretBundle.id, + }); + secretBundle.data = dataArg.secretBundle.data; + await secretBundle.save(); + return { + resultSecretBundle: await secretBundle.createSavableObject(), + }; + }), + ); + + this.typedrouter.addTypedHandler( + new plugins.typedrequest.TypedHandler('deleteSecretBundleById', async (dataArg) => { + const secretBundle = await SecretBundle.getInstance({ + id: dataArg.secretBundleId, + }); + await secretBundle.delete(); + return { + ok: true, + }; + }), + ); + + // secretgroup routes + this.typedrouter.addTypedHandler( + new plugins.typedrequest.TypedHandler( + 'getSecretGroups', + async (dataArg, toolsArg) => { + await toolsArg.passGuards([this.cloudlyRef.authManager.adminIdentityGuard], dataArg); + dataArg.identity.jwt; + const secretGroups = await SecretGroup.getInstances({}); + return { secretGroups: [ ...(await Promise.all( secretGroups.map((secretGroup) => secretGroup.createSavableObject()), @@ -59,50 +110,45 @@ export class CloudlySecretManager { ), ); - this.typedrouter.addTypedHandler( - new plugins.typedrequest.TypedHandler( - 'adminCreateConfigBundlesAndSecretGroups', - async (dataArg) => { - for (const secretGroupObject of dataArg.secretGroups) { - const secretGroup = new SecretGroup(); - secretGroup.id = plugins.smartunique.shortId(8); - secretGroup.data = secretGroupObject.data; - await secretGroup.save(); - } - return { - ok: true, - }; - }, - ), + this.typedrouter.addTypedHandler( + new plugins.typedrequest.TypedHandler('createSecretGroup', async (dataArg) => { + const secretGroup = new SecretGroup(); + secretGroup.id = plugins.smartunique.shortId(8); + secretGroup.data = dataArg.secretGroup.data; + await secretGroup.save(); + return { + resultSecretGroup: await secretGroup.createSavableObject(), + }; + }), + ); + + this.typedrouter.addTypedHandler( + new plugins.typedrequest.TypedHandler('updateSecretGroup', async (dataArg) => { + const secretGroup = await SecretGroup.getInstance({ + id: dataArg.secretGroup.id, + }); + secretGroup.data = dataArg.secretGroup.data; + await secretGroup.save(); + return { + resultSecretGroup: await secretGroup.createSavableObject(), + }; + }), + ); + + this.typedrouter.addTypedHandler( + new plugins.typedrequest.TypedHandler('deleteSecretGroupById', async (dataArg) => { + const secretGroup = await SecretGroup.getInstance({ + id: dataArg.secretGroupId, + }); + await secretGroup.delete(); + return { + ok: true, + }; + }), ); this.typedrouter.addTypedHandler( - new plugins.typedrequest.TypedHandler( - 'adminDeleteConfigBundlesAndSecretGroups', - async (dataArg) => { - for (const secretGroupId of dataArg.secretGroupIds) { - const secretGroup = await SecretGroup.getInstance({ - id: secretGroupId, - }); - await secretGroup.delete(); - } - for (const secretBundleId of dataArg.secretBundleIds) { - const configBundle = await SecretBundle.getInstance({ - id: secretBundleId, - }); - await configBundle.delete(); - console.log(`deleted configbundle ${secretBundleId}`); - } - return { - ok: true, - }; - }, - ), - ); - - // lets add typedrouter routes for accessing the configvailt from apps - this.typedrouter.addTypedHandler( - new plugins.typedrequest.TypedHandler( + new plugins.typedrequest.TypedHandler( 'getEnvBundle', async (dataArg) => { const wantedBundle = await SecretBundle.getInstance({ diff --git a/ts_apiclient/classes.secretbundle.ts b/ts_apiclient/classes.secretbundle.ts index e69de29..18d3852 100644 --- a/ts_apiclient/classes.secretbundle.ts +++ b/ts_apiclient/classes.secretbundle.ts @@ -0,0 +1,96 @@ +import * as plugins from './plugins.js'; +import type { CloudlyApiClient } from './classes.cloudlyapiclient.js'; + +export class SecretBundle implements plugins.servezoneInterfaces.data.ISecretBundle { + public cloudlyClientRef: CloudlyApiClient; + + public id: string; + public data: plugins.servezoneInterfaces.data.ISecretBundle['data']; + + constructor(cloudlyClientRef: CloudlyApiClient) { + this.cloudlyClientRef = cloudlyClientRef; + } + + public static async getSecretBundleById(cloudlyClientRef: CloudlyApiClient, secretBundleIdArg: string) { + const getSecretBundleByIdTR = cloudlyClientRef.typedsocketClient.createTypedRequest( + 'getSecretBundleById' + ); + const response = await getSecretBundleByIdTR.fire({ + identity: cloudlyClientRef.identity, + secretBundleId: secretBundleIdArg, + }); + const newSecretBundle = new SecretBundle(cloudlyClientRef); + Object.assign(newSecretBundle, response.secretBundle); + return newSecretBundle; + } + + public static async getSecretBundles(cloudlyClientRef: CloudlyApiClient) { + const getSecretBundlesTR = cloudlyClientRef.typedsocketClient.createTypedRequest( + 'getSecretBundles' + ); + const response = await getSecretBundlesTR.fire({ + identity: cloudlyClientRef.identity, + }); + const secretBundles: SecretBundle[] = []; + for (const secretBundle of response.secretBundles) { + const newSecretBundle = new SecretBundle(cloudlyClientRef); + Object.assign(newSecretBundle, secretBundle); + secretBundles.push(newSecretBundle); + } + return secretBundles; + } + + public static async createSecretBundle(cloudlyClientRef: CloudlyApiClient, secretBundleDataArg: Partial) { + const createSecretBundleTR = cloudlyClientRef.typedsocketClient.createTypedRequest( + 'createSecretBundle' + ); + const response = await createSecretBundleTR.fire({ + identity: cloudlyClientRef.identity, + secretBundle: { + id: null, + data: { + name: secretBundleDataArg.name, + description: secretBundleDataArg.description, + type: secretBundleDataArg.type, + authorizations: secretBundleDataArg.authorizations, + includedImages: secretBundleDataArg.includedImages, + includedSecretGroupIds: secretBundleDataArg.includedSecretGroupIds, + includedTags: secretBundleDataArg.includedTags, + }, + }, + }); + const newSecretBundle = new SecretBundle(cloudlyClientRef); + Object.assign(newSecretBundle, response.resultSecretBundle); + return newSecretBundle; + } + + public async update() { + const updateSecretBundleTR = this.cloudlyClientRef.typedsocketClient.createTypedRequest( + 'updateSecretBundle' + ); + const response = await updateSecretBundleTR.fire({ + identity: this.cloudlyClientRef.identity, + secretBundle: { + id: this.id, + data: this.data, + }, + }); + + const resultSecretBundleData = response.resultSecretBundle.data; + plugins.smartexpect.expect(resultSecretBundleData).toEqual(this.data); + + return this; + } + + public async delete(cloudlyClientRef: CloudlyApiClient, secretBundleIdArg: string) { + const deleteSecretBundleTR = cloudlyClientRef.typedsocketClient.createTypedRequest( + 'deleteSecretBundleById' + ); + const response = await deleteSecretBundleTR.fire({ + identity: cloudlyClientRef.identity, + secretBundleId: this.id, + }); + plugins.smartexpect.expect(response.ok).toBeTrue(); + return null; + } +} \ No newline at end of file diff --git a/ts_apiclient/classes.secretgroup.ts b/ts_apiclient/classes.secretgroup.ts index e69de29..3bc190c 100644 --- a/ts_apiclient/classes.secretgroup.ts +++ b/ts_apiclient/classes.secretgroup.ts @@ -0,0 +1,103 @@ +import * as plugins from './plugins.js'; +import type { CloudlyApiClient } from './classes.cloudlyapiclient.js'; + +export class SecretGroup implements plugins.servezoneInterfaces.data.ISecretGroup { + public cloudlyClientRef: CloudlyApiClient; + + public id: string; + public data: plugins.servezoneInterfaces.data.ISecretGroup['data']; + + constructor(cloudlyClientRef: CloudlyApiClient) { + this.cloudlyClientRef = cloudlyClientRef; + } + + public static async getSecretGroupById(cloudlyClientRef: CloudlyApiClient, secretGroupIdArg: string) { + const getSecretGroupByIdTR = cloudlyClientRef.typedsocketClient.createTypedRequest( + 'getSecretGroupById' + ); + const response = await getSecretGroupByIdTR.fire({ + identity: cloudlyClientRef.identity, + secretGroupId: secretGroupIdArg, + }); + const newSecretGroup = new SecretGroup(cloudlyClientRef); + Object.assign(newSecretGroup, response.secretGroup); + return newSecretGroup; + } + + public static async getSecretGroups(cloudlyClientRef: CloudlyApiClient) { + const getSecretGroupsTR = cloudlyClientRef.typedsocketClient.createTypedRequest( + 'getSecretGroups' + ); + const response = await getSecretGroupsTR.fire({ + identity: cloudlyClientRef.identity, + }); + const secretGroups: SecretGroup[] = []; + for (const secretGroup of response.secretGroups) { + const newSecretGroup = new SecretGroup(cloudlyClientRef); + Object.assign(newSecretGroup, secretGroup); + secretGroups.push(newSecretGroup); + } + return secretGroups; + } + + public static async createSecretGroup(cloudlyClientRef: CloudlyApiClient, secretGroupDataArg: Partial) { + const createSecretGroupTR = cloudlyClientRef.typedsocketClient.createTypedRequest( + 'createSecretGroup' + ); + const response = await createSecretGroupTR.fire({ + identity: cloudlyClientRef.identity, + secretGroup: { + id: null, + data: { + name: secretGroupDataArg.name, + description: secretGroupDataArg.description, + environments: secretGroupDataArg.environments, + key: secretGroupDataArg.key, + tags: secretGroupDataArg.tags, + priority: secretGroupDataArg.priority, + }, + }, + }); + const newSecretGroup = new SecretGroup(cloudlyClientRef); + Object.assign(newSecretGroup, response.resultSecretGroup); + return newSecretGroup; + } + + // INSTANCE + public async update() { + const updateSecretGroupTR = this.cloudlyClientRef.typedsocketClient.createTypedRequest( + 'updateSecretGroup' + ); + const response = await updateSecretGroupTR.fire({ + identity: this.cloudlyClientRef.identity, + secretGroup: { + id: this.id, + data: { + name: this.data.name, + description: this.data.description, + environments: this.data.environments, + key: this.data.key, + tags: this.data.tags, + priority: this.data.priority, + }, + }, + }); + + const resultSecretGroupData = response.resultSecretGroup.data; + plugins.smartexpect.expect(resultSecretGroupData).toEqual(this.data); + + return this; + } + + public async delete(cloudlyClientRef: CloudlyApiClient, secretGroupIdArg: string) { + const deleteSecretGroupTR = cloudlyClientRef.typedsocketClient.createTypedRequest( + 'deleteSecretGroupById' + ); + const response = await deleteSecretGroupTR.fire({ + identity: cloudlyClientRef.identity, + secretGroupId: this.id, + }); + plugins.smartexpect.expect(response.ok).toBeTrue(); + return null; + } +} diff --git a/ts_apiclient/classes.secretmanager.ts b/ts_apiclient/classes.secretmanager.ts new file mode 100644 index 0000000..6d49a90 --- /dev/null +++ b/ts_apiclient/classes.secretmanager.ts @@ -0,0 +1,27 @@ +import * as plugins from './plugins.js'; +import type { CloudlyApiClient } from './classes.cloudlyapiclient.js'; + +import { SecretBundle } from './classes.secretbundle.js'; +import { SecretGroup } from './classes.secretgroup.js'; + +export class SecretManager { + // INSTANCE + cloudlyClientRef: CloudlyApiClient; + + constructor(cloudlyClientRef: CloudlyApiClient) { + this.cloudlyClientRef = cloudlyClientRef; + } + + public async getSecretGroupsAndBundles() { + + } + + /** + * The secret group has a secret bundle. + * This function essentially returns the secret bundle as a flat object. + * In other words, it resolves secret groups and + */ + public async getSecretBundleAsFlatObject(environmentArg: string = 'production') { + + } +} diff --git a/ts_apiclient/plugins.ts b/ts_apiclient/plugins.ts index 276fea8..a30d627 100644 --- a/ts_apiclient/plugins.ts +++ b/ts_apiclient/plugins.ts @@ -6,11 +6,13 @@ export { } // @push.rocks scope +import * as smartexpect from '@push.rocks/smartexpect'; import * as smartpromise from '@push.rocks/smartpromise'; import * as smartrx from '@push.rocks/smartrx'; import * as webstream from '@push.rocks/smartstream/web'; export { + smartexpect, smartpromise, smartrx, webstream, diff --git a/ts_interfaces/requests/admin.ts b/ts_interfaces/requests/admin.ts new file mode 100644 index 0000000..71dd54b --- /dev/null +++ b/ts_interfaces/requests/admin.ts @@ -0,0 +1,16 @@ +import * as plugins from '../plugins.js'; +import * as userInterfaces from '../data/user.js'; + +export interface IReq_Admin_LoginWithUsernameAndPassword extends plugins.typedrequestInterfaces.implementsTR< + plugins.typedrequestInterfaces.ITypedRequest, + IReq_Admin_LoginWithUsernameAndPassword +> { + method: 'adminLoginWithUsernameAndPassword'; + request: { + username: string; + password: string; + }; + response: { + identity: userInterfaces.IIdentity; + } +} \ No newline at end of file diff --git a/ts_interfaces/requests/index.ts b/ts_interfaces/requests/index.ts index 3f204af..96d0a4f 100644 --- a/ts_interfaces/requests/index.ts +++ b/ts_interfaces/requests/index.ts @@ -1,5 +1,6 @@ import * as plugins from '../plugins.js'; +import * as adminRequests from './admin.js'; import * as certificateRequests from './certificate.js'; import * as clusterRequests from './cluster.js'; import * as configRequests from './config.js'; @@ -9,13 +10,15 @@ import * as informRequests from './inform.js'; import * as logRequests from './log.js'; import * as networkRequests from './network.js'; import * as routingRequests from './routing.js'; -import * as secretRequests from './secret.js'; +import * as secretBundleRequests from './secretbundle.js'; +import * as secretGroupRequests from './secretgroup.js'; import * as serverRequests from './server.js'; import * as serviceRequests from './service.js'; import * as statusRequests from './status.js'; import * as versionRequests from './version.js'; export { + adminRequests as admin, certificateRequests as certificate, clusterRequests as cluster, configRequests as config, @@ -25,7 +28,8 @@ export { logRequests as log, networkRequests as network, routingRequests as routing, - secretRequests as secret, + secretBundleRequests as secretbundle, + secretGroupRequests as secretgroup, serverRequests as server, serviceRequests as service, statusRequests as status, diff --git a/ts_interfaces/requests/secret.ts b/ts_interfaces/requests/secret.ts deleted file mode 100644 index 1792726..0000000 --- a/ts_interfaces/requests/secret.ts +++ /dev/null @@ -1,94 +0,0 @@ -import * as plugins from '../plugins.js'; -import * as data from '../data/index.js'; -import * as userInterfaces from '../data/user.js'; - -export interface IReq_GetEnvBundle extends plugins.typedrequestInterfaces.implementsTR< - plugins.typedrequestInterfaces.ITypedRequest, - IReq_GetEnvBundle -> { - method: 'getEnvBundle'; - request: { - authorization: string; - /** - * specify this if you want to get a warning, if the envBundle is for an unexpected environment - */ - environment?: string; - }; - response: { - envBundle: data.IEnvBundle; - }; -} - -export interface IReq_Admin_LoginWithUsernameAndPassword extends plugins.typedrequestInterfaces.implementsTR< - plugins.typedrequestInterfaces.ITypedRequest, - IReq_Admin_LoginWithUsernameAndPassword -> { - method: 'adminLoginWithUsernameAndPassword'; - request: { - username: string; - password: string; - }; - response: { - identity: userInterfaces.IIdentity; - } -} - -export interface IReq_Admin_GetConfigBundlesAndSecretGroups extends plugins.typedrequestInterfaces.implementsTR< - plugins.typedrequestInterfaces.ITypedRequest, - IReq_Admin_GetConfigBundlesAndSecretGroups -> { - method: 'adminGetConfigBundlesAndSecretGroups'; - request: { - identity: userInterfaces.IIdentity; - }; - response: { - secretBundles: data.ISecretBundle[]; - secretGroups: data.ISecretGroup[]; - }; - -} - -export interface IReq_Admin_CreateConfigBundlesAndSecretGroups extends plugins.typedrequestInterfaces.implementsTR< - plugins.typedrequestInterfaces.ITypedRequest, - IReq_Admin_CreateConfigBundlesAndSecretGroups -> { - method: 'adminCreateConfigBundlesAndSecretGroups'; - request: { - identity: userInterfaces.IIdentity; - secretBundles: data.ISecretBundle[]; - secretGroups: data.ISecretGroup[]; - }; - response: { - ok: boolean; - }; -} - -export interface IReq_Admin_UpdateConfigBundlesAndSecretGroups extends plugins.typedrequestInterfaces.implementsTR< - plugins.typedrequestInterfaces.ITypedRequest, - IReq_Admin_UpdateConfigBundlesAndSecretGroups -> { - method: 'adminUpdateConfigBundlesAndSecretGroups'; - request: { - identity: userInterfaces.IIdentity; - configBundles: data.ISecretBundle[]; - secretGroups: data.ISecretGroup[]; - }; - response: { - ok: boolean; - }; -} - -export interface IReq_Admin_DeleteConfigBundlesAndSecretGroups extends plugins.typedrequestInterfaces.implementsTR< - plugins.typedrequestInterfaces.ITypedRequest, - IReq_Admin_DeleteConfigBundlesAndSecretGroups -> { - method: 'adminDeleteConfigBundlesAndSecretGroups'; - request: { - identity: userInterfaces.IIdentity; - secretBundleIds: string[]; - secretGroupIds: string[]; - }; - response: { - ok: boolean; - }; -} diff --git a/ts_interfaces/requests/secretbundle.ts b/ts_interfaces/requests/secretbundle.ts new file mode 100644 index 0000000..68711d8 --- /dev/null +++ b/ts_interfaces/requests/secretbundle.ts @@ -0,0 +1,79 @@ +import * as plugins from '../plugins.js'; +import * as data from '../data/index.js'; +import * as userInterfaces from '../data/user.js'; + +/** + * when retrieving secrets for actual use, you do this in the form of an envBundle. + */ +export interface IReq_GetEnvBundle extends plugins.typedrequestInterfaces.implementsTR< + plugins.typedrequestInterfaces.ITypedRequest, + IReq_GetEnvBundle +> { + method: 'getEnvBundle'; + request: { + authorization: string; + /** + * specify this if you want to get a warning, if the envBundle is for an unexpected environment + */ + environment?: string; + }; + response: { + envBundle: data.IEnvBundle; + }; +} + +export interface IReq_GetSecretBundles extends plugins.typedrequestInterfaces.implementsTR< + plugins.typedrequestInterfaces.ITypedRequest, + IReq_GetSecretBundles +> { + method: 'getSecretBundles'; + request: { + identity: userInterfaces.IIdentity; + }; + response: { + secretBundles: data.ISecretBundle[]; + }; + +} + +export interface IReq_CreateSecretBundle extends plugins.typedrequestInterfaces.implementsTR< + plugins.typedrequestInterfaces.ITypedRequest, + IReq_CreateSecretBundle +> { + method: 'createSecretBundle'; + request: { + identity: userInterfaces.IIdentity; + secretBundle: data.ISecretBundle; + }; + response: { + resultSecretBundle: data.ISecretBundle; + }; +} + +export interface IReq_UpdateSecretBundle extends plugins.typedrequestInterfaces.implementsTR< + plugins.typedrequestInterfaces.ITypedRequest, + IReq_UpdateSecretBundle +> { + method: 'updateSecretBundle'; + request: { + identity: userInterfaces.IIdentity; + secretBundle: data.ISecretBundle; + }; + response: { + resultSecretBundle: data.ISecretBundle; + }; +} + +export interface IReq_DeleteSecretBundleById extends plugins.typedrequestInterfaces.implementsTR< + plugins.typedrequestInterfaces.ITypedRequest, + IReq_DeleteSecretBundleById +> { + method: 'deleteSecretBundleById'; + request: { + identity: userInterfaces.IIdentity; + secretBundleId: string; + }; + response: { + ok: boolean; + }; +} diff --git a/ts_interfaces/requests/secretgroup.ts b/ts_interfaces/requests/secretgroup.ts new file mode 100644 index 0000000..ddcac1e --- /dev/null +++ b/ts_interfaces/requests/secretgroup.ts @@ -0,0 +1,74 @@ +import * as plugins from '../plugins.js'; +import * as data from '../data/index.js'; +import * as userInterfaces from '../data/user.js'; + +export interface IReq_GetSecretGroups extends plugins.typedrequestInterfaces.implementsTR< + plugins.typedrequestInterfaces.ITypedRequest, + IReq_GetSecretGroups +> { + method: 'getSecretGroups'; + request: { + identity: userInterfaces.IIdentity; + }; + response: { + secretGroups: data.ISecretGroup[]; + }; + +} + +export interface IReq_GetSecretGroupById extends plugins.typedrequestInterfaces.implementsTR< + plugins.typedrequestInterfaces.ITypedRequest, + IReq_GetSecretGroupById +> { + method: 'getSecretGroupById'; + request: { + identity: userInterfaces.IIdentity; + secretGroupId: string; + }; + response: { + secretGroup: data.ISecretGroup; + }; + +} + +export interface IReq_CreateSecretGroup extends plugins.typedrequestInterfaces.implementsTR< + plugins.typedrequestInterfaces.ITypedRequest, + IReq_CreateSecretGroup +> { + method: 'createSecretGroup'; + request: { + identity: userInterfaces.IIdentity; + secretGroup: data.ISecretGroup; + }; + response: { + resultSecretGroup: data.ISecretGroup; + }; +} + +export interface IReq_UpdateSecretGroup extends plugins.typedrequestInterfaces.implementsTR< + plugins.typedrequestInterfaces.ITypedRequest, + IReq_UpdateSecretGroup +> { + method: 'updateSecretGroup'; + request: { + identity: userInterfaces.IIdentity; + secretGroup: data.ISecretGroup; + }; + response: { + resultSecretGroup: data.ISecretGroup; + }; +} + +export interface IReq_DeleteSecretGroupById extends plugins.typedrequestInterfaces.implementsTR< + plugins.typedrequestInterfaces.ITypedRequest, + IReq_DeleteSecretGroupById +> { + method: 'deleteSecretGroupById'; + request: { + identity: userInterfaces.IIdentity; + secretGroupId: string; + }; + response: { + ok: boolean; + }; +} \ No newline at end of file diff --git a/ts_web/00_commitinfo_data.ts b/ts_web/00_commitinfo_data.ts index 2fa7b58..a46e3b1 100644 --- a/ts_web/00_commitinfo_data.ts +++ b/ts_web/00_commitinfo_data.ts @@ -3,6 +3,6 @@ */ export const commitinfo = { name: '@serve.zone/cloudly', - version: '4.5.2', + version: '4.5.3', description: 'A comprehensive tool for managing containerized applications across multiple cloud providers using Docker Swarmkit, featuring web, CLI, and API interfaces.' } diff --git a/ts_web/appstate.ts b/ts_web/appstate.ts index f057a90..e451578 100644 --- a/ts_web/appstate.ts +++ b/ts_web/appstate.ts @@ -15,7 +15,7 @@ export const loginAction = loginStatePart.createAction<{ username: string; passw async (statePartArg, payloadArg) => { const currentState = statePartArg.getState(); const trLogin = - new domtools.plugins.typedrequest.TypedRequest( + new domtools.plugins.typedrequest.TypedRequest( '/typedrequest', 'adminLoginWithUsernameAndPassword' ); @@ -77,20 +77,34 @@ export const dataState = await appstate.getStatePart( ); // Getting data -export const getAllDataAction = dataState.createAction(async (statePartArg, partialArg?: 'secrets' | 'images') => { +export const getAllDataAction = dataState.createAction(async (statePartArg) => { let currentState = statePartArg.getState(); - // Secrets - const trGetSecrets = - new domtools.plugins.typedrequest.TypedRequest( + // SecretsGroups + const trGetSecretGroups = + new domtools.plugins.typedrequest.TypedRequest( '/typedrequest', - 'adminGetConfigBundlesAndSecretGroups' + 'getSecretGroups' ); - const response = await trGetSecrets.fire({ + const response = await trGetSecretGroups.fire({ identity: loginStatePart.getState().identity, }); currentState = { ...currentState, - ...response, + secretGroups: response.secretGroups, + }; + + // SecretBundles + const trGetSecretBundles = + new domtools.plugins.typedrequest.TypedRequest( + '/typedrequest', + 'getSecretBundles' + ); + const responseSecretBundles = await trGetSecretBundles.fire({ + identity: loginStatePart.getState().identity, + }); + currentState = { + ...currentState, + secretBundles: responseSecretBundles.secretBundles, }; // images @@ -104,7 +118,7 @@ export const getAllDataAction = dataState.createAction(async (statePartArg, part }); currentState = { ...currentState, - ...responseImages, + images: responseImages.images, }; // Clusters @@ -119,7 +133,7 @@ export const getAllDataAction = dataState.createAction(async (statePartArg, part currentState = { ...currentState, - ...responseClusters, + clusters: responseClusters.clusters, } return currentState; @@ -130,9 +144,9 @@ export const createSecretGroupAction = dataState.createAction( async (statePartArg, payloadArg: plugins.interfaces.data.ISecretGroup) => { let currentState = statePartArg.getState(); const trCreateSecretGroup = - new domtools.plugins.typedrequest.TypedRequest( + new domtools.plugins.typedrequest.TypedRequest( '/typedrequest', - 'adminCreateConfigBundlesAndSecretGroups' + 'adminCreateSecretBundlesAndGroups' ); const response = await trCreateSecretGroup.fire({ identity: loginStatePart.getState().identity, @@ -149,7 +163,7 @@ export const deleteSecretGroupAction = dataState.createAction( async (statePartArg, payloadArg: { secretGroupId: string }) => { let currentState = statePartArg.getState(); const trDeleteSecretGroup = - new domtools.plugins.typedrequest.TypedRequest( + new domtools.plugins.typedrequest.TypedRequest( '/typedrequest', 'adminDeleteConfigBundlesAndSecretGroups' ); @@ -168,7 +182,7 @@ export const deleteSecretBundleAction = dataState.createAction( async (statePartArg, payloadArg: { configBundleId: string }) => { let currentState = statePartArg.getState(); const trDeleteConfigBundle = - new domtools.plugins.typedrequest.TypedRequest( + new domtools.plugins.typedrequest.TypedRequest( '/typedrequest', 'adminDeleteConfigBundlesAndSecretGroups' );