add functionality on merge-account screen to first validate the token before showing the confimation-form

This commit is contained in:
Sofia Papacharalampous 2024-06-06 14:57:24 +03:00
parent e9a59671ea
commit 631e4bef8b
7 changed files with 61 additions and 3 deletions

View File

@ -37,6 +37,8 @@ public interface UserService {
void sendRemoveCredentialConfirmation(RemoveCredentialRequestPersist model) throws InvalidApplicationException, JAXBException;
boolean doesTokenBelongToLoggedInUser(String token) throws InvalidApplicationException, IOException;
void confirmMergeAccount(String token) throws InvalidApplicationException, IOException;
void confirmRemoveCredential(String token) throws InvalidApplicationException;

View File

@ -601,6 +601,12 @@ public class UserServiceImpl implements UserService {
return (String.format("%02d", hour) + ":" + String.format("%02d", min) + ":" + String.format("%02d", sec));
}
public boolean doesTokenBelongToLoggedInUser(String token) throws IOException, InvalidApplicationException {
UserEntity userToBeMerge = this.getUserEntityFromToken(token);
return this.userScope.getUserIdSafe().equals(userToBeMerge.getId());
}
public void confirmMergeAccount(String token) throws IOException, InvalidApplicationException {
ActionConfirmationEntity action = this.queryFactory.query(ActionConfirmationQuery.class).tokens(token).types(ActionConfirmationType.MergeAccount).isActive(IsActive.Active).first();
if (action == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{token, ActionConfirmationEntity.class.getSimpleName()}, LocaleContextHolder.getLocale()));
@ -842,4 +848,22 @@ public class UserServiceImpl implements UserService {
}
}
private UserEntity getUserEntityFromToken(String token) throws MyForbiddenException, MyNotFoundException {
ActionConfirmationEntity action = this.queryFactory.query(ActionConfirmationQuery.class).tokens(token).types(ActionConfirmationType.MergeAccount).isActive(IsActive.Active).first();
if (action == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{token, ActionConfirmationEntity.class.getSimpleName()}, LocaleContextHolder.getLocale()));
this.checkActionState(action);
MergeAccountConfirmationEntity mergeAccountConfirmationEntity = this.xmlHandlingService.fromXmlSafe(MergeAccountConfirmationEntity.class, action.getData());
if (mergeAccountConfirmationEntity == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{action.getId(), MergeAccountConfirmationEntity.class.getSimpleName()}, LocaleContextHolder.getLocale()));
UserContactInfoEntity userContactInfoEntity = this.queryFactory.query(UserContactInfoQuery.class).values(mergeAccountConfirmationEntity.getEmail()).types(ContactInfoType.Email).first();
if (userContactInfoEntity == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{mergeAccountConfirmationEntity.getEmail(), User.class.getSimpleName()}, LocaleContextHolder.getLocale()));
UserEntity userToBeMerge = this.queryFactory.query(UserQuery.class).ids(userContactInfoEntity.getUserId()).isActive(IsActive.Active).first();
if (userToBeMerge == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{userContactInfoEntity.getUserId(), User.class.getSimpleName()}, LocaleContextHolder.getLocale()));
return userToBeMerge;
}
}

View File

@ -297,6 +297,14 @@ public class UserController {
return true;
}
@GetMapping("mine/get-permission/token/{token}")
@Transactional
public Boolean getUserTokenPermission(@PathVariable("token") String token) throws InvalidApplicationException, IOException {
logger.debug(new MapLogEntry("confirm merge account to user").And("token", token));
return this.userTypeService.doesTokenBelongToLoggedInUser(token);
}
@PostMapping("mine/remove-credential-request")
@Transactional
@ValidationFilterAnnotation(validator = RemoveCredentialRequestPersist.RemoveCredentialRequestPersistValidator.ValidatorName, argumentName = "model")

View File

@ -117,6 +117,14 @@ export class UserService {
catchError((error: any) => throwError(error)));
}
getUserTokenPermission(token: Guid): Observable<boolean> {
const url = `${this.apiBase}/mine/get-permission/token/${token}`;
return this.http
.get<boolean>(url).pipe(
catchError((error: any) => throwError(error)));
}
confirmMergeAccount(token: Guid): Observable<boolean> {
const url = `${this.apiBase}/mine/confirm-merge-account/token/${token}`;

View File

@ -4,7 +4,7 @@
<div class="col merge-account-title">{{'MERGE-ACCOUNT.TITLE' | translate}}</div>
</div>
<div *ngIf="showForm" class="row merge-account-content">
<div class="col">
<div *ngIf="isTokenValid" class="col">
<div class="row justify-content-center">
<div class="col-auto">
<span>
@ -20,6 +20,9 @@
</div>
</div>
</div>
<div *ngIf="!isTokenValid" class="col">
<span>{{'MERGE-ACCOUNT.MESSAGES.INVALID-TOKEN' | translate}}</span>
</div>
</div>
<ng-template #loading>
</ng-template>

View File

@ -16,6 +16,8 @@ import { takeUntil } from "rxjs/operators";
})
export class MergeEmailConfirmation extends BaseComponent implements OnInit {
isTokenValid: boolean = false;
private token: Guid;
get showForm(): boolean {
@ -37,9 +39,19 @@ export class MergeEmailConfirmation extends BaseComponent implements OnInit {
.subscribe(params => {
const token = params['token']
if (token != null) {
this.token = token;
this.userService.getUserTokenPermission(token)
.subscribe(result => {
this.isTokenValid = result
this.token = token;
});
}
},
error => {
this.isTokenValid = false;
this.token = Guid.createEmpty();
this.onCallbackError(error);
});
}
onConfirm(): void {

View File

@ -2222,7 +2222,8 @@
"MERGE-ACCOUNT": {
"TITLE": "Merge Your Account",
"MESSAGES": {
"CONFIRMATION": "Are you sure that you want to merge this account?"
"CONFIRMATION": "Are you sure that you want to merge this account?",
"INVALID-TOKEN": "Looks like your mail invitation has expired, or you are not logged in with the correct account. Please try logging in again or have the invitation re-sent."
},
"ACTIONS": {
"CONFIRM": "Confirm"