From d3534e62a112719212f76d8dcc49b37fc3a23ed7 Mon Sep 17 00:00:00 2001 From: mahdahar <89adham@gmail.com> Date: Wed, 10 Dec 2025 16:37:51 +0700 Subject: [PATCH] add change password per user --- app/Config/Routes.php | 13 ++++----- app/Controllers/V2.php | 12 ++++++++ app/Views/v2/admin/index.php | 14 +++++----- app/Views/v2/admin/main.php | 9 +++--- app/Views/v2/admin/users.php | 6 ++-- app/Views/v2/dialog_setPassword.php | 35 +++++++++++++++++++++++ app/Views/v2/lab/index.php | 14 +++++----- app/Views/v2/lab/main.php | 2 +- public/js/app.js | 43 ++++++++++++++++++++++++++++- 9 files changed, 117 insertions(+), 31 deletions(-) create mode 100644 app/Views/v2/dialog_setPassword.php diff --git a/app/Config/Routes.php b/app/Config/Routes.php index b648948..b1f81c4 100644 --- a/app/Config/Routes.php +++ b/app/Config/Routes.php @@ -72,11 +72,11 @@ $routes->group('v2', function($routes) { $routes->get('login', 'V2::loginPage'); $routes->post('login', 'V2::login'); $routes->get('logout', 'V2::logout'); + $routes->patch('setPassword', 'V2::setPassword'); // Admin $routes->group('admin', ['filter' => 'role:1'], function($routes) { $routes->get('', 'V2\Admin::index'); $routes->get('users', 'V2\Admin::users'); - $routes->post('setPassword', 'V2\Users::setPassword'); // Users $routes->get('api/users', 'V2\Users::index'); $routes->post('api/users', 'V2\Users::create'); @@ -84,22 +84,21 @@ $routes->group('v2', function($routes) { $routes->delete('api/users/(:any)', 'V2\Users::delete/$1'); // Request $routes->get('api/requests', 'V2\Requests::index'); - $routes->post('api/requests/validate/(:any)', 'V2\Requests::validate/$1'); - $routes->delete('api/requests/validate/(:any)', 'V2\Requests::unvalidate/$1'); + $routes->post('api/requests/validate/(:any)', 'V2\Requests::val/$1'); + $routes->delete('api/requests/validate/(:any)', 'V2\Requests::unval/$1'); // Samples $routes->post('api/samples/collect/(:any)', 'V2\Samples::collect/$1'); $routes->delete('api/samples/collect/(:any)', 'V2\Samples::uncollect/$1'); $routes->delete('api/samples/receive/(:any)', 'V2\Samples::unreceive/$1'); $routes->get('api/samples/(:any)', 'V2\Samples::show/$1'); }); - // Analyst and doctor + // Lab $routes->group('lab', ['filter' => 'role:2'], function($routes) { $routes->get('', 'V2\Lab::index'); - $routes->post('setPassword', 'V2\Lab::setPassword'); // Request $routes->get('api/requests', 'V2\Requests::index'); - $routes->post('api/requests/validate/(:any)', 'V2\Requests::validate/$1'); - $routes->delete('api/requests/validate/(:any)', 'V2\Requests::unvalidate/$1'); + $routes->post('api/requests/validate/(:any)', 'V2\Requests::val/$1'); + $routes->delete('api/requests/validate/(:any)', 'V2\Requests::unval/$1'); // Samples $routes->post('api/samples/collect/(:any)', 'V2\Samples::collect/$1'); $routes->get('api/samples/(:any)', 'V2\Samples::show/$1'); diff --git a/app/Controllers/V2.php b/app/Controllers/V2.php index 9d50952..ef3fd02 100644 --- a/app/Controllers/V2.php +++ b/app/Controllers/V2.php @@ -97,4 +97,16 @@ class V2 extends BaseController { $session->destroy(); return redirect()->to('v2/login'); } + + public function setPassword() { + $input = $this->request->getJSON(true); + $userid = $input['userid']; + $password = $input['password']; + $password = password_hash($password, PASSWORD_DEFAULT); + $db = db_connect(); + $sql = "update GDC_CMOD.dbo.USERS set PASSWORD='$password' where USERID='$userid'"; + $db->query($sql); + $data = ['status' => 'success', 'message' => 'Password updated successfully', 'data' => "$userid" ]; + return $this->response->setJSON($data); + } } diff --git a/app/Views/v2/admin/index.php b/app/Views/v2/admin/index.php index 6149d2c..6ad5c70 100644 --- a/app/Views/v2/admin/index.php +++ b/app/Views/v2/admin/index.php @@ -177,7 +177,7 @@ let param = new URLSearchParams(this.filter).toString(); // reset counters before processing for (let k in this.counters) { this.counters[k] = 0; } - fetch(`${BASEURL}/api/requests?${param}`, { + fetch(`${BASEURL}/admin/api/requests?${param}`, { method: 'GET', headers: {'Content-Type': 'application/json'}, }).then(res => res.json()).then(data => { @@ -250,7 +250,7 @@ fetchItem(accessnumber){ this.item = []; - fetch(`${BASEURL}/api/samples/${accessnumber}`, { method: 'GET', headers: {'Content-Type': 'application/json'}}) + fetch(`${BASEURL}/admin/api/samples/${accessnumber}`, { method: 'GET', headers: {'Content-Type': 'application/json'}}) .then(res => res.json()).then(data => { this.item = data.data ?? {}; if (!Array.isArray(this.item.samples)) this.item.samples = []; @@ -258,7 +258,7 @@ }, collect(sampcode, accessnumber) { - fetch(`${BASEURL}/api/samples/collect/${accessnumber}`, { + fetch(`${BASEURL}/admin/api/samples/collect/${accessnumber}`, { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({samplenumber: sampcode, userid: ''}) }) @@ -269,7 +269,7 @@ uncollect(sampcode, accessnumber) { if(!confirm(`Uncollect sample ${sampcode} from request ${accessnumber}?`)) { return ;} - fetch(`${BASEURL}/api/samples/collect/${accessnumber}`, { + fetch(`${BASEURL}/admin/api/samples/collect/${accessnumber}`, { method: 'DELETE', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({samplenumber: sampcode, userid: ''}) }) @@ -280,7 +280,7 @@ unreceive(sampcode, accessnumber) { if(!confirm(`Unreceive sample ${sampcode} from request ${accessnumber}?`)) { return ;} - fetch(`${BASEURL}/api/samples/unreceive/${accessnumber}`, { + fetch(`${BASEURL}/admin/api/samples/unreceive/${accessnumber}`, { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({samplenumber: sampcode, userid : ''}) }) @@ -333,7 +333,7 @@ this.isDialogValOpen = false; }, validate(accessnumber, userid) { - fetch(`${BASEURL}/api/requests/validate/${accessnumber}`, { + fetch(`${BASEURL}/admin/api/requests/validate/${accessnumber}`, { method: "POST", headers: {"Content-Type": "application/json"}, body: JSON.stringify({ userid:`${userid}` }) @@ -357,7 +357,7 @@ }, unvalidate(accessnumber, userid) { if(!confirm(`Unvalidate request ${accessnumber}?`)) { return ;} - fetch(`${BASEURL}/api/requests/validate/${accessnumber}`, { + fetch(`${BASEURL}/admin/api/requests/validate/${accessnumber}`, { method: "DELETE", headers: {"Content-Type": "application/json"}, body: JSON.stringify({ userid:`${userid}`, comment: this.unvalReason.trim() }) diff --git a/app/Views/v2/admin/main.php b/app/Views/v2/admin/main.php index 3fa854e..bf788c4 100644 --- a/app/Views/v2/admin/main.php +++ b/app/Views/v2/admin/main.php @@ -23,7 +23,7 @@ } - + renderSection('content');?> - + include('v2/dialog_setPassword');?> - renderSection('script');?> diff --git a/app/Views/v2/admin/users.php b/app/Views/v2/admin/users.php index 2b7fddb..39c7a50 100644 --- a/app/Views/v2/admin/users.php +++ b/app/Views/v2/admin/users.php @@ -165,7 +165,7 @@ }, fetchUsers() { - fetch(`${BASEURL}/api/users`) + fetch(`${BASEURL}/admin/api/users`) .then(res => res.json()) .then(data => { this.list = data.data ?? []; @@ -213,13 +213,13 @@ try { let res; if(this.mode == 'create') { - res = await fetch(`${BASEURL}/api/users`, { + res = await fetch(`${BASEURL}/admin/api/users`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(this.form) }); } else { - res = await fetch(`${BASEURL}/api/users/${this.form.userid}`, { + res = await fetch(`${BASEURL}/admin/api/users/${this.form.userid}`, { method: 'PATCH', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(this.form) diff --git a/app/Views/v2/dialog_setPassword.php b/app/Views/v2/dialog_setPassword.php new file mode 100644 index 0000000..4b09510 --- /dev/null +++ b/app/Views/v2/dialog_setPassword.php @@ -0,0 +1,35 @@ + + + + \ No newline at end of file diff --git a/app/Views/v2/lab/index.php b/app/Views/v2/lab/index.php index f35fac3..ca8ccba 100644 --- a/app/Views/v2/lab/index.php +++ b/app/Views/v2/lab/index.php @@ -177,7 +177,7 @@ let param = new URLSearchParams(this.filter).toString(); // reset counters before processing for (let k in this.counters) { this.counters[k] = 0; } - fetch(`${BASEURL}/api/requests?${param}`, { + fetch(`${BASEURL}/admin/api/requests?${param}`, { method: 'GET', headers: {'Content-Type': 'application/json'}, }).then(res => res.json()).then(data => { @@ -250,7 +250,7 @@ fetchItem(accessnumber){ this.item = []; - fetch(`${BASEURL}/api/samples/${accessnumber}`, { method: 'GET', headers: {'Content-Type': 'application/json'}}) + fetch(`${BASEURL}/admin/api/samples/${accessnumber}`, { method: 'GET', headers: {'Content-Type': 'application/json'}}) .then(res => res.json()).then(data => { this.item = data.data ?? {}; if (!Array.isArray(this.item.samples)) this.item.samples = []; @@ -258,7 +258,7 @@ }, collect(sampcode, accessnumber) { - fetch(`${BASEURL}/api/samples/collect/${accessnumber}`, { + fetch(`${BASEURL}/admin/api/samples/collect/${accessnumber}`, { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({samplenumber: sampcode, userid: ''}) }) @@ -269,7 +269,7 @@ uncollect(sampcode, accessnumber) { if(!confirm(`Uncollect sample ${sampcode} from request ${accessnumber}?`)) { return ;} - fetch(`${BASEURL}/api/samples/collect/${accessnumber}`, { + fetch(`${BASEURL}/admin/api/samples/collect/${accessnumber}`, { method: 'DELETE', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({samplenumber: sampcode, userid: ''}) }) @@ -280,7 +280,7 @@ unreceive(sampcode, accessnumber) { if(!confirm(`Unreceive sample ${sampcode} from request ${accessnumber}?`)) { return ;} - fetch(`${BASEURL}/api/samples/unreceive/${accessnumber}`, { + fetch(`${BASEURL}/admin/api/samples/unreceive/${accessnumber}`, { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({samplenumber: sampcode, userid : ''}) }) @@ -333,7 +333,7 @@ this.isDialogValOpen = false; }, validate(accessnumber, userid) { - fetch(`${BASEURL}/api/requests/validate/${accessnumber}`, { + fetch(`${BASEURL}/admin/api/requests/validate/${accessnumber}`, { method: "POST", headers: {"Content-Type": "application/json"}, body: JSON.stringify({ userid:`${userid}` }) @@ -357,7 +357,7 @@ }, unvalidate(accessnumber, userid) { if(!confirm(`Unvalidate request ${accessnumber}?`)) { return ;} - fetch(`${BASEURL}/api/requests/validate/${accessnumber}`, { + fetch(`${BASEURL}/admin/api/requests/validate/${accessnumber}`, { method: "DELETE", headers: {"Content-Type": "application/json"}, body: JSON.stringify({ userid:`${userid}`, comment: this.unvalReason.trim() }) diff --git a/app/Views/v2/lab/main.php b/app/Views/v2/lab/main.php index f1c6235..b9f6d89 100644 --- a/app/Views/v2/lab/main.php +++ b/app/Views/v2/lab/main.php @@ -41,8 +41,8 @@ diff --git a/public/js/app.js b/public/js/app.js index efad83a..b348630 100644 --- a/public/js/app.js +++ b/public/js/app.js @@ -5,7 +5,48 @@ Alpine.plugin(persist) window.Alpine = Alpine Alpine.data("main", () => ({ - + /* + passwordDialog + */ + isDialogSetPasswordOpen: false, + password: '', + confirm_password: '', + isLoading: false, + error: '', + openDialogSetPassword(){ + this.isDialogSetPasswordOpen = true; + }, + closeDialogSetPassword(){ + this.isDialogSetPasswordOpen = false; + }, + savePassword(userid) { + this.error = ''; + if(!this.password) { this.error = "Password is required"; return; } + if(this.password !== this.confirm_password) { this.error = "Passwords do not match"; return; } + this.isLoading = true; + fetch(BASEURL + '/setPassword', { + method: 'PATCH', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ userid: userid, password: this.password }) + }) + .then(res => res.json()) + .then(data => { + this.isLoading = false; + if(data.status === 'success') { + alert('Password changed successfully'); + this.password = ''; + this.confirm_password = ''; + this.closeDialogSetPassword(); + } else { + this.error = data.message || 'Unknown error occurred'; + } + }) + .catch(err => { + this.isLoading = false; + this.error = 'Network error occurred. Please try again.'; + console.error(err); + }); + } })); export default Alpine; \ No newline at end of file