Skip to content

Commit

Permalink
Merge pull request #7728 from ProcessMaker/FOUR-20103
Browse files Browse the repository at this point in the history
FOUR-20103 confirm identity validation does not work when email field is updated
  • Loading branch information
ryancooley authored Nov 12, 2024
2 parents 2286619 + 3380468 commit c236ffe
Show file tree
Hide file tree
Showing 7 changed files with 236 additions and 59 deletions.
6 changes: 6 additions & 0 deletions ProcessMaker/Http/Controllers/Admin/UserController.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use ProcessMaker\Models\JsonData;
use ProcessMaker\Models\Permission;
use ProcessMaker\Models\User;
use ProcessMaker\Package\Auth\Models\SsoUser;
use ProcessMaker\Traits\HasControllerAddons;

class UserController extends Controller
Expand Down Expand Up @@ -66,6 +67,10 @@ function ($result, $item) {
return $result;
}
);
$ssoUser = false;
if (class_exists(SsoUser::class)) {
$ssoUser = SsoUser::where('user_id', $user->id)->exists();
}

// Get global and valid 2FA preferences for the user
$enabled2FA = config('password-policies.2fa_enabled', false);
Expand All @@ -92,6 +97,7 @@ function ($result, $item) {
'is2FAEnabledForGroup',
'addons',
'addonsSettings',
'ssoUser',
));
}

Expand Down
47 changes: 47 additions & 0 deletions ProcessMaker/Http/Controllers/Api/UserController.php
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,27 @@ public function update(User $user, Request $request)
return $response;
}
}
if ($fields['email'] !== $original['email']) {
if (!isset($fields['valpassword'])) {
return response([
'message' => __(
'A valid authentication is required for for update the email.'
),
'errors' => [
'email' => [
__(
'The password is required.'
),
],
],
], 422);
} else {
$response = $this->validateBeforeChange(Auth::user(), $fields['valpassword']);
if ($response) {
return $response;
}
}
}
if (Auth::user()->is_administrator && $request->has('is_administrator')) {
// user must be an admin to make another user an admin
$user->is_administrator = $request->get('is_administrator');
Expand Down Expand Up @@ -469,6 +490,32 @@ private function validateCellPhoneNumber(User $user, $number)
return false;
}

/**
* Validate the phone number for SMS two-factor authentication.
*
* @param User $user User to validate
* @param mixed $password String to validate
*/
private function validateBeforeChange(User $user, $password)
{
if (!Hash::check($password, $user->password)) {
return response([
'message' => __(
'A valid authentication is required for for update the email.'
),
'errors' => [
'email' => [
__(
'The authentication is incorrect.'
),
],
],
], 422);
}

return false;
}

