authorizedUsers = new AuthorizedUser(); $this->user = model(User::class); } public function index(): JsonResponse { $userId = $this->getCurrentUserId(); if (!$userId) { return $this->respondError('Unauthorized', Response::HTTP_UNAUTHORIZED); } $users = $this->authorizedUsers->newQuery() ->where('user_id', $userId) ->orderBy('created_at', 'DESC') ->get() ->toArray(); return $this->success($users, 'Authorized users retrieved successfully'); } public function show($id = null): JsonResponse { $userId = $this->getCurrentUserId(); if (!$userId) { return $this->respondError('Unauthorized', Response::HTTP_UNAUTHORIZED); } $record = $this->authorizedUsers->newQuery() ->where('user_id', $userId) ->where('id', $id) ->first(); if (!$record) { return $this->respondError('Authorized user not found', Response::HTTP_NOT_FOUND); } return $this->success($record, 'Authorized user retrieved successfully'); } public function store(): JsonResponse { $payload = $this->payloadData(); $rules = [ 'email' => 'required|valid_email', ]; $errors = $this->validateRequest($payload, $rules); if (!empty($errors)) { return $this->respondValidationError($errors); } $email = strtolower(trim($payload['email'])); $user = $this->user->where('email', $email)->first(); if (!$user) { return $this->respondError('No user found with this email.', Response::HTTP_NOT_FOUND); } $mainUserId = $this->getCurrentUserId(); if (!$mainUserId) { return $this->respondError('Unauthorized', Response::HTTP_UNAUTHORIZED); } $existing = $this->authorizedUsers->newQuery() ->where('user_id', $mainUserId) ->where('authorized_user_id', $user['id']) ->first(); if ($existing) { return $this->respondError('This user is already authorized.', Response::HTTP_CONFLICT); } $token = bin2hex(random_bytes(48)); $record = $this->authorizedUsers->newQuery()->create([ 'user_id' => $mainUserId, 'authorized_user_id' => $user['id'], 'firstname' => $user['firstname'] ?? null, 'lastname' => $user['lastname'] ?? null, 'email' => $email, 'token' => $token, 'status' => 'Pending', ]); $this->sendAuthorizedUserConfirmationEmail($email, $token); return $this->respondCreated([ 'id' => $record->id, 'message' => 'Authorized user added. A confirmation email has been sent.', ]); } public function update($id = null): JsonResponse { $mainUserId = $this->getCurrentUserId(); if (!$mainUserId) { return $this->respondError('Unauthorized', Response::HTTP_UNAUTHORIZED); } $record = $this->authorizedUsers->newQuery() ->where('user_id', $mainUserId) ->where('id', $id) ->first(); if (!$record) { return $this->respondError('Authorized user not found', Response::HTTP_NOT_FOUND); } $payload = $this->payloadData(); $rules = ['email' => 'permit_empty|valid_email']; $errors = $this->validateRequest($payload, $rules); if (!empty($errors)) { return $this->respondValidationError($errors); } if (!empty($payload['email'])) { $record->email = strtolower(trim($payload['email'])); } $record->save(); return $this->success($record->fresh(), 'Authorized user updated successfully'); } public function destroy($id = null): JsonResponse { $mainUserId = $this->getCurrentUserId(); if (!$mainUserId) { return $this->respondError('Unauthorized', Response::HTTP_UNAUTHORIZED); } $record = $this->authorizedUsers->newQuery() ->where('user_id', $mainUserId) ->where('id', $id) ->first(); if (!$record) { return $this->respondError('Authorized user not found', Response::HTTP_NOT_FOUND); } $record->delete(); return $this->respondDeleted(null, 'Authorized user deleted successfully'); } public function confirm(): JsonResponse { $payload = $this->payloadData(); $token = (string) ($payload['token'] ?? $this->request->get('token') ?? ''); if ($token === '') { return $this->respondError('Invalid confirmation token.', Response::HTTP_BAD_REQUEST); } $record = $this->authorizedUsers->newQuery() ->where('token', $token) ->first(); if (!$record) { return $this->respondError('Invalid or expired confirmation token.', Response::HTTP_BAD_REQUEST); } $record->status = 'Active'; $record->token = null; $record->save(); return $this->success([ 'authorized_user_id' => $record->authorized_user_id, 'message' => 'Authorized user confirmed.', ]); } public function setPassword($authorizedUserId): JsonResponse { $user = $this->user->find($authorizedUserId); if (!$user) { return $this->respondError('User not found.', Response::HTTP_NOT_FOUND); } return $this->success([ 'user_id' => $authorizedUserId, 'email' => $user['email'] ?? null, ], 'Authorized user retrieved.'); } public function savePassword($authorizedUserId): JsonResponse { $payload = $this->payloadData(); $rules = [ 'password' => 'required|min_length[8]', 'password_confirm' => 'required|matches[password]', ]; $errors = $this->validateRequest($payload, $rules); if (!empty($errors)) { return $this->respondValidationError($errors); } $user = $this->user->find($authorizedUserId); if (!$user) { return $this->respondError('User not found.', Response::HTTP_NOT_FOUND); } $hashed = pbkdf2_hash($payload['password']); $this->user->update($authorizedUserId, ['password' => $hashed]); return $this->success(['message' => 'Password has been set.']); } private function sendAuthorizedUserConfirmationEmail(string $email, string $token): void { $confirmLink = url('/confirm_authorized_user?token=' . $token); try { $message = view('emails/authorized_user_confirmation', [ 'confirmLink' => $confirmLink, ], ['saveData' => false]); } catch (\Throwable $e) { $message = '
You have been added as an authorized user for another account.
' . '' . 'If you did not request this, please ignore this email.
'; } $mailer = new EmailController(); $subject = 'Authorized User Confirmation'; if ($mailer->sendEmail($email, $subject, $message)) { log_message('info', 'Authorized user confirmation email sent to ' . $email); } else { log_message('error', 'Failed to send authorized user confirmation email to ' . $email); } } }