refactor lock entity

This commit is contained in:
amentis 2023-12-08 18:05:48 +02:00
parent 0c34502f08
commit 880e8c5aa8
23 changed files with 1408 additions and 83 deletions

View File

@ -97,5 +97,11 @@ public class AuditableAction {
public static final EventId Dashboard_MyDashboardStatistics = new EventId(15001, "Dashboard_MyDashboardStatistics"); public static final EventId Dashboard_MyDashboardStatistics = new EventId(15001, "Dashboard_MyDashboardStatistics");
public static final EventId Dashboard_PublicDashboardStatistics = new EventId(15002, "Dashboard_PublicDashboardStatistics"); public static final EventId Dashboard_PublicDashboardStatistics = new EventId(15002, "Dashboard_PublicDashboardStatistics");
public static final EventId Notification_Persist = new EventId(16000, "Notification_Persist");
public static final EventId Lock_Query = new EventId(17000, "Lock_Query");
public static final EventId Lock_Lookup = new EventId(17001, "Lock_Lookup");
public static final EventId Lock_Persist = new EventId(17002, "Lock_Persist");
public static final EventId Lock_Delete = new EventId(17003, "Lock_Delete");
} }

View File

@ -161,5 +161,10 @@ public final class Permission {
public static String EditTenantUser = "EditTenantUser"; public static String EditTenantUser = "EditTenantUser";
public static String DeleteTenantUser = "DeleteTenantUser"; public static String DeleteTenantUser = "DeleteTenantUser";
//Lock
public static String BrowseLock = "BrowseLock";
public static String EditLock = "EditLock";
public static String DeleteLock = "DeleteLock";
} }

View File

@ -0,0 +1,27 @@
package eu.eudat.commons.enums;
import com.fasterxml.jackson.annotation.JsonValue;
import eu.eudat.data.converters.enums.DatabaseEnum;
import java.util.Map;
public enum LockTargetType implements DatabaseEnum<Short> {
Dmp((short) 0),
Decription((short) 1);
private final Short value;
LockTargetType(Short value) {
this.value = value;
}
@JsonValue
public Short getValue() {
return value;
}
private static final Map<Short, LockTargetType> map = EnumUtils.getEnumValueMap(LockTargetType.class);
public static LockTargetType of(Short i) {
return map.get(i);
}
}

View File

@ -0,0 +1,90 @@
package eu.eudat.data;
import eu.eudat.commons.enums.LockTargetType;
import eu.eudat.data.converters.enums.LockTargetTypeConverter;
import eu.eudat.data.tenant.TenantScopedBaseEntity;
import jakarta.persistence.*;
import java.time.Instant;
import java.util.UUID;
@Entity
@Table(name = "\"Lock\"")
public class LockEntity extends TenantScopedBaseEntity {
@Id
@Column(name = "id", columnDefinition = "uuid", updatable = false, nullable = false)
private UUID id;
public static final String _id = "id";
@Column(name = "target", columnDefinition = "uuid", updatable = false, nullable = false)
private UUID target;
public static final String _target = "target";
@Column(name = "target_type", nullable = false)
@Convert(converter = LockTargetTypeConverter.class)
private LockTargetType targetType;
public static final String _targetType = "targetType";
@Column(name = "locked_by", columnDefinition = "uuid", updatable = false, nullable = false)
private UUID lockedBy;
public static final String _lockedBy = "lockedBy";
@Column(name = "locked_at", nullable = false)
private Instant lockedAt = null;
public static final String _lockedAt = "lockedAt";
@Column(name = "touched_at", nullable = true)
private Instant touchedAt;
public static final String _touchedAt = "touchedAt";
public UUID getId() {
return id;
}
public void setId(UUID id) {
this.id = id;
}
public UUID getTarget() {
return target;
}
public void setTarget(UUID target) {
this.target = target;
}
public LockTargetType getTargetType() {
return targetType;
}
public void setTargetType(LockTargetType targetType) {
this.targetType = targetType;
}
public UUID getLockedBy() {
return lockedBy;
}
public void setLockedBy(UUID lockedBy) {
this.lockedBy = lockedBy;
}
public Instant getLockedAt() {
return lockedAt;
}
public void setLockedAt(Instant lockedAt) {
this.lockedAt = lockedAt;
}
public Instant getTouchedAt() {
return touchedAt;
}
public void setTouchedAt(Instant touchedAt) {
this.touchedAt = touchedAt;
}
}

View File

@ -0,0 +1,11 @@
package eu.eudat.data.converters.enums;
import eu.eudat.commons.enums.LockTargetType;
import jakarta.persistence.Converter;
@Converter
public class LockTargetTypeConverter extends DatabaseEnumConverter<LockTargetType, Short>{
protected LockTargetType of(Short i) {
return LockTargetType.of(i);
}
}

View File

@ -0,0 +1,98 @@
package eu.eudat.model;
import eu.eudat.commons.enums.LockTargetType;
import java.time.Instant;
import java.util.UUID;
public class Lock {
private UUID id;
public static final String _id = "id";
private UUID target;
public static final String _target = "target";
private LockTargetType targetType;
public static final String _targetType = "targetType";
private User lockedBy;
public static final String _lockedBy = "lockedBy";
private Instant lockedAt;
public static final String _lockedAt = "lockedAt";
private Instant touchedAt;
public static final String _touchedAt = "touchedAt";
private Tenant tenant;
public static final String _tenant = "tenant";
private String hash;
public static final String _hash = "hash";
public UUID getId() {
return id;
}
public void setId(UUID id) {
this.id = id;
}
public UUID getTarget() {
return target;
}
public void setTarget(UUID target) {
this.target = target;
}
public LockTargetType getTargetType() {
return targetType;
}
public void setTargetType(LockTargetType targetType) {
this.targetType = targetType;
}
public User getLockedBy() {
return lockedBy;
}
public void setLockedBy(User lockedBy) {
this.lockedBy = lockedBy;
}
public Instant getLockedAt() {
return lockedAt;
}
public void setLockedAt(Instant lockedAt) {
this.lockedAt = lockedAt;
}
public Instant getTouchedAt() {
return touchedAt;
}
public void setTouchedAt(Instant touchedAt) {
this.touchedAt = touchedAt;
}
public Tenant getTenant() {
return tenant;
}
public void setTenant(Tenant tenant) {
this.tenant = tenant;
}
public String getHash() {
return hash;
}
public void setHash(String hash) {
this.hash = hash;
}
}

View File

