6177214e-ce7c-49e3-99de-ff9721b26f63 — Commit b7ed4816
Changed files
.../authentication/authentication_repository.dart | 82 ++++++++++++++++------ .../components/booking_details_bottom_sheet.dart | 19 ++--- comwell_key_app/lib/login/login_page.dart | 5 -- .../pregistration/pregistration_repository.dart | 1 - comwell_key_app/lib/routing/app_router.dart | 3 +- 5 files changed, 73 insertions(+), 37 deletions(-)
Diff
diff --git a/comwell_key_app/lib/authentication/authentication_repository.dart b/comwell_key_app/lib/authentication/authentication_repository.dart
index 8951e0e9..dc6d5e58 100644
--- a/comwell_key_app/lib/authentication/authentication_repository.dart
+++ b/comwell_key_app/lib/authentication/authentication_repository.dart
@@ -23,24 +23,26 @@ class AuthenticationRepository {
final seos = locator<SeosRepository>();
final database = locator<ComwellDatabase>();
final api = Api();
+ late final String configFilePath;
+ late final String authorityUrl;
late final MultipleAccountPca msAuth;
- final scopes = [
- 'api://19a8eb05-01e0-4076-9db3-34bcfefd67d8/Apim.Access'
- ];
+ final scopes = ['api://19a8eb05-01e0-4076-9db3-34bcfefd67d8/Apim.Access'];
Future<void> init() async {
final clientId = dotenv.env["ENTRA_ID_CLIENT_ID"]!;
final redirect = dotenv
.env["ENTRA_ID_REDIRECT_URL"]!; // should probably be an env variable
- final String configFilePath;
switch (appFlavor) {
case "Develop":
configFilePath = 'assets/msal/msal_config_dev.json';
+ authorityUrl = dotenv.env["ENTRA_ID_AUTHORITY_URL"]!;
case "Stage":
configFilePath = 'assets/msal/msal_config_stage.json';
+ authorityUrl = dotenv.env["ENTRA_ID_AUTHORITY_URL"]!;
case "Prod":
configFilePath = 'assets/msal/msal_config_prod.json';
+ authorityUrl = dotenv.env["ENTRA_ID_AUTHORITY_URL"]!;
default:
throw Exception("Missing config file for flavor $appFlavor");
}
@@ -53,13 +55,15 @@ class AuthenticationRepository {
appleConfig: AppleConfig(
authorityType: AuthorityType.aad,
broker: Broker.webView,
+ authority: authorityUrl,
));
}
AuthenticationRepository() {
broadcast.listen((status) {
statusBuffer = status;
- secureStorage.clearKeychainValues();
+ // Don't clear keychain values on every status change
+ // Only clear when actually logging out
});
_controller.sink.add(AuthenticationStatus.unknown);
@@ -103,19 +107,36 @@ class AuthenticationRepository {
}
Future<void> logOut({bool forced = false}) async {
- await secureStorage.deleteAll();
- await database.deleteDatabase();
- // Unregister DB is now handled in registerDatabase
- //TODO: Should we differentiate between forced and unauthenticated in the tracking event?
- locator<ComwellTracking>().trackEvent('logout');
- await FirebaseAnalytics.instance.setUserProperty(
- name: 'login_status',
- value: 'false',
- );
- if (forced) {
- _controller.sink.add(AuthenticationStatus.forcedUnauthenticated);
- } else {
- _controller.sink.add(AuthenticationStatus.unauthenticated);
+ try {
+ // Clear local storage first
+ await secureStorage.deleteAll();
+ await database.deleteDatabase();
+
+ // await msAuth.removeAccount();
+
+ // Track the logout event
+ locator<ComwellTracking>().trackEvent('logout');
+ await FirebaseAnalytics.instance.setUserProperty(
+ name: 'login_status',
+ value: 'false',
+ );
+
+ // Update authentication status
+ if (forced) {
+ _controller.sink.add(AuthenticationStatus.forcedUnauthenticated);
+ } else {
+ _controller.sink.add(AuthenticationStatus.unauthenticated);
+ }
+ } catch (e) {
+ debugPrint("Error during logout: $e");
+ // Even if logout fails, still clear local data and update status
+ await secureStorage.deleteAll();
+ await database.deleteDatabase();
+ if (forced) {
+ _controller.sink.add(AuthenticationStatus.forcedUnauthenticated);
+ } else {
+ _controller.sink.add(AuthenticationStatus.unauthenticated);
+ }
}
}
@@ -124,7 +145,7 @@ class AuthenticationRepository {
Future<void> openAuth(Prompt prompt) async {
try {
final token = await msAuth.acquireToken(scopes: scopes, prompt: prompt);
-
+
await loginWithCode(token.accessToken);
} catch (e) {
debugPrint("qqq e=$e");
@@ -133,7 +154,15 @@ class AuthenticationRepository {
Future<bool> doesTokenExist() async {
try {
- await msAuth.acquireTokenSilent(scopes: scopes);
+ // First check if we have a token in secure storage
+ final storedToken = await secureStorage.read(constants.accessToken);
+ if (storedToken == null || storedToken.isEmpty) {
+ return false;
+ }
+
+ // Then try to get a fresh token silently
+ await accessToken;
+
return true;
} catch (e) {
return false;
@@ -146,6 +175,17 @@ class AuthenticationRepository {
}
Future<String> get accessToken async {
- return (await msAuth.acquireTokenSilent(scopes: scopes)).accessToken;
+ try {
+ // First check if we have a token in secure storage
+ final storedToken = await secureStorage.read(constants.accessToken);
+ if (storedToken != null && storedToken.isNotEmpty) {
+ return storedToken;
+ }
+
+ // If no stored token, try to get a fresh one silently
+ return (await msAuth.acquireTokenSilent(scopes: scopes, authority: authorityUrl)).accessToken;
+ } catch (e) {
+ throw Exception('No valid access token available');
+ }
}
}
diff --git a/comwell_key_app/lib/booking_details/components/booking_details_bottom_sheet.dart b/comwell_key_app/lib/booking_details/components/booking_details_bottom_sheet.dart
index b8abcf5d..789bf324 100644
--- a/comwell_key_app/lib/booking_details/components/booking_details_bottom_sheet.dart
+++ b/comwell_key_app/lib/booking_details/components/booking_details_bottom_sheet.dart
@@ -24,8 +24,8 @@ class BookingDetailsBottomSheet extends StatelessWidget {
return BottomSheetWidget(
widgetChildren: [
const SizedBox(height: 16),
- cubit.booking.reservationStatus == ReservationStatus.checkedin
- // TODO Uncomment this when feature is ready && cubit.getCheckOutTime().isBefore(DateTime.now())
+ cubit.booking.reservationStatus == ReservationStatus.checkedin &&
+ cubit.getCheckOutTime().isBefore(DateTime.now())
? const Padding(
padding: EdgeInsets.symmetric(horizontal: 16.0),
child: CheckOutButton(),
@@ -81,15 +81,15 @@ class BookingDetailsBottomSheet extends StatelessWidget {
]),
const SizedBox(height: 16),
if (cubit.booking.rooms.length > 1)
- Padding(
- padding: const EdgeInsets.symmetric(horizontal: 16),
- child: Text('rooms'.tr(), style: theme.textTheme.headlineMedium),
- ),
+ Padding(
+ padding: const EdgeInsets.symmetric(horizontal: 16),
+ child: Text('rooms'.tr(), style: theme.textTheme.headlineMedium),
+ ),
const SizedBox(height: 16),
if (state.keys.isNotEmpty)
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
- child:
+ child:
Text('room_keys'.tr(), style: theme.textTheme.headlineMedium),
),
const SizedBox(height: 16),
@@ -145,8 +145,9 @@ class BookingDetailsBottomSheet extends StatelessWidget {
Widget _buildServices(BuildContext context) {
final theme = Theme.of(context);
final serviceUpgrades = cubit.state.upSales?.addOnUpgrades
- .where((upgrade) => upgrade.isService)
- .toList() ?? [];
+ .where((upgrade) => upgrade.isService)
+ .toList() ??
+ [];
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
diff --git a/comwell_key_app/lib/login/login_page.dart b/comwell_key_app/lib/login/login_page.dart
index 1c83e3e9..06c233b0 100644
--- a/comwell_key_app/lib/login/login_page.dart
+++ b/comwell_key_app/lib/login/login_page.dart
@@ -1,4 +1,3 @@
-import 'package:comwell_key_app/login/components/create_user_button.dart';
import 'package:comwell_key_app/login/components/forced_logout_banner.dart';
import 'package:comwell_key_app/login/components/login_button.dart';
import 'package:flutter/material.dart';
@@ -42,10 +41,6 @@ class LoginPage extends StatelessWidget {
cubit.login();
},
),
- const SizedBox(height: 10),
- CreateUserButton(onPressed: () {
- cubit.createAccount();
- }),
const SizedBox(height: 20),
],
),
diff --git a/comwell_key_app/lib/pregistration/pregistration_repository.dart b/comwell_key_app/lib/pregistration/pregistration_repository.dart
index dc70f8dc..9c9061cd 100644
--- a/comwell_key_app/lib/pregistration/pregistration_repository.dart
+++ b/comwell_key_app/lib/pregistration/pregistration_repository.dart
@@ -70,7 +70,6 @@ class PreregistrationRepository {
}
DropInConfiguration dropInConfiguration(Amount amount, String clientKey) {
- // TODO: missing endpoint to retrieve client key
return DropInConfiguration(
environment: Environment.test,
clientKey: clientKey,
diff --git a/comwell_key_app/lib/routing/app_router.dart b/comwell_key_app/lib/routing/app_router.dart
index 34c20019..2033cbf0 100644
--- a/comwell_key_app/lib/routing/app_router.dart
+++ b/comwell_key_app/lib/routing/app_router.dart
@@ -109,7 +109,8 @@ GoRouter goRouter() {
if (status == AuthenticationStatus.unknown) {
bool doesTokenExist = await authRepo.doesTokenExist();
if (doesTokenExist) {
- //authRepo.logIn();
+
+ authRepo.logIn();
}
}