/**
* Update a user's pinned BPMN elements on Modeler
*
Expand Down
8 changes: 7 additions & 1 deletion ProcessMaker/Http/Controllers/ProfileController.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use ProcessMaker\i18nHelper;
use ProcessMaker\Models\JsonData;
use ProcessMaker\Models\User;
use ProcessMaker\Package\Auth\Models\SsoUser;
use ProcessMaker\Traits\HasControllerAddons;

class ProfileController extends Controller
Expand Down Expand Up @@ -43,6 +44,11 @@ function ($result, $item) {
}
);

$ssoUser = false;
if (class_exists(SsoUser::class)) {
$ssoUser = SsoUser::where('user_id', $currentUser->id)->exists();
}

// Get global and valid 2FA preferences for the user
$enabled2FA = config('password-policies.2fa_enabled', false);
$global2FAEnabled = config('password-policies.2fa_method', []);
Expand All @@ -53,7 +59,7 @@ function ($result, $item) {

return view('profile.edit',
compact('currentUser', 'states', 'timezones', 'countries', 'datetimeFormats',
'status', 'enabled2FA', 'global2FAEnabled', 'is2FAEnabledForGroup', 'addons'));
'status', 'enabled2FA', 'global2FAEnabled', 'is2FAEnabledForGroup', 'addons', 'ssoUser'));
}

/**
Expand Down
79 changes: 57 additions & 22 deletions resources/views/admin/users/edit.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,7 @@
image: '',
status: @json($status),
global2FAEnabled: @json($global2FAEnabled),
ssoUser:@json($ssoUser),
errors: {
username: null,
firstname: null,
Expand All @@ -281,6 +282,8 @@
groups: [],
userGroupsFilter: '',
focusErrors: 'errors',
originalEmail: '',
emailHasChanged: false,
}
},
created() {
Expand Down Expand Up @@ -338,6 +341,15 @@
if (created) {
ProcessMaker.alert(this.$t('The user was successfully created'), 'success');
}
this.originalEmail = this.formData.email;
const togglePassword = document.querySelector('#togglePassword');
const password = document.querySelector('#valpassword');
togglePassword.addEventListener('click', function (e) {
const type = password.getAttribute('type') === 'password' ? 'text' : 'password';
password.setAttribute('type', type);
this.classList.toggle('fa-eye-slash');
});
},
watch: {
selectedPermissions: function () {
Expand Down Expand Up @@ -464,28 +476,12 @@
return true
},
profileUpdate($event) {
this.resetErrors();
if (@json($enabled2FA) && this.global2FAEnabled.length === 0) {
// User has not enabled two-factor authentication correctly
ProcessMaker.alert(
this.$t('The Two Step Authentication Method has not been set. Please contact your administrator.'),
'warning'
);
return false;
if(this.emailHasChanged && !this.ssoUser) {
$('#validateModal').modal('show');
} else {
this.saveProfileChanges();
}
if (!this.validatePassword()) return false;
if (@json($enabled2FA) && typeof this.formData.preferences_2fa != "undefined" &&
this.formData.preferences_2fa != null && this.formData.preferences_2fa.length < 1) return false;
ProcessMaker.apiClient.put('users/' + this.formData.id, this.formData)
.then(response => {
ProcessMaker.alert(this.$t('User Updated Successfully '), 'success');
if (this.formData.id == window.ProcessMaker.user.id) {
window.ProcessMaker.events.$emit('update-profile-avatar');
}
})
.catch(error => {
this.errors = error.response.data.errors;
});
},
permissionUpdate() {
ProcessMaker.apiClient.put("/permissions", {
Expand Down Expand Up @@ -560,7 +556,45 @@
.then(response => {
this.groups = response.data.data
});
}
},
showModal() {
$('#validateModal').modal('show');
},
closeModal() {
$('#validateModal').modal('hide');
},
saveProfileChanges() {
this.resetErrors();
if (@json($enabled2FA) && this.global2FAEnabled.length === 0) {
// User has not enabled two-factor authentication correctly
ProcessMaker.alert(
this.$t('The Two Step Authentication Method has not been set. Please contact your administrator.'),
'warning'
);
return false;
}
if (!this.validatePassword()) return false;
if (@json($enabled2FA) && typeof this.formData.preferences_2fa != "undefined" &&
this.formData.preferences_2fa != null && this.formData.preferences_2fa.length < 1) return false;
ProcessMaker.apiClient.put('users/' + this.formData.id, this.formData)
.then(response => {
ProcessMaker.alert(this.$t('User Updated Successfully '), 'success');
this.originalEmail = this.formData.email;
this.emailHasChanged = false;
if (this.formData.id == window.ProcessMaker.user.id) {
window.ProcessMaker.events.$emit('update-profile-avatar');
this.formData.valpassword = "";
}
})
.catch(error => {
this.errors = error.response.data.errors;
});
this.closeModal();
},
checkEmailChange() {
this.emailHasChanged = this.formData.email !== this.originalEmail;
},
}
});
</script>
Expand Down Expand Up @@ -623,3 +657,4 @@
}
</style>
@endsection
91 changes: 63 additions & 28 deletions resources/views/profile/edit.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@
states: @json($states),
status: @json($status),
global2FAEnabled: @json($global2FAEnabled),
ssoUser:@json($ssoUser),
errors: {
username: null,
firstname: null,
Expand All @@ -145,6 +146,8 @@
},
confPassword: '',
image: '',
originalEmail: '',
emailHasChanged: false,
options: [
{
src: @json($currentUser['avatar']),
Expand All @@ -168,37 +171,27 @@
});
}
},
mounted() {
this.originalEmail = this.formData.email;
const togglePassword = document.querySelector('#togglePassword');
const password = document.querySelector('#valpassword');
togglePassword.addEventListener('click', function (e) {
const type = password.getAttribute('type') === 'password' ? 'text' : 'password';
password.setAttribute('type', type);
this.classList.toggle('fa-eye-slash');
});
},
methods: {
openAvatarModal() {
modalVueInstance.$refs.updateAvatarModal.show();
},
profileUpdate() {
this.resetErrors();
if (@json($enabled2FA) && this.global2FAEnabled.length === 0) {
let message = 'The Two Step Authentication Method has not been set. ' +
'Please contact your administrator.';
// User has not enabled two-factor authentication correctly
ProcessMaker.alert(this.$t($message), 'warning');
return false;
}
if (!this.validatePassword()) return false;
if (@json($enabled2FA) && typeof this.formData.preferences_2fa != "undefined" &&
this.formData.preferences_2fa != null && this.formData.preferences_2fa.length < 1)
return false;
if (this.image) {
this.formData.avatar = this.image;
}
if (this.image === false) {
this.formData.avatar = false;
}
ProcessMaker.apiClient.put('users/' + this.formData.id, this.formData)
.then((response) => {
ProcessMaker.alert(this.$t('Your profile was saved.'), 'success')
window.ProcessMaker.events.$emit('update-profile-avatar');
})
.catch(error => {
this.errors = error.response.data.errors;
});
if(this.emailHasChanged && !this.ssoUser) {
$('#validateModal').modal('show');
} else {
this.saveProfileChanges();
}
},
deleteAvatar() {
let optionValues = formVueInstance.$data.options[0];
Expand Down Expand Up @@ -241,6 +234,48 @@
onClose() {
window.location.href = '/admin/users';
},
showModal() {
$('#validateModal').modal('show');
},
closeModal() {
$('#validateModal').modal('hide');
},
saveProfileChanges() {
this.resetErrors();
if (@json($enabled2FA) && this.global2FAEnabled.length === 0) {
let message = 'The Two Step Authentication Method has not been set. ' +
'Please contact your administrator.';
// User has not enabled two-factor authentication correctly
ProcessMaker.alert(this.$t($message), 'warning');
return false;
}
if (!this.validatePassword()) return false;
if (@json($enabled2FA) && typeof this.formData.preferences_2fa != "undefined" &&
this.formData.preferences_2fa != null && this.formData.preferences_2fa.length < 1)
return false;
if (this.image) {
this.formData.avatar = this.image;
}
if (this.image === false) {
this.formData.avatar = false;
}
ProcessMaker.apiClient.put('users/' + this.formData.id, this.formData)
.then((response) => {
ProcessMaker.alert(this.$t('Your profile was saved.'), 'success')
window.ProcessMaker.events.$emit('update-profile-avatar');
this.originalEmail = this.formData.email;
this.emailHasChanged = false;
this.formData.valpassword = "";
})
.catch(error => {
this.errors = error.response.data.errors;
});
this.closeModal();
},
checkEmailChange() {
this.emailHasChanged = this.formData.email !== this.originalEmail;
},
},
computed: {
state2FA() {
Expand Down Expand Up @@ -378,8 +413,8 @@
//TODO: HANDLE CONNECTION UPDATE
this.onCloseModal;
}
},
}
});
</script>
@endsection
@endsection
Loading

0 comments on commit c236ffe

Please sign in to comment.