Add password reset functionality

This commit is contained in:
Matteo Gheza 2024-01-11 22:51:13 +01:00
parent d99fc9264f
commit c91a592431
7 changed files with 127 additions and 10 deletions

View File

@ -235,6 +235,23 @@ class UserController extends Controller
return response()->json($user);
}
public function updatePassword(Request $request, User $user)
{
if($request->user()->id != $user->id && !$request->user()->hasPermission("users-update-auth")) abort(401);
if($request->user()->id == $user->id && !$request->user()->hasPermission("user-update-auth")) abort(401);
$request->validate([
'password' => 'required|string|min:6'
]);
$user->password = bcrypt($request->password);
$user->save();
Logger::log("Modifica password utente", $user);
return response()->json($user);
}
/**
* Remove the specified resource from storage.
*/

View File

@ -13,8 +13,8 @@ return [
'roles_structure' => [
'superadmin' => [
'users' => 'c,r,u,d,i,b,h,sc,sd,atc,ame',
'user' => 'u,h,sc,sd',
'users' => 'c,r,u,ua,d,i,b,h,sc,sd,atc,ame',
'user' => 'u,ua,h,sc,sd',
'services' => 'c,r,u,d',
'trainings' => 'c,r,u,d',
'alerts' => 'c,r,u',
@ -25,8 +25,8 @@ return [
'admin-roles' => 'r,u'
],
'admin' => [
'users' => 'c,r,u,d,i,b,h,sc,sd,atc,ame',
'user' => 'u,h,sc,sd',
'users' => 'c,r,u,ua,d,i,b,h,sc,sd,atc,ame',
'user' => 'u,ua,h,sc,sd',
'services' => 'c,r,u,d',
'trainings' => 'c,r,u,d',
'alerts' => 'c,r,u',
@ -37,7 +37,7 @@ return [
],
'chief' => [
'users' => 'r,u,sc,sd,atc,ame',
'user' => 'u',
'user' => 'u,ua',
'services' => 'c,r,u,d',
'trainings' => 'c,r,u,d',
'alerts' => 'c,r,u',
@ -45,7 +45,7 @@ return [
],
'user' => [
'users' => 'lr',
'user' => 'u',
'user' => 'u,ua',
'services' => 'c,r,u,d',
'trainings' => 'c,r,u,d',
'alerts' => 'r',
@ -58,6 +58,7 @@ return [
'lr' => 'limited-read',
'r' => 'read',
'u' => 'update',
'ua' => 'update-auth',
'd' => 'delete',
'i' => 'impersonate',
'b' => 'ban',

View File

@ -48,6 +48,7 @@ Route::middleware('auth:sanctum')->group( function () {
Route::get('/users/{user}', [UserController::class, 'show']);
Route::put('/users/{user}', [UserController::class, 'update']);
Route::put('/users/{user}/reset_password', [UserController::class, 'updatePassword']);
Route::post('/documents/driving_license', [DocumentsController::class, 'uploadDrivingLicenseScan']);
Route::post('/documents/training_course', [DocumentsController::class, 'addTrainingCourse']);

View File

@ -36,6 +36,9 @@
<input formControlName="birthplace_province" type="text" class="form-control" [placeholder]="'province'|translate|ftitlecase">
</div>
</div>
<div class="col-12 m-3 mt-4">
<button type="button" role="button" class="btn btn-primary" (click)="openResetPwdModal(resetPasswordModal)">{{ 'change_password'|translate }}</button>
</div>
<h2 class="text-center mt-5"><i class="fas fa-fire-extinguisher"></i> {{ 'service_information'|translate|ftitlecase }}</h2>
<div class="col-md-12">
@ -210,3 +213,33 @@
</tbody>
</table>
</div>
<ng-template #resetPasswordModal>
<div class="modal-header">
<h4 class="modal-title pull-left" translate>password_change_title</h4>
<button
type="button"
class="btn-close close pull-right"
[attr.aria-label]="'close' | translate | ftitlecase"
(click)="resetPwdModalRef?.hide()"
>
<span aria-hidden="true" class="visually-hidden">&times;</span>
</button>
</div>
<div class="modal-body">
<form>
<div class="form-group m-3">
<label for="password">{{ 'new_password'|translate|ftitlecase }}</label>
<input type="password" class="form-control" id="password" [(ngModel)]="newPwd" [ngModelOptions]="{standalone: true}">
</div>
<div class="form-group m-3 mt-4">
<label for="confirmPassword">{{ 'confirm_password'|translate|ftitlecase }}</label>
<input type="password" class="form-control" id="confirmPassword" [(ngModel)]="newPwdConfirm" [ngModelOptions]="{standalone: true}">
</div>
<div class="alert alert-warning m-4 mt-2" role="alert" *ngIf="newPwd !== newPwdConfirm && newPwd !== '' && newPwdConfirm !== ''">
{{ 'password_not_match'|translate }}
</div>
<button type="submit" role="button" class="btn btn-primary mt-2" (click)="resetPwdSubmit()" [disabled]="newPwd !== newPwdConfirm && newPwd !== '' && newPwdConfirm !== ''">{{ 'update'|translate|ftitlecase }}</button>
</form>
</div>
</ng-template>

View File

@ -1,4 +1,4 @@
import { Component, OnInit } from '@angular/core';
import { Component, OnInit, TemplateRef } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { ApiClientService } from 'src/app/_services/api-client.service';
@ -6,7 +6,7 @@ import { AuthService } from 'src/app/_services/auth.service';
import { TranslateService } from '@ngx-translate/core';
import { ModalAddTrainingCourseComponent } from 'src/app/_components/modal-add-traning-course/modal-add-training-course.component';
import { ModalAddMedicalExaminationComponent } from 'src/app/_components/modal-add-medical-examination/modal-add-medical-examination.component';
import { BsModalService } from 'ngx-bootstrap/modal';
import { BsModalService, BsModalRef } from 'ngx-bootstrap/modal';
import Swal from 'sweetalert2';
@Component({
@ -61,6 +61,10 @@ export class EditUserComponent implements OnInit {
dlScanNotUploadedYet = true;
dlCurrScanUrl: string | null = null;
resetPwdModalRef: BsModalRef | undefined;
newPwd: string = '';
newPwdConfirm: string = '';
constructor(
private route: ActivatedRoute,
private formBuilder: FormBuilder,
@ -282,4 +286,51 @@ export class EditUserComponent implements OnInit {
});
}
openResetPwdModal(template: TemplateRef<any>) {
this.resetPwdModalRef = this.modalService.show(template);
}
resetPwdSubmit() {
//Check if min size 6
if(this.newPwd.length < 6) {
Swal.fire({
title: this.translateService.instant("error_title"),
text: this.translateService.instant("validation.password_min_length"),
icon: 'error',
confirmButtonText: 'Ok'
});
return;
}
//Check if pwd and confirm are equal
if(this.newPwd !== this.newPwdConfirm) {
Swal.fire({
title: this.translateService.instant("error_title"),
text: this.translateService.instant("password_not_match"),
icon: 'error',
confirmButtonText: 'Ok'
});
return;
}
this.api.put(`users/${this.id}/reset_password`, {
password: this.newPwd
}).then((response) => {
console.log(response);
Swal.fire({
title: this.translateService.instant("success_title"),
text: this.translateService.instant("password_changed_successfully"),
icon: 'success',
confirmButtonText: 'Ok'
});
this.resetPwdModalRef?.hide();
}).catch((err) => {
console.log(err);
Swal.fire({
title: this.translateService.instant("error_title"),
text: err.error.message,
icon: 'error',
confirmButtonText: 'Ok'
});
});
}
}

View File

@ -152,7 +152,8 @@
"type_already_exists": "Type already exists",
"image_format_not_supported": "Image format not supported",
"document_format_not_supported": "Document format not supported",
"file_too_big": "File too big"
"file_too_big": "File too big",
"password_min_length": "Password must be at least 6 characters long"
},
"enable": "enable",
"disable": "disable",
@ -168,6 +169,12 @@
"cpu": "CPU",
"username": "username",
"password": "password",
"new_password": "new password",
"confirm_password": "confirm password",
"password_not_match": "Passwords do not match. Please try again.",
"password_changed_successfully": "Password changed successfully",
"password_change_title": "Change password",
"change_password": "Change password",
"warning": "warning",
"press_for_more_info": "press here for more info",
"update_availability_schedule": "Update availability schedule",

View File

@ -152,7 +152,8 @@
"type_already_exists": "La tipologia è già presente",
"image_format_not_supported": "Formato immagine non supportato",
"document_format_not_supported": "Formato documento non supportato",
"file_too_big": "File troppo grande"
"file_too_big": "File troppo grande",
"password_min_length": "La password deve essere di almeno 6 caratteri"
},
"enable": "attiva",
"disable": "disattiva",
@ -168,6 +169,12 @@
"cpu": "CPU",
"username": "username",
"password": "password",
"new_password": "nuova password",
"confirm_password": "conferma password",
"password_not_match": "Le password non corrispondono. Riprova.",
"password_changed_successfully": "Password cambiata con successo",
"password_change_title": "Cambio password",
"change_password": "Cambia password",
"warning": "attenzione",
"press_for_more_info": "premi qui per informazioni",
"update_availability_schedule": "Aggiorna programmazione disponibilità",