From 66e8b37f704aa4cbe385be52680d159cd60c0d4e Mon Sep 17 00:00:00 2001 From: KernelDeimos Date: Fri, 18 Oct 2024 20:42:25 -0400 Subject: [PATCH] dev: add dedupe_name option for app creation --- .../src/drivers/EntityStoreImplementation.js | 12 ++++++------ src/backend/src/om/entitystorage/AppES.js | 13 +++++++++++-- src/backend/src/services/EntityStoreService.js | 12 ++++++------ src/backend/src/services/drivers/interfaces.js | 3 +++ 4 files changed, 26 insertions(+), 14 deletions(-) diff --git a/src/backend/src/drivers/EntityStoreImplementation.js b/src/backend/src/drivers/EntityStoreImplementation.js index fffcac08..8b1c7432 100644 --- a/src/backend/src/drivers/EntityStoreImplementation.js +++ b/src/backend/src/drivers/EntityStoreImplementation.js @@ -91,26 +91,26 @@ class EntityStoreImplementation extends Driver { this.service = service; } static METHODS = { - create: async function ({ object }) { + create: async function ({ object, options }) { const svc_es = this.services.get(this.service); if ( object.hasOwnProperty(svc_es.om.primary_identifier) ) { throw APIError.create('field_not_allowed_for_create', null, { key: svc_es.om.primary_identifier }); } const entity = await Entity.create({ om: svc_es.om }, object); - return await svc_es.create(entity); + return await svc_es.create(entity, options); }, - update: async function ({ object, id }) { + update: async function ({ object, id, options }) { const svc_es = this.services.get(this.service); // if ( ! object.hasOwnProperty(svc_es.om.primary_identifier) ) { // throw APIError.create('field_required_for_update', null, { key: svc_es.om.primary_identifier }); // } const entity = await Entity.create({ om: svc_es.om }, object); - return await svc_es.update(entity, id); + return await svc_es.update(entity, id, options); }, - upsert: async function ({ object, id }) { + upsert: async function ({ object, id, options }) { const svc_es = this.services.get(this.service); const entity = await Entity.create({ om: svc_es.om }, object); - return await svc_es.upsert(entity, id); + return await svc_es.upsert(entity, id, options); }, read: async function ({ uid, id }) { if ( ! uid && ! id ) { diff --git a/src/backend/src/om/entitystorage/AppES.js b/src/backend/src/om/entitystorage/AppES.js index a50a2e62..ac99bcc0 100644 --- a/src/backend/src/om/entitystorage/AppES.js +++ b/src/backend/src/om/entitystorage/AppES.js @@ -89,12 +89,21 @@ class AppES extends BaseES { const { old_entity } = extra; const throw_it = ( ! old_entity ) || ( await old_entity.get('name') !== await entity.get('name') ); - if ( throw_it ) { + if ( throw_it && extra.options && extra.options.dedupe_name ) { + const base = await entity.get('name'); + let number = 0; + while ( await app_name_exists(`${base}-${number}`) ) { + number++; + } + await entity.set('name', `${base}-${number}`) + } + else if ( throw_it ) { throw APIError.create('app_name_already_in_use', null, { name: await entity.get('name') }); + } else { + entity.del('name'); } - entity.del('name'); } const subdomain_id = await this.maybe_insert_subdomain_(entity); diff --git a/src/backend/src/services/EntityStoreService.js b/src/backend/src/services/EntityStoreService.js index 8addef79..af732778 100644 --- a/src/backend/src/services/EntityStoreService.js +++ b/src/backend/src/services/EntityStoreService.js @@ -41,8 +41,8 @@ class EntityStoreService extends BaseService { } // TODO: can replace these with MethodProxyFeature - async create (entity) { - return await this.upstream.upsert(entity, { old_entity: null }); + async create (entity, options) { + return await this.upstream.upsert(entity, { old_entity: null, options }); } async read (uid) { return await this.upstream.read(uid); @@ -56,7 +56,7 @@ class EntityStoreService extends BaseService { if ( ! predicate) predicate = new Null(); return await this.upstream.select({ predicate, ...rest }); } - async update (entity, id) { + async update (entity, id, options) { let old_entity = await this.read( await entity.get(this.om.primary_identifier)); @@ -84,9 +84,9 @@ class EntityStoreService extends BaseService { const id_prop = this.om.properties[this.om.primary_identifier]; await entity.set(id_prop.name, await old_entity.get(id_prop.name)); - return await this.upstream.upsert(entity, { old_entity }); + return await this.upstream.upsert(entity, { old_entity, options }); } - async upsert (entity, id) { + async upsert (entity, id, options) { let old_entity = await this.read( await entity.get(this.om.primary_identifier)); @@ -110,7 +110,7 @@ class EntityStoreService extends BaseService { await entity.set(id_prop.name, await old_entity.get(id_prop.name)); } - return await this.upstream.upsert(entity, { old_entity }); + return await this.upstream.upsert(entity, { old_entity, options }); } async delete (uid) { const old_entity = await this.read(uid); diff --git a/src/backend/src/services/drivers/interfaces.js b/src/backend/src/services/drivers/interfaces.js index 9f0c6d31..66501bed 100644 --- a/src/backend/src/services/drivers/interfaces.js +++ b/src/backend/src/services/drivers/interfaces.js @@ -25,6 +25,7 @@ const ENTITY_STORAGE_INTERFACE = { subtype: 'object', required: true, }, + options: { type: 'json' }, } }, read: { @@ -48,6 +49,7 @@ const ENTITY_STORAGE_INTERFACE = { subtype: 'object', required: true, }, + options: { type: 'json' }, } }, upsert: { @@ -58,6 +60,7 @@ const ENTITY_STORAGE_INTERFACE = { subtype: 'object', required: true, }, + options: { type: 'json' }, } }, delete: {