Commit 94041959 authored by David Burke's avatar David Burke

Stay logged in when changing password

parent 74d92482
Pipeline #39357878 passed with stage
in 6 minutes and 6 seconds
......@@ -32,6 +32,10 @@ import {
ForceSetPassword
} from "./reset-password/set-password/set-password.actions";
import * as fromManageBackupCode from "./manage-backup-code/manage-backup-code.reducer";
import {
ChangePasswordSubmitFormSuccess,
ChangePasswordActionTypes
} from "./change-password/change-password.actions";
export interface IAuthState {
email: string | null;
......@@ -68,6 +72,7 @@ export function authReducer(
| ResetPasswordVerifyActionsUnion
| SetPasswordSuccess
| ForceSetPassword
| ChangePasswordSubmitFormSuccess
): IAuthState {
switch (action.type) {
case AccountActionTypes.LOGIN:
......@@ -89,6 +94,14 @@ export function authReducer(
optInErrorReporting: action.payload.optInErrorReporting
};
case ChangePasswordActionTypes.SUBMIT_FORM_SUCCESS:
return {
...state,
userToken: action.payload.token,
privateKey: action.payload.privateKey,
publicKey: action.payload.publicKey
};
case AccountActionTypes.SET_URL:
return {
...state,
......
......@@ -7,28 +7,35 @@ export enum ChangePasswordActionTypes {
RESET_FORM = "[Change Password] Reset"
}
export class SubmitForm implements Action {
readonly type = ChangePasswordActionTypes.SUBMIT_FORM;
}
export class SubmitFormSuccess implements Action {
readonly type = ChangePasswordActionTypes.SUBMIT_FORM_SUCCESS;
export class ChangePasswordSubmitForm implements Action {
readonly type = ChangePasswordActionTypes.SUBMIT_FORM;
}
constructor(public payload: string) {}
}
export class ChangePasswordSubmitFormSuccess implements Action {
readonly type = ChangePasswordActionTypes.SUBMIT_FORM_SUCCESS;
constructor(
public payload: {
backupCode: string;
token: string;
privateKey: string;
publicKey: string;
}
) {}
}
export class SubmitFormFailure implements Action {
readonly type = ChangePasswordActionTypes.SUBMIT_FORM_FAILURE;
export class ChangePasswordSubmitFormFailure implements Action {
readonly type = ChangePasswordActionTypes.SUBMIT_FORM_FAILURE;
constructor(public payload: string[]) {}
}
constructor(public payload: string[]) {}
}
export class ResetForm implements Action {
readonly type = ChangePasswordActionTypes.RESET_FORM;
}
export class ResetForm implements Action {
readonly type = ChangePasswordActionTypes.RESET_FORM;
}
export type ChangePasswordActionsUnion =
| SubmitForm
| SubmitFormSuccess
| SubmitFormFailure
| ResetForm;
export type ChangePasswordActionsUnion =
| ChangePasswordSubmitForm
| ChangePasswordSubmitFormSuccess
| ChangePasswordSubmitFormFailure
| ResetForm;
import { Component } from "@angular/core";
import { Store, select } from "@ngrx/store";
import { selectChangePasswordNewBackupCode } from "../account.reducer";
import { SubmitForm, ResetForm } from "./change-password.actions";
import { ChangePasswordSubmitForm, ResetForm } from "./change-password.actions";
import * as fromRoot from "../../app.reducers";
import * as fromAccount from "../account.reducer";
import * as fromChangePassword from "./change-password.reducer";
......@@ -70,6 +70,6 @@ export class ChangePasswordContainer {
}
changePassword() {
this.store.dispatch(new SubmitForm());
this.store.dispatch(new ChangePasswordSubmitForm());
}
}
......@@ -5,36 +5,50 @@ import { Observable, of } from "rxjs";
import { withLatestFrom, map, catchError, exhaustMap } from "rxjs/operators";
import {
ChangePasswordActionTypes,
SubmitForm,
SubmitFormSuccess,
SubmitFormFailure
ChangePasswordSubmitForm,
ChangePasswordSubmitFormSuccess,
ChangePasswordSubmitFormFailure
} from "./change-password.actions";
import * as fromAccount from "../account.reducer";
import { UserService } from "../user";
import { NgPassitSDK } from "~/app/ngsdk/sdk";
@Injectable()
export class ChangePasswordEffects {
constructor(
private actions$: Actions,
private userService: UserService,
private sdk: NgPassitSDK,
private store: Store<any>
) {}
@Effect()
changePassword$: Observable<Action> = this.actions$.pipe(
ofType<SubmitForm>(ChangePasswordActionTypes.SUBMIT_FORM),
ofType<ChangePasswordSubmitForm>(ChangePasswordActionTypes.SUBMIT_FORM),
withLatestFrom(this.store.pipe(select(fromAccount.changePassword))),
map(([action, form]) => form.value),
exhaustMap(formValue =>
this.userService
.changePassword(formValue.oldPassword, formValue.newPassword)
.pipe(
map(resp => new SubmitFormSuccess(resp.backupCode)),
map(resp => {
this.sdk.set_keys(resp.publicKey, resp.privateKey);
return new ChangePasswordSubmitFormSuccess({
backupCode: resp.backupCode,
token: resp.token,
privateKey: resp.privateKey,
publicKey: resp.publicKey
});
}),
catchError(err => {
if (err.res.status === 400) {
return of(new SubmitFormFailure(["Incorrect password"]));
return of(
new ChangePasswordSubmitFormFailure(["Incorrect password"])
);
} else {
return of(new SubmitFormFailure(["Unexpected error."]));
return of(
new ChangePasswordSubmitFormFailure(["Unexpected error."])
);
}
})
)
......
......@@ -8,7 +8,10 @@ import {
} from "ngrx-forms";
import { oldPasswordValidators, passwordValidators } from "../constants";
import { equalTo, required } from "ngrx-forms/validation";
import { ChangePasswordActionTypes, ChangePasswordActionsUnion } from "./change-password.actions";
import {
ChangePasswordActionTypes,
ChangePasswordActionsUnion
} from "./change-password.actions";
import { IBaseFormState } from "~/app/utils/interfaces";
export const FORM_ID = "Change Password Form";
......@@ -61,7 +64,8 @@ export const validateAndUpdateFormState = updateGroup<IChangePasswordForm>({
}
});
export const newBackupCode = (state: IChangePasswordState) => state.newBackupCode;
export const newBackupCode = (state: IChangePasswordState) =>
state.newBackupCode;
const initialFormState = validateAndUpdateFormState(
createFormGroupState<IChangePasswordForm>(FORM_ID, {
......@@ -77,7 +81,7 @@ export const initialState = {
hasFinished: false,
hasStarted: false,
newBackupCode: null,
errorMessage: null,
errorMessage: null
};
const formReducer = createFormStateReducerWithUpdate<IChangePasswordForm>(
......@@ -105,7 +109,7 @@ export function reducer(
return {
...state,
hasFinished: true,
newBackupCode: action.payload,
newBackupCode: action.payload.backupCode,
errorMessage: null,
hasStarted: false
};
......@@ -127,7 +131,10 @@ export function reducer(
}
export const getForm = (state: IChangePasswordState) => state.form;
export const getErrorMessage = (state: IChangePasswordState) => state.errorMessage;
export const getErrorMessage = (state: IChangePasswordState) =>
state.errorMessage;
export const getHasStarted = (state: IChangePasswordState) => state.hasStarted;
export const getHasFinished = (state: IChangePasswordState) => state.hasFinished;
export const getNewBackupCode = (state: IChangePasswordState) => state.newBackupCode;
export const getHasFinished = (state: IChangePasswordState) =>
state.hasFinished;
export const getNewBackupCode = (state: IChangePasswordState) =>
state.newBackupCode;
......@@ -649,7 +649,9 @@ export default class PassitSDK {
return {
backupCode,
token: response.token
token: response.token,
privateKey: newUserKeyPair.privateKey.string,
publicKey: newUserKeyPair.publicKey.string
};
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment