545 lines
18 KiB
PHP
545 lines
18 KiB
PHP
<?php
|
|
defined('BASEPATH') OR exit('No direct script access allowed');
|
|
|
|
class User extends MY_Controller
|
|
{
|
|
private $db_dashboard;
|
|
private $db_log;
|
|
|
|
public function __construct()
|
|
{
|
|
parent::__construct();
|
|
$this->db_dashboard = $this->load->database("cpone_dashboard", true);
|
|
$this->db_log = $this->load->database("log", true);
|
|
}
|
|
|
|
public function save()
|
|
{
|
|
if (!$this->isLogin) {
|
|
$this->sys_error("Invalid Token");
|
|
return;
|
|
}
|
|
|
|
$username = $this->sanitize_username($this->get_input('username'));
|
|
$password = (string) $this->get_input('password');
|
|
$displayName = $this->sanitize_text($this->get_input('display_name'), 100);
|
|
|
|
if ($username === '') {
|
|
$this->sys_error("username wajib diisi");
|
|
return;
|
|
}
|
|
|
|
if (!$this->is_valid_password_policy($password)) {
|
|
$this->sys_error("password harus minimal 8 karakter dan mengandung huruf besar, huruf kecil, angka, serta simbol");
|
|
return;
|
|
}
|
|
|
|
$query = $this->db_dashboard->query(
|
|
"CALL sp_insert_dashboard_user(?, ?, ?)",
|
|
array($username, $password, $displayName)
|
|
);
|
|
$this->clean_mysqli_connection($this->db_dashboard->conn_id);
|
|
|
|
if (!$query) {
|
|
$error = $this->db_dashboard->error();
|
|
$this->log_activity("SAVE_USER", $username, $this->sys_input, "N", $error['message']);
|
|
$this->sys_error_db("gagal insert dashboard user", $this->db_dashboard);
|
|
return;
|
|
}
|
|
|
|
$this->log_activity("SAVE_USER", $username, $this->sys_input, "Y", "success");
|
|
$this->sys_ok(array(
|
|
"message" => "user berhasil disimpan",
|
|
"username" => $username
|
|
));
|
|
}
|
|
|
|
public function reset_password()
|
|
{
|
|
if (!$this->isLogin) {
|
|
$this->sys_error("Invalid Token");
|
|
return;
|
|
}
|
|
|
|
$username = $this->sanitize_username($this->get_input('username'));
|
|
$newPassword = (string) $this->get_input('password');
|
|
|
|
if ($username === '') {
|
|
$this->sys_error("username wajib diisi");
|
|
return;
|
|
}
|
|
|
|
if (!$this->is_valid_password_policy($newPassword)) {
|
|
$this->sys_error("password harus minimal 8 karakter dan mengandung huruf besar, huruf kecil, angka, serta simbol");
|
|
return;
|
|
}
|
|
|
|
$query = $this->db_dashboard->query(
|
|
"CALL sp_reset_dashboard_user_password(?, ?)",
|
|
array($username, $newPassword)
|
|
);
|
|
$this->clean_mysqli_connection($this->db_dashboard->conn_id);
|
|
|
|
if (!$query) {
|
|
$error = $this->db_dashboard->error();
|
|
$this->log_activity("RESET_PASSWORD", $username, $this->sys_input, "N", $error['message']);
|
|
$this->sys_error_db("gagal reset password", $this->db_dashboard);
|
|
return;
|
|
}
|
|
|
|
$this->log_activity("RESET_PASSWORD", $username, $this->sys_input, "Y", "success");
|
|
$this->sys_ok(array(
|
|
"message" => "password berhasil direset",
|
|
"username" => $username
|
|
));
|
|
}
|
|
|
|
public function assign_project()
|
|
{
|
|
if (!$this->isLogin) {
|
|
$this->sys_error("Invalid Token");
|
|
return;
|
|
}
|
|
|
|
$username = $this->sanitize_username($this->get_input('username'));
|
|
$mcuID = intval($this->get_input('mcu_id'));
|
|
|
|
if ($username === '') {
|
|
$this->sys_error("username wajib diisi");
|
|
return;
|
|
}
|
|
|
|
if ($mcuID <= 0) {
|
|
$this->sys_error("mcu_id tidak valid");
|
|
return;
|
|
}
|
|
|
|
$query = $this->db_dashboard->query(
|
|
"CALL sp_assign_user_project(?, ?)",
|
|
array($username, $mcuID)
|
|
);
|
|
$this->clean_mysqli_connection($this->db_dashboard->conn_id);
|
|
|
|
if (!$query) {
|
|
$error = $this->db_dashboard->error();
|
|
$this->log_activity("ASSIGN_PROJECT", $username, $this->sys_input, "N", $error['message']);
|
|
$this->sys_error_db("gagal assign project", $this->db_dashboard);
|
|
return;
|
|
}
|
|
|
|
$this->log_activity("ASSIGN_PROJECT", $username, $this->sys_input, "Y", "success");
|
|
$this->sys_ok(array(
|
|
"message" => "project berhasil di-assign",
|
|
"username" => $username,
|
|
"mcu_id" => $mcuID
|
|
));
|
|
}
|
|
|
|
public function remove_project()
|
|
{
|
|
if (!$this->isLogin) {
|
|
$this->sys_error("Invalid Token");
|
|
return;
|
|
}
|
|
|
|
$username = $this->sanitize_username($this->get_input('username'));
|
|
$mcuID = intval($this->get_input('mcu_id'));
|
|
|
|
if ($username === '') {
|
|
$this->sys_error("username wajib diisi");
|
|
return;
|
|
}
|
|
|
|
if ($mcuID <= 0) {
|
|
$this->sys_error("mcu_id tidak valid");
|
|
return;
|
|
}
|
|
|
|
$query = $this->db_dashboard->query(
|
|
"CALL sp_remove_user_project(?, ?)",
|
|
array($username, $mcuID)
|
|
);
|
|
$this->clean_mysqli_connection($this->db_dashboard->conn_id);
|
|
|
|
if (!$query) {
|
|
$error = $this->db_dashboard->error();
|
|
$this->log_activity("REMOVE_PROJECT", $username, $this->sys_input, "N", $error['message']);
|
|
$this->sys_error_db("gagal remove project", $this->db_dashboard);
|
|
return;
|
|
}
|
|
|
|
$this->log_activity("REMOVE_PROJECT", $username, $this->sys_input, "Y", "success");
|
|
$this->sys_ok(array(
|
|
"message" => "project berhasil dihapus dari user",
|
|
"username" => $username,
|
|
"mcu_id" => $mcuID
|
|
));
|
|
}
|
|
|
|
public function remove_user()
|
|
{
|
|
if (!$this->isLogin) {
|
|
$this->sys_error("Invalid Token");
|
|
return;
|
|
}
|
|
|
|
$username = $this->sanitize_username($this->get_input('username'));
|
|
if ($username === '') {
|
|
$this->sys_error("username wajib diisi");
|
|
return;
|
|
}
|
|
|
|
$userQuery = $this->db_dashboard->query(
|
|
"SELECT User_ID
|
|
FROM cpone_dashboard.dashboard_user
|
|
WHERE User_Username = ?
|
|
LIMIT 1",
|
|
array($username)
|
|
);
|
|
if (!$userQuery || $userQuery->num_rows() === 0) {
|
|
$this->log_activity("REMOVE_USER", $username, $this->sys_input, "N", "user tidak ditemukan");
|
|
$this->sys_error("user tidak ditemukan");
|
|
return;
|
|
}
|
|
$userID = intval($userQuery->row()->User_ID);
|
|
|
|
$projectRows = $this->db_dashboard->query(
|
|
"SELECT UserProj_McuID
|
|
FROM cpone_dashboard.dashboard_user_project
|
|
WHERE UserProj_UserID = ?
|
|
AND UserProj_IsActive = 'Y'",
|
|
array($userID)
|
|
);
|
|
if (!$projectRows) {
|
|
$this->log_activity("REMOVE_USER", $username, $this->sys_input, "N", "gagal ambil project user");
|
|
$this->sys_error_db("gagal ambil project user", $this->db_dashboard);
|
|
return;
|
|
}
|
|
|
|
$mcuIDs = array();
|
|
foreach ($projectRows->result_array() as $row) {
|
|
$mcuID = isset($row['UserProj_McuID']) ? intval($row['UserProj_McuID']) : 0;
|
|
if ($mcuID > 0) {
|
|
$mcuIDs[] = $mcuID;
|
|
}
|
|
}
|
|
|
|
$this->db_dashboard->trans_begin();
|
|
|
|
foreach ($mcuIDs as $mcuID) {
|
|
$removeProjectQuery = $this->db_dashboard->query(
|
|
"CALL sp_remove_user_project(?, ?)",
|
|
array($username, $mcuID)
|
|
);
|
|
$this->clean_mysqli_connection($this->db_dashboard->conn_id);
|
|
|
|
if (!$removeProjectQuery) {
|
|
$error = $this->db_dashboard->error();
|
|
$this->db_dashboard->trans_rollback();
|
|
$this->log_activity("REMOVE_USER", $username, $this->sys_input, "N", $error['message']);
|
|
$this->sys_error_db("gagal remove project user", $this->db_dashboard);
|
|
return;
|
|
}
|
|
}
|
|
|
|
$updateUserQuery = $this->db_dashboard->query(
|
|
"UPDATE cpone_dashboard.dashboard_user
|
|
SET User_IsActive = 'N',
|
|
User_UpdatedAt = NOW()
|
|
WHERE User_ID = ?",
|
|
array($userID)
|
|
);
|
|
if (!$updateUserQuery) {
|
|
$this->db_dashboard->trans_rollback();
|
|
$this->log_activity("REMOVE_USER", $username, $this->sys_input, "N", "gagal nonaktifkan user");
|
|
$this->sys_error_db("gagal nonaktifkan user", $this->db_dashboard);
|
|
return;
|
|
}
|
|
|
|
if ($this->db_dashboard->trans_status() === FALSE) {
|
|
$this->db_dashboard->trans_rollback();
|
|
$this->log_activity("REMOVE_USER", $username, $this->sys_input, "N", "transaction failed");
|
|
$this->sys_error("gagal remove user");
|
|
return;
|
|
}
|
|
|
|
$this->db_dashboard->trans_commit();
|
|
|
|
$this->log_activity("REMOVE_USER", $username, $this->sys_input, "Y", "success");
|
|
$this->sys_ok(array(
|
|
"message" => "user berhasil dinonaktifkan",
|
|
"username" => $username,
|
|
"removed_project_count" => count($mcuIDs)
|
|
));
|
|
}
|
|
|
|
public function search_project()
|
|
{
|
|
if (!$this->isLogin) {
|
|
$this->sys_error("Invalid Token");
|
|
return;
|
|
}
|
|
|
|
$keyword = $this->sanitize_text($this->get_input('search'), 100);
|
|
$keywordLike = "%" . $keyword . "%";
|
|
|
|
$sql = "SELECT
|
|
Mgm_McuID AS mcu_id,
|
|
Mgm_McuNumber AS project_number,
|
|
Mgm_McuLabel AS project_name
|
|
FROM cpone.mgm_mcu
|
|
WHERE Mgm_McuIsActive = 'Y'
|
|
AND (
|
|
Mgm_McuNumber LIKE ?
|
|
OR Mgm_McuLabel LIKE ?
|
|
)
|
|
ORDER BY Mgm_McuID DESC
|
|
LIMIT 20";
|
|
|
|
$query = $this->db_dashboard->query($sql, array($keywordLike, $keywordLike));
|
|
if (!$query) {
|
|
$this->sys_error_db("gagal search project", $this->db_dashboard);
|
|
return;
|
|
}
|
|
|
|
$this->sys_ok(array(
|
|
"records" => $query->result_array()
|
|
));
|
|
}
|
|
|
|
public function search()
|
|
{
|
|
if (!$this->isLogin) {
|
|
$this->sys_error("Invalid Token");
|
|
return;
|
|
}
|
|
|
|
$username = $this->sanitize_text($this->get_input('username'), 50);
|
|
$project = $this->sanitize_text($this->get_input('project'), 20);
|
|
$page = intval($this->get_input('page'));
|
|
$limit = intval($this->get_input('limit'));
|
|
|
|
if ($page <= 0) {
|
|
$page = 1;
|
|
}
|
|
if ($limit <= 0) {
|
|
$limit = 20;
|
|
}
|
|
if ($limit > 100) {
|
|
$limit = 100;
|
|
}
|
|
|
|
$offset = ($page - 1) * $limit;
|
|
$usernameLike = "%" . $username . "%";
|
|
$projectID = 0;
|
|
if ($project !== '' && strtolower($project) !== 'all') {
|
|
$projectID = intval($project);
|
|
}
|
|
|
|
$whereProject = "";
|
|
$paramsCount = array($usernameLike);
|
|
$paramsData = array($usernameLike);
|
|
if ($projectID > 0) {
|
|
$whereProject = " AND up.UserProj_McuID = ? ";
|
|
$paramsCount[] = $projectID;
|
|
$paramsData[] = $projectID;
|
|
}
|
|
|
|
$sqlCount = "SELECT COUNT(DISTINCT u.User_ID) AS total_rows
|
|
FROM cpone_dashboard.dashboard_user u
|
|
LEFT JOIN cpone_dashboard.dashboard_user_project up
|
|
ON up.UserProj_UserID = u.User_ID
|
|
AND up.UserProj_IsActive = 'Y'
|
|
WHERE u.User_IsActive = 'Y'
|
|
AND u.User_Username LIKE ? " . $whereProject;
|
|
|
|
$countQuery = $this->db_dashboard->query($sqlCount, $paramsCount);
|
|
if (!$countQuery) {
|
|
$this->sys_error_db("gagal hitung data user", $this->db_dashboard);
|
|
return;
|
|
}
|
|
$totalRows = intval($countQuery->row()->total_rows);
|
|
$totalPages = $totalRows > 0 ? intval(ceil($totalRows / $limit)) : 0;
|
|
|
|
$sqlData = "SELECT
|
|
u.User_ID,
|
|
u.User_Username,
|
|
u.User_DisplayName,
|
|
u.User_IsActive,
|
|
u.User_CreatedAt,
|
|
u.User_UpdatedAt,
|
|
GROUP_CONCAT(
|
|
DISTINCT CONCAT(
|
|
up.UserProj_McuID, '|',
|
|
IFNULL(m.Mgm_McuNumber, ''), '|',
|
|
IFNULL(m.Mgm_McuLabel, '')
|
|
)
|
|
ORDER BY up.UserProj_McuID DESC
|
|
SEPARATOR '||'
|
|
) AS project_list
|
|
FROM cpone_dashboard.dashboard_user u
|
|
LEFT JOIN cpone_dashboard.dashboard_user_project up
|
|
ON up.UserProj_UserID = u.User_ID
|
|
AND up.UserProj_IsActive = 'Y'
|
|
LEFT JOIN cpone.mgm_mcu m
|
|
ON m.Mgm_McuID = up.UserProj_McuID
|
|
WHERE u.User_IsActive = 'Y'
|
|
AND u.User_Username LIKE ? " . $whereProject . "
|
|
GROUP BY
|
|
u.User_ID,
|
|
u.User_Username,
|
|
u.User_DisplayName,
|
|
u.User_IsActive,
|
|
u.User_CreatedAt,
|
|
u.User_UpdatedAt
|
|
ORDER BY u.User_ID DESC
|
|
LIMIT ? OFFSET ?";
|
|
|
|
$paramsData[] = $limit;
|
|
$paramsData[] = $offset;
|
|
|
|
$dataQuery = $this->db_dashboard->query($sqlData, $paramsData);
|
|
if (!$dataQuery) {
|
|
$this->sys_error_db("gagal ambil data user", $this->db_dashboard);
|
|
return;
|
|
}
|
|
|
|
$rows = $dataQuery->result_array();
|
|
foreach ($rows as &$row) {
|
|
$row['projects'] = array();
|
|
if (!empty($row['project_list'])) {
|
|
$items = explode("||", $row['project_list']);
|
|
foreach ($items as $item) {
|
|
$parts = explode("|", $item);
|
|
$row['projects'][] = array(
|
|
"mcu_id" => isset($parts[0]) ? intval($parts[0]) : 0,
|
|
"project_number" => isset($parts[1]) ? $parts[1] : "",
|
|
"project_name" => isset($parts[2]) ? $parts[2] : ""
|
|
);
|
|
}
|
|
}
|
|
unset($row['project_list']);
|
|
}
|
|
unset($row);
|
|
|
|
$this->sys_ok(array(
|
|
"pagination" => array(
|
|
"page" => $page,
|
|
"limit" => $limit,
|
|
"total_rows" => $totalRows,
|
|
"total_pages" => $totalPages
|
|
),
|
|
"filters" => array(
|
|
"username" => $username,
|
|
"project" => $project === '' ? 'all' : $project
|
|
),
|
|
"records" => $rows
|
|
));
|
|
}
|
|
|
|
private function log_activity($action, $target, $payload, $isSuccess, $message)
|
|
{
|
|
$actorUserID = isset($this->sys_user["M_UserID"]) ? intval($this->sys_user["M_UserID"]) : 0;
|
|
$actorUsername = isset($this->sys_user["M_UserUsername"]) ? $this->sys_user["M_UserUsername"] : "";
|
|
$actorEmail = isset($this->sys_user["M_UserEmail"]) ? $this->sys_user["M_UserEmail"] : "";
|
|
|
|
$sql = "INSERT INTO cpone_log.dashboard_user_activity_log (
|
|
DashboardUserActivityLogAction,
|
|
DashboardUserActivityLogTarget,
|
|
DashboardUserActivityLogPayloadJson,
|
|
DashboardUserActivityLogIsSuccess,
|
|
DashboardUserActivityLogMessage,
|
|
DashboardUserActivityLogActorUserID,
|
|
DashboardUserActivityLogActorUsername,
|
|
DashboardUserActivityLogActorEmail,
|
|
DashboardUserActivityLogCreatedAt
|
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, NOW())";
|
|
|
|
$safePayload = $this->mask_sensitive_payload($payload);
|
|
$payloadJson = json_encode($safePayload);
|
|
if ($payloadJson === false) {
|
|
$payloadJson = "{}";
|
|
}
|
|
|
|
$this->db_log->query($sql, array(
|
|
$this->sanitize_text($action, 50),
|
|
$this->sanitize_text($target, 100),
|
|
$payloadJson,
|
|
$isSuccess === "Y" ? "Y" : "N",
|
|
$this->sanitize_text($message, 255),
|
|
$actorUserID,
|
|
$this->sanitize_text($actorUsername, 100),
|
|
$this->sanitize_text($actorEmail, 150)
|
|
));
|
|
}
|
|
|
|
private function mask_sensitive_payload($payload)
|
|
{
|
|
if (!is_array($payload)) {
|
|
return $payload;
|
|
}
|
|
|
|
$sensitiveKeys = array(
|
|
'password',
|
|
'new_password',
|
|
'old_password',
|
|
'pass',
|
|
'passwd'
|
|
);
|
|
|
|
foreach ($payload as $key => $value) {
|
|
$lowerKey = strtolower((string) $key);
|
|
if (in_array($lowerKey, $sensitiveKeys, true)) {
|
|
$payload[$key] = hash('sha256', (string) $value);
|
|
continue;
|
|
}
|
|
|
|
if (is_array($value)) {
|
|
$payload[$key] = $this->mask_sensitive_payload($value);
|
|
}
|
|
}
|
|
|
|
return $payload;
|
|
}
|
|
|
|
private function get_input($key)
|
|
{
|
|
return isset($this->sys_input[$key]) ? $this->sys_input[$key] : "";
|
|
}
|
|
|
|
private function sanitize_username($value)
|
|
{
|
|
$value = trim((string) $value);
|
|
$value = preg_replace('/[^a-zA-Z0-9._-]/', '', $value);
|
|
return substr($value, 0, 50);
|
|
}
|
|
|
|
private function sanitize_text($value, $maxLen = 255)
|
|
{
|
|
$value = trim((string) $value);
|
|
$value = strip_tags($value);
|
|
if (strlen($value) > $maxLen) {
|
|
$value = substr($value, 0, $maxLen);
|
|
}
|
|
return $value;
|
|
}
|
|
|
|
private function is_valid_password_policy($password)
|
|
{
|
|
if (!is_string($password)) {
|
|
return false;
|
|
}
|
|
|
|
if (strlen($password) < 8) {
|
|
return false;
|
|
}
|
|
|
|
$hasUpper = preg_match('/[A-Z]/', $password) === 1;
|
|
$hasLower = preg_match('/[a-z]/', $password) === 1;
|
|
$hasNumber = preg_match('/[0-9]/', $password) === 1;
|
|
$hasSymbol = preg_match('/[^a-zA-Z0-9]/', $password) === 1;
|
|
|
|
return $hasUpper && $hasLower && $hasNumber && $hasSymbol;
|
|
}
|
|
}
|