update controllers logic

This commit is contained in:
root
2026-04-23 00:04:35 -04:00
parent 1977a513df
commit ca4ba272fc
353 changed files with 13402 additions and 1301 deletions
@@ -0,0 +1,111 @@
<?php
namespace App\Http\Controllers\Api\Parents;
use App\Http\Controllers\Controller;
use App\Services\Parents\AuthorizedUsersManagementService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Validator;
/**
* Public invite confirmation & password setup for authorized users.
*/
class AuthorizedUserInviteController extends Controller
{
public function __construct(
private AuthorizedUsersManagementService $svc,
) {}
public function confirm(Request $request): RedirectResponse|JsonResponse
{
$token = (string) ($request->query('token') ?? '');
try {
$result = $this->svc->confirmEmailClick($token);
} catch (\InvalidArgumentException $e) {
if ($request->expectsJson()) {
return response()->json(['message' => $e->getMessage()], 400);
}
return response(
'<!DOCTYPE html><html><head><meta charset="utf-8"></head><body style="font-family:sans-serif;padding:24px;">'
.'<p>'.e($e->getMessage()).'</p></body></html>',
400,
['Content-Type' => 'text/html; charset=UTF-8'],
);
}
if ($request->expectsJson()) {
return response()->json([
'message' => 'Confirmed.',
'redirect_url' => $result['redirect_url'],
]);
}
return redirect()->away($result['redirect_url']);
}
public function setPasswordForm(Request $request, int $authorizedUserId): JsonResponse|Response
{
$token = (string) ($request->query('token') ?? '');
$row = $this->svc->findActiveSetupRow($authorizedUserId, $token);
if (! $row) {
if ($request->expectsJson()) {
return response()->json(['message' => 'Invalid or expired confirmation link.'], 400);
}
return response('Invalid or expired confirmation link.', 400);
}
if ($request->expectsJson()) {
return response()->json([
'message' => 'OK',
'user_id' => $authorizedUserId,
'token' => $token,
]);
}
return response(
'<!DOCTYPE html><html><head><meta charset="utf-8"><title>Set password</title></head>'
.'<body><p>Set your password using the client app or API POST to this URL with JSON body.</p></body></html>',
200,
['Content-Type' => 'text/html; charset=UTF-8'],
);
}
public function savePassword(Request $request, int $authorizedUserId): JsonResponse
{
$validator = Validator::make($request->all(), [
'password' => ['required', 'string', 'min:8', 'regex:/[A-Z]/', 'regex:/[a-z]/', 'regex:/[0-9]/', 'regex:/[\W_]/'],
'password_confirm' => ['required', 'same:password'],
'user_id' => ['required', 'integer'],
'token' => ['required', 'string'],
], [
'password.regex' => 'Password must include uppercase, lowercase, number, and special character.',
]);
if ($validator->fails()) {
return response()->json([
'message' => 'Validation failed.',
'errors' => $validator->errors(),
], 422);
}
$data = $validator->validated();
try {
$this->svc->setAuthorizedUserPassword(
$authorizedUserId,
(int) $data['user_id'],
(string) $data['token'],
(string) $data['password'],
);
} catch (\InvalidArgumentException $e) {
return response()->json(['message' => $e->getMessage()], 400);
}
return response()->json(['message' => 'Password has been successfully set.']);
}
}
@@ -0,0 +1,141 @@
<?php
namespace App\Http\Controllers\Api\Parents;
use App\Http\Controllers\Api\Core\BaseApiController;
use App\Http\Requests\Parents\StoreAuthorizedUserRequest;
use App\Http\Requests\Parents\UpdateAuthorizedUserRequest;
use App\Models\AuthorizedUser;
use App\Services\Parents\AuthorizedUsersManagementService;
use Illuminate\Http\JsonResponse;
use Symfony\Component\HttpFoundation\Response;
/**
* Parent CRUD for secondary authorized users on their account (JWT parent role).
*/
class AuthorizedUsersController extends BaseApiController
{
public function __construct(
private AuthorizedUsersManagementService $svc,
) {
parent::__construct();
}
public function index(): JsonResponse
{
$guard = $this->guardJsonOrUnauthorized();
if ($guard instanceof JsonResponse) {
return $guard;
}
$rows = AuthorizedUser::query()
->where('user_id', $guard)
->orderBy('id')
->get();
return $this->success($rows);
}
public function show(int $id): JsonResponse
{
$guard = $this->guardJsonOrUnauthorized();
if ($guard instanceof JsonResponse) {
return $guard;
}
$resolution = $this->authorizedUserForParent($id, $guard);
if ($resolution instanceof JsonResponse) {
return $resolution;
}
return $this->success($resolution);
}
public function store(StoreAuthorizedUserRequest $request): JsonResponse
{
$guard = $this->guardJsonOrUnauthorized();
if ($guard instanceof JsonResponse) {
return $guard;
}
$email = strtolower($request->validated('email'));
$result = $this->svc->inviteByEmail($guard, $email);
$message = 'Authorized user added. A confirmation email has been sent.';
if (! $result['created']) {
return $this->success(['message' => $message], $message, Response::HTTP_CREATED);
}
return $this->success(
['message' => $message, 'id' => $result['record']->id],
$message,
Response::HTTP_CREATED
);
}
public function update(UpdateAuthorizedUserRequest $request, int $id): JsonResponse
{
$guard = $this->guardJsonOrUnauthorized();
if ($guard instanceof JsonResponse) {
return $guard;
}
$resolution = $this->authorizedUserForParent($id, $guard);
if ($resolution instanceof JsonResponse) {
return $resolution;
}
/** @var AuthorizedUser $row */
$row = $resolution;
$email = $request->validated('email') ?? null;
if (is_string($email) && $email !== '') {
$row->email = strtolower($email);
}
$row->save();
return $this->success(['message' => 'Authorized user information updated.'], 'Authorized user information updated.');
}
public function destroy(int $id): JsonResponse
{
$guard = $this->guardJsonOrUnauthorized();
if ($guard instanceof JsonResponse) {
return $guard;
}
$resolution = $this->authorizedUserForParent($id, $guard);
if ($resolution instanceof JsonResponse) {
return $resolution;
}
$resolution->delete();
return $this->success(['message' => 'Authorized user deleted successfully.'], 'Authorized user deleted successfully.');
}
private function guardJsonOrUnauthorized(): int|JsonResponse
{
$parentId = (int) (auth()->id() ?? 0);
if ($parentId <= 0) {
return $this->error('Authentication required.', Response::HTTP_UNAUTHORIZED);
}
return $parentId;
}
private function authorizedUserForParent(int $id, int $parentId): AuthorizedUser|JsonResponse
{
$row = AuthorizedUser::query()->find($id);
if (! $row) {
return $this->error('Authorized user not found.', Response::HTTP_NOT_FOUND);
}
if ((int) $row->user_id !== $parentId) {
return $this->error('You do not have access to this resource.', Response::HTTP_FORBIDDEN);
}
return $row;
}
}
@@ -2,7 +2,7 @@
namespace App\Http\Controllers\Api\Parents;
use App\Http\Controllers\Api\BaseApiController;
use App\Http\Controllers\Api\Core\BaseApiController;
use App\Http\Requests\Parents\ParentAttendanceReportSubmitRequest;
use App\Http\Requests\Parents\ParentAttendanceReportListRequest;
use App\Http\Requests\Parents\ParentAttendanceReportCheckRequest;
@@ -20,12 +20,12 @@ class ParentAttendanceReportController extends BaseApiController
public function form(): JsonResponse
{
$parentId = (int) (auth()->id() ?? 0);
if ($parentId <= 0) {
return response()->json(['ok' => false, 'message' => 'Unauthorized.'], 401);
$guard = $this->parentIdOrUnauthorized();
if ($guard instanceof JsonResponse) {
return $guard;
}
$data = $this->reportService->formData($parentId);
$data = $this->reportService->formData($guard);
return response()->json([
'ok' => true,
@@ -40,13 +40,13 @@ class ParentAttendanceReportController extends BaseApiController
public function submit(ParentAttendanceReportSubmitRequest $request): JsonResponse
{
$parentId = (int) (auth()->id() ?? 0);
if ($parentId <= 0) {
return response()->json(['ok' => false, 'message' => 'Unauthorized.'], 401);
$guard = $this->parentIdOrUnauthorized();
if ($guard instanceof JsonResponse) {
return $guard;
}
try {
$result = $this->reportService->submit($parentId, $request->validated());
$result = $this->reportService->submit($guard, $request->validated());
} catch (\RuntimeException $e) {
return response()->json(['ok' => false, 'message' => $e->getMessage()], 422);
}
@@ -62,13 +62,18 @@ class ParentAttendanceReportController extends BaseApiController
public function list(ParentAttendanceReportListRequest $request): JsonResponse
{
$guard = $this->parentIdOrUnauthorized();
if ($guard instanceof JsonResponse) {
return $guard;
}
$payload = $request->validated();
$start = $payload['start'] ?? now()->toDateString();
$end = $payload['end'] ?? null;
$schoolYear = $payload['school_year'] ?? null;
$semester = $payload['semester'] ?? null;
$rows = $this->reportService->listReports($start, $end, $schoolYear, $semester);
$rows = $this->reportService->listReports($start, $end, $schoolYear, $semester, $guard);
return response()->json([
'ok' => true,
@@ -78,8 +83,13 @@ class ParentAttendanceReportController extends BaseApiController
public function checkExisting(ParentAttendanceReportCheckRequest $request): JsonResponse
{
$guard = $this->parentIdOrUnauthorized();
if ($guard instanceof JsonResponse) {
return $guard;
}
try {
$rows = $this->reportService->checkExisting($request->validated());
$rows = $this->reportService->checkExisting($guard, $request->validated());
} catch (\RuntimeException $e) {
return response()->json(['ok' => false, 'message' => $e->getMessage()], 422);
}
@@ -92,17 +102,30 @@ class ParentAttendanceReportController extends BaseApiController
public function update(ParentAttendanceReportUpdateRequest $request, int $reportId): JsonResponse
{
$parentId = (int) (auth()->id() ?? 0);
if ($parentId <= 0) {
return response()->json(['ok' => false, 'message' => 'Unauthorized.'], 401);
$guard = $this->parentIdOrUnauthorized();
if ($guard instanceof JsonResponse) {
return $guard;
}
try {
$this->reportService->updateReport($parentId, $reportId, $request->validated());
$this->reportService->updateReport($guard, $reportId, $request->validated());
} catch (\RuntimeException $e) {
return response()->json(['ok' => false, 'message' => $e->getMessage()], 422);
}
return response()->json(['ok' => true]);
}
/**
* @return int|JsonResponse
*/
private function parentIdOrUnauthorized(): int|JsonResponse
{
$parentId = (int) (auth()->id() ?? 0);
if ($parentId <= 0) {
return response()->json(['ok' => false, 'message' => 'Unauthorized.'], 401);
}
return $parentId;
}
}
@@ -2,7 +2,7 @@
namespace App\Http\Controllers\Api\Parents;
use App\Http\Controllers\Api\BaseApiController;
use App\Http\Controllers\Api\Core\BaseApiController;
use App\Http\Requests\Parents\ParentAttendanceRequest;
use App\Http\Requests\Parents\ParentEnrollmentActionRequest;
use App\Http\Requests\Parents\ParentEnrollmentRequest;
@@ -41,12 +41,12 @@ class ParentController extends BaseApiController
public function attendance(ParentAttendanceRequest $request): JsonResponse
{
$parentId = (int) (auth()->id() ?? 0);
if ($parentId <= 0) {
return response()->json(['ok' => false, 'message' => 'Unauthorized.'], 401);
$guard = $this->parentIdOrUnauthorized();
if ($guard instanceof JsonResponse) {
return $guard;
}
$data = $this->attendanceService->listAttendance($parentId, $request->validated()['school_year'] ?? null);
$data = $this->attendanceService->listAttendance($guard, $request->validated()['school_year'] ?? null);
return response()->json([
'ok' => true,
@@ -58,13 +58,13 @@ class ParentController extends BaseApiController
public function invoices(ParentInvoiceRequest $request): JsonResponse
{
$parentId = (int) (auth()->id() ?? 0);
if ($parentId <= 0) {
return response()->json(['ok' => false, 'message' => 'Unauthorized.'], 401);
$guard = $this->parentIdOrUnauthorized();
if ($guard instanceof JsonResponse) {
return $guard;
}
$schoolYear = $request->validated()['school_year'] ?? null;
$rows = $this->invoiceService->listInvoices($parentId, $schoolYear);
$rows = $this->invoiceService->listInvoices($guard, $schoolYear);
return response()->json([
'ok' => true,
@@ -74,12 +74,12 @@ class ParentController extends BaseApiController
public function enrollments(ParentEnrollmentRequest $request): JsonResponse
{
$parentId = (int) (auth()->id() ?? 0);
if ($parentId <= 0) {
return response()->json(['ok' => false, 'message' => 'Unauthorized.'], 401);
$guard = $this->parentIdOrUnauthorized();
if ($guard instanceof JsonResponse) {
return $guard;
}
$data = $this->enrollmentService->overview($parentId, $request->validated()['school_year'] ?? null);
$data = $this->enrollmentService->overview($guard, $request->validated()['school_year'] ?? null);
return response()->json([
'ok' => true,
@@ -94,14 +94,14 @@ class ParentController extends BaseApiController
public function updateEnrollments(ParentEnrollmentActionRequest $request): JsonResponse
{
$parentId = (int) (auth()->id() ?? 0);
if ($parentId <= 0) {
return response()->json(['ok' => false, 'message' => 'Unauthorized.'], 401);
$guard = $this->parentIdOrUnauthorized();
if ($guard instanceof JsonResponse) {
return $guard;
}
$payload = $request->validated();
$result = $this->enrollmentService->updateEnrollment(
$parentId,
$guard,
$payload['enroll'] ?? [],
$payload['withdraw'] ?? []
);
@@ -115,12 +115,12 @@ class ParentController extends BaseApiController
public function registration(): JsonResponse
{
$parentId = (int) (auth()->id() ?? 0);
if ($parentId <= 0) {
return response()->json(['ok' => false, 'message' => 'Unauthorized.'], 401);
$guard = $this->parentIdOrUnauthorized();
if ($guard instanceof JsonResponse) {
return $guard;
}
$data = $this->registrationService->overview($parentId);
$data = $this->registrationService->overview($guard);
return response()->json([
'ok' => true,
@@ -136,14 +136,14 @@ class ParentController extends BaseApiController
public function storeRegistration(ParentRegistrationRequest $request): JsonResponse
{
$parentId = (int) (auth()->id() ?? 0);
if ($parentId <= 0) {
return response()->json(['ok' => false, 'message' => 'Unauthorized.'], 401);
$guard = $this->parentIdOrUnauthorized();
if ($guard instanceof JsonResponse) {
return $guard;
}
$payload = $request->validated();
$result = $this->registrationService->register(
$parentId,
$guard,
$payload['students'] ?? [],
$payload['emergency_contacts'] ?? []
);
@@ -156,36 +156,36 @@ class ParentController extends BaseApiController
public function updateStudent(ParentStudentUpdateRequest $request, int $studentId): JsonResponse
{
$parentId = (int) (auth()->id() ?? 0);
if ($parentId <= 0) {
return response()->json(['ok' => false, 'message' => 'Unauthorized.'], 401);
$guard = $this->parentIdOrUnauthorized();
if ($guard instanceof JsonResponse) {
return $guard;
}
$this->registrationService->updateStudent($parentId, $studentId, $request->validated());
$this->registrationService->updateStudent($guard, $studentId, $request->validated());
return response()->json(['ok' => true]);
}
public function deleteStudent(int $studentId): JsonResponse
{
$parentId = (int) (auth()->id() ?? 0);
if ($parentId <= 0) {
return response()->json(['ok' => false, 'message' => 'Unauthorized.'], 401);
$guard = $this->parentIdOrUnauthorized();
if ($guard instanceof JsonResponse) {
return $guard;
}
$this->registrationService->deleteStudent($parentId, $studentId);
$this->registrationService->deleteStudent($guard, $studentId);
return response()->json(['ok' => true]);
}
public function emergencyContacts(): JsonResponse
{
$parentId = (int) (auth()->id() ?? 0);
if ($parentId <= 0) {
return response()->json(['ok' => false, 'message' => 'Unauthorized.'], 401);
$guard = $this->parentIdOrUnauthorized();
if ($guard instanceof JsonResponse) {
return $guard;
}
$rows = $this->emergencyContactService->list($parentId);
$rows = $this->emergencyContactService->list($guard);
return response()->json([
'ok' => true,
@@ -195,12 +195,12 @@ class ParentController extends BaseApiController
public function storeEmergencyContact(ParentEmergencyContactRequest $request): JsonResponse
{
$parentId = (int) (auth()->id() ?? 0);
if ($parentId <= 0) {
return response()->json(['ok' => false, 'message' => 'Unauthorized.'], 401);
$guard = $this->parentIdOrUnauthorized();
if ($guard instanceof JsonResponse) {
return $guard;
}
$contact = $this->emergencyContactService->store($parentId, $request->validated());
$contact = $this->emergencyContactService->store($guard, $request->validated());
return response()->json([
'ok' => true,
@@ -210,12 +210,12 @@ class ParentController extends BaseApiController
public function updateEmergencyContact(ParentEmergencyContactRequest $request, int $contactId): JsonResponse
{
$parentId = (int) (auth()->id() ?? 0);
if ($parentId <= 0) {
return response()->json(['ok' => false, 'message' => 'Unauthorized.'], 401);
$guard = $this->parentIdOrUnauthorized();
if ($guard instanceof JsonResponse) {
return $guard;
}
$contact = $this->emergencyContactService->update($parentId, $contactId, $request->validated());
$contact = $this->emergencyContactService->update($guard, $contactId, $request->validated());
return response()->json([
'ok' => true,
@@ -225,12 +225,12 @@ class ParentController extends BaseApiController
public function profile(): JsonResponse
{
$parentId = (int) (auth()->id() ?? 0);
if ($parentId <= 0) {
return response()->json(['ok' => false, 'message' => 'Unauthorized.'], 401);
$guard = $this->parentIdOrUnauthorized();
if ($guard instanceof JsonResponse) {
return $guard;
}
$profile = $this->profileService->getProfile($parentId);
$profile = $this->profileService->getProfile($guard);
return response()->json([
'ok' => true,
@@ -240,12 +240,12 @@ class ParentController extends BaseApiController
public function updateProfile(ParentProfileUpdateRequest $request): JsonResponse
{
$parentId = (int) (auth()->id() ?? 0);
if ($parentId <= 0) {
return response()->json(['ok' => false, 'message' => 'Unauthorized.'], 401);
$guard = $this->parentIdOrUnauthorized();
if ($guard instanceof JsonResponse) {
return $guard;
}
$profile = $this->profileService->updateProfile($parentId, $request->validated());
$profile = $this->profileService->updateProfile($guard, $request->validated());
return response()->json([
'ok' => true,
@@ -255,12 +255,12 @@ class ParentController extends BaseApiController
public function events(): JsonResponse
{
$parentId = (int) (auth()->id() ?? 0);
if ($parentId <= 0) {
return response()->json(['ok' => false, 'message' => 'Unauthorized.'], 401);
$guard = $this->parentIdOrUnauthorized();
if ($guard instanceof JsonResponse) {
return $guard;
}
$data = $this->eventService->overview($parentId);
$data = $this->eventService->overview($guard);
return response()->json([
'ok' => true,
@@ -271,14 +271,27 @@ class ParentController extends BaseApiController
}
public function updateParticipation(ParentEventParticipationRequest $request): JsonResponse
{
$guard = $this->parentIdOrUnauthorized();
if ($guard instanceof JsonResponse) {
return $guard;
}
$this->eventService->updateParticipation($guard, $request->validated()['participation'] ?? []);
return response()->json(['ok' => true]);
}
/**
* @return int|JsonResponse Authenticated parent user id, or 401 JSON for this controller's legacy `{ ok }` shape.
*/
private function parentIdOrUnauthorized(): int|JsonResponse
{
$parentId = (int) (auth()->id() ?? 0);
if ($parentId <= 0) {
return response()->json(['ok' => false, 'message' => 'Unauthorized.'], 401);
}
$this->eventService->updateParticipation($parentId, $request->validated()['participation'] ?? []);
return response()->json(['ok' => true]);
return $parentId;
}
}