diff --git a/backend/core/src/main/java/org/opencdmp/service/description/DescriptionServiceImpl.java b/backend/core/src/main/java/org/opencdmp/service/description/DescriptionServiceImpl.java index 8cbad3d8d..c62f50880 100644 --- a/backend/core/src/main/java/org/opencdmp/service/description/DescriptionServiceImpl.java +++ b/backend/core/src/main/java/org/opencdmp/service/description/DescriptionServiceImpl.java @@ -70,6 +70,7 @@ import org.opencdmp.model.planblueprint.PlanBlueprint; import org.opencdmp.model.reference.Reference; import org.opencdmp.model.referencetype.ReferenceType; import org.opencdmp.query.*; +import org.opencdmp.service.accounting.AccountingService; import org.opencdmp.service.descriptiontemplate.DescriptionTemplateService; import org.opencdmp.service.elastic.ElasticService; import org.opencdmp.service.filetransformer.FileTransformerService; @@ -77,6 +78,7 @@ import org.opencdmp.service.responseutils.ResponseUtilsService; import org.opencdmp.service.storage.StorageFileProperties; import org.opencdmp.service.storage.StorageFileService; import org.opencdmp.service.tag.TagService; +import org.opencdmp.service.usagelimit.UsageLimitService; import org.opencdmp.service.visibility.VisibilityService; import org.opencdmp.service.visibility.VisibilityServiceImpl; import org.slf4j.LoggerFactory; @@ -138,21 +140,23 @@ public class DescriptionServiceImpl implements DescriptionService { private final ResponseUtilsService responseUtilsService; private final DescriptionTemplateService descriptionTemplateService; private final TagService tagService; + private final UsageLimitService usageLimitService; + private final AccountingService accountingService; @Autowired public DescriptionServiceImpl( - TenantEntityManager entityManager, - AuthorizationService authorizationService, - DeleterFactory deleterFactory, - BuilderFactory builderFactory, - ConventionService conventionService, - ErrorThesaurusProperties errors, - MessageSource messageSource, - EventBroker eventBroker, - QueryFactory queryFactory, - JsonHandlingService jsonHandlingService, - UserScope userScope, - XmlHandlingService xmlHandlingService, NotifyIntegrationEventHandler eventHandler, NotificationProperties notificationProperties, FileTransformerService fileTransformerService, ElasticService elasticService, ValidatorFactory validatorFactory, StorageFileProperties storageFileConfig, StorageFileService storageFileService, AuthorizationContentResolver authorizationContentResolver, AnnotationEntityTouchedIntegrationEventHandler annotationEntityTouchedIntegrationEventHandler, AnnotationEntityRemovalIntegrationEventHandler annotationEntityRemovalIntegrationEventHandler, TenantScope tenantScope, ResponseUtilsService responseUtilsService, DescriptionTemplateService descriptionTemplateService, TagService tagService) { + TenantEntityManager entityManager, + AuthorizationService authorizationService, + DeleterFactory deleterFactory, + BuilderFactory builderFactory, + ConventionService conventionService, + ErrorThesaurusProperties errors, + MessageSource messageSource, + EventBroker eventBroker, + QueryFactory queryFactory, + JsonHandlingService jsonHandlingService, + UserScope userScope, + XmlHandlingService xmlHandlingService, NotifyIntegrationEventHandler eventHandler, NotificationProperties notificationProperties, FileTransformerService fileTransformerService, ElasticService elasticService, ValidatorFactory validatorFactory, StorageFileProperties storageFileConfig, StorageFileService storageFileService, AuthorizationContentResolver authorizationContentResolver, AnnotationEntityTouchedIntegrationEventHandler annotationEntityTouchedIntegrationEventHandler, AnnotationEntityRemovalIntegrationEventHandler annotationEntityRemovalIntegrationEventHandler, TenantScope tenantScope, ResponseUtilsService responseUtilsService, DescriptionTemplateService descriptionTemplateService, TagService tagService, UsageLimitService usageLimitService, AccountingService accountingService) { this.entityManager = entityManager; this.authorizationService = authorizationService; this.deleterFactory = deleterFactory; @@ -179,6 +183,8 @@ public class DescriptionServiceImpl implements DescriptionService { this.responseUtilsService = responseUtilsService; this.descriptionTemplateService = descriptionTemplateService; this.tagService = tagService; + this.usageLimitService = usageLimitService; + this.accountingService = accountingService; } @Override @@ -222,7 +228,7 @@ public class DescriptionServiceImpl implements DescriptionService { if (!data.getPlanId().equals(model.getPlanId())) throw new MyValidationException(this.errors.getPlanCanNotChange().getCode(), this.errors.getPlanCanNotChange().getMessage()); if (!data.getPlanDescriptionTemplateId().equals(model.getPlanDescriptionTemplateId())) throw new MyValidationException(this.errors.getPlanDescriptionTemplateCanNotChange().getCode(), this.errors.getPlanDescriptionTemplateCanNotChange().getMessage()); } else { - //this.usageLimitService.checkIncrease("description_count"); + this.usageLimitService.checkIncrease(UsageLimitTargetMetric.DESCRIPTION_COUNT); PlanEntity planEntity = this.entityManager.find(PlanEntity.class, model.getPlanId(), true); if (planEntity == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{model.getPlanId(), Plan.class.getSimpleName()}, LocaleContextHolder.getLocale())); @@ -258,7 +264,10 @@ public class DescriptionServiceImpl implements DescriptionService { data.setDescriptionTemplateId(model.getDescriptionTemplateId()); data.setUpdatedAt(Instant.now()); if (isUpdate) this.entityManager.merge(data); - else this.entityManager.persist(data); + else { + this.entityManager.persist(data); + this.accountingService.increase(UsageLimitTargetMetric.DESCRIPTION_COUNT); + } this.entityManager.flush(); @@ -892,6 +901,7 @@ public class DescriptionServiceImpl implements DescriptionService { this.deleterFactory.deleter(DescriptionDeleter.class).deleteAndSaveByIds(List.of(id), false); this.annotationEntityRemovalIntegrationEventHandler.handleDescription(id); + this.accountingService.decrease(UsageLimitTargetMetric.DESCRIPTION_COUNT); } //endregion diff --git a/backend/core/src/main/java/org/opencdmp/service/descriptiontemplate/DescriptionTemplateServiceImpl.java b/backend/core/src/main/java/org/opencdmp/service/descriptiontemplate/DescriptionTemplateServiceImpl.java index 6718c6787..1b5f22fac 100644 --- a/backend/core/src/main/java/org/opencdmp/service/descriptiontemplate/DescriptionTemplateServiceImpl.java +++ b/backend/core/src/main/java/org/opencdmp/service/descriptiontemplate/DescriptionTemplateServiceImpl.java @@ -58,10 +58,12 @@ import org.opencdmp.model.user.User; import org.opencdmp.query.DescriptionTemplateQuery; import org.opencdmp.query.DescriptionTemplateTypeQuery; import org.opencdmp.query.UserDescriptionTemplateQuery; +import org.opencdmp.service.accounting.AccountingService; import org.opencdmp.service.descriptiontemplatetype.DescriptionTemplateTypeService; import org.opencdmp.service.fielddatahelper.FieldDataHelperService; import org.opencdmp.service.fielddatahelper.FieldDataHelperServiceProvider; import org.opencdmp.service.responseutils.ResponseUtilsService; +import org.opencdmp.service.usagelimit.UsageLimitService; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.MessageSource; @@ -120,24 +122,26 @@ public class DescriptionTemplateServiceImpl implements DescriptionTemplateServic private final ValidatorFactory validatorFactory; private final DescriptionTemplateTypeService descriptionTemplateTypeService; private final AuthorizationContentResolver authorizationContentResolver; + private final UsageLimitService usageLimitService; + private final AccountingService accountingService; @Autowired public DescriptionTemplateServiceImpl( - TenantEntityManager entityManager, - UserScope userScope, AuthorizationService authorizationService, - DeleterFactory deleterFactory, - BuilderFactory builderFactory, - ConventionService conventionService, - MessageSource messageSource, - XmlHandlingService xmlHandlingService, - FieldDataHelperServiceProvider fieldDataHelperServiceProvider, - QueryFactory queryFactory, ErrorThesaurusProperties errors, - TenantScope tenantScope, - ResponseUtilsService responseUtilsService, - JsonHandlingService jsonHandlingService, - NotifyIntegrationEventHandler eventHandler, - NotificationProperties notificationProperties, - ValidatorFactory validatorFactory, DescriptionTemplateTypeService descriptionTemplateTypeService, AuthorizationContentResolver authorizationContentResolver) { + TenantEntityManager entityManager, + UserScope userScope, AuthorizationService authorizationService, + DeleterFactory deleterFactory, + BuilderFactory builderFactory, + ConventionService conventionService, + MessageSource messageSource, + XmlHandlingService xmlHandlingService, + FieldDataHelperServiceProvider fieldDataHelperServiceProvider, + QueryFactory queryFactory, ErrorThesaurusProperties errors, + TenantScope tenantScope, + ResponseUtilsService responseUtilsService, + JsonHandlingService jsonHandlingService, + NotifyIntegrationEventHandler eventHandler, + NotificationProperties notificationProperties, + ValidatorFactory validatorFactory, DescriptionTemplateTypeService descriptionTemplateTypeService, AuthorizationContentResolver authorizationContentResolver, UsageLimitService usageLimitService, AccountingService accountingService) { this.entityManager = entityManager; this.userScope = userScope; this.authorizationService = authorizationService; @@ -157,6 +161,8 @@ public class DescriptionTemplateServiceImpl implements DescriptionTemplateServic this.validatorFactory = validatorFactory; this.descriptionTemplateTypeService = descriptionTemplateTypeService; this.authorizationContentResolver = authorizationContentResolver; + this.usageLimitService = usageLimitService; + this.accountingService = accountingService; } //region Persist @@ -178,6 +184,8 @@ public class DescriptionTemplateServiceImpl implements DescriptionTemplateServic if (data.getStatus().equals(DescriptionTemplateStatus.Finalized)) throw new MyForbiddenException("Can not update finalized template"); } else { + this.usageLimitService.checkIncrease(UsageLimitTargetMetric.DESCRIPTION_TEMPLATE_COUNT); + data = new DescriptionTemplateEntity(); data.setId(UUID.randomUUID()); data.setStatus(DescriptionTemplateStatus.Draft); @@ -206,8 +214,10 @@ public class DescriptionTemplateServiceImpl implements DescriptionTemplateServic data.setDefinition(this.xmlHandlingService.toXml(this.buildDefinitionEntity(model.getDefinition()))); if (isUpdate) this.entityManager.merge(data); - else + else { this.entityManager.persist(data); + this.accountingService.increase(UsageLimitTargetMetric.DESCRIPTION_TEMPLATE_COUNT); + } this.persistUsers(data.getId(), model.getUsers()); @@ -519,6 +529,7 @@ public class DescriptionTemplateServiceImpl implements DescriptionTemplateServic } this.deleterFactory.deleter(DescriptionTemplateDeleter.class).deleteAndSaveByIds(List.of(id)); + this.accountingService.decrease(UsageLimitTargetMetric.DESCRIPTION_TEMPLATE_COUNT); } //endregion diff --git a/backend/core/src/main/java/org/opencdmp/service/plan/PlanServiceImpl.java b/backend/core/src/main/java/org/opencdmp/service/plan/PlanServiceImpl.java index f4ef70fb6..1b81f6cf9 100644 --- a/backend/core/src/main/java/org/opencdmp/service/plan/PlanServiceImpl.java +++ b/backend/core/src/main/java/org/opencdmp/service/plan/PlanServiceImpl.java @@ -71,7 +71,6 @@ import org.opencdmp.integrationevent.outbox.notification.NotifyIntegrationEvent; import org.opencdmp.integrationevent.outbox.notification.NotifyIntegrationEventHandler; import org.opencdmp.model.PlanUser; import org.opencdmp.model.PlanValidationResult; -import org.opencdmp.model.PublicPlan; import org.opencdmp.model.builder.PlanUserBuilder; import org.opencdmp.model.builder.description.DescriptionBuilder; import org.opencdmp.model.builder.plan.PlanBuilder; @@ -92,8 +91,8 @@ import org.opencdmp.model.planblueprint.PlanBlueprint; import org.opencdmp.model.planreference.PlanReferenceData; import org.opencdmp.model.reference.Reference; import org.opencdmp.model.referencetype.ReferenceType; -import org.opencdmp.model.result.QueryResult; import org.opencdmp.query.*; +import org.opencdmp.service.accounting.AccountingService; import org.opencdmp.service.actionconfirmation.ActionConfirmationService; import org.opencdmp.service.description.DescriptionService; import org.opencdmp.service.descriptiontemplate.DescriptionTemplateService; @@ -101,6 +100,7 @@ import org.opencdmp.service.elastic.ElasticService; import org.opencdmp.service.filetransformer.FileTransformerService; import org.opencdmp.service.planblueprint.PlanBlueprintService; import org.opencdmp.service.responseutils.ResponseUtilsService; +import org.opencdmp.service.usagelimit.UsageLimitService; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.MessageSource; @@ -127,8 +127,6 @@ import java.time.Instant; import java.util.*; import java.util.stream.Collectors; -import static org.opencdmp.authorization.AuthorizationFlags.Public; - @Service public class PlanServiceImpl implements PlanService { @@ -179,29 +177,31 @@ public class PlanServiceImpl implements PlanService { private final TenantScope tenantScope; private final ResponseUtilsService responseUtilsService; private final PlanBlueprintService planBlueprintService; + private final UsageLimitService usageLimitService; + private final AccountingService accountingService; @Autowired public PlanServiceImpl( - TenantEntityManager entityManager, - AuthorizationService authorizationService, - DeleterFactory deleterFactory, - BuilderFactory builderFactory, - QueryFactory queryFactory, - ConventionService conventionService, - ErrorThesaurusProperties errors, - MessageSource messageSource, - XmlHandlingService xmlHandlingService, - JsonHandlingService jsonHandlingService, - UserScope userScope, - EventBroker eventBroker, - DescriptionService descriptionService, - NotifyIntegrationEventHandler eventHandler, - NotificationProperties notificationProperties, - ActionConfirmationService actionConfirmationService, - FileTransformerService fileTransformerService, - ValidatorFactory validatorFactory, - ElasticService elasticService, DescriptionTemplateService descriptionTemplateService, - AnnotationEntityTouchedIntegrationEventHandler annotationEntityTouchedIntegrationEventHandler, AnnotationEntityRemovalIntegrationEventHandler annotationEntityRemovalIntegrationEventHandler, AuthorizationContentResolver authorizationContentResolver, TenantScope tenantScope, ResponseUtilsService responseUtilsService, PlanBlueprintService planBlueprintService) { + TenantEntityManager entityManager, + AuthorizationService authorizationService, + DeleterFactory deleterFactory, + BuilderFactory builderFactory, + QueryFactory queryFactory, + ConventionService conventionService, + ErrorThesaurusProperties errors, + MessageSource messageSource, + XmlHandlingService xmlHandlingService, + JsonHandlingService jsonHandlingService, + UserScope userScope, + EventBroker eventBroker, + DescriptionService descriptionService, + NotifyIntegrationEventHandler eventHandler, + NotificationProperties notificationProperties, + ActionConfirmationService actionConfirmationService, + FileTransformerService fileTransformerService, + ValidatorFactory validatorFactory, + ElasticService elasticService, DescriptionTemplateService descriptionTemplateService, + AnnotationEntityTouchedIntegrationEventHandler annotationEntityTouchedIntegrationEventHandler, AnnotationEntityRemovalIntegrationEventHandler annotationEntityRemovalIntegrationEventHandler, AuthorizationContentResolver authorizationContentResolver, TenantScope tenantScope, ResponseUtilsService responseUtilsService, PlanBlueprintService planBlueprintService, UsageLimitService usageLimitService, AccountingService accountingService) { this.entityManager = entityManager; this.authorizationService = authorizationService; this.deleterFactory = deleterFactory; @@ -228,13 +228,18 @@ public class PlanServiceImpl implements PlanService { this.tenantScope = tenantScope; this.responseUtilsService = responseUtilsService; this.planBlueprintService = planBlueprintService; + this.usageLimitService = usageLimitService; + this.accountingService = accountingService; } public Plan persist(PlanPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException, JAXBException, IOException { Boolean isUpdate = this.conventionService.isValidGuid(model.getId()); if (isUpdate) this.authorizationService.authorizeAtLeastOneForce(List.of(this.authorizationContentResolver.planAffiliation(model.getId())), Permission.EditPlan); - else this.authorizationService.authorizeForce(Permission.NewPlan); + else { + this.authorizationService.authorizeForce(Permission.NewPlan); + this.usageLimitService.checkIncrease(UsageLimitTargetMetric.PLAN_COUNT); + } PlanEntity data = this.patchAndSave(model); @@ -384,6 +389,7 @@ public class PlanServiceImpl implements PlanService { if (previousPlan != null) this.elasticService.persistPlan(previousPlan); this.annotationEntityRemovalIntegrationEventHandler.handlePlan(data.getId()); + this.accountingService.decrease(UsageLimitTargetMetric.PLAN_COUNT); } @Override @@ -931,6 +937,7 @@ public class PlanServiceImpl implements PlanService { this.entityManager.merge(data); else { this.entityManager.persist(data); + this.accountingService.increase(UsageLimitTargetMetric.PLAN_COUNT); } this.entityManager.flush(); diff --git a/backend/core/src/main/java/org/opencdmp/service/planblueprint/PlanBlueprintServiceImpl.java b/backend/core/src/main/java/org/opencdmp/service/planblueprint/PlanBlueprintServiceImpl.java index bd8b8abd7..9b61c80ad 100644 --- a/backend/core/src/main/java/org/opencdmp/service/planblueprint/PlanBlueprintServiceImpl.java +++ b/backend/core/src/main/java/org/opencdmp/service/planblueprint/PlanBlueprintServiceImpl.java @@ -46,7 +46,9 @@ import org.opencdmp.query.DescriptionTemplateQuery; import org.opencdmp.query.PlanBlueprintQuery; import org.opencdmp.query.PrefillingSourceQuery; import org.opencdmp.query.ReferenceTypeQuery; +import org.opencdmp.service.accounting.AccountingService; import org.opencdmp.service.responseutils.ResponseUtilsService; +import org.opencdmp.service.usagelimit.UsageLimitService; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.MessageSource; @@ -90,18 +92,21 @@ public class PlanBlueprintServiceImpl implements PlanBlueprintService { private final ValidatorFactory validatorFactory; private final TenantScope tenantScope; + + private final UsageLimitService usageLimitService; + private final AccountingService accountingService; @Autowired public PlanBlueprintServiceImpl( - TenantEntityManager entityManager, - AuthorizationService authorizationService, - DeleterFactory deleterFactory, - BuilderFactory builderFactory, - ConventionService conventionService, - MessageSource messageSource, QueryFactory queryFactory, - ResponseUtilsService responseUtilsService, - XmlHandlingService xmlHandlingService, - ErrorThesaurusProperties errors, - ValidatorFactory validatorFactory, TenantScope tenantScope) { + TenantEntityManager entityManager, + AuthorizationService authorizationService, + DeleterFactory deleterFactory, + BuilderFactory builderFactory, + ConventionService conventionService, + MessageSource messageSource, QueryFactory queryFactory, + ResponseUtilsService responseUtilsService, + XmlHandlingService xmlHandlingService, + ErrorThesaurusProperties errors, + ValidatorFactory validatorFactory, TenantScope tenantScope, UsageLimitService usageLimitService, AccountingService accountingService) { this.entityManager = entityManager; this.authorizationService = authorizationService; this.deleterFactory = deleterFactory; @@ -114,6 +119,8 @@ public class PlanBlueprintServiceImpl implements PlanBlueprintService { this.errors = errors; this.validatorFactory = validatorFactory; this.tenantScope = tenantScope; + this.usageLimitService = usageLimitService; + this.accountingService = accountingService; } //region Persist @@ -135,6 +142,7 @@ public class PlanBlueprintServiceImpl implements PlanBlueprintService { if (data.getStatus().equals(PlanBlueprintStatus.Finalized)) throw new MyForbiddenException("Cannot update finalized blueprint"); } else { + this.usageLimitService.checkIncrease(UsageLimitTargetMetric.BLUEPRINT_COUNT); data = new PlanBlueprintEntity(); data.setId(UUID.randomUUID()); data.setStatus(PlanBlueprintStatus.Draft); @@ -164,8 +172,10 @@ public class PlanBlueprintServiceImpl implements PlanBlueprintService { if (isUpdate) this.entityManager.merge(data); - else + else{ this.entityManager.persist(data); + this.accountingService.increase(UsageLimitTargetMetric.BLUEPRINT_COUNT); + } this.entityManager.flush(); @@ -308,6 +318,7 @@ public class PlanBlueprintServiceImpl implements PlanBlueprintService { this.authorizationService.authorizeForce(Permission.DeletePlanBlueprint); this.deleterFactory.deleter(PlanBlueprintDeleter.class).deleteAndSaveByIds(List.of(id)); + this.accountingService.decrease(UsageLimitTargetMetric.BLUEPRINT_COUNT); } //endregion diff --git a/backend/core/src/main/java/org/opencdmp/service/prefillingsource/PrefillingSourceServiceImpl.java b/backend/core/src/main/java/org/opencdmp/service/prefillingsource/PrefillingSourceServiceImpl.java index 4d63d2833..b803fbe8f 100644 --- a/backend/core/src/main/java/org/opencdmp/service/prefillingsource/PrefillingSourceServiceImpl.java +++ b/backend/core/src/main/java/org/opencdmp/service/prefillingsource/PrefillingSourceServiceImpl.java @@ -20,6 +20,7 @@ import org.opencdmp.authorization.Permission; import org.opencdmp.commons.JsonHandlingService; import org.opencdmp.commons.XmlHandlingService; import org.opencdmp.commons.enums.IsActive; +import org.opencdmp.commons.enums.UsageLimitTargetMetric; import org.opencdmp.commons.types.descriptiontemplate.DefinitionEntity; import org.opencdmp.commons.types.descriptiontemplate.FieldEntity; import org.opencdmp.commons.types.descriptiontemplate.FieldSetEntity; @@ -60,10 +61,12 @@ import org.opencdmp.model.referencetype.ReferenceType; import org.opencdmp.query.PrefillingSourceQuery; import org.opencdmp.query.TagQuery; import org.opencdmp.query.lookup.ReferenceSearchLookup; +import org.opencdmp.service.accounting.AccountingService; import org.opencdmp.service.externalfetcher.ExternalFetcherService; import org.opencdmp.service.externalfetcher.criteria.ExternalReferenceCriteria; import org.opencdmp.service.externalfetcher.models.ExternalDataResult; import org.opencdmp.service.reference.ReferenceService; +import org.opencdmp.service.usagelimit.UsageLimitService; import org.slf4j.LoggerFactory; import org.springframework.context.MessageSource; import org.springframework.context.i18n.LocaleContextHolder; @@ -99,13 +102,15 @@ public class PrefillingSourceServiceImpl implements PrefillingSourceService { private final ErrorThesaurusProperties errors; private final JsonHandlingService jsonHandlingService; private final ReferenceService referenceService; + private final UsageLimitService usageLimitService; + private final AccountingService accountingService; private static final String Zenodo = "Zenodo"; public PrefillingSourceServiceImpl( TenantEntityManager entityManager, AuthorizationService authorizationService, DeleterFactory deleterFactory, BuilderFactory builderFactory, - QueryFactory queryFactory, ConventionService conventionService, MessageSource messageSource, - XmlHandlingService xmlHandlingService, ExternalFetcherService externalFetcherService, ErrorThesaurusProperties errors, JsonHandlingService jsonHandlingService, ReferenceService referenceService) { + QueryFactory queryFactory, ConventionService conventionService, MessageSource messageSource, + XmlHandlingService xmlHandlingService, ExternalFetcherService externalFetcherService, ErrorThesaurusProperties errors, JsonHandlingService jsonHandlingService, ReferenceService referenceService, UsageLimitService usageLimitService, AccountingService accountingService) { this.entityManager = entityManager; this.authorizationService = authorizationService; this.deleterFactory = deleterFactory; @@ -118,6 +123,8 @@ public class PrefillingSourceServiceImpl implements PrefillingSourceService { this.errors = errors; this.jsonHandlingService = jsonHandlingService; this.referenceService = referenceService; + this.usageLimitService = usageLimitService; + this.accountingService = accountingService; } @@ -135,6 +142,7 @@ public class PrefillingSourceServiceImpl implements PrefillingSourceService { throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{model.getId(), PrefillingSource.class.getSimpleName()}, LocaleContextHolder.getLocale())); if (!this.conventionService.hashValue(data.getUpdatedAt()).equals(model.getHash())) throw new MyValidationException(this.errors.getHashConflict().getCode(), this.errors.getHashConflict().getMessage()); } else { + this.usageLimitService.checkIncrease(UsageLimitTargetMetric.PREFILLING_SOURCES_COUNT); data = new PrefillingSourceEntity(); data.setId(UUID.randomUUID()); @@ -148,7 +156,10 @@ public class PrefillingSourceServiceImpl implements PrefillingSourceService { data.setUpdatedAt(Instant.now()); if (isUpdate) this.entityManager.merge(data); - else this.entityManager.persist(data); + else { + this.entityManager.persist(data); + this.accountingService.increase(UsageLimitTargetMetric.PREFILLING_SOURCES_COUNT); + } this.entityManager.flush(); @@ -318,6 +329,7 @@ public class PrefillingSourceServiceImpl implements PrefillingSourceService { this.authorizationService.authorizeForce(Permission.DeletePrefillingSource); this.deleterFactory.deleter(PrefillingSourceDeleter.class).deleteAndSaveByIds(List.of(id)); + this.accountingService.decrease(UsageLimitTargetMetric.PREFILLING_SOURCES_COUNT); } public List searchPrefillings(PrefillingSearchRequest model) { diff --git a/backend/core/src/main/java/org/opencdmp/service/referencetype/ReferenceTypeServiceImpl.java b/backend/core/src/main/java/org/opencdmp/service/referencetype/ReferenceTypeServiceImpl.java index 7ac2b5553..d74266fd4 100644 --- a/backend/core/src/main/java/org/opencdmp/service/referencetype/ReferenceTypeServiceImpl.java +++ b/backend/core/src/main/java/org/opencdmp/service/referencetype/ReferenceTypeServiceImpl.java @@ -19,6 +19,7 @@ import org.opencdmp.authorization.Permission; import org.opencdmp.commons.XmlHandlingService; import org.opencdmp.commons.enums.ExternalFetcherSourceType; import org.opencdmp.commons.enums.IsActive; +import org.opencdmp.commons.enums.UsageLimitTargetMetric; import org.opencdmp.commons.types.externalfetcher.*; import org.opencdmp.commons.types.referencetype.ReferenceTypeDefinitionEntity; import org.opencdmp.commons.types.referencetype.ReferenceTypeFieldEntity; @@ -34,6 +35,8 @@ import org.opencdmp.model.persist.referencetypedefinition.ReferenceTypeDefinitio import org.opencdmp.model.persist.referencetypedefinition.ReferenceTypeFieldPersist; import org.opencdmp.model.referencetype.ReferenceType; import org.opencdmp.query.ReferenceTypeQuery; +import org.opencdmp.service.accounting.AccountingService; +import org.opencdmp.service.usagelimit.UsageLimitService; import org.slf4j.LoggerFactory; import org.springframework.context.MessageSource; import org.springframework.context.i18n.LocaleContextHolder; @@ -59,11 +62,13 @@ public class ReferenceTypeServiceImpl implements ReferenceTypeService { private final XmlHandlingService xmlHandlingService; private final ErrorThesaurusProperties errors; private final QueryFactory queryFactory; + private final UsageLimitService usageLimitService; + private final AccountingService accountingService; public ReferenceTypeServiceImpl( - TenantEntityManager entityManager, AuthorizationService authorizationService, DeleterFactory deleterFactory, BuilderFactory builderFactory, - ConventionService conventionService, MessageSource messageSource, - XmlHandlingService xmlHandlingService, ErrorThesaurusProperties errors, QueryFactory queryFactory) { + TenantEntityManager entityManager, AuthorizationService authorizationService, DeleterFactory deleterFactory, BuilderFactory builderFactory, + ConventionService conventionService, MessageSource messageSource, + XmlHandlingService xmlHandlingService, ErrorThesaurusProperties errors, QueryFactory queryFactory, UsageLimitService usageLimitService, AccountingService accountingService) { this.entityManager = entityManager; this.authorizationService = authorizationService; this.deleterFactory = deleterFactory; @@ -73,6 +78,8 @@ public class ReferenceTypeServiceImpl implements ReferenceTypeService { this.xmlHandlingService = xmlHandlingService; this.errors = errors; this.queryFactory = queryFactory; + this.usageLimitService = usageLimitService; + this.accountingService = accountingService; } @@ -90,6 +97,7 @@ public class ReferenceTypeServiceImpl implements ReferenceTypeService { throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{model.getId(), ReferenceType.class.getSimpleName()}, LocaleContextHolder.getLocale())); if (!this.conventionService.hashValue(data.getUpdatedAt()).equals(model.getHash())) throw new MyValidationException(this.errors.getHashConflict().getCode(), this.errors.getHashConflict().getMessage()); } else { + this.usageLimitService.checkIncrease(UsageLimitTargetMetric.REFERENCE_TYPE_COUNT); data = new ReferenceTypeEntity(); data.setId(UUID.randomUUID()); @@ -103,7 +111,10 @@ public class ReferenceTypeServiceImpl implements ReferenceTypeService { data.setUpdatedAt(Instant.now()); if (isUpdate) this.entityManager.merge(data); - else this.entityManager.persist(data); + else { + this.entityManager.persist(data); + this.accountingService.increase(UsageLimitTargetMetric.REFERENCE_TYPE_COUNT); + } this.entityManager.flush(); @@ -295,5 +306,6 @@ public class ReferenceTypeServiceImpl implements ReferenceTypeService { this.authorizationService.authorizeForce(Permission.DeleteReferenceType); this.deleterFactory.deleter(ReferenceTypeDeleter.class).deleteAndSaveByIds(List.of(id)); + this.accountingService.decrease(UsageLimitTargetMetric.REFERENCE_TYPE_COUNT); } } diff --git a/backend/core/src/main/java/org/opencdmp/service/usagelimit/UsageLimitConfiguration.java b/backend/core/src/main/java/org/opencdmp/service/usagelimit/UsageLimitConfiguration.java new file mode 100644 index 000000000..3aabf609b --- /dev/null +++ b/backend/core/src/main/java/org/opencdmp/service/usagelimit/UsageLimitConfiguration.java @@ -0,0 +1,20 @@ +package org.opencdmp.service.usagelimit; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +@Configuration +@EnableConfigurationProperties(UsageLimitProperties.class) +public class UsageLimitConfiguration { + private final UsageLimitProperties properties; + + @Autowired + public UsageLimitConfiguration(UsageLimitProperties properties) { + this.properties = properties; + } + + public UsageLimitProperties getProperties() { + return this.properties; + } +} diff --git a/backend/core/src/main/java/org/opencdmp/service/usagelimit/UsageLimitProperties.java b/backend/core/src/main/java/org/opencdmp/service/usagelimit/UsageLimitProperties.java new file mode 100644 index 000000000..2ab576ad2 --- /dev/null +++ b/backend/core/src/main/java/org/opencdmp/service/usagelimit/UsageLimitProperties.java @@ -0,0 +1,16 @@ +package org.opencdmp.service.usagelimit; + +import org.springframework.boot.context.properties.ConfigurationProperties; + +@ConfigurationProperties(prefix = "usage-limits") +public class UsageLimitProperties { + private Boolean enabled; + + public Boolean getEnabled() { + return enabled; + } + + public void setEnabled(Boolean enabled) { + this.enabled = enabled; + } +} diff --git a/backend/core/src/main/java/org/opencdmp/service/usagelimit/UsageLimitServiceImpl.java b/backend/core/src/main/java/org/opencdmp/service/usagelimit/UsageLimitServiceImpl.java index c55cd5725..552f427cc 100644 --- a/backend/core/src/main/java/org/opencdmp/service/usagelimit/UsageLimitServiceImpl.java +++ b/backend/core/src/main/java/org/opencdmp/service/usagelimit/UsageLimitServiceImpl.java @@ -64,6 +64,8 @@ public class UsageLimitServiceImpl implements UsageLimitService { private final AccountingService accountingService; + private final UsageLimitProperties usageLimitProperties; + @Autowired public UsageLimitServiceImpl( @@ -74,7 +76,7 @@ public class UsageLimitServiceImpl implements UsageLimitService { ConventionService conventionService, ErrorThesaurusProperties errors, MessageSource messageSource, - QueryFactory queryFactory, TenantEntityManager tenantEntityManager, AccountingService accountingService) { + QueryFactory queryFactory, TenantEntityManager tenantEntityManager, AccountingService accountingService, UsageLimitProperties usageLimitProperties) { this.entityManager = entityManager; this.authorizationService = authorizationService; this.deleterFactory = deleterFactory; @@ -85,6 +87,7 @@ public class UsageLimitServiceImpl implements UsageLimitService { this.queryFactory = queryFactory; this.tenantEntityManager = tenantEntityManager; this.accountingService = accountingService; + this.usageLimitProperties = usageLimitProperties; } public UsageLimit persist(UsageLimitPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException { @@ -128,6 +131,9 @@ public class UsageLimitServiceImpl implements UsageLimitService { } public void checkIncrease(UsageLimitTargetMetric metric) { + + if (usageLimitProperties.getEnabled() == null || !usageLimitProperties.getEnabled()) return; + if (metric == null) throw new MyApplicationException("Target Metric not defined"); Integer currentValue = this.accountingService.getCurrentMetricValue(metric); diff --git a/backend/web/src/main/resources/config/application.yml b/backend/web/src/main/resources/config/application.yml index f9c7cbefa..03a93aa67 100644 --- a/backend/web/src/main/resources/config/application.yml +++ b/backend/web/src/main/resources/config/application.yml @@ -32,6 +32,7 @@ spring: optional:classpath:config/authorization.yml[.yml], optional:classpath:config/authorization-${spring.profiles.active}.yml[.yml], optional:file:../config/authorization-${spring.profiles.active}.yml[.yml], optional:classpath:config/metrics.yml[.yml], optional:classpath:config/metrics-${spring.profiles.active}.yml[.yml], optional:file:../config/metrics-${spring.profiles.active}.yml[.yml], optional:classpath:config/field-set-expander.yml[.yml], optional:classpath:config/field-set-expander-${spring.profiles.active}.yml[.yml], optional:file:../config/field-set-expander-${spring.profiles.active}.yml[.yml], - optional:classpath:config/lock.yml[.yml], optional:classpath:config/lock-${spring.profiles.active}.yml[.yml], optional:file:../config/lock-${spring.profiles.active}.yml[.yml] + optional:classpath:config/lock.yml[.yml], optional:classpath:config/lock-${spring.profiles.active}.yml[.yml], optional:file:../config/lock-${spring.profiles.active}.yml[.yml], + optional:classpath:config/usage-limits.yml[.yml], optional:classpath:config/usage-limits-${spring.profiles.active}.yml[.yml], optional:file:../config/usage-limits-${spring.profiles.active}.yml[.yml] diff --git a/backend/web/src/main/resources/config/usage-limits.yml b/backend/web/src/main/resources/config/usage-limits.yml new file mode 100644 index 000000000..1fa8e8f98 --- /dev/null +++ b/backend/web/src/main/resources/config/usage-limits.yml @@ -0,0 +1,2 @@ +usage-limits: + enabled: false