@ -0,0 +1,140 @@
package eu.eudat.model.builder;
import eu.eudat.authorization.AuthorizationFlags;
import eu.eudat.commons.XmlHandlingService;
import eu.eudat.convention.ConventionService;
import eu.eudat.data.LockEntity;
import eu.eudat.model.Lock;
import eu.eudat.model.Tenant;
import eu.eudat.model.User;
import eu.eudat.query.TenantQuery;
import eu.eudat.query.UserQuery;
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 LockBuilder extends BaseBuilder<Lock, LockEntity>{
private final BuilderFactory builderFactory;
private final QueryFactory queryFactory;
private final XmlHandlingService xmlHandlingService;
private EnumSet<AuthorizationFlags> authorize = EnumSet.of(AuthorizationFlags.None);
@Autowired
public LockBuilder(
ConventionService conventionService,
BuilderFactory builderFactory, QueryFactory queryFactory, XmlHandlingService xmlHandlingService) {
super(conventionService, new LoggerService(LoggerFactory.getLogger(LockBuilder.class)));
this.builderFactory = builderFactory;
this.queryFactory = queryFactory;
this.xmlHandlingService = xmlHandlingService;
}
public LockBuilder authorize(EnumSet<AuthorizationFlags> values) {
this.authorize = values;
return this;
}
@Override
public List<Lock> build(FieldSet fields, List<LockEntity> 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<>();
FieldSet userFields = fields.extractPrefixed(this.asPrefix(Lock._lockedBy));
Map<UUID, User> userMap = this.collectUsers(userFields, data);
FieldSet tenantFields = fields.extractPrefixed(this.asPrefix(Lock._tenant));
Map<UUID, Tenant> tenantMap = this.collectTenants(tenantFields, data);
List<Lock> models = new ArrayList<>();
for (LockEntity d : data) {
Lock m = new Lock();
if (fields.hasField(this.asIndexer(Lock._id))) m.setId(d.getId());
if (fields.hasField(this.asIndexer(Lock._target))) m.setTarget(d.getTarget());
if (fields.hasField(this.asIndexer(Lock._targetType))) m.setTargetType(d.getTargetType());
if (fields.hasField(this.asIndexer(Lock._lockedAt))) m.setLockedAt(d.getLockedAt());
if (fields.hasField(this.asIndexer(Lock._touchedAt))) m.setTouchedAt(d.getTouchedAt());
if (fields.hasField(this.asIndexer(Lock._hash))) m.setHash(this.hashValue(d.getTouchedAt()));
if (!userFields.isEmpty() && userMap != null && userMap.containsKey(d.getLockedBy())) m.setLockedBy(userMap.get(d.getLockedBy()));
if (!tenantFields.isEmpty() && tenantMap != null && tenantMap.containsKey(d.getTenantId())) m.setTenant(tenantMap.get(d.getTenantId()));
models.add(m);
}
this.logger.debug("build {} items", Optional.of(models).map(List::size).orElse(0));
return models;
}
private Map<UUID, User> collectUsers(FieldSet fields, List<LockEntity> data) throws MyApplicationException {
if (fields.isEmpty() || data.isEmpty())
return null;
this.logger.debug("checking related - {}", User.class.getSimpleName());
Map<UUID, User> itemMap;
if (!fields.hasOtherField(this.asIndexer(User._id))) {
itemMap = this.asEmpty(
data.stream().map(LockEntity::getLockedBy).distinct().collect(Collectors.toList()),
x -> {
User item = new User();
item.setId(x);
return item;
},
User::getId);
} else {
FieldSet clone = new BaseFieldSet(fields.getFields()).ensure(User._id);
UserQuery q = this.queryFactory.query(UserQuery.class).authorize(this.authorize).ids(data.stream().map(LockEntity::getLockedBy).distinct().collect(Collectors.toList()));
itemMap = this.builderFactory.builder(UserBuilder.class).authorize(this.authorize).asForeignKey(q, clone, User::getId);
}
if (!fields.hasField(User._id)) {
itemMap.forEach((id, item) -> {
if (item != null)
item.setId(null);
});
}
return itemMap;
}
private Map<UUID, Tenant> collectTenants(FieldSet fields, List<LockEntity> datas) throws MyApplicationException {
if (fields.isEmpty() || datas.isEmpty()) return null;
this.logger.debug("checking related - {}", Tenant.class.getSimpleName());
Map<UUID, Tenant> itemMap = null;
if (!fields.hasOtherField(this.asIndexer(Tenant._id))) {
itemMap = this.asEmpty(
datas.stream().map(x -> x.getTenantId()).distinct().collect(Collectors.toList()),
x -> {
Tenant item = new Tenant();
item.setId(x);
return item;
},
x -> x.getId());
} else {
FieldSet clone = new BaseFieldSet(fields.getFields()).ensure(Tenant._id);
TenantQuery q = this.queryFactory.query(TenantQuery.class).authorize(this.authorize).ids(datas.stream().map(x -> x.getTenantId()).distinct().collect(Collectors.toList()));
itemMap = this.builderFactory.builder(TenantBuilder.class).authorize(this.authorize).asForeignKey(q, clone, x -> x.getId());
}
if (!fields.hasField(Tenant._id)) {
itemMap.values().stream().filter(x -> x != null).map(x -> {
x.setId(null);
return x;
}).collect(Collectors.toList());
}
return itemMap;
}
}

View File

@ -0,0 +1,51 @@
package eu.eudat.model.censorship;
import eu.eudat.authorization.OwnedResource;
import eu.eudat.authorization.Permission;
import eu.eudat.convention.ConventionService;
import eu.eudat.model.Lock;
import gr.cite.commons.web.authz.service.AuthorizationService;
import gr.cite.tools.data.censor.CensorFactory;
import gr.cite.tools.exception.MyForbiddenException;
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.List;
import java.util.UUID;
@Component
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class LockCensor extends BaseCensor {
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(LockCensor.class));
protected final AuthorizationService authService;
protected final CensorFactory censorFactory;
@Autowired
public LockCensor(
ConventionService conventionService,
AuthorizationService authService,
CensorFactory censorFactory
) {
super(conventionService);
this.authService = authService;
this.censorFactory = censorFactory;
}
public void censor(FieldSet fields, UUID userId) throws MyForbiddenException {
logger.debug(new DataLogEntry("censoring fields", fields));
if (this.isEmpty(fields)) return;
this.authService.authorizeAtLeastOneForce(userId != null ? List.of(new OwnedResource(userId)) : null, Permission.BrowseLock);
FieldSet tenantFields = fields.extractPrefixed(this.asIndexerPrefix(Lock._tenant));
this.censorFactory.censor(TenantCensor.class).censor(tenantFields, null);
FieldSet userFields = fields.extractPrefixed(this.asIndexerPrefix(Lock._lockedBy));
this.censorFactory.censor(UserCensor.class).censor(userFields, userId);
}
}

