mirror of
https://github.com/hanskokx/arcane_framework.git
synced 2026-05-14 02:19:08 +02:00
v1.1.0
Breaking changes: - (ArcaneAuthInterface) Migrated `loginWithEmailAndPassword` to `login` - (ArcaneAuthInterface) Migrated `signup` to `register` Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>
This commit is contained in:
@@ -1,3 +1,14 @@
|
|||||||
|
## 1.1.0
|
||||||
|
|
||||||
|
- [BREAKING] Updated the authentication service and interface to be more versatile
|
||||||
|
|
||||||
|
### Migration
|
||||||
|
|
||||||
|
| Class | Migration path |
|
||||||
|
| ------------------- | -------------------------------------------------------------------------------------- |
|
||||||
|
| ArcaneAuthInterface | `loginWtihEmailAndPassword({String email, String password})` -> `login<T>({T? input})` |
|
||||||
|
| ArcaneAuthInterface | `signup({String email, String password})` -> `register<T>({T? input})` |
|
||||||
|
|
||||||
## 1.0.8
|
## 1.0.8
|
||||||
|
|
||||||
- Added the `extra` parameter to the `Arcane.log` shortcut method
|
- Added the `extra` parameter to the `Arcane.log` shortcut method
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import "package:arcane_framework/arcane_framework.dart";
|
import "package:arcane_framework/arcane_framework.dart";
|
||||||
|
|
||||||
typedef LoginInput = ({String email, String password});
|
typedef Credentials = ({String email, String password});
|
||||||
|
|
||||||
class DebugAuthInterface implements ArcaneAuthInterface {
|
class DebugAuthInterface implements ArcaneAuthInterface {
|
||||||
DebugAuthInterface._internal();
|
DebugAuthInterface._internal();
|
||||||
@@ -32,15 +32,8 @@ class DebugAuthInterface implements ArcaneAuthInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<Result<void, String>> loginWithEmailAndPassword({
|
Future<Result<void, String>> login<Credentials>({
|
||||||
required String email,
|
Credentials? input,
|
||||||
required String password,
|
|
||||||
}) async =>
|
|
||||||
throw UnimplementedError();
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<Result<void, String>> login<LoginInput>({
|
|
||||||
LoginInput? input,
|
|
||||||
Future<void> Function()? onLoggedIn,
|
Future<void> Function()? onLoggedIn,
|
||||||
}) async {
|
}) async {
|
||||||
final bool alreadyLoggedIn = await isSignedIn;
|
final bool alreadyLoggedIn = await isSignedIn;
|
||||||
@@ -66,11 +59,18 @@ class DebugAuthInterface implements ArcaneAuthInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<Result<SignUpStep, String>> signup({
|
Future<Result<SignUpStep, String>> register<Credentials>({
|
||||||
required String password,
|
Credentials? input,
|
||||||
required String email,
|
|
||||||
}) async {
|
}) async {
|
||||||
|
if (input != null) {
|
||||||
|
final credentials = input as ({String email, String password});
|
||||||
|
|
||||||
|
final String email = credentials.email;
|
||||||
|
final String password = credentials.password;
|
||||||
|
|
||||||
Arcane.log("Creating account for $email with password $password");
|
Arcane.log("Creating account for $email with password $password");
|
||||||
|
}
|
||||||
|
|
||||||
return Result.ok(SignUpStep.confirmSignUp);
|
return Result.ok(SignUpStep.confirmSignUp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,13 +14,13 @@ abstract class ArcaneAuthInterface {
|
|||||||
///
|
///
|
||||||
/// This is used to retrieve the current session's access token for authenticated
|
/// This is used to retrieve the current session's access token for authenticated
|
||||||
/// API requests. Returns `null` if the user is not signed in or the token is unavailable.
|
/// API requests. Returns `null` if the user is not signed in or the token is unavailable.
|
||||||
Future<String?> get accessToken;
|
Future<String?>? get accessToken;
|
||||||
|
|
||||||
/// Returns the refresh token if available.
|
/// Returns the refresh token if available.
|
||||||
///
|
///
|
||||||
/// The refresh token is used to renew access tokens when they expire. Returns `null` if
|
/// The refresh token is used to renew access tokens when they expire. Returns `null` if
|
||||||
/// the user is not signed in or the token is unavailable.
|
/// the user is not signed in or the token is unavailable.
|
||||||
Future<String?> get refreshToken;
|
Future<String?>? get refreshToken;
|
||||||
|
|
||||||
/// Initializes the authentication interface.
|
/// Initializes the authentication interface.
|
||||||
///
|
///
|
||||||
@@ -34,24 +34,6 @@ abstract class ArcaneAuthInterface {
|
|||||||
/// Returns a `Result` that either contains a `void` on success or an error message.
|
/// Returns a `Result` that either contains a `void` on success or an error message.
|
||||||
Future<Result<void, String>> logout();
|
Future<Result<void, String>> logout();
|
||||||
|
|
||||||
/// Logs the user in using an email address and password.
|
|
||||||
///
|
|
||||||
/// This method authenticates the user with their email and password credentials.
|
|
||||||
/// Returns a `Result` that either contains a `void` on success or an error message.
|
|
||||||
///
|
|
||||||
/// Example:
|
|
||||||
/// ```dart
|
|
||||||
/// await authInterface.loginWithEmailAndPassword(
|
|
||||||
/// email: "user@example.com",
|
|
||||||
/// password: "password123",
|
|
||||||
/// );
|
|
||||||
/// ```
|
|
||||||
@Deprecated("Use `login` instead. Deprecated as of version 1.0.5")
|
|
||||||
Future<Result<void, String>> loginWithEmailAndPassword({
|
|
||||||
required String email,
|
|
||||||
required String password,
|
|
||||||
});
|
|
||||||
|
|
||||||
/// Logs the user in using an optional, generic `T` type of input.
|
/// Logs the user in using an optional, generic `T` type of input.
|
||||||
/// This login method is a generic method that can be used to login with any
|
/// This login method is a generic method that can be used to login with any
|
||||||
/// type of input. It is useful for login methods that do not require an email
|
/// type of input. It is useful for login methods that do not require an email
|
||||||
@@ -78,32 +60,29 @@ abstract class ArcaneAuthInterface {
|
|||||||
/// This method is typically used when the user hasn't received or has lost their initial
|
/// This method is typically used when the user hasn't received or has lost their initial
|
||||||
/// verification code. Returns a `Result` that contains the verification code on success
|
/// verification code. Returns a `Result` that contains the verification code on success
|
||||||
/// or an error message.
|
/// or an error message.
|
||||||
Future<Result<String, String>> resendVerificationCode(
|
Future<Result<String, String>>? resendVerificationCode(
|
||||||
String email,
|
String email,
|
||||||
);
|
);
|
||||||
|
|
||||||
/// Signs a user up with a username, password, and email.
|
/// Registers a new account using user-supplied input.
|
||||||
///
|
///
|
||||||
/// This method registers a new user in the system. Returns a `Result` that contains
|
/// This method registers a new user in the system. Returns a `Result` that contains
|
||||||
/// the next [SignUpStep] in the process on success or an error message.
|
/// the next [SignUpStep] in the process on success or an error message.
|
||||||
///
|
///
|
||||||
/// Example:
|
/// Example:
|
||||||
/// ```dart
|
/// ```dart
|
||||||
/// await authInterface.signup(
|
/// await authInterface.register(
|
||||||
/// email: "user@example.com",
|
/// email: "user@example.com",
|
||||||
/// password: "password123",
|
/// password: "password123",
|
||||||
/// );
|
/// );
|
||||||
/// ```
|
/// ```
|
||||||
Future<Result<SignUpStep, String>> signup({
|
Future<Result<SignUpStep, String>>? register<T>({T? input});
|
||||||
required String password,
|
|
||||||
required String email,
|
|
||||||
});
|
|
||||||
|
|
||||||
/// Confirms a user's signup using a username and a confirmation code.
|
/// Confirms a user's signup using a username and a confirmation code.
|
||||||
///
|
///
|
||||||
/// This method completes the sign-up process by verifying the user's confirmation code.
|
/// This method completes the sign-up process by verifying the user's confirmation code.
|
||||||
/// Returns a `Result` that contains `true` on success or an error message.
|
/// Returns a `Result` that contains `true` on success or an error message.
|
||||||
Future<Result<bool, String>> confirmSignup({
|
Future<Result<bool, String>>? confirmSignup({
|
||||||
required String username,
|
required String username,
|
||||||
required String confirmationCode,
|
required String confirmationCode,
|
||||||
});
|
});
|
||||||
@@ -113,7 +92,12 @@ abstract class ArcaneAuthInterface {
|
|||||||
/// This method is used when a user requests to reset their password. The reset code
|
/// This method is used when a user requests to reset their password. The reset code
|
||||||
/// they receive via email is used to verify the request. Optionally, a new password can
|
/// they receive via email is used to verify the request. Optionally, a new password can
|
||||||
/// be provided. Returns a `Result` that contains `true` on success or an error message.
|
/// be provided. Returns a `Result` that contains `true` on success or an error message.
|
||||||
Future<Result<bool, String>> resetPassword({
|
///
|
||||||
|
/// This method may be called twice. In the first instance, the `email` is provided, which
|
||||||
|
/// triggers a password reset confirmation email to be sent, containing a password reset
|
||||||
|
/// code or pin. The second call should include the `email`, the user's new password
|
||||||
|
/// (`newPassword`), and the `code` they received in their email.
|
||||||
|
Future<Result<bool, String>>? resetPassword({
|
||||||
required String email,
|
required String email,
|
||||||
String? newPassword,
|
String? newPassword,
|
||||||
String? code,
|
String? code,
|
||||||
|
|||||||
@@ -52,11 +52,13 @@ class ArcaneAuthenticationService extends ArcaneService {
|
|||||||
/// Returns a JWT access token if the registered `ArcaneAuthInterface`
|
/// Returns a JWT access token if the registered `ArcaneAuthInterface`
|
||||||
/// provides one. This token is often used in the headers of HTTP requests
|
/// provides one. This token is often used in the headers of HTTP requests
|
||||||
/// to the backend API.
|
/// to the backend API.
|
||||||
Future<String?> get accessToken => authInterface.accessToken;
|
Future<String?> get accessToken =>
|
||||||
|
authInterface.accessToken ?? Future.value("");
|
||||||
|
|
||||||
/// Returns a JWT refresh token if the registered `ArcaneAuthInterface`
|
/// Returns a JWT refresh token if the registered `ArcaneAuthInterface`
|
||||||
/// provides one.
|
/// provides one.
|
||||||
Future<String?> get refreshToken => authInterface.refreshToken;
|
Future<String?> get refreshToken =>
|
||||||
|
authInterface.refreshToken ?? Future.value("");
|
||||||
|
|
||||||
/// Removes any registered `ArcaneAuthInterface` and resets all values to
|
/// Removes any registered `ArcaneAuthInterface` and resets all values to
|
||||||
/// default.
|
/// default.
|
||||||
@@ -174,36 +176,6 @@ class ArcaneAuthenticationService extends ArcaneService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Attempts to log in the user using their `email` and `password`.
|
|
||||||
/// Upon successful login, `status` will be set to
|
|
||||||
/// `AuthenticationStatus.authenticated]` If `onLoggedIn` is specified, the
|
|
||||||
/// method will run after the authentication status has been updated.
|
|
||||||
/// When logging in with email and password, the user's email address will be
|
|
||||||
/// cached in `ArcaneSecureStorage`.
|
|
||||||
@Deprecated("Use `login` instead. Deprecated as of version 1.0.5")
|
|
||||||
Future<Result<void, String>> loginWithEmailAndPassword({
|
|
||||||
required String email,
|
|
||||||
required String password,
|
|
||||||
Future<void> Function()? onLoggedIn,
|
|
||||||
}) async {
|
|
||||||
if (status != AuthenticationStatus.unauthenticated) {
|
|
||||||
return Result.error("Cannot sign in. Status is already ${status.name}.");
|
|
||||||
}
|
|
||||||
|
|
||||||
final Result<void, String> result =
|
|
||||||
await authInterface.loginWithEmailAndPassword(
|
|
||||||
email: email,
|
|
||||||
password: password,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (result.isSuccess) {
|
|
||||||
setAuthenticated();
|
|
||||||
if (onLoggedIn != null) await onLoggedIn();
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Logs the user in using an optional, generic `T` type of input.
|
/// Logs the user in using an optional, generic `T` type of input.
|
||||||
Future<Result<void, String>> login<T>({
|
Future<Result<void, String>> login<T>({
|
||||||
T? input,
|
T? input,
|
||||||
@@ -225,22 +197,26 @@ class ArcaneAuthenticationService extends ArcaneService {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Attempts to register a new account using the provided `email` and
|
/// Attempts to register a new account using user-defined input.
|
||||||
/// `password`. Upon success, returns a `SignUpStep` indicating the next step
|
/// Upon success, returns a `SignUpStep` indicating the next step
|
||||||
/// in the signup process as a `SignUpStep`.
|
/// in the signup process as a `SignUpStep`.
|
||||||
Future<Result<SignUpStep, String>> signup({
|
Future<Result<SignUpStep, String>> register<T>({
|
||||||
required String email,
|
T? input,
|
||||||
required String password,
|
|
||||||
}) async {
|
}) async {
|
||||||
if (_authInterface == null) {
|
if (_authInterface == null) {
|
||||||
return Result.error("No ArcaneAuthInterface has been registered");
|
return Result.error("No ArcaneAuthInterface has been registered");
|
||||||
}
|
}
|
||||||
|
|
||||||
final Result<SignUpStep, String> result = await authInterface.signup(
|
final Result<SignUpStep, String>? result = await authInterface.register(
|
||||||
email: email,
|
input: input,
|
||||||
password: password,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (result == null) {
|
||||||
|
return Result.error(
|
||||||
|
"Registered ArcaneAuthInterface returned a null value.",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -254,11 +230,17 @@ class ArcaneAuthenticationService extends ArcaneService {
|
|||||||
return Result.error("No ArcaneAuthInterface has been registered");
|
return Result.error("No ArcaneAuthInterface has been registered");
|
||||||
}
|
}
|
||||||
|
|
||||||
final Result<bool, String> result = await authInterface.confirmSignup(
|
final Result<bool, String>? result = await authInterface.confirmSignup(
|
||||||
username: email,
|
username: email,
|
||||||
confirmationCode: confirmationCode,
|
confirmationCode: confirmationCode,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (result == null) {
|
||||||
|
return Result.error(
|
||||||
|
"Registered ArcaneAuthInterface returned a null value.",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -269,7 +251,16 @@ class ArcaneAuthenticationService extends ArcaneService {
|
|||||||
return Result.error("No ArcaneAuthInterface has been registered");
|
return Result.error("No ArcaneAuthInterface has been registered");
|
||||||
}
|
}
|
||||||
|
|
||||||
return authInterface.resendVerificationCode(email);
|
final Future<Result<String, String>>? result =
|
||||||
|
authInterface.resendVerificationCode(email);
|
||||||
|
|
||||||
|
if (result == null) {
|
||||||
|
return Result.error(
|
||||||
|
"Registered ArcaneAuthInterface returned a null value.",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Attempts to reset the user's password using their `email`. This method
|
/// Attempts to reset the user's password using their `email`. This method
|
||||||
@@ -287,12 +278,18 @@ class ArcaneAuthenticationService extends ArcaneService {
|
|||||||
return Result.error("No ArcaneAuthInterface has been registered");
|
return Result.error("No ArcaneAuthInterface has been registered");
|
||||||
}
|
}
|
||||||
|
|
||||||
final Result<bool, String> result = await authInterface.resetPassword(
|
final Result<bool, String>? result = await authInterface.resetPassword(
|
||||||
email: email,
|
email: email,
|
||||||
newPassword: newPassword,
|
newPassword: newPassword,
|
||||||
code: confirmationCode,
|
code: confirmationCode,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (result == null) {
|
||||||
|
return Result.error(
|
||||||
|
"Registered ArcaneAuthInterface returned a null value.",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
name: arcane_framework
|
name: arcane_framework
|
||||||
description: "Agnostic Reusable Component Architecture for New Ecosystems: a modern framework for bootstrapping new applications"
|
description: "Agnostic Reusable Component Architecture for New Ecosystems: a modern framework for bootstrapping new applications"
|
||||||
version: 1.0.8
|
version: 1.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
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user