Skip to content

Commit

Permalink
Merge pull request #272 from ncats/provide_readonly2
Browse files Browse the repository at this point in the history
Allow an entity service to prevent direct inserts, updates and deletions by making isReadOnly() return true
  • Loading branch information
ChemMitch authored Aug 1, 2024
2 parents c559f1d + eb3117c commit 651bf4c
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,11 @@ public ResponseEntity<Object> createEntity(@RequestBody JsonNode newEntityJson,
@RequestParam Map<String, String> queryParameters,
Principal principal) throws IOException {
GsrsEntityService<T, I> entityService = getEntityService();
if( entityService.isReadOnly()) {
log.warn("detected forbidden operation in createEntity");
String message = "Please use the parent object to perform this operation";
return new ResponseEntity<>(message, gsrsControllerConfiguration.getHttpStatusFor(HttpStatus.BAD_REQUEST, queryParameters));
}
AbstractGsrsEntityService.CreationResult<T> result =null;
try {
result = entityService.createEntity(newEntityJson);
Expand Down Expand Up @@ -202,7 +207,13 @@ public ValidationResponse<T> validateEntity(@RequestBody JsonNode updatedEntityJ
public ResponseEntity<Object> updateEntity(@RequestBody JsonNode updatedEntityJson,
@RequestParam Map<String, String> queryParameters,
Principal principal) throws Exception {
AbstractGsrsEntityService.UpdateResult<T> result = getEntityService().updateEntity(updatedEntityJson);
if( getEntityService().isReadOnly()) {
log.warn("detected forbidden operation in createEntity");
String message = "Please use the parent object to perform this operation";
return new ResponseEntity<>(message, gsrsControllerConfiguration.getHttpStatusFor(HttpStatus.BAD_REQUEST, queryParameters));
}

AbstractGsrsEntityService.UpdateResult<T> result = getEntityService().updateEntity(updatedEntityJson);
if(result.getStatus()== AbstractGsrsEntityService.UpdateResult.STATUS.NOT_FOUND){
return gsrsControllerConfiguration.handleNotFound(queryParameters);
}
Expand Down Expand Up @@ -479,7 +490,13 @@ public ResponseEntity<Object> getById(@PathVariable("id") String id, @RequestPar
@PreAuthorize("isAuthenticated()")
@DeleteGsrsRestApiMapping(value = {"({id})", "/{id}"})
public ResponseEntity<Object> deleteById(@PathVariable("id") String id, @RequestParam Map<String, String> queryParameters){
if( getEntityService().isReadOnly()) {
log.warn("detected forbidden operation in createEntity");
String message = "Please use the parent object to perform this operation";
return new ResponseEntity<>(message, gsrsControllerConfiguration.getHttpStatusFor(HttpStatus.BAD_REQUEST, queryParameters));
}
Optional<I> idOptional = getEntityService().getEntityIdOnlyBySomeIdentifier(id);

if(idOptional.isPresent()){
getEntityService().delete(idOptional.get());
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ public abstract class AbstractGsrsEntityService<T,I> implements GsrsEntityServic
private final String context;
private final Pattern idPattern;

private boolean readOnly = false;

private CachedSupplier<ValidatorFactory> validatorFactory;
/**
* Create a new GSRS Entity Service with the given context.
Expand Down Expand Up @@ -290,7 +292,10 @@ public EntityManager getEntityManager() {

@Override
public CreationResult<T> createEntity(JsonNode newEntityJson, boolean partOfBatchLoad){

if( isReadOnly()){
log.error("Trying to create a {} when service is read-only", getFriendlyName());
throw new RuntimeException("Please use the parent object to create a " + getFriendlyName());
}
TransactionTemplate transactionTemplate = new TransactionTemplate(this.getTransactionManager());

ValidatorConfig.METHOD_TYPE methodType = partOfBatchLoad? ValidatorConfig.METHOD_TYPE.BATCH : ValidatorConfig.METHOD_TYPE.CREATE;
Expand Down Expand Up @@ -416,6 +421,11 @@ public PlatformTransactionManager getTransactionManager() {

@Override
public UpdateResult<T> updateEntity(T updatedEntity, EntityPersistAdapter.ChangeOperation<T> changeOperation) throws Exception {
log.trace("updateEntity 2 parms");
if( isReadOnly()){
log.error("Trying to update a {} when service is read-only", getFriendlyName());
throw new RuntimeException("Please use the parent object to update a " + getFriendlyName());
}

TransactionTemplate transactionTemplate = new TransactionTemplate(getTransactionManager());

Expand Down Expand Up @@ -448,6 +458,11 @@ public UpdateResult<T> updateEntity(T updatedEntity, EntityPersistAdapter.Change

@Override
public UpdateResult<T> updateEntity(JsonNode updatedEntityJson) throws Exception {
log.trace("updateEntity 1 parm");
if( isReadOnly()){
log.error("Trying to update a {} when service is read-only", getFriendlyName());
throw new RuntimeException("Please use the parent object to update a " + getFriendlyName());
}

TransactionTemplate transactionTemplate = new TransactionTemplate(this.getTransactionManager());

Expand Down Expand Up @@ -783,4 +798,22 @@ protected Optional<I> flexLookupIdOnly(String someKindOfId){
*/
@Transactional
public abstract Optional<T> flexLookup(String someKindOfId);

@Override
public boolean isReadOnly() {
return readOnly;
}

private String getFriendlyName() {
if( getEntityClass() != null ){
String fullClassName = getEntityClass().getName();
if( fullClassName.contains(".")) {
return fullClassName.substring(fullClassName.lastIndexOf(".")+1);
}
return fullClassName;
}
String name = getContext();
if( name.endsWith("s")) return name.substring(0, name.length()-1);
return name;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,12 @@
import lombok.Builder;
import lombok.Data;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.UUID;

/**
* Contains all the business logic for converting JSON into an Entity, reading and writing
Expand Down Expand Up @@ -157,4 +155,6 @@ public static ProcessResult ofUpdate(UpdateResult update) {
return builder.build();
}
}

boolean isReadOnly();
}

0 comments on commit 651bf4c

Please sign in to comment.