Compare commits
5 Commits
dcb0764bde
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
27cc2cf763 | ||
|
|
47e9949cef | ||
|
|
e908b7a1d6 | ||
|
|
211f72fa3b | ||
|
|
0469f2d343 |
@@ -388,5 +388,5 @@ define("SSL_KEY", array(
|
|||||||
"Payload_IV" => "Ae0Rf13j8e",
|
"Payload_IV" => "Ae0Rf13j8e",
|
||||||
"route" => "pkAddGs9DB3VeEGL"
|
"route" => "pkAddGs9DB3VeEGL"
|
||||||
));
|
));
|
||||||
define("JWT_KEY", "9QY3tGDFzS5aiI3Pz8Uf");
|
define("JWT_KEY", "9QY3tGDFzS5aiI3Pz8UfABCDEF1234567890");
|
||||||
// YG INI JANGAN DI HAPUS
|
// YG INI JANGAN DI HAPUS
|
||||||
|
|||||||
@@ -22,4 +22,7 @@ $routes->group('api', function($routes) {
|
|||||||
|
|
||||||
// Standard CRUD via DhivaRoutes (Keep for compatibility)
|
// Standard CRUD via DhivaRoutes (Keep for compatibility)
|
||||||
DhivaRoutes::Route($routes, 'user', 'SuperUserController');
|
DhivaRoutes::Route($routes, 'user', 'SuperUserController');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Catch all OPTIONS requests for CORS preflight
|
||||||
|
$routes->options('(:any)', function () {});
|
||||||
@@ -157,6 +157,7 @@ abstract class BaseController extends Controller
|
|||||||
$bypassed = [
|
$bypassed = [
|
||||||
'/api/auth' => 'POST',
|
'/api/auth' => 'POST',
|
||||||
'/api/personel/profil' => 'GET', // Allow profile access for QR
|
'/api/personel/profil' => 'GET', // Allow profile access for QR
|
||||||
|
'/api/personel/drh' => 'GET', // Allow DRH access for QR
|
||||||
];
|
];
|
||||||
|
|
||||||
$this->initHeader();
|
$this->initHeader();
|
||||||
|
|||||||
@@ -7,136 +7,137 @@ use Dhiva\Core\DhivaAES;
|
|||||||
|
|
||||||
class PersonelController extends BaseController
|
class PersonelController extends BaseController
|
||||||
{
|
{
|
||||||
protected $personelModel;
|
protected $personelModel;
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->personelModel = new PersonelModel();
|
$this->personelModel = new PersonelModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get basic profile info by NRP (supports encrypted NRP)
|
||||||
|
*/
|
||||||
|
public function getProfil()
|
||||||
|
{
|
||||||
|
$inputNrp = $this->request->getGet('nrp');
|
||||||
|
|
||||||
|
if (!$inputNrp) {
|
||||||
|
return $this->response(UNAUTHORIZED, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
// Try to decrypt if it's not a numeric NRP
|
||||||
* Get basic profile info by NRP (supports encrypted NRP)
|
$nrp = $inputNrp;
|
||||||
*/
|
if (!is_numeric($inputNrp)) {
|
||||||
public function getProfil()
|
try {
|
||||||
{
|
$decrypted = DhivaAES::base64url_decode($inputNrp);
|
||||||
$inputNrp = $this->request->getGet('nrp');
|
if ($decrypted !== false && !empty($decrypted)) {
|
||||||
|
$nrp = $decrypted;
|
||||||
if (!$inputNrp) {
|
|
||||||
return $this->response(UNAUTHORIZED, 1);
|
|
||||||
}
|
}
|
||||||
|
} catch (\Exception $e) {
|
||||||
// Try to decrypt if it's not a numeric NRP
|
// Keep original if crash
|
||||||
$nrp = $inputNrp;
|
}
|
||||||
if (!is_numeric($inputNrp)) {
|
|
||||||
try {
|
|
||||||
$decrypted = DhivaAES::base64url_decode($inputNrp);
|
|
||||||
if ($decrypted !== false && !empty($decrypted)) {
|
|
||||||
$nrp = $decrypted;
|
|
||||||
}
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
// Keep original if crash
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$personel = $this->personelModel->where('nrp', $nrp)->first();
|
|
||||||
|
|
||||||
if (!$personel) {
|
|
||||||
$response = [
|
|
||||||
'status' => 'error',
|
|
||||||
'message' => 'Personel tidak ditemukan',
|
|
||||||
'data' => null
|
|
||||||
];
|
|
||||||
return $this->respond($response, 404);
|
|
||||||
}
|
|
||||||
|
|
||||||
$response = [
|
|
||||||
'status' => 'success',
|
|
||||||
'message' => 'Data personel ditemukan',
|
|
||||||
'data' => $personel
|
|
||||||
];
|
|
||||||
|
|
||||||
$this->respond($response);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
$personel = $this->personelModel->where('nrp', $nrp)->first();
|
||||||
* Get full DRH by NRP and OTP (supports encrypted NRP)
|
|
||||||
*/
|
|
||||||
public function getDaftarRiwayatHidup()
|
|
||||||
{
|
|
||||||
$inputNrp = $this->request->getGet('nrp');
|
|
||||||
$otp = $this->request->getGet('otp');
|
|
||||||
|
|
||||||
// Try to decrypt if it's not a numeric NRP
|
|
||||||
$nrp = $inputNrp;
|
|
||||||
if (!is_numeric($inputNrp)) {
|
|
||||||
$nrp = DhivaAES::base64url_decode($inputNrp) ?: $inputNrp;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($otp !== '4444') {
|
if (!$personel) {
|
||||||
$this->respond([
|
$response = [
|
||||||
'status' => 'error',
|
'status' => 'error',
|
||||||
'message' => 'OTP tidak valid',
|
'message' => 'Personel tidak ditemukan',
|
||||||
'data' => null
|
'data' => null
|
||||||
], 401);
|
];
|
||||||
}
|
return $this->respond($response, 404);
|
||||||
|
|
||||||
if (!$nrp) {
|
|
||||||
$this->respond([
|
|
||||||
'status' => 'error',
|
|
||||||
'message' => 'NRP wajib diisi',
|
|
||||||
'data' => null
|
|
||||||
], 400);
|
|
||||||
}
|
|
||||||
|
|
||||||
$drh = $this->personelModel->getFullDRH($nrp);
|
|
||||||
|
|
||||||
if (!$drh) {
|
|
||||||
$this->respond([
|
|
||||||
'status' => 'error',
|
|
||||||
'message' => 'Data riwayat hidup tidak ditemukan',
|
|
||||||
'data' => null
|
|
||||||
], 404);
|
|
||||||
}
|
|
||||||
|
|
||||||
$response = [
|
|
||||||
'status' => 'success',
|
|
||||||
'message' => 'Data riwayat hidup berhasil diambil',
|
|
||||||
'data' => $drh
|
|
||||||
];
|
|
||||||
|
|
||||||
$this->respond($response);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
$response = [
|
||||||
* Generate Encrypted URL for Barcode (Admin only)
|
'status' => 'success',
|
||||||
*/
|
'message' => 'Data personel ditemukan',
|
||||||
public function generateEncryptedLink()
|
'data' => $personel
|
||||||
{
|
];
|
||||||
$nrp = $this->request->getPost('nrp');
|
|
||||||
|
|
||||||
if (!$nrp) {
|
|
||||||
$this->respond(['status' => 'error', 'message' => 'NRP wajib diisi'], 400);
|
|
||||||
}
|
|
||||||
|
|
||||||
$encryptedNrp = DhivaAES::base64url_encode($nrp);
|
$this->respond($response);
|
||||||
|
}
|
||||||
$response = [
|
|
||||||
'status' => 'success',
|
|
||||||
'data' => [
|
|
||||||
'nrp' => $nrp,
|
|
||||||
'encrypted_nrp' => $encryptedNrp,
|
|
||||||
'url' => "http://localhost:4200/kta/profil/" . $encryptedNrp
|
|
||||||
]
|
|
||||||
];
|
|
||||||
|
|
||||||
$this->respond($response);
|
/**
|
||||||
|
* Get full DRH by NRP and OTP (supports encrypted NRP)
|
||||||
|
*/
|
||||||
|
public function getDaftarRiwayatHidup()
|
||||||
|
{
|
||||||
|
$inputNrp = $this->request->getGet('nrp');
|
||||||
|
$otp = $this->request->getGet('otp');
|
||||||
|
|
||||||
|
// Try to decrypt if it's not a numeric NRP
|
||||||
|
$nrp = $inputNrp;
|
||||||
|
if (!is_numeric($inputNrp)) {
|
||||||
|
$nrp = DhivaAES::base64url_decode($inputNrp) ?: $inputNrp;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function respond($data, $code = 200)
|
if ($otp !== '4444') {
|
||||||
{
|
$this->respond([
|
||||||
header('Content-Type: application/json');
|
'status' => 'error',
|
||||||
http_response_code($code);
|
'message' => 'OTP tidak valid',
|
||||||
echo json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
|
'data' => null
|
||||||
die;
|
], 401);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!$nrp) {
|
||||||
|
$this->respond([
|
||||||
|
'status' => 'error',
|
||||||
|
'message' => 'NRP wajib diisi',
|
||||||
|
'data' => null
|
||||||
|
], 400);
|
||||||
|
}
|
||||||
|
|
||||||
|
$drh = $this->personelModel->getFullDRH($nrp);
|
||||||
|
|
||||||
|
if (!$drh) {
|
||||||
|
$this->respond([
|
||||||
|
'status' => 'error',
|
||||||
|
'message' => 'Data riwayat hidup tidak ditemukan',
|
||||||
|
'data' => null
|
||||||
|
], 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
$response = [
|
||||||
|
'status' => 'success',
|
||||||
|
'message' => 'Data riwayat hidup berhasil diambil',
|
||||||
|
'data' => $drh
|
||||||
|
];
|
||||||
|
|
||||||
|
$this->respond($response);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate Encrypted URL for Barcode (Admin only)
|
||||||
|
*/
|
||||||
|
public function generateEncryptedLink()
|
||||||
|
{
|
||||||
|
$json = $this->request->getJSON();
|
||||||
|
$nrp = $json ? $json->nrp : $this->request->getPost('nrp');
|
||||||
|
|
||||||
|
if (!$nrp) {
|
||||||
|
$this->respond(['status' => 'error', 'message' => 'NRP wajib diisi'], 400);
|
||||||
|
}
|
||||||
|
|
||||||
|
$encryptedNrp = DhivaAES::base64url_encode($nrp);
|
||||||
|
|
||||||
|
$response = [
|
||||||
|
'status' => 'success',
|
||||||
|
'data' => [
|
||||||
|
'nrp' => $nrp,
|
||||||
|
'encrypted_nrp' => $encryptedNrp,
|
||||||
|
'url' => "http://192.168.1.11:4200/kta/profil/" . $encryptedNrp
|
||||||
|
]
|
||||||
|
];
|
||||||
|
|
||||||
|
$this->respond($response);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function respond($data, $code = 200)
|
||||||
|
{
|
||||||
|
header('Content-Type: application/json');
|
||||||
|
http_response_code($code);
|
||||||
|
echo json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
|
||||||
|
die;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,12 +19,18 @@ class SuperUserController extends BaseController
|
|||||||
*/
|
*/
|
||||||
public function auth()
|
public function auth()
|
||||||
{
|
{
|
||||||
// Debug point
|
|
||||||
echo json_encode(["status" => "reached auth"]); die;
|
|
||||||
|
|
||||||
$inputUsername = $this->post('username');
|
$inputUsername = $this->post('username');
|
||||||
$inputPassword = $this->post('password');
|
$inputPassword = $this->post('password');
|
||||||
|
|
||||||
|
// Fallback for JSON payload (Angular)
|
||||||
|
if (empty($inputUsername) || empty($inputPassword)) {
|
||||||
|
$json = $this->request->getJSON();
|
||||||
|
if ($json) {
|
||||||
|
$inputUsername = $json->username ?? null;
|
||||||
|
$inputPassword = $json->password ?? null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (empty($inputUsername) || empty($inputPassword)) {
|
if (empty($inputUsername) || empty($inputPassword)) {
|
||||||
$this->respond([
|
$this->respond([
|
||||||
'success' => false,
|
'success' => false,
|
||||||
|
|||||||
@@ -26,13 +26,13 @@ class Cors implements FilterInterface
|
|||||||
*/
|
*/
|
||||||
public function before(RequestInterface $request, $arguments = null)
|
public function before(RequestInterface $request, $arguments = null)
|
||||||
{
|
{
|
||||||
// header("Access-Control-Allow-Origin: *");
|
header("Access-Control-Allow-Origin: *");
|
||||||
// header("Access-Control-Allow-Headers: X-API-KEY, Origin,X-Requested-With, Content-Type, Accept, Access-Control-Requested-Method, Authorization, ClientSecret");
|
header("Access-Control-Allow-Headers: X-API-KEY, Origin,X-Requested-With, Content-Type, Accept, Access-Control-Requested-Method, Authorization, ClientSecret");
|
||||||
// header("Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE");
|
header("Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE");
|
||||||
// $method = $_SERVER['REQUEST_METHOD'];
|
$method = $_SERVER['REQUEST_METHOD'];
|
||||||
// if ($method == "OPTIONS") {
|
if ($method == "OPTIONS") {
|
||||||
// die();
|
die();
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
38
schema.sql
38
schema.sql
@@ -17,10 +17,40 @@ CREATE TABLE IF NOT EXISTS kta_digital.personel (
|
|||||||
agama VARCHAR(50),
|
agama VARCHAR(50),
|
||||||
suku VARCHAR(50),
|
suku VARCHAR(50),
|
||||||
status_personel VARCHAR(50) DEFAULT 'AKTIF',
|
status_personel VARCHAR(50) DEFAULT 'AKTIF',
|
||||||
|
no_wa VARCHAR(20),
|
||||||
|
email VARCHAR(255),
|
||||||
|
otp_code VARCHAR(10),
|
||||||
|
otp_expired_at TIMESTAMP,
|
||||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
);
|
);
|
||||||
|
|
||||||
|
-- Table: public.super_user (Auth)
|
||||||
|
CREATE TABLE IF NOT EXISTS public.super_user (
|
||||||
|
super_user_id SERIAL PRIMARY KEY,
|
||||||
|
username VARCHAR(255) NOT NULL,
|
||||||
|
password VARCHAR(255) NOT NULL,
|
||||||
|
name VARCHAR(255),
|
||||||
|
email VARCHAR(255),
|
||||||
|
avatar TEXT,
|
||||||
|
satuan_id INTEGER,
|
||||||
|
jabatan VARCHAR(255),
|
||||||
|
nrp VARCHAR(20),
|
||||||
|
pangkat VARCHAR(100),
|
||||||
|
no_wa VARCHAR(20),
|
||||||
|
super_group_id INTEGER,
|
||||||
|
login_date TIMESTAMP,
|
||||||
|
access_at TIMESTAMP,
|
||||||
|
token TEXT,
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Seed demo admin user (username: dhivaadmin, password: dhivaadmin)
|
||||||
|
INSERT INTO public.super_user (username, password, name, super_group_id)
|
||||||
|
VALUES ('dhivaadmin', 'dhivaadmin', 'Admin KTA', 1)
|
||||||
|
ON CONFLICT DO NOTHING;
|
||||||
|
|
||||||
-- Table: kta_digital.pendidikan_kepolisian
|
-- Table: kta_digital.pendidikan_kepolisian
|
||||||
CREATE TABLE IF NOT EXISTS kta_digital.pendidikan_kepolisian (
|
CREATE TABLE IF NOT EXISTS kta_digital.pendidikan_kepolisian (
|
||||||
id SERIAL PRIMARY KEY,
|
id SERIAL PRIMARY KEY,
|
||||||
@@ -87,11 +117,11 @@ CREATE TABLE IF NOT EXISTS kta_digital.penugasan_luar_struktur (
|
|||||||
);
|
);
|
||||||
|
|
||||||
-- Seed Data: Personel
|
-- Seed Data: Personel
|
||||||
INSERT INTO kta_digital.personel (nrp, nama, pangkat, jabatan, satuan, foto_url, tmt_jabatan, lama_jabatan, tempat_lahir, tanggal_lahir, agama, suku, status_personel)
|
INSERT INTO kta_digital.personel (nrp, nama, pangkat, jabatan, satuan, foto_url, tmt_jabatan, lama_jabatan, tempat_lahir, tanggal_lahir, agama, suku, status_personel, no_wa, email)
|
||||||
VALUES
|
VALUES
|
||||||
('83121540', 'YOPPY ANGGI KRISNA', 'AKBP', 'KASUBBAGMINDOK BAGINFOPERS ROBINKAR SSDM POLRI', 'ROBINKAR SSDM POLRI', '/foto-yoppy.jpg', '2026-01-02', '0 Tahun 0 Bulan 5 Hari', 'KABUPATEN BANYUWANGI', '14 Maret 1982', 'ISLAM', 'JAWA', 'AKTIF'),
|
('83121540', 'YOPPY ANGGI KRISNA', 'AKBP', 'KASUBBAGMINDOK BAGINFOPERS ROBINKAR SSDM POLRI', 'ROBINKAR SSDM POLRI', '/foto-yoppy.jpg', '2026-01-02', '0 Tahun 0 Bulan 5 Hari', 'KABUPATEN BANYUWANGI', '14 Maret 1982', 'ISLAM', 'JAWA', 'AKTIF', '081234567890', 'yoppy@example.com'),
|
||||||
('72060510', 'LANGGENG PURNOMO', 'BRIGJEN POL', 'KAROBINKAR SSDM POLRI', 'ROBINKAR SSDM POLRI', '/foto-langgeng.jpg', '2023-03-15', '2 Tahun 1 Bulan 9 Hari', 'SURABAYA', '10 Juni 1972', 'ISLAM', 'JAWA', 'AKTIF'),
|
('72060510', 'LANGGENG PURNOMO', 'BRIGJEN POL', 'KAROBINKAR SSDM POLRI', 'ROBINKAR SSDM POLRI', '/foto-langgeng.jpg', '2023-03-15', '2 Tahun 1 Bulan 9 Hari', 'SURABAYA', '10 Juni 1972', 'ISLAM', 'JAWA', 'AKTIF', '081234567891', 'langgeng@example.com'),
|
||||||
('77110844', 'SIGIT DANY SETIYONO', 'KOMBES POL', 'KABAGINFOPERS ROBINKAR SSDM POLRI', 'ROBINKAR SSDM POLRI', '/foto-sigit.jpg', '2022-04-01', '2 Tahun 9 Bulan 23 Hari', 'SEMARANG', '08 November 1977', 'ISLAM', 'JAWA', 'AKTIF')
|
('77110844', 'SIGIT DANY SETIYONO', 'KOMBES POL', 'KABAGINFOPERS ROBINKAR SSDM POLRI', 'ROBINKAR SSDM POLRI', '/foto-sigit.jpg', '2022-04-01', '2 Tahun 9 Bulan 23 Hari', 'SEMARANG', '08 November 1977', 'ISLAM', 'JAWA', 'AKTIF', '081234567892', 'sigit@example.com')
|
||||||
ON CONFLICT (nrp) DO NOTHING;
|
ON CONFLICT (nrp) DO NOTHING;
|
||||||
|
|
||||||
-- Seed Data: Pendidikan Kepolisian (Example for Yoppy)
|
-- Seed Data: Pendidikan Kepolisian (Example for Yoppy)
|
||||||
|
|||||||
Reference in New Issue
Block a user