mirror of
https://github.com/hanskokx/arcane_implementations.git
synced 2026-05-14 02:19:05 +02:00
Added dev.log interface and microsoft entra (AD SSO) interface
Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>
This commit is contained in:
@@ -0,0 +1,105 @@
|
|||||||
|
import 'package:aad_oauth/aad_oauth.dart';
|
||||||
|
import 'package:aad_oauth/model/config.dart';
|
||||||
|
import 'package:arcane_framework/arcane_framework.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class MicrosoftEntraInterface implements ArcaneAuthInterface {
|
||||||
|
MicrosoftEntraInterface._internal();
|
||||||
|
static final ArcaneAuthInterface _instance =
|
||||||
|
MicrosoftEntraInterface._internal();
|
||||||
|
static ArcaneAuthInterface get I => _instance;
|
||||||
|
|
||||||
|
static bool _mocked = false;
|
||||||
|
|
||||||
|
AadOAuth? _oauth;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<String?>? get refreshToken async {
|
||||||
|
if (!await isSignedIn) return null;
|
||||||
|
|
||||||
|
final result = await _oauth?.refreshToken();
|
||||||
|
|
||||||
|
if (result == null) return null;
|
||||||
|
|
||||||
|
return result.fold(
|
||||||
|
(l) => null,
|
||||||
|
(r) async => r.refreshToken,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<String?> get accessToken async =>
|
||||||
|
_oauth?.getAccessToken() ?? Future.value(null);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<bool> get isSignedIn async =>
|
||||||
|
_oauth?.hasCachedAccountInformation ?? Future.value(false);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> init() async {
|
||||||
|
if (_mocked) return;
|
||||||
|
if (_oauth != null) return;
|
||||||
|
|
||||||
|
final String? tenant = AppEnv.valueOf(EnvVar.adSsoTenant);
|
||||||
|
final String? clientId = AppEnv.valueOf(EnvVar.adSsoClientId);
|
||||||
|
final String? scope = AppEnv.valueOf(EnvVar.adSsoScope);
|
||||||
|
final String? redirectUri = AppEnv.valueOf(EnvVar.adSsoRedirectUri);
|
||||||
|
|
||||||
|
if (tenant == null) throw const FormatException('Tenant must not be null.');
|
||||||
|
if (clientId == null)
|
||||||
|
throw const FormatException('Client ID must not be null.');
|
||||||
|
if (scope == null) throw const FormatException('Scope must not be null.');
|
||||||
|
if (redirectUri == null)
|
||||||
|
throw const FormatException('Redirect URI must not be null.');
|
||||||
|
|
||||||
|
final Config config = Config(
|
||||||
|
tenant: tenant,
|
||||||
|
clientId: clientId,
|
||||||
|
scope: scope,
|
||||||
|
redirectUri: redirectUri,
|
||||||
|
navigatorKey:
|
||||||
|
navigatorKey, // Should be a GlobalKey<NavigatorState>() in the app's router
|
||||||
|
);
|
||||||
|
|
||||||
|
_oauth = AadOAuth(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<Result<void, String>> login<T>(
|
||||||
|
{T? input, Future<void> Function()? onLoggedIn}) async {
|
||||||
|
if (_mocked) return Result.ok(null);
|
||||||
|
if (_oauth == null) await init();
|
||||||
|
|
||||||
|
if (await isSignedIn) return Result.ok(null);
|
||||||
|
|
||||||
|
final result = await _oauth!.login();
|
||||||
|
|
||||||
|
return result.fold(
|
||||||
|
(l) {
|
||||||
|
print(l);
|
||||||
|
return Result.error('Microsoft Authentication Failed!');
|
||||||
|
},
|
||||||
|
(r) async {
|
||||||
|
if (onLoggedIn != null) await onLoggedIn();
|
||||||
|
return Result.ok(null);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<Result<void, String>> logout() async {
|
||||||
|
if (_mocked) return Result.ok(null);
|
||||||
|
if (_oauth == null) await init();
|
||||||
|
|
||||||
|
if (!await isSignedIn) return Result.error('Not signed in');
|
||||||
|
|
||||||
|
await _oauth?.logout();
|
||||||
|
|
||||||
|
return Result.ok(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@visibleForTesting
|
||||||
|
static void setMocked() {
|
||||||
|
_mocked = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
import 'dart:developer' as dev;
|
||||||
|
|
||||||
|
import 'package:arcane_framework/arcane_framework.dart';
|
||||||
|
import 'package:arcane_helper_utils/arcane_helper_utils.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
|
||||||
|
class DevLog implements LoggingInterface {
|
||||||
|
static final DevLog _instance = DevLog._internal();
|
||||||
|
static DevLog get I => _instance;
|
||||||
|
|
||||||
|
final bool _initialized = true;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool get initialized => I._initialized;
|
||||||
|
|
||||||
|
DevLog._internal();
|
||||||
|
|
||||||
|
@visibleForTesting
|
||||||
|
void setMocked() => _mocked = true;
|
||||||
|
bool _mocked = false;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void log(
|
||||||
|
String message, {
|
||||||
|
Map<String, dynamic>? metadata,
|
||||||
|
Level? level,
|
||||||
|
StackTrace? stackTrace,
|
||||||
|
Object? extra,
|
||||||
|
}) {
|
||||||
|
// If the string is too long, the message won't print. This _shouldn't_ be
|
||||||
|
// the case with `log`, yet here we are.
|
||||||
|
for (final String part in message.splitByLength(256)) {
|
||||||
|
dev.log(part);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<LoggingInterface?> init() async {
|
||||||
|
if (_mocked) return null;
|
||||||
|
|
||||||
|
return I;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user