View File

@ -0,0 +1,71 @@
package eu.eudat.model.deleter;
import eu.eudat.data.LockEntity;
import eu.eudat.query.LockQuery;
import gr.cite.tools.data.deleter.Deleter;
import gr.cite.tools.data.deleter.DeleterFactory;
import gr.cite.tools.data.query.QueryFactory;
import gr.cite.tools.logging.LoggerService;
import gr.cite.tools.logging.MapLogEntry;
import jakarta.persistence.EntityManager;
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 javax.management.InvalidApplicationException;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
@Component
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class LockDeleter implements Deleter {
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(LockDeleter.class));
private final EntityManager entityManager;
protected final QueryFactory queryFactory;
protected final DeleterFactory deleterFactory;
@Autowired
public LockDeleter(
EntityManager entityManager,
QueryFactory queryFactory,
DeleterFactory deleterFactory
) {
this.entityManager = entityManager;
this.queryFactory = queryFactory;
this.deleterFactory = deleterFactory;
}
public void deleteAndSaveByIds(List<UUID> ids) throws InvalidApplicationException {
logger.debug(new MapLogEntry("collecting to delete").And("count", Optional.ofNullable(ids).map(List::size).orElse(0)).And("ids", ids));
List<LockEntity> data = this.queryFactory.query(LockQuery.class).ids(ids).collect();
logger.trace("retrieved {} items", Optional.ofNullable(data).map(List::size).orElse(0));
this.deleteAndSave(data);
}
public void deleteAndSave(List<LockEntity> data) throws InvalidApplicationException {
logger.debug("will delete {} items", Optional.ofNullable(data).map(List::size).orElse(0));
this.delete(data);
logger.trace("saving changes");
this.entityManager.flush();
logger.trace("changes saved");
}
public void delete(List<LockEntity> data) throws InvalidApplicationException {
logger.debug("will delete {} items", Optional.ofNullable(data).map(List::size).orElse(0));
if (data == null || data.isEmpty())
return;
for (LockEntity item : data) {
logger.trace("deleting item {}", item.getId());
this.entityManager.remove(item);
logger.trace("removed item");
}
}
}

View File

@ -82,6 +82,12 @@ public class UserDeleter implements Deleter {
UserContactInfoDeleter deleter = this.deleterFactory.deleter(UserContactInfoDeleter.class); UserContactInfoDeleter deleter = this.deleterFactory.deleter(UserContactInfoDeleter.class);
deleter.delete(items); deleter.delete(items);
} }
{
logger.debug("checking related - {}", TenantUserEntity.class.getSimpleName());
List<TenantUserEntity> items = this.queryFactory.query(TenantUserQuery.class).userIds(ids).collect();
TenantUserDeleter deleter = this.deleterFactory.deleter(TenantUserDeleter.class);
deleter.delete(items);
}
// { // {
// logger.debug("checking related - {}", DmpUserEntity.class.getSimpleName()); // logger.debug("checking related - {}", DmpUserEntity.class.getSimpleName());
// List<DmpUserEntity> items = this.queryFactory.query(DmpUserQuery.class).userIds(ids).collect(); // List<DmpUserEntity> items = this.queryFactory.query(DmpUserQuery.class).userIds(ids).collect();

View File

@ -0,0 +1,71 @@
package eu.eudat.model.persist;
import eu.eudat.commons.enums.LockTargetType;
import eu.eudat.commons.validation.FieldNotNullIfOtherSet;
import eu.eudat.commons.validation.ValidEnum;
import eu.eudat.commons.validation.ValidId;
import jakarta.validation.Valid;
import java.util.UUID;
@FieldNotNullIfOtherSet(message = "{validation.hashempty}")
public class LockPersist {
@ValidId(message = "{validation.invalidid}")
private UUID id;
@Valid
private UUID target;
@ValidEnum(message = "{validation.empty}")
private LockTargetType targetType;
@Valid
private UUID lockedBy;
public static final String _touchedAt = "touchedAt";
private String hash;
public static final String _hash = "hash";
public UUID getId() {
return id;
}
public void setId(UUID id) {
this.id = id;
}
public UUID getTarget() {
return target;
}
public void setTarget(UUID target) {
this.target = target;
}
public LockTargetType getTargetType() {
return targetType;
}
public void setTargetType(LockTargetType targetType) {
this.targetType = targetType;
}
public UUID getLockedBy() {
return lockedBy;
}
public void setLockedBy(UUID lockedBy) {
this.lockedBy = lockedBy;
}
public String getHash() {
return hash;
}
public void setHash(String hash) {
this.hash = hash;
}
}

View File

