Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make ApprovalValidations more configurable #334

Merged
merged 2 commits into from
May 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import org.springframework.context.annotation.Configuration;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

@Configuration
Expand All @@ -22,13 +23,17 @@ public class ApprovalIdConfiguration {

private Class generatorClass;
private Map<String, Object> parameters;
private Map<String, Boolean> validators;

@Bean
@ConditionalOnMissingBean
public ApprovalService defaultApprovalService(SubstanceApprovalIdGenerator approvalIdGenerator,
SubstanceRepository substanceRepository,
PrincipalRepository principalRepository){
return new DefaultApprovalService(approvalIdGenerator, substanceRepository, principalRepository);
if (validators == null) {
validators = new HashMap<String, Boolean>();
}
return new DefaultApprovalService(approvalIdGenerator, substanceRepository, principalRepository, validators);

}
@Bean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

public interface ApprovalService {

boolean isApprovable(Substance s);

ApprovalResult approve(Substance s) throws ApprovalException;

@Data
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

/**
Expand All @@ -38,13 +40,24 @@ public class DefaultApprovalService implements ApprovalService{

private PrincipalRepository principalRepository;

private Map<String, Boolean> validators;

@Autowired
public DefaultApprovalService(SubstanceApprovalIdGenerator approvalIdGenerator,
SubstanceRepository substanceRepository,
PrincipalRepository principalRepository) {
PrincipalRepository principalRepository,
Map<String, Boolean> validators) {
this.approvalIdGenerator = approvalIdGenerator;
this.substanceRepository = substanceRepository;
this.principalRepository = principalRepository;
Map<String, Boolean> vMap = new HashMap<String, Boolean>();
vMap.put("allowLastEditor", validators.getOrDefault("allowLastEditor", Boolean.FALSE));
vMap.put("allowCreator", validators.getOrDefault("allowCreator", Boolean.FALSE));
vMap.put("allowNonPrimary", validators.getOrDefault("allowNonPrimary", Boolean.FALSE));
vMap.put("allowConcept", validators.getOrDefault("allowConcept", Boolean.FALSE));
vMap.put("allowDependsOnNonPresent", validators.getOrDefault("allowDependsOnNonPresent", Boolean.FALSE));
vMap.put("allowDependsOnNonApproved", validators.getOrDefault("allowDependsOnNonApproved", Boolean.FALSE));
this.validators = vMap;
}

/**
Expand Down Expand Up @@ -100,30 +113,52 @@ protected void defaultApprovalValidation(Substance s, String usernameOfApprover)
throw new ApprovalException(
"There is no last editor associated with this record. One must be present to allow approval. Please contact your system administrator.");
} else {
if (s.lastEditedBy.username.equals(usernameOfApprover)) {
throw new ApprovalException(
if (validators.get("allowLastEditor") == Boolean.FALSE && s.lastEditedBy.username.equals(usernameOfApprover)) {
if (!(validators.get("allowCreator") == Boolean.TRUE && s.createdBy != null && s.createdBy.username.equals(usernameOfApprover))) {
throw new ApprovalException(
"You cannot approve a substance if you are the last editor of the substance.");
}
}
}
if (!s.isPrimaryDefinition()) {
if (validators.get("allowNonPrimary") == Boolean.FALSE && !s.isPrimaryDefinition()) {
throw new ApprovalException("Cannot approve non-primary definitions.");
}
if (Substance.SubstanceClass.concept.equals(s.substanceClass)) {
if (validators.get("allowConcept") == Boolean.FALSE && Substance.SubstanceClass.concept.equals(s.substanceClass)) {
throw new ApprovalException("Cannot approve non-substance concepts.");
}
for (SubstanceReference sr : s.getDependsOnSubstanceReferences()) {
Optional<SubstanceRepository.SubstanceSummary> s2 = substanceRepository.findSummaryBySubstanceReference(sr);
if (!s2.isPresent()) {
if (validators.get("allowDependsOnNonPresent") == Boolean.FALSE && !s2.isPresent()) {
throw new IllegalStateException("Cannot approve substance that depends on " + sr.toString()
+ " which is not found in database.");
}
if (!s2.get().isValidated()) {
if (validators.get("allowDependsOnNonApproved") == Boolean.FALSE && !s2.get().isValidated()) {
throw new IllegalStateException(
"Cannot approve substance that depends on " + sr.toString() + " which is not approved.");
}
}
}

/**
* Check if the given Substance is approvable by the user invoking this method.
* @param s the Substance to approve.
* @return a true if the user invoking this method is able to approve given Substance.
*/
@Override
public boolean isApprovable(Substance s) {
String userName = GsrsSecurityUtils.getCurrentUsername().orElse(null);
if (userName == null) {
return false;
}
try {
defaultApprovalValidation(s, userName);
extraApprovalValidation(s, userName);
return true;
} catch (ApprovalException ex) {
return false;
}
}

/**
* Try to approve the given Substance. The user invoking this method
* must have Approver Role.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1036,6 +1036,17 @@ public void saveTempStructure(Structure s) {

}

@GetGsrsRestApiMapping(value={"({id})/@isApprovable", "/{id}/@isApprovable" })
public ResponseEntity isApprovableGetMethod(@PathVariable("id") String substanceUUIDOrName, @RequestParam Map<String, String> queryParameters) throws Exception {
Optional<Substance> substance = getEntityService().getEntityBySomeIdentifier(substanceUUIDOrName);

if(!substance.isPresent()){
return getGsrsControllerConfiguration().handleNotFound(queryParameters);
}
boolean approvable = approvalService.isApprovable(substance.get());
return new ResponseEntity<>(String.valueOf(approvable), HttpStatus.OK);
}

@Transactional
@GetGsrsRestApiMapping(value={"({id})/@approve", "/{id}/@approve" })
@hasApproverRole
Expand Down
Loading