6177214e-ce7c-49e3-99de-ff9721b26f63 — Commit 1e34ab86
Changed files
common/.flutter-plugins-dependencies | 1 + common/assets/msal/msal_config_dev.json | 17 +++ common/assets/msal/msal_config_prod.json | 17 +++ common/assets/msal/msal_config_stage.json | 17 +++ common/lib/gen/assets.gen.dart | 32 ++++++ common/lib/services/msal_service.dart | 79 +++++++++++++ common/lib/storage/common_preferences.dart | 21 ++++ common/lib/utils/env_utils.dart | 25 ++++ common/pubspec.lock | 127 ++++++++++++++++++++- common/pubspec.yaml | 6 + comwell_key_app/assets/msal/msal_config_dev.json | 17 --- comwell_key_app/assets/msal/msal_config_prod.json | 17 --- comwell_key_app/assets/msal/msal_config_stage.json | 17 --- .../ios/Runner.xcodeproj/project.pbxproj | 18 +-- .../lib/.generated/assets/assets.gen.dart | 42 ++----- .../authentication/authentication_repository.dart | 6 +- .../authentication/bloc/authentication_bloc.dart | 8 +- comwell_key_app/lib/data/remote/msal_service.dart | 81 ------------- comwell_key_app/lib/main.dart | 7 +- .../components/concierge_button.dart | 19 +-- .../screens/concierge/concierge_route.dart | 2 +- comwell_key_app/lib/services/http_client.dart | 2 +- .../interceptors/response_handle_interceptor.dart | 8 +- comwell_key_app/lib/utils/env_utils.dart | 25 ---- comwell_key_app/lib/utils/locator.dart | 5 +- comwell_key_app/lib/utils/seos_repository.dart | 2 +- comwell_key_app/pubspec.yaml | 4 +- .../lib/_generated/data/remote/models/order.g.dart | 4 +- .../hotel_overview_page_route.g.dart | 6 - concierge/lib/concierge_app.dart | 23 ++-- concierge/lib/concierge_route.dart | 53 ++++----- .../secure_storage/concierge_secure_storage.dart | 17 --- .../lib/data/remote/api/concierge_interceptor.dart | 10 +- .../lib/data/remote/api/payment_interceptor.dart | 11 +- concierge/lib/data/remote/models/order.dart | 16 ++- .../lib/presentation/app/concierge_cubit.dart | 15 +-- .../hotel_overview_page_route.dart | 6 - .../screens/payment/bloc/payment_cubit.dart | 8 +- .../screens/payment/payment_screen.dart | 4 - concierge/lib/utils/context_utils.dart | 2 +- .../lib/presentation/app/bloc/payment_cubit.dart | 4 + 41 files changed, 448 insertions(+), 353 deletions(-)
Diff
diff --git a/common/.flutter-plugins-dependencies b/common/.flutter-plugins-dependencies
new file mode 100644
index 00000000..dd4b2a62
--- /dev/null
+++ b/common/.flutter-plugins-dependencies
@@ -0,0 +1 @@
+{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"msal_auth","path":"/Users/mth/.pub-cache/hosted/pub.dev/msal_auth-3.3.0/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_foundation","path":"/Users/mth/.pub-cache/hosted/pub.dev/shared_preferences_foundation-2.5.6/","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false}],"android":[{"name":"msal_auth","path":"/Users/mth/.pub-cache/hosted/pub.dev/msal_auth-3.3.0/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_android","path":"/Users/mth/.pub-cache/hosted/pub.dev/shared_preferences_android-2.4.21/","native_build":true,"dependencies":[],"dev_dependency":false}],"macos":[{"name":"msal_auth","path":"/Users/mth/.pub-cache/hosted/pub.dev/msal_auth-3.3.0/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_foundation","path":"/Users/mth/.pub-cache/hosted/pub.dev/shared_preferences_foundation-2.5.6/","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false}],"linux":[{"name":"path_provider_linux","path":"/Users/mth/.pub-cache/hosted/pub.dev/path_provider_linux-2.2.1/","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_linux","path":"/Users/mth/.pub-cache/hosted/pub.dev/shared_preferences_linux-2.4.1/","native_build":false,"dependencies":["path_provider_linux"],"dev_dependency":false}],"windows":[{"name":"path_provider_windows","path":"/Users/mth/.pub-cache/hosted/pub.dev/path_provider_windows-2.3.0/","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_windows","path":"/Users/mth/.pub-cache/hosted/pub.dev/shared_preferences_windows-2.4.1/","native_build":false,"dependencies":["path_provider_windows"],"dev_dependency":false}],"web":[{"name":"shared_preferences_web","path":"/Users/mth/.pub-cache/hosted/pub.dev/shared_preferences_web-2.4.3/","dependencies":[],"dev_dependency":false}]},"dependencyGraph":[{"name":"msal_auth","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"shared_preferences","dependencies":["shared_preferences_android","shared_preferences_foundation","shared_preferences_linux","shared_preferences_web","shared_preferences_windows"]},{"name":"shared_preferences_android","dependencies":[]},{"name":"shared_preferences_foundation","dependencies":[]},{"name":"shared_preferences_linux","dependencies":["path_provider_linux"]},{"name":"shared_preferences_web","dependencies":[]},{"name":"shared_preferences_windows","dependencies":["path_provider_windows"]}],"date_created":"2026-03-12 00:19:48.325302","version":"3.41.1","swift_package_manager_enabled":{"ios":false,"macos":false}}
\ No newline at end of file
diff --git a/common/assets/msal/msal_config_dev.json b/common/assets/msal/msal_config_dev.json
new file mode 100644
index 00000000..9a962b27
--- /dev/null
+++ b/common/assets/msal/msal_config_dev.json
@@ -0,0 +1,17 @@
+{
+ "client_id" : "b7cdbf4c-39d3-4c20-bff5-c0566f8bec0b",
+ "redirect_uri" : "msauth://com.comwell.phoenix.stage/VzSiQcXRmi2kyjzcA%2BmYLEtbGVs%3D",
+ "broker_redirect_uri_registered": false,
+ "account_mode": "SINGLE",
+ "authorities" : [
+ {
+ "type": "B2C",
+ "authority_url": "https://comwellidstage.ciamlogin.com/comwellidstage.onmicrosoft.com",
+ "audience": {
+ "type": "AzureADMyOrg",
+ "tenant_id": "1e38b065-3224-4155-88e2a5af1c4aa98d"
+ },
+ "default": true
+ }
+ ]
+}
\ No newline at end of file
diff --git a/common/assets/msal/msal_config_prod.json b/common/assets/msal/msal_config_prod.json
new file mode 100644
index 00000000..46c48088
--- /dev/null
+++ b/common/assets/msal/msal_config_prod.json
@@ -0,0 +1,17 @@
+{
+ "client_id" : "cd3b91f4-3b87-4c22-a2fc-b844acad097f",
+ "redirect_uri" : "msauth://com.comwell.phoenix/VzSiQcXRmi2kyjzcA%2BmYLEtbGVs%3D",
+ "broker_redirect_uri_registered": false,
+ "account_mode": "SINGLE",
+ "authorities" : [
+ {
+ "type": "B2C",
+ "authority_url": "https://comwellid.ciamlogin.com/comwellid.onmicrosoft.com",
+ "audience": {
+ "type": "AzureADMyOrg",
+ "tenant_id": "ffd4daa9-3247-44f5-baf4-2ba49ee6675b"
+ },
+ "default": true
+ }
+ ]
+}
\ No newline at end of file
diff --git a/common/assets/msal/msal_config_stage.json b/common/assets/msal/msal_config_stage.json
new file mode 100644
index 00000000..9a962b27
--- /dev/null
+++ b/common/assets/msal/msal_config_stage.json
@@ -0,0 +1,17 @@
+{
+ "client_id" : "b7cdbf4c-39d3-4c20-bff5-c0566f8bec0b",
+ "redirect_uri" : "msauth://com.comwell.phoenix.stage/VzSiQcXRmi2kyjzcA%2BmYLEtbGVs%3D",
+ "broker_redirect_uri_registered": false,
+ "account_mode": "SINGLE",
+ "authorities" : [
+ {
+ "type": "B2C",
+ "authority_url": "https://comwellidstage.ciamlogin.com/comwellidstage.onmicrosoft.com",
+ "audience": {
+ "type": "AzureADMyOrg",
+ "tenant_id": "1e38b065-3224-4155-88e2a5af1c4aa98d"
+ },
+ "default": true
+ }
+ ]
+}
\ No newline at end of file
diff --git a/common/lib/gen/assets.gen.dart b/common/lib/gen/assets.gen.dart
new file mode 100644
index 00000000..8814c169
--- /dev/null
+++ b/common/lib/gen/assets.gen.dart
@@ -0,0 +1,32 @@
+// dart format width=80
+
+/// GENERATED CODE - DO NOT MODIFY BY HAND
+/// *****************************************************
+/// FlutterGen
+/// *****************************************************
+
+// coverage:ignore-file
+// ignore_for_file: type=lint
+// ignore_for_file: deprecated_member_use,directives_ordering,implicit_dynamic_list_literal,unnecessary_import
+
+class $AssetsMsalGen {
+ const $AssetsMsalGen();
+
+ /// File path: assets/msal/msal_config_dev.json
+ String get msalConfigDev => 'assets/msal/msal_config_dev.json';
+
+ /// File path: assets/msal/msal_config_prod.json
+ String get msalConfigProd => 'assets/msal/msal_config_prod.json';
+
+ /// File path: assets/msal/msal_config_stage.json
+ String get msalConfigStage => 'assets/msal/msal_config_stage.json';
+
+ /// List of all assets
+ List<String> get values => [msalConfigDev, msalConfigProd, msalConfigStage];
+}
+
+class Assets {
+ const Assets._();
+
+ static const $AssetsMsalGen msal = $AssetsMsalGen();
+}
diff --git a/common/lib/services/msal_service.dart b/common/lib/services/msal_service.dart
new file mode 100644
index 00000000..ae72d6d8
--- /dev/null
+++ b/common/lib/services/msal_service.dart
@@ -0,0 +1,79 @@
+import 'package:common/storage/common_preferences.dart';
+import 'package:common/utils/env_utils.dart';
+import 'package:flutter/services.dart';
+import 'package:flutter_dotenv/flutter_dotenv.dart';
+import 'package:msal_auth/msal_auth.dart';
+
+import '../gen/assets.gen.dart';
+
+class MSALService {
+ final scopes = dotenv.ENTRA_SCOPES.split(',');
+ final authorityUrl = dotenv.ENTRA_ID_AUTHORITY_URL;
+ final clientId = dotenv.ENTRA_ID_CLIENT_ID;
+ final redirect = dotenv.ENTRA_ID_REDIRECT_URL;
+
+ late final SingleAccountPca msAuth;
+ final _preferences = CommonPreferences();
+
+ MSALService();
+
+ Future<void> init() async {
+ try {
+ await _preferences.init();
+ final configFilePath = switch (appFlavor?.toLowerCase()) {
+ "develop" => "packages/common/${Assets.msal.msalConfigDev}",
+ "stage" => "packages/common/${Assets.msal.msalConfigStage}",
+ "prod" => "packages/common/${Assets.msal.msalConfigProd}",
+ _ => throw Exception("Missing config file for flavor $appFlavor"),
+ };
+ msAuth = await SingleAccountPca.create(
+ clientId: clientId,
+ androidConfig: AndroidConfig(configFilePath: configFilePath, redirectUri: redirect),
+ appleConfig: AppleConfig(
+ authorityType: AuthorityType.aad,
+ broker: Broker.webView,
+ authority: authorityUrl,
+ ),
+ );
+ } catch (e) {
+ print("qqq msauth init=$e");
+ }
+ }
+
+ Future<void> openAuth(Prompt prompt) async {
+ try {
+ await msAuth.acquireToken(
+ scopes: scopes,
+ prompt: prompt,
+ customWebViewConfig: const CustomWebViewConfig(),
+ authority: authorityUrl,
+ );
+ await _preferences.setIsLoggedIn(true);
+ } catch (e) {
+ await logout();
+ rethrow;
+ }
+ }
+
+ Future<String> acquireTokenSilent() async {
+ try {
+ final response = await msAuth.acquireTokenSilent(scopes: scopes, authority: authorityUrl);
+ await _preferences.setIsLoggedIn(true);
+ return response.accessToken;
+ } catch (e) {
+ await logout();
+ rethrow;
+ }
+ }
+
+ Future<void> logout() async {
+ await _preferences.setIsLoggedIn(false);
+ try {
+ await msAuth.signOut();
+ } catch (e) {
+ // Ignore sign-out errors when there is no active account or sign-out fails
+ }
+ }
+
+ bool get isLoggedIn => _preferences.isLoggedIn;
+}
diff --git a/common/lib/storage/common_preferences.dart b/common/lib/storage/common_preferences.dart
new file mode 100644
index 00000000..817ff5ef
--- /dev/null
+++ b/common/lib/storage/common_preferences.dart
@@ -0,0 +1,21 @@
+import 'package:shared_preferences/shared_preferences.dart';
+
+class CommonPreferences {
+ late final SharedPreferences _sharedPreferences;
+
+ Future<void> init() async {
+ _sharedPreferences = await SharedPreferences.getInstance();
+ }
+
+ bool get isLoggedIn => _sharedPreferences.getBool(_keyIsLoggedIn) ?? false;
+
+ Future<void> setIsLoggedIn(bool isLoggedIn) async {
+ await _sharedPreferences.setBool(_keyIsLoggedIn, isLoggedIn);
+ }
+
+ Future<void> clear() async {
+ await _sharedPreferences.clear();
+ }
+
+ static const _keyIsLoggedIn = "_keyIsLoggedIn";
+}
diff --git a/common/lib/utils/env_utils.dart b/common/lib/utils/env_utils.dart
new file mode 100644
index 00000000..da1c6038
--- /dev/null
+++ b/common/lib/utils/env_utils.dart
@@ -0,0 +1,25 @@
+import 'package:flutter_dotenv/flutter_dotenv.dart';
+
+extension EnvUtils on DotEnv {
+ String get OCP_APIM_SUBSCRIPTION_KEY => env["OCP_APIM_SUBSCRIPTION_KEY"]!;
+
+ String get ENTRA_ID_CLIENT_ID => env["ENTRA_ID_CLIENT_ID"]!;
+
+ String get ENTRA_ID_REDIRECT_URL => env["ENTRA_ID_REDIRECT_URL"]!;
+
+ String get ENTRA_ID_AUTHORITY_URL => env["ENTRA_ID_AUTHORITY_URL"]!;
+
+ String get ENTRA_SCOPES => env["ENTRA_SCOPES"]!;
+
+ String get SENTRY_DSN => env["SENTRY_DSN"]!;
+
+ String get MOBILE_KEYS_OPTION_APPLICATION_ID => env["MOBILEKEYSOPTIONAPPLICATIONID"]!;
+
+ String get MOBILE_KEYS_OPTION_APP_DESCRIPTION => env["MOBILEKEYSOPTIONAPPDESCRIPTION"]!;
+
+ String get MOBILE_KEYS_OPTION_VERSION => env["MOBILEKEYSOPTIONVERSION"]!;
+
+ String get MOBILE_KEYS_OPTION_LOGS_MAIL => env["MOBILEKEYSOPTIONLOGSMAIL"]!;
+
+ String get SERVICE_URL => env["SERVICE_URL"]!;
+}
diff --git a/common/pubspec.lock b/common/pubspec.lock
index 6edf7a60..962e9f88 100644
--- a/common/pubspec.lock
+++ b/common/pubspec.lock
@@ -222,6 +222,14 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
+ flutter_dotenv:
+ dependency: "direct main"
+ description:
+ name: flutter_dotenv
+ sha256: d4130c4a43e0b13fefc593bc3961f2cb46e30cb79e253d4a526b1b5d24ae1ce4
+ url: "https://pub.dev"
+ source: hosted
+ version: "6.0.0"
flutter_gen_core:
dependency: transitive
description:
@@ -256,6 +264,11 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
+ flutter_web_plugins:
+ dependency: transitive
+ description: flutter
+ source: sdk
+ version: "0.0.0"
glob:
dependency: transitive
description:
@@ -416,6 +429,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.0.0"
+ msal_auth:
+ dependency: "direct main"
+ description:
+ name: msal_auth
+ sha256: "3e563ef107e9d87a9645b7e21e23b8af50786786762d9f37324057c36c44f5c0"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.3.0"
package_config:
dependency: transitive
description:
@@ -440,6 +461,30 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.1.0"
+ path_provider_linux:
+ dependency: transitive
+ description:
+ name: path_provider_linux
+ sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.2.1"
+ path_provider_platform_interface:
+ dependency: transitive
+ description:
+ name: path_provider_platform_interface
+ sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.2"
+ path_provider_windows:
+ dependency: transitive
+ description:
+ name: path_provider_windows
+ sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.3.0"
petitparser:
dependency: transitive
description:
@@ -448,6 +493,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "7.0.2"
+ platform:
+ dependency: transitive
+ description:
+ name: platform
+ sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.1.6"
+ plugin_platform_interface:
+ dependency: transitive
+ description:
+ name: plugin_platform_interface
+ sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.8"
pool:
dependency: transitive
description:
@@ -480,6 +541,62 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.5.0"
+ shared_preferences:
+ dependency: "direct main"
+ description:
+ name: shared_preferences
+ sha256: "2939ae520c9024cb197fc20dee269cd8cdbf564c8b5746374ec6cacdc5169e64"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.5.4"
+ shared_preferences_android:
+ dependency: transitive
+ description:
+ name: shared_preferences_android
+ sha256: "8374d6200ab33ac99031a852eba4c8eb2170c4bf20778b3e2c9eccb45384fb41"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.4.21"
+ shared_preferences_foundation:
+ dependency: transitive
+ description:
+ name: shared_preferences_foundation
+ sha256: "4e7eaffc2b17ba398759f1151415869a34771ba11ebbccd1b0145472a619a64f"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.5.6"
+ shared_preferences_linux:
+ dependency: transitive
+ description:
+ name: shared_preferences_linux
+ sha256: "580abfd40f415611503cae30adf626e6656dfb2f0cee8f465ece7b6defb40f2f"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.4.1"
+ shared_preferences_platform_interface:
+ dependency: transitive
+ description:
+ name: shared_preferences_platform_interface
+ sha256: "57cbf196c486bc2cf1f02b85784932c6094376284b3ad5779d1b1c6c6a816b80"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.4.1"
+ shared_preferences_web:
+ dependency: transitive
+ description:
+ name: shared_preferences_web
+ sha256: c49bd060261c9a3f0ff445892695d6212ff603ef3115edbb448509d407600019
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.4.3"
+ shared_preferences_windows:
+ dependency: transitive
+ description:
+ name: shared_preferences_windows
+ sha256: "94ef0f72b2d71bc3e700e025db3710911bd51a71cefb65cc609dd0d9a982e3c1"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.4.1"
shelf:
dependency: transitive
description:
@@ -637,6 +754,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.0.3"
+ xdg_directories:
+ dependency: transitive
+ description:
+ name: xdg_directories
+ sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.1.0"
xml:
dependency: transitive
description:
@@ -655,4 +780,4 @@ packages:
version: "3.1.3"
sdks:
dart: ">=3.9.0 <4.0.0"
- flutter: ">=3.18.0-18.0.pre.54"
+ flutter: ">=3.35.0"
diff --git a/common/pubspec.yaml b/common/pubspec.yaml
index 2b8084a1..7dca118e 100644
--- a/common/pubspec.yaml
+++ b/common/pubspec.yaml
@@ -14,6 +14,9 @@ dependencies:
intl: any
csv: ^6.0.0
json_pretty: ^1.0.4
+ msal_auth: ^3.3.0
+ flutter_dotenv: ^6.0.0
+ shared_preferences: ^2.5.3
dev_dependencies:
flutter_test:
@@ -24,3 +27,6 @@ dev_dependencies:
flutter:
generate: true
+ assets:
+ - assets/
+ - assets/msal/
diff --git a/comwell_key_app/assets/msal/msal_config_dev.json b/comwell_key_app/assets/msal/msal_config_dev.json
deleted file mode 100644
index 9a962b27..00000000
--- a/comwell_key_app/assets/msal/msal_config_dev.json
+++ /dev/null
@@ -1,17 +0,0 @@
-{
- "client_id" : "b7cdbf4c-39d3-4c20-bff5-c0566f8bec0b",
- "redirect_uri" : "msauth://com.comwell.phoenix.stage/VzSiQcXRmi2kyjzcA%2BmYLEtbGVs%3D",
- "broker_redirect_uri_registered": false,
- "account_mode": "SINGLE",
- "authorities" : [
- {
- "type": "B2C",
- "authority_url": "https://comwellidstage.ciamlogin.com/comwellidstage.onmicrosoft.com",
- "audience": {
- "type": "AzureADMyOrg",
- "tenant_id": "1e38b065-3224-4155-88e2a5af1c4aa98d"
- },
- "default": true
- }
- ]
-}
\ No newline at end of file
diff --git a/comwell_key_app/assets/msal/msal_config_prod.json b/comwell_key_app/assets/msal/msal_config_prod.json
deleted file mode 100644
index 46c48088..00000000
--- a/comwell_key_app/assets/msal/msal_config_prod.json
+++ /dev/null
@@ -1,17 +0,0 @@
-{
- "client_id" : "cd3b91f4-3b87-4c22-a2fc-b844acad097f",
- "redirect_uri" : "msauth://com.comwell.phoenix/VzSiQcXRmi2kyjzcA%2BmYLEtbGVs%3D",
- "broker_redirect_uri_registered": false,
- "account_mode": "SINGLE",
- "authorities" : [
- {
- "type": "B2C",
- "authority_url": "https://comwellid.ciamlogin.com/comwellid.onmicrosoft.com",
- "audience": {
- "type": "AzureADMyOrg",
- "tenant_id": "ffd4daa9-3247-44f5-baf4-2ba49ee6675b"
- },
- "default": true
- }
- ]
-}
\ No newline at end of file
diff --git a/comwell_key_app/assets/msal/msal_config_stage.json b/comwell_key_app/assets/msal/msal_config_stage.json
deleted file mode 100644
index 9a962b27..00000000
--- a/comwell_key_app/assets/msal/msal_config_stage.json
+++ /dev/null
@@ -1,17 +0,0 @@
-{
- "client_id" : "b7cdbf4c-39d3-4c20-bff5-c0566f8bec0b",
- "redirect_uri" : "msauth://com.comwell.phoenix.stage/VzSiQcXRmi2kyjzcA%2BmYLEtbGVs%3D",
- "broker_redirect_uri_registered": false,
- "account_mode": "SINGLE",
- "authorities" : [
- {
- "type": "B2C",
- "authority_url": "https://comwellidstage.ciamlogin.com/comwellidstage.onmicrosoft.com",
- "audience": {
- "type": "AzureADMyOrg",
- "tenant_id": "1e38b065-3224-4155-88e2a5af1c4aa98d"
- },
- "default": true
- }
- ]
-}
\ No newline at end of file
diff --git a/comwell_key_app/ios/Runner.xcodeproj/project.pbxproj b/comwell_key_app/ios/Runner.xcodeproj/project.pbxproj
index 513c6793..5ac200dc 100644
--- a/comwell_key_app/ios/Runner.xcodeproj/project.pbxproj
+++ b/comwell_key_app/ios/Runner.xcodeproj/project.pbxproj
@@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
- objectVersion = 60;
+ objectVersion = 54;
objects = {
/* Begin PBXBuildFile section */
@@ -204,8 +204,8 @@
);
mainGroup = 97C146E51CF9000F007C117D;
packageReferences = (
- 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage" */,
- 60BC597B2DEF216C00031449 /* XCLocalSwiftPackageReference "../../mobilekeys_sdk_plugin/ios/seos_mobile_keys_plugin" */,
+ 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "FlutterGeneratedPluginSwiftPackage" */,
+ 60BC597B2DEF216C00031449 /* XCLocalSwiftPackageReference "seos_mobile_keys_plugin" */,
);
productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
projectDirPath = "";
@@ -328,14 +328,10 @@
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
- inputPaths = (
- );
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
- outputPaths = (
- );
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
@@ -349,14 +345,10 @@
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist",
);
- inputPaths = (
- );
name = "[CP] Copy Pods Resources";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist",
);
- outputPaths = (
- );
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n";
@@ -1128,11 +1120,11 @@
/* End XCConfigurationList section */
/* Begin XCLocalSwiftPackageReference section */
- 60BC597B2DEF216C00031449 /* XCLocalSwiftPackageReference "../../mobilekeys_sdk_plugin/ios/seos_mobile_keys_plugin" */ = {
+ 60BC597B2DEF216C00031449 /* XCLocalSwiftPackageReference "seos_mobile_keys_plugin" */ = {
isa = XCLocalSwiftPackageReference;
relativePath = ../../mobilekeys_sdk_plugin/ios/seos_mobile_keys_plugin;
};
- 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage" */ = {
+ 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "FlutterGeneratedPluginSwiftPackage" */ = {
isa = XCLocalSwiftPackageReference;
relativePath = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage;
};
diff --git a/comwell_key_app/lib/.generated/assets/assets.gen.dart b/comwell_key_app/lib/.generated/assets/assets.gen.dart
index d2a282fe..a5464c59 100644
--- a/comwell_key_app/lib/.generated/assets/assets.gen.dart
+++ b/comwell_key_app/lib/.generated/assets/assets.gen.dart
@@ -17,14 +17,20 @@ import 'package:vector_graphics/vector_graphics.dart' as _vg;
class $EnvGen {
const $EnvGen();
+ /// File path: env/.local.env
+ String get aLocal => 'env/.local.env';
+
/// File path: env/.prod.env
String get aProd => 'env/.prod.env';
/// File path: env/.stage.env
String get aStage => 'env/.stage.env';
+ /// File path: env/Archive.zip
+ String get archive => 'env/Archive.zip';
+
/// List of all assets
- List<String> get values => [aProd, aStage];
+ List<String> get values => [aLocal, aProd, aStage, archive];
}
class $AssetsAnimationsGen {
@@ -481,46 +487,12 @@ class $AssetsImagesGen {
];
}
-class $AssetsMsalGen {
- const $AssetsMsalGen();
-
- /// File path: assets/msal/msal_config_dev.json
- String get msalConfigDev => 'assets/msal/msal_config_dev.json';
-
- /// File path: assets/msal/msal_config_prod.json
- String get msalConfigProd => 'assets/msal/msal_config_prod.json';
-
- /// File path: assets/msal/msal_config_stage.json
- String get msalConfigStage => 'assets/msal/msal_config_stage.json';
-
- /// List of all assets
- List<String> get values => [msalConfigDev, msalConfigProd, msalConfigStage];
-}
-
-class $AssetsTranslationsGen {
- const $AssetsTranslationsGen();
-
- /// File path: assets/translations/all_translations.csv
- String get allTranslations => 'assets/translations/all_translations.csv';
-
- /// File path: assets/translations/intl_da.arb
- String get intlDa => 'assets/translations/intl_da.arb';
-
- /// File path: assets/translations/intl_en.arb
- String get intlEn => 'assets/translations/intl_en.arb';
-
- /// List of all assets
- List<String> get values => [allTranslations, intlDa, intlEn];
-}
-
class Assets {
const Assets._();
static const $AssetsAnimationsGen animations = $AssetsAnimationsGen();
static const $AssetsIconsGen icons = $AssetsIconsGen();
static const $AssetsImagesGen images = $AssetsImagesGen();
- static const $AssetsMsalGen msal = $AssetsMsalGen();
- static const $AssetsTranslationsGen translations = $AssetsTranslationsGen();
static const $EnvGen env = $EnvGen();
}
diff --git a/comwell_key_app/lib/authentication/authentication_repository.dart b/comwell_key_app/lib/authentication/authentication_repository.dart
index 06c0e9ce..5ee78d19 100644
--- a/comwell_key_app/lib/authentication/authentication_repository.dart
+++ b/comwell_key_app/lib/authentication/authentication_repository.dart
@@ -1,6 +1,6 @@
import 'dart:async';
-import 'package:comwell_key_app/data/remote/msal_service.dart';
+import 'package:common/services/msal_service.dart';
import 'package:comwell_key_app/database/comwell_db.dart';
import 'package:comwell_key_app/tracking/comwell_tracking.dart';
import 'package:comwell_key_app/utils/secure_storage.dart';
@@ -14,14 +14,12 @@ class AuthenticationRepository {
final ComwellDatabase _database;
final ComwellTracking _comwellTracking;
final MSALService _msalService;
- final ComwellPreferences _comwellPreferences;
AuthenticationRepository(
this._seosRepository,
this._database,
this._comwellTracking,
this._msalService,
- this._comwellPreferences,
) {
FirebaseAnalytics.instance.setUserProperty(
name: 'login_status',
@@ -29,7 +27,7 @@ class AuthenticationRepository {
);
}
- bool get isLoggedIn => _comwellPreferences.isLoggedIn;
+ bool get isLoggedIn => _msalService.isLoggedIn;
Future<void> logOut() async {
try {
diff --git a/comwell_key_app/lib/authentication/bloc/authentication_bloc.dart b/comwell_key_app/lib/authentication/bloc/authentication_bloc.dart
index 653cf955..faff5975 100644
--- a/comwell_key_app/lib/authentication/bloc/authentication_bloc.dart
+++ b/comwell_key_app/lib/authentication/bloc/authentication_bloc.dart
@@ -7,8 +7,7 @@ part 'authentication_event.dart';
part 'authentication_state.dart';
-class AuthenticationBloc
- extends Bloc<AuthenticationEvent, AuthenticationState> {
+class AuthenticationBloc extends Bloc<AuthenticationEvent, AuthenticationState> {
final AuthenticationRepository authenticationRepository;
AuthenticationBloc({
@@ -16,9 +15,4 @@ class AuthenticationBloc
}) : super(const AuthenticationState.unknown()) {
add(AuthenticationSubscriptionRequested());
}
-
-
-
-
-
}
diff --git a/comwell_key_app/lib/data/remote/msal_service.dart b/comwell_key_app/lib/data/remote/msal_service.dart
deleted file mode 100644
index 0942332d..00000000
--- a/comwell_key_app/lib/data/remote/msal_service.dart
+++ /dev/null
@@ -1,81 +0,0 @@
-import 'package:comwell_key_app/.generated/assets/assets.gen.dart';
-import 'package:comwell_key_app/utils/env_utils.dart';
-import 'package:comwell_key_app/utils/secure_storage.dart';
-import 'package:flutter/services.dart';
-import 'package:flutter_dotenv/flutter_dotenv.dart';
-import 'package:msal_auth/msal_auth.dart';
-
-class MSALService {
- final scopes = dotenv.ENTRA_SCOPES.split(',');
- final authorityUrl = dotenv.ENTRA_ID_AUTHORITY_URL;
- final clientId = dotenv.ENTRA_ID_CLIENT_ID;
- final redirect = dotenv.ENTRA_ID_REDIRECT_URL;
-
- late final SingleAccountPca msAuth;
- final ComwellPreferences _comwellPreferences;
-
- MSALService(this._comwellPreferences);
-
- Future<void> init() async {
- try {
- final configFilePath = switch (appFlavor?.toLowerCase()) {
- "develop" => Assets.msal.msalConfigDev,
- "stage" => Assets.msal.msalConfigStage,
- "prod" => Assets.msal.msalConfigProd,
- _ => throw Exception("Missing config file for flavor $appFlavor"),
- };
- msAuth = await SingleAccountPca.create(
- clientId: clientId,
- androidConfig: AndroidConfig(
- configFilePath: configFilePath,
- redirectUri: redirect,
- ),
- appleConfig: AppleConfig(
- authorityType: AuthorityType.aad,
- broker: Broker.webView,
- authority: authorityUrl,
- ),
- );
- } catch (e) {
- print("qqq msauth init=$e");
- }
- }
-
- Future<void> openAuth(Prompt prompt) async {
- try {
- await msAuth.acquireToken(
- scopes: scopes,
- prompt: prompt,
- customWebViewConfig: const CustomWebViewConfig(),
- authority: authorityUrl,
- );
- await _comwellPreferences.setIsLoggedIn(true);
- } catch (e) {
- await logout();
- rethrow;
- }
- }
-
- Future<String> acquireTokenSilent() async {
- try {
- final response = await msAuth.acquireTokenSilent(
- scopes: scopes,
- authority: authorityUrl,
- );
- await _comwellPreferences.setIsLoggedIn(true);
- return response.accessToken;
- } catch (e) {
- await logout();
- rethrow;
- }
- }
-
- Future<void> logout() async {
- await _comwellPreferences.setIsLoggedIn(false);
- try {
- await msAuth.signOut();
- } catch (e) {
- // Ignore sign-out errors when there is no active account or sign-out fails
- }
- }
-}
diff --git a/comwell_key_app/lib/main.dart b/comwell_key_app/lib/main.dart
index 651c61b8..d54454fd 100644
--- a/comwell_key_app/lib/main.dart
+++ b/comwell_key_app/lib/main.dart
@@ -1,6 +1,6 @@
import 'package:common/.generated/l10n/app_localizations.dart';
-import 'package:comwell_key_app/data/remote/msal_service.dart';
-import 'package:comwell_key_app/utils/env_utils.dart';
+import 'package:common/services/msal_service.dart';
+import 'package:common/utils/env_utils.dart';
import 'package:comwell_key_app/utils/firebase.dart';
import 'package:comwell_key_app/utils/locator.dart';
import 'package:comwell_key_app/services/http_client.dart';
@@ -12,9 +12,6 @@ import 'package:flutter/services.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:sentry_flutter/sentry_flutter.dart';
import 'comwell_app.dart';
-import 'firebase_options_dev.dart' as fb_dev;
-import 'firebase_options_stage.dart' as fb_stage;
-import 'firebase_options_prod.dart' as fb_prod;
import 'package:payment_plugin/payment_plugin.dart';
void main() async {
diff --git a/comwell_key_app/lib/presentation/screens/booking_details/components/concierge_button.dart b/comwell_key_app/lib/presentation/screens/booking_details/components/concierge_button.dart
index f77f0e62..7b76c8d1 100644
--- a/comwell_key_app/lib/presentation/screens/booking_details/components/concierge_button.dart
+++ b/comwell_key_app/lib/presentation/screens/booking_details/components/concierge_button.dart
@@ -1,8 +1,8 @@
-import 'package:comwell_key_app/data/remote/msal_service.dart';
+import 'package:common/services/msal_service.dart';
import 'package:comwell_key_app/overview/models/booking.dart';
import 'package:comwell_key_app/presentation/app/bloc/profile_cubit.dart';
import 'package:comwell_key_app/themes/light_theme.dart';
-import 'package:comwell_key_app/utils/env_utils.dart';
+import 'package:common/utils/env_utils.dart';
import 'package:comwell_key_app/utils/l10n_utils.dart';
import 'package:comwell_key_app/utils/locator.dart';
import 'package:concierge/flavors.dart';
@@ -22,17 +22,10 @@ class ConciergeButton extends StatelessWidget {
return GestureDetector(
onTap: () async {
- final msalService = locator<MSALService>();
- final token = await msalService.acquireTokenSilent();
- if (context.mounted) {
- HotelOverviewPageRoute(
- hotelCode: booking.hotelCode,
- authToken: token,
- flavor: F.appFlavor.name,
- roomNumber: booking.roomNumber,
- subKey: dotenv.OCP_APIM_SUBSCRIPTION_KEY,
- ).push(context);
- }
+ HotelOverviewPageRoute(
+ hotelCode: booking.hotelCode,
+ roomNumber: booking.roomNumber,
+ ).push(context);
},
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
diff --git a/comwell_key_app/lib/presentation/screens/concierge/concierge_route.dart b/comwell_key_app/lib/presentation/screens/concierge/concierge_route.dart
index 21322c75..fadabfc5 100644
--- a/comwell_key_app/lib/presentation/screens/concierge/concierge_route.dart
+++ b/comwell_key_app/lib/presentation/screens/concierge/concierge_route.dart
@@ -1,4 +1,4 @@
-import 'package:comwell_key_app/data/remote/msal_service.dart';
+import 'package:common/services/msal_service.dart';
import 'package:comwell_key_app/presentation/screens/login/login_route.dart';
import 'package:comwell_key_app/routing/app_routes.dart';
import 'package:comwell_key_app/utils/locator.dart';
diff --git a/comwell_key_app/lib/services/http_client.dart b/comwell_key_app/lib/services/http_client.dart
index 3b0fcf9e..f24d4733 100644
--- a/comwell_key_app/lib/services/http_client.dart
+++ b/comwell_key_app/lib/services/http_client.dart
@@ -1,5 +1,5 @@
import 'package:comwell_key_app/services/interceptors/response_handle_interceptor.dart';
-import 'package:comwell_key_app/utils/env_utils.dart';
+import 'package:common/utils/env_utils.dart';
import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
diff --git a/comwell_key_app/lib/services/interceptors/response_handle_interceptor.dart b/comwell_key_app/lib/services/interceptors/response_handle_interceptor.dart
index 689ccabd..72536d9b 100644
--- a/comwell_key_app/lib/services/interceptors/response_handle_interceptor.dart
+++ b/comwell_key_app/lib/services/interceptors/response_handle_interceptor.dart
@@ -1,8 +1,7 @@
-import 'package:comwell_key_app/data/remote/msal_service.dart';
+import 'package:common/services/msal_service.dart';
import 'package:comwell_key_app/presentation/screens/login/login_route.dart';
-import 'package:comwell_key_app/routing/app_routes.dart';
import 'package:comwell_key_app/services/exceptions.dart';
-import 'package:comwell_key_app/utils/env_utils.dart';
+import 'package:common/utils/env_utils.dart';
import 'package:comwell_key_app/utils/locator.dart';
import 'package:comwell_key_app/utils/secure_storage.dart';
import 'package:dio/dio.dart';
@@ -29,7 +28,8 @@ class ResponseHandleInterceptor extends Interceptor {
throw UnauthorizedException();
}
}
- void addUserAgentHeader(RequestOptions requestOptions) {
+
+ void addUserAgentHeader(RequestOptions requestOptions) {
requestOptions.headers['User-Agent'] = _comwellPreferences.userAgent;
}
diff --git a/comwell_key_app/lib/utils/env_utils.dart b/comwell_key_app/lib/utils/env_utils.dart
deleted file mode 100644
index da1c6038..00000000
--- a/comwell_key_app/lib/utils/env_utils.dart
+++ /dev/null
@@ -1,25 +0,0 @@
-import 'package:flutter_dotenv/flutter_dotenv.dart';
-
-extension EnvUtils on DotEnv {
- String get OCP_APIM_SUBSCRIPTION_KEY => env["OCP_APIM_SUBSCRIPTION_KEY"]!;
-
- String get ENTRA_ID_CLIENT_ID => env["ENTRA_ID_CLIENT_ID"]!;
-
- String get ENTRA_ID_REDIRECT_URL => env["ENTRA_ID_REDIRECT_URL"]!;
-
- String get ENTRA_ID_AUTHORITY_URL => env["ENTRA_ID_AUTHORITY_URL"]!;
-
- String get ENTRA_SCOPES => env["ENTRA_SCOPES"]!;
-
- String get SENTRY_DSN => env["SENTRY_DSN"]!;
-
- String get MOBILE_KEYS_OPTION_APPLICATION_ID => env["MOBILEKEYSOPTIONAPPLICATIONID"]!;
-
- String get MOBILE_KEYS_OPTION_APP_DESCRIPTION => env["MOBILEKEYSOPTIONAPPDESCRIPTION"]!;
-
- String get MOBILE_KEYS_OPTION_VERSION => env["MOBILEKEYSOPTIONVERSION"]!;
-
- String get MOBILE_KEYS_OPTION_LOGS_MAIL => env["MOBILEKEYSOPTIONLOGSMAIL"]!;
-
- String get SERVICE_URL => env["SERVICE_URL"]!;
-}
diff --git a/comwell_key_app/lib/utils/locator.dart b/comwell_key_app/lib/utils/locator.dart
index d8e5dfc9..057093e7 100644
--- a/comwell_key_app/lib/utils/locator.dart
+++ b/comwell_key_app/lib/utils/locator.dart
@@ -2,7 +2,7 @@ import 'package:comwell_key_app/authentication/authentication_repository.dart';
import 'package:comwell_key_app/check_out/check_out_repository.dart';
import 'package:comwell_key_app/choose_share_room/choose_share_room_repository.dart';
import 'package:comwell_key_app/contact/repository/contact_repository.dart';
-import 'package:comwell_key_app/data/remote/msal_service.dart';
+import 'package:common/services/msal_service.dart';
import 'package:comwell_key_app/database/comwell_db.dart';
import 'package:comwell_key_app/domain/repositories/bluetooth_repository.dart';
import 'package:comwell_key_app/domain/repositories/booking_details_repository.dart';
@@ -48,7 +48,7 @@ void setupLocator() {
locator.registerSingleton(ComwellTracking());
registerDatabase();
locator.registerSingleton(SecureStorage());
- locator.registerSingleton(MSALService(locator()));
+ locator.registerSingleton(MSALService());
locator.registerSingleton(SeosMobileKeysPlugin());
locator.registerSingleton(ComwellHttpClient());
locator.registerSingleton(Api());
@@ -69,7 +69,6 @@ void setupLocator() {
locator.get(),
locator.get(),
locator.get(),
- locator.get(),
),
);
locator.registerFactory(() => BookingDetailsRepository());
diff --git a/comwell_key_app/lib/utils/seos_repository.dart b/comwell_key_app/lib/utils/seos_repository.dart
index 2007281f..4a01da5c 100644
--- a/comwell_key_app/lib/utils/seos_repository.dart
+++ b/comwell_key_app/lib/utils/seos_repository.dart
@@ -1,5 +1,5 @@
import 'package:comwell_key_app/services/api.dart';
-import 'package:comwell_key_app/utils/env_utils.dart';
+import 'package:common/utils/env_utils.dart';
import 'package:comwell_key_app/utils/secure_storage.dart';
import 'package:flutter/material.dart';
diff --git a/comwell_key_app/pubspec.yaml b/comwell_key_app/pubspec.yaml
index 759f5e4a..8ae030a0 100644
--- a/comwell_key_app/pubspec.yaml
+++ b/comwell_key_app/pubspec.yaml
@@ -61,10 +61,10 @@ dependencies:
in_app_update: ^4.2.3
uri: ^1.0.0
pretty_dio_logger: ^1.4.0
- msal_auth: ^3.3.0
cached_network_image: ^3.4.1
gap: ^3.0.1
freezed: ^3.2.3
+ msal_auth: ^3.3.0
freezed_annotation: ^3.1.0
flutter_blue_plus: ^2.1.0
app_settings: ^7.0.0
@@ -97,10 +97,10 @@ flutter:
generate: true
uses-material-design: true
assets:
- - assets/msal/
- assets/animations/
- assets/images/
- assets/icons/
+ - packages/common/assets/msal/
- env/
fonts:
diff --git a/concierge/lib/_generated/data/remote/models/order.g.dart b/concierge/lib/_generated/data/remote/models/order.g.dart
index 5743e8a4..7a3722a9 100644
--- a/concierge/lib/_generated/data/remote/models/order.g.dart
+++ b/concierge/lib/_generated/data/remote/models/order.g.dart
@@ -8,7 +8,7 @@ part of '../../../../data/remote/models/order.dart';
Order _$OrderFromJson(Map json) => Order(
id: (json['id'] as num).toInt(),
- status: json['status'] as String,
+ status: const OrderStatusConverter().fromJson(json['status'] as String),
type: json['type'] as String,
isArchived: json['is_archived'] as bool,
archivedAt: json['archived_at'],
@@ -42,7 +42,7 @@ Order _$OrderFromJson(Map json) => Order(
Map<String, dynamic> _$OrderToJson(Order instance) => <String, dynamic>{
'id': instance.id,
- 'status': instance.status,
+ 'status': const OrderStatusConverter().toJson(instance.status),
'type': instance.type,
'is_archived': instance.isArchived,
'archived_at': instance.archivedAt,
diff --git a/concierge/lib/_generated/presentation/screens/hotel_overview_page/hotel_overview_page_route.g.dart b/concierge/lib/_generated/presentation/screens/hotel_overview_page/hotel_overview_page_route.g.dart
index 4131ccad..fc9e70a0 100644
--- a/concierge/lib/_generated/presentation/screens/hotel_overview_page/hotel_overview_page_route.g.dart
+++ b/concierge/lib/_generated/presentation/screens/hotel_overview_page/hotel_overview_page_route.g.dart
@@ -17,9 +17,6 @@ mixin $HotelOverviewPageRoute on GoRouteData {
static HotelOverviewPageRoute _fromState(GoRouterState state) =>
HotelOverviewPageRoute(
hotelCode: state.uri.queryParameters['hotel-code']!,
- authToken: state.uri.queryParameters['auth-token']!,
- flavor: state.uri.queryParameters['flavor']!,
- subKey: state.uri.queryParameters['sub-key']!,
roomNumber: state.uri.queryParameters['room-number']!,
);
@@ -30,9 +27,6 @@ mixin $HotelOverviewPageRoute on GoRouteData {
'/concierge/hotel-overview-page',
queryParams: {
'hotel-code': _self.hotelCode,
- 'auth-token': _self.authToken,
- 'flavor': _self.flavor,
- 'sub-key': _self.subKey,
'room-number': _self.roomNumber,
},
);
diff --git a/concierge/lib/concierge_app.dart b/concierge/lib/concierge_app.dart
index 99d9762c..eeabfc91 100644
--- a/concierge/lib/concierge_app.dart
+++ b/concierge/lib/concierge_app.dart
@@ -1,4 +1,4 @@
-import 'package:concierge/data/local/secure_storage/concierge_secure_storage.dart';
+import 'package:common/services/msal_service.dart';
import 'package:concierge/data/remote/api/concierge_interceptor.dart';
import 'package:concierge/data/remote/api/concierge_service.dart';
import 'package:concierge/domain/repositories/property_repository.dart';
@@ -8,7 +8,6 @@ import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
-import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:payment_plugin/payment_plugin.dart';
import 'package:pretty_dio_logger/pretty_dio_logger.dart';
@@ -26,29 +25,26 @@ class ConciergeApp extends StatelessWidget {
final String authToken;
final String flavor;
- Future<(ConciergeService, ConciergeSecureStorage)> _getDependencies() async {
+ Future<ConciergeService> _getDependencies() async {
F.appFlavor = Flavor.values.firstWhere((flavor) {
return flavor.name == this.flavor.toLowerCase();
});
- final storage = ConciergeSecureStorage();
+ final msal = MSALService();
+ await msal.init();
final conciergeDio = Dio(BaseOptions(baseUrl: F.baseConciergeUrl));
conciergeDio.interceptors.addAll([
- ConciergeInterceptor(storage),
+ ConciergeInterceptor(msal),
if (kDebugMode) PrettyDioLogger(requestBody: true, requestHeader: true),
]);
final apimDio = Dio(
- BaseOptions(
- baseUrl: "https://apim-comwell-net-services-stage.azure-api.net/api",
- headers: {"Ocp-Apim-Subscription-Key": ""},
- ),
+ BaseOptions(baseUrl: "https://apim-comwell-net-services-stage.azure-api.net/api"),
);
apimDio.interceptors.addAll([
- ConciergeInterceptor(storage),
+ ConciergeInterceptor(msal),
if (kDebugMode) PrettyDioLogger(requestBody: true, requestHeader: true),
]);
await PaymentPlugin.initialize(config: PaymentConfig(dio: apimDio));
- await storage.setUserToken(authToken);
- return (ConciergeService(conciergeDio), storage);
+ return (ConciergeService(conciergeDio));
}
@override
@@ -62,11 +58,10 @@ class ConciergeApp extends StatelessWidget {
if (asyncSnapshot.hasError) {
return Center(child: Text(asyncSnapshot.error.toString()));
}
- final (service, storage) = asyncSnapshot.data!;
+ final (service) = asyncSnapshot.data!;
return MultiRepositoryProvider(
providers: [
RepositoryProvider(create: (context) => PropertyRepository(service)),
- RepositoryProvider(create: (context) => storage),
RepositoryProvider(create: (context) => PaymentPlugin.instance),
],
child: MultiBlocProvider(
diff --git a/concierge/lib/concierge_route.dart b/concierge/lib/concierge_route.dart
index 6a3bece3..bf212026 100644
--- a/concierge/lib/concierge_route.dart
+++ b/concierge/lib/concierge_route.dart
@@ -1,3 +1,4 @@
+import 'package:common/services/msal_service.dart';
import 'package:concierge/data/remote/api/payment_interceptor.dart';
import 'package:concierge/presentation/app/cart_cubit.dart';
import 'package:concierge/presentation/app/concierge_cubit.dart';
@@ -16,7 +17,6 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:go_router/go_router.dart';
import 'package:payment_plugin/payment_plugin.dart';
import 'package:pretty_dio_logger/pretty_dio_logger.dart';
-import 'data/local/secure_storage/concierge_secure_storage.dart';
import 'data/remote/api/concierge_interceptor.dart';
import 'data/remote/api/concierge_service.dart';
import 'domain/repositories/property_repository.dart';
@@ -25,9 +25,6 @@ import 'flavors.dart';
final conciergeNavigatorKey = GlobalKey<NavigatorState>();
final conciergeShellRoute = StatefulShellRoute.indexedStack(
- redirect: (context, state) {
- return null;
- },
branches: [
StatefulShellBranch(
navigatorKey: conciergeNavigatorKey,
@@ -43,47 +40,43 @@ final conciergeShellRoute = StatefulShellRoute.indexedStack(
),
],
builder: (context, state, child) {
- Future<(ConciergeService, ConciergeSecureStorage, Dio)> getDependencies() async {
- F.appFlavor = Flavor.values.firstWhere((flavor) => flavor.name == appFlavor);
- final storage = ConciergeSecureStorage();
- final dio = Dio(BaseOptions(baseUrl: F.baseConciergeUrl));
- dio.interceptors.addAll([
- ConciergeInterceptor(storage),
- if (kDebugMode) PrettyDioLogger(requestBody: true, requestHeader: true),
- ]);
- final apimDio = Dio(BaseOptions(baseUrl: F.baseApimUrl));
- apimDio.interceptors.addAll([
- PaymentInterceptor(storage),
- if (kDebugMode) PrettyDioLogger(requestBody: true, requestHeader: true),
- ]);
- await PaymentPlugin.initialize(config: PaymentConfig(dio: apimDio));
- return (ConciergeService(dio), storage, apimDio);
+ Future<(ConciergeService, Dio)> getDependencies() async {
+ try {
+ F.appFlavor = Flavor.values.firstWhere((flavor) => flavor.name == appFlavor?.toLowerCase());
+ final msal = MSALService();
+ await msal.init();
+ final dio = Dio(BaseOptions(baseUrl: F.baseConciergeUrl));
+ dio.interceptors.addAll([
+ ConciergeInterceptor(msal),
+ if (kDebugMode) PrettyDioLogger(requestBody: true, requestHeader: true),
+ ]);
+ final apimDio = Dio(BaseOptions(baseUrl: F.baseApimUrl));
+ apimDio.interceptors.addAll([
+ PaymentInterceptor(msal),
+ if (kDebugMode) PrettyDioLogger(requestBody: true, requestHeader: true),
+ ]);
+ // await PaymentPlugin.initialize(config: PaymentConfig(dio: apimDio));
+ return (ConciergeService(dio), apimDio);
+ } catch (e, st) {
+ print("qqq concierge init error=$e, $st");
+ rethrow;
+ }
}
return FutureBuilder(
future: getDependencies(),
builder: (context, asyncSnapshot) {
- if (!asyncSnapshot.hasData) {
- return Center(child: CircularProgressIndicator());
- }
-
- if (asyncSnapshot.hasError) {
- return Center(child: Text(asyncSnapshot.error.toString()));
- }
-
- final (service, storage, apimDio) = asyncSnapshot.data!;
+ final (service, apimDio) = asyncSnapshot.requireData;
return MultiRepositoryProvider(
providers: [
RepositoryProvider(create: (context) => PropertyRepository(service)),
RepositoryProvider(create: (context) => AdyenRepository(dio: apimDio)),
- RepositoryProvider(create: (context) => storage),
RepositoryProvider(create: (context) => PaymentPlugin.instance),
],
child: MultiBlocProvider(
providers: [
BlocProvider(
create: (context) => ConciergeCubit(
- context.read(),
context.read(),
launchParameters: state.uri.queryParameters,
),
diff --git a/concierge/lib/data/local/secure_storage/concierge_secure_storage.dart b/concierge/lib/data/local/secure_storage/concierge_secure_storage.dart
index 577e37a3..48e5e122 100644
--- a/concierge/lib/data/local/secure_storage/concierge_secure_storage.dart
+++ b/concierge/lib/data/local/secure_storage/concierge_secure_storage.dart
@@ -1,8 +1,6 @@
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
class ConciergeSecureStorage {
- static const _tokenKey = 'concierge_user_token';
- static const _roomNumber = 'room_number';
final FlutterSecureStorage _storage = FlutterSecureStorage(
iOptions: IOSOptions(groupId: "concierge"),
@@ -11,21 +9,6 @@ class ConciergeSecureStorage {
ConciergeSecureStorage();
- Future<void> setUserToken(String token) async {
- await _storage.write(key: _tokenKey, value: token);
- }
-
- Future<String?> getUserToken() async {
- return _storage.read(key: _tokenKey);
- }
-
- Future<void> setRoomNumber(String value) async {
- await _storage.write(key: _roomNumber, value: value);
- }
-
- Future<String> getRoomNumber() async {
- return await _storage.read(key: _roomNumber) ?? "";
- }
Future<void> dispose() async {
await _storage.deleteAll();
diff --git a/concierge/lib/data/remote/api/concierge_interceptor.dart b/concierge/lib/data/remote/api/concierge_interceptor.dart
index 98fabf6d..ae55aa5d 100644
--- a/concierge/lib/data/remote/api/concierge_interceptor.dart
+++ b/concierge/lib/data/remote/api/concierge_interceptor.dart
@@ -1,15 +1,15 @@
-import 'package:concierge/data/local/secure_storage/concierge_secure_storage.dart';
+import 'package:common/services/msal_service.dart';
import 'package:dio/dio.dart';
class ConciergeInterceptor extends Interceptor {
- final ConciergeSecureStorage _conciergeSecureStorage;
+ final MSALService _msalService;
- const ConciergeInterceptor(this._conciergeSecureStorage);
+ const ConciergeInterceptor(this._msalService);
@override
void onRequest(RequestOptions options, RequestInterceptorHandler handler) async {
- final token = await _conciergeSecureStorage.getUserToken();
- if (token != null) {
+ if (_msalService.isLoggedIn) {
+ final token = await _msalService.acquireTokenSilent();
options.headers["X-Authorization"] = token;
}
options.headers["Accept"] = "application/json";
diff --git a/concierge/lib/data/remote/api/payment_interceptor.dart b/concierge/lib/data/remote/api/payment_interceptor.dart
index 67b5c599..beb8bbc8 100644
--- a/concierge/lib/data/remote/api/payment_interceptor.dart
+++ b/concierge/lib/data/remote/api/payment_interceptor.dart
@@ -1,17 +1,16 @@
-import 'package:concierge/data/local/secure_storage/concierge_secure_storage.dart';
+import 'package:common/services/msal_service.dart';
import 'package:dio/dio.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
class PaymentInterceptor extends Interceptor {
- final ConciergeSecureStorage _conciergeSecureStorage;
+ final MSALService _msalService;
- const PaymentInterceptor(this._conciergeSecureStorage);
+ const PaymentInterceptor(this._msalService);
@override
void onRequest(RequestOptions options, RequestInterceptorHandler handler) async {
- final token = await _conciergeSecureStorage.getUserToken();
- if (token != null) {
- options.headers["Authorization"] = token;
+ if (_msalService.isLoggedIn) {
+ options.headers["Authorization"] = await _msalService.acquireTokenSilent();
}
options.headers["Ocp-Apim-Subscription-Key"] = dotenv.get("OCP_APIM_SUBSCRIPTION_KEY");
super.onRequest(options, handler);
diff --git a/concierge/lib/data/remote/models/order.dart b/concierge/lib/data/remote/models/order.dart
index f32b4c30..843dd97d 100644
--- a/concierge/lib/data/remote/models/order.dart
+++ b/concierge/lib/data/remote/models/order.dart
@@ -2,14 +2,28 @@
//
// final order = orderFromJson(jsonString);
+import 'package:concierge/data/remote/converters/order_status_converter.dart';
import 'package:json_annotation/json_annotation.dart';
part '../../../_generated/data/remote/models/order.g.dart';
+enum OrderStatus {
+ received("RECEIVED"),
+ accepted("ACCEPTED"),
+ inProgress("INPROGRESS"),
+ delivered("DELIVERED"),
+ cancelled("CANCELLED");
+
+ final String serializedValue;
+
+ const OrderStatus(this.serializedValue);
+}
+
@JsonSerializable(fieldRename: FieldRename.snake)
class Order {
final int id;
- final String status;
+ @OrderStatusConverter()
+ final OrderStatus status;
final String type;
final bool isArchived;
final dynamic archivedAt;
diff --git a/concierge/lib/presentation/app/concierge_cubit.dart b/concierge/lib/presentation/app/concierge_cubit.dart
index f8759ae6..9efd09c9 100644
--- a/concierge/lib/presentation/app/concierge_cubit.dart
+++ b/concierge/lib/presentation/app/concierge_cubit.dart
@@ -10,22 +10,14 @@ part '../../_generated/presentation/app/concierge_cubit.freezed.dart';
class ConciergeCubit extends BaseCubit<ConciergeState> {
final PropertyRepository _propertyRepository;
- final ConciergeSecureStorage _storage;
final Map<String, String> launchParameters;
ConciergeCubit(
- this._propertyRepository,
- this._storage, {
+ this._propertyRepository,{
required this.launchParameters,
- }) : super(const ConciergeState()) {
- init();
- }
-
- Future<void> init() async {
- final authToken = launchParameters["auth-token"] ?? "";
+ }) : super(const ConciergeState());
- if (authToken.isNotEmpty) await _storage.setUserToken(authToken);
- }
+ String get roomNumber => launchParameters["room-number"] ?? "";
DataState getProductState(int pId) {
final pExists = state.products.containsKey(pId);
@@ -59,7 +51,6 @@ class ConciergeCubit extends BaseCubit<ConciergeState> {
@override
Future<void> close() async {
- await _storage.dispose();
return super.close();
}
}
diff --git a/concierge/lib/presentation/screens/hotel_overview_page/hotel_overview_page_route.dart b/concierge/lib/presentation/screens/hotel_overview_page/hotel_overview_page_route.dart
index 6ebba7bb..9a5be770 100644
--- a/concierge/lib/presentation/screens/hotel_overview_page/hotel_overview_page_route.dart
+++ b/concierge/lib/presentation/screens/hotel_overview_page/hotel_overview_page_route.dart
@@ -11,16 +11,10 @@ part '../../../_generated/presentation/screens/hotel_overview_page/hotel_overvie
@TypedGoRoute<HotelOverviewPageRoute>(path: AppRoutes.hotelOverviewPage)
class HotelOverviewPageRoute extends GoRouteData with $HotelOverviewPageRoute {
final String hotelCode;
- final String authToken;
- final String flavor;
- final String subKey;
final String roomNumber;
HotelOverviewPageRoute({
required this.hotelCode,
- required this.authToken,
- required this.flavor,
- required this.subKey,
required this.roomNumber,
});
diff --git a/concierge/lib/presentation/screens/payment/bloc/payment_cubit.dart b/concierge/lib/presentation/screens/payment/bloc/payment_cubit.dart
index fb8a9089..1b8a7a6f 100644
--- a/concierge/lib/presentation/screens/payment/bloc/payment_cubit.dart
+++ b/concierge/lib/presentation/screens/payment/bloc/payment_cubit.dart
@@ -1,3 +1,4 @@
+import 'package:concierge/data/remote/models/order.dart';
import 'package:concierge/domain/models/app_error.dart';
import 'package:concierge/domain/repositories/property_repository.dart';
import 'package:concierge/presentation/app/cart_cubit.dart';
@@ -74,10 +75,10 @@ class PaymentCubit extends BaseCubit<PaymentState> {
final sessionData = session["sessionData"];
final sessionId = session["id"];
await _paymentCubit.createConciergeSession(sessionId, clientKey, sessionData);
- print(data);
} catch (e, st) {
handleError(e, st);
safeEmit(state.copyWith(error: AppError.unknown(e.toString())));
+ _paymentCubit.emitError(e);
} finally {
safeEmit(state.copyWith(isLoading: false));
}
@@ -86,13 +87,16 @@ class PaymentCubit extends BaseCubit<PaymentState> {
Future<void> _checkStatus() async {
try {
final response = await _propertyRepository.getOrder(state.orderId);
- if (response.status == "RECEIVED") {
+ if (response.status == OrderStatus.received) {
safeEmit(state.copyWith(paymentSuccess: true));
+ } else if (response.status == OrderStatus.cancelled) {
+ _paymentCubit.emitError("Operation cancelled");
} else {
await Future.delayed(Duration(seconds: 1));
_checkStatus();
}
} catch (e, st) {
+ _paymentCubit.emitError(e);
handleError(e, st);
}
}
diff --git a/concierge/lib/presentation/screens/payment/payment_screen.dart b/concierge/lib/presentation/screens/payment/payment_screen.dart
index bfe24f76..8b7ea24e 100644
--- a/concierge/lib/presentation/screens/payment/payment_screen.dart
+++ b/concierge/lib/presentation/screens/payment/payment_screen.dart
@@ -21,10 +21,6 @@ class PaymentScreen extends StatelessWidget {
builder: (context, state) {
return MultiBlocListener(
listeners: [
- BlocListener<PaymentCubit, PaymentState>(
- listenWhen: (prev, curr) => prev.isLoading && curr.error.isError,
- listener: (context, state) {},
- ),
BlocListener<PaymentCubit, PaymentState>(
listenWhen: (prev, curr) => !prev.paymentSuccess && curr.paymentSuccess,
listener: (context, state) {
diff --git a/concierge/lib/utils/context_utils.dart b/concierge/lib/utils/context_utils.dart
index 608b61ce..33bf8a70 100644
--- a/concierge/lib/utils/context_utils.dart
+++ b/concierge/lib/utils/context_utils.dart
@@ -4,8 +4,8 @@ import 'package:go_router/go_router.dart';
extension ContextUtils on BuildContext {
Future<void> popUntil(String route) async {
while (route != _matchedLocation && canPop()) {
- await Future.delayed(Duration(milliseconds: 10));
pop();
+ await Future.delayed(Duration(milliseconds: 10));
}
}
diff --git a/payment_plugin/lib/presentation/app/bloc/payment_cubit.dart b/payment_plugin/lib/presentation/app/bloc/payment_cubit.dart
index 9dcfe68a..6772c07c 100644
--- a/payment_plugin/lib/presentation/app/bloc/payment_cubit.dart
+++ b/payment_plugin/lib/presentation/app/bloc/payment_cubit.dart
@@ -66,6 +66,10 @@ class PaymentCubit extends Cubit<PaymentProcessingState> {
}
}
+ void emitError(Object e) {
+ emit(PaymentProcessingStateError(message: e.toString()));
+ }
+
void onUserDismissPaymentPopup() {
emit(PaymentProcessingStateNotStarted());
}