@ -0,0 +1,173 @@
package eu.eudat.query;
import eu.eudat.authorization.AuthorizationFlags;
import eu.eudat.commons.enums.LockTargetType;
import eu.eudat.data.LockEntity;
import eu.eudat.model.Lock;
import gr.cite.tools.data.query.FieldResolver;
import gr.cite.tools.data.query.QueryBase;
import gr.cite.tools.data.query.QueryContext;
import jakarta.persistence.Tuple;
import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.Predicate;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import java.time.Instant;
import java.util.*;
@Component
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class LockQuery extends QueryBase<LockEntity> {
private Collection<UUID> ids;
private Collection<UUID> targetIds;
private Collection<LockTargetType> targetTypes;
private Collection<UUID> excludedIds;
private EnumSet<AuthorizationFlags> authorize = EnumSet.of(AuthorizationFlags.None);
public LockQuery ids(UUID value) {
this.ids = List.of(value);
return this;
}
public LockQuery ids(UUID... value) {
this.ids = Arrays.asList(value);
return this;
}
public LockQuery ids(Collection<UUID> values) {
this.ids = values;
return this;
}
public LockQuery targetIds(UUID value) {
this.targetIds = List.of(value);
return this;
}
public LockQuery targetIds(UUID... value) {
this.targetIds = Arrays.asList(value);
return this;
}
public LockQuery targetIds(Collection<UUID> values) {
this.targetIds = values;
return this;
}
public LockQuery targetTypes(LockTargetType value) {
this.targetTypes = List.of(value);
return this;
}
public LockQuery targetTypes(LockTargetType... value) {
this.targetTypes = Arrays.asList(value);
return this;
}
public LockQuery targetTypes(Collection<LockTargetType> values) {
this.targetTypes = values;
return this;
}
public LockQuery excludedIds(Collection<UUID> values) {
this.excludedIds = values;
return this;
}
public LockQuery excludedIds(UUID value) {
this.excludedIds = List.of(value);
return this;
}
public LockQuery excludedIds(UUID... value) {
this.excludedIds = Arrays.asList(value);
return this;
}
public LockQuery authorize(EnumSet<AuthorizationFlags> values) {
this.authorize = values;
return this;
}
public LockQuery() {
}
@Override
protected Class<LockEntity> entityClass() {
return LockEntity.class;
}
@Override
protected Boolean isFalseQuery() {
return this.isEmpty(this.ids) || this.isEmpty(this.targetIds) || this.isEmpty(this.excludedIds) || this.isEmpty(this.targetTypes);
}
@Override
protected <X, Y> Predicate applyFilters(QueryContext<X, Y> queryContext) {
List<Predicate> predicates = new ArrayList<>();
if (this.ids != null) {
CriteriaBuilder.In<UUID> inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(LockEntity._id));
for (UUID item : this.ids)
inClause.value(item);
predicates.add(inClause);
}
if (this.targetIds != null) {
CriteriaBuilder.In<UUID> inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(LockEntity._target));
for (UUID item : this.targetIds)
inClause.value(item);
predicates.add(inClause);
}
if (this.targetTypes != null) {
CriteriaBuilder.In<LockTargetType> inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(LockEntity._targetType));
for (LockTargetType item : this.targetTypes)
inClause.value(item);
predicates.add(inClause);
}
if (this.excludedIds != null) {
CriteriaBuilder.In<UUID> notInClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(LockEntity._id));
for (UUID item : this.excludedIds)
notInClause.value(item);
predicates.add(notInClause.not());
}
if (!predicates.isEmpty()) {
Predicate[] predicatesArray = predicates.toArray(new Predicate[0]);
return queryContext.CriteriaBuilder.and(predicatesArray);
} else {
return null;
}
}
@Override
protected LockEntity convert(Tuple tuple, Set<String> columns) {
LockEntity item = new LockEntity();
item.setId(QueryBase.convertSafe(tuple, columns, LockEntity._id, UUID.class));
item.setTarget(QueryBase.convertSafe(tuple, columns, LockEntity._target, UUID.class));
item.setTargetType(QueryBase.convertSafe(tuple, columns, LockEntity._targetType, LockTargetType.class));
item.setLockedBy(QueryBase.convertSafe(tuple, columns, LockEntity._lockedBy, UUID.class));
item.setLockedAt(QueryBase.convertSafe(tuple, columns, LockEntity._lockedAt, Instant.class));
item.setTouchedAt(QueryBase.convertSafe(tuple, columns, LockEntity._touchedAt, Instant.class));
item.setTenantId(QueryBase.convertSafe(tuple, columns, LockEntity._tenantId, UUID.class));
return item;
}
@Override
protected String fieldNameOf(FieldResolver item) {
if (item.match(Lock._id)) return LockEntity._id;
else if (item.match(Lock._target)) return LockEntity._target;
else if (item.match(Lock._targetType)) return LockEntity._targetType;
else if (item.prefix(Lock._lockedBy)) return LockEntity._lockedBy;
else if (item.match(Lock._lockedAt)) return LockEntity._lockedAt;
else if (item.match(Lock._touchedAt)) return LockEntity._touchedAt;
else if (item.prefix(Lock._tenant)) return LockEntity._tenantId;
else if (item.match(Lock._hash)) return LockEntity._lockedAt;
else return null;
}
}

View File

@ -0,0 +1,66 @@
package eu.eudat.query.lookup;
import eu.eudat.commons.enums.LockTargetType;
import eu.eudat.query.LockQuery;
import gr.cite.tools.data.query.Lookup;
import gr.cite.tools.data.query.QueryFactory;
import java.util.List;
import java.util.UUID;
public class LockLookup extends Lookup {
private List<UUID> ids;
private List<UUID> targetIds;
private List<LockTargetType> targetTypes;
private List<UUID> excludedIds;
public List<UUID> getIds() {
return ids;
}
public void setIds(List<UUID> ids) {
this.ids = ids;
}
public List<UUID> getTargetIds() {
return targetIds;
}
public void setTargetIds(List<UUID> targetIds) {
this.targetIds = targetIds;
}
public List<UUID> getExcludedIds() {
return excludedIds;
}
public void setExcludedIds(List<UUID> excludeIds) {
this.excludedIds = excludeIds;
}
public List<LockTargetType> getTargetTypes() {
return targetTypes;
}
public void setTargetTypes(List<LockTargetType> targetTypes) {
this.targetTypes = targetTypes;
}
public LockQuery enrich(QueryFactory queryFactory) {
LockQuery query = queryFactory.query(LockQuery.class);
if (this.ids != null) query.ids(this.ids);
if (this.targetIds != null) query.targetIds(this.targetIds);
if (this.targetTypes != null) query.targetTypes(this.targetTypes);
if (this.excludedIds != null) query.excludedIds(this.excludedIds);
this.enrichCommon(query);
return query;
}
}

View File

