From 44c6117ce1c8187f682f0426165b6430635a1c50 Mon Sep 17 00:00:00 2001 From: Alexander Wong Date: Sun, 3 Sep 2017 12:01:16 -0600 Subject: [PATCH] Complete change password functionality --- src/actions/auth/reducer.actions.js | 26 +++++- src/actions/auth/saga.actions.js | 10 ++- src/api/auth.api.js | 14 +++ src/api/baseApi.js | 2 +- src/components/Auth/Settings.jsx | 129 ++++++++++++++++++++++++++-- src/constants/auth.constants.js | 2 + src/reducers/authReducer.js | 11 ++- src/sagas/auth.sagas.js | 32 ++++++- src/sagas/index.js | 7 +- 9 files changed, 219 insertions(+), 14 deletions(-) diff --git a/src/actions/auth/reducer.actions.js b/src/actions/auth/reducer.actions.js index 41a4f49..a9ac78b 100644 --- a/src/actions/auth/reducer.actions.js +++ b/src/actions/auth/reducer.actions.js @@ -12,7 +12,8 @@ import { SET_FORM_EMAIL, SET_FORM_PASSWORD, SET_FORM_PASSWORD_CONFIRMATION, - SET_FORM_EMAIL_VERIFICATION + SET_FORM_EMAIL_VERIFICATION, + SET_FORM_OLD_PASSWORD } from "../../constants/auth.constants"; import { parseError } from "../common.actions"; @@ -41,6 +42,22 @@ export function setAuthRequestError(exception) { error["Non Field Errors"] = error.non_field_errors; delete error["non_field_errors"]; } + if (error.detail) { + error["Detail"] = error.detail; + delete error["detail"]; + } + if (error.old_password) { + error["Old Password"] = error.old_password; + delete error["old_password"]; + } + if (error.new_password1) { + error["New Password"] = error.new_password1; + delete error["new_password1"]; + } + if (error.new_password2) { + error["Confirm New Password"] = error.new_password2; + delete error["new_password2"]; + } return { type: SET_AUTH_REQUEST_ERROR, @@ -137,3 +154,10 @@ export function setFormEmailVerification(emailKey) { data: emailKey }; } + +export function setFormOldPassword(oldPassword) { + return { + type: SET_FORM_OLD_PASSWORD, + data: oldPassword + }; +} diff --git a/src/actions/auth/saga.actions.js b/src/actions/auth/saga.actions.js index b33eb3e..16a5032 100644 --- a/src/actions/auth/saga.actions.js +++ b/src/actions/auth/saga.actions.js @@ -2,7 +2,8 @@ import { SEND_REGISTER_REQUEST, SEND_EMAIL_VERIFICATION_REQUEST, SEND_LOGIN_REQUEST, - SEND_LOGOUT_REQUEST + SEND_LOGOUT_REQUEST, + SEND_CHANGE_PASSWORD_REQUEST } from "../../constants/auth.constants"; export function sendRegisterRequest(postBody) { @@ -31,3 +32,10 @@ export function sendLogoutRequest() { type: SEND_LOGOUT_REQUEST } } + +export function sendChangePasswordRequest(postBody) { + return { + type: SEND_CHANGE_PASSWORD_REQUEST, + data: postBody + } +} diff --git a/src/api/auth.api.js b/src/api/auth.api.js index 0b9e349..9ff8c3d 100644 --- a/src/api/auth.api.js +++ b/src/api/auth.api.js @@ -41,3 +41,17 @@ export function loginUser(email, password) { export function logoutUser() { return post("/rest-auth/logout/").then(resp => Promise.resolve(resp)); } + +/** + * Function wrapping POST request for change password + * @param {string} new_password1 - user new password + * @param {string} new_password2 - user new password confirmation + * @param {string} old_password - old password of user + */ +export function changePassword(new_password1, new_password2, old_password) { + return post("/rest-auth/password/change/", { + new_password1, + new_password2, + old_password + }).then(resp => Promise.resolve(resp)); +} diff --git a/src/api/baseApi.js b/src/api/baseApi.js index a614810..4912329 100644 --- a/src/api/baseApi.js +++ b/src/api/baseApi.js @@ -14,7 +14,7 @@ function headers() { return { Accept: "application/json", "Content-Type": "application/json", - Authorization: `Token: ${token}` + Authorization: `Token ${token}` }; } diff --git a/src/components/Auth/Settings.jsx b/src/components/Auth/Settings.jsx index c347055..6d5279b 100644 --- a/src/components/Auth/Settings.jsx +++ b/src/components/Auth/Settings.jsx @@ -1,10 +1,76 @@ import React, { Component } from "react"; import { connect } from "react-redux"; -import { Container } from "semantic-ui-react"; +import { Container, Form, Header, Message, Segment } from "semantic-ui-react"; + +import { + clearAuthRequestError, + clearAuthRequestSuccess, + setFormPassword, + setFormPasswordConfirmation, + setFormOldPassword +} from "../../actions/auth/reducer.actions"; +import { sendChangePasswordRequest } from "../../actions/auth/saga.actions"; +import Error from "../Shared/Error"; class Settings extends Component { + constructor(props) { + super(props); + this.props.dispatch(clearAuthRequestError()); + this.props.dispatch(clearAuthRequestSuccess()); + } + + changePassword = event => { + this.props.dispatch(setFormPassword(event.target.value)); + }; + + changePasswordConfirmation = event => { + this.props.dispatch(setFormPasswordConfirmation(event.target.value)); + }; + + changeOldPassword = event => { + this.props.dispatch(setFormOldPassword(event.target.value)); + }; + + onSubmitChangePassword = event => { + event.preventDefault(); + const { + dispatch, + password, + passwordConfirmation, + oldPassword + } = this.props; + dispatch( + sendChangePasswordRequest({ + new_password1: password, + new_password2: passwordConfirmation, + old_password: oldPassword + }) + ); + }; + render() { - return ; + const { + isSendingAuthRequest, + authRequestError, + authRequestSuccess, + password, + passwordConfirmation, + oldPassword + } = this.props; + return ( + + ); } } @@ -12,10 +78,63 @@ function mapStateToProps(state) { return { ...state.auth }; } -const SettingsView = () => ( +const SettingsView = ({ + isSendingAuthRequest, + authRequestError, + authRequestSuccess, + password, + passwordConfirmation, + oldPassword, + changePassword, + changePasswordConfirmation, + changeOldPassword, + onSubmitChangePassword +}) => ( -

Settings

-

todo, change password

+
Settings
+
Change Password
+ +
+ + + + + + + + + + + + + + + Password Successfully Changed! +

New password has been set.

+
+ Change Password + +
); diff --git a/src/constants/auth.constants.js b/src/constants/auth.constants.js index 1861b04..a89c0bd 100644 --- a/src/constants/auth.constants.js +++ b/src/constants/auth.constants.js @@ -14,6 +14,7 @@ export const SET_FORM_EMAIL = "SET_FORM_EMAIL"; export const SET_FORM_PASSWORD = "SET_FORM_PASSWORD"; export const SET_FORM_PASSWORD_CONFIRMATION = "SET_FORM_PASSWORD_CONFIRMATION"; export const SET_FORM_EMAIL_VERIFICATION = "SET_FORM_EMAIL_VERIFICATION"; +export const SET_FORM_OLD_PASSWORD = "SET_FORM_OLD_PASSWORD"; // Saga Auth Action Constants export const SEND_REGISTER_REQUEST = "SEND_REGISTER_REQUEST"; @@ -21,3 +22,4 @@ export const SEND_EMAIL_VERIFICATION_REQUEST = "SEND_EMAIL_VERIFICATION_REQUEST"; export const SEND_LOGIN_REQUEST = "SEND_LOGIN_REQUEST"; export const SEND_LOGOUT_REQUEST = "SEND_LOGOUT_REQUEST"; +export const SEND_CHANGE_PASSWORD_REQUEST = "SEND_CHANGE_PASSWORD_REQUEST"; diff --git a/src/reducers/authReducer.js b/src/reducers/authReducer.js index 9772bed..69d5bd9 100644 --- a/src/reducers/authReducer.js +++ b/src/reducers/authReducer.js @@ -12,7 +12,8 @@ import { SET_FORM_EMAIL, SET_FORM_PASSWORD, SET_FORM_PASSWORD_CONFIRMATION, - SET_FORM_EMAIL_VERIFICATION + SET_FORM_EMAIL_VERIFICATION, + SET_FORM_OLD_PASSWORD } from "../constants/auth.constants"; /** @@ -37,7 +38,8 @@ const initialState = { email: "", password: "", passwordConfirmation: "", - emailVerificationString: "" + emailVerificationString: "", + oldPassword: "" // used for change password functionality }; function authReducer(state = initialState, action) { @@ -112,6 +114,11 @@ function authReducer(state = initialState, action) { ...state, emailVerificationString: action.data }; + case SET_FORM_OLD_PASSWORD: + return { + ...state, + oldPassword: action.data + } default: return state; } diff --git a/src/sagas/auth.sagas.js b/src/sagas/auth.sagas.js index 04ac07c..ff0f4d7 100644 --- a/src/sagas/auth.sagas.js +++ b/src/sagas/auth.sagas.js @@ -9,17 +9,19 @@ import { clearEmailVerificationError, clearAuthRequestSuccess, clearEmailVerificationSuccess, + setSelfUserToken, setFormEmail, setFormPassword, setFormPasswordConfirmation, setFormEmailVerification, - setSelfUserToken + setFormOldPassword, } from "../actions/auth/reducer.actions"; import { registerUser, verifyEmail, loginUser, - logoutUser + logoutUser, + changePassword } from "../api/auth.api"; function* registerUserCall(postBody) { @@ -65,6 +67,19 @@ function* logoutUserCall() { yield effects.call(logoutUser); } +function* changePasswordCall(postBody) { + yield effects.put(isSendingAuthRequest(true)); + const { new_password1, new_password2, old_password } = postBody; + try { + return yield effects.call(changePassword, new_password1, new_password2, old_password); + } catch (exception) { + yield effects.put(setAuthRequestError(exception)); + return false; + } finally { + yield effects.put(isSendingAuthRequest(false)); + } +} + export function* registerUserFlow(request) { yield effects.put(clearAuthRequestSuccess()); yield effects.put(clearAuthRequestError()); @@ -109,3 +124,16 @@ export function* logoutUserFlow(request) { yield effects.call(logoutUserCall); yield effects.put(setSelfUserToken("")); } + +export function* changePasswordFlow(request) { + yield effects.put(clearAuthRequestSuccess()); + yield effects.put(clearAuthRequestError()); + const wasSuccessful = yield effects.call(changePasswordCall, request.data); + if (wasSuccessful) { + yield effects.put(setAuthRequestSuccess(wasSuccessful)); + yield effects.put(clearAuthRequestError()); + yield effects.put(setFormOldPassword("")); + yield effects.put(setFormPassword("")); + yield effects.put(setFormPasswordConfirmation("")); + } +} diff --git a/src/sagas/index.js b/src/sagas/index.js index 82c31b0..7367245 100644 --- a/src/sagas/index.js +++ b/src/sagas/index.js @@ -3,13 +3,15 @@ import { SEND_REGISTER_REQUEST, SEND_EMAIL_VERIFICATION_REQUEST, SEND_LOGIN_REQUEST, - SEND_LOGOUT_REQUEST + SEND_LOGOUT_REQUEST, + SEND_CHANGE_PASSWORD_REQUEST } from "../constants/auth.constants"; import { registerUserFlow, verifyEmailFlow, loginUserFlow, - logoutUserFlow + logoutUserFlow, + changePasswordFlow } from "./auth.sagas"; export default function* rootSaga() { @@ -17,4 +19,5 @@ export default function* rootSaga() { yield takeLatest(SEND_EMAIL_VERIFICATION_REQUEST, verifyEmailFlow); yield takeLatest(SEND_LOGIN_REQUEST, loginUserFlow); yield takeLatest(SEND_LOGOUT_REQUEST, logoutUserFlow); + yield takeLatest(SEND_CHANGE_PASSWORD_REQUEST, changePasswordFlow); }