external plan user invitation fixes
(cherry picked from commit d0cd1719a9
)
This commit is contained in:
parent
fabeca2631
commit
6c94ccadf9
|
@ -18,6 +18,9 @@ public class PlanInvitationEntity {
|
|||
@XmlAttribute(name = "plan-role")
|
||||
private PlanUserRole role;
|
||||
|
||||
@XmlAttribute(name = "section")
|
||||
private UUID sectionId;
|
||||
|
||||
public String getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
@ -41,4 +44,12 @@ public class PlanInvitationEntity {
|
|||
public void setRole(PlanUserRole role) {
|
||||
this.role = role;
|
||||
}
|
||||
|
||||
public UUID getSectionId() {
|
||||
return sectionId;
|
||||
}
|
||||
|
||||
public void setSectionId(UUID sectionId) {
|
||||
this.sectionId = sectionId;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
package org.opencdmp.model;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class PlanInvitationResult {
|
||||
|
||||
private UUID planId;
|
||||
|
||||
private Boolean isAlreadyAccepted;
|
||||
|
||||
public UUID getPlanId() {
|
||||
return planId;
|
||||
}
|
||||
|
||||
public void setPlanId(UUID planId) {
|
||||
this.planId = planId;
|
||||
}
|
||||
|
||||
public Boolean getIsAlreadyAccepted() {
|
||||
return isAlreadyAccepted;
|
||||
}
|
||||
|
||||
public void setIsAlreadyAccepted(Boolean alreadyAccepted) {
|
||||
isAlreadyAccepted = alreadyAccepted;
|
||||
}
|
||||
}
|
|
@ -12,6 +12,9 @@ public class PlanInvitation {
|
|||
private UUID planId;
|
||||
public static final String _planId = "planId";
|
||||
|
||||
private UUID sectionId;
|
||||
public static final String _sectionId = "sectionId";
|
||||
|
||||
private PlanUserRole role;
|
||||
public static final String _role = "role";
|
||||
|
||||
|
@ -32,6 +35,14 @@ public class PlanInvitation {
|
|||
this.planId = planId;
|
||||
}
|
||||
|
||||
public UUID getSectionId() {
|
||||
return sectionId;
|
||||
}
|
||||
|
||||
public void setSectionId(UUID sectionId) {
|
||||
this.sectionId = sectionId;
|
||||
}
|
||||
|
||||
public PlanUserRole getRole() {
|
||||
return role;
|
||||
}
|
||||
|
|
|
@ -47,6 +47,7 @@ public class PlanInvitationBuilder extends BaseBuilder<PlanInvitation, PlanInvit
|
|||
PlanInvitation m = new PlanInvitation();
|
||||
if (fields.hasField(this.asIndexer(PlanInvitation._email))) m.setEmail(d.getEmail());
|
||||
if (fields.hasField(this.asIndexer(PlanInvitation._planId))) m.setPlanId(d.getPlanId());
|
||||
if (fields.hasField(this.asIndexer(PlanInvitation._sectionId))) m.setSectionId(d.getSectionId());
|
||||
if (fields.hasField(this.asIndexer(PlanInvitation._role))) m.setRole(d.getRole());
|
||||
|
||||
models.add(m);
|
||||
|
|
|
@ -25,13 +25,18 @@ public class PlanInvitationPersist {
|
|||
|
||||
public static final String _planId = "planId";
|
||||
|
||||
private UUID sectionId;
|
||||
|
||||
public static final String _sectionId = "sectionId";
|
||||
|
||||
private PlanUserRole role;
|
||||
|
||||
public static final String _role = "role";
|
||||
|
||||
public PlanInvitationPersist(String email, UUID planId, PlanUserRole role) {
|
||||
public PlanInvitationPersist(String email, UUID planId, UUID sectionId, PlanUserRole role) {
|
||||
this.email = email;
|
||||
this.planId = planId;
|
||||
this.sectionId = sectionId;
|
||||
this.role = role;
|
||||
}
|
||||
|
||||
|
@ -51,6 +56,14 @@ public class PlanInvitationPersist {
|
|||
this.planId = planId;
|
||||
}
|
||||
|
||||
public UUID getSectionId() {
|
||||
return sectionId;
|
||||
}
|
||||
|
||||
public void setSectionId(UUID sectionId) {
|
||||
this.sectionId = sectionId;
|
||||
}
|
||||
|
||||
public PlanUserRole getRole() {
|
||||
return role;
|
||||
}
|
||||
|
|
|
@ -126,6 +126,7 @@ public class ActionConfirmationServiceImpl implements ActionConfirmationService
|
|||
data.setEmail(persist.getEmail());
|
||||
data.setRole(persist.getRole());
|
||||
data.setPlanId(persist.getPlanId());
|
||||
data.setSectionId(persist.getSectionId());
|
||||
|
||||
return data;
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import gr.cite.tools.fieldset.FieldSet;
|
|||
import jakarta.xml.bind.JAXBException;
|
||||
import org.opencdmp.commons.types.plan.importexport.PlanImportExport;
|
||||
import org.opencdmp.filetransformerbase.models.misc.PreprocessingPlanModel;
|
||||
import org.opencdmp.model.PlanInvitationResult;
|
||||
import org.opencdmp.model.PlanUser;
|
||||
import org.opencdmp.model.PlanValidationResult;
|
||||
import org.opencdmp.model.plan.Plan;
|
||||
|
@ -50,7 +51,7 @@ public interface PlanService {
|
|||
|
||||
void inviteUserOrAssignUsers(UUID id, List<PlanUserPersist> users) throws InvalidApplicationException, JAXBException, IOException;
|
||||
|
||||
UUID planInvitationAccept(String token) throws InvalidApplicationException, IOException;
|
||||
PlanInvitationResult planInvitationAccept(String token) throws InvalidApplicationException, IOException;
|
||||
|
||||
PlanImportExport exportXmlEntity(UUID id, boolean ignoreAuthorize, boolean isPublic) throws MyForbiddenException, MyNotFoundException, JAXBException, ParserConfigurationException, IOException, InstantiationException, IllegalAccessException, SAXException, InvalidApplicationException;
|
||||
|
||||
|
|
|
@ -69,10 +69,7 @@ import org.opencdmp.integrationevent.outbox.annotationentityremoval.AnnotationEn
|
|||
import org.opencdmp.integrationevent.outbox.annotationentitytouch.AnnotationEntityTouchedIntegrationEventHandler;
|
||||
import org.opencdmp.integrationevent.outbox.notification.NotifyIntegrationEvent;
|
||||
import org.opencdmp.integrationevent.outbox.notification.NotifyIntegrationEventHandler;
|
||||
import org.opencdmp.model.PlanDescriptionTemplate;
|
||||
import org.opencdmp.model.PlanUser;
|
||||
import org.opencdmp.model.PlanValidationResult;
|
||||
import org.opencdmp.model.PublicPlan;
|
||||
import org.opencdmp.model.*;
|
||||
import org.opencdmp.model.builder.PlanUserBuilder;
|
||||
import org.opencdmp.model.builder.description.DescriptionBuilder;
|
||||
import org.opencdmp.model.builder.plan.PlanBuilder;
|
||||
|
@ -1975,7 +1972,7 @@ public class PlanServiceImpl implements PlanService {
|
|||
this.sendPlanInvitationExistingUser(user.getUser(), plan, user.getRole());
|
||||
}
|
||||
}else if (user.getEmail() != null) {
|
||||
this.sendPlanInvitationExternalUser(user.getEmail(),plan, user.getRole());
|
||||
this.sendPlanInvitationExternalUser(user.getEmail(),plan, user.getRole(), user.getSectionId());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -2013,8 +2010,8 @@ public class PlanServiceImpl implements PlanService {
|
|||
this.eventHandler.handle(event);
|
||||
}
|
||||
|
||||
private void sendPlanInvitationExternalUser(String email, PlanEntity plan, PlanUserRole role) throws JAXBException, InvalidApplicationException {
|
||||
String token = this.createActionConfirmation(email, plan, role);
|
||||
private void sendPlanInvitationExternalUser(String email, PlanEntity plan, PlanUserRole role, UUID sectionId) throws JAXBException, InvalidApplicationException {
|
||||
String token = this.createActionConfirmation(email, plan, role, sectionId);
|
||||
|
||||
NotifyIntegrationEvent event = new NotifyIntegrationEvent();
|
||||
|
||||
|
@ -2038,12 +2035,12 @@ public class PlanServiceImpl implements PlanService {
|
|||
this.eventHandler.handle(event);
|
||||
}
|
||||
|
||||
private String createActionConfirmation(String email, PlanEntity plan, PlanUserRole role) throws JAXBException, InvalidApplicationException {
|
||||
private String createActionConfirmation(String email, PlanEntity plan, PlanUserRole role, UUID sectionId) throws JAXBException, InvalidApplicationException {
|
||||
ActionConfirmationPersist persist = new ActionConfirmationPersist();
|
||||
persist.setType(ActionConfirmationType.PlanInvitation);
|
||||
persist.setStatus(ActionConfirmationStatus.Requested);
|
||||
persist.setToken(UUID.randomUUID().toString());
|
||||
persist.setPlanInvitation(new PlanInvitationPersist(email, plan.getId(), role));
|
||||
persist.setPlanInvitation(new PlanInvitationPersist(email, plan.getId(), sectionId, role));
|
||||
persist.setExpiresAt(Instant.now().plusSeconds(this.notificationProperties.getEmailExpirationTimeSeconds()));
|
||||
this.validatorFactory.validator(ActionConfirmationPersist.ActionConfirmationPersistValidator.class).validateForce(persist);
|
||||
this.actionConfirmationService.persist(persist, null);
|
||||
|
@ -2051,23 +2048,29 @@ public class PlanServiceImpl implements PlanService {
|
|||
return persist.getToken();
|
||||
}
|
||||
|
||||
public UUID planInvitationAccept(String token) throws InvalidApplicationException {
|
||||
public PlanInvitationResult planInvitationAccept(String token) throws InvalidApplicationException {
|
||||
PlanInvitationResult planInvitationResult = new PlanInvitationResult();
|
||||
ActionConfirmationEntity action = this.queryFactory.query(ActionConfirmationQuery.class).tokens(token).types(ActionConfirmationType.PlanInvitation).isActive(IsActive.Active).first();
|
||||
|
||||
if (action == null){
|
||||
throw new MyValidationException(this.errors.getTokenNotExist().getCode(), this.errors.getTokenNotExist().getMessage());
|
||||
}
|
||||
if (action.getStatus().equals(ActionConfirmationStatus.Accepted)){
|
||||
throw new MyValidationException(this.errors.getPlanInvitationAlreadyConfirmed().getCode(), this.errors.getPlanInvitationAlreadyConfirmed().getMessage());
|
||||
}
|
||||
if (action.getExpiresAt().compareTo(Instant.now()) < 0){
|
||||
throw new MyValidationException(this.errors.getRequestHasExpired().getCode(), this.errors.getRequestHasExpired().getMessage());
|
||||
}
|
||||
|
||||
PlanInvitationEntity planInvitation = this.xmlHandlingService.fromXmlSafe(PlanInvitationEntity.class, action.getData());
|
||||
if (planInvitation == null) {
|
||||
throw new MyApplicationException("plan invitation don't exist");
|
||||
}
|
||||
if (action.getStatus().equals(ActionConfirmationStatus.Accepted)){
|
||||
UserContactInfoEntity contactInfoEntity = this.queryFactory.query(UserContactInfoQuery.class).disableTracking().userIds(this.userScope.getUserId()).values(planInvitation.getEmail()).types(ContactInfoType.Email).first();
|
||||
if (contactInfoEntity == null){
|
||||
throw new MyValidationException(this.errors.getAnotherUserToken().getCode(), this.errors.getAnotherUserToken().getMessage());
|
||||
}
|
||||
planInvitationResult.setPlanId(planInvitation.getPlanId());
|
||||
planInvitationResult.setIsAlreadyAccepted(true);
|
||||
return planInvitationResult;
|
||||
}
|
||||
if (action.getExpiresAt().compareTo(Instant.now()) < 0){
|
||||
throw new MyValidationException(this.errors.getRequestHasExpired().getCode(), this.errors.getRequestHasExpired().getMessage());
|
||||
}
|
||||
|
||||
UserContactInfoEntity contactInfoEntity = this.queryFactory.query(UserContactInfoQuery.class).disableTracking().userIds(this.userScope.getUserId()).values(planInvitation.getEmail()).types(ContactInfoType.Email).first();
|
||||
if (contactInfoEntity == null){
|
||||
|
@ -2081,13 +2084,16 @@ public class PlanServiceImpl implements PlanService {
|
|||
data.setRole(planInvitation.getRole());
|
||||
data.setUserId(this.userScope.getUserIdSafe());
|
||||
data.setPlanId(planInvitation.getPlanId());
|
||||
data.setSectionId(planInvitation.getSectionId());
|
||||
this.entityManager.persist(data);
|
||||
|
||||
action.setStatus(ActionConfirmationStatus.Accepted);
|
||||
this.entityManager.merge(action);
|
||||
|
||||
this.annotationEntityTouchedIntegrationEventHandler.handlePlan(planInvitation.getPlanId());
|
||||
return planInvitation.getPlanId();
|
||||
planInvitationResult.setPlanId(planInvitation.getPlanId());
|
||||
planInvitationResult.setIsAlreadyAccepted(false);
|
||||
return planInvitationResult;
|
||||
}
|
||||
|
||||
//region Export
|
||||
|
|
|
@ -31,10 +31,7 @@ import org.opencdmp.controllers.swagger.annotation.Swagger400;
|
|||
import org.opencdmp.controllers.swagger.annotation.Swagger404;
|
||||
import org.opencdmp.controllers.swagger.annotation.SwaggerCommonErrorResponses;
|
||||
import org.opencdmp.filetransformerbase.models.misc.PreprocessingPlanModel;
|
||||
import org.opencdmp.model.DescriptionsToBeFinalized;
|
||||
import org.opencdmp.model.PlanUser;
|
||||
import org.opencdmp.model.PlanValidationResult;
|
||||
import org.opencdmp.model.PublicPlan;
|
||||
import org.opencdmp.model.*;
|
||||
import org.opencdmp.model.builder.PublicPlanBuilder;
|
||||
import org.opencdmp.model.builder.plan.PlanBuilder;
|
||||
import org.opencdmp.model.censorship.PublicPlanCensor;
|
||||
|
@ -469,16 +466,16 @@ public class PlanController {
|
|||
@OperationWithTenantHeader(summary = "Accept an invitation token for a plan by token")
|
||||
@Transactional
|
||||
@Hidden
|
||||
public UUID acceptInvitation(@PathVariable("token") String token) throws InvalidApplicationException, JAXBException, IOException {
|
||||
public PlanInvitationResult acceptInvitation(@PathVariable("token") String token) throws InvalidApplicationException, JAXBException, IOException {
|
||||
logger.debug(new MapLogEntry("inviting users to plan").And("token", token));
|
||||
|
||||
UUID planId = this.planService.planInvitationAccept(token);
|
||||
PlanInvitationResult planInvitationResult = this.planService.planInvitationAccept(token);
|
||||
|
||||
this.auditService.track(AuditableAction.Plan_Invite_Accept, Map.ofEntries(
|
||||
new AbstractMap.SimpleEntry<String, Object>("token", token)
|
||||
));
|
||||
|
||||
return planId;
|
||||
return planInvitationResult;
|
||||
}
|
||||
|
||||
@RequestMapping(method = RequestMethod.GET, value = "/xml/export/{id}", produces = "application/xml")
|
||||
|
|
|
@ -183,5 +183,10 @@ export interface PlanUserInvitePersist {
|
|||
}
|
||||
|
||||
//
|
||||
// Public
|
||||
// Invitation
|
||||
//
|
||||
|
||||
export interface PlanInvitationResult {
|
||||
planId: Guid;
|
||||
isAlreadyAccepted: boolean;
|
||||
}
|
|
@ -15,7 +15,7 @@ import { catchError, map } from 'rxjs/operators';
|
|||
import { nameof } from 'ts-simple-nameof';
|
||||
import { BaseHttpParams } from '../../../../common/http/base-http-params';
|
||||
import { InterceptorType } from '../../../../common/http/interceptors/interceptor-type';
|
||||
import { ClonePlanPersist, Plan, PlanPersist, PlanUser, PlanUserInvitePersist, PlanUserPersist, PlanUserRemovePersist, NewVersionPlanPersist, PublicPlan } from '../../model/plan/plan';
|
||||
import { ClonePlanPersist, Plan, PlanPersist, PlanUser, PlanUserInvitePersist, PlanUserPersist, PlanUserRemovePersist, NewVersionPlanPersist, PublicPlan, PlanInvitationResult } from '../../model/plan/plan';
|
||||
import { AuthService } from '../auth/auth.service';
|
||||
import { ConfigurationService } from '../configuration/configuration.service';
|
||||
import { BaseHttpV2Service } from '../http/base-http-v2.service';
|
||||
|
@ -162,10 +162,10 @@ export class PlanService {
|
|||
catchError((error: any) => throwError(error)));
|
||||
}
|
||||
|
||||
acceptInvitation(token: string): Observable<Guid> {
|
||||
acceptInvitation(token: string): Observable<PlanInvitationResult> {
|
||||
const url = `${this.apiBase}/token/${token}/invite-accept`;
|
||||
|
||||
return this.http.get<Guid>(url).pipe(catchError((error: any) => throwError(error)));
|
||||
return this.http.get<PlanInvitationResult>(url).pipe(catchError((error: any) => throwError(error)));
|
||||
}
|
||||
|
||||
downloadXML(id: Guid): Observable<HttpResponse<Blob>> {
|
||||
|
|
|
@ -2,11 +2,12 @@ import { HttpErrorResponse } from '@angular/common/http';
|
|||
import { Component, OnInit } from '@angular/core';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { AuthService } from '@app/core/services/auth/auth.service';
|
||||
import { SnackBarNotificationLevel } from '@app/core/services/notification/ui-notification-service';
|
||||
import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/services/notification/ui-notification-service';
|
||||
import { PlanService } from '@app/core/services/plan/plan.service';
|
||||
import { RouterUtilsService } from '@app/core/services/router/router-utils.service';
|
||||
import { BaseComponent } from '@common/base/base.component';
|
||||
import { HttpError, HttpErrorHandlingService } from '@common/modules/errors/error-handling/http-error-handling.service';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
|
||||
@Component({
|
||||
|
@ -21,7 +22,9 @@ export class InvitationAcceptedComponent extends BaseComponent implements OnInit
|
|||
private router: Router,
|
||||
private authentication: AuthService,
|
||||
protected routerUtils: RouterUtilsService,
|
||||
private httpErrorHandlingService: HttpErrorHandlingService
|
||||
protected language: TranslateService,
|
||||
private httpErrorHandlingService: HttpErrorHandlingService,
|
||||
private uiNotificationService: UiNotificationService
|
||||
) { super(); }
|
||||
|
||||
ngOnInit(): void {
|
||||
|
@ -35,7 +38,10 @@ export class InvitationAcceptedComponent extends BaseComponent implements OnInit
|
|||
this.planService.acceptInvitation(token)
|
||||
.pipe(takeUntil(this._destroyed))
|
||||
.subscribe(result => {
|
||||
this.router.navigate([this.routerUtils.generateUrl('plans/edit/' + result)]);
|
||||
if (result?.isAlreadyAccepted == false) {
|
||||
this.uiNotificationService.snackBarNotification(this.language.instant('PLAN-USER-INVITATION-DIALOG.SUCCESS'), SnackBarNotificationLevel.Success);
|
||||
}
|
||||
this.router.navigate([this.routerUtils.generateUrl('plans/overview/' + result?.planId)]);
|
||||
},
|
||||
error => this.onCallbackError(error));
|
||||
}else{
|
||||
|
|
Loading…
Reference in New Issue