@ -0,0 +1,24 @@
package eu.eudat.service.lock;
import eu.eudat.model.Lock;
import eu.eudat.model.persist.LockPersist;
import eu.eudat.query.lookup.LockLookup;
import gr.cite.tools.exception.MyApplicationException;
import gr.cite.tools.exception.MyForbiddenException;
import gr.cite.tools.exception.MyNotFoundException;
import gr.cite.tools.exception.MyValidationException;
import gr.cite.tools.fieldset.FieldSet;
import javax.management.InvalidApplicationException;
import java.util.UUID;
public interface LockService {
Lock persist(LockPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException;
boolean isLocked(LockLookup lookup) throws InvalidApplicationException;
void unlock(LockLookup lookup) throws InvalidApplicationException;
void deleteAndSave(UUID id) throws MyForbiddenException, InvalidApplicationException;
}

View File

@ -0,0 +1,188 @@
package eu.eudat.service.lock;
import eu.eudat.authorization.AuthorizationFlags;
import eu.eudat.authorization.Permission;
import eu.eudat.commons.scope.user.UserScope;
import eu.eudat.convention.ConventionService;
import eu.eudat.data.LockEntity;
import eu.eudat.errorcode.ErrorThesaurusProperties;
import eu.eudat.model.Lock;
import eu.eudat.model.builder.LockBuilder;
import eu.eudat.model.deleter.LockDeleter;
import eu.eudat.model.persist.LockPersist;
import eu.eudat.query.LockQuery;
import eu.eudat.query.lookup.LockLookup;
import gr.cite.commons.web.authz.service.AuthorizationService;
import gr.cite.tools.data.builder.BuilderFactory;
import gr.cite.tools.data.deleter.DeleterFactory;
import gr.cite.tools.data.query.QueryFactory;
import gr.cite.tools.exception.MyApplicationException;
import gr.cite.tools.exception.MyForbiddenException;
import gr.cite.tools.exception.MyNotFoundException;
import gr.cite.tools.exception.MyValidationException;
import gr.cite.tools.fieldset.BaseFieldSet;
import gr.cite.tools.fieldset.FieldSet;
import gr.cite.tools.logging.LoggerService;
import gr.cite.tools.logging.MapLogEntry;
import jakarta.persistence.EntityManager;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Service;
import javax.management.InvalidApplicationException;
import java.time.Instant;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.UUID;
@Service
public class LockServiceImpl implements LockService {
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(LockServiceImpl.class));
private final Comparator<LockEntity> compareByTouchedAt = Comparator.comparing(o -> o.getTouchedAt());
private final EntityManager entityManager;
private final UserScope userScope;
private final AuthorizationService authorizationService;
private final DeleterFactory deleterFactory;
private final BuilderFactory builderFactory;
private final QueryFactory queryFactory;
private final ConventionService conventionService;
private final MessageSource messageSource;
private final ErrorThesaurusProperties errors;
@Autowired
public LockServiceImpl(
EntityManager entityManager,
UserScope userScope,
AuthorizationService authorizationService,
DeleterFactory deleterFactory,
BuilderFactory builderFactory,
QueryFactory queryFactory,
ConventionService conventionService,
MessageSource messageSource,
ErrorThesaurusProperties errors) {
this.entityManager = entityManager;
this.userScope = userScope;
this.authorizationService = authorizationService;
this.deleterFactory = deleterFactory;
this.builderFactory = builderFactory;
this.queryFactory = queryFactory;
this.conventionService = conventionService;
this.messageSource = messageSource;
this.errors = errors;
}
public Lock persist(LockPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException {
logger.debug(new MapLogEntry("persisting data").And("model", model).And("fields", fields));
this.authorizationService.authorizeForce(Permission.EditLock);
Boolean isUpdate = this.conventionService.isValidGuid(model.getId());
LockEntity data;
if (isUpdate) {
data = this.entityManager.find(LockEntity.class, model.getId());
if (data == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{model.getId(), Lock.class.getSimpleName()}, LocaleContextHolder.getLocale()));
if (!data.getLockedBy().equals(this.userScope.getUserId())) throw new MyApplicationException("Is not locked by that user");
if (!this.conventionService.hashValue(data.getTouchedAt()).equals(model.getHash())) throw new MyValidationException(this.errors.getHashConflict().getCode(), this.errors.getHashConflict().getMessage());
} else {
data = new LockEntity();
data.setId(UUID.randomUUID());
data.setLockedAt(Instant.now());
data.setLockedBy(this.userScope.getUserId());
}
data.setTarget(model.getTarget());
data.setTargetType(model.getTargetType());
data.setTouchedAt(Instant.now());
if (isUpdate) this.entityManager.merge(data);
else this.entityManager.persist(data);
this.entityManager.flush();
return this.builderFactory.builder(LockBuilder.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermissionOrPublic).build(BaseFieldSet.build(fields, Lock._id), data);
}
public boolean isLocked(LockLookup lookup) throws InvalidApplicationException {
if (lookup !=null && lookup.getTargetIds() != null && lookup.getTargetIds().size() > 0){
LockQuery query = this.queryFactory.query(LockQuery.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermissionOrPublic).targetIds(lookup.getTargetIds());
if (query.count() == 1) {
LockEntity lock = query.firstAs(lookup.getProject());
if (lock.getLockedBy().equals(this.userScope.getUserId())) {
lock.setTouchedAt(Instant.now());
this.entityManager.merge(lock);
this.entityManager.flush();
return false;
}
return this.forceUnlock(lookup) > 0;
} else if (query.count() > 1) {
this.forceUnlock(lookup);
return this.isLocked(lookup);
}
return false;
} else{
throw new InvalidApplicationException("Wrong LockLookup");
}
}
private Long forceUnlock(LockLookup lookup) throws InvalidApplicationException {
LockQuery query = this.queryFactory.query(LockQuery.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermissionOrPublic).targetIds(lookup.getTargetIds());
Long availableLocks = query.count();
long deletedLocks = 0L;
if (availableLocks > 0) {
List<LockEntity> locks = query.collectAs(lookup.getProject());
for (LockEntity lock : locks) {
if (new Date().getTime() - Date.from(lock.getTouchedAt()).getTime() > 120000) {
this.deleteAndSave(lock.getId());
deletedLocks++;
}
}
if (deletedLocks == 0) {
LockEntity recentLock = locks.stream().max(compareByTouchedAt).get();
for (LockEntity lock : locks) {
if (lock != recentLock) {
this.deleteAndSave(lock.getId());
deletedLocks++;
}
}
}
}
return availableLocks - deletedLocks;
}
public void unlock(LockLookup lookup) throws InvalidApplicationException {
LockQuery query = this.queryFactory.query(LockQuery.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermissionOrPublic).targetIds(lookup.getTargetIds());
if (query.count() == 1) {
LockEntity lock = query.firstAs(lookup.getProject());
if (!lock.getLockedBy().equals(this.userScope.getUserId())) {
throw new InvalidApplicationException("Only the user who created that lock can delete it");
}
this.deleteAndSave(lock.getId());
} else if (query.count() > 1) {
List<LockEntity> locks = query.collectAs(lookup.getProject());
locks.stream().filter(lock -> lock.getLockedBy().equals(this.userScope.getUserIdSafe())).forEach(lock -> {
try {
this.deleteAndSave(lock.getId());
} catch (InvalidApplicationException e) {
throw new RuntimeException(e);
}
});
}
}
public void deleteAndSave(UUID id) throws MyForbiddenException, InvalidApplicationException {
logger.debug("deleting : {}", id);
this.authorizationService.authorizeForce(Permission.DeleteLock);
this.deleterFactory.deleter(LockDeleter.class).deleteAndSaveByIds(List.of(id));
}
}

