security fix and fix parent pages
API CI/CD / Validate (composer + pint) (push) Successful in 3m7s
API CI/CD / Test (PHPUnit) (push) Failing after 5m46s
API CI/CD / Build frontend assets (push) Successful in 1m2s
API CI/CD / Security audit (push) Failing after 49s
API CI/CD / Deploy to shared hosting (PHP) (push) Has been skipped

This commit is contained in:
root
2026-07-06 02:14:16 -04:00
parent 39228168c8
commit 90f9857b06
43 changed files with 4323 additions and 132 deletions
+17
View File
@@ -38,6 +38,10 @@ class ApiDocsAuth
return $this->deny('Unauthorized access to documentation.', 401);
}
if ($response = $this->denyUnavailableAccount($user)) {
return $response;
}
if (! $this->userIsAdmin((int) $user->id)) {
return $this->deny('Admin privileges required.', 403);
}
@@ -55,6 +59,19 @@ class ApiDocsAuth
->exists();
}
private function denyUnavailableAccount(object $user): ?Response
{
$status = strtolower(trim((string) ($user->status ?? '')));
$isVerified = filter_var($user->is_verified ?? false, FILTER_VALIDATE_BOOLEAN);
$isSuspended = filter_var($user->is_suspended ?? false, FILTER_VALIDATE_BOOLEAN);
if (! $isVerified || $status !== 'active' || $isSuspended) {
return response()->json(['message' => 'Account unavailable.'], 403);
}
return null;
}
private function deny(string $message, int $status): Response
{
return response()->json([
+17
View File
@@ -20,10 +20,27 @@ class ApiJwtAuth
}
Auth::setUser($user);
if ($response = $this->denyUnavailableAccount($user)) {
return $response;
}
} catch (JWTException $e) {
return response()->json(['status' => false, 'message' => 'Unauthorized.'], 401);
}
return $next($request);
}
private function denyUnavailableAccount(object $user): ?Response
{
$status = strtolower(trim((string) ($user->status ?? '')));
$isVerified = filter_var($user->is_verified ?? false, FILTER_VALIDATE_BOOLEAN);
$isSuspended = filter_var($user->is_suspended ?? false, FILTER_VALIDATE_BOOLEAN);
if (! $isVerified || $status !== 'active' || $isSuspended) {
return response()->json(['message' => 'Account unavailable.'], 403);
}
return null;
}
}
@@ -22,15 +22,6 @@ class EnsurePrintRequestsAdminAccess
return response()->json(['message' => 'Unauthorized.'], 401);
}
if (app()->runningUnitTests()) {
try {
if (Auth::guard('sanctum')->user()) {
return $next($request);
}
} catch (\InvalidArgumentException) {
}
}
$roles = $user->roles()
->pluck('roles.name')
->map(fn ($name) => strtolower((string) $name))
+25
View File
@@ -22,6 +22,10 @@ class MultiAuth
if ($sanctumUser) {
Auth::setUser($sanctumUser);
if ($response = $this->denyUnavailableAccount($sanctumUser)) {
return $response;
}
return $next($request);
}
@@ -29,6 +33,10 @@ class MultiAuth
if ($apiUser = Auth::guard('api')->user()) {
Auth::setUser($apiUser);
if ($response = $this->denyUnavailableAccount($apiUser)) {
return $response;
}
return $next($request);
}
} catch (\Throwable) {
@@ -41,6 +49,10 @@ class MultiAuth
if ($jwtUser) {
Auth::setUser($jwtUser);
if ($response = $this->denyUnavailableAccount($jwtUser)) {
return $response;
}
return $next($request);
}
} catch (JWTException $e) {
@@ -49,4 +61,17 @@ class MultiAuth
return response()->json(['message' => 'Unauthorized.'], 401);
}
private function denyUnavailableAccount(object $user): ?Response
{
$status = strtolower(trim((string) ($user->status ?? '')));
$isVerified = filter_var($user->is_verified ?? false, FILTER_VALIDATE_BOOLEAN);
$isSuspended = filter_var($user->is_suspended ?? false, FILTER_VALIDATE_BOOLEAN);
if (! $isVerified || $status !== 'active' || $isSuspended) {
return response()->json(['message' => 'Account unavailable.'], 403);
}
return null;
}
}
@@ -18,6 +18,15 @@ class RequirePermission
return response()->json(['status' => false, 'message' => 'Unauthorized.'], 401);
}
$user = $request->user();
$status = strtolower(trim((string) ($user->status ?? '')));
$isVerified = filter_var($user->is_verified ?? false, FILTER_VALIDATE_BOOLEAN);
$isSuspended = filter_var($user->is_suspended ?? false, FILTER_VALIDATE_BOOLEAN);
if (! $isVerified || $status !== 'active' || $isSuspended) {
return response()->json(['message' => 'Account unavailable.'], 403);
}
if (! $this->permissions->hasPermission($userId, $permission)) {
if ($request->expectsJson()) {
return response()->json(['status' => false, 'message' => 'Access denied.'], 403);
@@ -17,7 +17,12 @@ class TeacherPortalAuthenticate
public function handle(Request $request, Closure $next): Response
{
if (Auth::guard('web')->check()) {
Auth::setUser(Auth::guard('web')->user());
$user = Auth::guard('web')->user();
Auth::setUser($user);
if ($response = $this->denyUnavailableAccount($user)) {
return $response;
}
return $next($request);
}
@@ -30,6 +35,10 @@ class TeacherPortalAuthenticate
if ($sanctumUser) {
Auth::setUser($sanctumUser);
if ($response = $this->denyUnavailableAccount($sanctumUser)) {
return $response;
}
return $next($request);
}
@@ -40,6 +49,10 @@ class TeacherPortalAuthenticate
if ($jwtUser) {
Auth::setUser($jwtUser);
if ($response = $this->denyUnavailableAccount($jwtUser)) {
return $response;
}
return $next($request);
}
} catch (JWTException $e) {
@@ -49,4 +62,17 @@ class TeacherPortalAuthenticate
return response()->json(['message' => 'Unauthorized.'], 401);
}
private function denyUnavailableAccount(object $user): ?Response
{
$status = strtolower(trim((string) ($user->status ?? '')));
$isVerified = filter_var($user->is_verified ?? false, FILTER_VALIDATE_BOOLEAN);
$isSuspended = filter_var($user->is_suspended ?? false, FILTER_VALIDATE_BOOLEAN);
if (! $isVerified || $status !== 'active' || $isSuspended) {
return response()->json(['message' => 'Account unavailable.'], 403);
}
return null;
}
}