validate([ 'email' => ['required', 'email'], 'password' => ['required', 'string'], 'device_name' => ['nullable', 'string', 'max:120'], ]); $issuer = rtrim((string) config('services.ladill_sso.issuer'), '/'); $tokenRes = Http::asForm()->post($issuer.'/oauth/token', [ 'grant_type' => 'password', 'client_id' => (string) config('services.ladill_sso.client_id'), 'client_secret' => (string) config('services.ladill_sso.client_secret'), 'username' => $credentials['email'], 'password' => $credentials['password'], 'scope' => 'openid profile email', ]); if ($tokenRes->failed()) { throw ValidationException::withMessages([ 'email' => ['The email or password is incorrect.'], ]); } $user = $this->provisionFromAccessToken($issuer, (string) $tokenRes->json('access_token')); if (! $user) { throw ValidationException::withMessages([ 'email' => ['We could not verify your Ladill account. Please try again.'], ]); } QrTeamMember::linkPendingInvitesFor($user); $deviceName = $credentials['device_name'] ?? 'Ladill Mini Android'; $token = $user->createToken($deviceName, ['mini:read', 'mini:write']); return response()->json([ 'data' => [ 'token' => $token->plainTextToken, 'user' => $this->presentUser($user), ], ]); } public function logout(Request $request): JsonResponse { $token = $request->user()?->currentAccessToken(); $token?->delete(); return response()->json(['data' => ['message' => 'Signed out.']]); } public function me(Request $request): JsonResponse { return response()->json(['data' => $this->presentUser($request->user())]); } private function provisionFromAccessToken(string $issuer, string $accessToken): ?User { if ($accessToken === '') { return null; } $claims = Http::withToken($accessToken)->acceptJson()->get($issuer.'/oauth/userinfo'); if ($claims->failed() || ! $claims->json('sub')) { return null; } $email = (string) ($claims->json('email') ?: ''); return User::updateOrCreate( ['public_id' => (string) $claims->json('sub')], [ 'name' => $claims->json('name'), 'email' => $email !== '' ? $email : (string) $claims->json('sub').'@users.ladill.com', 'avatar_url' => $claims->json('picture'), ], ); } /** @return array */ private function presentUser(User $user): array { $account = ladill_account(); return [ 'id' => $user->id, 'public_id' => $user->public_id, 'name' => $user->name, 'email' => $user->email, 'avatar_url' => $user->avatarUrl(), 'acting_account' => [ 'id' => $account->id, 'public_id' => $account->public_id, 'name' => $account->name, 'email' => $account->email, ], 'accessible_account_ids' => $user->accessibleAccounts()->pluck('id')->values(), ]; } }