View File

@ -1,65 +0,0 @@
package eu.eudat.controllers;
import eu.eudat.authorization.Permission;
import eu.eudat.logic.managers.LockManager;
import eu.eudat.models.data.helpers.responses.ResponseItem;
import eu.eudat.models.data.lock.Lock;
import eu.eudat.types.ApiMessageCode;
import gr.cite.commons.web.authz.service.AuthorizationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import java.util.UUID;
@RestController
@CrossOrigin
@RequestMapping(value = {"/api/lock/"})
public class LockController {
private LockManager lockManager;
private final AuthorizationService authorizationService;
@Autowired
public LockController(LockManager lockManager, AuthorizationService authorizationService) {
this.lockManager = lockManager;
this.authorizationService = authorizationService;
}
@Transactional
@RequestMapping(method = RequestMethod.GET, path = "target/status/{id}")
public @ResponseBody ResponseEntity<ResponseItem<Boolean>> getLocked(@PathVariable String id) throws Exception {
this.authorizationService.authorizeForce(Permission.AuthenticatedRole);
boolean locked = this.lockManager.isLocked(id);
return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem<Boolean>().status(ApiMessageCode.SUCCESS_MESSAGE).message("locked").payload(locked));
}
@Transactional
@RequestMapping(method = RequestMethod.DELETE, path = "target/unlock/{id}")
public @ResponseBody ResponseEntity<ResponseItem<String>> unlock(@PathVariable String id) throws Exception {
this.authorizationService.authorizeForce(Permission.AuthenticatedRole);
this.lockManager.unlock(id);
return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem<String>().status(ApiMessageCode.SUCCESS_MESSAGE).message("Created").payload("Lock Removed"));
}
@Transactional
@RequestMapping(method = RequestMethod.POST, consumes = "application/json", produces = "application/json")
public @ResponseBody ResponseEntity<ResponseItem<UUID>> createOrUpdate(@RequestBody Lock lock) throws Exception {
this.authorizationService.authorizeForce(Permission.AuthenticatedRole);
eu.eudat.data.old.Lock result = this.lockManager.createOrUpdate(lock);
return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem<UUID>().status(ApiMessageCode.SUCCESS_MESSAGE).message("Created").payload(result.getId()));
}
@RequestMapping(method = RequestMethod.GET, path = "target/{id}")
public @ResponseBody ResponseEntity<ResponseItem<Lock>> getSingle(@PathVariable String id) throws Exception {
this.authorizationService.authorizeForce(Permission.AuthenticatedRole);
Lock lock = this.lockManager.getFromTarget(id);
return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem<Lock>().status(ApiMessageCode.NO_MESSAGE).payload(lock));
}
}

View File

