233 lines
8.3 KiB
PHP
233 lines
8.3 KiB
PHP
<?php
|
|
|
|
namespace App\Modules\Auth\Controllers;
|
|
|
|
use App\Core\BaseApiController;
|
|
use App\Modules\Auth\Models\RoleModel;
|
|
use App\Modules\Auth\Models\UserModel;
|
|
use App\Modules\Auth\Models\UserRoleModel;
|
|
use CodeIgniter\HTTP\ResponseInterface;
|
|
|
|
/**
|
|
* User API (ADMIN only). List by role; create/update/delete users (for teachers).
|
|
*/
|
|
class UserController extends BaseApiController
|
|
{
|
|
/**
|
|
* GET /api/users?role=GURU_MAPEL
|
|
* Returns users with optional role filter. Response: [{ id, name, email }, ...]
|
|
*/
|
|
public function index(): ResponseInterface
|
|
{
|
|
$roleCode = $this->request->getGet('role');
|
|
if ($roleCode === null || $roleCode === '') {
|
|
return $this->errorResponse('Query parameter role is required', null, null, 422);
|
|
}
|
|
|
|
$roleModel = new RoleModel();
|
|
$role = $roleModel->findByCode((string) $roleCode);
|
|
if (!$role) {
|
|
return $this->successResponse([], 'Users');
|
|
}
|
|
|
|
$userRoleModel = new UserRoleModel();
|
|
$db = \Config\Database::connect();
|
|
$builder = $db->table('user_roles');
|
|
$builder->select('user_id');
|
|
$builder->where('role_id', $role->id);
|
|
$rows = $builder->get()->getResultArray();
|
|
$userIdList = array_values(array_unique(array_map(static fn ($r) => (int) $r['user_id'], $rows)));
|
|
if ($userIdList === []) {
|
|
return $this->successResponse([], 'Users');
|
|
}
|
|
|
|
$userModel = new UserModel();
|
|
$users = $userModel->whereIn('id', $userIdList)->findAll();
|
|
$data = [];
|
|
foreach ($users as $u) {
|
|
$data[] = [
|
|
'id' => (int) $u->id,
|
|
'name' => (string) $u->name,
|
|
'email' => (string) $u->email,
|
|
];
|
|
}
|
|
usort($data, static fn ($a, $b) => strcasecmp($a['name'], $b['name']));
|
|
|
|
return $this->successResponse($data, 'Users');
|
|
}
|
|
|
|
/**
|
|
* POST /api/users
|
|
* Body (baru): name, email, password, roles[] (isi: GURU_MAPEL dan/atau WALI_KELAS).
|
|
* Body (lama, tetap didukung): name, email, password, role_code.
|
|
*/
|
|
public function store(): ResponseInterface
|
|
{
|
|
$payload = $this->request->getJSON(true) ?? [];
|
|
$name = trim($payload['name'] ?? '');
|
|
$email = trim($payload['email'] ?? '');
|
|
$password = $payload['password'] ?? '';
|
|
$rolesInput = $payload['roles'] ?? null;
|
|
$roleCode = $payload['role_code'] ?? null; // fallback lama
|
|
|
|
if ($name === '' || $email === '' || $password === '') {
|
|
return $this->errorResponse('Name, email, and password are required', null, null, 422);
|
|
}
|
|
|
|
$roleModel = new RoleModel();
|
|
$allowedCodes = ['GURU_MAPEL', 'WALI_KELAS'];
|
|
|
|
// Normalisasi roles: jika roles[] tidak ada, pakai role_code tunggal (kompatibilitas lama)
|
|
$roleCodes = [];
|
|
if (is_array($rolesInput)) {
|
|
foreach ($rolesInput as $rc) {
|
|
$rc = (string) $rc;
|
|
if (in_array($rc, $allowedCodes, true)) {
|
|
$roleCodes[] = $rc;
|
|
}
|
|
}
|
|
$roleCodes = array_values(array_unique($roleCodes));
|
|
} elseif (is_string($roleCode) && $roleCode !== '') {
|
|
if (! in_array($roleCode, $allowedCodes, true)) {
|
|
return $this->errorResponse('role_code must be GURU_MAPEL or WALI_KELAS', null, null, 422);
|
|
}
|
|
$roleCodes = [$roleCode];
|
|
}
|
|
|
|
if ($roleCodes === []) {
|
|
return $this->errorResponse('At least one role (GURU_MAPEL or WALI_KELAS) is required', null, null, 422);
|
|
}
|
|
|
|
$userModel = new UserModel();
|
|
$existing = $userModel->findByEmail($email);
|
|
if ($existing) {
|
|
return $this->errorResponse('Email already registered', null, null, 422);
|
|
}
|
|
|
|
$userModel->skipValidation(false);
|
|
$id = $userModel->insert([
|
|
'name' => $name,
|
|
'email' => $email,
|
|
'password_hash' => password_hash($password, PASSWORD_DEFAULT),
|
|
'is_active' => 1,
|
|
]);
|
|
if ($id === false) {
|
|
return $this->errorResponse(implode(' ', $userModel->errors()), $userModel->errors(), null, 422);
|
|
}
|
|
|
|
$userRoleModel = new UserRoleModel();
|
|
foreach ($roleCodes as $code) {
|
|
$role = $roleModel->findByCode($code);
|
|
if ($role) {
|
|
$userRoleModel->insert(['user_id' => $id, 'role_id' => $role->id]);
|
|
}
|
|
}
|
|
|
|
$user = $userModel->find($id);
|
|
return $this->successResponse([
|
|
'id' => (int) $user->id,
|
|
'name' => (string) $user->name,
|
|
'email' => (string) $user->email,
|
|
], 'User created', null, ResponseInterface::HTTP_CREATED);
|
|
}
|
|
|
|
/**
|
|
* PUT /api/users/{id}
|
|
* Body (baru): name?, email?, password?, roles[] (GURU_MAPEL/WALI_KELAS)
|
|
* Body (lama, tetap didukung): role_code tunggal.
|
|
*/
|
|
public function update(int $id): ResponseInterface
|
|
{
|
|
$userModel = new UserModel();
|
|
$user = $userModel->find($id);
|
|
if (! $user) {
|
|
return $this->errorResponse('User not found', null, null, 404);
|
|
}
|
|
|
|
$payload = $this->request->getJSON(true) ?? [];
|
|
$data = [];
|
|
if (array_key_exists('name', $payload)) {
|
|
$data['name'] = trim($payload['name']);
|
|
}
|
|
if (array_key_exists('email', $payload)) {
|
|
$data['email'] = trim($payload['email']);
|
|
}
|
|
if (isset($payload['password']) && $payload['password'] !== '') {
|
|
$data['password_hash'] = password_hash($payload['password'], PASSWORD_DEFAULT);
|
|
}
|
|
|
|
if ($data !== []) {
|
|
$validation = \Config\Services::validation();
|
|
$rules = [
|
|
'name' => 'required|max_length[255]',
|
|
'email' => 'required|valid_email|max_length[255]|is_unique[users.email,id,' . $id . ']',
|
|
];
|
|
$toValidate = [
|
|
'name' => $data['name'] ?? $user->name,
|
|
'email' => $data['email'] ?? $user->email,
|
|
];
|
|
if (! $validation->setRules($rules)->run($toValidate)) {
|
|
return $this->errorResponse(implode(' ', $validation->getErrors()), $validation->getErrors(), null, 422);
|
|
}
|
|
$userModel->skipValidation(true);
|
|
$userModel->update($id, $data);
|
|
}
|
|
|
|
// Sinkronisasi roles
|
|
$rolesInput = $payload['roles'] ?? null;
|
|
$roleCode = $payload['role_code'] ?? null; // fallback lama
|
|
$allowedCodes = ['GURU_MAPEL', 'WALI_KELAS'];
|
|
|
|
$roleCodes = null;
|
|
if (is_array($rolesInput)) {
|
|
$roleCodes = [];
|
|
foreach ($rolesInput as $rc) {
|
|
$rc = (string) $rc;
|
|
if (in_array($rc, $allowedCodes, true)) {
|
|
$roleCodes[] = $rc;
|
|
}
|
|
}
|
|
$roleCodes = array_values(array_unique($roleCodes));
|
|
} elseif (isset($roleCode) && in_array($roleCode, $allowedCodes, true)) {
|
|
// kompatibilitas lama: satu role_code
|
|
$roleCodes = [$roleCode];
|
|
}
|
|
|
|
if (is_array($roleCodes)) {
|
|
$roleModel = new RoleModel();
|
|
$userRoleModel = new UserRoleModel();
|
|
$db = \Config\Database::connect();
|
|
|
|
// Hapus semua role sebelumnya, lalu insert sesuai request
|
|
$db->table('user_roles')->where('user_id', $id)->delete();
|
|
|
|
foreach ($roleCodes as $code) {
|
|
$role = $roleModel->findByCode($code);
|
|
if ($role) {
|
|
$userRoleModel->insert(['user_id' => $id, 'role_id' => $role->id]);
|
|
}
|
|
}
|
|
}
|
|
|
|
$updated = $userModel->find($id);
|
|
return $this->successResponse([
|
|
'id' => (int) $updated->id,
|
|
'name' => (string) $updated->name,
|
|
'email' => (string) $updated->email,
|
|
], 'User updated');
|
|
}
|
|
|
|
/**
|
|
* DELETE /api/users/{id}
|
|
*/
|
|
public function delete(int $id): ResponseInterface
|
|
{
|
|
$userModel = new UserModel();
|
|
if (! $userModel->find($id)) {
|
|
return $this->errorResponse('User not found', null, null, 404);
|
|
}
|
|
$userModel->delete($id);
|
|
return $this->successResponse(null, 'User deleted');
|
|
}
|
|
}
|