-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'dev' into 35276_add_metagenomic_workflow_resource
- Loading branch information
Showing
15 changed files
with
583 additions
and
2 deletions.
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
41 changes: 41 additions & 0 deletions
41
src/main/java/ca/gc/aafc/seqdb/api/dto/SequenceManagedAttributeDto.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
package ca.gc.aafc.seqdb.api.dto; | ||
|
||
import ca.gc.aafc.dina.dto.RelatedEntity; | ||
import ca.gc.aafc.dina.i18n.MultilingualDescription; | ||
import ca.gc.aafc.dina.vocabulary.TypedVocabularyElement; | ||
import ca.gc.aafc.seqdb.api.entities.SequenceManagedAttribute; | ||
|
||
import io.crnk.core.resource.annotations.JsonApiId; | ||
import io.crnk.core.resource.annotations.JsonApiResource; | ||
import lombok.Data; | ||
|
||
import java.time.OffsetDateTime; | ||
import java.util.UUID; | ||
|
||
import org.javers.core.metamodel.annotation.Id; | ||
import org.javers.core.metamodel.annotation.PropertyName; | ||
import org.javers.core.metamodel.annotation.TypeName; | ||
|
||
@RelatedEntity(SequenceManagedAttribute.class) | ||
@Data | ||
@JsonApiResource(type = SequenceManagedAttributeDto.TYPENAME) | ||
@TypeName(SequenceManagedAttributeDto.TYPENAME) | ||
public class SequenceManagedAttributeDto { | ||
public static final String TYPENAME = "managed-attribute"; | ||
|
||
@JsonApiId | ||
@Id | ||
@PropertyName("id") | ||
private UUID uuid; | ||
private String name; | ||
private String key; | ||
private TypedVocabularyElement.VocabularyElementType vocabularyElementType; | ||
private String unit; | ||
private SequenceManagedAttribute.ManagedAttributeComponent managedAttributeComponent; | ||
private String[] acceptedValues; | ||
private OffsetDateTime createdOn; | ||
private String createdBy; | ||
private String group; | ||
private MultilingualDescription multilingualDescription; | ||
|
||
} |
118 changes: 118 additions & 0 deletions
118
src/main/java/ca/gc/aafc/seqdb/api/entities/SequenceManagedAttribute.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
package ca.gc.aafc.seqdb.api.entities; | ||
|
||
import java.time.OffsetDateTime; | ||
import java.util.UUID; | ||
import javax.persistence.Column; | ||
import javax.persistence.Entity; | ||
import javax.persistence.EnumType; | ||
import javax.persistence.Enumerated; | ||
import javax.persistence.GeneratedValue; | ||
import javax.persistence.GenerationType; | ||
import javax.persistence.Id; | ||
import javax.validation.Valid; | ||
import javax.validation.constraints.NotBlank; | ||
import javax.validation.constraints.NotNull; | ||
import javax.validation.constraints.Size; | ||
import lombok.AllArgsConstructor; | ||
import lombok.Builder; | ||
import lombok.RequiredArgsConstructor; | ||
import lombok.Setter; | ||
import lombok.Getter; | ||
|
||
import org.hibernate.annotations.Generated; | ||
import org.hibernate.annotations.GenerationTime; | ||
import org.hibernate.annotations.NaturalId; | ||
import org.hibernate.annotations.NaturalIdCache; | ||
import org.hibernate.annotations.Type; | ||
|
||
import ca.gc.aafc.dina.entity.DinaEntityIdentifiableByName; | ||
import ca.gc.aafc.dina.entity.ManagedAttribute; | ||
import ca.gc.aafc.dina.i18n.MultilingualDescription; | ||
import ca.gc.aafc.dina.i18n.MultilingualTitle; | ||
|
||
@Entity(name = "managed_attribute") | ||
@Getter | ||
@Setter | ||
@Builder | ||
@AllArgsConstructor | ||
@RequiredArgsConstructor | ||
@NaturalIdCache | ||
public class SequenceManagedAttribute implements ManagedAttribute, DinaEntityIdentifiableByName { | ||
|
||
public enum ManagedAttributeComponent { | ||
GENERIC_MOLECULAR_ANALYSIS; | ||
|
||
public static ManagedAttributeComponent fromString(String s) { | ||
for (ManagedAttributeComponent source : ManagedAttributeComponent.values()) { | ||
if (source.name().equalsIgnoreCase(s)) { | ||
return source; | ||
} | ||
} | ||
return null; | ||
} | ||
} | ||
|
||
@Id | ||
@GeneratedValue(strategy = GenerationType.IDENTITY) | ||
private Integer id; | ||
|
||
@NaturalId | ||
@NotNull | ||
@Column(name = "uuid", unique = true) | ||
private UUID uuid; | ||
|
||
@Column(name = "created_on", insertable = false, updatable = false) | ||
@Generated(value = GenerationTime.INSERT) | ||
private OffsetDateTime createdOn; | ||
|
||
@NotBlank | ||
@Column(name = "created_by", updatable = false) | ||
private String createdBy; | ||
|
||
@NotBlank | ||
private String name; | ||
|
||
@Type(type = "jsonb") | ||
@Column(name = "multilingual_description") | ||
@Valid | ||
private MultilingualDescription multilingualDescription; | ||
|
||
@NotBlank | ||
@Column(name = "_group") | ||
@Size(max = 50) | ||
private String group; | ||
|
||
@NotBlank | ||
@Size(max = 50) | ||
@Column(updatable = false) | ||
private String key; | ||
|
||
@NotNull | ||
@Type(type = "pgsql_enum") | ||
@Enumerated(EnumType.STRING) | ||
@Column(name = "type") | ||
private VocabularyElementType vocabularyElementType; | ||
|
||
@NotNull | ||
@Enumerated(EnumType.STRING) | ||
@Column(name = "component") | ||
private ManagedAttributeComponent managedAttributeComponent; | ||
|
||
@Type(type = "string-array") | ||
@Column(name = "accepted_values", columnDefinition = "text[]") | ||
private String[] acceptedValues; | ||
|
||
@Size(max = 50) | ||
private String unit; | ||
|
||
@Override | ||
public String getTerm() { | ||
return null; | ||
} | ||
|
||
@Override | ||
public MultilingualTitle getMultilingualTitle() { | ||
return null; | ||
} | ||
|
||
} |
88 changes: 88 additions & 0 deletions
88
src/main/java/ca/gc/aafc/seqdb/api/repository/SequenceManagedAttributeRepository.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
package ca.gc.aafc.seqdb.api.repository; | ||
|
||
import org.springframework.boot.info.BuildProperties; | ||
import org.springframework.stereotype.Repository; | ||
|
||
import com.fasterxml.jackson.databind.ObjectMapper; | ||
|
||
import ca.gc.aafc.dina.mapper.DinaMapper; | ||
import ca.gc.aafc.dina.repository.DinaRepository; | ||
import ca.gc.aafc.dina.repository.external.ExternalResourceProvider; | ||
import ca.gc.aafc.dina.security.DinaAuthenticatedUser; | ||
import ca.gc.aafc.dina.security.TextHtmlSanitizer; | ||
import ca.gc.aafc.dina.service.AuditService; | ||
import ca.gc.aafc.seqdb.api.dto.SequenceManagedAttributeDto; | ||
import ca.gc.aafc.seqdb.api.entities.SequenceManagedAttribute; | ||
import ca.gc.aafc.seqdb.api.security.SuperUserInGroupCUDAuthorizationService; | ||
import ca.gc.aafc.seqdb.api.service.SequenceManagedAttributeService; | ||
|
||
import io.crnk.core.exception.ResourceNotFoundException; | ||
import io.crnk.core.queryspec.QuerySpec; | ||
import java.io.Serializable; | ||
import java.util.Optional; | ||
import java.util.regex.Pattern; | ||
import lombok.NonNull; | ||
|
||
@Repository | ||
public class SequenceManagedAttributeRepository extends DinaRepository<SequenceManagedAttributeDto, SequenceManagedAttribute> { | ||
|
||
private final SequenceManagedAttributeService dinaService; | ||
private Optional<DinaAuthenticatedUser> dinaAuthenticatedUser; | ||
|
||
public static final Pattern KEY_LOOKUP_PATTERN = Pattern.compile("(.*)\\.(.*)"); | ||
|
||
public SequenceManagedAttributeRepository( | ||
@NonNull SequenceManagedAttributeService service, | ||
@NonNull SuperUserInGroupCUDAuthorizationService authService, | ||
ExternalResourceProvider externalResourceProvider, | ||
@NonNull AuditService auditService, | ||
@NonNull BuildProperties buildProperties, | ||
Optional<DinaAuthenticatedUser> dinaAuthenticatedUser, | ||
ObjectMapper objectMapper | ||
) { | ||
super( | ||
service, authService, | ||
Optional.of(auditService), | ||
new DinaMapper<>(SequenceManagedAttributeDto.class), | ||
SequenceManagedAttributeDto.class, | ||
SequenceManagedAttribute.class, | ||
null, | ||
externalResourceProvider, | ||
buildProperties, objectMapper); | ||
this.dinaService = service; | ||
this.dinaAuthenticatedUser = dinaAuthenticatedUser; | ||
} | ||
|
||
@Override | ||
public <S extends SequenceManagedAttributeDto> S create(S resource) { | ||
dinaAuthenticatedUser.ifPresent( | ||
authenticatedUser -> resource.setCreatedBy(authenticatedUser.getUsername())); | ||
return super.create(resource); | ||
} | ||
|
||
@Override | ||
public SequenceManagedAttributeDto findOne(Serializable id, QuerySpec querySpec) { | ||
|
||
// Allow lookup by component type + key. | ||
// e.g. collecting_event.attribute_name | ||
var matcher = KEY_LOOKUP_PATTERN.matcher(id.toString()); | ||
if (matcher.groupCount() == 2) { | ||
if (matcher.find()) { | ||
SequenceManagedAttribute.ManagedAttributeComponent component = SequenceManagedAttribute.ManagedAttributeComponent | ||
.fromString(matcher.group(1)); | ||
String attributeKey = matcher.group(2); | ||
|
||
SequenceManagedAttribute managedAttribute = | ||
dinaService.findOneByKeyAndComponent(attributeKey, component); | ||
|
||
if (managedAttribute != null) { | ||
return getMappingLayer().toDtoSimpleMapping(managedAttribute); | ||
} else { | ||
throw new ResourceNotFoundException("Managed Attribute not found: " + TextHtmlSanitizer.sanitizeText(id.toString())); | ||
} | ||
} | ||
} | ||
|
||
return super.findOne(id, querySpec); | ||
} | ||
} |
39 changes: 39 additions & 0 deletions
39
src/main/java/ca/gc/aafc/seqdb/api/security/SuperUserInGroupCUDAuthorizationService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package ca.gc.aafc.seqdb.api.security; | ||
|
||
import org.springframework.security.access.prepost.PreAuthorize; | ||
import org.springframework.stereotype.Service; | ||
|
||
import ca.gc.aafc.dina.security.auth.PermissionAuthorizationService; | ||
|
||
/** | ||
* Authorization service that will authorize SUPER_USER (and DINA_ADMIN) for the group of the entity. | ||
* The currentUser must be at least SUPER_USER on the group defined on the entity. | ||
*/ | ||
@Service | ||
public class SuperUserInGroupCUDAuthorizationService extends PermissionAuthorizationService { | ||
|
||
@Override | ||
@PreAuthorize("hasMinimumGroupAndRolePermissions(@currentUser, 'SUPER_USER', #entity)") | ||
public void authorizeCreate(Object entity) { | ||
} | ||
|
||
@Override | ||
@PreAuthorize("hasMinimumGroupAndRolePermissions(@currentUser, 'SUPER_USER', #entity)") | ||
public void authorizeUpdate(Object entity) { | ||
} | ||
|
||
@Override | ||
@PreAuthorize("hasMinimumGroupAndRolePermissions(@currentUser, 'SUPER_USER', #entity)") | ||
public void authorizeDelete(Object entity) { | ||
} | ||
|
||
// Do nothing for now | ||
@Override | ||
public void authorizeRead(Object entity) { | ||
} | ||
|
||
@Override | ||
public String getName() { | ||
return "SuperUserInGroupCUDAuthorizationService"; | ||
} | ||
} |
69 changes: 69 additions & 0 deletions
69
src/main/java/ca/gc/aafc/seqdb/api/service/SequenceManagedAttributeService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
package ca.gc.aafc.seqdb.api.service; | ||
|
||
import liquibase.repackaged.org.apache.commons.lang3.StringUtils; | ||
import lombok.NonNull; | ||
|
||
import org.apache.commons.lang3.tuple.Pair; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.validation.SmartValidator; | ||
|
||
import ca.gc.aafc.dina.jpa.BaseDAO; | ||
import ca.gc.aafc.dina.service.ManagedAttributeService; | ||
import ca.gc.aafc.dina.service.PostgresJsonbService; | ||
import ca.gc.aafc.dina.util.UUIDHelper; | ||
import ca.gc.aafc.seqdb.api.entities.SequenceManagedAttribute; | ||
|
||
@Service | ||
public class SequenceManagedAttributeService extends ManagedAttributeService<SequenceManagedAttribute> { | ||
|
||
public static final String MANAGED_ATTRIBUTES_COL_NAME = "managed_attributes"; | ||
|
||
public static final String GENERIC_MOLECULAR_ANALYSIS_TABLE_NAME = "generic_molecular_analysis"; | ||
|
||
private static final String COMPONENT_FIELD_NAME = "managedAttributeComponent"; | ||
|
||
private final PostgresJsonbService jsonbService; | ||
|
||
public SequenceManagedAttributeService( | ||
@NonNull BaseDAO baseDAO, | ||
@NonNull SmartValidator sv, | ||
@NonNull PostgresJsonbService postgresJsonbService) { | ||
super(baseDAO, sv, SequenceManagedAttribute.class); | ||
this.jsonbService = postgresJsonbService; | ||
} | ||
|
||
@Override | ||
protected void preCreate(SequenceManagedAttribute entity) { | ||
entity.setUuid(UUIDHelper.generateUUIDv7()); | ||
entity.setGroup(standardizeGroupName(entity)); | ||
super.preCreate(entity); | ||
} | ||
|
||
@Override | ||
protected void preDelete(SequenceManagedAttribute entity) { | ||
switch (entity.getManagedAttributeComponent()) { | ||
case GENERIC_MOLECULAR_ANALYSIS: | ||
checkKeysFor(entity.getKey(), GENERIC_MOLECULAR_ANALYSIS_TABLE_NAME); | ||
break; | ||
default: | ||
throw new IllegalStateException( | ||
"Unexpected managed attribute component of: " + entity.getManagedAttributeComponent()); | ||
} | ||
} | ||
|
||
public SequenceManagedAttribute findOneByKeyAndComponent(String key, | ||
SequenceManagedAttribute.ManagedAttributeComponent component) { | ||
if (StringUtils.isBlank(key) || component == null) { | ||
return null; | ||
} | ||
return findOneByKeyAnd(key, Pair.of(COMPONENT_FIELD_NAME, component)); | ||
} | ||
|
||
private void checkKeysFor(String key, String tableName) { | ||
Integer countFirstLevelKeys = jsonbService.countFirstLevelKeys( | ||
tableName, SequenceManagedAttributeService.MANAGED_ATTRIBUTES_COL_NAME, key); | ||
if (countFirstLevelKeys > 0) { | ||
throw new IllegalStateException("Managed attribute key: " + key + ", is currently in use."); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.