add dmp associated user query
This commit is contained in:
parent
1a567c9a81
commit
c9640bcb54
|
@ -86,6 +86,7 @@ public class AuditableAction {
|
|||
public static final EventId User_MergeConfirm = new EventId(11011, "User_MergeConfirm");
|
||||
public static final EventId User_RemoveCredentialRequest = new EventId(11012, "User_RemoveCredentialRequest");
|
||||
public static final EventId User_RemoveCredentialConfirm = new EventId(11013, "User_RemoveCredentialConfirm");
|
||||
public static final EventId User_DmpAssociatedQuery = new EventId(11014, "User_DmpAssociatedQuery");
|
||||
|
||||
public static final EventId Tenant_Query = new EventId(12000, "Tenant_Query");
|
||||
public static final EventId Tenant_Lookup = new EventId(12001, "Tenant_Lookup");
|
||||
|
|
|
@ -56,7 +56,7 @@ public final class Permission {
|
|||
public static String EditUser = "EditUser";
|
||||
public static String DeleteUser = "DeleteUser";
|
||||
public static String ExportUsers = "ExportUsers";
|
||||
|
||||
public static String BrowseDmpAssociatedUser = "BrowseDmpAssociatedUser";
|
||||
|
||||
|
||||
//StorageFile
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
package eu.eudat.model;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class DmpAssociatedUser {
|
||||
|
||||
private UUID id;
|
||||
public static final String _id = "id";
|
||||
|
||||
private String name;
|
||||
public static final String _name = "name";
|
||||
|
||||
private String email;
|
||||
public static final String _email = "email";
|
||||
|
||||
public UUID getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(UUID id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
public void setEmail(String email) {
|
||||
this.email = email;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
package eu.eudat.model.builder;
|
||||
|
||||
import eu.eudat.authorization.AuthorizationFlags;
|
||||
import eu.eudat.commons.JsonHandlingService;
|
||||
import eu.eudat.commons.enums.ContactInfoType;
|
||||
import eu.eudat.commons.types.user.AdditionalInfoEntity;
|
||||
import eu.eudat.convention.ConventionService;
|
||||
import eu.eudat.data.UserEntity;
|
||||
import eu.eudat.model.*;
|
||||
import eu.eudat.model.referencetypedefinition.ReferenceTypeSourceBaseConfiguration;
|
||||
import eu.eudat.query.TenantUserQuery;
|
||||
import eu.eudat.query.UserContactInfoQuery;
|
||||
import eu.eudat.query.UserCredentialQuery;
|
||||
import eu.eudat.query.UserRoleQuery;
|
||||
import gr.cite.tools.data.builder.BuilderFactory;
|
||||
import gr.cite.tools.data.query.QueryFactory;
|
||||
import gr.cite.tools.exception.MyApplicationException;
|
||||
import gr.cite.tools.fieldset.BaseFieldSet;
|
||||
import gr.cite.tools.fieldset.FieldSet;
|
||||
import gr.cite.tools.logging.DataLogEntry;
|
||||
import gr.cite.tools.logging.LoggerService;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Component
|
||||
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
|
||||
public class DmpAssociatedUserBuilder extends BaseBuilder<DmpAssociatedUser, UserEntity> {
|
||||
|
||||
private final QueryFactory queryFactory;
|
||||
|
||||
private final BuilderFactory builderFactory;
|
||||
|
||||
private EnumSet<AuthorizationFlags> authorize = EnumSet.of(AuthorizationFlags.None);
|
||||
|
||||
@Autowired
|
||||
public DmpAssociatedUserBuilder(ConventionService conventionService,
|
||||
QueryFactory queryFactory,
|
||||
BuilderFactory builderFactory) {
|
||||
super(conventionService, new LoggerService(LoggerFactory.getLogger(DmpAssociatedUserBuilder.class)));
|
||||
this.queryFactory = queryFactory;
|
||||
this.builderFactory = builderFactory;
|
||||
}
|
||||
|
||||
public DmpAssociatedUserBuilder authorize(EnumSet<AuthorizationFlags> values) {
|
||||
this.authorize = values;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DmpAssociatedUser> build(FieldSet fields, List<UserEntity> data) throws MyApplicationException {
|
||||
this.logger.debug("building for {} items requesting {} fields", Optional.ofNullable(data).map(List::size).orElse(0), Optional.ofNullable(fields).map(FieldSet::getFields).map(Set::size).orElse(0));
|
||||
this.logger.trace(new DataLogEntry("requested fields", fields));
|
||||
if (fields == null || data == null || fields.isEmpty())
|
||||
return new ArrayList<>();
|
||||
|
||||
List<DmpAssociatedUser> models = new ArrayList<>();
|
||||
|
||||
Map<UUID, List<UserContactInfo>> contactsMap = this.collectUserContactInfos(new BaseFieldSet().ensure(UserContactInfo._value).ensure(UserContactInfo._type).ensure(UserContactInfo._ordinal), data);
|
||||
|
||||
for (UserEntity d : data) {
|
||||
DmpAssociatedUser m = new DmpAssociatedUser();
|
||||
if (fields.hasField(this.asIndexer(User._id))) m.setId(d.getId());
|
||||
if (fields.hasField(this.asIndexer(User._name))) m.setName(d.getName());
|
||||
if (contactsMap != null && contactsMap.containsKey(d.getId())){
|
||||
List<UserContactInfo> contactInfos = contactsMap.get(d.getId());
|
||||
if (contactInfos != null) {
|
||||
contactInfos.sort(Comparator.comparing(UserContactInfo::getOrdinal));
|
||||
m.setEmail(contactInfos.stream().filter(x -> ContactInfoType.Email.equals(x.getType())).map(UserContactInfo::getValue).findFirst().orElse(null));
|
||||
}
|
||||
}
|
||||
models.add(m);
|
||||
}
|
||||
this.logger.debug("build {} items", Optional.of(models).map(List::size).orElse(0));
|
||||
|
||||
return models;
|
||||
}
|
||||
|
||||
private Map<UUID, List<UserContactInfo>> collectUserContactInfos(FieldSet fields, List<UserEntity> data) throws MyApplicationException {
|
||||
if (fields.isEmpty() || data.isEmpty()) return null;
|
||||
this.logger.debug("checking related - {}", UserContactInfo.class.getSimpleName());
|
||||
|
||||
Map<UUID, List<UserContactInfo>> itemMap;
|
||||
FieldSet clone = new BaseFieldSet(fields.getFields()).ensure(this.asIndexer(UserContactInfo._user, User._id));
|
||||
UserContactInfoQuery query = this.queryFactory.query(UserContactInfoQuery.class).authorize(this.authorize).userIds(data.stream().map(UserEntity::getId).distinct().collect(Collectors.toList()));
|
||||
itemMap = this.builderFactory.builder(UserContactInfoBuilder.class).authorize(this.authorize).asMasterKey(query, clone, x -> x.getUser().getId());
|
||||
|
||||
if (!fields.hasField(this.asIndexer(UserContactInfo._user, User._id))) {
|
||||
itemMap.values().stream().flatMap(List::stream).filter(x -> x != null && x.getUser() != null).peek(x -> {
|
||||
x.getUser().setId(null);
|
||||
});
|
||||
}
|
||||
|
||||
return itemMap;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
package eu.eudat.model.censorship;
|
||||
|
||||
import eu.eudat.authorization.OwnedResource;
|
||||
import eu.eudat.authorization.Permission;
|
||||
import eu.eudat.convention.ConventionService;
|
||||
import gr.cite.commons.web.authz.service.AuthorizationService;
|
||||
import gr.cite.tools.fieldset.FieldSet;
|
||||
import gr.cite.tools.logging.DataLogEntry;
|
||||
import gr.cite.tools.logging.LoggerService;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@Component
|
||||
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
|
||||
public class DmpAssociatedUserCensor extends BaseCensor {
|
||||
|
||||
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(DmpAssociatedUserCensor.class));
|
||||
|
||||
protected final AuthorizationService authService;
|
||||
|
||||
|
||||
public DmpAssociatedUserCensor(ConventionService conventionService, AuthorizationService authService) {
|
||||
super(conventionService);
|
||||
this.authService = authService;
|
||||
}
|
||||
|
||||
public void censor(FieldSet fields, UUID userId) {
|
||||
logger.debug(new DataLogEntry("censoring fields", fields));
|
||||
if (fields == null || fields.isEmpty())
|
||||
return;
|
||||
this.authService.authorizeAtLeastOneForce(userId != null ? List.of(new OwnedResource(userId)) : null, Permission.BrowseDmpAssociatedUser);
|
||||
}
|
||||
|
||||
}
|
|
@ -5,22 +5,23 @@ import eu.eudat.authorization.Permission;
|
|||
import eu.eudat.commons.enums.IsActive;
|
||||
import eu.eudat.commons.scope.user.UserScope;
|
||||
import eu.eudat.data.*;
|
||||
import eu.eudat.model.DmpDescriptionTemplate;
|
||||
import eu.eudat.model.Language;
|
||||
import eu.eudat.model.User;
|
||||
import eu.eudat.model.PublicUser;
|
||||
import eu.eudat.model.UserRole;
|
||||
import eu.eudat.query.utils.BuildSubQueryInput;
|
||||
import eu.eudat.query.utils.QueryUtilsService;
|
||||
import gr.cite.commons.web.authz.service.AuthorizationService;
|
||||
import gr.cite.tools.data.query.FieldResolver;
|
||||
import gr.cite.tools.data.query.QueryBase;
|
||||
import gr.cite.tools.data.query.QueryContext;
|
||||
import gr.cite.tools.exception.MyNotFoundException;
|
||||
import jakarta.persistence.Tuple;
|
||||
import jakarta.persistence.criteria.CriteriaBuilder;
|
||||
import jakarta.persistence.criteria.Predicate;
|
||||
import jakarta.persistence.criteria.Subquery;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.context.i18n.LocaleContextHolder;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.Instant;
|
||||
|
@ -30,6 +31,7 @@ import java.util.*;
|
|||
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
|
||||
public class UserQuery extends QueryBase<UserEntity> {
|
||||
private String like;
|
||||
private Boolean dmpAssociated;
|
||||
private Collection<UUID> ids;
|
||||
private Collection<String> emails;
|
||||
private Collection<UUID> excludedIds;
|
||||
|
@ -117,6 +119,11 @@ public class UserQuery extends QueryBase<UserEntity> {
|
|||
return this;
|
||||
}
|
||||
|
||||
public UserQuery dmpAssociated(Boolean dmpAssociated) {
|
||||
this.dmpAssociated = dmpAssociated;
|
||||
return this;
|
||||
}
|
||||
|
||||
public UserQuery authorize(EnumSet<AuthorizationFlags> values) {
|
||||
this.authorize = values;
|
||||
return this;
|
||||
|
@ -186,7 +193,7 @@ public class UserQuery extends QueryBase<UserEntity> {
|
|||
new BuildSubQueryInput.Builder<>(UserContactInfoQuery.class, UUID.class, queryContext)
|
||||
.keyPathFunc((subQueryRoot) -> subQueryRoot.get(UserContactInfoEntity._id))
|
||||
.filterFunc((subQueryRoot, cb) -> {
|
||||
CriteriaBuilder.In<String> inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(UserContactInfoEntity._value));
|
||||
CriteriaBuilder.In<String> inClause = cb.in(subQueryRoot.get(UserContactInfoEntity._value));
|
||||
for (String item : this.emails)
|
||||
inClause.value(item);
|
||||
return inClause;
|
||||
|
@ -199,6 +206,30 @@ public class UserQuery extends QueryBase<UserEntity> {
|
|||
QueryContext<UserRoleEntity, UUID> subQuery = this.applySubQuery(this.userRoleQuery, queryContext, UUID.class, userRoleEntityRoot -> userRoleEntityRoot.get(UserRoleEntity._userId));
|
||||
predicates.add(queryContext.CriteriaBuilder.in(queryContext.Root.get(UserEntity._id)).value(subQuery.Query));
|
||||
}
|
||||
if (this.dmpAssociated){
|
||||
UUID userId;
|
||||
if (this.userScope.isSet()) userId = this.userScope.getUserIdSafe();
|
||||
else throw new MyNotFoundException("Only user scoped allowed");
|
||||
|
||||
Subquery<UUID> dmpUserDmpQuery = queryUtilsService.buildSubQuery(new BuildSubQueryInput<>(
|
||||
new BuildSubQueryInput.Builder<>(DmpUserQuery.class, UUID.class, queryContext)
|
||||
.keyPathFunc((subQueryRoot) -> subQueryRoot.get(DmpUserEntity._dmpId))
|
||||
.filterFunc((subQueryRoot, cb) -> cb.and(
|
||||
cb.equal(subQueryRoot.get(DmpUserEntity._userId), userId),
|
||||
cb.equal(subQueryRoot.get(DmpUserEntity._isActive), IsActive.Active)
|
||||
))
|
||||
));
|
||||
|
||||
Subquery<UUID> dmpUserUserQuery = queryUtilsService.buildSubQuery(new BuildSubQueryInput<>(
|
||||
new BuildSubQueryInput.Builder<>(DmpUserQuery.class, UUID.class, queryContext)
|
||||
.keyPathFunc((subQueryRoot) -> subQueryRoot.get(DmpUserEntity._userId))
|
||||
.filterFunc((subQueryRoot, cb) -> cb.and(
|
||||
cb.in(subQueryRoot.get(DmpUserEntity._dmpId)).value(dmpUserDmpQuery) ,
|
||||
cb.equal(subQueryRoot.get(DmpUserEntity._isActive), IsActive.Active)
|
||||
))
|
||||
));
|
||||
predicates.add(queryContext.CriteriaBuilder.in(queryContext.Root.get(UserEntity._id)).value(dmpUserUserQuery));
|
||||
}
|
||||
|
||||
|
||||
if (!predicates.isEmpty()) {
|
||||
|
|
|
@ -3,12 +3,16 @@ package eu.eudat.controllers.v2;
|
|||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import eu.eudat.audit.AuditableAction;
|
||||
import eu.eudat.authorization.AuthorizationFlags;
|
||||
import eu.eudat.commons.enums.IsActive;
|
||||
import eu.eudat.commons.scope.user.UserScope;
|
||||
import eu.eudat.commons.validation.ValidationFilterAnnotation;
|
||||
import eu.eudat.data.UserEntity;
|
||||
import eu.eudat.model.DmpAssociatedUser;
|
||||
import eu.eudat.model.User;
|
||||
import eu.eudat.model.UserRole;
|
||||
import eu.eudat.model.builder.DmpAssociatedUserBuilder;
|
||||
import eu.eudat.model.builder.UserBuilder;
|
||||
import eu.eudat.model.censorship.DmpAssociatedUserCensor;
|
||||
import eu.eudat.model.censorship.UserCensor;
|
||||
import eu.eudat.model.persist.UserPersist;
|
||||
import eu.eudat.model.persist.UserRolePatchPersist;
|
||||
|
@ -107,6 +111,23 @@ public class UserController {
|
|||
return new QueryResult<>(models, count);
|
||||
}
|
||||
|
||||
@PostMapping("dmp-associated/query")
|
||||
public QueryResult<DmpAssociatedUser> queryDmpAssociated(@RequestBody UserLookup lookup) throws MyApplicationException, MyForbiddenException {
|
||||
logger.debug("querying {}", User.class.getSimpleName());
|
||||
|
||||
this.censorFactory.censor(DmpAssociatedUserCensor.class).censor(lookup.getProject(), null);
|
||||
|
||||
UserQuery query = lookup.enrich(this.queryFactory).dmpAssociated(true).isActive(IsActive.Active);
|
||||
|
||||
List<UserEntity> data = query.collectAs(lookup.getProject());
|
||||
List<DmpAssociatedUser> models = this.builderFactory.builder(DmpAssociatedUserBuilder.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermissionOrPublic).build(lookup.getProject(), data);
|
||||
long count = (lookup.getMetadata() != null && lookup.getMetadata().getCountAll()) ? query.count() : models.size();
|
||||
|
||||
this.auditService.track(AuditableAction.User_DmpAssociatedQuery, "lookup", lookup);
|
||||
|
||||
return new QueryResult<>(models, count);
|
||||
}
|
||||
|
||||
@GetMapping("{id}")
|
||||
public User get(@PathVariable("id") UUID id, FieldSet fieldSet) throws MyApplicationException, MyForbiddenException, MyNotFoundException {
|
||||
logger.debug(new MapLogEntry("retrieving" + User.class.getSimpleName()).And("id", id).And("fields", fieldSet));
|
||||
|
|
|
@ -217,6 +217,16 @@ permissions:
|
|||
clients: [ ]
|
||||
allowAnonymous: false
|
||||
allowAuthenticated: false
|
||||
BrowseDmpAssociatedUser:
|
||||
roles:
|
||||
- Admin
|
||||
- DescriptionTemplateEditor
|
||||
- Manager
|
||||
- User
|
||||
claims: [ ]
|
||||
clients: [ ]
|
||||
allowAnonymous: false
|
||||
allowAuthenticated: false
|
||||
# DescriptionTemplateType
|
||||
BrowseDescriptionTemplateType:
|
||||
roles:
|
||||
|
|
Loading…
Reference in New Issue