feat: implement barangay system phases 2-14
Complete adaptation from BukidBountyApp to Philippine barangay governance: - Barangay models: Resident, Household, HouseholdMember, Blotter, BlotterHearing, DocumentRequest, RequestPayment, RequestType, BarangayProject, BarangayBudget - Controllers: ResidentController, HouseholdController, BlotterController, BlotterHearingController, DocumentRequestController, RequestTypeController, ProjectController, BudgetController, QRPHController, AdminConsoleController, UserController, FileController, ChapterController, LoginController - Vue pages: Home, ManageResidents, ResidentProfile, ManageHouseholds, ManageBlotters, BlotterDetail, RequestDocument, ManageDocumentRequests, DocumentRequestDetail, ManageRequestTypes, ManageProjects, BudgetLedger, AdminConsole - Barangay roles: PunongBarangay, Kagawad, Secretary, Treasurer, SK, Tanod, BHW, Staff, Resident - UserPermissions matrix rewritten with barangay-specific permission mappings - VueRouteMap replaced with barangay SPA routes - UserActions enum references corrected across all controllers - Removed all market/cooperative/POS/subscription code and models
This commit is contained in:
184
app/Http/Controllers/Auth/LoginController.php
Normal file
184
app/Http/Controllers/Auth/LoginController.php
Normal file
@@ -0,0 +1,184 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Http\Controllers\Auth;
|
||||
|
||||
use Hypervel\Http\Request;
|
||||
use Hypervel\Support\Facades\Cache;
|
||||
use Hypervel\Support\Facades\Response;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Hypervel\Support\Facades\Auth;
|
||||
use App\Models\User;
|
||||
use Hypervel\Support\Facades\Hash;
|
||||
use Hypervel\Support\Facades\Log;
|
||||
|
||||
use Hypervel\Support\Facades\Redis;
|
||||
|
||||
class LoginController
|
||||
{
|
||||
public function authenticate(Request $request): ResponseInterface
|
||||
{
|
||||
$credentials = $request->inputs(['mobile_number', 'password']);
|
||||
$keepalive = $request->input('keepalive');
|
||||
|
||||
if (!$credentials['mobile_number'] || !$credentials['password']) {
|
||||
return Response::json([
|
||||
'success' => false,
|
||||
'message' => 'Missing fields.',
|
||||
], 422);
|
||||
}
|
||||
|
||||
$candidates = self::phMobileVariants($credentials['mobile_number']);
|
||||
|
||||
$user = User::whereIn('mobile_number', $candidates)->first();
|
||||
|
||||
if (!$user) {
|
||||
return Response::json([
|
||||
'success' => false,
|
||||
'message' => 'Account not found.',
|
||||
], 401);
|
||||
}
|
||||
|
||||
Log::info('Login attempt', [
|
||||
'mobile_number' => $credentials['mobile_number'],
|
||||
'candidates' => $candidates,
|
||||
'user_found' => true,
|
||||
'active' => $user->active,
|
||||
'acct_type' => $user->acct_type->value ?? null,
|
||||
]);
|
||||
|
||||
if (!$user->active) {
|
||||
return Response::json([
|
||||
'success' => false,
|
||||
'message' => 'Account is inactive. Please contact support.',
|
||||
], 401);
|
||||
}
|
||||
|
||||
if ($user && Hash::check($credentials['password'], $user->password)) {
|
||||
|
||||
Auth::login($user); // or Auth::guard()->login($user)
|
||||
|
||||
$current_userHashkey = $user->hashkey;
|
||||
$sessionId = session()->getId();
|
||||
|
||||
|
||||
|
||||
|
||||
Redis::sadd("user_sessions:{$current_userHashkey}", $sessionId);
|
||||
// $request->session()->regenerate();
|
||||
|
||||
Log::info('KeepAlive Value ' . $keepalive);
|
||||
if ($keepalive === true || $keepalive === 'true') {
|
||||
self::setSessiontoKeepAlive();
|
||||
}
|
||||
|
||||
return Response::json([
|
||||
'success' => true,
|
||||
'message' => 'Login successful',
|
||||
]);
|
||||
}
|
||||
|
||||
return Response::json([
|
||||
'success' => false,
|
||||
'message' => 'Invalid credentials.',
|
||||
], 401);
|
||||
|
||||
}
|
||||
/**
|
||||
* Set or extends current session auth<br>
|
||||
* This Function is Not Working JWT Automatically sets based on config file ttl
|
||||
* @param string|bool $sessionid if false then get current sessionID
|
||||
* @param int|bool $aliveinseconds if true then consider it forever
|
||||
* @return null|bool // Time To Live TTL
|
||||
*/
|
||||
public static function setSessiontoKeepAlive(string|false $sessionId = false, int|bool $aliveinseconds = true)
|
||||
{
|
||||
$sessionId = $sessionId ?: session()->getId();
|
||||
if (!$sessionId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($aliveinseconds === true) {
|
||||
$aliveinseconds = 7889472; // 3 months
|
||||
}
|
||||
if ($aliveinseconds === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// The redis session driver stores the key under the Redis connection prefix.
|
||||
// Cache::get/put uses a different prefix (cache store), so we use Redis::expire()
|
||||
// directly to extend the TTL of the existing session key without reading its value.
|
||||
$result = Redis::expire($sessionId, $aliveinseconds);
|
||||
if (!$result) {
|
||||
Log::warning('setSessiontoKeepAlive: session key not found in Redis, cannot extend TTL for: ' . $sessionId);
|
||||
return false;
|
||||
}
|
||||
|
||||
$ttl = Redis::ttl($sessionId);
|
||||
Log::info('extended session: ' . $sessionId . ' for ' . $aliveinseconds . 's, TTL: ' . $ttl);
|
||||
return $ttl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build all plausible stored forms of a Philippine mobile number so the
|
||||
* caller can match whichever variant is in the DB. Variants returned:
|
||||
* - 09XXXXXXXXX
|
||||
* - 9XXXXXXXXX (no leading 0)
|
||||
* - 639XXXXXXXXX
|
||||
* - +639XXXXXXXXX
|
||||
* plus the original raw input as a final fallback.
|
||||
*/
|
||||
public static function phMobileVariants(string $input): array
|
||||
{
|
||||
$digits = preg_replace('/\D+/', '', $input);
|
||||
$core = null; // the 10-digit 9XXXXXXXXX portion
|
||||
|
||||
if (preg_match('/^639(\d{9})$/', $digits, $m)) {
|
||||
$core = '9' . $m[1];
|
||||
} elseif (preg_match('/^09(\d{9})$/', $digits, $m)) {
|
||||
$core = '9' . $m[1];
|
||||
} elseif (preg_match('/^9(\d{9})$/', $digits, $m)) {
|
||||
$core = '9' . $m[1];
|
||||
}
|
||||
|
||||
$variants = [$input];
|
||||
if ($core) {
|
||||
$variants[] = '0' . $core;
|
||||
$variants[] = $core;
|
||||
$variants[] = '63' . $core;
|
||||
$variants[] = '+63' . $core;
|
||||
}
|
||||
|
||||
return array_values(array_unique($variants));
|
||||
}
|
||||
|
||||
/**
|
||||
* Back-compat shim: still used by UserModifyAdminPageController to
|
||||
* canonicalize on save (admin edit). Picks 09XXXXXXXXX when possible.
|
||||
*/
|
||||
public static function normalizePhMobile(string $input): string
|
||||
{
|
||||
$digits = preg_replace('/\D+/', '', $input);
|
||||
|
||||
if (preg_match('/^639(\d{9})$/', $digits, $m)) {
|
||||
return '09' . $m[1];
|
||||
}
|
||||
if (preg_match('/^9(\d{9})$/', $digits, $m)) {
|
||||
return '09' . $m[1];
|
||||
}
|
||||
if (preg_match('/^09\d{9}$/', $digits)) {
|
||||
return $digits;
|
||||
}
|
||||
|
||||
return $input;
|
||||
}
|
||||
|
||||
public function extendcurrentSession()
|
||||
{
|
||||
$ttl = self::setSessiontoKeepAlive();
|
||||
|
||||
return Response::make('TTL is '.$ttl);
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user