@ -0,0 +1,218 @@
package eu.eudat.controllers.v2;
import eu.eudat.audit.AuditableAction;
import eu.eudat.authorization.AuthorizationFlags;
import eu.eudat.authorization.Permission;
import eu.eudat.data.LockEntity;
import eu.eudat.model.Lock;
import eu.eudat.model.builder.LockBuilder;
import eu.eudat.model.censorship.LockCensor;
import eu.eudat.model.persist.LockPersist;
import eu.eudat.model.result.QueryResult;
import eu.eudat.models.data.helpers.responses.ResponseItem;
import eu.eudat.query.LockQuery;
import eu.eudat.query.lookup.LockLookup;
import eu.eudat.service.lock.LockService;
import eu.eudat.types.ApiMessageCode;
import gr.cite.commons.web.authz.service.AuthorizationService;
import gr.cite.tools.auditing.AuditService;
import gr.cite.tools.data.builder.BuilderFactory;
import gr.cite.tools.data.censor.CensorFactory;
import gr.cite.tools.data.query.QueryFactory;
import gr.cite.tools.exception.MyApplicationException;
import gr.cite.tools.exception.MyForbiddenException;
import gr.cite.tools.exception.MyNotFoundException;
import gr.cite.tools.fieldset.FieldSet;
import gr.cite.tools.logging.LoggerService;
import gr.cite.tools.logging.MapLogEntry;
import gr.cite.tools.validation.MyValidate;
import jakarta.transaction.Transactional;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.management.InvalidApplicationException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.AbstractMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
@RestController
@RequestMapping(path = {"api/lock"})
public class LockController {
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(LockController.class));
private final BuilderFactory builderFactory;
private final AuditService auditService;
private final LockService lockService;
private final CensorFactory censorFactory;
private final QueryFactory queryFactory;
private final MessageSource messageSource;
private final AuthorizationService authorizationService;
@Autowired
public LockController(BuilderFactory builderFactory,
AuditService auditService,
LockService lockService,
CensorFactory censorFactory,
QueryFactory queryFactory,
MessageSource messageSource,
AuthorizationService authorizationService) {
this.builderFactory = builderFactory;
this.auditService = auditService;
this.lockService = lockService;
this.censorFactory = censorFactory;
this.queryFactory = queryFactory;
this.messageSource = messageSource;
this.authorizationService = authorizationService;
}
@PostMapping("query")
public QueryResult<Lock> query(@RequestBody LockLookup lookup) throws MyApplicationException, MyForbiddenException, InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException {
logger.debug("querying {}", Lock.class.getSimpleName());
this.censorFactory.censor(LockCensor.class).censor(lookup.getProject(), null);
LockQuery query = lookup.enrich(this.queryFactory).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermissionOrPublic);
List<LockEntity> data = query.collectAs(lookup.getProject());
List<Lock> models = this.builderFactory.builder(LockBuilder.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermissionOrPublic).build(lookup.getProject(), data);
long count = (lookup.getMetadata() != null && lookup.getMetadata().getCountAll()) ? query.count() : models.size();
this.auditService.track(AuditableAction.Lock_Query, "lookup", lookup);
return new QueryResult(models, count);
}
@GetMapping("{id}")
public Lock get(@PathVariable("id") UUID id, FieldSet fieldSet) throws MyApplicationException, MyForbiddenException, MyNotFoundException {
logger.debug(new MapLogEntry("retrieving" + Lock.class.getSimpleName()).And("id", id).And("fields", fieldSet));
this.censorFactory.censor(LockCensor.class).censor(fieldSet, null);
LockQuery query = this.queryFactory.query(LockQuery.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermissionOrPublic).ids(id);
Lock model = this.builderFactory.builder(LockBuilder.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermissionOrPublic).build(fieldSet, query.firstAs(fieldSet));
if (model == null)
throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{id, Lock.class.getSimpleName()}, LocaleContextHolder.getLocale()));
this.auditService.track(AuditableAction.Lock_Lookup, Map.ofEntries(
new AbstractMap.SimpleEntry<String, Object>("id", id),
new AbstractMap.SimpleEntry<String, Object>("fields", fieldSet)
));
return model;
}
@PostMapping("persist")
@Transactional
public Lock persist(@MyValidate @RequestBody LockPersist model, FieldSet fieldSet) throws MyApplicationException, MyForbiddenException, MyNotFoundException, InvalidApplicationException {
logger.debug(new MapLogEntry("persisting" + Lock.class.getSimpleName()).And("model", model).And("fieldSet", fieldSet));
this.censorFactory.censor(LockCensor.class).censor(fieldSet, null);
Lock persisted = this.lockService.persist(model, fieldSet);
this.auditService.track(AuditableAction.Lock_Persist, Map.ofEntries(
new AbstractMap.SimpleEntry<String, Object>("model", model),
new AbstractMap.SimpleEntry<String, Object>("fields", fieldSet)
));
return persisted;
}
@GetMapping("target/{id}")
public Lock getWithTarget(@PathVariable("id") UUID targetId, FieldSet fieldSet) throws MyApplicationException, MyForbiddenException, MyNotFoundException {
logger.debug(new MapLogEntry("retrieving" + Lock.class.getSimpleName()).And("targetId", targetId).And("fields", fieldSet));
this.censorFactory.censor(LockCensor.class).censor(fieldSet, null);
LockQuery query = this.queryFactory.query(LockQuery.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermissionOrPublic).targetIds(targetId);
Lock model = this.builderFactory.builder(LockBuilder.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermissionOrPublic).build(fieldSet, query.firstAs(fieldSet));
if (model == null)
throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{targetId, Lock.class.getSimpleName()}, LocaleContextHolder.getLocale()));
this.auditService.track(AuditableAction.Lock_Lookup, Map.ofEntries(
new AbstractMap.SimpleEntry<String, Object>("targetId", targetId),
new AbstractMap.SimpleEntry<String, Object>("fields", fieldSet)
));
return model;
}
@Transactional
@PostMapping("target/status/{id}")
public @ResponseBody ResponseEntity<ResponseItem<Boolean>> getLocked(@RequestBody LockLookup lookup) throws Exception {
this.authorizationService.authorizeForce(Permission.AuthenticatedRole);
boolean locked = this.lockService.isLocked(lookup);
return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem<Boolean>().status(ApiMessageCode.SUCCESS_MESSAGE).message("locked").payload(locked));
}
@Transactional
@PostMapping("target/unlock/{id}")
public @ResponseBody ResponseEntity<ResponseItem<String>> unlock(@RequestBody LockLookup lookup) throws Exception {
this.authorizationService.authorizeForce(Permission.AuthenticatedRole);
this.lockService.unlock(lookup);
return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem<String>().status(ApiMessageCode.SUCCESS_MESSAGE).message("Created").payload("Lock Removed"));
}
@DeleteMapping("{id}")
@Transactional
public void delete(@PathVariable("id") UUID id) throws MyForbiddenException, InvalidApplicationException {
logger.debug(new MapLogEntry("retrieving" + Lock.class.getSimpleName()).And("id", id));
this.lockService.deleteAndSave(id);
this.auditService.track(AuditableAction.Lock_Delete, "id", id);
}
// @Transactional
// @RequestMapping(method = RequestMethod.GET, path = "target/status/{id}")
// public @ResponseBody ResponseEntity<ResponseItem<Boolean>> getLocked(@PathVariable String id) throws Exception {
// this.authorizationService.authorizeForce(Permission.AuthenticatedRole);
//
// boolean locked = this.lockManager.isLocked(id);
// return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem<Boolean>().status(ApiMessageCode.SUCCESS_MESSAGE).message("locked").payload(locked));
// }
//
// @Transactional
// @RequestMapping(method = RequestMethod.DELETE, path = "target/unlock/{id}")
// public @ResponseBody ResponseEntity<ResponseItem<String>> unlock(@PathVariable String id) throws Exception {
// this.authorizationService.authorizeForce(Permission.AuthenticatedRole);
//
// this.lockManager.unlock(id);
// return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem<String>().status(ApiMessageCode.SUCCESS_MESSAGE).message("Created").payload("Lock Removed"));
// }
//
// @Transactional
// @RequestMapping(method = RequestMethod.POST, consumes = "application/json", produces = "application/json")
// public @ResponseBody ResponseEntity<ResponseItem<UUID>> createOrUpdate(@RequestBody Lock lock) throws Exception {
// this.authorizationService.authorizeForce(Permission.AuthenticatedRole);
//
// eu.eudat.data.old.Lock result = this.lockManager.createOrUpdate(lock);
// return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem<UUID>().status(ApiMessageCode.SUCCESS_MESSAGE).message("Created").payload(result.getId()));
// }
//
// @RequestMapping(method = RequestMethod.GET, path = "target/{id}")
// public @ResponseBody ResponseEntity<ResponseItem<Lock>> getSingle(@PathVariable String id) throws Exception {
// this.authorizationService.authorizeForce(Permission.AuthenticatedRole);
//
// Lock lock = this.lockManager.getFromTarget(id);
// return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem<Lock>().status(ApiMessageCode.NO_MESSAGE).payload(lock));
// }
}

View File

@ -634,3 +634,24 @@ permissions:
clients: [ ] clients: [ ]
allowAnonymous: false allowAnonymous: false
allowAuthenticated: false allowAuthenticated: false
# Lock Permissions
BrowseLock:
roles:
- Admin
clients: [ ]
allowAnonymous: false
allowAuthenticated: false
EditLock:
roles:
- Admin
clients: [ ]
allowAnonymous: false
allowAuthenticated: false
DeleteLock:
roles:
- Admin
claims: [ ]
clients: [ ]
allowAnonymous: false
allowAuthenticated: false

View File

