Skip to content

Commit

Permalink
feat: add TMS Connection, add Prefix to flavor, implement SP Request (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
Grodien authored Oct 28, 2024
1 parent c5ae57b commit 25270ee
Show file tree
Hide file tree
Showing 27 changed files with 377 additions and 133 deletions.
4 changes: 2 additions & 2 deletions das_client/integration_test/di.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ class IntegrationTestDI {
GetIt.I.registerTokenSpecProvider();
GetIt.I.registerOidcClient();
_registerIntegrationTestAuthenticator();
GetIt.I.registerBackendService();
GetIt.I.registerSferaAuthService();
_registerMqttClientConnector();
GetIt.I.registerMqttService();
GetIt.I.registerRepositories();
GetIt.I.registerServices();
GetIt.I.registerSferaService();
_initialized = true;
}
return GetIt.I.allReady();
Expand Down
2 changes: 1 addition & 1 deletion das_client/integration_test/test/fahrbild_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ void main() {
await tester.pumpAndSettle(const Duration(seconds: 1));

// check if station is present
expect(find.text('unkown'), findsExactly(6));
expect(find.text('SO_W'), findsOneWidget);
});
});
}
6 changes: 5 additions & 1 deletion das_client/l10n/strings_de.arb
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,9 @@
"w_navigation_drawer_fahrtinfo_title": "Fahrtinfo",
"w_navigation_drawer_links_title": "Links",
"w_navigation_drawer_settings_title": "Einstellungen",
"w_navigation_drawer_profile_title": "Profil"
"w_navigation_drawer_profile_title": "Profil",
"p_login_connect_to_tms": "Mit TMS verbinden",
"p_login_login_button_text": "Login",
"p_login_login_button_description": "Mit Ihrem Account einloggen",
"p_login_login_failed": "Login fehlgeschlagen"
}
11 changes: 4 additions & 7 deletions das_client/lib/auth/auth_cubit.dart
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
import 'package:das_client/auth/authenticator.dart';
import 'package:das_client/di.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

part 'auth_state.dart';

