Merge branch 'dmp-refactoring' of https://code-repo.d4science.org/MaDgiK-CITE/argos into dmp-refactoring
This commit is contained in:
commit
6e12d13a3b
|
@ -81,11 +81,11 @@ public class AuthorizationContentResolverImpl implements AuthorizationContentRes
|
|||
|
||||
List<AnnotationEntity> annotationEntities = this.queryFactory.query(AnnotationQuery.class).disableTracking().ids(ids).collectAs(new BaseFieldSet().ensure(Annotation._id).ensure(Annotation._entityId).ensure(Annotation._id));
|
||||
List<EntityUserEntity> entityUsers = this.queryFactory.query(EntityUserQuery.class).disableTracking().entityIds(annotationEntities.stream().map(AnnotationEntity::getEntityId).distinct().toList()).userIds(userId).isActive(IsActive.Active).collectAs(new BaseFieldSet().ensure(EntityUser._id).ensure(EntityUser._entityId));
|
||||
Map<UUID, List<EntityUserEntity>> dmpUsersMap = entityUsers.stream().collect(Collectors.groupingBy(EntityUserEntity::getEntityId));
|
||||
Map<UUID, List<EntityUserEntity>> entityUsersMap = entityUsers.stream().collect(Collectors.groupingBy(EntityUserEntity::getEntityId));
|
||||
|
||||
for (AnnotationEntity annotation : annotationEntities){
|
||||
List<EntityUserEntity> dmpDescriptionUsers = dmpUsersMap.getOrDefault(annotation.getEntityId(), new ArrayList<>());
|
||||
if (!dmpDescriptionUsers.isEmpty()) {
|
||||
List<EntityUserEntity> annotationEntityUsers = entityUsersMap.getOrDefault(annotation.getEntityId(), new ArrayList<>());
|
||||
if (!annotationEntityUsers.isEmpty()) {
|
||||
affiliatedResources.get(annotation.getId()).setAffiliated(true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -104,6 +104,8 @@ public class AuditableAction {
|
|||
public static final EventId User_RemoveCredentialConfirm = new EventId(11013, "User_RemoveCredentialConfirm");
|
||||
public static final EventId User_DmpAssociatedQuery = new EventId(11014, "User_DmpAssociatedQuery");
|
||||
public static final EventId User_AllowMergeAccount = new EventId(11015, "User_AllowMergeAccount");
|
||||
public static final EventId User_InviteToTenant = new EventId(11016, "User_InviteToTenant");
|
||||
public static final EventId User_InviteToTenantConfirm = new EventId(11017, "User_InviteToTenantConfirm");
|
||||
|
||||
public static final EventId Tenant_Query = new EventId(12000, "Tenant_Query");
|
||||
public static final EventId Tenant_Lookup = new EventId(12001, "Tenant_Lookup");
|
||||
|
|
|
@ -9,7 +9,8 @@ public enum ActionConfirmationType implements DatabaseEnum<Short> {
|
|||
|
||||
MergeAccount((short) 0),
|
||||
RemoveCredential((short) 1),
|
||||
DmpInvitation((short) 2);
|
||||
DmpInvitation((short) 2),
|
||||
UserInviteToTenant ((short) 3);
|
||||
|
||||
private final Short value;
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ public class NotificationProperties {
|
|||
private UUID descriptionTemplateInvitationType;
|
||||
private UUID contactSupportType;
|
||||
private UUID publicContactSupportType;
|
||||
private UUID tenantSpecificInvitationUserType;
|
||||
private int emailExpirationTimeSeconds;
|
||||
private String contactSupportEmail;
|
||||
|
||||
|
@ -151,4 +152,12 @@ public class NotificationProperties {
|
|||
public void setDescriptionAnnotationCreated(UUID descriptionAnnotationCreated) {
|
||||
this.descriptionAnnotationCreated = descriptionAnnotationCreated;
|
||||
}
|
||||
|
||||
public UUID getTenantSpecificInvitationUserType() {
|
||||
return tenantSpecificInvitationUserType;
|
||||
}
|
||||
|
||||
public void setTenantSpecificInvitationUserType(UUID tenantSpecificInvitationUserType) {
|
||||
this.tenantSpecificInvitationUserType = tenantSpecificInvitationUserType;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
package org.opencdmp.commons.types.actionconfirmation;
|
||||
|
||||
import jakarta.xml.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@XmlRootElement(name = "user-invite-to-tenant-confirmation")
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
public class UserInviteToTenantRequestEntity {
|
||||
|
||||
@XmlAttribute(name = "email")
|
||||
private String email;
|
||||
|
||||
@XmlAttribute(name = "tenantCode")
|
||||
private String tenantCode;
|
||||
|
||||
@XmlElementWrapper(name = "roles")
|
||||
@XmlElement(name = "role")
|
||||
private List<String> roles;
|
||||
|
||||
|
||||
public String getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
public void setEmail(String email) {
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
public String getTenantCode() {
|
||||
return tenantCode;
|
||||
}
|
||||
|
||||
public void setTenantCode(String tenantCode) {
|
||||
this.tenantCode = tenantCode;
|
||||
}
|
||||
|
||||
public List<String> getRoles() {
|
||||
return roles;
|
||||
}
|
||||
|
||||
public void setRoles(List<String> roles) {
|
||||
this.roles = roles;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -26,6 +26,10 @@ public class ActionConfirmation {
|
|||
|
||||
public static final String _removeCredentialRequest = "removeCredentialRequest";
|
||||
|
||||
private UserInviteToTenantRequest userInviteToTenantRequest;
|
||||
|
||||
public static final String _userInviteToTenantRequest = "userInviteToTenantRequest";
|
||||
|
||||
private DmpInvitation dmpInvitation;
|
||||
public static final String _dmpInvitation = "dmpInvitation";
|
||||
|
||||
|
@ -154,4 +158,12 @@ public class ActionConfirmation {
|
|||
public void setRemoveCredentialRequest(RemoveCredentialRequest removeCredentialRequest) {
|
||||
this.removeCredentialRequest = removeCredentialRequest;
|
||||
}
|
||||
|
||||
public UserInviteToTenantRequest getUserInviteToTenantRequest() {
|
||||
return userInviteToTenantRequest;
|
||||
}
|
||||
|
||||
public void setUserInviteToTenantRequest(UserInviteToTenantRequest userInviteToTenantRequest) {
|
||||
this.userInviteToTenantRequest = userInviteToTenantRequest;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
package org.opencdmp.model.actionconfirmation;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class UserInviteToTenantRequest {
|
||||
|
||||
private String email;
|
||||
public static final String _email = "email";
|
||||
|
||||
private String tenantCode;
|
||||
public static final String _tenantCode = "tenantCode";
|
||||
|
||||
private List<String> roles;
|
||||
public static final String _roles = "roles";
|
||||
|
||||
public String getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
public void setEmail(String email) {
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
public String getTenantCode() {
|
||||
return tenantCode;
|
||||
}
|
||||
|
||||
public void setTenantCode(String tenantCode) {
|
||||
this.tenantCode = tenantCode;
|
||||
}
|
||||
|
||||
public List<String> getRoles() {
|
||||
return roles;
|
||||
}
|
||||
|
||||
public void setRoles(List<String> roles) {
|
||||
this.roles = roles;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -13,6 +13,7 @@ import org.opencdmp.commons.scope.tenant.TenantScope;
|
|||
import org.opencdmp.commons.types.actionconfirmation.DmpInvitationEntity;
|
||||
import org.opencdmp.commons.types.actionconfirmation.MergeAccountConfirmationEntity;
|
||||
import org.opencdmp.commons.types.actionconfirmation.RemoveCredentialRequestEntity;
|
||||
import org.opencdmp.commons.types.actionconfirmation.UserInviteToTenantRequestEntity;
|
||||
import org.opencdmp.convention.ConventionService;
|
||||
import org.opencdmp.data.ActionConfirmationEntity;
|
||||
import org.opencdmp.model.actionconfirmation.ActionConfirmation;
|
||||
|
@ -60,6 +61,7 @@ public class ActionConfirmationBuilder extends BaseBuilder<ActionConfirmation, A
|
|||
|
||||
FieldSet mergeAccountConfirmationFields = fields.extractPrefixed(this.asPrefix(ActionConfirmation._mergeAccountConfirmation));
|
||||
FieldSet removeCredentialRequestFields = fields.extractPrefixed(this.asPrefix(ActionConfirmation._removeCredentialRequest));
|
||||
FieldSet userInviteToTenantRequestFields = fields.extractPrefixed(this.asPrefix(ActionConfirmation._userInviteToTenantRequest));
|
||||
FieldSet dmpInvitationFields = fields.extractPrefixed(this.asPrefix(ActionConfirmation._dmpInvitation));
|
||||
|
||||
FieldSet userFields = fields.extractPrefixed(this.asPrefix(ActionConfirmation._createdBy));
|
||||
|
@ -89,6 +91,10 @@ public class ActionConfirmationBuilder extends BaseBuilder<ActionConfirmation, A
|
|||
RemoveCredentialRequestEntity emailConfirmation = this.xmlHandlingService.fromXmlSafe(RemoveCredentialRequestEntity.class, d.getData());
|
||||
m.setRemoveCredentialRequest(this.builderFactory.builder(RemoveCredentialRequestBuilder.class).authorize(this.authorize).build(removeCredentialRequestFields, emailConfirmation));
|
||||
}
|
||||
case UserInviteToTenant -> {
|
||||
UserInviteToTenantRequestEntity emailConfirmation = this.xmlHandlingService.fromXmlSafe(UserInviteToTenantRequestEntity.class, d.getData());
|
||||
m.setUserInviteToTenantRequest(this.builderFactory.builder(UserInviteToTenantRequestBuilder.class).authorize(this.authorize).build(userInviteToTenantRequestFields, emailConfirmation));
|
||||
}
|
||||
default -> throw new InternalError("unknown type: " + d.getType());
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
package org.opencdmp.model.builder.actionconfirmation;
|
||||
|
||||
import gr.cite.tools.exception.MyApplicationException;
|
||||
import gr.cite.tools.fieldset.FieldSet;
|
||||
import gr.cite.tools.logging.DataLogEntry;
|
||||
import gr.cite.tools.logging.LoggerService;
|
||||
import org.opencdmp.authorization.AuthorizationFlags;
|
||||
import org.opencdmp.commons.types.actionconfirmation.UserInviteToTenantRequestEntity;
|
||||
import org.opencdmp.convention.ConventionService;
|
||||
import org.opencdmp.model.actionconfirmation.UserInviteToTenantRequest;
|
||||
import org.opencdmp.model.builder.BaseBuilder;
|
||||
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.*;
|
||||
|
||||
@Component
|
||||
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
|
||||
public class UserInviteToTenantRequestBuilder extends BaseBuilder<UserInviteToTenantRequest, UserInviteToTenantRequestEntity> {
|
||||
|
||||
private EnumSet<AuthorizationFlags> authorize = EnumSet.of(AuthorizationFlags.None);
|
||||
|
||||
@Autowired
|
||||
public UserInviteToTenantRequestBuilder(
|
||||
ConventionService conventionService) {
|
||||
super(conventionService, new LoggerService(LoggerFactory.getLogger(UserInviteToTenantRequestBuilder.class)));
|
||||
}
|
||||
|
||||
public UserInviteToTenantRequestBuilder authorize(EnumSet<AuthorizationFlags> values) {
|
||||
this.authorize = values;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserInviteToTenantRequest> build(FieldSet fields, List<UserInviteToTenantRequestEntity> data) throws MyApplicationException {
|
||||
this.logger.debug("building for {} items requesting {} fields", Optional.ofNullable(data).map(List::size).orElse(0), Optional.ofNullable(fields).map(FieldSet::getFields).map(Set::size).orElse(0));
|
||||
this.logger.trace(new DataLogEntry("requested fields", fields));
|
||||
if (fields == null || data == null || fields.isEmpty())
|
||||
return new ArrayList<>();
|
||||
|
||||
|
||||
List<UserInviteToTenantRequest> models = new ArrayList<>();
|
||||
for (UserInviteToTenantRequestEntity d : data) {
|
||||
UserInviteToTenantRequest m = new UserInviteToTenantRequest();
|
||||
if (fields.hasField(this.asIndexer(UserInviteToTenantRequest._email))) m.setEmail(d.getEmail());
|
||||
if (fields.hasField(this.asIndexer(UserInviteToTenantRequest._tenantCode))) m.setTenantCode(d.getTenantCode());
|
||||
if (fields.hasField(this.asIndexer(UserInviteToTenantRequest._roles))) m.setRoles(d.getRoles());
|
||||
|
||||
models.add(m);
|
||||
}
|
||||
this.logger.debug("build {} items", Optional.of(models).map(List::size).orElse(0));
|
||||
return models;
|
||||
}
|
||||
}
|
|
@ -49,6 +49,10 @@ public class ActionConfirmationPersist {
|
|||
|
||||
private static final String _removeCredentialRequest = "removeCredentialRequest";
|
||||
|
||||
private UserInviteToTenantRequestPersist userInviteToTenantRequestPersist;
|
||||
|
||||
private static final String _userInviteToTenantRequest = "userInviteToTenantRequest";
|
||||
|
||||
private Instant expiresAt;
|
||||
|
||||
private static final String _expiresAt = "expiresAt";
|
||||
|
@ -105,6 +109,14 @@ public class ActionConfirmationPersist {
|
|||
this.removeCredentialRequest = removeCredentialRequest;
|
||||
}
|
||||
|
||||
public UserInviteToTenantRequestPersist getUserInviteToTenantRequest() {
|
||||
return userInviteToTenantRequestPersist;
|
||||
}
|
||||
|
||||
public void setUserInviteToTenantRequest(UserInviteToTenantRequestPersist userInviteToTenantRequestPersist) {
|
||||
this.userInviteToTenantRequestPersist = userInviteToTenantRequestPersist;
|
||||
}
|
||||
|
||||
public String getToken() {
|
||||
return token;
|
||||
}
|
||||
|
@ -182,12 +194,14 @@ public class ActionConfirmationPersist {
|
|||
.iff(() -> ActionConfirmationType.DmpInvitation.equals(item.getType()))
|
||||
.must(() -> !this.isNull(item.getDmpInvitation()))
|
||||
.failOn(ActionConfirmationPersist._dmpInvitation).failWith(messageSource.getMessage("Validation_Required", new Object[]{ActionConfirmationPersist._dmpInvitation}, LocaleContextHolder.getLocale())),
|
||||
|
||||
this.spec()
|
||||
.iff(() -> ActionConfirmationType.RemoveCredential.equals(item.getType()))
|
||||
.must(() -> !this.isNull(item.getRemoveCredentialRequest()))
|
||||
.failOn(ActionConfirmationPersist._removeCredentialRequest).failWith(messageSource.getMessage("Validation_Required", new Object[]{ActionConfirmationPersist._removeCredentialRequest}, LocaleContextHolder.getLocale())),
|
||||
|
||||
this.spec()
|
||||
.iff(() -> ActionConfirmationType.UserInviteToTenant.equals(item.getType()))
|
||||
.must(() -> !this.isNull(item.getUserInviteToTenantRequest()))
|
||||
.failOn(ActionConfirmationPersist._userInviteToTenantRequest).failWith(messageSource.getMessage("Validation_Required", new Object[]{ActionConfirmationPersist._userInviteToTenantRequest}, LocaleContextHolder.getLocale())),
|
||||
this.refSpec()
|
||||
.iff(() -> !this.isNull(item.getDmpInvitation()))
|
||||
.on(ActionConfirmationPersist._dmpInvitation)
|
||||
|
@ -198,12 +212,16 @@ public class ActionConfirmationPersist {
|
|||
.on(ActionConfirmationPersist._mergeAccountConfirmation)
|
||||
.over(item.getMergeAccountConfirmation())
|
||||
.using(() -> this.validatorFactory.validator(MergeAccountConfirmationPersist.MergeAccountConfirmationPersistValidator.class)),
|
||||
|
||||
this.refSpec()
|
||||
.iff(() -> !this.isNull(item.getRemoveCredentialRequest()))
|
||||
.on(ActionConfirmationPersist._removeCredentialRequest)
|
||||
.over(item.getRemoveCredentialRequest())
|
||||
.using(() -> this.validatorFactory.validator(RemoveCredentialRequestPersist.RemoveCredentialRequestPersistValidator.class))
|
||||
.using(() -> this.validatorFactory.validator(RemoveCredentialRequestPersist.RemoveCredentialRequestPersistValidator.class)),
|
||||
this.refSpec()
|
||||
.iff(() -> !this.isNull(item.getUserInviteToTenantRequest()))
|
||||
.on(ActionConfirmationPersist._userInviteToTenantRequest)
|
||||
.over(item.getUserInviteToTenantRequest())
|
||||
.using(() -> this.validatorFactory.validator(UserInviteToTenantRequestPersist.UserInviteToTenantRequestPersistValidator.class))
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
package org.opencdmp.model.persist;
|
||||
|
||||
import gr.cite.tools.validation.specification.Specification;
|
||||
import org.opencdmp.commons.validation.BaseValidator;
|
||||
import org.opencdmp.convention.ConventionService;
|
||||
import org.opencdmp.errorcode.ErrorThesaurusProperties;
|
||||
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 java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class UserInviteToTenantRequestPersist {
|
||||
|
||||
private String email;
|
||||
public static final String _email = "email";
|
||||
|
||||
|
||||
private String tenantCode;
|
||||
public static final String _tenantCode = "tenantCode";
|
||||
|
||||
private List<String> roles;
|
||||
public static final String _roles = "roles";
|
||||
|
||||
|
||||
public String getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
public void setEmail(String email) {
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
public String getTenantCode() {
|
||||
return tenantCode;
|
||||
}
|
||||
|
||||
public void setTenantCode(String tenantCode) {
|
||||
this.tenantCode = tenantCode;
|
||||
}
|
||||
|
||||
public List<String> getRoles() {
|
||||
return roles;
|
||||
}
|
||||
|
||||
public void setRoles(List<String> roles) {
|
||||
this.roles = roles;
|
||||
}
|
||||
|
||||
@Component(UserInviteToTenantRequestPersistValidator.ValidatorName)
|
||||
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
|
||||
public static class UserInviteToTenantRequestPersistValidator extends BaseValidator<UserInviteToTenantRequestPersist> {
|
||||
|
||||
public static final String ValidatorName = "UserInviteToTenantRequestPersistValidator";
|
||||
|
||||
private final MessageSource messageSource;
|
||||
|
||||
|
||||
protected UserInviteToTenantRequestPersistValidator(ConventionService conventionService, ErrorThesaurusProperties errors, MessageSource messageSource) {
|
||||
super(conventionService, errors);
|
||||
this.messageSource = messageSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<UserInviteToTenantRequestPersist> modelClass() {
|
||||
return UserInviteToTenantRequestPersist.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Specification> specifications(UserInviteToTenantRequestPersist item) {
|
||||
return Arrays.asList(
|
||||
this.spec()
|
||||
.must(() -> !this.isEmpty(item.getEmail()))
|
||||
.failOn(UserInviteToTenantRequestPersist._email).failWith(messageSource.getMessage("Validation_Required", new Object[]{UserInviteToTenantRequestPersist._email}, LocaleContextHolder.getLocale())),
|
||||
this.spec()
|
||||
.must(() -> !this.isEmpty(item.getTenantCode()))
|
||||
.failOn(UserInviteToTenantRequestPersist._tenantCode).failWith(messageSource.getMessage("Validation_Required", new Object[]{UserInviteToTenantRequestPersist._tenantCode}, LocaleContextHolder.getLocale())),
|
||||
this.spec()
|
||||
.iff(() -> !this.isEmpty(item.getEmail()))
|
||||
.must(() -> this.isValidEmail(item.getEmail()))
|
||||
.failOn(UserInviteToTenantRequestPersist._email).failWith(messageSource.getMessage("Validation_UnexpectedValue", new Object[]{UserInviteToTenantRequestPersist._email}, LocaleContextHolder.getLocale())),
|
||||
this.spec()
|
||||
.must(() -> !this.isListNullOrEmpty(item.getRoles()))
|
||||
.failOn(UserInviteToTenantRequestPersist._roles).failWith(messageSource.getMessage("Validation_Required", new Object[]{UserInviteToTenantRequestPersist._roles}, LocaleContextHolder.getLocale()))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
package org.opencdmp.model.persist;
|
||||
|
||||
import gr.cite.tools.validation.ValidatorFactory;
|
||||
import gr.cite.tools.validation.specification.Specification;
|
||||
import org.opencdmp.commons.validation.BaseValidator;
|
||||
import org.opencdmp.convention.ConventionService;
|
||||
import org.opencdmp.errorcode.ErrorThesaurusProperties;
|
||||
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 java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class UserTenantUsersInviteRequest {
|
||||
|
||||
private List<UserInviteToTenantRequestPersist> users;
|
||||
public static final String _users = "users";
|
||||
|
||||
public List<UserInviteToTenantRequestPersist> getUsers() {
|
||||
return users;
|
||||
}
|
||||
|
||||
public void setUsers(List<UserInviteToTenantRequestPersist> users) {
|
||||
this.users = users;
|
||||
}
|
||||
|
||||
@Component(UserTenantUsersInviteRequestValidator.ValidatorName)
|
||||
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
|
||||
public static class UserTenantUsersInviteRequestValidator extends BaseValidator<UserTenantUsersInviteRequest> {
|
||||
|
||||
public static final String ValidatorName = "UserTenantUsersInviteRequestValidator";
|
||||
|
||||
private final ValidatorFactory validatorFactory;
|
||||
private final MessageSource messageSource;
|
||||
|
||||
|
||||
protected UserTenantUsersInviteRequestValidator(ConventionService conventionService, ErrorThesaurusProperties errors, ValidatorFactory validatorFactory, MessageSource messageSource) {
|
||||
super(conventionService, errors);
|
||||
this.validatorFactory = validatorFactory;
|
||||
this.messageSource = messageSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<UserTenantUsersInviteRequest> modelClass() {
|
||||
return UserTenantUsersInviteRequest.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Specification> specifications(UserTenantUsersInviteRequest item) {
|
||||
return Arrays.asList(
|
||||
this.spec()
|
||||
.must(() -> !this.isListNullOrEmpty(item.getUsers()))
|
||||
.failOn(UserTenantUsersInviteRequest._users).failWith(messageSource.getMessage("Validation_Required", new Object[]{UserTenantUsersInviteRequest._users}, LocaleContextHolder.getLocale())),
|
||||
this.navSpec()
|
||||
.iff(() -> !this.isListNullOrEmpty(item.getUsers()))
|
||||
.on(UserTenantUsersInviteRequest._users)
|
||||
.over(item.getUsers())
|
||||
.using((itm) -> this.validatorFactory.validator(UserInviteToTenantRequestPersist.UserInviteToTenantRequestPersistValidator.class))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -21,6 +21,7 @@ import org.opencdmp.commons.scope.user.UserScope;
|
|||
import org.opencdmp.commons.types.actionconfirmation.DmpInvitationEntity;
|
||||
import org.opencdmp.commons.types.actionconfirmation.MergeAccountConfirmationEntity;
|
||||
import org.opencdmp.commons.types.actionconfirmation.RemoveCredentialRequestEntity;
|
||||
import org.opencdmp.commons.types.actionconfirmation.UserInviteToTenantRequestEntity;
|
||||
import org.opencdmp.convention.ConventionService;
|
||||
import org.opencdmp.data.ActionConfirmationEntity;
|
||||
import org.opencdmp.data.TenantEntityManager;
|
||||
|
@ -29,6 +30,7 @@ import org.opencdmp.model.actionconfirmation.ActionConfirmation;
|
|||
import org.opencdmp.model.builder.actionconfirmation.ActionConfirmationBuilder;
|
||||
import org.opencdmp.model.deleter.ActionConfirmationDeleter;
|
||||
import org.opencdmp.model.persist.ActionConfirmationPersist;
|
||||
import org.opencdmp.model.persist.UserInviteToTenantRequestPersist;
|
||||
import org.opencdmp.model.persist.actionconfirmation.DmpInvitationPersist;
|
||||
import org.opencdmp.model.persist.actionconfirmation.MergeAccountConfirmationPersist;
|
||||
import org.opencdmp.model.persist.actionconfirmation.RemoveCredentialRequestPersist;
|
||||
|
@ -104,6 +106,7 @@ public class ActionConfirmationServiceImpl implements ActionConfirmationService
|
|||
case MergeAccount -> data.setData(this.xmlHandlingService.toXmlSafe(this.buildMergeAccountConfirmationEntity(model.getMergeAccountConfirmation())));
|
||||
case DmpInvitation -> data.setData(this.xmlHandlingService.toXmlSafe(this.buildDmpInvitationEntity(model.getDmpInvitation())));
|
||||
case RemoveCredential -> data.setData(this.xmlHandlingService.toXmlSafe(this.buildMergeAccountConfirmationEntity(model.getRemoveCredentialRequest())));
|
||||
case UserInviteToTenant -> data.setData(this.xmlHandlingService.toXmlSafe(this.buildUserInviteToTenantRequestEntity(model.getUserInviteToTenantRequest())));
|
||||
default -> throw new InternalError("unknown type: " + model.getType());
|
||||
}
|
||||
data.setUpdatedAt(Instant.now());
|
||||
|
@ -145,6 +148,17 @@ public class ActionConfirmationServiceImpl implements ActionConfirmationService
|
|||
return data;
|
||||
}
|
||||
|
||||
private @NotNull UserInviteToTenantRequestEntity buildUserInviteToTenantRequestEntity(UserInviteToTenantRequestPersist persist){
|
||||
UserInviteToTenantRequestEntity data = new UserInviteToTenantRequestEntity();
|
||||
if (persist == null) return data;
|
||||
|
||||
data.setEmail(persist.getEmail());
|
||||
data.setTenantCode(persist.getTenantCode());
|
||||
data.setRoles(persist.getRoles());
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
public void deleteAndSave(UUID id) throws MyForbiddenException, InvalidApplicationException {
|
||||
logger.debug("deleting : {}", id);
|
||||
|
||||
|
|
|
@ -7,9 +7,7 @@ import gr.cite.tools.exception.MyNotFoundException;
|
|||
import gr.cite.tools.exception.MyValidationException;
|
||||
import gr.cite.tools.fieldset.FieldSet;
|
||||
import jakarta.xml.bind.JAXBException;
|
||||
import org.opencdmp.model.persist.UserMergeRequestPersist;
|
||||
import org.opencdmp.model.persist.UserPersist;
|
||||
import org.opencdmp.model.persist.UserRolePatchPersist;
|
||||
import org.opencdmp.model.persist.*;
|
||||
import org.opencdmp.model.persist.actionconfirmation.RemoveCredentialRequestPersist;
|
||||
import org.opencdmp.model.user.User;
|
||||
|
||||
|
@ -37,9 +35,13 @@ public interface UserService {
|
|||
|
||||
void sendRemoveCredentialConfirmation(RemoveCredentialRequestPersist model) throws InvalidApplicationException, JAXBException;
|
||||
|
||||
void sendUserToTenantInvitation(UserTenantUsersInviteRequest users) throws InvalidApplicationException, JAXBException;
|
||||
|
||||
boolean doesTokenBelongToLoggedInUser(String token) throws InvalidApplicationException, IOException;
|
||||
|
||||
void confirmMergeAccount(String token) throws InvalidApplicationException, IOException;
|
||||
|
||||
void confirmRemoveCredential(String token) throws InvalidApplicationException;
|
||||
|
||||
void confirmUserInviteToTenant(String token) throws InvalidApplicationException;
|
||||
}
|
||||
|
|
|
@ -33,9 +33,8 @@ import org.opencdmp.commons.scope.tenant.TenantScope;
|
|||
import org.opencdmp.commons.scope.user.UserScope;
|
||||
import org.opencdmp.commons.types.actionconfirmation.MergeAccountConfirmationEntity;
|
||||
import org.opencdmp.commons.types.actionconfirmation.RemoveCredentialRequestEntity;
|
||||
import org.opencdmp.commons.types.notification.DataType;
|
||||
import org.opencdmp.commons.types.notification.FieldInfo;
|
||||
import org.opencdmp.commons.types.notification.NotificationFieldData;
|
||||
import org.opencdmp.commons.types.actionconfirmation.UserInviteToTenantRequestEntity;
|
||||
import org.opencdmp.commons.types.notification.*;
|
||||
import org.opencdmp.commons.types.reference.DefinitionEntity;
|
||||
import org.opencdmp.commons.types.user.AdditionalInfoEntity;
|
||||
import org.opencdmp.commons.types.usercredential.UserCredentialDataEntity;
|
||||
|
@ -912,4 +911,145 @@ public class UserServiceImpl implements UserService {
|
|||
throw new MyApplicationException("Token has expired!");
|
||||
}
|
||||
}
|
||||
|
||||
public void sendUserToTenantInvitation(UserTenantUsersInviteRequest users) throws InvalidApplicationException, JAXBException {
|
||||
String tenantName = null;
|
||||
String tenantCode = null;
|
||||
if (this.tenantScope.getTenantCode() != null && !this.tenantScope.getTenantCode().equals(this.tenantScope.getDefaultTenantCode())) {
|
||||
TenantEntity tenantEntity = this.queryFactory.query(TenantQuery.class).disableTracking().authorize(AuthorizationFlags.AllExceptPublic).codes(this.tenantScope.getTenantCode()).isActive(IsActive.Active).first();
|
||||
if (tenantEntity == null) throw new MyApplicationException("Tenant not found");
|
||||
tenantName = tenantEntity.getName();
|
||||
tenantCode = tenantEntity.getCode();
|
||||
} else {
|
||||
tenantName = "OpenCDMP";
|
||||
tenantCode = this.tenantScope.getDefaultTenantCode();
|
||||
}
|
||||
for (UserInviteToTenantRequestPersist user: users.getUsers()) {
|
||||
String token = this.createUserInviteToTenantConfirmation(user, tenantCode);
|
||||
this.createTenantSpecificInvitationUserNotificationEvent(token, user.getEmail(), tenantName);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private String createUserInviteToTenantConfirmation(UserInviteToTenantRequestPersist model, String tenantCode) throws JAXBException, InvalidApplicationException {
|
||||
ActionConfirmationPersist persist = new ActionConfirmationPersist();
|
||||
persist.setType(ActionConfirmationType.UserInviteToTenant);
|
||||
persist.setStatus(ActionConfirmationStatus.Requested);
|
||||
persist.setToken(UUID.randomUUID().toString());
|
||||
persist.setUserInviteToTenantRequest(new UserInviteToTenantRequestPersist());
|
||||
persist.getUserInviteToTenantRequest().setEmail(model.getEmail());
|
||||
persist.getUserInviteToTenantRequest().setRoles(model.getRoles());
|
||||
persist.getUserInviteToTenantRequest().setTenantCode(tenantCode);
|
||||
persist.setExpiresAt(Instant.now().plusSeconds(this.notificationProperties.getEmailExpirationTimeSeconds()));
|
||||
this.validatorFactory.validator(ActionConfirmationPersist.ActionConfirmationPersistValidator.class).validateForce(persist);
|
||||
this.actionConfirmationService.persist(persist, null);
|
||||
|
||||
try {
|
||||
this.entityManager.disableTenantFilters();
|
||||
} finally {
|
||||
this.entityManager.reloadTenantFilters();
|
||||
}
|
||||
return persist.getToken();
|
||||
}
|
||||
|
||||
private void createTenantSpecificInvitationUserNotificationEvent(String token, String email, String tenantName) throws InvalidApplicationException {
|
||||
UserEntity currentUser = this.entityManager.find(UserEntity.class, this.userScope.getUserIdSafe());
|
||||
if (currentUser == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{ this.userScope.getUserIdSafe(), User.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
||||
|
||||
NotifyIntegrationEvent event = new NotifyIntegrationEvent();
|
||||
|
||||
List<ContactPair> contactPairs = new ArrayList<>();
|
||||
contactPairs.add(new ContactPair(ContactInfoType.Email, email));
|
||||
|
||||
NotificationContactData contactData = new NotificationContactData(contactPairs, null, null);
|
||||
event.setContactHint(this.jsonHandlingService.toJsonSafe(contactData));
|
||||
event.setContactTypeHint(NotificationContactType.EMAIL);
|
||||
|
||||
event.setNotificationType(this.notificationProperties.getTenantSpecificInvitationUserType());
|
||||
NotificationFieldData data = new NotificationFieldData();
|
||||
List<FieldInfo> fieldInfoList = new ArrayList<>();
|
||||
fieldInfoList.add(new FieldInfo("{userName}", DataType.String, currentUser.getName()));
|
||||
fieldInfoList.add(new FieldInfo("{confirmationToken}", DataType.String, token));
|
||||
fieldInfoList.add(new FieldInfo("{expiration_time}", DataType.String, this.secondsToTime(this.notificationProperties.getEmailExpirationTimeSeconds())));
|
||||
fieldInfoList.add(new FieldInfo("{tenantName}", DataType.String, tenantName));
|
||||
|
||||
data.setFields(fieldInfoList);
|
||||
event.setData(this.jsonHandlingService.toJsonSafe(data));
|
||||
this.eventHandler.handle(event);
|
||||
}
|
||||
|
||||
public void confirmUserInviteToTenant(String token) throws InvalidApplicationException {
|
||||
ActionConfirmationEntity action;
|
||||
try {
|
||||
this.entityManager.disableTenantFilters();
|
||||
action = this.queryFactory.query(ActionConfirmationQuery.class).tokens(token).types(ActionConfirmationType.UserInviteToTenant).isActive(IsActive.Active).first();
|
||||
} finally {
|
||||
this.entityManager.reloadTenantFilters();
|
||||
}
|
||||
if (action == null)
|
||||
throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{token, ActionConfirmationEntity.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
||||
this.checkActionState(action);
|
||||
|
||||
UserInviteToTenantRequestEntity userInviteToTenantRequest = this.xmlHandlingService.fromXmlSafe(UserInviteToTenantRequestEntity.class, action.getData());
|
||||
if (userInviteToTenantRequest == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{action.getId(), UserInviteToTenantRequestEntity.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
||||
|
||||
TenantEntity tenantEntity = this.queryFactory.query(TenantQuery.class).disableTracking().authorize(AuthorizationFlags.AllExceptPublic).codes(userInviteToTenantRequest.getTenantCode()).isActive(IsActive.Active).first();
|
||||
if (tenantEntity == null) throw new MyApplicationException("Tenant not found");
|
||||
this.addUserToTenant(tenantEntity, userInviteToTenantRequest);
|
||||
|
||||
}
|
||||
|
||||
private void addUserToTenant(TenantEntity tenant, UserInviteToTenantRequestEntity userInviteToTenantRequest) throws InvalidApplicationException {
|
||||
|
||||
UUID userId = null;
|
||||
try {
|
||||
this.entityManager.disableTenantFilters();
|
||||
|
||||
UserContactInfoEntity contactInfoEntity = this.queryFactory.query(UserContactInfoQuery.class).disableTracking().values(userInviteToTenantRequest.getEmail()).types(ContactInfoType.Email).first();
|
||||
if (contactInfoEntity != null){
|
||||
userId = contactInfoEntity.getUserId();
|
||||
}
|
||||
|
||||
if (userId != null) {
|
||||
UserCredentialEntity userCredential = this.queryFactory.query(UserCredentialQuery.class).disableTracking().userIds(userId).first();
|
||||
if (userCredential == null) throw new MyApplicationException();
|
||||
|
||||
TenantUserEntity tenantUserEntity = new TenantUserEntity();
|
||||
tenantUserEntity.setId(UUID.randomUUID());
|
||||
tenantUserEntity.setUserId(userId);
|
||||
tenantUserEntity.setIsActive(IsActive.Active);
|
||||
tenantUserEntity.setTenantId(tenant.getId());
|
||||
tenantUserEntity.setCreatedAt(Instant.now());
|
||||
tenantUserEntity.setUpdatedAt(Instant.now());
|
||||
this.entityManager.persist(tenantUserEntity);
|
||||
this.eventBroker.emit(new UserAddedToTenantEvent(tenantUserEntity.getUserId(), tenantUserEntity.getTenantId()));
|
||||
|
||||
for (String role: userInviteToTenantRequest.getRoles()) {
|
||||
UserRoleEntity item = new UserRoleEntity();
|
||||
item.setId(UUID.randomUUID());
|
||||
item.setUserId(userId);
|
||||
item.setTenantId(tenant.getId());
|
||||
item.setRole(role);
|
||||
item.setCreatedAt(Instant.now());
|
||||
this.entityManager.persist(item);
|
||||
}
|
||||
this.eventBroker.emit(new UserCredentialTouchedEvent(userCredential.getId(), userCredential.getExternalId()));
|
||||
|
||||
this.entityManager.flush();
|
||||
|
||||
this.userTouchedIntegrationEventHandler.handle(userId);
|
||||
this.eventBroker.emit(new UserTouchedEvent(userId));
|
||||
|
||||
this.entityManager.flush();
|
||||
|
||||
for (String role: userInviteToTenantRequest.getRoles()) {
|
||||
this.keycloakService.addUserToTenantRoleGroup(userCredential.getExternalId(), tenant.getCode(), role);
|
||||
}
|
||||
}
|
||||
|
||||
} finally {
|
||||
this.entityManager.reloadTenantFilters();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -24,9 +24,7 @@ import org.opencdmp.model.builder.DmpAssociatedUserBuilder;
|
|||
import org.opencdmp.model.builder.UserBuilder;
|
||||
import org.opencdmp.model.censorship.DmpAssociatedUserCensor;
|
||||
import org.opencdmp.model.censorship.UserCensor;
|
||||
import org.opencdmp.model.persist.UserMergeRequestPersist;
|
||||
import org.opencdmp.model.persist.UserPersist;
|
||||
import org.opencdmp.model.persist.UserRolePatchPersist;
|
||||
import org.opencdmp.model.persist.*;
|
||||
import org.opencdmp.model.persist.actionconfirmation.RemoveCredentialRequestPersist;
|
||||
import org.opencdmp.model.result.QueryResult;
|
||||
import org.opencdmp.model.user.User;
|
||||
|
@ -334,4 +332,33 @@ public class UserController {
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
@PostMapping("invite-users-to-tenant")
|
||||
@Transactional
|
||||
@ValidationFilterAnnotation(validator = UserTenantUsersInviteRequest.UserTenantUsersInviteRequestValidator.ValidatorName, argumentName = "model")
|
||||
public Boolean inviteUsersToTenant(@RequestBody UserTenantUsersInviteRequest users) throws InvalidApplicationException, JAXBException {
|
||||
logger.debug(new MapLogEntry("send tenant invitation to users").And("users", users));
|
||||
|
||||
this.userTypeService.sendUserToTenantInvitation(users);
|
||||
|
||||
this.auditService.track(AuditableAction.User_InviteToTenant, Map.ofEntries(
|
||||
new AbstractMap.SimpleEntry<String, Object>("users", users)
|
||||
));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@GetMapping("confirm-invite-user-to-tenant/token/{token}")
|
||||
@Transactional
|
||||
public Boolean confirmInviteUserToTenant(@PathVariable("token") String token) throws InvalidApplicationException {
|
||||
logger.debug(new MapLogEntry("confirm merge account to user").And("token", token));
|
||||
|
||||
this.userTypeService.confirmUserInviteToTenant(token);
|
||||
|
||||
this.auditService.track(AuditableAction.User_InviteToTenantConfirm, Map.ofEntries(
|
||||
new AbstractMap.SimpleEntry<String, Object>("token", token)
|
||||
));
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,4 +13,5 @@ notification:
|
|||
descriptionTemplateInvitationType: 223BB607-EFA1-4CE7-99EC-4BEABFEF9A8B
|
||||
contactSupportType: 5B1D6C52-88F9-418B-9B8A-6F1F963D9EAD
|
||||
publicContactSupportType: B542B606-ACC6-4629-ADEF-4D8EE2F01222
|
||||
tenantSpecificInvitationUserType: 497dada5-eccc-4bc0-9e0b-63e22b4eb0be
|
||||
contactSupportEmail: support@dmp.com
|
|
@ -57,8 +57,8 @@
|
|||
<button [disabled]="saving" mat-menu-item (click)="formSubmit()" type="button">{{ 'DMP-EDITOR.ACTIONS.SAVE-AND-CONTINUE' | translate }}</button>
|
||||
</mat-menu>
|
||||
</div>
|
||||
<div class="col-auto d-flex align-items-center" [matTooltipDisabled]="canFinalize && formGroup.pristine" matTooltip="{{'DMP-EDITOR.ACTIONS.FINALIZE.CAN-NOT-FINALIZE' | translate}}">
|
||||
<button [disabled]="!canFinalize || !formGroup.pristine" mat-raised-button class="save-btn mr-2" type="button" (click)="finalize()">{{ 'DMP-EDITOR.ACTIONS.FINALIZE.FINALIZE' | translate }}</button>
|
||||
<div class="col-auto d-flex align-items-center" *ngIf="canFinalize" [matTooltipDisabled]="canFinalize && formGroup.pristine" matTooltip="{{'DMP-EDITOR.ACTIONS.FINALIZE.CAN-NOT-FINALIZE' | translate}}">
|
||||
<button [disabled]="!formGroup.pristine" mat-raised-button class="save-btn mr-2" type="button" (click)="finalize()">{{ 'DMP-EDITOR.ACTIONS.FINALIZE.FINALIZE' | translate }}</button>
|
||||
</div>
|
||||
<div *ngIf="formGroup.pristine" class="col-auto d-flex align-items-center">
|
||||
<button [disabled]="saving" *ngIf="isLocked" mat-raised-button class="save-btn mr-2" type="button">{{ 'DMP-EDITOR.ACTIONS.LOCKED' | translate}}</button>
|
||||
|
|
|
@ -660,15 +660,18 @@ public class DescriptionTemplateXmlMigrationService {
|
|||
|
||||
ExternalFetcherApiSourceConfigurationEntity apiEntity = new ExternalFetcherApiSourceConfigurationEntity();
|
||||
|
||||
|
||||
String source = persist.getAutoCompleteOptions() != null ? persist.getAutoCompleteOptions().getSource() : null;
|
||||
|
||||
if ( source == null || source.isEmpty()) {
|
||||
URI uri;
|
||||
if (persist.getUrl().contains("?")) {
|
||||
uri = new URI(persist.getUrl().substring(0, persist.getUrl().trim().lastIndexOf("?")));
|
||||
} else {
|
||||
uri = new URI(persist.getUrl().trim());
|
||||
}
|
||||
String source = persist.getAutoCompleteOptions().getSource();
|
||||
source = source != null && !source.isEmpty() ? source : uri.getHost();
|
||||
|
||||
source = uri.getHost();
|
||||
}
|
||||
String parsedUrl = persist.getUrl().trim();
|
||||
parsedUrl = parsedUrl.replace("%20", " ");
|
||||
parsedUrl = parsedUrl.replace("%22", "\"");
|
||||
|
@ -705,14 +708,14 @@ public class DescriptionTemplateXmlMigrationService {
|
|||
|
||||
|
||||
data.setResultsArrayPath(persist.getOptionsRoot());
|
||||
if (persist.getAutoCompleteOptions() == null && this.conventionService.isNullOrEmpty(persist.getAutoCompleteOptions().getLabel())) {
|
||||
if (persist.getAutoCompleteOptions() != null && !this.conventionService.isNullOrEmpty(persist.getAutoCompleteOptions().getLabel())) {
|
||||
data.setFieldsMapping(new ArrayList<>());
|
||||
ResultFieldsMappingConfigurationEntity labelField = new ResultFieldsMappingConfigurationEntity();
|
||||
labelField.setCode(ReferenceEntity.KnownFields.Label);
|
||||
labelField.setResponsePath(persist.getAutoCompleteOptions().getLabel());
|
||||
data.getFieldsMapping().add(labelField);
|
||||
}
|
||||
if (persist.getAutoCompleteOptions() == null && this.conventionService.isNullOrEmpty(persist.getAutoCompleteOptions().getValue())) {
|
||||
if (persist.getAutoCompleteOptions() != null && !this.conventionService.isNullOrEmpty(persist.getAutoCompleteOptions().getValue())) {
|
||||
ResultFieldsMappingConfigurationEntity idField = new ResultFieldsMappingConfigurationEntity();
|
||||
idField.setCode(ReferenceEntity.KnownFields.ReferenceId);
|
||||
idField.setResponsePath(persist.getAutoCompleteOptions().getValue());
|
||||
|
|
|
@ -48,6 +48,9 @@ notification:
|
|||
- #publicContactSupportType
|
||||
type: B542B606-ACC6-4629-ADEF-4D8EE2F01222
|
||||
contacts: [ email ]
|
||||
- #tenantSpecificInvitationUserType
|
||||
type: 497dada5-eccc-4bc0-9e0b-63e22b4eb0be
|
||||
contacts: [ email ]
|
||||
message:
|
||||
email:
|
||||
flows:
|
||||
|
@ -386,6 +389,29 @@ notification:
|
|||
bcc-mode: 0
|
||||
allow-attachments: false
|
||||
cipher-fields: [ ]
|
||||
- #tenantSpecificInvitationUserType
|
||||
key: 497dada5-eccc-4bc0-9e0b-63e22b4eb0be
|
||||
subject-path: classpath:notification_templates/tenantspecificinvitationuser/email/subject.{language}.txt
|
||||
subject-field-options:
|
||||
mandatory: [ ]
|
||||
optional: [ ]
|
||||
body-path: classpath:notification_templates/tenantspecificinvitationuser/email/body.{language}.html
|
||||
body-field-options:
|
||||
mandatory: [ "{userName}", "{installation-url}", "{confirmationToken}", "{tenantName}" ]
|
||||
optional:
|
||||
- key: "{expiration_time}"
|
||||
value: ---
|
||||
formatting:
|
||||
'[{userName}]': null
|
||||
'[{tenantName}]': null
|
||||
'[{installation-url}]': null
|
||||
'[{expiration_time}]': null
|
||||
cc: [ ]
|
||||
cc-mode: 0
|
||||
bcc: [ ]
|
||||
bcc-mode: 0
|
||||
allow-attachments: false
|
||||
cipher-fields: [ ]
|
||||
template-cache:
|
||||
prefix: ${CACHE_DISAMBIGUATION:}
|
||||
key-pattern: "{prefix}:Notification_Message_Email_Template:{key}:v0"
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1 @@
|
|||
OpenCDMP - Tenant Invitation
|
Loading…
Reference in New Issue