@ -0,0 +1,33 @@
DO $$DECLARE
this_version CONSTANT varchar := '00.01.039';
BEGIN
PERFORM * FROM "DBVersion" WHERE version = this_version;
IF FOUND THEN RETURN; END IF;
DROP TABLE public."Lock";
CREATE TABLE public."Lock"
(
id uuid NOT NULL,
target uuid NOT NULL,
target_type smallint NOT NULL,
locked_by uuid NOT NULL,
locked_at timestamp without time zone NOT NULL,
touched_at timestamp without time zone,
tenant uuid,
CONSTRAINT "Lock_pkey" PRIMARY KEY (id),
CONSTRAINT "Lock_lockedby_fkey" FOREIGN KEY (locked_by)
REFERENCES public."User" (id) MATCH SIMPLE
ON UPDATE NO ACTION
ON DELETE NO ACTION
NOT VALID,
CONSTRAINT "Lock_tenant_fkey" FOREIGN KEY (tenant)
REFERENCES public."Tenant" (id) MATCH SIMPLE
ON UPDATE NO ACTION
ON DELETE NO ACTION
NOT VALID
);
INSERT INTO public."DBVersion" VALUES ('DMPDB', '00.01.039', '2023-12-08 12:00:00.000000+02', now(), 'Drop old Lock Table and create New Lock table.');
END$$;

View File

@ -0,0 +1,4 @@
export enum LockTargetType {
Dmp = 0,
Description = 1
}

View File

@ -1,6 +1,9 @@
import { Guid } from '@common/types/guid'; import { Guid } from '@common/types/guid';
import { UserInfoListingModel } from '../user/user-info-listing'; import { UserInfoListingModel } from '../user/user-info-listing';
import { LockTargetType } from '@app/core/common/enum/lock-target-type';
import { User } from '../user/user';
// old model
export class LockModel { export class LockModel {
id: Guid; id: Guid;
target: Guid; target: Guid;
@ -16,3 +19,24 @@ export class LockModel {
} }
} }
export interface Lock{
id: Guid;
target: Guid;
targetType: LockTargetType;
lockedBy: User;
lockedAt: Date;
touchedAt: Date;
hash: String;
}
// Persist
export interface LockPersist{
id: Guid;
target: Guid;
targetType: LockTargetType;
lockedBy: User;
hash: String;
}

View File

@ -0,0 +1,21 @@
import { Lookup } from "@common/model/lookup";
import { Guid } from "@common/types/guid";
import { LockTargetType } from "../common/enum/lock-target-type";
export class LockLookup extends Lookup implements LockLookup {
ids: Guid[];
excludedIds: Guid[];
targetIds: Guid[];
targetTypes: LockTargetType[];
constructor() {
super();
}
}
export interface LockLookup {
ids: Guid[];
excludedIds: Guid[];
targetIds: Guid[];
targetTypes: LockTargetType[];
}

View File

@ -1,34 +1,76 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { HttpHeaders, HttpClient } from '@angular/common/http'; import { HttpHeaders, HttpClient } from '@angular/common/http';
import { BaseHttpService } from '../http/base-http.service'; import { Observable, throwError } from 'rxjs';
import { environment } from 'environments/environment'; import { Lock, LockModel, LockPersist } from '@app/core/model/lock/lock.model';
import { Observable } from 'rxjs';
import { LockModel } from '@app/core/model/lock/lock.model';
import { ConfigurationService } from '../configuration/configuration.service'; import { ConfigurationService } from '../configuration/configuration.service';
import { BaseHttpV2Service } from '../http/base-http-v2.service';
import { FilterService } from '@common/modules/text-filter/filter-service';
import { LockLookup } from '@app/core/query/lock.lookup';
import { QueryResult } from '@common/model/query-result';
import { catchError } from 'rxjs/operators';
import { Guid } from '@common/types/guid';
@Injectable() @Injectable()
export class LockService { export class LockService {
private actionUrl: string;
private headers = new HttpHeaders(); private headers = new HttpHeaders();
constructor(private http: BaseHttpService, private httpClient: HttpClient, private configurationService: ConfigurationService) { constructor(private http: BaseHttpV2Service, private configurationService: ConfigurationService, private filterService: FilterService) {
this.actionUrl = configurationService.server + 'lock/';
} }
private get apiBase(): string { return `${this.configurationService.server}lock`; }
query(q: LockLookup): Observable<QueryResult<Lock>> {
const url = `${this.apiBase}/query`;
return this.http.post<QueryResult<Lock>>(url, q).pipe(catchError((error: any) => throwError(error)));
}
getSingle(id: Guid, reqFields: string[] = []): Observable<Lock> {
const url = `${this.apiBase}/${id}`;
const options = { params: { f: reqFields } };
return this.http
.get<Lock>(url, options).pipe(
catchError((error: any) => throwError(error)));
}
persist(item: LockPersist): Observable<Lock> {
const url = `${this.apiBase}/persist`;
return this.http
.post<Lock>(url, item).pipe(
catchError((error: any) => throwError(error)));
}
delete(id: Guid): Observable<Lock> {
const url = `${this.apiBase}/${id}`;
return this.http
.delete<Lock>(url).pipe(
catchError((error: any) => throwError(error)));
}
//ToDo change Parameters
checkLockStatus(id: string): Observable<boolean> { checkLockStatus(id: string): Observable<boolean> {
return this.http.get(`${this.actionUrl}target/status/${id}`, { headers: this.headers }); return this.http.get(`${this.apiBase}/target/status/${id}`, { headers: this.headers });
} }
//ToDo change Parameters
unlockTarget(id: string): Observable<any> { unlockTarget(id: string): Observable<any> {
return this.http.delete(`${this.actionUrl}target/unlock/${id}`, { headers: this.headers }); return this.http.delete(`${this.apiBase}/target/unlock/${id}`, { headers: this.headers });
} }
getSingle(id: string): Observable<LockModel> { getSingleWithTarget(targetId: Guid, reqFields: string[] = []): Observable<Lock> {
return this.http.get(`${this.actionUrl}target/${id}`, { headers: this.headers }); const url = `${this.apiBase}/target/${targetId}`;
const options = { params: { f: reqFields } };
return this.http
.get<Lock>(url, options).pipe(
catchError((error: any) => throwError(error)));
} }
//ToDo replace with persist function
createOrUpdate(lock: LockModel): Observable<string> { createOrUpdate(lock: LockModel): Observable<string> {
return this.http.post(`${this.actionUrl}`, lock, { headers: this.headers }); return this.http.post(`${this.apiBase}`, lock, { headers: this.headers });
} }
} }