whereIn('type', [UserTypeEnum::ADMIN->value, UserTypeEnum::USER->value]) ->first(); if (! $user || ! $user->password || ! Hash::check($password, $user->password)) { return null; } $deviceId = Str::uuid()->toString(); $accessToken = $user->createAccessToken($deviceId); $refreshToken = $user->createRefreshToken($deviceId); return [ 'payload' => [ 'access_token' => $accessToken, 'user' => $user, ], 'refreshToken' => $refreshToken, ]; } public function refresh(string $refreshToken, bool $isApp = false): ?array { if (! $refreshToken) { return null; } $tokenModel = PersonalAccessToken::findToken($refreshToken); if ( ! $tokenModel || ! in_array('refresh', $tokenModel->abilities) || $tokenModel->expires_at < now() ) { return null; } $user = $tokenModel->tokenable; if (! $user) { return null; } $deviceId = Str::afterLast($tokenModel->name, '_'); $tokens = $this->refreshTokenTransaction($tokenModel, $user, $deviceId, $isApp); return [ 'payload' => [ 'access_token' => data_get($tokens, 'access_token'), 'user' => $user, ], 'refreshToken' => data_get($tokens, 'refresh_token'), ]; } public function logout(): void { $user = Auth::user(); if (! $user) { return; } $tokenName = $user->currentAccessToken()->name; $deviceId = Str::afterLast($tokenName, '_'); $user->tokens()->where('name', 'like', "%_{$deviceId}")->delete(); } // protected function refreshTokenTransaction( PersonalAccessToken $tokenModel, User $user, string $deviceId, bool $isApp = false, ): array { return DB::transaction(function () use ( $tokenModel, $user, $deviceId, $isApp, ): array { $tokenModel->update(['expires_at' => Carbon::now()]); $accessToken = $isApp ? $user->createAccessTokenApp($deviceId) : $user->createAccessToken($deviceId); $refreshToken = $isApp ? $user->createRefreshTokenApp($deviceId) : $user->createRefreshToken($deviceId); return [ 'access_token' => $accessToken, 'refresh_token' => $refreshToken, ]; }); } // public function clientSendCode(array $data): bool|array|null { try { DB::beginTransaction(); $code = str_pad((string) random_int(0, 999999), 6, '0', STR_PAD_LEFT); $user = User::where(function ($query) use ($data) { $query->when(! empty(data_get($data, 'email')), function ($q) use ($data) { $q->where('email', data_get($data, 'email')); })->when(! empty(data_get($data, 'phone')), function ($q) use ($data) { $q->where('phone', data_get($data, 'phone')); }); })->where('type', UserTypeEnum::CLIENT->value)->first(); $isLogin = false; if ($user) { $user->code = $code; $user->validated_code = false; $user->save(); $client = Client::where('user_id', $user->id)->first(); $hasAddress = $client && Address::where('source', 'client') ->where('source_id', $client->id) ->exists(); $isLogin = $client && $hasAddress; } else { $user = new User; $user->fill($data); $user->code = $code; $user->name = data_get($data, 'name', 'Usuário'); $user->type = data_get($data, 'type', UserTypeEnum::CLIENT->value); $user->save(); Client::create(['user_id' => $user->id]); } if (! empty(data_get($data, 'email'))) { $this->emailService->sendVerificationCode( email: data_get($data, 'email'), code: $code, recipientName: data_get($data, 'name', ''), ); } elseif (! empty(data_get($data, 'phone'))) { Log::info('SMS: envio de código por telefone ainda não implementado.', [ 'phone' => data_get($data, 'phone'), ]); } DB::commit(); return $isLogin; } catch (\Exception $e) { DB::rollBack(); Log::error('Erro ao enviar código de verificação.', [ 'error' => $e->getMessage(), 'data' => $data, ]); return false; } } public function providerSendCode(array $data): bool|array|null { try { DB::beginTransaction(); $code = str_pad((string) random_int(0, 999999), 6, '0', STR_PAD_LEFT); $user = User::where(function ($query) use ($data) { $query->when(! empty(data_get($data, 'email')), function ($q) use ($data) { $q->where('email', data_get($data, 'email')); })->when(! empty(data_get($data, 'phone')), function ($q) use ($data) { $q->where('phone', data_get($data, 'phone')); }); })->where('type', UserTypeEnum::PROVIDER->value)->first(); $isLogin = false; if ($user) { $provider = Provider::where('user_id', $user->id)->first(); $isLogin = $provider !== null; $user->code = $code; $user->validated_code = false; $user->save(); } else { $user = new User; $user->fill($data); $user->code = $code; $user->name = data_get($data, 'name', 'Usuário'); $user->type = data_get($data, 'type', UserTypeEnum::PROVIDER->value); $user->save(); } if (! empty(data_get($data, 'email'))) { $this->emailService->sendVerificationCode( email: data_get($data, 'email'), code: $code, recipientName: data_get($data, 'name', ''), ); } elseif (! empty(data_get($data, 'phone'))) { Log::info('SMS: envio de código por telefone ainda não implementado.', [ 'phone' => data_get($data, 'phone'), ]); } DB::commit(); return $isLogin; } catch (\Exception $e) { DB::rollBack(); Log::error('Erro ao enviar código de verificação.', [ 'error' => $e->getMessage(), 'data' => $data, ]); return false; } } // public function validateCodeClient(array $data, bool $isLogin): bool|array { $email = data_get($data, 'email'); $phone = data_get($data, 'phone'); $code = data_get($data, 'code', ''); $user = User::where(function ($query) use ($email, $phone) { $query->when($email, fn ($q) => $q->where('email', $email)) ->when($phone, fn ($q) => $q->where('phone', $phone)); })->where('type', UserTypeEnum::CLIENT->value)->where('code', $code)->first(); if (! $user) { return false; } if ($isLogin) { $user->load('client'); $client = $user->client; $hasAddress = $client && Address::where('source', 'client') ->where('source_id', $client->id) ->exists(); if (! $hasAddress) { return ['error' => 'registration_incomplete']; } return $this->loginWithEmail($user->email, $code, UserTypeEnum::CLIENT->value); } return true; } public function validateCodeProvider(array $data, bool $isLogin): bool|array { $email = data_get($data, 'email'); $phone = data_get($data, 'phone'); $code = data_get($data, 'code', ''); $user = User::where(function ($query) use ($email, $phone) { $query->when($email, fn ($q) => $q->where('email', $email)) ->when($phone, fn ($q) => $q->where('phone', $phone)); })->where('type', UserTypeEnum::PROVIDER->value)->where('code', $code)->first(); if (! $user) { return false; } if ($isLogin) { $user->load('provider'); $provider = $user->provider ?? null; if (! $provider) { return ['error' => 'registration_incomplete']; } return $this->loginWithEmail($user->email, $code, UserTypeEnum::PROVIDER->value); } return true; } // public function validateCode(array $data, bool $isLogin): bool|array { $email = data_get($data, 'email'); $phone = data_get($data, 'phone'); $code = data_get($data, 'code', ''); $user = User::where(function ($query) use ($email, $phone) { $query->when($email, function ($q) use ($email) { $q->where('email', $email); })->when($phone, function ($q) use ($phone) { $q->where('phone', $phone); }); })->where('code', $code)->first(); if (! $user) { return false; } if ($isLogin) { $resultLogin = $this->loginWithEmail($user->email, $code, $user->type->value); return $resultLogin; } return true; } public function loginWithEmail(string $email, string $code, ?string $type = null): ?array { $user = User::where('email', $email) ->where('code', $code) ->when($type, fn ($q) => $q->where('type', $type)) ->first(); if (! $user) { return null; } $user->validated_code = true; $user->code = null; $user->save(); return $this->createAppSession($user); } // public function createAppSession(User $user): array { $user->loadMissing(['provider.profileMedia', 'client.profileMedia']); $deviceId = Str::uuid()->toString(); $accessToken = $user->createAccessTokenApp($deviceId); $refreshToken = $user->createRefreshTokenApp($deviceId); return [ 'payload' => [ 'access_token' => $accessToken, 'user' => $user, ], 'refreshToken' => $refreshToken, ]; } }