Merge branch 'dmp-refactoring' of https://code-repo.d4science.org/MaDgiK-CITE/argos into dmp-refactoring
This commit is contained in:
commit
dcbaf92128
|
@ -67,7 +67,7 @@ public class TenantScope {
|
|||
this.tenant.set(tenant);
|
||||
this.tenantCode.set(tenantCode);
|
||||
|
||||
if (this.tenant.get() != null && !this.isDefaultTenant()) {
|
||||
if (this.tenant.get() != null || this.isDefaultTenant()) {
|
||||
if(!this.isDefaultTenant()) {
|
||||
entityManager
|
||||
.unwrap(Session.class)
|
||||
|
@ -84,7 +84,7 @@ public class TenantScope {
|
|||
public void removeTempTenant(EntityManager entityManager) {
|
||||
this.tenant.set(this.initialTenant.get());
|
||||
this.tenantCode.set(this.initialTenantCode.get());
|
||||
if (this.initialTenant.get() != null && !this.isDefaultTenant()) {
|
||||
if (this.initialTenant.get() != null || this.isDefaultTenant()) {
|
||||
if(!this.isDefaultTenant()) {
|
||||
entityManager
|
||||
.unwrap(Session.class)
|
||||
|
|
|
@ -39,9 +39,13 @@ public class User {
|
|||
|
||||
public static final String _contacts = "contacts";
|
||||
|
||||
private List<UserRole> roles;
|
||||
private List<UserRole> globalRoles;
|
||||
|
||||
public static final String _roles = "roles";
|
||||
public static final String _globalRoles = "globalRoles";
|
||||
|
||||
private List<UserRole> tenantRoles;
|
||||
|
||||
public static final String _tenantRoles = "tenantRoles";
|
||||
|
||||
private List<UserCredential> credentials;
|
||||
|
||||
|
@ -114,14 +118,6 @@ public class User {
|
|||
this.contacts = contacts;
|
||||
}
|
||||
|
||||
public List<UserRole> getRoles() {
|
||||
return roles;
|
||||
}
|
||||
|
||||
public void setRoles(List<UserRole> roles) {
|
||||
this.roles = roles;
|
||||
}
|
||||
|
||||
public List<UserCredential> getCredentials() {
|
||||
return credentials;
|
||||
}
|
||||
|
@ -137,4 +133,20 @@ public class User {
|
|||
public void setTenantUsers(List<TenantUser> tenantUsers) {
|
||||
this.tenantUsers = tenantUsers;
|
||||
}
|
||||
|
||||
public List<UserRole> getTenantRoles() {
|
||||
return tenantRoles;
|
||||
}
|
||||
|
||||
public void setTenantRoles(List<UserRole> tenantRoles) {
|
||||
this.tenantRoles = tenantRoles;
|
||||
}
|
||||
|
||||
public List<UserRole> getGlobalRoles() {
|
||||
return globalRoles;
|
||||
}
|
||||
|
||||
public void setGlobalRoles(List<UserRole> globalRoles) {
|
||||
this.globalRoles = globalRoles;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,18 +1,21 @@
|
|||
package eu.eudat.model.builder;
|
||||
|
||||
import eu.eudat.authorization.AuthorizationFlags;
|
||||
import eu.eudat.authorization.AuthorizationProperties;
|
||||
import eu.eudat.commons.JsonHandlingService;
|
||||
import eu.eudat.commons.scope.tenant.TenantScope;
|
||||
import eu.eudat.commons.types.user.AdditionalInfoEntity;
|
||||
import eu.eudat.convention.ConventionService;
|
||||
import eu.eudat.data.TenantEntity;
|
||||
import eu.eudat.data.TenantEntityManager;
|
||||
import eu.eudat.data.UserEntity;
|
||||
import eu.eudat.model.*;
|
||||
import eu.eudat.query.TenantUserQuery;
|
||||
import eu.eudat.query.UserContactInfoQuery;
|
||||
import eu.eudat.query.UserCredentialQuery;
|
||||
import eu.eudat.query.UserRoleQuery;
|
||||
import eu.eudat.query.*;
|
||||
import gr.cite.tools.data.builder.BuilderFactory;
|
||||
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.BaseFieldSet;
|
||||
import gr.cite.tools.fieldset.FieldSet;
|
||||
import gr.cite.tools.logging.DataLogEntry;
|
||||
|
@ -20,9 +23,12 @@ 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.MessageSource;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.context.i18n.LocaleContextHolder;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.management.InvalidApplicationException;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
@ -34,17 +40,26 @@ public class UserBuilder extends BaseBuilder<User, UserEntity> {
|
|||
|
||||
private final BuilderFactory builderFactory;
|
||||
private final JsonHandlingService jsonHandlingService;
|
||||
private final AuthorizationProperties authorizationProperties;
|
||||
private final TenantEntityManager tenantEntityManager;
|
||||
private final TenantScope tenantScope;
|
||||
|
||||
private final MessageSource messageSource;
|
||||
|
||||
private EnumSet<AuthorizationFlags> authorize = EnumSet.of(AuthorizationFlags.None);
|
||||
|
||||
@Autowired
|
||||
public UserBuilder(ConventionService conventionService,
|
||||
QueryFactory queryFactory,
|
||||
BuilderFactory builderFactory, JsonHandlingService jsonHandlingService) {
|
||||
BuilderFactory builderFactory, JsonHandlingService jsonHandlingService, AuthorizationProperties authorizationProperties, TenantEntityManager tenantEntityManager, TenantScope tenantScope, MessageSource messageSource) {
|
||||
super(conventionService, new LoggerService(LoggerFactory.getLogger(UserBuilder.class)));
|
||||
this.queryFactory = queryFactory;
|
||||
this.builderFactory = builderFactory;
|
||||
this.jsonHandlingService = jsonHandlingService;
|
||||
this.authorizationProperties = authorizationProperties;
|
||||
this.tenantEntityManager = tenantEntityManager;
|
||||
this.tenantScope = tenantScope;
|
||||
this.messageSource = messageSource;
|
||||
}
|
||||
|
||||
public UserBuilder authorize(EnumSet<AuthorizationFlags> values) {
|
||||
|
@ -64,8 +79,11 @@ public class UserBuilder extends BaseBuilder<User, UserEntity> {
|
|||
FieldSet contactsFields = fields.extractPrefixed(this.asPrefix(User._contacts));
|
||||
Map<UUID, List<UserContactInfo>> contactsMap = this.collectUserContactInfos(contactsFields, data);
|
||||
|
||||
FieldSet rolesFields = fields.extractPrefixed(this.asPrefix(User._roles));
|
||||
Map<UUID, List<UserRole>> rolesMap = this.collectUserRoles(rolesFields, data);
|
||||
FieldSet globalRolesFields = fields.extractPrefixed(this.asPrefix(User._globalRoles));
|
||||
Map<UUID, List<UserRole>> globalRolesMap = this.collectUserGlobalRoles(globalRolesFields, data);
|
||||
|
||||
FieldSet tenantRolesFields = fields.extractPrefixed(this.asPrefix(User._tenantRoles));
|
||||
Map<UUID, List<UserRole>> tenantRolesMap = this.collectUserTenantRoles(tenantRolesFields, data);
|
||||
|
||||
FieldSet credentialsFields = fields.extractPrefixed(this.asPrefix(User._credentials));
|
||||
Map<UUID, List<UserCredential>> credentialsMap = this.collectUserCredentials(credentialsFields, data);
|
||||
|
@ -83,7 +101,8 @@ public class UserBuilder extends BaseBuilder<User, UserEntity> {
|
|||
if (fields.hasField(this.asIndexer(User._isActive))) m.setIsActive(d.getIsActive());
|
||||
if (fields.hasField(this.asIndexer(User._hash))) m.setHash(this.hashValue(d.getUpdatedAt()));
|
||||
if (contactsMap != null && !contactsFields.isEmpty() && contactsMap.containsKey(d.getId())) m.setContacts(contactsMap.get(d.getId()));
|
||||
if (rolesMap != null && !rolesFields.isEmpty() && rolesMap.containsKey(d.getId())) m.setRoles(rolesMap.get(d.getId()));
|
||||
if (globalRolesMap != null && !globalRolesFields.isEmpty() && globalRolesMap.containsKey(d.getId())) m.setGlobalRoles(globalRolesMap.get(d.getId()));
|
||||
if (tenantRolesMap != null && !tenantRolesFields.isEmpty() && tenantRolesMap.containsKey(d.getId())) m.setTenantRoles(tenantRolesMap.get(d.getId()));
|
||||
if (credentialsMap != null && !credentialsFields.isEmpty() && credentialsMap.containsKey(d.getId())) m.setCredentials(credentialsMap.get(d.getId()));
|
||||
if (!additionalInfoFields.isEmpty() && d.getAdditionalInfo() != null){
|
||||
AdditionalInfoEntity definition = this.jsonHandlingService.fromJsonSafe(AdditionalInfoEntity.class, d.getAdditionalInfo());
|
||||
|
@ -115,13 +134,42 @@ public class UserBuilder extends BaseBuilder<User, UserEntity> {
|
|||
return itemMap;
|
||||
}
|
||||
|
||||
private Map<UUID, List<UserRole>> collectUserRoles(FieldSet fields, List<UserEntity> data) throws MyApplicationException {
|
||||
private Map<UUID, List<UserRole>> collectUserGlobalRoles(FieldSet fields, List<UserEntity> data) throws MyApplicationException {
|
||||
if (fields.isEmpty() || data.isEmpty()) return null;
|
||||
this.logger.debug("checking related - {}", UserRole.class.getSimpleName());
|
||||
|
||||
Map<UUID, List<UserRole>> itemMap;
|
||||
FieldSet clone = new BaseFieldSet(fields.getFields()).ensure(this.asIndexer(UserRole._user, User._id));
|
||||
UserRoleQuery query = this.queryFactory.query(UserRoleQuery.class).authorize(this.authorize).userIds(data.stream().map(UserEntity::getId).distinct().collect(Collectors.toList()));
|
||||
UserRoleQuery query = this.queryFactory.query(UserRoleQuery.class).authorize(this.authorize).tenantIsSet(false).roles(this.authorizationProperties.getAllowedGlobalRoles()).userIds(data.stream().map(UserEntity::getId).distinct().collect(Collectors.toList()));
|
||||
itemMap = this.builderFactory.builder(UserRoleBuilder.class).authorize(this.authorize).asMasterKey(query, clone, x -> x.getUser().getId());
|
||||
|
||||
if (!fields.hasField(this.asIndexer(UserRole._user, User._id))) {
|
||||
itemMap.values().stream().flatMap(List::stream).filter(x -> x != null && x.getUser() != null).peek(x -> {
|
||||
x.getUser().setId(null);
|
||||
});
|
||||
}
|
||||
|
||||
return itemMap;
|
||||
}
|
||||
|
||||
private Map<UUID, List<UserRole>> collectUserTenantRoles(FieldSet fields, List<UserEntity> data) throws MyApplicationException {
|
||||
if (fields.isEmpty() || data.isEmpty()) return null;
|
||||
this.logger.debug("checking related - {}", UserRole.class.getSimpleName());
|
||||
Map<UUID, List<UserRole>> itemMap;
|
||||
FieldSet clone = new BaseFieldSet(fields.getFields()).ensure(this.asIndexer(UserRole._user, User._id));
|
||||
|
||||
if (!tenantScope.isSet()) throw new MyForbiddenException("tenant scope required");
|
||||
|
||||
UserRoleQuery query = this.queryFactory.query(UserRoleQuery.class).authorize(this.authorize).roles(this.authorizationProperties.getAllowedTenantRoles()).userIds(data.stream().map(UserEntity::getId).distinct().collect(Collectors.toList()));
|
||||
if (tenantScope.isDefaultTenant()) query.tenantIsSet(false);
|
||||
else {
|
||||
try {
|
||||
query.tenantIsSet(true).tenantIds(this.tenantScope.getTenant());
|
||||
} catch (InvalidApplicationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
itemMap = this.builderFactory.builder(UserRoleBuilder.class).authorize(this.authorize).asMasterKey(query, clone, x -> x.getUser().getId());
|
||||
|
||||
if (!fields.hasField(this.asIndexer(UserRole._user, User._id))) {
|
||||
|
|
|
@ -39,8 +39,11 @@ public class UserCensor extends BaseCensor {
|
|||
return;
|
||||
this.authService.authorizeAtLeastOneForce(userId != null ? List.of(new OwnedResource(userId)) : null, Permission.BrowseUser, Permission.DeferredAffiliation);
|
||||
|
||||
FieldSet rolesFields = fields.extractPrefixed(this.asIndexerPrefix(User._roles));
|
||||
this.censorFactory.censor(UserRoleCensor.class).censor(rolesFields, userId);
|
||||
FieldSet globalRolesFields = fields.extractPrefixed(this.asIndexerPrefix(User._globalRoles));
|
||||
this.censorFactory.censor(UserRoleCensor.class).censor(globalRolesFields, userId);
|
||||
|
||||
FieldSet tenantRolesFields = fields.extractPrefixed(this.asIndexerPrefix(User._tenantRoles));
|
||||
this.censorFactory.censor(UserRoleCensor.class).censor(tenantRolesFields, userId);
|
||||
|
||||
FieldSet contactsFields = fields.extractPrefixed(this.asIndexerPrefix(User._contacts));
|
||||
this.censorFactory.censor(UserContactInfoCensor.class).censor(contactsFields, userId);
|
||||
|
|
|
@ -4,10 +4,7 @@ import eu.eudat.authorization.AuthorizationFlags;
|
|||
import eu.eudat.authorization.Permission;
|
||||
import eu.eudat.commons.enums.*;
|
||||
import eu.eudat.commons.scope.user.UserScope;
|
||||
import eu.eudat.data.DmpDescriptionTemplateEntity;
|
||||
import eu.eudat.data.DmpEntity;
|
||||
import eu.eudat.data.DmpReferenceEntity;
|
||||
import eu.eudat.data.DmpUserEntity;
|
||||
import eu.eudat.data.*;
|
||||
import eu.eudat.model.Dmp;
|
||||
import eu.eudat.model.PublicDmp;
|
||||
import eu.eudat.query.utils.QueryUtilsService;
|
||||
|
@ -364,6 +361,11 @@ public class DmpQuery extends QueryBase<DmpEntity> {
|
|||
predicates.add(queryContext.CriteriaBuilder.in(queryContext.Root.get(DmpEntity._id)).value(subQuery.Query));
|
||||
}
|
||||
|
||||
if (this.entityDoiQuery != null) {
|
||||
QueryContext<EntityDoiEntity, UUID> subQuery = this.applySubQuery(this.entityDoiQuery, queryContext, UUID.class, entityDoiEntityRoot -> entityDoiEntityRoot.get(EntityDoiEntity._entityId));
|
||||
predicates.add(queryContext.CriteriaBuilder.in(queryContext.Root.get(DmpEntity._id)).value(subQuery.Query));
|
||||
}
|
||||
|
||||
if (!predicates.isEmpty()) {
|
||||
Predicate[] predicatesArray = predicates.toArray(new Predicate[0]);
|
||||
return queryContext.CriteriaBuilder.and(predicatesArray);
|
||||
|
|
|
@ -27,6 +27,7 @@ public class TenantQuery extends QueryBase<TenantEntity> {
|
|||
|
||||
private String like;
|
||||
private Collection<UUID> ids;
|
||||
private Collection<String> codes;
|
||||
private Collection<IsActive> isActives;
|
||||
private Collection<UUID> excludedIds;
|
||||
private EnumSet<AuthorizationFlags> authorize = EnumSet.of(AuthorizationFlags.None);
|
||||
|
@ -58,6 +59,21 @@ public class TenantQuery extends QueryBase<TenantEntity> {
|
|||
return this;
|
||||
}
|
||||
|
||||
public TenantQuery codes(String value) {
|
||||
this.codes = List.of(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TenantQuery codes(String... value) {
|
||||
this.codes = Arrays.asList(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TenantQuery codes(Collection<String> values) {
|
||||
this.codes = values;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TenantQuery isActive(IsActive value) {
|
||||
this.isActives = List.of(value);
|
||||
return this;
|
||||
|
@ -95,7 +111,7 @@ public class TenantQuery extends QueryBase<TenantEntity> {
|
|||
|
||||
@Override
|
||||
protected Boolean isFalseQuery() {
|
||||
return this.isEmpty(this.ids) || this.isEmpty(this.isActives);
|
||||
return this.isEmpty(this.ids) || this.isEmpty(this.codes) ||this.isEmpty(this.isActives);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -112,6 +128,12 @@ public class TenantQuery extends QueryBase<TenantEntity> {
|
|||
predicates.add(inClause);
|
||||
}
|
||||
|
||||
if (this.codes != null) {
|
||||
CriteriaBuilder.In<String> inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(TenantEntity._code));
|
||||
for (String item : this.codes) inClause.value(item);
|
||||
predicates.add(inClause);
|
||||
}
|
||||
|
||||
if (this.like != null && !this.like.isEmpty()) {
|
||||
predicates.add(queryContext.CriteriaBuilder.or(queryUtilsService.ilike(queryContext.CriteriaBuilder, queryContext.Root.get(TenantEntity._code), this.like),
|
||||
queryUtilsService.ilike(queryContext.CriteriaBuilder, queryContext.Root.get(TenantEntity._name), this.like)
|
||||
|
|
|
@ -26,6 +26,8 @@ public class UserRoleQuery extends QueryBase<UserRoleEntity> {
|
|||
private Collection<UUID> excludedIds;
|
||||
private Collection<UUID> userIds;
|
||||
private Collection<String> roles;
|
||||
private Collection<UUID> tenantIds;
|
||||
private Boolean tenantIsSet;
|
||||
|
||||
private EnumSet<AuthorizationFlags> authorize = EnumSet.of(AuthorizationFlags.None);
|
||||
|
||||
|
@ -81,6 +83,26 @@ public class UserRoleQuery extends QueryBase<UserRoleEntity> {
|
|||
return this;
|
||||
}
|
||||
|
||||
public UserRoleQuery tenantIds(UUID value) {
|
||||
this.tenantIds = List.of(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public UserRoleQuery tenantIds(UUID... value) {
|
||||
this.tenantIds = Arrays.asList(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public UserRoleQuery tenantIds(Collection<UUID> values) {
|
||||
this.tenantIds = values;
|
||||
return this;
|
||||
}
|
||||
|
||||
public UserRoleQuery tenantIsSet(Boolean value) {
|
||||
this.tenantIsSet = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
public UserRoleQuery roles(String value) {
|
||||
this.roles = List.of(value);
|
||||
return this;
|
||||
|
@ -107,6 +129,7 @@ public class UserRoleQuery extends QueryBase<UserRoleEntity> {
|
|||
this.isEmpty(this.ids) ||
|
||||
this.isEmpty(this.userIds) ||
|
||||
this.isEmpty(this.roles) ||
|
||||
this.isEmpty(this.tenantIds) ||
|
||||
this.isEmpty(this.excludedIds);
|
||||
}
|
||||
|
||||
|
@ -144,6 +167,16 @@ public class UserRoleQuery extends QueryBase<UserRoleEntity> {
|
|||
inClause.value(item);
|
||||
predicates.add(inClause);
|
||||
}
|
||||
if (this.tenantIds != null) {
|
||||
CriteriaBuilder.In<UUID> inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(UserRoleEntity._tenantId));
|
||||
for (UUID item : this.tenantIds)
|
||||
inClause.value(item);
|
||||
predicates.add(inClause);
|
||||
}
|
||||
if (this.tenantIsSet != null) {
|
||||
if (this.tenantIsSet) predicates.add(queryContext.CriteriaBuilder.isNotNull(queryContext.Root.get(UserRoleEntity._tenantId)));
|
||||
else predicates.add(queryContext.CriteriaBuilder.isNull(queryContext.Root.get(UserRoleEntity._tenantId)));
|
||||
}
|
||||
if (this.userIds != null) {
|
||||
CriteriaBuilder.In<UUID> inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(UserRoleEntity._userId));
|
||||
for (UUID item : this.userIds)
|
||||
|
@ -177,6 +210,7 @@ public class UserRoleQuery extends QueryBase<UserRoleEntity> {
|
|||
else if (item.prefix(UserRole._user)) return UserRoleEntity._userId;
|
||||
else if (item.match(UserRole._user)) return UserRoleEntity._userId;
|
||||
else if (item.match(UserRole._createdAt) ) return UserRoleEntity._createdAt;
|
||||
else if (item.match(UserRoleEntity._tenantId) ) return UserRoleEntity._tenantId;
|
||||
else if (item.match(UserRole._belongsToCurrentTenant) ) return UserRoleEntity._tenantId;
|
||||
else return null;
|
||||
}
|
||||
|
|
|
@ -2,6 +2,6 @@ package eu.eudat.service.keycloak;
|
|||
|
||||
public enum KeycloakRole {
|
||||
|
||||
Admin, DescriptionTemplateEditor, Manager, User
|
||||
Admin, User
|
||||
|
||||
}
|
||||
|
|
|
@ -181,6 +181,7 @@ public class MetricsServiceImpl implements MetricsService {
|
|||
dmpQuery.after(_config.getNexusDate());
|
||||
EntityDoiQuery entityDoiQuery = this.queryFactory.query(EntityDoiQuery.class).types(EntityType.DMP).isActive(IsActive.Active);
|
||||
dmpQuery.entityDoiSubQuery(entityDoiQuery);
|
||||
dmpQuery.setDistinct(true);
|
||||
return dmpQuery.count();
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ package eu.eudat.service.user;
|
|||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import eu.eudat.authorization.AuthorizationFlags;
|
||||
import eu.eudat.authorization.AuthorizationProperties;
|
||||
import eu.eudat.authorization.OwnedResource;
|
||||
import eu.eudat.authorization.Permission;
|
||||
import eu.eudat.commons.JsonHandlingService;
|
||||
|
@ -11,6 +12,7 @@ import eu.eudat.commons.enums.ActionConfirmationType;
|
|||
import eu.eudat.commons.enums.ContactInfoType;
|
||||
import eu.eudat.commons.enums.IsActive;
|
||||
import eu.eudat.commons.enums.notification.NotificationContactType;
|
||||
import eu.eudat.commons.scope.tenant.TenantScope;
|
||||
import eu.eudat.commons.scope.user.UserScope;
|
||||
import eu.eudat.commons.types.actionconfirmation.MergeAccountConfirmationEntity;
|
||||
import eu.eudat.commons.types.actionconfirmation.RemoveCredentialRequestEntity;
|
||||
|
@ -27,6 +29,7 @@ import eu.eudat.integrationevent.outbox.notification.NotifyIntegrationEvent;
|
|||
import eu.eudat.integrationevent.outbox.notification.NotifyIntegrationEventHandler;
|
||||
import eu.eudat.integrationevent.outbox.userremoval.UserRemovalIntegrationEventHandler;
|
||||
import eu.eudat.integrationevent.outbox.usertouched.UserTouchedIntegrationEventHandler;
|
||||
import eu.eudat.model.Tenant;
|
||||
import eu.eudat.model.User;
|
||||
import eu.eudat.model.UserContactInfo;
|
||||
import eu.eudat.model.UserCredential;
|
||||
|
@ -107,6 +110,8 @@ public class UserServiceImpl implements UserService {
|
|||
private final ElasticService elasticService;
|
||||
private final UserTouchedIntegrationEventHandler userTouchedIntegrationEventHandler;
|
||||
private final UserRemovalIntegrationEventHandler userRemovalIntegrationEventHandler;
|
||||
private final AuthorizationProperties authorizationProperties;
|
||||
private final TenantScope tenantScope;
|
||||
|
||||
@Autowired
|
||||
public UserServiceImpl(
|
||||
|
@ -120,7 +125,7 @@ public class UserServiceImpl implements UserService {
|
|||
EventBroker eventBroker,
|
||||
JsonHandlingService jsonHandlingService,
|
||||
XmlHandlingService xmlHandlingService, QueryFactory queryFactory,
|
||||
UserScope userScope, KeycloakService keycloakService, ActionConfirmationService actionConfirmationService, NotificationProperties notificationProperties, NotifyIntegrationEventHandler eventHandler, ValidatorFactory validatorFactory, ElasticService elasticService, UserTouchedIntegrationEventHandler userTouchedIntegrationEventHandler, UserRemovalIntegrationEventHandler userRemovalIntegrationEventHandler) {
|
||||
UserScope userScope, KeycloakService keycloakService, ActionConfirmationService actionConfirmationService, NotificationProperties notificationProperties, NotifyIntegrationEventHandler eventHandler, ValidatorFactory validatorFactory, ElasticService elasticService, UserTouchedIntegrationEventHandler userTouchedIntegrationEventHandler, UserRemovalIntegrationEventHandler userRemovalIntegrationEventHandler, AuthorizationProperties authorizationProperties, TenantScope tenantScope) {
|
||||
this.entityManager = entityManager;
|
||||
this.authorizationService = authorizationService;
|
||||
this.deleterFactory = deleterFactory;
|
||||
|
@ -141,6 +146,8 @@ public class UserServiceImpl implements UserService {
|
|||
this.elasticService = elasticService;
|
||||
this.userTouchedIntegrationEventHandler = userTouchedIntegrationEventHandler;
|
||||
this.userRemovalIntegrationEventHandler = userRemovalIntegrationEventHandler;
|
||||
this.authorizationProperties = authorizationProperties;
|
||||
this.tenantScope = tenantScope;
|
||||
}
|
||||
|
||||
//region persist
|
||||
|
@ -247,15 +254,27 @@ public class UserServiceImpl implements UserService {
|
|||
throw new MyApplicationException("Currently cannot update roles for this user");
|
||||
UUID subjectId = UUID.fromString(userCredentials.getFirst().getExternalId());
|
||||
|
||||
this.applyGlobalRoles(data.getId(), subjectId, model);
|
||||
|
||||
List<UserRoleEntity> existingItems = this.queryFactory.query(UserRoleQuery.class).userIds(data.getId()).collect();
|
||||
this.applyTenantRoles(data.getId(), subjectId, model);
|
||||
|
||||
this.entityManager.flush();
|
||||
|
||||
this.eventBroker.emit(new UserTouchedEvent(data.getId()));
|
||||
|
||||
this.userTouchedIntegrationEventHandler.handle(data.getId());
|
||||
return this.builderFactory.builder(UserBuilder.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermission).build(BaseFieldSet.build(fields, User._id), data);
|
||||
}
|
||||
|
||||
private void applyGlobalRoles(UUID userId, UUID subjectId, UserRolePatchPersist model) throws InvalidApplicationException {
|
||||
List<UserRoleEntity> existingItems = this.queryFactory.query(UserRoleQuery.class).userIds(userId).tenantIsSet(false).roles(this.authorizationProperties.getAllowedGlobalRoles()).collect();
|
||||
List<UUID> foundIds = new ArrayList<>();
|
||||
for (String roleName : model.getRoles().stream().filter(x-> x != null && !x.isBlank()).distinct().toList()) {
|
||||
for (String roleName : model.getRoles().stream().filter(x-> x != null && !x.isBlank() && this.authorizationProperties.getAllowedGlobalRoles().contains(x)).distinct().toList()) {
|
||||
UserRoleEntity item = existingItems.stream().filter(x-> x.getRole().equals(roleName)).findFirst().orElse(null);
|
||||
if (item == null) {
|
||||
item = new UserRoleEntity();
|
||||
item.setId(UUID.randomUUID());
|
||||
item.setUserId(data.getId());
|
||||
item.setUserId(userId);
|
||||
item.setRole(roleName);
|
||||
item.setCreatedAt(Instant.now());
|
||||
this.entityManager.persist(item);
|
||||
|
@ -271,11 +290,40 @@ public class UserServiceImpl implements UserService {
|
|||
this.deleterFactory.deleter(UserRoleDeleter.class).deleteAndSave(toDelete);
|
||||
|
||||
this.entityManager.flush();
|
||||
}
|
||||
|
||||
this.eventBroker.emit(new UserTouchedEvent(data.getId()));
|
||||
private void applyTenantRoles(UUID userId, UUID subjectId, UserRolePatchPersist model) throws InvalidApplicationException {
|
||||
if (!tenantScope.isSet()) throw new MyForbiddenException("tenant scope required");
|
||||
|
||||
UserRoleQuery userRoleQuery = this.queryFactory.query(UserRoleQuery.class).userIds(userId).roles(this.authorizationProperties.getAllowedTenantRoles());
|
||||
if (tenantScope.isDefaultTenant()) userRoleQuery.tenantIsSet(false);
|
||||
else userRoleQuery.tenantIsSet(true).tenantIds(this.tenantScope.getTenant());
|
||||
|
||||
List<UserRoleEntity> existingItems = userRoleQuery.collect();
|
||||
List<UUID> foundIds = new ArrayList<>();
|
||||
for (String roleName : model.getRoles().stream().filter(x-> x != null && !x.isBlank() && this.authorizationProperties.getAllowedTenantRoles().contains(x)).distinct().toList()) {
|
||||
UserRoleEntity item = existingItems.stream().filter(x-> x.getRole().equals(roleName)).findFirst().orElse(null);
|
||||
if (item == null) {
|
||||
item = new UserRoleEntity();
|
||||
item.setId(UUID.randomUUID());
|
||||
item.setUserId(userId);
|
||||
item.setRole(roleName);
|
||||
item.setCreatedAt(Instant.now());
|
||||
item.setTenantId(this.tenantScope.getTenant());
|
||||
this.entityManager.persist(item);
|
||||
this.keycloakService.addUserToGroup(subjectId, KeycloakRole.valueOf(roleName));
|
||||
}
|
||||
foundIds.add(item.getId());
|
||||
}
|
||||
|
||||
this.entityManager.flush();
|
||||
|
||||
List<UserRoleEntity> toDelete = existingItems.stream().filter(x-> foundIds.stream().noneMatch(y-> y.equals(x.getId()))).collect(Collectors.toList());
|
||||
toDelete.forEach(x -> this.keycloakService.removeUserFromGroup(subjectId, KeycloakRole.valueOf(x.getRole())));
|
||||
this.deleterFactory.deleter(UserRoleDeleter.class).deleteAndSave(toDelete);
|
||||
|
||||
this.entityManager.flush();
|
||||
|
||||
this.userTouchedIntegrationEventHandler.handle(data.getId());
|
||||
return this.builderFactory.builder(UserBuilder.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermission).build(BaseFieldSet.build(fields, User._id), data);
|
||||
}
|
||||
|
||||
//region mine
|
||||
|
|
|
@ -45,8 +45,6 @@ public class EntityDoiController {
|
|||
|
||||
private final EntityDoiService entityDoiService;
|
||||
|
||||
private final DepositService repositoryDepositService;
|
||||
|
||||
private final CensorFactory censorFactory;
|
||||
|
||||
private final QueryFactory queryFactory;
|
||||
|
@ -56,14 +54,12 @@ public class EntityDoiController {
|
|||
public EntityDoiController(
|
||||
BuilderFactory builderFactory,
|
||||
AuditService auditService,
|
||||
EntityDoiService entityDoiService,
|
||||
DepositService repositoryDepositService, CensorFactory censorFactory,
|
||||
EntityDoiService entityDoiService, CensorFactory censorFactory,
|
||||
QueryFactory queryFactory,
|
||||
MessageSource messageSource) {
|
||||
this.builderFactory = builderFactory;
|
||||
this.auditService = auditService;
|
||||
this.entityDoiService = entityDoiService;
|
||||
this.repositoryDepositService = repositoryDepositService;
|
||||
this.censorFactory = censorFactory;
|
||||
this.queryFactory = queryFactory;
|
||||
this.messageSource = messageSource;
|
||||
|
|
|
@ -25,6 +25,12 @@ permissions:
|
|||
clients: [ ]
|
||||
allowAnonymous: false
|
||||
allowAuthenticated: false
|
||||
AllowNoTenant:
|
||||
roles:
|
||||
- Admin
|
||||
clients: [ ]
|
||||
allowAnonymous: false
|
||||
allowAuthenticated: false
|
||||
# public
|
||||
PublicBrowseDescription:
|
||||
roles: [ ]
|
||||
|
@ -232,26 +238,26 @@ permissions:
|
|||
# User
|
||||
BrowseUser:
|
||||
roles:
|
||||
- TenantAdmin
|
||||
- Admin
|
||||
clients: [ ]
|
||||
allowAnonymous: false
|
||||
allowAuthenticated: false
|
||||
EditUser:
|
||||
roles:
|
||||
- TenantAdmin
|
||||
- Admin
|
||||
clients: [ ]
|
||||
allowAnonymous: false
|
||||
allowAuthenticated: false
|
||||
DeleteUser:
|
||||
roles:
|
||||
- TenantAdmin
|
||||
- Admin
|
||||
claims: [ ]
|
||||
clients: [ ]
|
||||
allowAnonymous: false
|
||||
allowAuthenticated: false
|
||||
ExportUsers:
|
||||
roles:
|
||||
- TenantAdmin
|
||||
- Admin
|
||||
claims: [ ]
|
||||
clients: [ ]
|
||||
allowAnonymous: false
|
||||
|
@ -916,7 +922,7 @@ permissions:
|
|||
allowAuthenticated: false
|
||||
ViewUserPage:
|
||||
roles:
|
||||
- TenantAdmin
|
||||
- Admin
|
||||
clients: [ ]
|
||||
allowAnonymous: false
|
||||
allowAuthenticated: false
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
export enum AppRole {
|
||||
Admin = "Admin",
|
||||
Manager = "Manager",
|
||||
User = "User",
|
||||
DescriptionTemplateEditor = "DescriptionTemplateEditor",
|
||||
TenantAdmin = "TenantAdmin"
|
||||
TenantAdmin = "TenantAdmin",
|
||||
TenantUser = "TenantUser",
|
||||
TenantManager = "TenantManager",
|
||||
TenantDescriptionTemplateEditor = "TenantDescriptionTemplateEditor"
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import { BaseEntity, BaseEntityPersist } from "@common/base/base-entity.model";
|
||||
|
||||
export interface Tenant extends BaseEntity{
|
||||
name: string;
|
||||
code: string;
|
||||
description: string;
|
||||
name?: string;
|
||||
code?: string;
|
||||
description?: string;
|
||||
config?: TenantConfig;
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,8 @@ export interface User extends BaseEntity {
|
|||
name: string;
|
||||
additionalInfo: UserAdditionalInfo;
|
||||
contacts: UserContactInfo[];
|
||||
roles: UserRole[];
|
||||
globalRoles: UserRole[];
|
||||
tenantRoles: UserRole[];
|
||||
credentials: UserCredential[];
|
||||
}
|
||||
|
||||
|
|
|
@ -60,9 +60,10 @@ export class EnumUtils {
|
|||
switch (status) {
|
||||
case AppRole.Admin: return this.language.instant('TYPES.APP-ROLE.ADMIN');
|
||||
case AppRole.User: return this.language.instant('TYPES.APP-ROLE.USER');
|
||||
case AppRole.Manager: return this.language.instant('TYPES.APP-ROLE.MANAGER');
|
||||
case AppRole.DescriptionTemplateEditor: return this.language.instant('TYPES.APP-ROLE.DESCRIPTION-TEMPLATE-EDITOR');
|
||||
case AppRole.TenantAdmin: return this.language.instant('TYPES.APP-ROLE.TENANT-ADMIN');
|
||||
case AppRole.TenantUser: return this.language.instant('TYPES.APP-ROLE.TENANT-USER');
|
||||
case AppRole.TenantManager: return this.language.instant('TYPES.APP-ROLE.TENANT-MANAGER');
|
||||
case AppRole.TenantDescriptionTemplateEditor: return this.language.instant('TYPES.APP-ROLE.TENANT-DESCRIPTION-TEMPLATE-EDITOR');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<div *ngIf="!this.nowEditing"class="roles col-8">
|
||||
<div *ngFor="let role of this.formGroup.get('roles').value" class="row">
|
||||
<div class="col-auto p-0">
|
||||
<span class="user-role" [ngClass]="{'user': role == appRole.User, 'manager': role == appRole.Manager, 'admin': role == appRole.Admin, 'description-template-editor': role == appRole.DescriptionTemplateEditor, 'tenant-admin': role == appRole.TenantAdmin}">
|
||||
<span class="user-role" [ngClass]="{'user': role == appRole.User, 'tenant-manager': role == appRole.TenantManager, 'admin': role == appRole.Admin, 'tenant-description-template-editor': role == appRole.TenantDescriptionTemplateEditor, 'tenant-admin': role == appRole.TenantAdmin, 'tenant-user': role == appRole.TenantUser}">
|
||||
{{enumUtils.toAppRoleString(role)}}
|
||||
</span>
|
||||
</div>
|
||||
|
|
|
@ -49,7 +49,7 @@
|
|||
padding-right: 10px;
|
||||
}
|
||||
|
||||
.manager {
|
||||
.tenant-manager {
|
||||
// display: flex;
|
||||
// justify-content: center;
|
||||
// align-items: center;
|
||||
|
@ -103,7 +103,7 @@
|
|||
padding-right: 10px;
|
||||
}
|
||||
|
||||
.description-template-editor {
|
||||
.tenant-description-template-editor {
|
||||
// display: flex;
|
||||
// justify-content: center;
|
||||
// align-items: center;
|
||||
|
@ -121,6 +121,43 @@
|
|||
padding-right: 10px;
|
||||
}
|
||||
|
||||
|
||||
.tenant-user {
|
||||
// display: flex;
|
||||
// justify-content: center;
|
||||
// align-items: center;
|
||||
min-width: 67px;
|
||||
min-height: 28px;
|
||||
color: #00c4ff;
|
||||
background: #d3f5ff3a 0% 0% no-repeat padding-box;
|
||||
border-radius: 44px;
|
||||
letter-spacing: 0.11px;
|
||||
font-weight: 400;
|
||||
opacity: 1;
|
||||
margin-top: 0.5em;
|
||||
margin-bottom: 0.5em;
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
.tenant-admin {
|
||||
// display: flex;
|
||||
// justify-content: center;
|
||||
// align-items: center;
|
||||
min-width: 77px;
|
||||
min-height: 28px;
|
||||
color: #ff3d33;
|
||||
background: #ffd5d32f 0% 0% no-repeat padding-box;
|
||||
border-radius: 44px;
|
||||
letter-spacing: 0.11px;
|
||||
font-weight: 400;
|
||||
opacity: 1;
|
||||
margin-top: 0.5em;
|
||||
margin-bottom: 0.5em;
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
.save-button {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ import { FormService } from '@common/forms/form-service';
|
|||
import { HttpErrorResponse } from '@angular/common/http';
|
||||
import { HttpError, HttpErrorHandlingService } from '@common/modules/errors/error-handling/http-error-handling.service';
|
||||
import { AppRole } from '@app/core/common/enum/app-role';
|
||||
import { Guid } from '@common/types/guid';
|
||||
|
||||
@Component({
|
||||
selector: 'app-user-role-editor-component',
|
||||
|
|
|
@ -20,7 +20,8 @@ export class UserRolePatchEditorModel implements UserRolePatchPersist {
|
|||
public fromModel(item: User): UserRolePatchEditorModel {
|
||||
if (item) {
|
||||
this.id = item.id;
|
||||
if (item.roles != null)this.roles = item.roles.map(x => x.role);
|
||||
if (item.globalRoles != null)this.roles = item.globalRoles.map(x => x.role);
|
||||
if (item.tenantRoles != null) item.tenantRoles.map(x => this.roles.push(x.role));
|
||||
this.hash = item.hash;
|
||||
}
|
||||
return this;
|
||||
|
|
|
@ -2,10 +2,13 @@ import { Component, OnInit, TemplateRef, ViewChild } from '@angular/core';
|
|||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { IsActive } from '@app/core/common/enum/is-active.enum';
|
||||
import { Tenant } from '@app/core/model/tenant/tenant';
|
||||
import { User, UserAdditionalInfo, UserContactInfo, UserRole } from '@app/core/model/user/user';
|
||||
import { TenantLookup } from '@app/core/query/tenant.lookup';
|
||||
import { UserLookup } from '@app/core/query/user.lookup';
|
||||
import { AuthService } from '@app/core/services/auth/auth.service';
|
||||
import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/services/notification/ui-notification-service';
|
||||
import { TenantService } from '@app/core/services/tenant/tenant.service';
|
||||
import { UserService } from '@app/core/services/user/user.service';
|
||||
import { EnumUtils } from '@app/core/services/utilities/enum-utils.service';
|
||||
import { FileUtils } from '@app/core/services/utilities/file-utils.service';
|
||||
|
@ -44,8 +47,10 @@ export class UserListingComponent extends BaseListingComponent<User, UserLookup>
|
|||
[nameof<User>(x => x.contacts), nameof<UserContactInfo>(x => x.id)].join('.'),
|
||||
[nameof<User>(x => x.contacts), nameof<UserContactInfo>(x => x.type)].join('.'),
|
||||
[nameof<User>(x => x.contacts), nameof<UserContactInfo>(x => x.value)].join('.'),
|
||||
[nameof<User>(x => x.roles), nameof<UserRole>(x => x.id)].join('.'),
|
||||
[nameof<User>(x => x.roles), nameof<UserRole>(x => x.role)].join('.'),
|
||||
[nameof<User>(x => x.globalRoles), nameof<UserRole>(x => x.id)].join('.'),
|
||||
[nameof<User>(x => x.globalRoles), nameof<UserRole>(x => x.role)].join('.'),
|
||||
[nameof<User>(x => x.tenantRoles), nameof<UserRole>(x => x.id)].join('.'),
|
||||
[nameof<User>(x => x.tenantRoles), nameof<UserRole>(x => x.role)].join('.'),
|
||||
[nameof<User>(x => x.additionalInfo), nameof<UserAdditionalInfo>(x => x.avatarUrl)].join('.'),
|
||||
nameof<User>(x => x.updatedAt),
|
||||
nameof<User>(x => x.createdAt),
|
||||
|
@ -55,6 +60,7 @@ export class UserListingComponent extends BaseListingComponent<User, UserLookup>
|
|||
|
||||
rowIdentity = x => x.id;
|
||||
|
||||
|
||||
constructor(
|
||||
protected router: Router,
|
||||
protected route: ActivatedRoute,
|
||||
|
@ -120,7 +126,7 @@ export class UserListingComponent extends BaseListingComponent<User, UserLookup>
|
|||
pipe: this.pipeService.getPipe<DataTableDateTimeFormatPipe>(DataTableDateTimeFormatPipe).withFormat('short')
|
||||
},
|
||||
{
|
||||
prop: nameof<User>(x => x.roles),
|
||||
prop: nameof<User>(x => x.globalRoles),
|
||||
languageName: 'USER-LISTING.FIELDS.ROLES',
|
||||
alwaysShown: true,
|
||||
maxWidth: 300,
|
||||
|
|
|
@ -10,6 +10,7 @@ import { UserListingFiltersComponent } from './listing/filters/user-listing-filt
|
|||
import { UserListingComponent } from './listing/user-listing.component';
|
||||
import { UsersRoutingModule } from './user.routing';
|
||||
import { UserRoleEditorComponent } from './listing/role-editor/user-role-editor.component';
|
||||
import { AutoCompleteModule } from '@app/library/auto-complete/auto-complete.module';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
|
@ -25,6 +26,7 @@ import { UserRoleEditorComponent } from './listing/role-editor/user-role-editor.
|
|||
CommonFormattingModule,
|
||||
UsersRoutingModule,
|
||||
HybridListingModule,
|
||||
AutoCompleteModule,
|
||||
TextFilterModule,
|
||||
UserSettingsModule
|
||||
]
|
||||
|
|
|
@ -196,8 +196,8 @@
|
|||
</div>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="canCreateNewVersion()">
|
||||
<div class="col-12 d-flex align-items-center">
|
||||
<button mat-mini-fab class="frame-btn" (click)="newVersionClicked()">
|
||||
<div class="col-12 d-flex align-items-center" (click)="newVersionClicked()">
|
||||
<button mat-mini-fab class="frame-btn">
|
||||
<mat-icon class="mat-mini-fab-icon">add_to_photos</mat-icon>
|
||||
</button>
|
||||
<p class="mb-0 pl-2 frame-txt">{{ 'DMP-OVERVIEW.ACTIONS.NEW-VERSION' | translate }}</p>
|
||||
|
|
|
@ -1429,8 +1429,10 @@
|
|||
"APP-ROLE": {
|
||||
"ADMIN": "Administrator",
|
||||
"USER": "Benutzer",
|
||||
"MANAGER": "Manager",
|
||||
"DESCRIPTION-TEMPLATE-EDITOR": "Description Template Editor"
|
||||
"TENANT-ADMIN": "Tenant Administrator",
|
||||
"TENANT-USER": "Tenant Benutzer",
|
||||
"TENANT-MANAGER": "Manager",
|
||||
"TENANT-DESCRIPTION-TEMPLATE-EDITOR": "Description Template Editor"
|
||||
},
|
||||
"DMP-PROFILE-FIELD": {
|
||||
"DATA-TYPE": {
|
||||
|
|
|
@ -1577,9 +1577,10 @@
|
|||
"APP-ROLE": {
|
||||
"ADMIN": "Admin",
|
||||
"USER": "User",
|
||||
"MANAGER": "Manager",
|
||||
"DESCRIPTION-TEMPLATE-EDITOR": "Description Template Editor",
|
||||
"TENANT-ADMIN": "Tenant Admin"
|
||||
"TENANT-ADMIN": "Tenant Admin",
|
||||
"TENANT-USER": "Tenant User",
|
||||
"TENANT-MANAGER": "Manager",
|
||||
"TENANT-DESCRIPTION-TEMPLATE-EDITOR": "Description Template Editor"
|
||||
},
|
||||
"IS-ACTIVE": {
|
||||
"ACTIVE": "Active",
|
||||
|
|
|
@ -1429,8 +1429,10 @@
|
|||
"APP-ROLE": {
|
||||
"ADMIN": "Administrador",
|
||||
"USER": "Usuario",
|
||||
"MANAGER": "Director",
|
||||
"DESCRIPTION-TEMPLATE-EDITOR": "Description Template Editor"
|
||||
"TENANT-ADMIN": "Tenant Administrador",
|
||||
"TENANT-USER": "Tenant Usuario",
|
||||
"TENANT-MANAGER": "Director",
|
||||
"TENANT-DESCRIPTION-TEMPLATE-EDITOR": "Description Template Editor"
|
||||
},
|
||||
"DMP-PROFILE-FIELD": {
|
||||
"DATA-TYPE": {
|
||||
|
|
|
@ -1429,8 +1429,10 @@
|
|||
"APP-ROLE": {
|
||||
"ADMIN": "Διαχειριστής",
|
||||
"USER": "Χρήστης",
|
||||
"MANAGER": "Υπεύθυνος",
|
||||
"DESCRIPTION-TEMPLATE-EDITOR": "Description Template Editor"
|
||||
"TENANT-ADMIN": "Διαχειριστής Teannt",
|
||||
"TENANT-USER": "Χρήστης Teannt",
|
||||
"TENANT-MANAGER": "Υπεύθυνος",
|
||||
"TENANT-DESCRIPTION-TEMPLATE-EDITOR": "Description Template Editor"
|
||||
},
|
||||
"DMP-PROFILE-FIELD": {
|
||||
"DATA-TYPE": {
|
||||
|
|
|
@ -1429,8 +1429,10 @@
|
|||
"APP-ROLE": {
|
||||
"ADMIN": "Administrator",
|
||||
"USER": "Korisnik",
|
||||
"MANAGER": "Upravitelj",
|
||||
"DESCRIPTION-TEMPLATE-EDITOR": "Description Template Editor"
|
||||
"TENANT-ADMIN": "Tenant Administrator",
|
||||
"TENANT-USER": "Tenant Korisnik",
|
||||
"TENANT-MANAGER": "Upravitelj",
|
||||
"TENANT-DESCRIPTION-TEMPLATE-EDITOR": "Description Template Editor"
|
||||
},
|
||||
"DMP-PROFILE-FIELD": {
|
||||
"DATA-TYPE": {
|
||||
|
|
|
@ -1429,8 +1429,10 @@
|
|||
"APP-ROLE": {
|
||||
"ADMIN": "Administrator",
|
||||
"USER": "Użytkownik",
|
||||
"MANAGER": "Menedżer",
|
||||
"DESCRIPTION-TEMPLATE-EDITOR": "Description Template Editor"
|
||||
"TENANT-ADMIN": "Tenant Administrator",
|
||||
"TENANT-USER": "Tenant Użytkownik",
|
||||
"TENANT-MANAGER": "Menedżer",
|
||||
"TENANT-DESCRIPTION-TEMPLATE-EDITOR": "Description Template Editor"
|
||||
},
|
||||
"DMP-PROFILE-FIELD": {
|
||||
"DATA-TYPE": {
|
||||
|
|
|
@ -1429,8 +1429,10 @@
|
|||
"APP-ROLE": {
|
||||
"ADMIN": "Administrador",
|
||||
"USER": "Utilizador",
|
||||
"MANAGER": "Gestor",
|
||||
"DESCRIPTION-TEMPLATE-EDITOR": "Description Template Editor"
|
||||
"TENANT-ADMIN": "Tenant Administrador",
|
||||
"TENANT-USER": "Tenant Utilizador",
|
||||
"TENANT-MANAGER": "Gestor",
|
||||
"TENANT-DESCRIPTION-TEMPLATE-EDITOR": "Description Template Editor"
|
||||
},
|
||||
"DMP-PROFILE-FIELD": {
|
||||
"DATA-TYPE": {
|
||||
|
|
|
@ -1429,8 +1429,10 @@
|
|||
"APP-ROLE": {
|
||||
"ADMIN": "Admin",
|
||||
"USER": "Používateľ",
|
||||
"MANAGER": "Manažér",
|
||||
"DESCRIPTION-TEMPLATE-EDITOR": "Description Template Editor"
|
||||
"TENANT-ADMIN": "Tenant Admin",
|
||||
"TENANT-USER": "Tenant Používateľ",
|
||||
"TENANT-MANAGER": "Manažér",
|
||||
"TENANT-DESCRIPTION-TEMPLATE-EDITOR": "Description Template Editor"
|
||||
},
|
||||
"DMP-PROFILE-FIELD": {
|
||||
"DATA-TYPE": {
|
||||
|
|
|
@ -1429,8 +1429,10 @@
|
|||
"APP-ROLE": {
|
||||
"ADMIN": "Administrator",
|
||||
"USER": "Korisnik",
|
||||
"MANAGER": "Menadžer",
|
||||
"DESCRIPTION-TEMPLATE-EDITOR": "Description Template Editor"
|
||||
"TENANT-ADMIN": "Tenant Admin",
|
||||
"TENANT-USER": "Tenant Korisnik",
|
||||
"TENANT-MANAGER": "Menadžer",
|
||||
"TENANT-DESCRIPTION-TEMPLATE-EDITOR": "Description Template Editor"
|
||||
},
|
||||
"DMP-PROFILE-FIELD": {
|
||||
"DATA-TYPE": {
|
||||
|
|
|
@ -1429,8 +1429,10 @@
|
|||
"APP-ROLE": {
|
||||
"ADMIN": "Admin",
|
||||
"USER": "Kullanıcı",
|
||||
"MANAGER": "Yönetici",
|
||||
"DESCRIPTION-TEMPLATE-EDITOR": "Description Template Editor"
|
||||
"TENANT-ADMIN": "Tenant Admin",
|
||||
"TENANT-USER": "Tenant Kullanıcı",
|
||||
"TENANT-MANAGER": "Yönetici",
|
||||
"TENANT-DESCRIPTION-TEMPLATE-EDITOR": "Description Template Editor"
|
||||
},
|
||||
"DMP-PROFILE-FIELD": {
|
||||
"DATA-TYPE": {
|
||||
|
|
Loading…
Reference in New Issue