class AuthCubit extends Cubit<AuthState> {
AuthCubit(
Authenticator authenticator,
) :
_authenticator = authenticator,
super(InitialAuthState());

final Authenticator _authenticator;
AuthCubit() : super(InitialAuthState());

String? get userId => (state is Authenticated) ? (state as Authenticated).userId : null;

Authenticator get _authenticator => DI.get<Authenticator>();

Future<void> init() async {
final isAuthenticated = await _authenticator.isAuthenticated;
if (isAuthenticated) {
Expand Down
66 changes: 42 additions & 24 deletions das_client/lib/di.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ import 'package:das_client/auth/azure_authenticator.dart';
import 'package:das_client/auth/token_spec_provider.dart';
import 'package:das_client/flavor.dart';
import 'package:das_client/repo/sfera_repository.dart';
import 'package:das_client/service/backend_service.dart';
import 'package:das_client/service/mqtt/mqtt_client_connector.dart';
import 'package:das_client/service/mqtt/mqtt_client_oauth_connector.dart';
import 'package:das_client/service/mqtt/mqtt_client_tms_oauth_connector.dart';
import 'package:das_client/service/mqtt/mqtt_service.dart';
import 'package:das_client/service/sfera/sfera_service.dart';
import 'package:das_client/service/sfera_auth_service.dart';
import 'package:fimber/fimber.dart';
import 'package:get_it/get_it.dart';
import 'package:sbb_oidc/sbb_oidc.dart';
Expand All @@ -20,6 +21,15 @@ class DI {
return GetIt.I.init(flavor);
}

static Future<void> reinitialize({required bool useTms}) async {
Fimber.i('Reinitialize dependency injection with useTms=$useTms');
final flavor = DI.get<Flavor>();
await GetIt.I.reset();
GetIt.I.init(flavor, useTms: useTms);

return GetIt.I.allReady();
}

static T get<T extends Object>({
String? instanceName,
dynamic param1,
Expand All @@ -36,36 +46,36 @@ class DI {
// Internal

extension GetItX on GetIt {
Future<void> init(Flavor flavor) async {
Future<void> init(Flavor flavor, {bool useTms = false}) async {
registerFlavor(flavor);
registerTokenSpecProvider();
registerOidcClient();
registerTokenSpecProvider(useTms: useTms);
registerOidcClient(useTms: useTms);
registerAzureAuthenticator();
registerBackendService();
registerMqttClientConnector();
registerMqttService();
registerSferaAuthService(useTms: useTms);
registerMqttClientConnector(useTms: useTms);
registerMqttService(useTms: useTms);
registerRepositories();
registerServices();
registerSferaService();
await allReady();
}

void registerFlavor(Flavor flavor) {
registerSingleton<Flavor>(flavor);
}

void registerTokenSpecProvider() {
void registerTokenSpecProvider({bool useTms = false}) {
factoryFunc() {
final flavor = get<Flavor>();
return flavor.authenticatorConfig.tokenSpecs;
return useTms ? flavor.tmsAuthenticatorConfig!.tokenSpecs : flavor.authenticatorConfig.tokenSpecs;
}

registerSingleton<TokenSpecProvider>(factoryFunc());
}

void registerOidcClient() {
void registerOidcClient({bool useTms = false}) {
factoryFunc() {
final flavor = get<Flavor>();
final authenticatorConfig = flavor.authenticatorConfig;
final authenticatorConfig = useTms ? flavor.tmsAuthenticatorConfig! : flavor.authenticatorConfig;
return SBBOpenIDConnect.createClient(
discoveryUrl: authenticatorConfig.discoveryUrl,
clientId: authenticatorConfig.clientId,
Expand All @@ -77,17 +87,21 @@ extension GetItX on GetIt {
registerSingletonAsync<OidcClient>(factoryFunc);
}

void registerMqttService() {
void registerMqttService({bool useTms = false}) {
final flavor = get<Flavor>();
registerSingletonWithDependencies<MqttService>(
() => MqttService(mqttUrl: flavor.mqttUrl, mqttClientConnector: get()),
() => MqttService(
mqttUrl: useTms ? flavor.tmsMqttUrl! : flavor.mqttUrl,
mqttClientConnector: get(),
prefix: flavor.mqttTopicPrefix),
dependsOn: [MqttClientConnector]);
}

void registerBackendService() {
void registerSferaAuthService({bool useTms = false}) {
final flavor = get<Flavor>();
registerSingletonWithDependencies<BackendService>(
() => BackendService(authenticator: get(), backendUrl: flavor.backendUrl),
registerSingletonWithDependencies<SferaAuthService>(
() => SferaAuthService(
authenticator: get(), tokenExchangeUrl: useTms ? flavor.tmsTokenExchangeUrl! : flavor.tokenExchangeUrl),
dependsOn: [Authenticator]);
}

Expand All @@ -106,19 +120,23 @@ extension GetItX on GetIt {
);
}

void registerMqttClientConnector() {
registerSingletonWithDependencies<MqttClientConnector>(
() => MqttClientOauthConnector(backendService: get(), authenticator: get()),
dependsOn: [Authenticator, BackendService]);
void registerMqttClientConnector({bool useTms = false}) {
if (useTms) {
registerSingletonWithDependencies<MqttClientConnector>(() => MqttClientTMSOauthConnector(sferaAuthService: get()),
dependsOn: [SferaAuthService]);
} else {
registerSingletonWithDependencies<MqttClientConnector>(
() => MqttClientOauthConnector(sferaAuthService: get(), authenticator: get()),
dependsOn: [Authenticator, SferaAuthService]);
}
}

void registerRepositories() {
registerSingletonAsync<SferaRepository>(() async => SferaRepository());
}

void registerServices() {
registerSingletonWithDependencies<SferaService>(
() => SferaService(mqttService: get(), sferaRepository: get()),
void registerSferaService() {
registerSingletonWithDependencies<SferaService>(() => SferaService(mqttService: get(), sferaRepository: get()),
dependsOn: [MqttService, SferaRepository]);
}
}
43 changes: 33 additions & 10 deletions das_client/lib/flavor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,40 +5,63 @@ import 'package:das_client/auth/token_spec_provider.dart';
enum Flavor {
dev(
displayName: 'Dev',
//backendUrl: 'http://localhost:8080',
backendUrl: 'https://sfera-mock.app.sbb.ch',
tokenExchangeUrl: 'https://sfera-mock.app.sbb.ch/customClaim/requestToken',
tmsTokenExchangeUrl: 'https://imts-token-provider-tms-vad-imtrackside-dev.apps.halon-ocp1-1-t.sbb-aws-test.net/token/exchange',
mqttUrl: 'wss://das-poc.messaging.solace.cloud',
authenticatorConfig: _authenticatorConfigDev,
tmsMqttUrl: 'wss://tms-vad-imtrackside-dev-mobile.messaging.solace.cloud',
authenticatorConfig: _authenticatorConfigMockDev,
tmsAuthenticatorConfig: _authenticatorConfigTmsDev,
mqttTopicPrefix: "thomas/",
),
inte(
displayName: 'Inte',
//backendUrl: 'http://localhost:8080',
backendUrl: 'https://sfera-mock.app.sbb.ch',
tokenExchangeUrl: 'https://sfera-mock.app.sbb.ch/customClaim/requestToken',
mqttUrl: 'wss://das-poc.messaging.solace.cloud',
authenticatorConfig: _authenticatorConfigInte,
),
prod(
displayName: 'Prod',
//backendUrl: 'http://localhost:8080',
backendUrl: 'https://sfera-mock.app.sbb.ch',
tokenExchangeUrl: 'https://sfera-mock.app.sbb.ch/customClaim/requestToken',
mqttUrl: 'wss://das-poc.messaging.solace.cloud',
authenticatorConfig: _authenticatorConfigProd,
);

const Flavor({
required this.displayName,
required this.backendUrl,
required this.tokenExchangeUrl,
this.tmsTokenExchangeUrl,
required this.mqttUrl,
this.tmsMqttUrl,
required this.authenticatorConfig,
this.tmsAuthenticatorConfig,
this.mqttTopicPrefix = ''
});

final String displayName;
final String backendUrl;
final String tokenExchangeUrl;
final String? tmsTokenExchangeUrl;
final String mqttUrl;
final String? tmsMqttUrl;
final AuthenticatorConfig authenticatorConfig;
final AuthenticatorConfig? tmsAuthenticatorConfig;
final String mqttTopicPrefix;
}

const _authenticatorConfigDev = AuthenticatorConfig(

const _authenticatorConfigTmsDev = AuthenticatorConfig(
discoveryUrl: "https://login.microsoftonline.com/2cda5d11-f0ac-46b3-967d-af1b2e1bd01a/v2.0/.well-known/openid-configuration",
clientId: '8af8281c-4f1d-47b5-ad77-526b1da61b2b',
redirectUrl: 'ch.sbb.das://sbbauth/redirect',
tokenSpecs: TokenSpecProvider([
TokenSpec(
id: TokenSpec.defaultTokenId,
displayName: 'User Token',
scopes: ['openid', 'profile', 'email', 'offline_access', '8af8281c-4f1d-47b5-ad77-526b1da61b2b/.default'],
),
]),
);

const _authenticatorConfigMockDev = AuthenticatorConfig(
discoveryUrl: "https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration",
clientId: '6025180f-123b-4f2f-9703-16e08fc221f0',
redirectUrl: 'ch.sbb.das://sbbauth/redirect',
Expand Down
3 changes: 1 addition & 2 deletions das_client/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@ Future<void> start(Flavor flavor) async {
Future<void> runDasApp() async {
runApp(MultiBlocProvider(
providers: [
BlocProvider(create: (context) => AuthCubit(DI.get())..init()),
BlocProvider(create: (context) => FahrbildCubit(sferaService: DI.get()))
BlocProvider(create: (context) => AuthCubit()..init()),
],
child: App(),
));
Expand Down
13 changes: 10 additions & 3 deletions das_client/lib/model/sfera/b2g_request.dart
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
import 'package:das_client/model/sfera/jp_request.dart';
import 'package:das_client/model/sfera/sfera_xml_element.dart';
import 'package:das_client/model/sfera/sp_request.dart';

class B2gRequest extends SferaXmlElement {
static const String elementType = "B2G_Request";

B2gRequest({super.type = elementType, super.attributes, super.children, super.value});

factory B2gRequest.create({JpRequest? jpRequest}) {
factory B2gRequest.createJPRequest(JpRequest jpRequest) {
final request = B2gRequest();
if (jpRequest != null) {
request.children.add(jpRequest);
request.children.add(jpRequest);
return request;
}

factory B2gRequest.createSPRequest(List<SpRequest> spRequests) {
final request = B2gRequest();
for (final spRequest in spRequests) {
request.children.add(spRequest);
}
return request;
}
Expand Down
17 changes: 17 additions & 0 deletions das_client/lib/model/sfera/sp_request.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import 'package:das_client/model/sfera/sfera_xml_element.dart';
import 'package:das_client/model/sfera/sp_zone.dart';

class SpRequest extends SferaXmlElement {
static const String elementType = "SP_Request";

SpRequest({super.type = elementType, super.attributes, super.children, super.value});

factory SpRequest.create({required String id, required String versionMajor, required String versionMinor, required SpZone spZone}) {
final request = SpRequest();
request.attributes["SP_ID"] = id;
request.attributes["SP_VersionMajor"] = versionMajor;
request.attributes["SP_VersionMinor"] = versionMinor;
request.children.add(spZone);
return request;
}
}
15 changes: 14 additions & 1 deletion das_client/lib/pages/fahrt/fahrt_page.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'package:auto_route/auto_route.dart';
import 'package:das_client/auth/auth_cubit.dart';
import 'package:das_client/bloc/fahrbild_cubit.dart';
import 'package:das_client/di.dart';
import 'package:das_client/i18n/src/build_context_x.dart';
import 'package:das_client/nav/app_router.dart';
import 'package:das_client/nav/das_navigation_drawer.dart';
Expand All @@ -14,12 +15,24 @@ import 'package:flutter_bloc/flutter_bloc.dart';
class FahrtPage extends StatelessWidget {
const FahrtPage({super.key});

@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => FahrbildCubit(sferaService: DI.get()),
child: const FahrtPageContent(),
);
}
}

class FahrtPageContent extends StatelessWidget {
const FahrtPageContent({super.key});

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: _appBar(context),
body: _body(context),
drawer: DASNavigationDrawer(),
drawer: const DASNavigationDrawer(),
);
}

Expand Down
Loading

0 comments on commit 25270ee

Please sign in to comment.