diff --git a/android/app/build.gradle b/android/app/build.gradle index bc2192c5..b95ac025 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -65,7 +65,14 @@ android { keyPassword keyProperties.getProperty('keyPassword') } } - debug {} + debug { + if (signingConfigExists) { + storeFile file(keyProperties.getProperty('storeFile')) + storePassword keyProperties.getProperty('storePassword') + keyAlias keyProperties.getProperty('keyAlias') + keyPassword keyProperties.getProperty('keyPassword') + } + } } buildTypes { diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 0356ad36..c459676d 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -44,14 +44,16 @@ - + - + - + - - - - - - - - @@ -171,15 +165,42 @@ + + + + + + + + + + + + + + + + + + + + - + - + 6.1.0) - - PolarBleSdk (6.1.0): - - RxSwift (~> 6.8.0) - - SwiftProtobuf (~> 1.0) - - Zip (~> 2.1.2) - - RxSwift (6.8.0) - - screen_state (1.0.0): - - Flutter - - SwiftProtobuf (1.33.3) - - Zip (2.1.2) - -DEPENDENCIES: - - audio_streamer (from `.symlinks/plugins/audio_streamer/ios`) - - dchs_flutter_beacon (from `.symlinks/plugins/dchs_flutter_beacon/ios`) - - Flutter (from `Flutter`) - - flutter_activity_recognition (from `.symlinks/plugins/flutter_activity_recognition/ios`) - - flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`) - - flutter_sound (from `.symlinks/plugins/flutter_sound/ios`) - - flutter_web_auth_2 (from `.symlinks/plugins/flutter_web_auth_2/ios`) - - health (from `.symlinks/plugins/health/ios`) - - location (from `.symlinks/plugins/location/ios`) - - mdsflutter (from `.symlinks/plugins/mdsflutter/ios`) - - Movesense (from `https://bitbucket.org/movesense/movesense-mobile-lib/`) - - oidc_ios (from `.symlinks/plugins/oidc_ios/ios`) - - open_settings_plus (from `.symlinks/plugins/open_settings_plus/ios`) - - permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`) - - polar (from `.symlinks/plugins/polar/ios`) - - screen_state (from `.symlinks/plugins/screen_state/ios`) - -SPEC REPOS: - trunk: - - flutter_sound_core - - PolarBleSdk - - RxSwift - - SwiftProtobuf - - Zip - -EXTERNAL SOURCES: - audio_streamer: - :path: ".symlinks/plugins/audio_streamer/ios" - dchs_flutter_beacon: - :path: ".symlinks/plugins/dchs_flutter_beacon/ios" - Flutter: - :path: Flutter - flutter_activity_recognition: - :path: ".symlinks/plugins/flutter_activity_recognition/ios" - flutter_secure_storage: - :path: ".symlinks/plugins/flutter_secure_storage/ios" - flutter_sound: - :path: ".symlinks/plugins/flutter_sound/ios" - flutter_web_auth_2: - :path: ".symlinks/plugins/flutter_web_auth_2/ios" - health: - :path: ".symlinks/plugins/health/ios" - location: - :path: ".symlinks/plugins/location/ios" - mdsflutter: - :path: ".symlinks/plugins/mdsflutter/ios" - Movesense: - :git: https://bitbucket.org/movesense/movesense-mobile-lib/ - oidc_ios: - :path: ".symlinks/plugins/oidc_ios/ios" - open_settings_plus: - :path: ".symlinks/plugins/open_settings_plus/ios" - permission_handler_apple: - :path: ".symlinks/plugins/permission_handler_apple/ios" - polar: - :path: ".symlinks/plugins/polar/ios" - screen_state: - :path: ".symlinks/plugins/screen_state/ios" - -CHECKOUT OPTIONS: - Movesense: - :commit: 580c812f2696ff05ed2c1c1e93053c137ef7942a - :git: https://bitbucket.org/movesense/movesense-mobile-lib/ - -SPEC CHECKSUMS: - audio_streamer: 2e472b9f81cec5e381c4cf7667afa3055dcb45a4 - dchs_flutter_beacon: 88d72cc467de508d621e454ea66c6231d0897d4c - Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467 - flutter_activity_recognition: 52dfad4c1e9cec99f0841b3ed0efcc9d424b3deb - flutter_secure_storage: 1ed9476fba7e7a782b22888f956cce43e2c62f13 - flutter_sound: d95194f6476c9ad211d22b3a414d852c12c7ca44 - flutter_sound_core: 7f2626d249d3a57bfa6da892ef7e22d234482c1a - flutter_web_auth_2: 5c8d9dcd7848b5a9efb086d24e7a9adcae979c80 - health: fe206e65f13a9b88623605fbd8af8f029e23dc35 - location: 155caecf9da4f280ab5fe4a55f94ceccfab838f8 - mdsflutter: bd3c0b3335d50947d1a192cf70f930e0fb04a766 - Movesense: dc64047c1feb856b7f7ac6ea2c67685350d99dd5 - oidc_ios: 16966cad509ce6850ca4ca1216c5138bef2a8726 - open_settings_plus: d19f91e8a04649358a51c19b484ce2e637149d70 - permission_handler_apple: 4ed2196e43d0651e8ff7ca3483a069d469701f2d - polar: 0374f6063ade7e2dd85d626f87cbe2393d3eda7c - PolarBleSdk: bfb57cf8350f0c53d441b8632ba6df363ce7c79f - RxSwift: 4e28be97cbcfeee614af26d83415febbf2bf6f45 - screen_state: 52d6e997d31bddba6417c60d9cdd22effd0320a7 - SwiftProtobuf: e1b437c8e31a4c5577b643249a0bb62ed4f02153 - Zip: b3fef584b147b6e582b2256a9815c897d60ddc67 - -PODFILE CHECKSUM: 45842edf150243fea66883d4dfad1e5ddb428147 - -COCOAPODS: 1.16.2 diff --git a/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 7f1c67b8..a71b474b 100644 --- a/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,14 +1,5 @@ { "pins" : [ - { - "identity" : "appauth-ios", - "kind" : "remoteSourceControl", - "location" : "https://github.com/openid/AppAuth-iOS", - "state" : { - "revision" : "145104f5ea9d58ae21b60add007c33c1cc0c948e", - "version" : "2.0.0" - } - }, { "identity" : "phonenumberkit", "kind" : "remoteSourceControl", diff --git a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index e596a992..f613b6b9 100644 --- a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,7 +1,7 @@ + version = "1.7"> @@ -91,6 +91,13 @@ ReferencedContainer = "container:Runner.xcodeproj"> + + + + CFBundleURLSchemes carp-studies + carp-studies-anonymous carp-studies-auth diff --git a/ios/Runner/Runner.entitlements b/ios/Runner/Runner.entitlements index b8ebe5cc..0fe07231 100644 --- a/ios/Runner/Runner.entitlements +++ b/ios/Runner/Runner.entitlements @@ -4,7 +4,9 @@ com.apple.developer.associated-domains - applinks:carp.computerome.dk + applinks:study.app.dev.carp.dk + applinks:study.app.test.carp.dk + applinks:study.app.carp.computerome.dk com.apple.developer.authentication-services.autofill-credential-provider diff --git a/ios/Runner/RunnerRelease.entitlements b/ios/Runner/RunnerRelease.entitlements index 94a192bd..8521f0b3 100644 --- a/ios/Runner/RunnerRelease.entitlements +++ b/ios/Runner/RunnerRelease.entitlements @@ -6,8 +6,8 @@ development com.apple.developer.associated-domains - webcredentials:carp.computerome.com - applinks:carp.computerome.dk + applinks:app.dev.carp.dk + applinks:app.carp.computerome.dk com.apple.developer.authentication-services.autofill-credential-provider diff --git a/lib/carp_study_app.dart b/lib/carp_study_app.dart index eb34048e..446d7a94 100644 --- a/lib/carp_study_app.dart +++ b/lib/carp_study_app.dart @@ -154,6 +154,26 @@ class CarpStudyAppState extends State { return task?.widget ?? const ErrorPage(); }, ), + // Handle external magic-link callbacks from the auth server. The + // identity provider posts a link like + // /auth/realms/Carp/login-actions/action-token?key=... + // We attempt to authenticate using the URI. On + // success we go to '/', on failure we redirect to the login page. + GoRoute( + path: '/auth/realms/Carp/login-actions/action-token', + parentNavigatorKey: _rootNavigatorKey, + redirect: (context, state) async { + // We don't show any page, but handle the magic link in the background. + try { + await bloc.backend.authenticateWithMagicLink(state.uri.toString()); + return homeRoute; + } catch (error) { + debugPrint( + 'Magic-link authentication failed: $error, redirecting to login page'); + return LoginPage.route; + } + }, + ), GoRoute( path: LoginPage.route, parentNavigatorKey: _rootNavigatorKey, diff --git a/lib/data/carp_backend.dart b/lib/data/carp_backend.dart index 52a08e8a..af666c47 100644 --- a/lib/data/carp_backend.dart +++ b/lib/data/carp_backend.dart @@ -57,7 +57,7 @@ class CarpBackend { authURL: uri, clientId: 'studies-app', redirectURI: Uri.parse('carp-studies-auth://auth'), - anonymousRedirectURI: Uri.parse('carp-studies:/anonymous'), + anonymousRedirectURI: Uri.parse('carp-studies-anonymous://anonymous'), // For authentication at CAWS the path is '/auth/realms/Carp' discoveryURL: uri.replace(pathSegments: [ 'auth', @@ -115,12 +115,15 @@ class CarpBackend { Future authenticateWithMagicLink(String uri) async { try { await initialize(); + if (Platform.isIOS) { + sleep(const Duration(seconds: 1)); + } user = await CarpAuthService().authenticateWithMagicLink(uri); LocalSettings().isAnonymous = true; - info('$runtimeType - ANONYMOUS User authenticated - user: $user'); + print('$runtimeType - ANONYMOUS User authenticated - user: $user'); } catch (error) { user = null; - warning('$runtimeType - ANONYMOUS Error authenticating user - $error'); + print('$runtimeType - ANONYMOUS Error authenticating user - $error'); } } diff --git a/lib/main.dart b/lib/main.dart index 94c7a691..0fc4ec59 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -9,7 +9,6 @@ import 'dart:io'; import 'package:app_version_update/data/models/app_version_result.dart'; import 'package:async/async.dart'; -import 'package:flutter/cupertino.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; diff --git a/lib/ui/pages/login_page.dart b/lib/ui/pages/login_page.dart index fcc72f02..9bf54a7a 100644 --- a/lib/ui/pages/login_page.dart +++ b/lib/ui/pages/login_page.dart @@ -68,10 +68,15 @@ class _LoginPageState extends State { child: TextButton( onPressed: () async { bool isConnected = await bloc.checkConnectivity(); + print("isConnected: $isConnected"); if (isConnected) { await bloc.backend.initialize(); await bloc.backend.authenticate(); - if (context.mounted) context.go(CarpStudyAppState.homeRoute); + if (context.mounted) { + WidgetsBinding.instance.addPostFrameCallback((_) { + context.go(CarpStudyAppState.homeRoute); + }); + } } else { showDialog( context: context, diff --git a/lib/ui/pages/qr_scanner.dart b/lib/ui/pages/qr_scanner.dart index b67ec16e..db4821e5 100644 --- a/lib/ui/pages/qr_scanner.dart +++ b/lib/ui/pages/qr_scanner.dart @@ -6,11 +6,11 @@ class QRViewExample extends StatefulWidget { @override State createState() => _QRViewExampleState(); } + final GlobalKey qrKey = GlobalKey(debugLabel: 'QR'); class _QRViewExampleState extends State { qr.Barcode? result; qr.QRViewController? controller; - final GlobalKey qrKey = GlobalKey(debugLabel: 'QR'); // In order to get hot reload to work we need to pause the camera if the platform // is android, or resume the camera if the platform is iOS. @@ -115,6 +115,7 @@ class _QRViewExampleState extends State { }); final qrcode = scanData.code; + print('QR code scanned: $qrcode'); if (qrcode != null && Uri.tryParse(qrcode)?.hasAbsolutePath == true) { await bloc.backend.authenticateWithMagicLink(qrcode).then((_) { diff --git a/pubspec.lock b/pubspec.lock index 569ab9b3..e8d3a31a 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -93,10 +93,10 @@ packages: dependency: transitive description: name: audioplayers - sha256: a72dd459d1a48f61a6fb9c0134dba26597c9236af40639ff0eb70eb4e0baab70 + sha256: f16640453cc47487b7de72a2b28d37c7df1ac97999849f4a46d92b1d2b0f093d url: "https://pub.dev" source: hosted - version: "6.6.0" + version: "6.7.1" audioplayers_android: dependency: transitive description: @@ -133,18 +133,18 @@ packages: dependency: transitive description: name: audioplayers_web - sha256: faa8fa6587f996a6f604433b53af44c57a1407d4fe8dff5766cf63d6875e8de9 + sha256: "24a6f258062bd7da8cb2157e83fccb9816a08dd306cbaaa24f9813d071470545" url: "https://pub.dev" source: hosted - version: "5.2.0" + version: "5.2.1" audioplayers_windows: dependency: transitive description: name: audioplayers_windows - sha256: bafff2b38b6f6d331887558ba6e0a01c9c208d9dbb3ad0005234db065122a734 + sha256: "95f875a96c88c3dbbcb608d4f8288e300b0113d256a81d0b3197fcc18f0dc91a" url: "https://pub.dev" source: hosted - version: "4.3.0" + version: "4.3.1" base_codecs: dependency: transitive description: @@ -370,12 +370,11 @@ packages: source: hosted version: "0.0.5" carp_webservices: - dependency: "direct main" + dependency: "direct overridden" description: - name: carp_webservices - sha256: "6459af381237f38e65e6300763cddc04186c69e746ab97210f8134426e8a17dc" - url: "https://pub.dev" - source: hosted + path: "../carp.sensing-flutter/backends/carp_webservices" + relative: true + source: path version: "3.8.0" characters: dependency: transitive @@ -421,10 +420,10 @@ packages: dependency: transitive description: name: code_assets - sha256: "67cf6d84013f9c601e42a6f8a6b74c4c0d9dc1a1619d775f2b28b732d3551b85" + sha256: bf394f466ba9205f1812a0433b392d6af280f155f56651eda7c18cc32ed493b8 url: "https://pub.dev" source: hosted - version: "1.2.0" + version: "1.2.1" code_builder: dependency: transitive description: @@ -557,10 +556,10 @@ packages: dependency: transitive description: name: dbus - sha256: d0c98dcd4f5169878b6cf8f6e0a52403a9dff371a3e2f019697accbf6f44a270 + sha256: "0ce9b0a839e6dee59a37a623d2fc26a35bbbe6404213e419b0d6411023d62645" url: "https://pub.dev" source: hosted - version: "0.7.12" + version: "0.7.14" dchs_flutter_beacon: dependency: transitive description: @@ -799,10 +798,10 @@ packages: dependency: "direct main" description: name: flutter_plugin_android_lifecycle - sha256: "38d1c268de9097ff59cf0e844ac38759fc78f76836d37edad06fa21e182055a0" + sha256: "3854fe5e3bff0b113c658f260b90c95dea17c92db0f2addeac2e343dd9969785" url: "https://pub.dev" source: hosted - version: "2.0.34" + version: "2.0.35" flutter_secure_storage: dependency: transitive description: @@ -977,10 +976,10 @@ packages: dependency: transitive description: name: hooks - sha256: a41af4e8fc687cd6d33de9751eb936c8c0204ebe2bcb6c15ecf707504bf47f31 + sha256: "9a62a50b50b769a737bc0a8ff381f333529df3ab746b2f6b02e83760231455ba" url: "https://pub.dev" source: hosted - version: "2.0.0" + version: "2.0.2" html: dependency: transitive description: @@ -1257,10 +1256,10 @@ packages: dependency: transitive description: name: meta - sha256: "1741988757a65eb6b36abe716829688cf01910bbf91c34354ff7ec1c3de2b349" + sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394" url: "https://pub.dev" source: hosted - version: "1.18.0" + version: "1.17.0" mime: dependency: transitive description: @@ -1585,10 +1584,10 @@ packages: dependency: transitive description: name: permission_handler_apple - sha256: f000131e755c54cf4d84a5d8bd6e4149e262cc31c5a8b1d698de1ac85fa41023 + sha256: e20daf680eef1ca62ffe8c8c526b778cc386d50137c77ac71c8ec9c88c13fb9d url: "https://pub.dev" source: hosted - version: "9.4.7" + version: "9.4.9" permission_handler_html: dependency: transitive description: @@ -1697,10 +1696,10 @@ packages: dependency: "direct main" description: name: qr_code_scanner_plus - sha256: dae0596b2763c2fd0294f5cfddb1d3a21577ae4dc7fc1449eb5aafc957872f61 + sha256: "2bcf9df32aa639fba07c183b1ab9c3f03eb6b1d688ab4f4f6bc868a75afd824d" url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" recase: dependency: transitive description: @@ -2046,26 +2045,26 @@ packages: dependency: "direct dev" description: name: test - sha256: "8d9ceddbab833f180fbefed08afa76d7c03513dfdba87ffcec2718b02bbcbf20" + sha256: "280d6d890011ca966ad08df7e8a4ddfab0fb3aa49f96ed6de56e3521347a9ae7" url: "https://pub.dev" source: hosted - version: "1.31.0" + version: "1.30.0" test_api: dependency: transitive description: name: test_api - sha256: "949a932224383300f01be9221c39180316445ecb8e7547f70a41a35bf421fb9e" + sha256: "8161c84903fd860b26bfdefb7963b3f0b68fee7adea0f59ef805ecca346f0c7a" url: "https://pub.dev" source: hosted - version: "0.7.11" + version: "0.7.10" test_core: dependency: transitive description: name: test_core - sha256: "1991d4cfe85d5043241acac92962c3977c8d2f2add1ee73130c7b286417d1d34" + sha256: "0381bd1585d1a924763c308100f2138205252fb90c9d4eeaf28489ee65ccde51" url: "https://pub.dev" source: hosted - version: "0.6.17" + version: "0.6.16" timeago: dependency: "direct main" description: @@ -2206,10 +2205,10 @@ packages: dependency: transitive description: name: vector_graphics_compiler - sha256: b9b3f391857781aa96acacef96066f2f49b4cd03cf9fce3ca4d8da2ef5ea129e + sha256: "7ee12e6dffe0fc8e755179d6d91b3b34f5924223fc104d85572ef9180d73d172" url: "https://pub.dev" source: hosted - version: "1.2.3" + version: "1.2.5" vector_math: dependency: transitive description: @@ -2334,10 +2333,10 @@ packages: dependency: transitive description: name: window_to_front - sha256: "7aef379752b7190c10479e12b5fd7c0b9d92adc96817d9e96c59937929512aee" + sha256: "14fad8984db4415e2eeb30b04bb77140b180e260d6cb66b26de126a8657a9241" url: "https://pub.dev" source: hosted - version: "0.0.3" + version: "0.0.4" x509_plus: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 39b3f24d..e33e3d34 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -23,7 +23,7 @@ dependencies: carp_movesense_package: ^1.7.2 carp_themes_package: ^0.0.5 - carp_webservices: ^3.8.0 + # carp_webservices: ^3.8.0 carp_backend: ^1.9.2 research_package: ^2.2.0 @@ -93,8 +93,8 @@ dependency_overrides: # path: ../carp/carp.sensing-flutter/packages/carp_health_package/ # carp_movesense_package: # path: ../carp/carp.sensing-flutter/packages/carp_movesense_package/ - # carp_webservices: - # path: ../carp.sensing-flutter/backends/carp_webservices/ + carp_webservices: + path: ../carp.sensing-flutter/backends/carp_webservices/ # carp_backend: # path: ../carp/carp.sensing-flutter/backends/carp_backend/ # research_package: