From 68491d6f34fef6cd0eeae38e2d7c18d07b8455c3 Mon Sep 17 00:00:00 2001
From: Larbi Gharib <larbi.gharib@savoirfairelinux.com>
Date: Thu, 27 Aug 2020 17:25:25 -0400
Subject: [PATCH] Password change

Change-Id: I4269f85309799454df2c319a9db2b35f5db08982
---
 jams-react-client/src/auth.js                 |  78 ++++++----
 .../src/components/FormikField/FormikField.js |   3 +
 .../src/components/Navbars/Navbar.js          |   2 +-
 .../src/components/Snackbar/Snackbar.js       |   2 +-
 .../components/Snackbar/SnackbarContent.js    |   2 +-
 jams-react-client/src/globalUrls.js           |   2 +
 jams-react-client/src/layouts/SignIn.js       |   2 +-
 jams-react-client/src/layouts/SignUp.js       |   2 +-
 .../src/views/Blueprints/Blueprints.js        |   4 +-
 .../src/views/Contacts/Contacts.js            |   2 +-
 .../src/views/Dashboard/Dashboard.js          |   6 +-
 jams-react-client/src/views/Groups/Groups.js  |  13 +-
 .../src/views/Notifications/Notifications.js  |   4 +-
 .../src/views/RTLPage/RTLPage.js              |   6 +-
 .../src/views/UpgradeToPro/UpgradeToPro.js    |   2 +-
 .../views/UserProfile/DisplayUserProfile.js   | 147 +++++++++++++++++-
 .../UserProfile/EditCreateUserProfile.js      |   9 +-
 17 files changed, 223 insertions(+), 63 deletions(-)

