This commit is contained in:
mahdahar 2025-09-04 11:05:28 +07:00
commit 1305b2bc3e
6 changed files with 438 additions and 82 deletions

View File

@ -35,6 +35,7 @@ class Filters extends BaseFilters
'forcehttps' => ForceHTTPS::class,
'pagecache' => PageCache::class,
'performance' => PerformanceMetrics::class,
'auth' => \App\Filters\AuthFilter::class,
];
/**
@ -70,7 +71,7 @@ class Filters extends BaseFilters
*/
public array $globals = [
'before' => [
'cors'
'cors',
// 'honeypot',
// 'csrf',
// 'invalidchars',

View File

@ -10,9 +10,21 @@ $routes->options('(:any)', function() {
});
$routes->get('/', 'Home::index');
$routes->post('/auth/login/', 'Auth::login');
$routes->post('/auth/change_pass/', 'Auth::change_pass');
$routes->post('/auth/register/', 'Auth::register');
//PUNYA GUS INI TEMP
$routes->get('/api/v1/emr/lab/list-new', 'NUHATEMP::index');
$routes->post('/api/v1/emr/lab/insert', 'NUHATEMP::create');
$routes->post('/api/v1/emr/lab/update-validasi', 'NUHATEMP::update');
$routes->post('/api/v1/emr/lab/detail', 'NUHATEMP::detail');
$routes->group('api', ['filter' => 'auth'], function($routes) {
$routes->get('coba-auth', 'Auth::coba');
});
$routes->post('/api/auth/login', 'Auth::login');
$routes->post('/api/auth/change_pass', 'Auth::change_pass');
$routes->post('/api/auth/register', 'Auth::register');
$routes->get('/api/auth/check', 'Auth::checkAuth');
$routes->post('/api/auth/logout', 'Auth::logout');
$routes->get('/api/patient', 'Patient::index');
$routes->post('/api/patient', 'Patient::create');

View File

@ -4,16 +4,79 @@ namespace App\Controllers;
use CodeIgniter\API\ResponseTrait;
use CodeIgniter\Controller;
use \Firebase\JWT\JWT;
use Firebase\JWT\JWT;
use Firebase\JWT\Key;
use Firebase\JWT\ExpiredException;
use Firebase\JWT\SignatureInvalidException;
use Firebase\JWT\BeforeValidException;
use CodeIgniter\Cookie\Cookie;
class Auth extends Controller {
use ResponseTrait;
// ok
public function __construct() {
$this->db = \Config\Database::connect();
}
// ok
public function checkAuth() {
$token = $this->request->getCookie('token');
$key = getenv('JWT_SECRET');
// Jika token FE tidak ada langsung kabarkan failed
if (!$token) {
return $this->respond([
'status' => 'failed',
'message' => 'No token found'
], 401);
}
try {
// Decode Token dengan Key yg ada di .env
$decodedPayload = JWT::decode($token, new Key($key, 'HS256'));
return $this->respond([
'status' => 'success',
'message' => 'Authenticated',
'data' => $decodedPayload
], 200);
} catch (ExpiredException $e) {
return $this->respond([
'status' => 'failed',
'message' => 'Token expired',
'data' => []
], 401);
} catch (SignatureInvalidException $e) {
return $this->respond([
'status' => 'failed',
'message' => 'Invalid token signature',
'data' => []
], 401);
} catch (BeforeValidException $e) {
return $this->respond([
'status' => 'failed',
'message' => 'Token not valid yet',
'data' => []
], 401);
} catch (\Exception $e) {
return $this->respond([
'status' => 'failed',
'message' => 'Invalid token: ' . $e->getMessage(),
'data' => []
], 401);
}
}
// ok
public function login() {
// Ambil dari JSON Form dan Key .env
$username = $this->request->getVar('username');
$password = $this->request->getVar('password');
$key = getenv('JWT_SECRET');
@ -21,115 +84,147 @@ class Auth extends Controller {
if (!$username) {
return $this->fail('Username required.', 400);
}
$sql = "select * from users where username=".$this->db->escape($username);
$sql = "SELECT * FROM users WHERE username=" . $this->db->escape($username);
$query = $this->db->query($sql);
$row = $query->getRowArray();
if (!$row) {
return $this->fail('User not found.', 401); // Use 401 for authentication failures
return $this->fail('User not found.', 401);
}
if (!password_verify($password, $row['password'])) {
return $this->fail('Invalid password.', 401);
}
// JWT payload
// Buat JWT payload
$payload = [
'userid' => $row['id'],
'username' => $row['username'],
'exp' => time() + 3600
'exp' => time() + 86400 // 1 hari
];
try {
// Melakukan Hash terhadap Payload dengan Kunci .env menggunakan Algortima HMAC + SHA-256
$jwt = JWT::encode($payload, $key, 'HS256');
} catch (Exception $e) {
return $this->fail('Error generating JWT: ' . $e->getMessage(), 500);
}
// Update last_login
//$this->userModel->update($user['id'], ['lastlogin' => date('Y-m-d H:i:s')]);
// Kirim Respon ke HttpOnly yg akan disimpan di browser dan tidak akan dapat diakses oleh siapapun
$this->response->setCookie([
'name' => 'token', // nama token
'value' => $jwt, // value dari jwt yg sudah di hash
'expire' => 86400, // 1 hari
'path' => '/', // valid untuk semua path
'secure' => true, // set true kalau sudah HTTPS
'httponly' => true, // dipakai agar cookie berikut tidak dapat diakses oleh javascript
'samesite' => Cookie::SAMESITE_NONE
]);
$response = [
'message' => 'Login successful',
'token' => $jwt,
];
return $this->respond($response);
// Response tanpa token di body
return $this->respond([
'status' => 'success',
'message' => 'Login successful'
], 200);
}
public function change_pass() {
$db = \Config\Database::connect();
$username = $this->request->getJsonVar('username');
$password = $this->request->getJsonVar('password');
$password = password_hash($password, PASSWORD_DEFAULT);
$master = $this->request->getJsonVar('master');
$masterkey = getenv('masterkey');
// ok
public function logout() {
// Definisikan ini pada cookies browser, harus sama dengan cookies login
return $this->response->setCookie([
'name' => 'token',
'value' => '',
'expire' => time() - 3600,
'path' => '/',
'secure' => true,
'httponly' => true,
'samesite' => Cookie::SAMESITE_NONE
if($master != $masterkey) {
return $this->fail('Invalid master key.', 401);
}
$sql = "update users set password='$password' where username='$username'";
$query = $db->query($sql);
$response = [
'message' => "Password Changed for $username"
];
return $this->respond($response);
])->setJSON([
'status' => 'success',
'message' => 'Logout successful'
], 200);
}
// ok
public function register() {
$username = $this->request->getJsonVar('username');
$password = $this->request->getJsonVar('password');
$password = password_hash($password, PASSWORD_DEFAULT);
$master = $this->request->getJsonVar('master');
$masterkey = getenv('MASTERKEY');
if($master != $masterkey) {
return $this->fail('Invalid master key.', 401);
}
$sql = "insert into users(username, password) values('$username', '$password')";
$this->db->query($sql);
$response = [
'message' => "user $username created"
];
return $this->respondCreated($response);
}
public function checkAuth() {
$authorizationHeader = $this->request->getHeader('Authorization');
if (!$authorizationHeader) {
return $this->fail('Authorization header is missing', 401);
}
$authHeaderValue = $authorizationHeader->getValue();
if (empty($authHeaderValue)) {
return $this->fail('Authorization header is empty', 401);
}
// Extract the token from the "Bearer <token>" format
if (strpos($authHeaderValue, 'Bearer ') === 0) {
$token = substr($authHeaderValue, 7);
} else {
$token = $authHeaderValue; // Assume the header contains only the token
// Validasi
if (empty($username) || empty($password)) {
return $this->respond([
'status' => 'failed',
'message' => 'Username and password are required'
], 400); // Gunakan 400 Bad Request
}
$hashedPassword = password_hash($password, PASSWORD_DEFAULT);
$sql = "INSERT INTO users(username, password) VALUES(?, ?)";
try {
$decoded = JWT::decode($token, $this->key, ['HS256']); // Use the Key object
// You can now access user data from $decoded
$response = [
'message' => 'Authentication successful',
'user' => $decoded, // return the decoded token
];
return $this->respond($response);
// Jalankan kueri dan binding data secara terpisah
$this->db->query($sql, [$username, $hashedPassword]);
} catch (Exception $e) {
return $this->fail('Invalid token: ' . $e->getMessage(), 401);
// Respon sukses jika kueri berhasil
return $this->respond([
'status' => 'success',
'message' => 'User ' . $username . ' successfully created.'
], 201); // Kode 201 Created sudah benar untuk resource baru
} catch (\Exception $e) {
// Tangani error lain-lain
return $this->respond([
'status' => 'error',
'message' => 'Failed to create user. Please try again later.'
], 500); // Kode 500 Internal Server Error untuk masalah di server
}
}
}
// public function change_pass() {
// $db = \Config\Database::connect();
// $username = $this->request->getJsonVar('username');
// $password = $this->request->getJsonVar('password');
// $password = password_hash($password, PASSWORD_DEFAULT);
// $master = $this->request->getJsonVar('master');
// $masterkey = getenv('masterkey');
// if($master != $masterkey) {
// return $this->fail('Invalid master key.', 401);
// }
// $sql = "update users set password='$password' where username='$username'";
// $query = $db->query($sql);
// $response = [
// 'message' => "Password Changed for $username"
// ];
// return $this->respond($response);
// }
public function coba() {
$token = $this->request->getCookie('token');
$key = getenv('JWT_SECRET');
// Decode Token dengan Key yg ada di .env
$decodedPayload = JWT::decode($token, new Key($key, 'HS256'));
return $this->respond([
'status' => 'success',
'message' => 'Authenticated',
'data' => $decodedPayload
], 200);
// return $this->respond([
// 'status' => 'success',
// 'message' => 'Already Login'
// ],200);
}
}

View File

@ -0,0 +1,197 @@
<?php
namespace App\Controllers;
use CodeIgniter\API\ResponseTrait;
use CodeIgniter\Controller;
use CodeIgniter\Database\RawSql;
class NUHATEMP extends Controller {
use ResponseTrait;
public function __construct() {
$this->db = \Config\Database::connect();
}
// OK - Done
public function index() {
$valid_from = $this->request->getVar('valid_from');
$valid_to = $this->request->getVar('valid_to');
try {
// Data pasien ditemukan dan mengembalikan - success 200
return $this->respond([
"response" => [
"list" => [
[
"tgl" => "2023-07-31T00:12:00Z",
"no_lab" => 153304,
"no_rm" => "001063898",
"nama" => "WAHYUDI",
"tgl_lahir" => "1976-05-15T00:00:00Z",
"jenis_kelamin" => "Laki-laki",
"umur" => "47 tahun, 2 bulan, 15 hari",
"alamat" => "KP GEBANG RT 01/03 SANGIANG JAYA PERIUK",
"ruang" => "",
"kelas" => "",
"status" => "BPJS",
"dokter_pengirim" => "dr. Arie Asnafi, Sp.U",
"jenis_lab" => "pk",
"lis_id" => "2307310001",
"id_ruangan" => "1",
"nama_ruangan" => "Flamboyan",
"id_asuransi" => "2",
"nama_asuransi" => "BPJS KESEHATAN",
"cito" => false,
"list_test" => [
[
"detail_id" => 265833,
"no_lab" => 153304,
"test_id" => 72,
"nama_test" => "Glukosa Sewaktu",
"jenis_lab" => "pk",
"jenis_test" => "t",
"detail_test" => []
]
]
],
[
"tgl" => "2023-07-31T00:53:00Z",
"no_lab" => 153307,
"no_rm" => "001301669",
"nama" => "RAFFASYAH ALKHALIFI PUTRA H",
"tgl_lahir" => "2017-11-28T00:00:00Z",
"jenis_kelamin" => "Laki-laki",
"umur" => "5 tahun, 8 bulan, 2 hari",
"alamat" => "JL TARUMANEGARA I / 4 RT 04 RW 022",
"ruang" => "",
"kelas" => "",
"status" => "BPJS",
"dokter_pengirim" => "dr. Arif Budiman, Sp.A (K)",
"jenis_lab" => "pk",
"lis_id" => "2307310004",
"id_ruangan" => "1",
"nama_ruangan" => "Flamboyan",
"id_asuransi" => "2",
"nama_asuransi" => "BPJS KESEHATAN",
"list_test" => [
[
"detail_id" => 265836,
"no_lab" => 153307,
"test_id" => 31,
"nama_test" => "Darah Lengkap",
"jenis_lab" => "pk",
"jenis_test" => "p",
"detail_test" => [
["paket_id"=>31,"index"=>1,"spasi"=>"0","test_id"=>16,"nama_test"=>"Hemoglobin"],
["paket_id"=>31,"index"=>2,"spasi"=>"0","test_id"=>26,"nama_test"=>"Leukosit"],
["paket_id"=>31,"index"=>3,"spasi"=>"0","test_id"=>28,"nama_test"=>"Eritrosit"],
["paket_id"=>31,"index"=>4,"spasi"=>"0","test_id"=>29,"nama_test"=>"Hematokrit"],
["paket_id"=>31,"index"=>5,"spasi"=>"0","test_id"=>30,"nama_test"=>"Trombosit"],
["paket_id"=>31,"index"=>6,"spasi"=>"0","test_id"=>32,"nama_test"=>"Hitung Jenis"],
["paket_id"=>31,"index"=>7,"spasi"=>"0","test_id"=>33,"nama_test"=>"Eosinofil"],
["paket_id"=>31,"index"=>8,"spasi"=>"0","test_id"=>34,"nama_test"=>"Basofil"],
["paket_id"=>31,"index"=>9,"spasi"=>"0","test_id"=>35,"nama_test"=>"Netrofil Batang"],
["paket_id"=>31,"index"=>10,"spasi"=>"0","test_id"=>36,"nama_test"=>"Netrofil Segmen"],
["paket_id"=>31,"index"=>11,"spasi"=>"0","test_id"=>37,"nama_test"=>"Limfosit"],
["paket_id"=>31,"index"=>12,"spasi"=>"0","test_id"=>38,"nama_test"=>"Monosit"],
["paket_id"=>31,"index"=>13,"spasi"=>"0","test_id"=>39,"nama_test"=>"Laju Endap Darah"]
]
]
]
]
]
],
"metadata" => [
"message" => "Ok",
"code" => 200
]
], 200);
} catch (\Exception $e) {
// Error Server Mengembalikan 500
return $this->failServerError('Something went wrong.'.$e->getMessage());
}
}
// OK - Done
public function create() {
try {
// Data pasien ditemukan dan mengembalikan - success 200
return $this->respond([
"message"=> "Ok",
'status' => 200
], 200);
} catch (\Exception $e) {
// Error Server Mengembalikan 500
return $this->failServerError('Something went wrong.'.$e->getMessage());
}
}
// OK - Done
public function update() {
try {
// Data pasien ditemukan dan mengembalikan - success 200
return $this->respond([
"message"=> "Ok",
'status' => 200
], 200);
} catch (\Exception $e) {
// Error Server Mengembalikan 500
return $this->failServerError('Something went wrong.'.$e->getMessage());
}
}
// OK - Done
public function detail() {
try {
// Data pasien ditemukan dan mengembalikan - success 200
return $this->respond([
"response" => [
"tgl" => "2024-03-08T09:37:00Z",
"no_lab" => 3021,
"no_rm" => "000264395",
"nama" => "CANDY RAMADONA, AN",
"tgl_lahir" => "2007-09-02",
"jenis_kelamin" => "Perempuan",
"umur" => "2023 tahun, 2 bulan, 7 hari",
"alamat" => "PERUM PONDOK JAGUNG BLOK AC.45 001/004",
"ruang" => "",
"kelas" => "",
"status" => "ASURANSI SINAR MAS, PT",
"id_dokter_pengirim" => 2,
"dokter_pengirim" => "dr.Mila Agustia.Sp.A",
"jenis_lab" => "pk",
"lis_id" => "240308208",
"id_ruangan" => "1",
"nama_ruangan" => "DAMAR",
"id_asuransi" => "118",
"nama_asuransi" => "ASURANSI SINAR MAS, PT",
"cito" => false,
"list_test" => [
[
"detail_id" => 4981,
"no_lab" => 3021,
"test_id" => 145,
"nama_test" => "Urin Lengkap (Paket)",
"jenis_lab" => "",
"jenis_test" => "",
"detail_test" => null
]
]
],
"metadata" => [
"message" => "Ok",
"code" => 200
]
], 200);
} catch (\Exception $e) {
// Error Server Mengembalikan 500
return $this->failServerError('Something went wrong.'.$e->getMessage());
}
}
}

View File

@ -0,0 +1,50 @@
<?php
namespace App\Filters;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
use CodeIgniter\Filters\FilterInterface;
use Config\Services;
use Firebase\JWT\JWT;
use Firebase\JWT\Key;
class AuthFilter implements FilterInterface
{
public function before(RequestInterface $request, $arguments = null)
{
$key = getenv('JWT_SECRET');
$token = $request->getCookie('token'); // ambil dari cookie
// Kalau tidak ada token
if (!$token) {
return Services::response()
->setStatusCode(401)
->setJSON([
'status' => 'failed',
'message' => 'Unauthorized: Token not found'
]);
}
try {
// Decode JWT : jika error maka akan mentrigger catch
$decoded = JWT::decode($token, new Key($key, 'HS256'));
// Kalau mau, bisa inject user info ke request
// $request->userData = $decoded;
} catch (\Exception $e) {
return Services::response()
->setStatusCode(401)
->setJSON([
'status' => 'failed',
'message' => 'Unauthorized: ' . $e->getMessage()
]);
}
}
public function after(RequestInterface $request, ResponseInterface $response, $arguments = null)
{
// Tidak perlu apa-apa
}
}

View File

@ -22,7 +22,8 @@ class Cors implements FilterInterface
if (in_array($origin, $this->allowedOrigins)) {
$response->setHeader('Access-Control-Allow-Origin', $origin);
$response->setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, PATCH, DELETE, OPTIONS');
$response->setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization, X-Requested-With');
$response->setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization, X-Requested-With, Accept, Origin, Cache-Control, Pragma');
// $response->setHeader('Access-Control-Allow-Headers', '*');
$response->setHeader('Access-Control-Allow-Credentials', 'true');
}