From 397baec24e57adad61d240aebc54aeca744602af Mon Sep 17 00:00:00 2001 From: Yesha Mavani Date: Fri, 25 Oct 2024 17:19:21 +0530 Subject: [PATCH 1/5] feat(core): restrict modification of createdon and modifiedon gh-2158 --- ...ansactional-user-modify-repository.base.ts | 35 +++++++++++++++++++ ...efault-user-modify-crud.repository.base.ts | 34 ++++++++++++++++++ packages/core/src/types.ts | 8 ++++- 3 files changed, 76 insertions(+), 1 deletion(-) diff --git a/packages/core/src/repositories/default-transactional-user-modify-repository.base.ts b/packages/core/src/repositories/default-transactional-user-modify-repository.base.ts index ca30ae9a29..bcd4f8dcfe 100644 --- a/packages/core/src/repositories/default-transactional-user-modify-repository.base.ts +++ b/packages/core/src/repositories/default-transactional-user-modify-repository.base.ts @@ -16,6 +16,7 @@ import {AuthErrorKeys} from 'loopback4-authentication'; import {DefaultTransactionSoftCrudRepository} from 'loopback4-soft-delete'; import {IAuthUserWithPermissions} from '../components'; import {UserModifiableEntity} from '../models'; +import {RepositoryOverridingOptions} from '../types'; export abstract class DefaultTransactionalUserModifyRepository< T extends UserModifiableEntity, @@ -34,6 +35,8 @@ export abstract class DefaultTransactionalUserModifyRepository< super(entityClass, dataSource); } + public overridingOptions?: RepositoryOverridingOptions; + async create(entity: DataObject, options?: Options): Promise { let currentUser = await this.getCurrentUser(); currentUser = currentUser ?? options?.currentUser; @@ -43,6 +46,10 @@ export abstract class DefaultTransactionalUserModifyRepository< const uid = currentUser?.userTenantId ?? currentUser?.id; entity.createdBy = uid; entity.modifiedBy = uid; + if (this.overridingOptions?.restrictDateModification) { + delete entity.createdOn; + delete entity.modifiedOn; + } return super.create(entity, options); } @@ -56,6 +63,10 @@ export abstract class DefaultTransactionalUserModifyRepository< entities.forEach(entity => { entity.createdBy = uid ?? ''; entity.modifiedBy = uid ?? ''; + if (this.overridingOptions?.restrictDateModification) { + delete entity.createdOn; + delete entity.modifiedOn; + } }); return super.createAll(entities, options); } @@ -67,6 +78,10 @@ export abstract class DefaultTransactionalUserModifyRepository< } const uid = currentUser?.userTenantId ?? currentUser?.id; entity.modifiedBy = uid; + if (this.overridingOptions?.restrictDateModification) { + delete entity.createdOn; + delete entity.modifiedOn; + } return super.save(entity, options); } @@ -77,6 +92,11 @@ export abstract class DefaultTransactionalUserModifyRepository< } const uid = currentUser?.userTenantId ?? currentUser?.id; entity.modifiedBy = uid; + if (this.overridingOptions?.restrictDateModification) { + /**not deleting the createdOn as it can be a use case where + * we want to update the modifiedOn but not the createdOn */ + delete entity.modifiedOn; + } return super.update(entity, options); } @@ -92,6 +112,11 @@ export abstract class DefaultTransactionalUserModifyRepository< } const uid = currentUser?.userTenantId ?? currentUser?.id; data.modifiedBy = uid; + if (this.overridingOptions?.restrictDateModification) { + /**not deleting the createdOn as it can be a use case where + * we want to update the modifiedOn but not the createdOn */ + delete data.modifiedOn; + } return super.updateAll(data, where, options); } @@ -107,6 +132,11 @@ export abstract class DefaultTransactionalUserModifyRepository< } const uid = currentUser?.userTenantId ?? currentUser?.id; data.modifiedBy = uid; + if (this.overridingOptions?.restrictDateModification) { + /**not deleting the createdOn as it can be a use case where + * we want to update the modifiedOn but not the createdOn */ + delete data.modifiedOn; + } return super.updateById(id, data, options); } @@ -121,6 +151,11 @@ export abstract class DefaultTransactionalUserModifyRepository< } const uid = currentUser?.userTenantId ?? currentUser?.id; data.modifiedBy = uid; + if (this.overridingOptions?.restrictDateModification) { + /**not deleting the createdOn as it can be a use case where + * we want to update the modifiedOn but not the createdOn */ + delete data.modifiedOn; + } return super.replaceById(id, data, options); } } diff --git a/packages/core/src/repositories/default-user-modify-crud.repository.base.ts b/packages/core/src/repositories/default-user-modify-crud.repository.base.ts index 43b6ca994d..d1dc6ae52c 100644 --- a/packages/core/src/repositories/default-user-modify-crud.repository.base.ts +++ b/packages/core/src/repositories/default-user-modify-crud.repository.base.ts @@ -17,6 +17,7 @@ import {SoftCrudRepository} from 'loopback4-soft-delete'; import {IAuthUserWithPermissions} from '../components'; import {UserModifiableEntity} from '../models'; +import {RepositoryOverridingOptions} from '../types'; export class DefaultUserModifyCrudRepository< T extends UserModifiableEntity, @@ -34,6 +35,7 @@ export class DefaultUserModifyCrudRepository< ) { super(entityClass, dataSource); } + public overridingOptions?: RepositoryOverridingOptions; async create(entity: DataObject, options?: Options): Promise { let currentUser = await this.getCurrentUser(); @@ -44,6 +46,10 @@ export class DefaultUserModifyCrudRepository< const uid = currentUser?.userTenantId ?? currentUser?.id; entity.createdBy = uid; entity.modifiedBy = uid; + if (this.overridingOptions?.restrictDateModification) { + delete entity.createdOn; + delete entity.modifiedOn; + } return super.create(entity, options); } @@ -57,6 +63,10 @@ export class DefaultUserModifyCrudRepository< entities.forEach(entity => { entity.createdBy = uid ?? ''; entity.modifiedBy = uid ?? ''; + if (this.overridingOptions?.restrictDateModification) { + delete entity.createdOn; + delete entity.modifiedOn; + } }); return super.createAll(entities, options); } @@ -68,6 +78,10 @@ export class DefaultUserModifyCrudRepository< } const uid = currentUser?.userTenantId ?? currentUser?.id; entity.modifiedBy = uid; + if (this.overridingOptions?.restrictDateModification) { + delete entity.createdOn; + delete entity.modifiedOn; + } return super.save(entity, options); } @@ -78,6 +92,11 @@ export class DefaultUserModifyCrudRepository< } const uid = currentUser?.userTenantId ?? currentUser?.id; entity.modifiedBy = uid; + if (this.overridingOptions?.restrictDateModification) { + /**not deleting the createdOn as it can be a use case where + * we want to update the modifiedOn but not the createdOn */ + delete entity.modifiedOn; + } return super.update(entity, options); } @@ -93,6 +112,11 @@ export class DefaultUserModifyCrudRepository< } const uid = currentUser?.userTenantId ?? currentUser?.id; data.modifiedBy = uid; + if (this.overridingOptions?.restrictDateModification) { + /**not deleting the createdOn as it can be a use case where + * we want to update the modifiedOn but not the createdOn */ + delete data.modifiedOn; + } return super.updateAll(data, where, options); } @@ -108,6 +132,11 @@ export class DefaultUserModifyCrudRepository< } const uid = currentUser?.userTenantId ?? currentUser?.id; data.modifiedBy = uid; + if (this.overridingOptions?.restrictDateModification) { + /**not deleting the createdOn as it can be a use case where + * we want to update the modifiedOn but not the createdOn */ + delete data.modifiedOn; + } return super.updateById(id, data, options); } async replaceById( @@ -121,6 +150,11 @@ export class DefaultUserModifyCrudRepository< } const uid = currentUser?.userTenantId ?? currentUser?.id; data.modifiedBy = uid; + if (this.overridingOptions?.restrictDateModification) { + /**not deleting the createdOn as it can be a use case where + * we want to update the modifiedOn but not the createdOn */ + delete data.modifiedOn; + } return super.replaceById(id, data, options); } } diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index 2a4bbc3d55..9c34db7795 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -12,7 +12,13 @@ export interface IServiceConfig { useCustomSequence: boolean; useSequelize?: boolean; } - +/**This type is used to override the default behaviour of our repo classes */ +export interface RepositoryOverridingOptions { + /**restricts user to pass createdOn and modifiedOn fields in the request body + * and only current date will be set in the database */ + restrictDateModification: boolean; + [property: string]: any; //NOSONAR +} export type OASPathDefinition = AnyObject; export interface CoreConfig { From 0efe67c53eb35e9dca18b7836d1a63d57a2cf07f Mon Sep 17 00:00:00 2001 From: Yesha Mavani Date: Mon, 28 Oct 2024 09:52:10 +0530 Subject: [PATCH 2/5] feat(core): lint fixes gh-2158 --- packages/core/src/types.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index 9c34db7795..7cd5cf77ac 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -17,6 +17,7 @@ export interface RepositoryOverridingOptions { /**restricts user to pass createdOn and modifiedOn fields in the request body * and only current date will be set in the database */ restrictDateModification: boolean; + //eslint-disable-next-line @typescript-eslint/no-explicit-any [property: string]: any; //NOSONAR } export type OASPathDefinition = AnyObject; From 48af493b3facec50cf9adc04b6b3a5869abff828 Mon Sep 17 00:00:00 2001 From: Yesha Mavani Date: Mon, 28 Oct 2024 11:58:45 +0530 Subject: [PATCH 3/5] docs(core): update the readme file gh-2158 --- packages/core/README.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/packages/core/README.md b/packages/core/README.md index de863f04fb..f38f831c3c 100644 --- a/packages/core/README.md +++ b/packages/core/README.md @@ -570,6 +570,29 @@ export class UserRepository extends DefaultUserModifyCrudRepository< ) ``` +The repository by default allows to pass back dated or future dates for createdOn and modifiedOn values but to restrict the manual date modification we can pass overridingOptions like this + +```ts +export class UsersRepository extends DefaultUserModifyCrudRepository< + Users, + typeof Users.prototype.id, + UsersRelations +> { + constructor( + @inject(`datasources.AuditDB`) dataSource: juggler.DataSource, + @inject.getter(AuthenticationBindings.CURRENT_USER) + protected readonly getCurrentUser: Getter< + IAuthUserWithPermissions | undefined + >, + ) { + super(Users, dataSource, getCurrentUser); + } + public overridingOptions = { + restrictDateModification: true, + }; +} +``` + ![Connector](https://loopback.io/images/9830486.png) #### SequelizeUserModifyCrudRepository From 9845d7052e552ab068a97b715d107e149606eccd Mon Sep 17 00:00:00 2001 From: Yesha Mavani Date: Mon, 28 Oct 2024 19:46:06 +0530 Subject: [PATCH 4/5] feat(core): restrict modification of createdon and modifiedon gh-2158 --- packages/core/README.md | 21 +----- packages/core/src/component.ts | 4 + packages/core/src/keys.ts | 11 ++- ...ansactional-user-modify-repository.base.ts | 51 ++++--------- ...efault-user-modify-crud.repository.base.ts | 52 +++++-------- .../default-user-modify-crud.service.ts | 75 +++++++++++++++++++ packages/core/src/types.ts | 24 ++++-- 7 files changed, 140 insertions(+), 98 deletions(-) create mode 100644 packages/core/src/services/default-user-modify-crud.service.ts diff --git a/packages/core/README.md b/packages/core/README.md index f38f831c3c..42f46808a9 100644 --- a/packages/core/README.md +++ b/packages/core/README.md @@ -570,27 +570,10 @@ export class UserRepository extends DefaultUserModifyCrudRepository< ) ``` -The repository by default allows to pass back dated or future dates for createdOn and modifiedOn values but to restrict the manual date modification we can pass overridingOptions like this +The repository by default does not restrict setting up of createdOn and modifiedOn through API or external sources. However, you can restrict it by binding the restrictDateModification property to config like this ```ts -export class UsersRepository extends DefaultUserModifyCrudRepository< - Users, - typeof Users.prototype.id, - UsersRelations -> { - constructor( - @inject(`datasources.AuditDB`) dataSource: juggler.DataSource, - @inject.getter(AuthenticationBindings.CURRENT_USER) - protected readonly getCurrentUser: Getter< - IAuthUserWithPermissions | undefined - >, - ) { - super(Users, dataSource, getCurrentUser); - } - public overridingOptions = { - restrictDateModification: true, - }; -} +this.bind(SFCoreBindings.config).to({restrictDateModification: true}); ``` ![Connector](https://loopback.io/images/9830486.png) diff --git a/packages/core/src/component.ts b/packages/core/src/component.ts index 9a6117b67a..9f6c02a446 100644 --- a/packages/core/src/component.ts +++ b/packages/core/src/component.ts @@ -30,6 +30,7 @@ import {LocaleKey} from './enums'; import {OASBindings, SFCoreBindings} from './keys'; import {TenantContextMiddlewareInterceptorProvider} from './middlewares'; import {TenantIdEncryptionProvider} from './providers/tenantid-encryption.provider'; +import {DefaultUserModifyCrudService} from './services/default-user-modify-crud.service'; import {CoreConfig, addTenantId} from './types'; export class CoreComponent implements Component { @@ -100,6 +101,9 @@ export class CoreComponent implements Component { this.bindings.push(Binding.bind(OASBindings.HiddenEndpoint).to([])); this.bindings.push(Binding.bind(SFCoreBindings.i18n).to(this.localeObj)); this.application.add(createBindingFromClass(OperationSpecEnhancer)); + this.application + .bind(SFCoreBindings.DEFAULT_USER_MODIFY_CRUD_SERVICE) + .toClass(DefaultUserModifyCrudService); } private _setupSwaggerStats(): ExpressRequestHandler | undefined { diff --git a/packages/core/src/keys.ts b/packages/core/src/keys.ts index e5c94468a9..3440bf96b5 100644 --- a/packages/core/src/keys.ts +++ b/packages/core/src/keys.ts @@ -7,7 +7,12 @@ import {ExpressRequestHandler} from '@loopback/rest'; import {SetupDatasourceFn} from 'loopback4-dynamic-datasource'; import {BINDING_PREFIX} from './constants'; import {HttpMethod} from './enums'; -import {CoreConfig, TenantIdEncryptionFn} from './types'; +import {UserModifiableEntity} from './models'; +import { + CoreConfig, + IDefaultUserModifyCrud, + TenantIdEncryptionFn, +} from './types'; export namespace SFCoreBindings { export const i18n = BindingKey.create(`${BINDING_PREFIX}.i18n`); @@ -27,6 +32,10 @@ export namespace SFCoreBindings { BindingKey.create( `sf.packages.core.dynamicDatasourceMiddleware`, ); + + export const DEFAULT_USER_MODIFY_CRUD_SERVICE = BindingKey.create< + IDefaultUserModifyCrud + >(`${BINDING_PREFIX}.services.defaultUserModifyCrudService`); } const hiddenKey = 'sf.oas.hiddenEndpoints'; diff --git a/packages/core/src/repositories/default-transactional-user-modify-repository.base.ts b/packages/core/src/repositories/default-transactional-user-modify-repository.base.ts index bcd4f8dcfe..be28ff41e9 100644 --- a/packages/core/src/repositories/default-transactional-user-modify-repository.base.ts +++ b/packages/core/src/repositories/default-transactional-user-modify-repository.base.ts @@ -2,6 +2,7 @@ // // This software is released under the MIT License. // https://opensource.org/licenses/MIT +import {inject} from '@loopback/core'; import { Count, DataObject, @@ -15,8 +16,9 @@ import {Options} from 'loopback-datasource-juggler'; import {AuthErrorKeys} from 'loopback4-authentication'; import {DefaultTransactionSoftCrudRepository} from 'loopback4-soft-delete'; import {IAuthUserWithPermissions} from '../components'; +import {SFCoreBindings} from '../keys'; import {UserModifiableEntity} from '../models'; -import {RepositoryOverridingOptions} from '../types'; +import {IDefaultUserModifyCrud} from '../types'; export abstract class DefaultTransactionalUserModifyRepository< T extends UserModifiableEntity, @@ -35,7 +37,8 @@ export abstract class DefaultTransactionalUserModifyRepository< super(entityClass, dataSource); } - public overridingOptions?: RepositoryOverridingOptions; + @inject(SFCoreBindings.DEFAULT_USER_MODIFY_CRUD_SERVICE) + public defaultUserModifyCrudService: IDefaultUserModifyCrud; async create(entity: DataObject, options?: Options): Promise { let currentUser = await this.getCurrentUser(); @@ -46,10 +49,7 @@ export abstract class DefaultTransactionalUserModifyRepository< const uid = currentUser?.userTenantId ?? currentUser?.id; entity.createdBy = uid; entity.modifiedBy = uid; - if (this.overridingOptions?.restrictDateModification) { - delete entity.createdOn; - delete entity.modifiedOn; - } + entity = await this.defaultUserModifyCrudService.create(entity); return super.create(entity, options); } @@ -63,11 +63,8 @@ export abstract class DefaultTransactionalUserModifyRepository< entities.forEach(entity => { entity.createdBy = uid ?? ''; entity.modifiedBy = uid ?? ''; - if (this.overridingOptions?.restrictDateModification) { - delete entity.createdOn; - delete entity.modifiedOn; - } }); + entities = await this.defaultUserModifyCrudService.createAll(entities); return super.createAll(entities, options); } @@ -78,10 +75,7 @@ export abstract class DefaultTransactionalUserModifyRepository< } const uid = currentUser?.userTenantId ?? currentUser?.id; entity.modifiedBy = uid; - if (this.overridingOptions?.restrictDateModification) { - delete entity.createdOn; - delete entity.modifiedOn; - } + entity = await this.defaultUserModifyCrudService.save(entity); return super.save(entity, options); } @@ -92,11 +86,7 @@ export abstract class DefaultTransactionalUserModifyRepository< } const uid = currentUser?.userTenantId ?? currentUser?.id; entity.modifiedBy = uid; - if (this.overridingOptions?.restrictDateModification) { - /**not deleting the createdOn as it can be a use case where - * we want to update the modifiedOn but not the createdOn */ - delete entity.modifiedOn; - } + entity = await this.defaultUserModifyCrudService.update(entity); return super.update(entity, options); } @@ -112,12 +102,11 @@ export abstract class DefaultTransactionalUserModifyRepository< } const uid = currentUser?.userTenantId ?? currentUser?.id; data.modifiedBy = uid; - if (this.overridingOptions?.restrictDateModification) { - /**not deleting the createdOn as it can be a use case where - * we want to update the modifiedOn but not the createdOn */ - delete data.modifiedOn; - } - return super.updateAll(data, where, options); + const result = await this.defaultUserModifyCrudService.updateAll( + data, + where, + ); + return super.updateAll(result.data, result.where, options); } async updateById( @@ -132,11 +121,7 @@ export abstract class DefaultTransactionalUserModifyRepository< } const uid = currentUser?.userTenantId ?? currentUser?.id; data.modifiedBy = uid; - if (this.overridingOptions?.restrictDateModification) { - /**not deleting the createdOn as it can be a use case where - * we want to update the modifiedOn but not the createdOn */ - delete data.modifiedOn; - } + data = await this.defaultUserModifyCrudService.updateById(id, data); return super.updateById(id, data, options); } @@ -151,11 +136,7 @@ export abstract class DefaultTransactionalUserModifyRepository< } const uid = currentUser?.userTenantId ?? currentUser?.id; data.modifiedBy = uid; - if (this.overridingOptions?.restrictDateModification) { - /**not deleting the createdOn as it can be a use case where - * we want to update the modifiedOn but not the createdOn */ - delete data.modifiedOn; - } + data = await this.defaultUserModifyCrudService.replaceById(id, data); return super.replaceById(id, data, options); } } diff --git a/packages/core/src/repositories/default-user-modify-crud.repository.base.ts b/packages/core/src/repositories/default-user-modify-crud.repository.base.ts index d1dc6ae52c..e2d32bbd00 100644 --- a/packages/core/src/repositories/default-user-modify-crud.repository.base.ts +++ b/packages/core/src/repositories/default-user-modify-crud.repository.base.ts @@ -15,9 +15,11 @@ import {Options} from 'loopback-datasource-juggler'; import {AuthErrorKeys} from 'loopback4-authentication'; import {SoftCrudRepository} from 'loopback4-soft-delete'; +import {inject} from '@loopback/core'; import {IAuthUserWithPermissions} from '../components'; +import {SFCoreBindings} from '../keys'; import {UserModifiableEntity} from '../models'; -import {RepositoryOverridingOptions} from '../types'; +import {IDefaultUserModifyCrud} from '../types'; export class DefaultUserModifyCrudRepository< T extends UserModifiableEntity, @@ -35,7 +37,9 @@ export class DefaultUserModifyCrudRepository< ) { super(entityClass, dataSource); } - public overridingOptions?: RepositoryOverridingOptions; + + @inject(SFCoreBindings.DEFAULT_USER_MODIFY_CRUD_SERVICE) + public defaultUserModifyCrudService: IDefaultUserModifyCrud; async create(entity: DataObject, options?: Options): Promise { let currentUser = await this.getCurrentUser(); @@ -46,10 +50,7 @@ export class DefaultUserModifyCrudRepository< const uid = currentUser?.userTenantId ?? currentUser?.id; entity.createdBy = uid; entity.modifiedBy = uid; - if (this.overridingOptions?.restrictDateModification) { - delete entity.createdOn; - delete entity.modifiedOn; - } + entity = await this.defaultUserModifyCrudService.create(entity); return super.create(entity, options); } @@ -63,11 +64,8 @@ export class DefaultUserModifyCrudRepository< entities.forEach(entity => { entity.createdBy = uid ?? ''; entity.modifiedBy = uid ?? ''; - if (this.overridingOptions?.restrictDateModification) { - delete entity.createdOn; - delete entity.modifiedOn; - } }); + entities = await this.defaultUserModifyCrudService.createAll(entities); return super.createAll(entities, options); } @@ -78,10 +76,7 @@ export class DefaultUserModifyCrudRepository< } const uid = currentUser?.userTenantId ?? currentUser?.id; entity.modifiedBy = uid; - if (this.overridingOptions?.restrictDateModification) { - delete entity.createdOn; - delete entity.modifiedOn; - } + entity = await this.defaultUserModifyCrudService.save(entity); return super.save(entity, options); } @@ -92,11 +87,7 @@ export class DefaultUserModifyCrudRepository< } const uid = currentUser?.userTenantId ?? currentUser?.id; entity.modifiedBy = uid; - if (this.overridingOptions?.restrictDateModification) { - /**not deleting the createdOn as it can be a use case where - * we want to update the modifiedOn but not the createdOn */ - delete entity.modifiedOn; - } + entity = await this.defaultUserModifyCrudService.update(entity); return super.update(entity, options); } @@ -112,12 +103,11 @@ export class DefaultUserModifyCrudRepository< } const uid = currentUser?.userTenantId ?? currentUser?.id; data.modifiedBy = uid; - if (this.overridingOptions?.restrictDateModification) { - /**not deleting the createdOn as it can be a use case where - * we want to update the modifiedOn but not the createdOn */ - delete data.modifiedOn; - } - return super.updateAll(data, where, options); + const result = await this.defaultUserModifyCrudService.updateAll( + data, + where, + ); + return super.updateAll(result.data, result.where, options); } async updateById( @@ -132,11 +122,7 @@ export class DefaultUserModifyCrudRepository< } const uid = currentUser?.userTenantId ?? currentUser?.id; data.modifiedBy = uid; - if (this.overridingOptions?.restrictDateModification) { - /**not deleting the createdOn as it can be a use case where - * we want to update the modifiedOn but not the createdOn */ - delete data.modifiedOn; - } + data = await this.defaultUserModifyCrudService.updateById(id, data); return super.updateById(id, data, options); } async replaceById( @@ -150,11 +136,7 @@ export class DefaultUserModifyCrudRepository< } const uid = currentUser?.userTenantId ?? currentUser?.id; data.modifiedBy = uid; - if (this.overridingOptions?.restrictDateModification) { - /**not deleting the createdOn as it can be a use case where - * we want to update the modifiedOn but not the createdOn */ - delete data.modifiedOn; - } + data = await this.defaultUserModifyCrudService.replaceById(id, data); return super.replaceById(id, data, options); } } diff --git a/packages/core/src/services/default-user-modify-crud.service.ts b/packages/core/src/services/default-user-modify-crud.service.ts new file mode 100644 index 0000000000..5371f5bb2a --- /dev/null +++ b/packages/core/src/services/default-user-modify-crud.service.ts @@ -0,0 +1,75 @@ +import {BindingScope, inject, injectable} from '@loopback/core'; +import {DataObject, Where} from '@loopback/repository'; +import {SFCoreBindings} from '../keys'; +import {UserModifiableEntity} from '../models'; +import {CoreConfig, IDefaultUserModifyCrud} from '../types'; + +@injectable({scope: BindingScope.TRANSIENT}) +export class DefaultUserModifyCrudService + implements IDefaultUserModifyCrud +{ + constructor( + @inject(SFCoreBindings.config, {optional: true}) + private readonly coreConfig: CoreConfig, + ) {} + create(data: DataObject): Promise> { + if (this.coreConfig?.restrictDateModification) { + return this.removeDateFields(data); + } + return Promise.resolve(data); + } + createAll(data: DataObject[]): Promise[]> { + if (this.coreConfig?.restrictDateModification) { + data.forEach(d => { + delete d.createdOn; + delete d.modifiedOn; + }); + } + return Promise.resolve(data); + } + save(entity: T): Promise { + if (this.coreConfig?.restrictDateModification) { + return this.removeDateFields(entity); + } + return Promise.resolve(entity); + } + update(data: T): Promise { + if (this.coreConfig?.restrictDateModification) { + return this.removeDateFields(data); + } + return Promise.resolve(data); + } + + updateAll( + data: DataObject, + where?: Where, + ): Promise<{data: DataObject; where: Where}> { + if (this.coreConfig?.restrictDateModification) { + return this.removeDateFields(data).then(d => ({ + data: d, + where: where || ({} as Where), + })); + } + return Promise.resolve({data, where: where || ({} as Where)}); + } + updateById(id: ID, data: DataObject): Promise> { + if (this.coreConfig?.restrictDateModification) { + return this.removeDateFields(data); + } + return Promise.resolve(data); + } + replaceById(id: ID, data: DataObject): Promise> { + if (this.coreConfig?.restrictDateModification) { + return this.removeDateFields(data); + } + return Promise.resolve(data); + } + + private async removeDateFields | T>( + data: S, + ): Promise { + delete data.createdOn; + delete data.modifiedOn; + return data; + } +} diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index 7cd5cf77ac..f621a082b9 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -3,23 +3,17 @@ // This software is released under the MIT License. // https://opensource.org/licenses/MIT +import {DataObject, Where} from '@loopback/repository'; import CryptoJS from 'crypto-js'; import {IncomingMessage, ServerResponse} from 'http'; import {AnyObject} from 'loopback-datasource-juggler'; import {SWStats} from 'swagger-stats'; +import {UserModifiableEntity} from './models'; export interface IServiceConfig { useCustomSequence: boolean; useSequelize?: boolean; } -/**This type is used to override the default behaviour of our repo classes */ -export interface RepositoryOverridingOptions { - /**restricts user to pass createdOn and modifiedOn fields in the request body - * and only current date will be set in the database */ - restrictDateModification: boolean; - //eslint-disable-next-line @typescript-eslint/no-explicit-any - [property: string]: any; //NOSONAR -} export type OASPathDefinition = AnyObject; export interface CoreConfig { @@ -59,6 +53,7 @@ export interface CoreConfig { username?: string, password?: string, ) => boolean; + restrictDateModification?: boolean; } /** @@ -95,3 +90,16 @@ export type TenantIdEncryptionFn = ( secretKey: string, tenantId: string, ) => Promise; + +export interface IDefaultUserModifyCrud { + create(data: DataObject): Promise>; + createAll(data: DataObject[]): Promise[]>; + save(entity: T): Promise; + update(data: T): Promise; + updateAll( + data: DataObject, + where?: Where, + ): Promise<{data: DataObject; where: Where}>; + updateById(id: ID, data: DataObject): Promise>; + replaceById(id: ID, data: DataObject): Promise>; +} From 091897b939e6ea3e2df40c336172b6d286aa0bd2 Mon Sep 17 00:00:00 2001 From: Yesha Mavani Date: Mon, 28 Oct 2024 20:05:51 +0530 Subject: [PATCH 5/5] chore(core): lint issues gh-2158 --- .../core/src/services/default-user-modify-crud.service.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/core/src/services/default-user-modify-crud.service.ts b/packages/core/src/services/default-user-modify-crud.service.ts index 5371f5bb2a..8ca33be2d0 100644 --- a/packages/core/src/services/default-user-modify-crud.service.ts +++ b/packages/core/src/services/default-user-modify-crud.service.ts @@ -47,10 +47,10 @@ export class DefaultUserModifyCrudService if (this.coreConfig?.restrictDateModification) { return this.removeDateFields(data).then(d => ({ data: d, - where: where || ({} as Where), + where: where ?? ({} as Where), })); } - return Promise.resolve({data, where: where || ({} as Where)}); + return Promise.resolve({data, where: where ?? ({} as Where)}); } updateById(id: ID, data: DataObject): Promise> { if (this.coreConfig?.restrictDateModification) {