v2.1.0: Added unknown (default) value to the AuthenticationStatus enum

Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>
This commit is contained in:
2026-07-29 21:56:51 +02:00
parent 0078e344fd
commit 60d7b6f97e
7 changed files with 127 additions and 11 deletions
+11
View File
@@ -1,3 +1,14 @@
## 2.1.0
### Authentication Service
- [NEW] Added `AuthenticationStatus.unknown` as the new default authentication state (replaces `unauthenticated` as default).
- [NEW] Added `AuthenticationStatus.isUnknown` getter to explicitly check for unknown state.
- [CHANGE] `AuthenticationStatus.isUnauthenticated` now returns `true` for both `unauthenticated` and `unknown` states (use `isUnknown` to distinguish).
- [CHANGE] `ArcaneAuthenticationService` now initializes with `AuthenticationStatus.unknown` instead of `unauthenticated`.
- [CHANGE] `ArcaneAuthenticationService.reset()` now resets status to `unknown`.
- [CHANGE] Updated tests to reflect new default status behavior.
## 2.0.6 ## 2.0.6
### Arcane Framework ### Arcane Framework
+31
View File
@@ -966,6 +966,37 @@ void dispose() {
} }
``` ```
#### Authentication Status
The `AuthenticationStatus` enum represents the current authentication state:
| Status | Description |
| ----------------- | ----------------------------------------------------------- |
| `authenticated` | The user is authenticated and signed in. |
| `unauthenticated` | The user is not authenticated (explicitly signed out). |
| `unknown` | The authentication status is not yet known (initial state). |
Use the provided getters to check the current status:
```dart
// Check if user is authenticated
if (Arcane.auth.status.isAuthenticated) {
// User is signed in
}
// Check if user is explicitly unauthenticated (signed out)
if (Arcane.auth.status.isUnauthenticated) {
// User is not signed in
}
// Check if authentication status is still being determined
if (Arcane.auth.status.isUnknown) {
// Show loading indicator, etc.
}
```
The default status is `unknown` until an authentication interface is registered and initialized. After calling `reset()`, the status returns to `unknown`.
### Application Environments ### Application Environments
Arcane environments are value-based and extensible. Two built-in values are Arcane environments are value-based and extensible. Two built-in values are
@@ -27,6 +27,7 @@ enum SignUpStep {
/// This enum has two possible states: /// This enum has two possible states:
/// - `authenticated`: The user is authenticated. /// - `authenticated`: The user is authenticated.
/// - `unauthenticated`: The user is not authenticated. /// - `unauthenticated`: The user is not authenticated.
/// - `unknown` (default): The authentication status is not yet known.
/// ///
/// Example: /// Example:
/// ```dart /// ```dart
@@ -40,11 +41,17 @@ enum AuthenticationStatus {
authenticated, authenticated,
/// The user is not authenticated. /// The user is not authenticated.
unauthenticated; unauthenticated,
/// The authentication status is currently unknown.
unknown;
/// Returns `true` if the current status is `authenticated`. /// Returns `true` if the current status is `authenticated`.
bool get isAuthenticated => this == authenticated; bool get isAuthenticated => this == authenticated;
/// Returns `true` if the current status is `unauthenticated`. /// Returns `true` if the current status is not `authenticated`.
bool get isUnauthenticated => this == unauthenticated; bool get isUnauthenticated => !isAuthenticated;
/// Returns `true` if the current status is `unknown`.
bool get isUnknown => this == unknown;
} }
@@ -20,7 +20,7 @@ class ArcaneAuthenticationService extends ArcaneService {
static ArcaneAuthenticationService get I => _instance; static ArcaneAuthenticationService get I => _instance;
final ValueNotifier<AuthenticationStatus> _notifier = final ValueNotifier<AuthenticationStatus> _notifier =
ValueNotifier<AuthenticationStatus>(AuthenticationStatus.unauthenticated); ValueNotifier<AuthenticationStatus>(AuthenticationStatus.unknown);
/// A `ValueNotifier` that emits the current `AuthenticationStatus`. /// A `ValueNotifier` that emits the current `AuthenticationStatus`.
ValueNotifier<AuthenticationStatus> get notifier => _notifier; ValueNotifier<AuthenticationStatus> get notifier => _notifier;
@@ -54,7 +54,7 @@ class ArcaneAuthenticationService extends ArcaneService {
ArcaneAuthInterface? get authInterface => _authInterface; ArcaneAuthInterface? get authInterface => _authInterface;
/// Returns `true` when the current status is authenticated. /// Returns `true` when the current status is authenticated.
bool get isAuthenticated => status == AuthenticationStatus.authenticated; bool get isAuthenticated => status.isAuthenticated;
final ValueNotifier<bool> _isSignedIn = ValueNotifier<bool>(false); final ValueNotifier<bool> _isSignedIn = ValueNotifier<bool>(false);
@@ -86,7 +86,7 @@ class ArcaneAuthenticationService extends ArcaneService {
/// default. /// default.
Future<void> reset() async { Future<void> reset() async {
_authInterface = null; _authInterface = null;
_notifier.value = AuthenticationStatus.unauthenticated; _notifier.value = AuthenticationStatus.unknown;
_isSignedIn.value = isAuthenticated; _isSignedIn.value = isAuthenticated;
_statusController.add(_notifier.value); _statusController.add(_notifier.value);
_signedInController.add(_isSignedIn.value); _signedInController.add(_isSignedIn.value);
+1 -1
View File
@@ -1,7 +1,7 @@
name: arcane_framework name: arcane_framework
description: "Agnostic Reusable Component Architecture for New Ecosystems: a description: "Agnostic Reusable Component Architecture for New Ecosystems: a
modern framework for bootstrapping new applications" modern framework for bootstrapping new applications"
version: 2.0.6 version: 2.1.0
repository: https://github.com/hanskokx/arcane_framework repository: https://github.com/hanskokx/arcane_framework
issue_tracker: https://github.com/hanskokx/arcane_framework/issues issue_tracker: https://github.com/hanskokx/arcane_framework/issues
@@ -13,10 +13,17 @@ void main() {
test("isAuthenticated returns true only for authenticated", () { test("isAuthenticated returns true only for authenticated", () {
expect(AuthenticationStatus.authenticated.isAuthenticated, isTrue); expect(AuthenticationStatus.authenticated.isAuthenticated, isTrue);
expect(AuthenticationStatus.unauthenticated.isAuthenticated, isFalse); expect(AuthenticationStatus.unauthenticated.isAuthenticated, isFalse);
expect(AuthenticationStatus.unknown.isAuthenticated, isFalse);
}); });
test("isUnauthenticated returns true only for unauthenticated", () { test("isUnauthenticated returns true for unauthenticated and unknown", () {
expect(AuthenticationStatus.authenticated.isUnauthenticated, isFalse); expect(AuthenticationStatus.authenticated.isUnauthenticated, isFalse);
expect(AuthenticationStatus.unauthenticated.isUnauthenticated, isTrue); expect(AuthenticationStatus.unauthenticated.isUnauthenticated, isTrue);
expect(AuthenticationStatus.unknown.isUnauthenticated, isTrue);
});
test("isUnknown returns true only for unknown", () {
expect(AuthenticationStatus.authenticated.isUnknown, isFalse);
expect(AuthenticationStatus.unauthenticated.isUnknown, isFalse);
expect(AuthenticationStatus.unknown.isUnknown, isTrue);
}); });
}); });
} }
@@ -28,7 +28,7 @@ void main() {
expect(ArcaneAuthenticationService.I.authInterface, isNull); expect(ArcaneAuthenticationService.I.authInterface, isNull);
expect( expect(
ArcaneAuthenticationService.I.status, ArcaneAuthenticationService.I.status,
AuthenticationStatus.unauthenticated, AuthenticationStatus.unknown,
); );
expect(ArcaneAuthenticationService.I.isSignedIn.value, false); expect(ArcaneAuthenticationService.I.isSignedIn.value, false);
}); });
@@ -225,7 +225,67 @@ void main() {
test("notifier getter reflects unauthenticated default", () { test("notifier getter reflects unauthenticated default", () {
expect( expect(
ArcaneAuthenticationService.I.notifier.value, ArcaneAuthenticationService.I.notifier.value,
AuthenticationStatus.unauthenticated, AuthenticationStatus.unknown,
);
});
test("isUnknown getter reflects unknown status", () {
expect(
ArcaneAuthenticationService.I.status.isUnknown,
isTrue,
);
});
test("isUnknown getter reflects unknown status after a reset", () async {
expect(
ArcaneAuthenticationService.I.status.isUnknown,
isTrue,
);
ArcaneAuthenticationService.I.setAuthenticated();
expect(
ArcaneAuthenticationService.I.status.isUnknown,
isFalse,
);
expect(
ArcaneAuthenticationService.I.status.isAuthenticated,
isTrue,
);
ArcaneAuthenticationService.I.setUnauthenticated();
expect(
ArcaneAuthenticationService.I.status.isUnknown,
isFalse,
);
expect(
ArcaneAuthenticationService.I.status.isAuthenticated,
isFalse,
);
expect(
ArcaneAuthenticationService.I.status.isUnauthenticated,
isTrue,
);
await ArcaneAuthenticationService.I.reset();
expect(
ArcaneAuthenticationService.I.status.isUnknown,
isTrue,
);
expect(
ArcaneAuthenticationService.I.status.isAuthenticated,
isFalse,
);
expect(
ArcaneAuthenticationService.I.status.isUnauthenticated,
isTrue,
); );
}); });
@@ -334,7 +394,7 @@ void main() {
expect(result.isFailure, true); expect(result.isFailure, true);
expect( expect(
ArcaneAuthenticationService.I.status, ArcaneAuthenticationService.I.status,
equals(AuthenticationStatus.unauthenticated), equals(AuthenticationStatus.unknown),
); );
}); });