diff --git a/jams-react-client/src/auth.js b/jams-react-client/src/auth.js
index 72b476a2..ffaf9639 100644
--- a/jams-react-client/src/auth.js
+++ b/jams-react-client/src/auth.js
@@ -11,12 +11,11 @@ import {
 
 class Auth {
     constructor() {
-        this.authenticated = false
-        this.admin = false
-        this.installed = false
-        this.uri = ''
-        this.adminScope = true
-        this.username = ''
+        this.authenticated = false;
+        this.admin = false;
+        this.installed = false;
+        this.uri = '';
+        this.username = '';
     }
 
     setJWT(access_token) {
@@ -24,19 +23,37 @@ class Auth {
         window.localStorage.setItem('access_token', access_token);
     }
 
+    setScope(scope) {
+        window.localStorage.removeItem('scope');
+        window.localStorage.setItem('scope', scope);
+    }
+
+    setLocalDirectory(localDirectory) {
+        window.localStorage.removeItem('localDirectory');
+        window.localStorage.setItem('localDirectory', localDirectory);
+    }
+
     deleteJWT(){
         window.localStorage.removeItem('access_token');
     }
 
+    setUsername(username) {
+        window.localStorage.removeItem('username');
+        window.localStorage.setItem('username', username);        
+    }
+
+    deleteUserhame() {
+        window.localStorage.removeItem('username');
+    }
+
     login(jsonData, cb) {
         this.deleteJWT()
         axios(configApiCall(api_path_post_auth_login, "POST", jsonData, null)).then((response) => {
             if(response.status == 200){
-                this.setJWT(response.data['access_token'])
-                this.adminScope = JSON.parse(atob(response.data['access_token'].split('.')[1])).scope == "ADMIN" ? true : false;
-                if(!this.adminScope)
-                    this.username= jsonData.username
-                this.authenticated = true
+                this.setJWT(response.data['access_token']);
+                this.setScope(response.data["scope"] == "ADMIN" ? true : false);
+                this.setUsername(jsonData.username);
+                this.authenticated = true;
             }
             cb()
         }).catch((error) => {
@@ -47,8 +64,7 @@ class Auth {
     logout(cb) {
         this.deleteJWT()
         this.authenticated = false
-        this.username=''
-        this.adminScope = true
+        this.deleteUserhame()
         cb()
     }
 
@@ -57,22 +73,22 @@ class Auth {
     }
 
     isLocalDirectory() {
-        return this.localDirectory
+        return window.localStorage.getItem('localDirectory') === 'true' ? true : false;
     }
 
     checkDirectoryType(cb){
         axios(configApiCall(api_path_get_directories, "GET", null, null)).then((response) => {
             if (response.data.length == 1) {
-                this.localDirectory = true
+                this.setLocalDirectory(true);
             }
             else if (response.data.length == 2){
-                this.localDirectory = false
+                this.setLocalDirectory(false);
             }else{
-                console.log("Error getting on checkDirectoryType: Size of directory types is " + response.data.length)    
+                console.log("Error getting on checkDirectoryType: Size of directory types is " + response.data.length);
             }
             cb()
         }).catch((error) => {
-            console.log("Error getting on checkDirectoryType: " + error)
+            console.log("Error getting on checkDirectoryType: " + error);
             cb()
         });
     }
@@ -80,15 +96,15 @@ class Auth {
     checkAdminAccountStatus(cb) {
         axios(configApiCall(api_path_post_install_admin, "GET", null, null)).then((response) => {
             if (response['headers']['showlogin'] == "true") {
-                this.admin = true
+                this.admin = true;
             }
             cb()
         }).catch((error) => {
             if(error.response.status == 404){
-                this.admin = true
+                this.admin = true;
             }
             else{
-                console.log("Error during API request on checkAdminAccountStatus: " + error)
+                console.log("Error during API request on checkAdminAccountStatus: " + error);
             }
             cb()
         });
@@ -97,11 +113,11 @@ class Auth {
     isServerInstalled(cb) {
         axios(configApiCall(api_path_get_server_status, "GET", null, null)).then((response) => {                       
             if (response.data['installed'] == 'true') {
-                this.installed = true
-                console.log("Server is insalled")
+                this.installed = true;
+                console.log("Server is insalled");
             } else {
-                this.installed = false
-                console.log("Server is not insalled")
+                this.installed = false;
+                console.log("Server is not insalled");
             }
             cb()
         }).catch((error) => {
@@ -116,8 +132,8 @@ class Auth {
             cb()
         }else{
             axios(configApiCall(api_path_get_install_lastKnownStep, 'GET', null, null)).then((response) => {
-                this.uri = response.data['uri']
-                this.authenticated = true
+                this.uri = response.data['uri'];
+                this.authenticated = true;
                 cb()
             }).catch((error) => {
                 console.log("Error during API request on checkLastKnowStep: " + error);
@@ -127,19 +143,19 @@ class Auth {
     }
 
     hasAdmin() {
-        return this.admin
+        return this.admin;
     }
 
     hasAdminScope(){
-        return this.adminScope
+        return window.localStorage.getItem('scope') === 'true' ? true : false;
     }
 
     getUsername(){
-        return this.username
+        return window.localStorage.getItem('username');
     }
 
     isInstalled() {
-        return this.installed
+        return this.installed;
     }
 }
 
diff --git a/jams-react-client/src/components/FormikField/FormikField.js b/jams-react-client/src/components/FormikField/FormikField.js
index a1762a67..3dc5394c 100644
--- a/jams-react-client/src/components/FormikField/FormikField.js
+++ b/jams-react-client/src/components/FormikField/FormikField.js
@@ -18,6 +18,7 @@ class FormikField extends React.Component {
                         name={this.props.name}
                         as={Input}
                         startAdornment={this.props.startAdornment}
+                        endAdornment={this.props.endAdornment}
                         label={this.props.label} 
                         fullWidth
                         type={this.props.type}
@@ -29,6 +30,8 @@ class FormikField extends React.Component {
 }
 
 FormikField.propTypes = {
+    startAdornment: false,
+    endAdornment: false,
     placeholder: PropTypes.string,
     required: false,
     name: PropTypes.string.isRequired,
diff --git a/jams-react-client/src/components/Navbars/Navbar.js b/jams-react-client/src/components/Navbars/Navbar.js
index 5636b793..2b6a4356 100755
--- a/jams-react-client/src/components/Navbars/Navbar.js
+++ b/jams-react-client/src/components/Navbars/Navbar.js
@@ -48,7 +48,7 @@ export default function Header(props) {
         </Hidden> */}
         <Hidden mdUp implementation="css">
           <IconButton
-            color="inherit"
+            color="info"
             aria-label="open drawer"
             onClick={props.handleDrawerToggle}
           >
diff --git a/jams-react-client/src/components/Snackbar/Snackbar.js b/jams-react-client/src/components/Snackbar/Snackbar.js
index 14527a79..4b4e6ebf 100644
--- a/jams-react-client/src/components/Snackbar/Snackbar.js
+++ b/jams-react-client/src/components/Snackbar/Snackbar.js
@@ -25,7 +25,7 @@ export default function Snackbar(props) {
         className={classes.iconButton}
         key="close"
         aria-label="Close"
-        color="inherit"
+        color="info"
         onClick={() => props.closeNotification()}
       >
         <Close className={classes.close} />
diff --git a/jams-react-client/src/components/Snackbar/SnackbarContent.js b/jams-react-client/src/components/Snackbar/SnackbarContent.js
index 120178b6..f0002739 100644
--- a/jams-react-client/src/components/Snackbar/SnackbarContent.js
+++ b/jams-react-client/src/components/Snackbar/SnackbarContent.js
@@ -25,7 +25,7 @@ export default function SnackbarContent(props) {
         className={classes.iconButton}
         key="close"
         aria-label="Close"
-        color="inherit"
+        color="info"
       >
         <Close className={classes.close} />
       </IconButton>
diff --git a/jams-react-client/src/globalUrls.js b/jams-react-client/src/globalUrls.js
index e3caeb49..ec31b557 100644
--- a/jams-react-client/src/globalUrls.js
+++ b/jams-react-client/src/globalUrls.js
@@ -31,6 +31,7 @@ const api_path_get_needs_update = '/api/admin/update';
 const api_path_get_start_update = '/api/admin/update';
 const api_path_post_create_group = '/api/admin/group';
 const api_path_post_create_user = '/api/admin/user';
+const api_path_put_update_user = '/api/admin/user';
 const api_path_get_auth_user = '/api/auth/user';
 const api_path_get_admin_user = '/api/admin/user';
 const api_path_post_update_user = '/api/auth/user';
@@ -75,6 +76,7 @@ module.exports = {
     api_path_get_needs_update,
     api_path_get_start_update,
     api_path_post_create_user,
+    api_path_put_update_user,
     api_path_get_auth_user,
     api_path_get_admin_user,
     api_path_post_update_user,
diff --git a/jams-react-client/src/layouts/SignIn.js b/jams-react-client/src/layouts/SignIn.js
index d2b00a44..d9d9447a 100644
--- a/jams-react-client/src/layouts/SignIn.js
+++ b/jams-react-client/src/layouts/SignIn.js
@@ -25,7 +25,7 @@ function Copyright() {
     return (
         <Typography variant="body2" color="textSecondary" align="center">
             {'Copyright © '}
-            <Link color="inherit" href="https://material-ui.com/">
+            <Link color="info" href="https://material-ui.com/">
                 Your Website
             </Link>{' '}
             {new Date().getFullYear()}
diff --git a/jams-react-client/src/layouts/SignUp.js b/jams-react-client/src/layouts/SignUp.js
index fae10c16..c311d4bd 100644
--- a/jams-react-client/src/layouts/SignUp.js
+++ b/jams-react-client/src/layouts/SignUp.js
@@ -25,7 +25,7 @@ function Copyright() {
     return (
         <Typography variant="body2" color="textSecondary" align="center">
             {'Copyright © '}
-            <Link color="inherit" href="https://savoirfairelinux.com/">
+            <Link color="info" href="https://savoirfairelinux.com/">
                 JAMS by Savoir-faire Linux
             </Link>{' '}
             {new Date().getFullYear()}
diff --git a/jams-react-client/src/views/Blueprints/Blueprints.js b/jams-react-client/src/views/Blueprints/Blueprints.js
index b963eaca..13e72936 100644
--- a/jams-react-client/src/views/Blueprints/Blueprints.js
+++ b/jams-react-client/src/views/Blueprints/Blueprints.js
@@ -220,7 +220,7 @@ export default function Blueprints() {
                         </DialogContentText>
                         </DialogContent>
                         <DialogActions>
-                        <Button onClick={handleClose} color="danger">
+                        <Button onClick={handleClose} color="info">
                             Cancel
                         </Button>
                         <Button onClick={handleCreateBlueprint} color="primary" autoFocus>
@@ -244,7 +244,7 @@ export default function Blueprints() {
                         <Button onClick={() => setOpenRemoveDialog(false)} color="primary">
                             Cancel
                         </Button>
-                        <Button onClick={removeBlueprint} color="danger" autoFocus>
+                        <Button onClick={removeBlueprint} color="info" autoFocus>
                             Remove
                         </Button>
                         </DialogActions>
diff --git a/jams-react-client/src/views/Contacts/Contacts.js b/jams-react-client/src/views/Contacts/Contacts.js
index 80075e5f..500e1b50 100644
--- a/jams-react-client/src/views/Contacts/Contacts.js
+++ b/jams-react-client/src/views/Contacts/Contacts.js
@@ -182,7 +182,7 @@ export default function Users(props) {
                     <Button onClick={() => setOpen(false)} color="primary">
                         Cancel
                     </Button>
-                    <Button onClick={removeContact} color="danger" autoFocus>
+                    <Button onClick={removeContact} color="info" autoFocus>
                         Remove
                     </Button>
                     </DialogActions>
diff --git a/jams-react-client/src/views/Dashboard/Dashboard.js b/jams-react-client/src/views/Dashboard/Dashboard.js
index a737dfe7..0678d244 100755
--- a/jams-react-client/src/views/Dashboard/Dashboard.js
+++ b/jams-react-client/src/views/Dashboard/Dashboard.js
@@ -88,8 +88,8 @@ export default function Dashboard() {
         </GridItem>
         <GridItem xs={12} sm={6} md={3}>
           <Card>
-            <CardHeader color="danger" stats icon>
-              <CardIcon color="danger">
+            <CardHeader color="info" stats icon>
+              <CardIcon color="info">
                 <Icon>info_outline</Icon>
               </CardIcon>
               <p className={classes.cardCategory}>Fixed Issues</p>
@@ -174,7 +174,7 @@ export default function Dashboard() {
         </GridItem>
         <GridItem xs={12} sm={12} md={4}>
           <Card chart>
-            <CardHeader color="danger">
+            <CardHeader color="info">
               <ChartistGraph
                 className="ct-chart"
                 data={completedTasksChart.data}
diff --git a/jams-react-client/src/views/Groups/Groups.js b/jams-react-client/src/views/Groups/Groups.js
index 84df70fb..9399fa7c 100644
--- a/jams-react-client/src/views/Groups/Groups.js
+++ b/jams-react-client/src/views/Groups/Groups.js
@@ -222,7 +222,14 @@ export default function Groups() {
         setSelectedBlueprint(getBlueprintsOptions()[e.target.value])
     }
 
-    if(selectedGroup && auth.hasAdminScope()){
+    if (!auth.hasAdminScope()) {
+        return (
+            <div>
+                <h4>You are not allowed to access this section. Please contact your administrator to get administrator privileges.</h4>
+            </div>
+        )
+    }
+    else if(selectedGroup && auth.hasAdminScope()){
         return(
             <div>
                 <EditGroup
@@ -282,7 +289,7 @@ export default function Groups() {
                         </DialogContentText>
                     </DialogContent>
                     <DialogActions>
-                        <Button onClick={handleCloseCreate} color="danger">
+                        <Button onClick={handleCloseCreate} color="info">
                             Cancel
                         </Button>
                         <Button onClick={handleCreateGroup} color="primary" autoFocus>
@@ -306,7 +313,7 @@ export default function Groups() {
                         <Button onClick={() => setOpenRemoveDialog(false)} color="primary">
                             Cancel
                         </Button>
-                        <Button onClick={removeGroup} color="danger" autoFocus>
+                        <Button onClick={removeGroup} color="info" autoFocus>
                             Remove
                         </Button>
                     </DialogActions>
diff --git a/jams-react-client/src/views/Notifications/Notifications.js b/jams-react-client/src/views/Notifications/Notifications.js
index 7674258c..b10db293 100755
--- a/jams-react-client/src/views/Notifications/Notifications.js
+++ b/jams-react-client/src/views/Notifications/Notifications.js
@@ -195,10 +195,10 @@ export default function Notifications() {
             />
             <SnackbarContent
               message={
-                'DANGER - This is a regular notification made with color="danger"'
+                'DANGER - This is a regular notification made with color="info"'
               }
               close
-              color="danger"
+              color="info"
             />
             <SnackbarContent
               message={
diff --git a/jams-react-client/src/views/RTLPage/RTLPage.js b/jams-react-client/src/views/RTLPage/RTLPage.js
index 47934d68..eca4168e 100644
--- a/jams-react-client/src/views/RTLPage/RTLPage.js
+++ b/jams-react-client/src/views/RTLPage/RTLPage.js
@@ -108,8 +108,8 @@ export default function RTLPage() {
         </GridItem>
         <GridItem xs={12} sm={6} md={3}>
           <Card>
-            <CardHeader color="danger" stats icon>
-              <CardIcon color="danger">
+            <CardHeader color="info" stats icon>
+              <CardIcon color="info">
                 <Icon>info_outline</Icon>
               </CardIcon>
               <p className={classes.cardCategory}>مشکلات حل شده</p>
@@ -194,7 +194,7 @@ export default function RTLPage() {
         </GridItem>
         <GridItem xs={12} sm={12} md={4}>
           <Card chart>
-            <CardHeader color="danger">
+            <CardHeader color="info">
               <ChartistGraph
                 className="ct-chart"
                 data={completedTasksChart.data}
diff --git a/jams-react-client/src/views/UpgradeToPro/UpgradeToPro.js b/jams-react-client/src/views/UpgradeToPro/UpgradeToPro.js
index ffee3263..fd6d2af0 100644
--- a/jams-react-client/src/views/UpgradeToPro/UpgradeToPro.js
+++ b/jams-react-client/src/views/UpgradeToPro/UpgradeToPro.js
@@ -194,7 +194,7 @@ export default function UpgradeToPro() {
                     <td className={classes.center}>
                       <Button
                         round
-                        color="danger"
+                        color="info"
                         href="https://www.creative-tim.com/product/material-dashboard-pro-react?ref=mdr-upgrade-live"
                       >
                         Upgrade to Pro
diff --git a/jams-react-client/src/views/UserProfile/DisplayUserProfile.js b/jams-react-client/src/views/UserProfile/DisplayUserProfile.js
index 5251d5f9..dd850c4b 100644
--- a/jams-react-client/src/views/UserProfile/DisplayUserProfile.js
+++ b/jams-react-client/src/views/UserProfile/DisplayUserProfile.js
@@ -40,7 +40,11 @@ import ListItemText from '@material-ui/core/ListItemText';
 
 import auth from "auth.js"
 import configApiCall from "api.js";
-import { api_path_get_admin_user, api_path_get_auth_user, api_path_get_user_directory_search, api_path_delete_admin_user_revoke} from "globalUrls";
+import { api_path_get_admin_user, 
+    api_path_get_auth_user, 
+    api_path_get_user_directory_search, 
+    api_path_delete_admin_user_revoke, 
+    api_path_put_update_user} from "globalUrls";
 
 import dashboardStyle from "assets/jss/material-dashboard-react/views/dashboardStyle.js";
 
@@ -48,6 +52,17 @@ import { hexToRgb, blackColor } from "assets/jss/material-dashboard-react.js";
 import axios from "axios";
 import PersonIcon from "../../../node_modules/@material-ui/icons/Person";
 
+import Input from '@material-ui/core/Input';
+import InputAdornment from '@material-ui/core/InputAdornment';
+import Visibility from '@material-ui/icons/Visibility';
+import VisibilityOff from '@material-ui/icons/VisibilityOff';
+
+import VpnKeyIcon from '@material-ui/icons/VpnKey';
+import IconButton from '@material-ui/core/IconButton';
+
+import {Formik} from 'formik';
+import FormikField from 'components/FormikField/FormikField';
+import * as Yup from 'yup';
 
 const styles = (theme)=> ( {
     ...dashboardStyle,
@@ -111,9 +126,7 @@ const styles = (theme)=> ( {
     //     [theme.breakpoints.up('sm')]: {
     //       flexDirection: 'row',
     //       alignItems: 'center',
-    //     },
-    // },
-    // sliderContainer: {
+    //     },passwordSchematainer: {
     //     display: 'flex',
     //     flex: '1',
     //     alignItems: 'center',
@@ -143,6 +156,11 @@ export default function DisplayUserProfile(props) {
     const [userStatus, setUserStatus] = React.useState(false)
     const [open, setOpen] = React.useState(false);
     const [revokedUser, setRevokedUser] = React.useState("");
+    const [changePasswordOpen, setChangePasswordOpen] = React.useState(false)
+    const [currentPassword, setCurrentPassword] = React.useState("");
+    const [visibilityValues, setVisibilityValues] = React.useState({
+        showPassword: false
+    });
 
     const  searchData = {
         "queryString":props.username
@@ -158,13 +176,14 @@ export default function DisplayUserProfile(props) {
                 axios(configApiCall(api_path_get_admin_user, 'GET', userData, null)).then((response)=>{
                         const result = JSON.parse(response.data.replace(/\s+/g, ' ').trim());
                         setUserStatus(result.revoked)
+                        setCurrentPassword(result.password)
                     }
                 ).catch((error) =>{
                     console.log(error);
                 });
             }
             else{
-                axios(configApiCall(api_path_get_auth_user, 'GET', null, null)).then((response)=>{
+                axios(configApiCall(api_path_get_auth_user, 'GET', userData, null)).then((response)=>{
                     const result = JSON.parse(response.data.replace(/\s+/g, ' ').trim());
                     setUserStatus(result.revoked)
                     }
@@ -212,6 +231,34 @@ export default function DisplayUserProfile(props) {
         setOpen(false);
     };
 
+    const handleClosechangePassword = () => {
+        setChangePasswordOpen(false);
+    }
+
+    const changePassword = (values) => {
+        axios(configApiCall(api_path_put_update_user+'?username='+props.username+'&password='+values.password, 'PUT', null, null)).then(()=>{
+            setChangePasswordOpen(false);
+            setCurrentPassword(values.password);
+        }).catch((error)=> {
+            console.log("Updating user " + props.username + ' password failed with error: ' + error);
+        });
+        setChangePasswordOpen(false);
+    }
+
+    const passwordSchema = Yup.object().shape({
+        password: Yup.string().required('Password is required'),
+        passwordConfirmation: Yup.string()
+           .oneOf([Yup.ref('password'), null], 'Passwords must match')
+    });
+
+    const handleClickShowPassword = () => {
+        setVisibilityValues({ ...visibilityValues, showPassword: !visibilityValues.showPassword });
+    };
+
+    const handleMouseDownPassword = (event) => {
+        event.preventDefault();
+    };
+
     return (
         <div>
         <Dialog
@@ -230,11 +277,66 @@ export default function DisplayUserProfile(props) {
             <Button onClick={handleClose} color="primary">
                 Cancel
             </Button>
-            <Button onClick={revokeUser} color="danger" autoFocus>
+            <Button onClick={revokeUser} color="info" autoFocus>
                 Revoke
             </Button>
             </DialogActions>
         </Dialog>
+        <Dialog
+            open={changePasswordOpen}
+            onClose={handleClosechangePassword}
+            aria-labelledby="alert-dialog-title"
+            aria-describedby="alert-dialog-description"
+        >
+            <DialogTitle id="change-password-dialog">{"Change password"}</DialogTitle>
+            <Formik initialValues={{
+                    password: "",
+                    passwordConfirmation: ""
+                }}
+                validationSchema={passwordSchema}
+                onSubmit={changePassword}
+                >
+                    {({ isValid, dirty, handleSubmit}) => (
+                        <form onSubmit={handleSubmit}>
+            <DialogContent>
+            <DialogContentText id="change-password-description">
+                Password change for <strong>{props.username}</strong>
+            </DialogContentText>           
+                <FormikField 
+                    name="password" 
+                    label="Password" 
+                    placeholder="Password"
+                    type="password"
+                    startAdornment={
+                        <InputAdornment position="start">
+                            <VpnKeyIcon />
+                        </InputAdornment>
+                    }
+                />
+                <FormikField 
+                    name="passwordConfirmation" 
+                    label="Confirm password" 
+                    placeholder="Confirm password"
+                    type="password"
+                    startAdornment={
+                        <InputAdornment position="start">
+                            <VpnKeyIcon />
+                        </InputAdornment>
+                    }
+                />
+            </DialogContent>
+            <DialogActions>
+            <Button onClick={handleClosechangePassword} color="primary">
+                Cancel
+            </Button>
+            <Button type="submit" disable={!isValid && !dirty} color="info" autoFocus>
+                Update password
+            </Button>
+            </DialogActions>
+                </form>
+               )}
+            </Formik>
+        </Dialog>
         {users.map(user =>
             <GridContainer>
                 <Grid item xs={12} sm={12} md={8}>
@@ -341,6 +443,34 @@ export default function DisplayUserProfile(props) {
                                                         primary={user.faxNumber ? user.faxNumber : 'no fax number'}
                                                     />
                                                 </ListItem>
+                                                {auth.isLocalDirectory() && auth.hasAdminScope() && <ListItem>
+                                                    <ListItemAvatar>
+                                                        <Avatar>
+                                                        <VpnKeyIcon/>
+                                                        </Avatar>
+                                                    </ListItemAvatar>
+                                                    <ListItemText
+                                                        children={
+                                                            <Input
+                                                                disabled
+                                                                id="current-password"
+                                                                type={visibilityValues.showPassword ? 'text' : 'password'}
+                                                                value={currentPassword}
+                                                                endAdornment={
+                                                                <InputAdornment position="end">
+                                                                    <IconButton
+                                                                    aria-label="toggle password visibility"
+                                                                    onClick={handleClickShowPassword}
+                                                                    onMouseDown={handleMouseDownPassword}
+                                                                    >
+                                                                    {visibilityValues.showPassword ? <Visibility /> : <VisibilityOff />}
+                                                                    </IconButton>
+                                                                </InputAdornment>
+                                                                }
+                                                            />
+                                                        }
+                                                    />
+                                                </ListItem>}
                                         </List>
                                     </Grid>
                                 </Grid>
@@ -350,8 +480,11 @@ export default function DisplayUserProfile(props) {
                             {auth.isLocalDirectory() && <Button color="info" onClick={() => props.setDisplayUser(false)}>
                                 <EditIcon /> Edit Profile
                             </Button>}
+                            {auth.isLocalDirectory() && auth.hasAdminScope() && <Button color="info" onClick={() => {setChangePasswordOpen(true);}}>
+                                <VpnKeyIcon /> Change password
+                            </Button>}
                             {auth.hasAdminScope() && (userStatus === "Active" || userStatus === '') &&
-                            <Button color="danger" onClick={() => handleClickOpen(user.username)} >
+                            <Button color="info" onClick={() => handleClickOpen(user.username)} >
                                 <DeleteIcon fontSize="small"/> Revoke user
                             </Button>}
                         </CardFooter>
diff --git a/jams-react-client/src/views/UserProfile/EditCreateUserProfile.js b/jams-react-client/src/views/UserProfile/EditCreateUserProfile.js
index 2d5d6ab7..8b030e82 100644
--- a/jams-react-client/src/views/UserProfile/EditCreateUserProfile.js
+++ b/jams-react-client/src/views/UserProfile/EditCreateUserProfile.js
@@ -62,9 +62,8 @@ import {
 import dashboardStyle from "assets/jss/material-dashboard-react/views/dashboardStyle.js";
 
 import FormikField from 'components/FormikField/FormikField';
-import {Formik, ErrorMessage, Field} from "formik";
+import {Formik} from "formik";
 import * as Yup from 'yup';
-require('yup-phone');
 
 const fileUpload = require('fuctbase64');
 
@@ -408,7 +407,7 @@ export default function EditCreateUserProfile(props) {
                             />
                         </div>
                     </div>
-                    <Button onClick={handleClose} color="danger">
+                    <Button onClick={handleClose} color="info">
                         Cancel
                     </Button>
                     <Button onClick={cropProfilePicture} color="success" autoFocus>
@@ -439,7 +438,7 @@ export default function EditCreateUserProfile(props) {
                                                 <Grid item xs={12} sm={12} md={12}>
                                                     <input accept="image/*"  className={classes.input} id="icon-button-file" type="file" onChange={handleProfilePictureChange}/>
                                                     <label htmlFor="icon-button-file" >
-                                                        <IconButton color="inherit" aria-label="upload picture" component="span" >
+                                                        <IconButton color="info" aria-label="upload picture" component="span" >
                                                             <PhotoCamera />
                                                         </IconButton> Change profile image
                                                     </label>
@@ -529,7 +528,7 @@ export default function EditCreateUserProfile(props) {
                                         </div>
                                     </CardBody>
                                     <CardFooter className={classes.alignRight}>
-                                        {!createUser && <Button color="danger" onClick={handleCancelUpdate}>Cancel</Button>}
+                                        {!createUser && <Button color="info" onClick={handleCancelUpdate}>Cancel</Button>}
                                         {createUser ? <Button type="submit" disabled={!isValid || !dirty} color="info">Create Profile</Button> : <Button type="submit" disabled={!isValid || !dirty} color="info">Save Profile</Button>}
                                     </CardFooter>
                                 </Card>
-- 
GitLab