diff --git a/composer.json b/composer.json index 52a0d7f3..3a31ff07 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,6 @@ { "name": "fleetbase/core-api", - "version": "1.6.35", + "version": "1.6.36", "description": "Core Framework and Resources for Fleetbase API", "keywords": [ "fleetbase", diff --git a/src/Http/Controllers/Internal/v1/UserController.php b/src/Http/Controllers/Internal/v1/UserController.php index 02e1677a..12e86b06 100644 --- a/src/Http/Controllers/Internal/v1/UserController.php +++ b/src/Http/Controllers/Internal/v1/UserController.php @@ -182,7 +182,7 @@ public function current(Request $request) // Try to get from server cache $companyId = session('company'); - $cachedData = UserCacheService::get($user->id, $companyId); + $cachedData = UserCacheService::get($user, $companyId); if ($cachedData) { // Return cached data with cache headers @@ -202,7 +202,7 @@ public function current(Request $request) $userArray = $userData->toArray($request); // Store in cache - UserCacheService::put($user->id, $companyId, $userArray); + UserCacheService::put($user, $companyId, $userArray); // Return with cache headers return response()->json(['user' => $userArray]) diff --git a/src/Mail/VerificationMail.php b/src/Mail/VerificationMail.php index 16a616cb..283d708c 100644 --- a/src/Mail/VerificationMail.php +++ b/src/Mail/VerificationMail.php @@ -5,8 +5,6 @@ use Fleetbase\Models\VerificationCode; use Illuminate\Bus\Queueable; use Illuminate\Mail\Mailable; -use Illuminate\Mail\Mailables\Content; -use Illuminate\Mail\Mailables\Envelope; use Illuminate\Queue\SerializesModels; class VerificationMail extends Mailable @@ -17,12 +15,12 @@ class VerificationMail extends Mailable /** * The verification code to email. */ - private VerificationCode $verificationCode; + public VerificationCode $verificationCode; /** * Custom content to render if supplied. */ - private ?string $content; + public ?string $content; /** * Create a new message instance. @@ -36,30 +34,21 @@ public function __construct(VerificationCode $verificationCode, ?string $content } /** - * Get the message content definition. - */ - public function envelope(): Envelope - { - return new Envelope( - subject: $this->verificationCode->code . ' is your ' . config('app.name') . ' verification code', - ); - } - - /** - * Get the message content definition. + * Build the message. + * + * @return $this */ - public function content(): Content + public function build() { - return new Content( - markdown: 'fleetbase::mail.verification', - with: [ + return $this + ->subject($this->verificationCode->code . ' is your ' . config('app.name') . ' verification code') + ->markdown('fleetbase::mail.verification', [ 'appName' => config('app.name'), 'currentHour' => now()->hour, 'user' => $this->verificationCode->subject, 'code' => $this->verificationCode->code, 'type' => $this->verificationCode->for, 'content' => $this->content, - ] - ); + ]); } } diff --git a/src/Models/User.php b/src/Models/User.php index 7cc1ab60..881c7344 100644 --- a/src/Models/User.php +++ b/src/Models/User.php @@ -1343,6 +1343,8 @@ public function assignSingleRole($role): self $this->companyUser->assignSingleRole($role); // Invalidate user cache after role change + // Note: With updated_at in cache key, this provides immediate invalidation + // while the timestamp-based key provides automatic cache busting \Fleetbase\Services\UserCacheService::invalidateUser($this); return $this; diff --git a/src/Models/VerificationCode.php b/src/Models/VerificationCode.php index 9f616d59..dc804989 100644 --- a/src/Models/VerificationCode.php +++ b/src/Models/VerificationCode.php @@ -88,8 +88,9 @@ public function subject() */ public static function generateFor($subject = null, $for = 'general_verification', $save = true) { - $verifyCode = new static(); - $verifyCode->for = $for; + $verifyCode = new static(); + $verifyCode->for = $for; + $verifyCode->status = 'pending'; // Set default status if ($subject) { $verifyCode->setSubject($subject, false); diff --git a/src/Observers/UserObserver.php b/src/Observers/UserObserver.php index 820c9948..ca726457 100644 --- a/src/Observers/UserObserver.php +++ b/src/Observers/UserObserver.php @@ -15,6 +15,8 @@ class UserObserver public function updated(User $user): void { // Invalidate user cache when user is updated + // Note: With updated_at in cache key, this provides immediate invalidation + // while the timestamp-based key provides automatic cache busting UserCacheService::invalidateUser($user); // Invalidate organizations cache (user might be an owner) diff --git a/src/Services/SmsService.php b/src/Services/SmsService.php index afab319e..1967325c 100644 --- a/src/Services/SmsService.php +++ b/src/Services/SmsService.php @@ -161,11 +161,13 @@ protected function sendViaTwilio(string $to, string $text, array $options = []): 'response' => $response, ]; } catch (\Throwable $e) { - return [ - 'success' => false, - 'error' => $e->getMessage(), - 'code' => $e->getCode(), - ]; + // return [ + // 'success' => false, + // 'error' => $e->getMessage(), + // 'code' => $e->getCode(), + // ]; + + throw $e; } } diff --git a/src/Services/UserCacheService.php b/src/Services/UserCacheService.php index f2d9a56f..db3b678e 100644 --- a/src/Services/UserCacheService.php +++ b/src/Services/UserCacheService.php @@ -25,29 +25,34 @@ class UserCacheService /** * Generate cache key for a user and company. + * Includes the user's updated_at timestamp for automatic cache busting. * - * @param int|string $userId + * @param User $user + * @param string $companyId + * @return string */ - public static function getCacheKey($userId, string $companyId): string + public static function getCacheKey(User $user, string $companyId): string { - return self::CACHE_PREFIX . $userId . ':' . $companyId; + return self::CACHE_PREFIX . $user->uuid . ':' . $companyId . ':' . $user->updated_at->timestamp; } /** * Get cached user data. * - * @param int|string $userId + * @param User $user + * @param string $companyId + * @return array|null */ - public static function get($userId, string $companyId): ?array + public static function get(User $user, string $companyId): ?array { - $cacheKey = self::getCacheKey($userId, $companyId); + $cacheKey = self::getCacheKey($user, $companyId); try { $cached = Cache::get($cacheKey); if ($cached) { Log::debug('User cache hit', [ - 'user_id' => $userId, + 'user_id' => $user->uuid, 'company_id' => $companyId, 'cache_key' => $cacheKey, ]); @@ -57,7 +62,7 @@ public static function get($userId, string $companyId): ?array } catch (\Exception $e) { Log::error('Failed to get user cache', [ 'error' => $e->getMessage(), - 'user_id' => $userId, + 'user_id' => $user->uuid, 'company_id' => $companyId, ]); @@ -68,18 +73,22 @@ public static function get($userId, string $companyId): ?array /** * Store user data in cache. * - * @param int|string $userId + * @param User $user + * @param string $companyId + * @param array $data + * @param int|null $ttl + * @return bool */ - public static function put($userId, string $companyId, array $data, ?int $ttl = null): bool + public static function put(User $user, string $companyId, array $data, ?int $ttl = null): bool { - $cacheKey = self::getCacheKey($userId, $companyId); + $cacheKey = self::getCacheKey($user, $companyId); $ttl = $ttl ?? self::CACHE_TTL; try { Cache::put($cacheKey, $data, $ttl); Log::debug('User cache stored', [ - 'user_id' => $userId, + 'user_id' => $user->uuid, 'company_id' => $companyId, 'cache_key' => $cacheKey, 'ttl' => $ttl, @@ -89,7 +98,7 @@ public static function put($userId, string $companyId, array $data, ?int $ttl = } catch (\Exception $e) { Log::error('Failed to store user cache', [ 'error' => $e->getMessage(), - 'user_id' => $userId, + 'user_id' => $user->uuid, 'company_id' => $companyId, ]); @@ -108,7 +117,7 @@ public static function invalidateUser(User $user): void // Clear cache for each company foreach ($companies as $companyId) { - $cacheKey = self::getCacheKey($user->id, $companyId); + $cacheKey = self::getCacheKey($user, $companyId); Cache::forget($cacheKey); Log::debug('User cache invalidated', [ @@ -121,7 +130,7 @@ public static function invalidateUser(User $user): void // Also clear for current session company if different $sessionCompany = session('company'); if ($sessionCompany && !in_array($sessionCompany, $companies)) { - $cacheKey = self::getCacheKey($user->id, $sessionCompany); + $cacheKey = self::getCacheKey($user, $sessionCompany); Cache::forget($cacheKey); Log::debug('User cache invalidated for session company', [ @@ -141,24 +150,26 @@ public static function invalidateUser(User $user): void /** * Invalidate cache for a specific user and company. * - * @param int|string $userId + * @param User $user + * @param string $companyId + * @return void */ - public static function invalidate($userId, string $companyId): void + public static function invalidate(User $user, string $companyId): void { - $cacheKey = self::getCacheKey($userId, $companyId); + $cacheKey = self::getCacheKey($user, $companyId); try { Cache::forget($cacheKey); Log::debug('User cache invalidated', [ - 'user_id' => $userId, + 'user_id' => $user->uuid, 'company_id' => $companyId, 'cache_key' => $cacheKey, ]); } catch (\Exception $e) { Log::error('Failed to invalidate user cache', [ 'error' => $e->getMessage(), - 'user_id' => $userId, + 'user_id' => $user->uuid, 'company_id' => $companyId, ]); } diff --git a/src/Types/Currency.php b/src/Types/Currency.php index 76f1c9b7..1339cb3a 100644 --- a/src/Types/Currency.php +++ b/src/Types/Currency.php @@ -596,6 +596,15 @@ class Currency implements \JsonSerializable 'decimalSeparator' => '.', 'symbolPlacement' => 'before', ], + 'KZT' => [ + 'code' => 'KZT', + 'title' => 'Kazakhstani Tenge', + 'symbol' => '₸', + 'precision' => 2, + 'thousandSeparator' => ' ', + 'decimalSeparator' => '.', + 'symbolPlacement' => 'after', + ], 'KES' => [ 'code' => 'KES', 'title' => 'Kenyan Shilling', diff --git a/views/mail/verification.blade.php b/views/mail/verification.blade.php index ada64df5..f326bdc4 100644 --- a/views/mail/verification.blade.php +++ b/views/mail/verification.blade.php @@ -20,9 +20,9 @@ @endif @if($type === 'email_verification') - @component('mail::button', ['url' => \Fleetbase\Support\Utils::consoleUrl('onboard', ['step' => 'verify-email', 'session' => base64_encode($user->uuid), 'code' => $code ])]) - Verify Email - @endcomponent +@component('mail::button', ['url' => \Fleetbase\Support\Utils::consoleUrl('onboard', ['step' => 'verify-email', 'session' => base64_encode($user->uuid), 'code' => $code ])]) +Verify Email +@endcomponent @endif