feat(auth): a password with TOTP on the register, and resets
The register's side of signing in with an address, a password that never leaves the device (SRP-6a) and a code from an authenticator (ADR 0017), with members forwarding every step through AccountRegister: - password.set: salt, Argon2id's costs, SRP's verifier, the public keys and the private keys wrapped twice, all made on the device; with the address a mailed code proves, an anonymous person becomes identified under their ID. It signs in once an authenticator is confirmed. - passwordSignIn.begin and complete: SRP's two steps with a TOTP or recovery code. An address nobody has is answered from a decoy key as an account would be; every wrong credential is refused alike. - authenticator: secrets sealed under totpKey (XChaCha20-Poly1305, bound to their row), each code accepted once, ten recovery codes with the first, the last one kept. - accountRecovery: a lost authenticator reset 72 hours after the password and a mailed code or the recovery phrase ask, a lost password set anew with the phrase's signature, or the account reset with new keys 72 hours after a mailed code asks; a mail at each start, a sign-in calling it off. - An account with a password no longer signs in by a mailed code or GitHub; no new GitHub account is linked where passwords are offered, and from GITHUB_SIGN_IN_ENDS GitHub signs nobody in and its IDs go. Five tables, added by the module's migration; deletePerson deletes their rows. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
parent
200a2df32f
commit
a3a8ed3890
117 changed files with 22557 additions and 60 deletions
|
|
@ -40,7 +40,11 @@ enum EmailSignInRefusal implements _isc.SerializableModel {
|
|||
otherAddressLinked,
|
||||
|
||||
/// The mail couldn't be sent; nothing was kept of the request.
|
||||
mailFailed;
|
||||
mailFailed,
|
||||
|
||||
/// The account signs in with its password and an authenticator (ADR
|
||||
/// 0017): a code by mail no longer signs into it.
|
||||
usePassword;
|
||||
|
||||
static EmailSignInRefusal fromJson(String name) {
|
||||
switch (name) {
|
||||
|
|
@ -60,6 +64,8 @@ enum EmailSignInRefusal implements _isc.SerializableModel {
|
|||
return EmailSignInRefusal.otherAddressLinked;
|
||||
case 'mailFailed':
|
||||
return EmailSignInRefusal.mailFailed;
|
||||
case 'usePassword':
|
||||
return EmailSignInRefusal.usePassword;
|
||||
default:
|
||||
throw ArgumentError(
|
||||
'Value "$name" cannot be converted to "EmailSignInRefusal"',
|
||||
|
|
|
|||
|
|
@ -25,7 +25,19 @@ enum GitHubSignInRefusal implements _isc.SerializableModel {
|
|||
otherGitHubAccountLinked,
|
||||
|
||||
/// No person has this GitHub account; only linking one creates it.
|
||||
unknownAccount;
|
||||
unknownAccount,
|
||||
|
||||
/// The account signs in with its password: GitHub is deprecated (ADR 0017),
|
||||
/// and can't unlock the account's keys.
|
||||
usePassword,
|
||||
|
||||
/// GitHub accounts are no longer linked (ADR 0017): an address and a
|
||||
/// password are the way in.
|
||||
deprecated,
|
||||
|
||||
/// GitHub signs nobody in any more here: its time ended
|
||||
/// (`GITHUB_SIGN_IN_ENDS`).
|
||||
ended;
|
||||
|
||||
static GitHubSignInRefusal fromJson(String name) {
|
||||
switch (name) {
|
||||
|
|
@ -37,6 +49,12 @@ enum GitHubSignInRefusal implements _isc.SerializableModel {
|
|||
return GitHubSignInRefusal.otherGitHubAccountLinked;
|
||||
case 'unknownAccount':
|
||||
return GitHubSignInRefusal.unknownAccount;
|
||||
case 'usePassword':
|
||||
return GitHubSignInRefusal.usePassword;
|
||||
case 'deprecated':
|
||||
return GitHubSignInRefusal.deprecated;
|
||||
case 'ended':
|
||||
return GitHubSignInRefusal.ended;
|
||||
default:
|
||||
throw ArgumentError(
|
||||
'Value "$name" cannot be converted to "GitHubSignInRefusal"',
|
||||
|
|
|
|||
|
|
@ -18,17 +18,28 @@ abstract class SignInWays
|
|||
SignInWays._({
|
||||
required this.gitHub,
|
||||
required this.email,
|
||||
});
|
||||
bool? password,
|
||||
bool? authenticator,
|
||||
}) : password = password ?? false,
|
||||
authenticator = authenticator ?? false;
|
||||
|
||||
factory SignInWays({
|
||||
required bool gitHub,
|
||||
required bool email,
|
||||
bool? password,
|
||||
bool? authenticator,
|
||||
}) = _SignInWaysImpl;
|
||||
|
||||
factory SignInWays.fromJson(Map<String, dynamic> jsonSerialization) {
|
||||
return SignInWays(
|
||||
gitHub: _isc.BoolJsonExtension.fromJson(jsonSerialization['gitHub']),
|
||||
email: _isc.BoolJsonExtension.fromJson(jsonSerialization['email']),
|
||||
password: jsonSerialization['password'] == null
|
||||
? null
|
||||
: _isc.BoolJsonExtension.fromJson(jsonSerialization['password']),
|
||||
authenticator: jsonSerialization['authenticator'] == null
|
||||
? null
|
||||
: _isc.BoolJsonExtension.fromJson(jsonSerialization['authenticator']),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -36,12 +47,20 @@ abstract class SignInWays
|
|||
|
||||
bool email;
|
||||
|
||||
/// A password (ADR 0017), which an address needs for resets.
|
||||
bool password;
|
||||
|
||||
/// A confirmed authenticator: the password signs in only with one.
|
||||
bool authenticator;
|
||||
|
||||
/// Returns a shallow copy of this [SignInWays]
|
||||
/// with some or all fields replaced by the given arguments.
|
||||
@_isc.useResult
|
||||
SignInWays copyWith({
|
||||
bool? gitHub,
|
||||
bool? email,
|
||||
bool? password,
|
||||
bool? authenticator,
|
||||
});
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
|
|
@ -49,6 +68,8 @@ abstract class SignInWays
|
|||
'__className__': 'halkyon_base.SignInWays',
|
||||
'gitHub': gitHub,
|
||||
'email': email,
|
||||
'password': password,
|
||||
'authenticator': authenticator,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -58,6 +79,8 @@ abstract class SignInWays
|
|||
'__className__': 'halkyon_base.SignInWays',
|
||||
'gitHub': gitHub,
|
||||
'email': email,
|
||||
'password': password,
|
||||
'authenticator': authenticator,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -71,9 +94,13 @@ class _SignInWaysImpl extends SignInWays {
|
|||
_SignInWaysImpl({
|
||||
required bool gitHub,
|
||||
required bool email,
|
||||
bool? password,
|
||||
bool? authenticator,
|
||||
}) : super._(
|
||||
gitHub: gitHub,
|
||||
email: email,
|
||||
password: password,
|
||||
authenticator: authenticator,
|
||||
);
|
||||
|
||||
/// Returns a shallow copy of this [SignInWays]
|
||||
|
|
@ -83,10 +110,14 @@ class _SignInWaysImpl extends SignInWays {
|
|||
SignInWays copyWith({
|
||||
bool? gitHub,
|
||||
bool? email,
|
||||
bool? password,
|
||||
bool? authenticator,
|
||||
}) {
|
||||
return SignInWays(
|
||||
gitHub: gitHub ?? this.gitHub,
|
||||
email: email ?? this.email,
|
||||
password: password ?? this.password,
|
||||
authenticator: authenticator ?? this.authenticator,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,22 @@ import 'package:halkyon_base_client/src/protocol/auth/sign_in_ways.dart'
|
|||
as _ifld8s4r;
|
||||
import 'package:halkyon_base_client/src/protocol/instance/instance_basics.dart'
|
||||
as _isnyur2i;
|
||||
import 'package:halkyon_base_client/src/protocol/password/authenticator.dart'
|
||||
as _ivfmflch;
|
||||
import 'package:halkyon_base_client/src/protocol/password/authenticator_enrolment.dart'
|
||||
as _it1lo7kq;
|
||||
import 'package:halkyon_base_client/src/protocol/password/key_proof_challenge.dart'
|
||||
as _ir3ecgdn;
|
||||
import 'package:halkyon_base_client/src/protocol/password/new_password.dart'
|
||||
as _i95l60wq;
|
||||
import 'package:halkyon_base_client/src/protocol/password/password_challenge.dart'
|
||||
as _iykren7a;
|
||||
import 'package:halkyon_base_client/src/protocol/password/password_setup.dart'
|
||||
as _ipn3lqh9;
|
||||
import 'package:halkyon_base_client/src/protocol/password/password_signed_in.dart'
|
||||
as _ix90myvx;
|
||||
import 'package:halkyon_base_client/src/protocol/password/reset_pending.dart'
|
||||
as _ippuf33k;
|
||||
import 'package:halkyon_base_client/src/protocol/profile/profile.dart'
|
||||
as _i8qdmv6n;
|
||||
import 'package:halkyon_base_client/src/protocol/profile/profile_refusal.dart'
|
||||
|
|
@ -153,9 +169,8 @@ class EndpointGitHubSignIn extends _isc.EndpointRef {
|
|||
@override
|
||||
String get name => 'halkyon_base.gitHubSignIn';
|
||||
|
||||
/// A session for the person with the GitHub account that [code] proves,
|
||||
/// whom the instance's register knows by it; an account it doesn't know
|
||||
/// is refused ([GitHubSignInRefusal.unknownAccount]).
|
||||
/// A session for the person with the GitHub account that [code] proves;
|
||||
/// refusals as [gitHubAccountToSignIn]'s.
|
||||
_ida.Future<_iacc.AuthSuccess> signIn({
|
||||
required String code,
|
||||
required String codeVerifier,
|
||||
|
|
@ -209,8 +224,10 @@ class EndpointInstance extends _isc.EndpointRef {
|
|||
String get name => 'halkyon_base.instance';
|
||||
|
||||
/// This instance's basics: the app it serves, GitHub sign-in only with the
|
||||
/// operator's OAuth app, email sign-in only where the register can mail
|
||||
/// codes (this server, or on a member the register, ADR 0016), where its
|
||||
/// operator's OAuth app and until it ends (ADR 0017), email sign-in only
|
||||
/// where the register can mail codes (this server, or on a member the
|
||||
/// register, ADR 0016), password sign-in where the register holds its
|
||||
/// keys, where its
|
||||
/// source is, the oldest app build it works with, and where it keeps
|
||||
/// people's data and its backups.
|
||||
_ida.Future<_isnyur2i.InstanceBasics> basics() =>
|
||||
|
|
@ -221,6 +238,285 @@ class EndpointInstance extends _isc.EndpointRef {
|
|||
);
|
||||
}
|
||||
|
||||
/// Getting back into an account (ADR 0017): a lost authenticator, a lost
|
||||
/// password with the recovery phrase, a lost password without it. Called
|
||||
/// without a session, as the person can't sign in. The instance's register
|
||||
/// checks every proof (ADR 0016); a session is this server's.
|
||||
/// {@category Endpoint}
|
||||
class EndpointAccountRecovery extends _isc.EndpointRef {
|
||||
EndpointAccountRecovery(_isc.EndpointCaller caller) : super(caller);
|
||||
|
||||
@override
|
||||
String get name => 'halkyon_base.accountRecovery';
|
||||
|
||||
/// Mails a code to [address], worded in [language] (`en`, `de`), as email
|
||||
/// sign-in mails it, and returns the request it answers: the proof of the
|
||||
/// address that resets take. Refusals as `sendSignInCode`'s.
|
||||
_ida.Future<_isc.UuidValue> sendCode({
|
||||
required String address,
|
||||
required String language,
|
||||
}) => caller.callServerEndpoint<_isc.UuidValue>(
|
||||
'halkyon_base.accountRecovery',
|
||||
'sendCode',
|
||||
{
|
||||
'address': address,
|
||||
'language': language,
|
||||
},
|
||||
);
|
||||
|
||||
/// Asks for the reset of the authenticators of the account at [address]:
|
||||
/// the password's proof for [challenge] (`passwordSignIn.begin`), and a
|
||||
/// [code] mailed for [request] or the recovery phrase's [signature] for
|
||||
/// [keyChallenge] ([beginKeyProof]). It takes effect 72 hours later
|
||||
/// unless the owner signs in with a code meanwhile; a mail in [language]
|
||||
/// says so. Refusals as `resetAuthenticator`'s.
|
||||
_ida.Future<_ippuf33k.ResetPending> resetAuthenticator({
|
||||
required _isc.UuidValue challenge,
|
||||
required _idt.ByteData clientValue,
|
||||
required _idt.ByteData clientProof,
|
||||
required String address,
|
||||
required String language,
|
||||
_isc.UuidValue? request,
|
||||
String? code,
|
||||
_isc.UuidValue? keyChallenge,
|
||||
_idt.ByteData? signature,
|
||||
}) => caller.callServerEndpoint<_ippuf33k.ResetPending>(
|
||||
'halkyon_base.accountRecovery',
|
||||
'resetAuthenticator',
|
||||
{
|
||||
'challenge': challenge,
|
||||
'clientValue': clientValue,
|
||||
'clientProof': clientProof,
|
||||
'address': address,
|
||||
'language': language,
|
||||
'request': request,
|
||||
'code': code,
|
||||
'keyChallenge': keyChallenge,
|
||||
'signature': signature,
|
||||
},
|
||||
);
|
||||
|
||||
/// The first step of proving the recovery phrase for [address]: the
|
||||
/// account's keys wrapped under the phrase and a nonce to sign; alike for
|
||||
/// an address nobody has. Refusals as `beginKeyProof`'s.
|
||||
_ida.Future<_ir3ecgdn.KeyProofChallenge> beginKeyProof({
|
||||
required String address,
|
||||
}) => caller.callServerEndpoint<_ir3ecgdn.KeyProofChallenge>(
|
||||
'halkyon_base.accountRecovery',
|
||||
'beginKeyProof',
|
||||
{'address': address},
|
||||
);
|
||||
|
||||
/// Sets a new [password] with the recovery phrase's [signature] for
|
||||
/// [challenge] and a [totpCode] or [recoveryCode]; the keys stay. Signs
|
||||
/// in. Refusals as `resetPasswordWithPhrase`'s.
|
||||
_ida.Future<_iacc.AuthSuccess> resetPassword({
|
||||
required _isc.UuidValue challenge,
|
||||
required _idt.ByteData signature,
|
||||
required _i95l60wq.NewPassword password,
|
||||
String? totpCode,
|
||||
String? recoveryCode,
|
||||
}) => caller.callServerEndpoint<_iacc.AuthSuccess>(
|
||||
'halkyon_base.accountRecovery',
|
||||
'resetPassword',
|
||||
{
|
||||
'challenge': challenge,
|
||||
'signature': signature,
|
||||
'password': password,
|
||||
'totpCode': totpCode,
|
||||
'recoveryCode': recoveryCode,
|
||||
},
|
||||
);
|
||||
|
||||
/// Asks for the reset of the whole account at [address], as a [code]
|
||||
/// mailed for [request] proves: new keys, 72 hours later unless the owner
|
||||
/// signs in with the password meanwhile; a mail in [language] says so.
|
||||
/// Refusals as `startAccountReset`'s.
|
||||
_ida.Future<_ippuf33k.ResetPending> startAccountReset({
|
||||
required String address,
|
||||
required String language,
|
||||
required _isc.UuidValue request,
|
||||
required String code,
|
||||
}) => caller.callServerEndpoint<_ippuf33k.ResetPending>(
|
||||
'halkyon_base.accountRecovery',
|
||||
'startAccountReset',
|
||||
{
|
||||
'address': address,
|
||||
'language': language,
|
||||
'request': request,
|
||||
'code': code,
|
||||
},
|
||||
);
|
||||
|
||||
/// Carries out the reset of the whole account at [address] once due, as
|
||||
/// a new [code] mailed for [request] proves: [setup] replaces its
|
||||
/// password and keys, and an authenticator must be set up again. Signs
|
||||
/// in. Refusals as `completeAccountReset`'s.
|
||||
_ida.Future<_iacc.AuthSuccess> completeAccountReset({
|
||||
required String address,
|
||||
required _isc.UuidValue request,
|
||||
required String code,
|
||||
required _ipn3lqh9.PasswordSetup setup,
|
||||
}) => caller.callServerEndpoint<_iacc.AuthSuccess>(
|
||||
'halkyon_base.accountRecovery',
|
||||
'completeAccountReset',
|
||||
{
|
||||
'address': address,
|
||||
'request': request,
|
||||
'code': code,
|
||||
'setup': setup,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/// The signed-in person's authenticators and recovery codes (ADR 0017),
|
||||
/// which the instance's register keeps (ADR 0016).
|
||||
/// {@category Endpoint}
|
||||
class EndpointAuthenticator extends _isc.EndpointRef {
|
||||
EndpointAuthenticator(_isc.EndpointCaller caller) : super(caller);
|
||||
|
||||
@override
|
||||
String get name => 'halkyon_base.authenticator';
|
||||
|
||||
/// A new authenticator called [name], for the app to read from the
|
||||
/// returned URI (shown once), which names the account [label] (the
|
||||
/// address the device signs in with). Refusals as `enrolAuthenticator`'s.
|
||||
_ida.Future<_it1lo7kq.AuthenticatorEnrolment> enrol({
|
||||
required String name,
|
||||
required String label,
|
||||
}) => caller.callServerEndpoint<_it1lo7kq.AuthenticatorEnrolment>(
|
||||
'halkyon_base.authenticator',
|
||||
'enrol',
|
||||
{
|
||||
'name': name,
|
||||
'label': label,
|
||||
},
|
||||
);
|
||||
|
||||
/// Confirms [authenticator] with a [code] from it; the account's first
|
||||
/// returns its recovery codes, shown once. Refusals as
|
||||
/// `confirmAuthenticator`'s.
|
||||
_ida.Future<List<String>> confirm({
|
||||
required _isc.UuidValue authenticator,
|
||||
required String code,
|
||||
}) => caller.callServerEndpoint<List<String>>(
|
||||
'halkyon_base.authenticator',
|
||||
'confirm',
|
||||
{
|
||||
'authenticator': authenticator,
|
||||
'code': code,
|
||||
},
|
||||
);
|
||||
|
||||
/// The caller's authenticators, the oldest first.
|
||||
_ida.Future<List<_ivfmflch.Authenticator>> list() =>
|
||||
caller.callServerEndpoint<List<_ivfmflch.Authenticator>>(
|
||||
'halkyon_base.authenticator',
|
||||
'list',
|
||||
{},
|
||||
);
|
||||
|
||||
/// Removes [authenticator]: a confirmed one with a [code] from one of the
|
||||
/// caller's, while another stays. Refusals as `removeAuthenticator`'s.
|
||||
_ida.Future<void> remove({
|
||||
required _isc.UuidValue authenticator,
|
||||
String? code,
|
||||
}) => caller.callServerEndpoint<void>(
|
||||
'halkyon_base.authenticator',
|
||||
'remove',
|
||||
{
|
||||
'authenticator': authenticator,
|
||||
'code': code,
|
||||
},
|
||||
);
|
||||
|
||||
/// New recovery codes in place of the old, with a [code] from one of the
|
||||
/// caller's authenticators: shown once. Refusals as `newRecoveryCodes`'.
|
||||
_ida.Future<List<String>> newRecoveryCodes({required String code}) =>
|
||||
caller.callServerEndpoint<List<String>>(
|
||||
'halkyon_base.authenticator',
|
||||
'newRecoveryCodes',
|
||||
{'code': code},
|
||||
);
|
||||
}
|
||||
|
||||
/// Giving the signed-in person a password (ADR 0017): the way an anonymous
|
||||
/// person becomes identified, keeping everything they have, and the way
|
||||
/// someone who signs in with a code by mail or GitHub moves to a password.
|
||||
/// The instance's register keeps it (ADR 0016).
|
||||
/// {@category Endpoint}
|
||||
class EndpointPassword extends _isc.EndpointRef {
|
||||
EndpointPassword(_isc.EndpointCaller caller) : super(caller);
|
||||
|
||||
@override
|
||||
String get name => 'halkyon_base.password';
|
||||
|
||||
/// Gives the caller the password [setup] describes (all of it made on the
|
||||
/// device), with the address [code] proves for [request] (mailed with
|
||||
/// `emailCode.sendCode`) unless the caller has one; refusals as
|
||||
/// `setPassword`'s. It signs in once an authenticator is confirmed
|
||||
/// (`authenticator.confirm`).
|
||||
_ida.Future<void> set({
|
||||
required _ipn3lqh9.PasswordSetup setup,
|
||||
_isc.UuidValue? request,
|
||||
String? code,
|
||||
}) => caller.callServerEndpoint<void>(
|
||||
'halkyon_base.password',
|
||||
'set',
|
||||
{
|
||||
'setup': setup,
|
||||
'request': request,
|
||||
'code': code,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/// Signing in with an address, a password and a code from an authenticator
|
||||
/// (ADR 0017), in SRP-6a's two steps. Called without a session: Serverpod
|
||||
/// issues no session for another person inside a signed-in call. The
|
||||
/// instance's register checks both steps (ADR 0016); the session is this
|
||||
/// server's.
|
||||
/// {@category Endpoint}
|
||||
class EndpointPasswordSignIn extends _isc.EndpointRef {
|
||||
EndpointPasswordSignIn(_isc.EndpointCaller caller) : super(caller);
|
||||
|
||||
@override
|
||||
String get name => 'halkyon_base.passwordSignIn';
|
||||
|
||||
/// The first step for [address]: its salt and costs, which the device
|
||||
/// derives the password's keys with, and SRP's B; alike for an address
|
||||
/// nobody has. Refusals as `beginPasswordSignIn`'s.
|
||||
_ida.Future<_iykren7a.PasswordChallenge> begin({required String address}) =>
|
||||
caller.callServerEndpoint<_iykren7a.PasswordChallenge>(
|
||||
'halkyon_base.passwordSignIn',
|
||||
'begin',
|
||||
{'address': address},
|
||||
);
|
||||
|
||||
/// The second step: the device's A ([clientValue]) and proof M1
|
||||
/// ([clientProof]) for [challenge], and a [totpCode] or a [recoveryCode].
|
||||
/// Signed in, SRP's M2 (which the device checks before trusting anything
|
||||
/// else), the account's keys as the register keeps them, and the session.
|
||||
/// Refusals as `completePasswordSignIn`'s.
|
||||
_ida.Future<_ix90myvx.PasswordSignedIn> complete({
|
||||
required _isc.UuidValue challenge,
|
||||
required _idt.ByteData clientValue,
|
||||
required _idt.ByteData clientProof,
|
||||
String? totpCode,
|
||||
String? recoveryCode,
|
||||
}) => caller.callServerEndpoint<_ix90myvx.PasswordSignedIn>(
|
||||
'halkyon_base.passwordSignIn',
|
||||
'complete',
|
||||
{
|
||||
'challenge': challenge,
|
||||
'clientValue': clientValue,
|
||||
'clientProof': clientProof,
|
||||
'totpCode': totpCode,
|
||||
'recoveryCode': recoveryCode,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/// Your public profile (Halkyon Learn's ADR 0005, rule 2; ADR 0016): the
|
||||
/// handle others find you by, your display name, bio and links, the same in
|
||||
/// every service of the instance. Only for people with an identity: a profile
|
||||
|
|
@ -347,6 +643,10 @@ class Caller extends _isc.ModuleEndpointCaller {
|
|||
gitHubSignIn = EndpointGitHubSignIn(this);
|
||||
gitHubUpgrade = EndpointGitHubUpgrade(this);
|
||||
instance = EndpointInstance(this);
|
||||
accountRecovery = EndpointAccountRecovery(this);
|
||||
authenticator = EndpointAuthenticator(this);
|
||||
password = EndpointPassword(this);
|
||||
passwordSignIn = EndpointPasswordSignIn(this);
|
||||
profile = EndpointProfile(this);
|
||||
profiles = EndpointProfiles(this);
|
||||
}
|
||||
|
|
@ -365,6 +665,14 @@ class Caller extends _isc.ModuleEndpointCaller {
|
|||
|
||||
late final EndpointInstance instance;
|
||||
|
||||
late final EndpointAccountRecovery accountRecovery;
|
||||
|
||||
late final EndpointAuthenticator authenticator;
|
||||
|
||||
late final EndpointPassword password;
|
||||
|
||||
late final EndpointPasswordSignIn passwordSignIn;
|
||||
|
||||
late final EndpointProfile profile;
|
||||
|
||||
late final EndpointProfiles profiles;
|
||||
|
|
@ -378,6 +686,10 @@ class Caller extends _isc.ModuleEndpointCaller {
|
|||
'halkyon_base.gitHubSignIn': gitHubSignIn,
|
||||
'halkyon_base.gitHubUpgrade': gitHubUpgrade,
|
||||
'halkyon_base.instance': instance,
|
||||
'halkyon_base.accountRecovery': accountRecovery,
|
||||
'halkyon_base.authenticator': authenticator,
|
||||
'halkyon_base.password': password,
|
||||
'halkyon_base.passwordSignIn': passwordSignIn,
|
||||
'halkyon_base.profile': profile,
|
||||
'halkyon_base.profiles': profiles,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -26,7 +26,8 @@ abstract class InstanceBasics
|
|||
required this.minimumAppBuild,
|
||||
this.dataLocation,
|
||||
this.backupLocation,
|
||||
});
|
||||
bool? passwordSignIn,
|
||||
}) : passwordSignIn = passwordSignIn ?? false;
|
||||
|
||||
factory InstanceBasics({
|
||||
required String app,
|
||||
|
|
@ -36,6 +37,7 @@ abstract class InstanceBasics
|
|||
required int minimumAppBuild,
|
||||
String? dataLocation,
|
||||
String? backupLocation,
|
||||
bool? passwordSignIn,
|
||||
}) = _InstanceBasicsImpl;
|
||||
|
||||
factory InstanceBasics.fromJson(Map<String, dynamic> jsonSerialization) {
|
||||
|
|
@ -49,6 +51,11 @@ abstract class InstanceBasics
|
|||
minimumAppBuild: jsonSerialization['minimumAppBuild'] as int,
|
||||
dataLocation: jsonSerialization['dataLocation'] as String?,
|
||||
backupLocation: jsonSerialization['backupLocation'] as String?,
|
||||
passwordSignIn: jsonSerialization['passwordSignIn'] == null
|
||||
? null
|
||||
: _isc.BoolJsonExtension.fromJson(
|
||||
jsonSerialization['passwordSignIn'],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -82,6 +89,10 @@ abstract class InstanceBasics
|
|||
/// `none` where it keeps none. Null where the operator says nothing.
|
||||
String? backupLocation;
|
||||
|
||||
/// Whether people sign in with a password and TOTP here (ADR 0017): the
|
||||
/// operator set the keys it needs.
|
||||
bool passwordSignIn;
|
||||
|
||||
/// Returns a shallow copy of this [InstanceBasics]
|
||||
/// with some or all fields replaced by the given arguments.
|
||||
@_isc.useResult
|
||||
|
|
@ -93,6 +104,7 @@ abstract class InstanceBasics
|
|||
int? minimumAppBuild,
|
||||
String? dataLocation,
|
||||
String? backupLocation,
|
||||
bool? passwordSignIn,
|
||||
});
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
|
|
@ -105,6 +117,7 @@ abstract class InstanceBasics
|
|||
'minimumAppBuild': minimumAppBuild,
|
||||
if (dataLocation != null) 'dataLocation': dataLocation,
|
||||
if (backupLocation != null) 'backupLocation': backupLocation,
|
||||
'passwordSignIn': passwordSignIn,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -119,6 +132,7 @@ abstract class InstanceBasics
|
|||
'minimumAppBuild': minimumAppBuild,
|
||||
if (dataLocation != null) 'dataLocation': dataLocation,
|
||||
if (backupLocation != null) 'backupLocation': backupLocation,
|
||||
'passwordSignIn': passwordSignIn,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -139,6 +153,7 @@ class _InstanceBasicsImpl extends InstanceBasics {
|
|||
required int minimumAppBuild,
|
||||
String? dataLocation,
|
||||
String? backupLocation,
|
||||
bool? passwordSignIn,
|
||||
}) : super._(
|
||||
app: app,
|
||||
gitHubClientId: gitHubClientId,
|
||||
|
|
@ -147,6 +162,7 @@ class _InstanceBasicsImpl extends InstanceBasics {
|
|||
minimumAppBuild: minimumAppBuild,
|
||||
dataLocation: dataLocation,
|
||||
backupLocation: backupLocation,
|
||||
passwordSignIn: passwordSignIn,
|
||||
);
|
||||
|
||||
/// Returns a shallow copy of this [InstanceBasics]
|
||||
|
|
@ -161,6 +177,7 @@ class _InstanceBasicsImpl extends InstanceBasics {
|
|||
int? minimumAppBuild,
|
||||
Object? dataLocation = _Undefined,
|
||||
Object? backupLocation = _Undefined,
|
||||
bool? passwordSignIn,
|
||||
}) {
|
||||
return InstanceBasics(
|
||||
app: app ?? this.app,
|
||||
|
|
@ -174,6 +191,7 @@ class _InstanceBasicsImpl extends InstanceBasics {
|
|||
backupLocation: backupLocation is String?
|
||||
? backupLocation
|
||||
: this.backupLocation,
|
||||
passwordSignIn: passwordSignIn ?? this.passwordSignIn,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,42 @@
|
|||
/* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */
|
||||
/* To generate run: "serverpod generate" */
|
||||
|
||||
// ignore_for_file: implementation_imports
|
||||
// ignore_for_file: library_private_types_in_public_api
|
||||
// ignore_for_file: non_constant_identifier_names
|
||||
// ignore_for_file: public_member_api_docs
|
||||
// ignore_for_file: type_literal_in_constant_pattern
|
||||
// ignore_for_file: use_super_parameters
|
||||
// ignore_for_file: invalid_use_of_internal_member
|
||||
|
||||
// ignore_for_file: no_leading_underscores_for_library_prefixes
|
||||
import 'package:serverpod_client/serverpod_client.dart' as _isc;
|
||||
|
||||
/// Which reset an account waits for.
|
||||
enum AccountResetKind implements _isc.SerializableModel {
|
||||
/// Its authenticators and recovery codes go: a lost second factor.
|
||||
authenticator,
|
||||
|
||||
/// Its password and keys are made anew: a lost password without the
|
||||
/// recovery phrase, which loses what was encrypted under the old keys.
|
||||
account;
|
||||
|
||||
static AccountResetKind fromJson(String name) {
|
||||
switch (name) {
|
||||
case 'authenticator':
|
||||
return AccountResetKind.authenticator;
|
||||
case 'account':
|
||||
return AccountResetKind.account;
|
||||
default:
|
||||
throw ArgumentError(
|
||||
'Value "$name" cannot be converted to "AccountResetKind"',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
String toJson() => name;
|
||||
|
||||
@override
|
||||
String toString() => name;
|
||||
}
|
||||
|
|
@ -0,0 +1,122 @@
|
|||
/* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */
|
||||
/* To generate run: "serverpod generate" */
|
||||
|
||||
// ignore_for_file: implementation_imports
|
||||
// ignore_for_file: library_private_types_in_public_api
|
||||
// ignore_for_file: non_constant_identifier_names
|
||||
// ignore_for_file: public_member_api_docs
|
||||
// ignore_for_file: type_literal_in_constant_pattern
|
||||
// ignore_for_file: use_super_parameters
|
||||
// ignore_for_file: invalid_use_of_internal_member
|
||||
|
||||
// ignore_for_file: no_leading_underscores_for_library_prefixes
|
||||
import 'package:serverpod_client/serverpod_client.dart' as _isc;
|
||||
|
||||
/// One of the account's authenticators, as its owner sees them: never its
|
||||
/// secret.
|
||||
abstract class Authenticator
|
||||
implements _isc.SerializableModel, _isc.ProtocolSerialization {
|
||||
Authenticator._({
|
||||
required this.id,
|
||||
required this.name,
|
||||
required this.confirmed,
|
||||
required this.createdAt,
|
||||
});
|
||||
|
||||
factory Authenticator({
|
||||
required _isc.UuidValue id,
|
||||
required String name,
|
||||
required bool confirmed,
|
||||
required DateTime createdAt,
|
||||
}) = _AuthenticatorImpl;
|
||||
|
||||
factory Authenticator.fromJson(Map<String, dynamic> jsonSerialization) {
|
||||
return Authenticator(
|
||||
id: _isc.UuidValueJsonExtension.fromJson(jsonSerialization['id']),
|
||||
name: jsonSerialization['name'] as String,
|
||||
confirmed: _isc.BoolJsonExtension.fromJson(
|
||||
jsonSerialization['confirmed'],
|
||||
),
|
||||
createdAt: _isc.DateTimeJsonExtension.fromJson(
|
||||
jsonSerialization['createdAt'],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
_isc.UuidValue id;
|
||||
|
||||
String name;
|
||||
|
||||
/// Whether a code from it was accepted; one that wasn't counts for nothing.
|
||||
bool confirmed;
|
||||
|
||||
DateTime createdAt;
|
||||
|
||||
/// Returns a shallow copy of this [Authenticator]
|
||||
/// with some or all fields replaced by the given arguments.
|
||||
@_isc.useResult
|
||||
Authenticator copyWith({
|
||||
_isc.UuidValue? id,
|
||||
String? name,
|
||||
bool? confirmed,
|
||||
DateTime? createdAt,
|
||||
});
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'__className__': 'halkyon_base.Authenticator',
|
||||
'id': id.toJson(),
|
||||
'name': name,
|
||||
'confirmed': confirmed,
|
||||
'createdAt': createdAt.toJson(),
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJsonForProtocol() {
|
||||
return {
|
||||
'__className__': 'halkyon_base.Authenticator',
|
||||
'id': id.toJson(),
|
||||
'name': name,
|
||||
'confirmed': confirmed,
|
||||
'createdAt': createdAt.toJson(),
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return _isc.SerializationManager.encode(this);
|
||||
}
|
||||
}
|
||||
|
||||
class _AuthenticatorImpl extends Authenticator {
|
||||
_AuthenticatorImpl({
|
||||
required _isc.UuidValue id,
|
||||
required String name,
|
||||
required bool confirmed,
|
||||
required DateTime createdAt,
|
||||
}) : super._(
|
||||
id: id,
|
||||
name: name,
|
||||
confirmed: confirmed,
|
||||
createdAt: createdAt,
|
||||
);
|
||||
|
||||
/// Returns a shallow copy of this [Authenticator]
|
||||
/// with some or all fields replaced by the given arguments.
|
||||
@_isc.useResult
|
||||
@override
|
||||
Authenticator copyWith({
|
||||
_isc.UuidValue? id,
|
||||
String? name,
|
||||
bool? confirmed,
|
||||
DateTime? createdAt,
|
||||
}) {
|
||||
return Authenticator(
|
||||
id: id ?? this.id,
|
||||
name: name ?? this.name,
|
||||
confirmed: confirmed ?? this.confirmed,
|
||||
createdAt: createdAt ?? this.createdAt,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
/* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */
|
||||
/* To generate run: "serverpod generate" */
|
||||
|
||||
// ignore_for_file: implementation_imports
|
||||
// ignore_for_file: library_private_types_in_public_api
|
||||
// ignore_for_file: non_constant_identifier_names
|
||||
// ignore_for_file: public_member_api_docs
|
||||
// ignore_for_file: type_literal_in_constant_pattern
|
||||
// ignore_for_file: use_super_parameters
|
||||
// ignore_for_file: invalid_use_of_internal_member
|
||||
|
||||
// ignore_for_file: no_leading_underscores_for_library_prefixes
|
||||
import 'package:serverpod_client/serverpod_client.dart' as _isc;
|
||||
|
||||
/// A new authenticator (ADR 0017): the `otpauth://` URI its app reads from a
|
||||
/// QR code, shown this once, and the ID a code from it confirms.
|
||||
abstract class AuthenticatorEnrolment
|
||||
implements _isc.SerializableModel, _isc.ProtocolSerialization {
|
||||
AuthenticatorEnrolment._({
|
||||
required this.authenticator,
|
||||
required this.uri,
|
||||
});
|
||||
|
||||
factory AuthenticatorEnrolment({
|
||||
required _isc.UuidValue authenticator,
|
||||
required String uri,
|
||||
}) = _AuthenticatorEnrolmentImpl;
|
||||
|
||||
factory AuthenticatorEnrolment.fromJson(
|
||||
Map<String, dynamic> jsonSerialization,
|
||||
) {
|
||||
return AuthenticatorEnrolment(
|
||||
authenticator: _isc.UuidValueJsonExtension.fromJson(
|
||||
jsonSerialization['authenticator'],
|
||||
),
|
||||
uri: jsonSerialization['uri'] as String,
|
||||
);
|
||||
}
|
||||
|
||||
_isc.UuidValue authenticator;
|
||||
|
||||
String uri;
|
||||
|
||||
/// Returns a shallow copy of this [AuthenticatorEnrolment]
|
||||
/// with some or all fields replaced by the given arguments.
|
||||
@_isc.useResult
|
||||
AuthenticatorEnrolment copyWith({
|
||||
_isc.UuidValue? authenticator,
|
||||
String? uri,
|
||||
});
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'__className__': 'halkyon_base.AuthenticatorEnrolment',
|
||||
'authenticator': authenticator.toJson(),
|
||||
'uri': uri,
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJsonForProtocol() {
|
||||
return {
|
||||
'__className__': 'halkyon_base.AuthenticatorEnrolment',
|
||||
'authenticator': authenticator.toJson(),
|
||||
'uri': uri,
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return _isc.SerializationManager.encode(this);
|
||||
}
|
||||
}
|
||||
|
||||
class _AuthenticatorEnrolmentImpl extends AuthenticatorEnrolment {
|
||||
_AuthenticatorEnrolmentImpl({
|
||||
required _isc.UuidValue authenticator,
|
||||
required String uri,
|
||||
}) : super._(
|
||||
authenticator: authenticator,
|
||||
uri: uri,
|
||||
);
|
||||
|
||||
/// Returns a shallow copy of this [AuthenticatorEnrolment]
|
||||
/// with some or all fields replaced by the given arguments.
|
||||
@_isc.useResult
|
||||
@override
|
||||
AuthenticatorEnrolment copyWith({
|
||||
_isc.UuidValue? authenticator,
|
||||
String? uri,
|
||||
}) {
|
||||
return AuthenticatorEnrolment(
|
||||
authenticator: authenticator ?? this.authenticator,
|
||||
uri: uri ?? this.uri,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,144 @@
|
|||
/* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */
|
||||
/* To generate run: "serverpod generate" */
|
||||
|
||||
// ignore_for_file: implementation_imports
|
||||
// ignore_for_file: library_private_types_in_public_api
|
||||
// ignore_for_file: non_constant_identifier_names
|
||||
// ignore_for_file: public_member_api_docs
|
||||
// ignore_for_file: type_literal_in_constant_pattern
|
||||
// ignore_for_file: use_super_parameters
|
||||
// ignore_for_file: invalid_use_of_internal_member
|
||||
|
||||
// ignore_for_file: no_leading_underscores_for_library_prefixes
|
||||
import 'dart:typed_data' as _idt;
|
||||
import 'package:halkyon_base_client/src/protocol/protocol.dart' as _iwgbpyo5;
|
||||
import 'package:serverpod_client/serverpod_client.dart' as _isc;
|
||||
import '../password/wrapped_keys.dart' as _i2rxumte;
|
||||
|
||||
/// What a device needs to prove the recovery phrase (ADR 0017): the
|
||||
/// account's private keys wrapped under the phrase's key and its public
|
||||
/// keys, which the device opens with the phrase, and a nonce it signs with
|
||||
/// the signing key so opened, within two minutes, once. Alike for an address
|
||||
/// nobody has.
|
||||
abstract class KeyProofChallenge
|
||||
implements _isc.SerializableModel, _isc.ProtocolSerialization {
|
||||
KeyProofChallenge._({
|
||||
required this.challenge,
|
||||
required this.nonce,
|
||||
required this.encryptionPublicKey,
|
||||
required this.signingPublicKey,
|
||||
required this.recoveryKeys,
|
||||
});
|
||||
|
||||
factory KeyProofChallenge({
|
||||
required _isc.UuidValue challenge,
|
||||
required _idt.ByteData nonce,
|
||||
required _idt.ByteData encryptionPublicKey,
|
||||
required _idt.ByteData signingPublicKey,
|
||||
required _i2rxumte.WrappedKeys recoveryKeys,
|
||||
}) = _KeyProofChallengeImpl;
|
||||
|
||||
factory KeyProofChallenge.fromJson(Map<String, dynamic> jsonSerialization) {
|
||||
return KeyProofChallenge(
|
||||
challenge: _isc.UuidValueJsonExtension.fromJson(
|
||||
jsonSerialization['challenge'],
|
||||
),
|
||||
nonce: _isc.ByteDataJsonExtension.fromJson(jsonSerialization['nonce']),
|
||||
encryptionPublicKey: _isc.ByteDataJsonExtension.fromJson(
|
||||
jsonSerialization['encryptionPublicKey'],
|
||||
),
|
||||
signingPublicKey: _isc.ByteDataJsonExtension.fromJson(
|
||||
jsonSerialization['signingPublicKey'],
|
||||
),
|
||||
recoveryKeys: _iwgbpyo5.Protocol().deserialize<_i2rxumte.WrappedKeys>(
|
||||
jsonSerialization['recoveryKeys'],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
_isc.UuidValue challenge;
|
||||
|
||||
_idt.ByteData nonce;
|
||||
|
||||
_idt.ByteData encryptionPublicKey;
|
||||
|
||||
_idt.ByteData signingPublicKey;
|
||||
|
||||
_i2rxumte.WrappedKeys recoveryKeys;
|
||||
|
||||
/// Returns a shallow copy of this [KeyProofChallenge]
|
||||
/// with some or all fields replaced by the given arguments.
|
||||
@_isc.useResult
|
||||
KeyProofChallenge copyWith({
|
||||
_isc.UuidValue? challenge,
|
||||
_idt.ByteData? nonce,
|
||||
_idt.ByteData? encryptionPublicKey,
|
||||
_idt.ByteData? signingPublicKey,
|
||||
_i2rxumte.WrappedKeys? recoveryKeys,
|
||||
});
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'__className__': 'halkyon_base.KeyProofChallenge',
|
||||
'challenge': challenge.toJson(),
|
||||
'nonce': nonce.toJson(),
|
||||
'encryptionPublicKey': encryptionPublicKey.toJson(),
|
||||
'signingPublicKey': signingPublicKey.toJson(),
|
||||
'recoveryKeys': recoveryKeys.toJson(),
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJsonForProtocol() {
|
||||
return {
|
||||
'__className__': 'halkyon_base.KeyProofChallenge',
|
||||
'challenge': challenge.toJson(),
|
||||
'nonce': nonce.toJson(),
|
||||
'encryptionPublicKey': encryptionPublicKey.toJson(),
|
||||
'signingPublicKey': signingPublicKey.toJson(),
|
||||
'recoveryKeys': recoveryKeys.toJsonForProtocol(),
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return _isc.SerializationManager.encode(this);
|
||||
}
|
||||
}
|
||||
|
||||
class _KeyProofChallengeImpl extends KeyProofChallenge {
|
||||
_KeyProofChallengeImpl({
|
||||
required _isc.UuidValue challenge,
|
||||
required _idt.ByteData nonce,
|
||||
required _idt.ByteData encryptionPublicKey,
|
||||
required _idt.ByteData signingPublicKey,
|
||||
required _i2rxumte.WrappedKeys recoveryKeys,
|
||||
}) : super._(
|
||||
challenge: challenge,
|
||||
nonce: nonce,
|
||||
encryptionPublicKey: encryptionPublicKey,
|
||||
signingPublicKey: signingPublicKey,
|
||||
recoveryKeys: recoveryKeys,
|
||||
);
|
||||
|
||||
/// Returns a shallow copy of this [KeyProofChallenge]
|
||||
/// with some or all fields replaced by the given arguments.
|
||||
@_isc.useResult
|
||||
@override
|
||||
KeyProofChallenge copyWith({
|
||||
_isc.UuidValue? challenge,
|
||||
_idt.ByteData? nonce,
|
||||
_idt.ByteData? encryptionPublicKey,
|
||||
_idt.ByteData? signingPublicKey,
|
||||
_i2rxumte.WrappedKeys? recoveryKeys,
|
||||
}) {
|
||||
return KeyProofChallenge(
|
||||
challenge: challenge ?? this.challenge,
|
||||
nonce: nonce ?? this.nonce.clone(),
|
||||
encryptionPublicKey:
|
||||
encryptionPublicKey ?? this.encryptionPublicKey.clone(),
|
||||
signingPublicKey: signingPublicKey ?? this.signingPublicKey.clone(),
|
||||
recoveryKeys: recoveryKeys ?? this.recoveryKeys.copyWith(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,128 @@
|
|||
/* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */
|
||||
/* To generate run: "serverpod generate" */
|
||||
|
||||
// ignore_for_file: implementation_imports
|
||||
// ignore_for_file: library_private_types_in_public_api
|
||||
// ignore_for_file: non_constant_identifier_names
|
||||
// ignore_for_file: public_member_api_docs
|
||||
// ignore_for_file: type_literal_in_constant_pattern
|
||||
// ignore_for_file: use_super_parameters
|
||||
// ignore_for_file: invalid_use_of_internal_member
|
||||
|
||||
// ignore_for_file: no_leading_underscores_for_library_prefixes
|
||||
import 'dart:typed_data' as _idt;
|
||||
import 'package:halkyon_base_client/src/protocol/protocol.dart' as _iwgbpyo5;
|
||||
import 'package:serverpod_client/serverpod_client.dart' as _isc;
|
||||
import '../password/password_costs.dart' as _ioe6tior;
|
||||
import '../password/wrapped_keys.dart' as _i2rxumte;
|
||||
|
||||
/// A new password for an account whose keys stay (ADR 0017: a lost password,
|
||||
/// proven with the recovery phrase): a new salt, costs, verifier, and the
|
||||
/// same private keys wrapped under the new password's key.
|
||||
abstract class NewPassword
|
||||
implements _isc.SerializableModel, _isc.ProtocolSerialization {
|
||||
NewPassword._({
|
||||
required this.salt,
|
||||
required this.costs,
|
||||
required this.verifier,
|
||||
required this.passwordKeys,
|
||||
});
|
||||
|
||||
factory NewPassword({
|
||||
required _idt.ByteData salt,
|
||||
required _ioe6tior.PasswordCosts costs,
|
||||
required _idt.ByteData verifier,
|
||||
required _i2rxumte.WrappedKeys passwordKeys,
|
||||
}) = _NewPasswordImpl;
|
||||
|
||||
factory NewPassword.fromJson(Map<String, dynamic> jsonSerialization) {
|
||||
return NewPassword(
|
||||
salt: _isc.ByteDataJsonExtension.fromJson(jsonSerialization['salt']),
|
||||
costs: _iwgbpyo5.Protocol().deserialize<_ioe6tior.PasswordCosts>(
|
||||
jsonSerialization['costs'],
|
||||
),
|
||||
verifier: _isc.ByteDataJsonExtension.fromJson(
|
||||
jsonSerialization['verifier'],
|
||||
),
|
||||
passwordKeys: _iwgbpyo5.Protocol().deserialize<_i2rxumte.WrappedKeys>(
|
||||
jsonSerialization['passwordKeys'],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
_idt.ByteData salt;
|
||||
|
||||
_ioe6tior.PasswordCosts costs;
|
||||
|
||||
_idt.ByteData verifier;
|
||||
|
||||
_i2rxumte.WrappedKeys passwordKeys;
|
||||
|
||||
/// Returns a shallow copy of this [NewPassword]
|
||||
/// with some or all fields replaced by the given arguments.
|
||||
@_isc.useResult
|
||||
NewPassword copyWith({
|
||||
_idt.ByteData? salt,
|
||||
_ioe6tior.PasswordCosts? costs,
|
||||
_idt.ByteData? verifier,
|
||||
_i2rxumte.WrappedKeys? passwordKeys,
|
||||
});
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'__className__': 'halkyon_base.NewPassword',
|
||||
'salt': salt.toJson(),
|
||||
'costs': costs.toJson(),
|
||||
'verifier': verifier.toJson(),
|
||||
'passwordKeys': passwordKeys.toJson(),
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJsonForProtocol() {
|
||||
return {
|
||||
'__className__': 'halkyon_base.NewPassword',
|
||||
'salt': salt.toJson(),
|
||||
'costs': costs.toJsonForProtocol(),
|
||||
'verifier': verifier.toJson(),
|
||||
'passwordKeys': passwordKeys.toJsonForProtocol(),
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return _isc.SerializationManager.encode(this);
|
||||
}
|
||||
}
|
||||
|
||||
class _NewPasswordImpl extends NewPassword {
|
||||
_NewPasswordImpl({
|
||||
required _idt.ByteData salt,
|
||||
required _ioe6tior.PasswordCosts costs,
|
||||
required _idt.ByteData verifier,
|
||||
required _i2rxumte.WrappedKeys passwordKeys,
|
||||
}) : super._(
|
||||
salt: salt,
|
||||
costs: costs,
|
||||
verifier: verifier,
|
||||
passwordKeys: passwordKeys,
|
||||
);
|
||||
|
||||
/// Returns a shallow copy of this [NewPassword]
|
||||
/// with some or all fields replaced by the given arguments.
|
||||
@_isc.useResult
|
||||
@override
|
||||
NewPassword copyWith({
|
||||
_idt.ByteData? salt,
|
||||
_ioe6tior.PasswordCosts? costs,
|
||||
_idt.ByteData? verifier,
|
||||
_i2rxumte.WrappedKeys? passwordKeys,
|
||||
}) {
|
||||
return NewPassword(
|
||||
salt: salt ?? this.salt.clone(),
|
||||
costs: costs ?? this.costs.copyWith(),
|
||||
verifier: verifier ?? this.verifier.clone(),
|
||||
passwordKeys: passwordKeys ?? this.passwordKeys.copyWith(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,129 @@
|
|||
/* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */
|
||||
/* To generate run: "serverpod generate" */
|
||||
|
||||
// ignore_for_file: implementation_imports
|
||||
// ignore_for_file: library_private_types_in_public_api
|
||||
// ignore_for_file: non_constant_identifier_names
|
||||
// ignore_for_file: public_member_api_docs
|
||||
// ignore_for_file: type_literal_in_constant_pattern
|
||||
// ignore_for_file: use_super_parameters
|
||||
// ignore_for_file: invalid_use_of_internal_member
|
||||
|
||||
// ignore_for_file: no_leading_underscores_for_library_prefixes
|
||||
import 'dart:typed_data' as _idt;
|
||||
import 'package:halkyon_base_client/src/protocol/protocol.dart' as _iwgbpyo5;
|
||||
import 'package:serverpod_client/serverpod_client.dart' as _isc;
|
||||
import '../password/password_costs.dart' as _ioe6tior;
|
||||
|
||||
/// The register's answer to the first step of signing in with a password
|
||||
/// (ADR 0017, SRP-6a): what the device needs to derive the password's keys
|
||||
/// and its proof. Alike for an address nobody has.
|
||||
abstract class PasswordChallenge
|
||||
implements _isc.SerializableModel, _isc.ProtocolSerialization {
|
||||
PasswordChallenge._({
|
||||
required this.challenge,
|
||||
required this.salt,
|
||||
required this.costs,
|
||||
required this.serverValue,
|
||||
});
|
||||
|
||||
factory PasswordChallenge({
|
||||
required _isc.UuidValue challenge,
|
||||
required _idt.ByteData salt,
|
||||
required _ioe6tior.PasswordCosts costs,
|
||||
required _idt.ByteData serverValue,
|
||||
}) = _PasswordChallengeImpl;
|
||||
|
||||
factory PasswordChallenge.fromJson(Map<String, dynamic> jsonSerialization) {
|
||||
return PasswordChallenge(
|
||||
challenge: _isc.UuidValueJsonExtension.fromJson(
|
||||
jsonSerialization['challenge'],
|
||||
),
|
||||
salt: _isc.ByteDataJsonExtension.fromJson(jsonSerialization['salt']),
|
||||
costs: _iwgbpyo5.Protocol().deserialize<_ioe6tior.PasswordCosts>(
|
||||
jsonSerialization['costs'],
|
||||
),
|
||||
serverValue: _isc.ByteDataJsonExtension.fromJson(
|
||||
jsonSerialization['serverValue'],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// Names this sign-in in the second step; SRP's identity too.
|
||||
_isc.UuidValue challenge;
|
||||
|
||||
_idt.ByteData salt;
|
||||
|
||||
_ioe6tior.PasswordCosts costs;
|
||||
|
||||
/// SRP's B, big-endian.
|
||||
_idt.ByteData serverValue;
|
||||
|
||||
/// Returns a shallow copy of this [PasswordChallenge]
|
||||
/// with some or all fields replaced by the given arguments.
|
||||
@_isc.useResult
|
||||
PasswordChallenge copyWith({
|
||||
_isc.UuidValue? challenge,
|
||||
_idt.ByteData? salt,
|
||||
_ioe6tior.PasswordCosts? costs,
|
||||
_idt.ByteData? serverValue,
|
||||
});
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'__className__': 'halkyon_base.PasswordChallenge',
|
||||
'challenge': challenge.toJson(),
|
||||
'salt': salt.toJson(),
|
||||
'costs': costs.toJson(),
|
||||
'serverValue': serverValue.toJson(),
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJsonForProtocol() {
|
||||
return {
|
||||
'__className__': 'halkyon_base.PasswordChallenge',
|
||||
'challenge': challenge.toJson(),
|
||||
'salt': salt.toJson(),
|
||||
'costs': costs.toJsonForProtocol(),
|
||||
'serverValue': serverValue.toJson(),
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return _isc.SerializationManager.encode(this);
|
||||
}
|
||||
}
|
||||
|
||||
class _PasswordChallengeImpl extends PasswordChallenge {
|
||||
_PasswordChallengeImpl({
|
||||
required _isc.UuidValue challenge,
|
||||
required _idt.ByteData salt,
|
||||
required _ioe6tior.PasswordCosts costs,
|
||||
required _idt.ByteData serverValue,
|
||||
}) : super._(
|
||||
challenge: challenge,
|
||||
salt: salt,
|
||||
costs: costs,
|
||||
serverValue: serverValue,
|
||||
);
|
||||
|
||||
/// Returns a shallow copy of this [PasswordChallenge]
|
||||
/// with some or all fields replaced by the given arguments.
|
||||
@_isc.useResult
|
||||
@override
|
||||
PasswordChallenge copyWith({
|
||||
_isc.UuidValue? challenge,
|
||||
_idt.ByteData? salt,
|
||||
_ioe6tior.PasswordCosts? costs,
|
||||
_idt.ByteData? serverValue,
|
||||
}) {
|
||||
return PasswordChallenge(
|
||||
challenge: challenge ?? this.challenge,
|
||||
salt: salt ?? this.salt.clone(),
|
||||
costs: costs ?? this.costs.copyWith(),
|
||||
serverValue: serverValue ?? this.serverValue.clone(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,108 @@
|
|||
/* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */
|
||||
/* To generate run: "serverpod generate" */
|
||||
|
||||
// ignore_for_file: implementation_imports
|
||||
// ignore_for_file: library_private_types_in_public_api
|
||||
// ignore_for_file: non_constant_identifier_names
|
||||
// ignore_for_file: public_member_api_docs
|
||||
// ignore_for_file: type_literal_in_constant_pattern
|
||||
// ignore_for_file: use_super_parameters
|
||||
// ignore_for_file: invalid_use_of_internal_member
|
||||
|
||||
// ignore_for_file: no_leading_underscores_for_library_prefixes
|
||||
import 'package:serverpod_client/serverpod_client.dart' as _isc;
|
||||
|
||||
/// Argon2id's costs for an account's password (ADR 0017), as halkyon_keys'
|
||||
/// `PasswordKdf` names them: the device refuses costs below its floor.
|
||||
abstract class PasswordCosts
|
||||
implements _isc.SerializableModel, _isc.ProtocolSerialization {
|
||||
PasswordCosts._({
|
||||
required this.algorithm,
|
||||
required this.opsLimit,
|
||||
required this.memLimit,
|
||||
});
|
||||
|
||||
factory PasswordCosts({
|
||||
required String algorithm,
|
||||
required int opsLimit,
|
||||
required int memLimit,
|
||||
}) = _PasswordCostsImpl;
|
||||
|
||||
factory PasswordCosts.fromJson(Map<String, dynamic> jsonSerialization) {
|
||||
return PasswordCosts(
|
||||
algorithm: jsonSerialization['algorithm'] as String,
|
||||
opsLimit: jsonSerialization['opsLimit'] as int,
|
||||
memLimit: jsonSerialization['memLimit'] as int,
|
||||
);
|
||||
}
|
||||
|
||||
/// libsodium's name for the algorithm: `argon2id13`.
|
||||
String algorithm;
|
||||
|
||||
/// Passes.
|
||||
int opsLimit;
|
||||
|
||||
/// Memory, in bytes.
|
||||
int memLimit;
|
||||
|
||||
/// Returns a shallow copy of this [PasswordCosts]
|
||||
/// with some or all fields replaced by the given arguments.
|
||||
@_isc.useResult
|
||||
PasswordCosts copyWith({
|
||||
String? algorithm,
|
||||
int? opsLimit,
|
||||
int? memLimit,
|
||||
});
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'__className__': 'halkyon_base.PasswordCosts',
|
||||
'algorithm': algorithm,
|
||||
'opsLimit': opsLimit,
|
||||
'memLimit': memLimit,
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJsonForProtocol() {
|
||||
return {
|
||||
'__className__': 'halkyon_base.PasswordCosts',
|
||||
'algorithm': algorithm,
|
||||
'opsLimit': opsLimit,
|
||||
'memLimit': memLimit,
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return _isc.SerializationManager.encode(this);
|
||||
}
|
||||
}
|
||||
|
||||
class _PasswordCostsImpl extends PasswordCosts {
|
||||
_PasswordCostsImpl({
|
||||
required String algorithm,
|
||||
required int opsLimit,
|
||||
required int memLimit,
|
||||
}) : super._(
|
||||
algorithm: algorithm,
|
||||
opsLimit: opsLimit,
|
||||
memLimit: memLimit,
|
||||
);
|
||||
|
||||
/// Returns a shallow copy of this [PasswordCosts]
|
||||
/// with some or all fields replaced by the given arguments.
|
||||
@_isc.useResult
|
||||
@override
|
||||
PasswordCosts copyWith({
|
||||
String? algorithm,
|
||||
int? opsLimit,
|
||||
int? memLimit,
|
||||
}) {
|
||||
return PasswordCosts(
|
||||
algorithm: algorithm ?? this.algorithm,
|
||||
opsLimit: opsLimit ?? this.opsLimit,
|
||||
memLimit: memLimit ?? this.memLimit,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,120 @@
|
|||
/* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */
|
||||
/* To generate run: "serverpod generate" */
|
||||
|
||||
// ignore_for_file: implementation_imports
|
||||
// ignore_for_file: library_private_types_in_public_api
|
||||
// ignore_for_file: non_constant_identifier_names
|
||||
// ignore_for_file: public_member_api_docs
|
||||
// ignore_for_file: type_literal_in_constant_pattern
|
||||
// ignore_for_file: use_super_parameters
|
||||
// ignore_for_file: invalid_use_of_internal_member
|
||||
|
||||
// ignore_for_file: no_leading_underscores_for_library_prefixes
|
||||
import 'package:serverpod_client/serverpod_client.dart' as _isc;
|
||||
|
||||
/// Why something to do with a password, an authenticator or a reset was
|
||||
/// refused (ADR 0017); nothing changed then.
|
||||
enum PasswordRefusal implements _isc.SerializableModel {
|
||||
/// This instance has no password sign-in (its operator set none of the
|
||||
/// keys it needs).
|
||||
unavailable,
|
||||
|
||||
/// The address, the password, or the code (a TOTP or a recovery code)
|
||||
/// isn't right: one answer for all, so none tells which.
|
||||
wrongCredentials,
|
||||
|
||||
/// Too many sign-ins begun for this address or from this network in the
|
||||
/// last hour, or too many codes tried for this account.
|
||||
tooManyAttempts,
|
||||
|
||||
/// The step began too long ago, or was finished already: begin again.
|
||||
challengeExpired,
|
||||
|
||||
/// The password is right, but no authenticator was confirmed yet: finish
|
||||
/// setting one up where the password was set (or, while email codes still
|
||||
/// sign in, signed in with a code by mail).
|
||||
setupIncomplete,
|
||||
|
||||
/// What the device sent isn't a password's setup: a verifier, a key, a
|
||||
/// salt or costs out of range.
|
||||
invalidSetup,
|
||||
|
||||
/// The account has a password already.
|
||||
passwordExists,
|
||||
|
||||
/// The account has no email address yet: a password needs one, for
|
||||
/// resets. A code mailed to one makes it the account's.
|
||||
noAddress,
|
||||
|
||||
/// The address the code proved is another account's.
|
||||
addressTaken,
|
||||
|
||||
/// The account has no password yet.
|
||||
noPassword,
|
||||
|
||||
/// No such authenticator of the account.
|
||||
unknownAuthenticator,
|
||||
|
||||
/// The account's last confirmed authenticator can't go: the second factor
|
||||
/// is mandatory.
|
||||
lastAuthenticator,
|
||||
|
||||
/// The account has as many authenticators as it may: remove one first.
|
||||
tooManyAuthenticators,
|
||||
|
||||
/// The code from the authenticator isn't right.
|
||||
wrongCode,
|
||||
|
||||
/// The reset's time hasn't come yet.
|
||||
notDue,
|
||||
|
||||
/// No such reset is waiting, or the address isn't the account's.
|
||||
noReset;
|
||||
|
||||
static PasswordRefusal fromJson(String name) {
|
||||
switch (name) {
|
||||
case 'unavailable':
|
||||
return PasswordRefusal.unavailable;
|
||||
case 'wrongCredentials':
|
||||
return PasswordRefusal.wrongCredentials;
|
||||
case 'tooManyAttempts':
|
||||
return PasswordRefusal.tooManyAttempts;
|
||||
case 'challengeExpired':
|
||||
return PasswordRefusal.challengeExpired;
|
||||
case 'setupIncomplete':
|
||||
return PasswordRefusal.setupIncomplete;
|
||||
case 'invalidSetup':
|
||||
return PasswordRefusal.invalidSetup;
|
||||
case 'passwordExists':
|
||||
return PasswordRefusal.passwordExists;
|
||||
case 'noAddress':
|
||||
return PasswordRefusal.noAddress;
|
||||
case 'addressTaken':
|
||||
return PasswordRefusal.addressTaken;
|
||||
case 'noPassword':
|
||||
return PasswordRefusal.noPassword;
|
||||
case 'unknownAuthenticator':
|
||||
return PasswordRefusal.unknownAuthenticator;
|
||||
case 'lastAuthenticator':
|
||||
return PasswordRefusal.lastAuthenticator;
|
||||
case 'tooManyAuthenticators':
|
||||
return PasswordRefusal.tooManyAuthenticators;
|
||||
case 'wrongCode':
|
||||
return PasswordRefusal.wrongCode;
|
||||
case 'notDue':
|
||||
return PasswordRefusal.notDue;
|
||||
case 'noReset':
|
||||
return PasswordRefusal.noReset;
|
||||
default:
|
||||
throw ArgumentError(
|
||||
'Value "$name" cannot be converted to "PasswordRefusal"',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
String toJson() => name;
|
||||
|
||||
@override
|
||||
String toString() => name;
|
||||
}
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
/* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */
|
||||
/* To generate run: "serverpod generate" */
|
||||
|
||||
// ignore_for_file: implementation_imports
|
||||
// ignore_for_file: library_private_types_in_public_api
|
||||
// ignore_for_file: non_constant_identifier_names
|
||||
// ignore_for_file: public_member_api_docs
|
||||
// ignore_for_file: type_literal_in_constant_pattern
|
||||
// ignore_for_file: use_super_parameters
|
||||
// ignore_for_file: invalid_use_of_internal_member
|
||||
|
||||
// ignore_for_file: no_leading_underscores_for_library_prefixes
|
||||
import 'package:serverpod_client/serverpod_client.dart' as _isc;
|
||||
import '../password/password_refusal.dart' as _i647hpdf;
|
||||
|
||||
/// Something to do with a password, an authenticator or a reset was refused
|
||||
/// (ADR 0017); nothing changed.
|
||||
abstract class PasswordRefusedException
|
||||
implements
|
||||
_isc.SerializableException,
|
||||
_isc.SerializableModel,
|
||||
_isc.ProtocolSerialization {
|
||||
PasswordRefusedException._({required this.reason});
|
||||
|
||||
factory PasswordRefusedException({
|
||||
required _i647hpdf.PasswordRefusal reason,
|
||||
}) = _PasswordRefusedExceptionImpl;
|
||||
|
||||
factory PasswordRefusedException.fromJson(
|
||||
Map<String, dynamic> jsonSerialization,
|
||||
) {
|
||||
return PasswordRefusedException(
|
||||
reason: _i647hpdf.PasswordRefusal.fromJson(
|
||||
(jsonSerialization['reason'] as String),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
_i647hpdf.PasswordRefusal reason;
|
||||
|
||||
/// Returns a shallow copy of this [PasswordRefusedException]
|
||||
/// with some or all fields replaced by the given arguments.
|
||||
@_isc.useResult
|
||||
PasswordRefusedException copyWith({_i647hpdf.PasswordRefusal? reason});
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'__className__': 'halkyon_base.PasswordRefusedException',
|
||||
'reason': reason.toJson(),
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJsonForProtocol() {
|
||||
return {
|
||||
'__className__': 'halkyon_base.PasswordRefusedException',
|
||||
'reason': reason.toJson(),
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'PasswordRefusedException(reason: $reason)';
|
||||
}
|
||||
}
|
||||
|
||||
class _PasswordRefusedExceptionImpl extends PasswordRefusedException {
|
||||
_PasswordRefusedExceptionImpl({required _i647hpdf.PasswordRefusal reason})
|
||||
: super._(reason: reason);
|
||||
|
||||
/// Returns a shallow copy of this [PasswordRefusedException]
|
||||
/// with some or all fields replaced by the given arguments.
|
||||
@_isc.useResult
|
||||
@override
|
||||
PasswordRefusedException copyWith({_i647hpdf.PasswordRefusal? reason}) {
|
||||
return PasswordRefusedException(reason: reason ?? this.reason);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,174 @@
|
|||
/* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */
|
||||
/* To generate run: "serverpod generate" */
|
||||
|
||||
// ignore_for_file: implementation_imports
|
||||
// ignore_for_file: library_private_types_in_public_api
|
||||
// ignore_for_file: non_constant_identifier_names
|
||||
// ignore_for_file: public_member_api_docs
|
||||
// ignore_for_file: type_literal_in_constant_pattern
|
||||
// ignore_for_file: use_super_parameters
|
||||
// ignore_for_file: invalid_use_of_internal_member
|
||||
|
||||
// ignore_for_file: no_leading_underscores_for_library_prefixes
|
||||
import 'dart:typed_data' as _idt;
|
||||
import 'package:halkyon_base_client/src/protocol/protocol.dart' as _iwgbpyo5;
|
||||
import 'package:serverpod_client/serverpod_client.dart' as _isc;
|
||||
import '../password/password_costs.dart' as _ioe6tior;
|
||||
import '../password/wrapped_keys.dart' as _i2rxumte;
|
||||
|
||||
/// What a device sends to give an account a password (ADR 0017), all made on
|
||||
/// the device: the salt and costs it derived the password's keys with, SRP's
|
||||
/// verifier, the account's public keys, and its private keys wrapped under
|
||||
/// the password's key and the recovery phrase's. Nothing of it signs in or
|
||||
/// decrypts in the password's place.
|
||||
abstract class PasswordSetup
|
||||
implements _isc.SerializableModel, _isc.ProtocolSerialization {
|
||||
PasswordSetup._({
|
||||
required this.salt,
|
||||
required this.costs,
|
||||
required this.verifier,
|
||||
required this.encryptionPublicKey,
|
||||
required this.signingPublicKey,
|
||||
required this.passwordKeys,
|
||||
required this.recoveryKeys,
|
||||
});
|
||||
|
||||
factory PasswordSetup({
|
||||
required _idt.ByteData salt,
|
||||
required _ioe6tior.PasswordCosts costs,
|
||||
required _idt.ByteData verifier,
|
||||
required _idt.ByteData encryptionPublicKey,
|
||||
required _idt.ByteData signingPublicKey,
|
||||
required _i2rxumte.WrappedKeys passwordKeys,
|
||||
required _i2rxumte.WrappedKeys recoveryKeys,
|
||||
}) = _PasswordSetupImpl;
|
||||
|
||||
factory PasswordSetup.fromJson(Map<String, dynamic> jsonSerialization) {
|
||||
return PasswordSetup(
|
||||
salt: _isc.ByteDataJsonExtension.fromJson(jsonSerialization['salt']),
|
||||
costs: _iwgbpyo5.Protocol().deserialize<_ioe6tior.PasswordCosts>(
|
||||
jsonSerialization['costs'],
|
||||
),
|
||||
verifier: _isc.ByteDataJsonExtension.fromJson(
|
||||
jsonSerialization['verifier'],
|
||||
),
|
||||
encryptionPublicKey: _isc.ByteDataJsonExtension.fromJson(
|
||||
jsonSerialization['encryptionPublicKey'],
|
||||
),
|
||||
signingPublicKey: _isc.ByteDataJsonExtension.fromJson(
|
||||
jsonSerialization['signingPublicKey'],
|
||||
),
|
||||
passwordKeys: _iwgbpyo5.Protocol().deserialize<_i2rxumte.WrappedKeys>(
|
||||
jsonSerialization['passwordKeys'],
|
||||
),
|
||||
recoveryKeys: _iwgbpyo5.Protocol().deserialize<_i2rxumte.WrappedKeys>(
|
||||
jsonSerialization['recoveryKeys'],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
_idt.ByteData salt;
|
||||
|
||||
_ioe6tior.PasswordCosts costs;
|
||||
|
||||
/// v = g^x mod N, big-endian.
|
||||
_idt.ByteData verifier;
|
||||
|
||||
_idt.ByteData encryptionPublicKey;
|
||||
|
||||
_idt.ByteData signingPublicKey;
|
||||
|
||||
_i2rxumte.WrappedKeys passwordKeys;
|
||||
|
||||
_i2rxumte.WrappedKeys recoveryKeys;
|
||||
|
||||
/// Returns a shallow copy of this [PasswordSetup]
|
||||
/// with some or all fields replaced by the given arguments.
|
||||
@_isc.useResult
|
||||
PasswordSetup copyWith({
|
||||
_idt.ByteData? salt,
|
||||
_ioe6tior.PasswordCosts? costs,
|
||||
_idt.ByteData? verifier,
|
||||
_idt.ByteData? encryptionPublicKey,
|
||||
_idt.ByteData? signingPublicKey,
|
||||
_i2rxumte.WrappedKeys? passwordKeys,
|
||||
_i2rxumte.WrappedKeys? recoveryKeys,
|
||||
});
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'__className__': 'halkyon_base.PasswordSetup',
|
||||
'salt': salt.toJson(),
|
||||
'costs': costs.toJson(),
|
||||
'verifier': verifier.toJson(),
|
||||
'encryptionPublicKey': encryptionPublicKey.toJson(),
|
||||
'signingPublicKey': signingPublicKey.toJson(),
|
||||
'passwordKeys': passwordKeys.toJson(),
|
||||
'recoveryKeys': recoveryKeys.toJson(),
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJsonForProtocol() {
|
||||
return {
|
||||
'__className__': 'halkyon_base.PasswordSetup',
|
||||
'salt': salt.toJson(),
|
||||
'costs': costs.toJsonForProtocol(),
|
||||
'verifier': verifier.toJson(),
|
||||
'encryptionPublicKey': encryptionPublicKey.toJson(),
|
||||
'signingPublicKey': signingPublicKey.toJson(),
|
||||
'passwordKeys': passwordKeys.toJsonForProtocol(),
|
||||
'recoveryKeys': recoveryKeys.toJsonForProtocol(),
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return _isc.SerializationManager.encode(this);
|
||||
}
|
||||
}
|
||||
|
||||
class _PasswordSetupImpl extends PasswordSetup {
|
||||
_PasswordSetupImpl({
|
||||
required _idt.ByteData salt,
|
||||
required _ioe6tior.PasswordCosts costs,
|
||||
required _idt.ByteData verifier,
|
||||
required _idt.ByteData encryptionPublicKey,
|
||||
required _idt.ByteData signingPublicKey,
|
||||
required _i2rxumte.WrappedKeys passwordKeys,
|
||||
required _i2rxumte.WrappedKeys recoveryKeys,
|
||||
}) : super._(
|
||||
salt: salt,
|
||||
costs: costs,
|
||||
verifier: verifier,
|
||||
encryptionPublicKey: encryptionPublicKey,
|
||||
signingPublicKey: signingPublicKey,
|
||||
passwordKeys: passwordKeys,
|
||||
recoveryKeys: recoveryKeys,
|
||||
);
|
||||
|
||||
/// Returns a shallow copy of this [PasswordSetup]
|
||||
/// with some or all fields replaced by the given arguments.
|
||||
@_isc.useResult
|
||||
@override
|
||||
PasswordSetup copyWith({
|
||||
_idt.ByteData? salt,
|
||||
_ioe6tior.PasswordCosts? costs,
|
||||
_idt.ByteData? verifier,
|
||||
_idt.ByteData? encryptionPublicKey,
|
||||
_idt.ByteData? signingPublicKey,
|
||||
_i2rxumte.WrappedKeys? passwordKeys,
|
||||
_i2rxumte.WrappedKeys? recoveryKeys,
|
||||
}) {
|
||||
return PasswordSetup(
|
||||
salt: salt ?? this.salt.clone(),
|
||||
costs: costs ?? this.costs.copyWith(),
|
||||
verifier: verifier ?? this.verifier.clone(),
|
||||
encryptionPublicKey:
|
||||
encryptionPublicKey ?? this.encryptionPublicKey.clone(),
|
||||
signingPublicKey: signingPublicKey ?? this.signingPublicKey.clone(),
|
||||
passwordKeys: passwordKeys ?? this.passwordKeys.copyWith(),
|
||||
recoveryKeys: recoveryKeys ?? this.recoveryKeys.copyWith(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,233 @@
|
|||
/* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */
|
||||
/* To generate run: "serverpod generate" */
|
||||
|
||||
// ignore_for_file: implementation_imports
|
||||
// ignore_for_file: library_private_types_in_public_api
|
||||
// ignore_for_file: non_constant_identifier_names
|
||||
// ignore_for_file: public_member_api_docs
|
||||
// ignore_for_file: type_literal_in_constant_pattern
|
||||
// ignore_for_file: use_super_parameters
|
||||
// ignore_for_file: invalid_use_of_internal_member
|
||||
|
||||
// ignore_for_file: no_leading_underscores_for_library_prefixes
|
||||
import 'dart:typed_data' as _idt;
|
||||
import 'package:halkyon_base_client/src/protocol/protocol.dart' as _iwgbpyo5;
|
||||
import 'package:serverpod_client/serverpod_client.dart' as _isc;
|
||||
import '../password/wrapped_keys.dart' as _i2rxumte;
|
||||
|
||||
/// Signed in with a password (ADR 0017): SRP's proof M2, which the device
|
||||
/// checks before it trusts anything else here, the account's public keys and
|
||||
/// its private keys under the password's key, which the device opens, and
|
||||
/// the session. With [needsAuthenticator], the device sets up an
|
||||
/// authenticator before anything else (a reset of the second factor took
|
||||
/// effect).
|
||||
abstract class PasswordSignedIn
|
||||
implements _isc.SerializableModel, _isc.ProtocolSerialization {
|
||||
PasswordSignedIn._({
|
||||
required this.serverProof,
|
||||
required this.encryptionPublicKey,
|
||||
required this.signingPublicKey,
|
||||
required this.passwordKeys,
|
||||
required this.needsAuthenticator,
|
||||
required this.authStrategy,
|
||||
required this.token,
|
||||
this.tokenExpiresAt,
|
||||
this.refreshToken,
|
||||
required this.authUserId,
|
||||
required this.scopeNames,
|
||||
});
|
||||
|
||||
factory PasswordSignedIn({
|
||||
required _idt.ByteData serverProof,
|
||||
required _idt.ByteData encryptionPublicKey,
|
||||
required _idt.ByteData signingPublicKey,
|
||||
required _i2rxumte.WrappedKeys passwordKeys,
|
||||
required bool needsAuthenticator,
|
||||
required String authStrategy,
|
||||
required String token,
|
||||
DateTime? tokenExpiresAt,
|
||||
String? refreshToken,
|
||||
required _isc.UuidValue authUserId,
|
||||
required Set<String> scopeNames,
|
||||
}) = _PasswordSignedInImpl;
|
||||
|
||||
factory PasswordSignedIn.fromJson(Map<String, dynamic> jsonSerialization) {
|
||||
return PasswordSignedIn(
|
||||
serverProof: _isc.ByteDataJsonExtension.fromJson(
|
||||
jsonSerialization['serverProof'],
|
||||
),
|
||||
encryptionPublicKey: _isc.ByteDataJsonExtension.fromJson(
|
||||
jsonSerialization['encryptionPublicKey'],
|
||||
),
|
||||
signingPublicKey: _isc.ByteDataJsonExtension.fromJson(
|
||||
jsonSerialization['signingPublicKey'],
|
||||
),
|
||||
passwordKeys: _iwgbpyo5.Protocol().deserialize<_i2rxumte.WrappedKeys>(
|
||||
jsonSerialization['passwordKeys'],
|
||||
),
|
||||
needsAuthenticator: _isc.BoolJsonExtension.fromJson(
|
||||
jsonSerialization['needsAuthenticator'],
|
||||
),
|
||||
authStrategy: jsonSerialization['authStrategy'] as String,
|
||||
token: jsonSerialization['token'] as String,
|
||||
tokenExpiresAt: jsonSerialization['tokenExpiresAt'] == null
|
||||
? null
|
||||
: _isc.DateTimeJsonExtension.fromJson(
|
||||
jsonSerialization['tokenExpiresAt'],
|
||||
),
|
||||
refreshToken: jsonSerialization['refreshToken'] as String?,
|
||||
authUserId: _isc.UuidValueJsonExtension.fromJson(
|
||||
jsonSerialization['authUserId'],
|
||||
),
|
||||
scopeNames: _iwgbpyo5.Protocol().deserialize<Set<String>>(
|
||||
jsonSerialization['scopeNames'],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
_idt.ByteData serverProof;
|
||||
|
||||
_idt.ByteData encryptionPublicKey;
|
||||
|
||||
_idt.ByteData signingPublicKey;
|
||||
|
||||
_i2rxumte.WrappedKeys passwordKeys;
|
||||
|
||||
bool needsAuthenticator;
|
||||
|
||||
/// The session, as Serverpod's `AuthSuccess` has it (the device makes one
|
||||
/// of these fields for its session manager).
|
||||
String authStrategy;
|
||||
|
||||
String token;
|
||||
|
||||
DateTime? tokenExpiresAt;
|
||||
|
||||
String? refreshToken;
|
||||
|
||||
_isc.UuidValue authUserId;
|
||||
|
||||
Set<String> scopeNames;
|
||||
|
||||
/// Returns a shallow copy of this [PasswordSignedIn]
|
||||
/// with some or all fields replaced by the given arguments.
|
||||
@_isc.useResult
|
||||
PasswordSignedIn copyWith({
|
||||
_idt.ByteData? serverProof,
|
||||
_idt.ByteData? encryptionPublicKey,
|
||||
_idt.ByteData? signingPublicKey,
|
||||
_i2rxumte.WrappedKeys? passwordKeys,
|
||||
bool? needsAuthenticator,
|
||||
String? authStrategy,
|
||||
String? token,
|
||||
DateTime? tokenExpiresAt,
|
||||
String? refreshToken,
|
||||
_isc.UuidValue? authUserId,
|
||||
Set<String>? scopeNames,
|
||||
});
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'__className__': 'halkyon_base.PasswordSignedIn',
|
||||
'serverProof': serverProof.toJson(),
|
||||
'encryptionPublicKey': encryptionPublicKey.toJson(),
|
||||
'signingPublicKey': signingPublicKey.toJson(),
|
||||
'passwordKeys': passwordKeys.toJson(),
|
||||
'needsAuthenticator': needsAuthenticator,
|
||||
'authStrategy': authStrategy,
|
||||
'token': token,
|
||||
if (tokenExpiresAt != null) 'tokenExpiresAt': tokenExpiresAt?.toJson(),
|
||||
if (refreshToken != null) 'refreshToken': refreshToken,
|
||||
'authUserId': authUserId.toJson(),
|
||||
'scopeNames': scopeNames.toJson(),
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJsonForProtocol() {
|
||||
return {
|
||||
'__className__': 'halkyon_base.PasswordSignedIn',
|
||||
'serverProof': serverProof.toJson(),
|
||||
'encryptionPublicKey': encryptionPublicKey.toJson(),
|
||||
'signingPublicKey': signingPublicKey.toJson(),
|
||||
'passwordKeys': passwordKeys.toJsonForProtocol(),
|
||||
'needsAuthenticator': needsAuthenticator,
|
||||
'authStrategy': authStrategy,
|
||||
'token': token,
|
||||
if (tokenExpiresAt != null) 'tokenExpiresAt': tokenExpiresAt?.toJson(),
|
||||
if (refreshToken != null) 'refreshToken': refreshToken,
|
||||
'authUserId': authUserId.toJson(),
|
||||
'scopeNames': scopeNames.toJson(),
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return _isc.SerializationManager.encode(this);
|
||||
}
|
||||
}
|
||||
|
||||
class _Undefined {}
|
||||
|
||||
class _PasswordSignedInImpl extends PasswordSignedIn {
|
||||
_PasswordSignedInImpl({
|
||||
required _idt.ByteData serverProof,
|
||||
required _idt.ByteData encryptionPublicKey,
|
||||
required _idt.ByteData signingPublicKey,
|
||||
required _i2rxumte.WrappedKeys passwordKeys,
|
||||
required bool needsAuthenticator,
|
||||
required String authStrategy,
|
||||
required String token,
|
||||
DateTime? tokenExpiresAt,
|
||||
String? refreshToken,
|
||||
required _isc.UuidValue authUserId,
|
||||
required Set<String> scopeNames,
|
||||
}) : super._(
|
||||
serverProof: serverProof,
|
||||
encryptionPublicKey: encryptionPublicKey,
|
||||
signingPublicKey: signingPublicKey,
|
||||
passwordKeys: passwordKeys,
|
||||
needsAuthenticator: needsAuthenticator,
|
||||
authStrategy: authStrategy,
|
||||
token: token,
|
||||
tokenExpiresAt: tokenExpiresAt,
|
||||
refreshToken: refreshToken,
|
||||
authUserId: authUserId,
|
||||
scopeNames: scopeNames,
|
||||
);
|
||||
|
||||
/// Returns a shallow copy of this [PasswordSignedIn]
|
||||
/// with some or all fields replaced by the given arguments.
|
||||
@_isc.useResult
|
||||
@override
|
||||
PasswordSignedIn copyWith({
|
||||
_idt.ByteData? serverProof,
|
||||
_idt.ByteData? encryptionPublicKey,
|
||||
_idt.ByteData? signingPublicKey,
|
||||
_i2rxumte.WrappedKeys? passwordKeys,
|
||||
bool? needsAuthenticator,
|
||||
String? authStrategy,
|
||||
String? token,
|
||||
Object? tokenExpiresAt = _Undefined,
|
||||
Object? refreshToken = _Undefined,
|
||||
_isc.UuidValue? authUserId,
|
||||
Set<String>? scopeNames,
|
||||
}) {
|
||||
return PasswordSignedIn(
|
||||
serverProof: serverProof ?? this.serverProof.clone(),
|
||||
encryptionPublicKey:
|
||||
encryptionPublicKey ?? this.encryptionPublicKey.clone(),
|
||||
signingPublicKey: signingPublicKey ?? this.signingPublicKey.clone(),
|
||||
passwordKeys: passwordKeys ?? this.passwordKeys.copyWith(),
|
||||
needsAuthenticator: needsAuthenticator ?? this.needsAuthenticator,
|
||||
authStrategy: authStrategy ?? this.authStrategy,
|
||||
token: token ?? this.token,
|
||||
tokenExpiresAt: tokenExpiresAt is DateTime?
|
||||
? tokenExpiresAt
|
||||
: this.tokenExpiresAt,
|
||||
refreshToken: refreshToken is String? ? refreshToken : this.refreshToken,
|
||||
authUserId: authUserId ?? this.authUserId,
|
||||
scopeNames: scopeNames ?? this.scopeNames.map((e0) => e0).toSet(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
/* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */
|
||||
/* To generate run: "serverpod generate" */
|
||||
|
||||
// ignore_for_file: implementation_imports
|
||||
// ignore_for_file: library_private_types_in_public_api
|
||||
// ignore_for_file: non_constant_identifier_names
|
||||
// ignore_for_file: public_member_api_docs
|
||||
// ignore_for_file: type_literal_in_constant_pattern
|
||||
// ignore_for_file: use_super_parameters
|
||||
// ignore_for_file: invalid_use_of_internal_member
|
||||
|
||||
// ignore_for_file: no_leading_underscores_for_library_prefixes
|
||||
import 'package:serverpod_client/serverpod_client.dart' as _isc;
|
||||
|
||||
/// A reset asked for (ADR 0017): it takes effect at [takesEffectAt], unless
|
||||
/// the account's owner signs in before; a mail said so.
|
||||
abstract class ResetPending
|
||||
implements _isc.SerializableModel, _isc.ProtocolSerialization {
|
||||
ResetPending._({required this.takesEffectAt});
|
||||
|
||||
factory ResetPending({required DateTime takesEffectAt}) = _ResetPendingImpl;
|
||||
|
||||
factory ResetPending.fromJson(Map<String, dynamic> jsonSerialization) {
|
||||
return ResetPending(
|
||||
takesEffectAt: _isc.DateTimeJsonExtension.fromJson(
|
||||
jsonSerialization['takesEffectAt'],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
DateTime takesEffectAt;
|
||||
|
||||
/// Returns a shallow copy of this [ResetPending]
|
||||
/// with some or all fields replaced by the given arguments.
|
||||
@_isc.useResult
|
||||
ResetPending copyWith({DateTime? takesEffectAt});
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'__className__': 'halkyon_base.ResetPending',
|
||||
'takesEffectAt': takesEffectAt.toJson(),
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJsonForProtocol() {
|
||||
return {
|
||||
'__className__': 'halkyon_base.ResetPending',
|
||||
'takesEffectAt': takesEffectAt.toJson(),
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return _isc.SerializationManager.encode(this);
|
||||
}
|
||||
}
|
||||
|
||||
class _ResetPendingImpl extends ResetPending {
|
||||
_ResetPendingImpl({required DateTime takesEffectAt})
|
||||
: super._(takesEffectAt: takesEffectAt);
|
||||
|
||||
/// Returns a shallow copy of this [ResetPending]
|
||||
/// with some or all fields replaced by the given arguments.
|
||||
@_isc.useResult
|
||||
@override
|
||||
ResetPending copyWith({DateTime? takesEffectAt}) {
|
||||
return ResetPending(takesEffectAt: takesEffectAt ?? this.takesEffectAt);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
/* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */
|
||||
/* To generate run: "serverpod generate" */
|
||||
|
||||
// ignore_for_file: implementation_imports
|
||||
// ignore_for_file: library_private_types_in_public_api
|
||||
// ignore_for_file: non_constant_identifier_names
|
||||
// ignore_for_file: public_member_api_docs
|
||||
// ignore_for_file: type_literal_in_constant_pattern
|
||||
// ignore_for_file: use_super_parameters
|
||||
// ignore_for_file: invalid_use_of_internal_member
|
||||
|
||||
// ignore_for_file: no_leading_underscores_for_library_prefixes
|
||||
import 'package:serverpod_client/serverpod_client.dart' as _isc;
|
||||
|
||||
/// What a sign-in challenge is for.
|
||||
enum SignInChallengePurpose implements _isc.SerializableModel {
|
||||
/// Signing in with the password (SRP).
|
||||
password,
|
||||
|
||||
/// Proving the recovery phrase by signing a nonce with the account's key.
|
||||
keyProof;
|
||||
|
||||
static SignInChallengePurpose fromJson(String name) {
|
||||
switch (name) {
|
||||
case 'password':
|
||||
return SignInChallengePurpose.password;
|
||||
case 'keyProof':
|
||||
return SignInChallengePurpose.keyProof;
|
||||
default:
|
||||
throw ArgumentError(
|
||||
'Value "$name" cannot be converted to "SignInChallengePurpose"',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
String toJson() => name;
|
||||
|
||||
@override
|
||||
String toString() => name;
|
||||
}
|
||||
|
|
@ -0,0 +1,98 @@
|
|||
/* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */
|
||||
/* To generate run: "serverpod generate" */
|
||||
|
||||
// ignore_for_file: implementation_imports
|
||||
// ignore_for_file: library_private_types_in_public_api
|
||||
// ignore_for_file: non_constant_identifier_names
|
||||
// ignore_for_file: public_member_api_docs
|
||||
// ignore_for_file: type_literal_in_constant_pattern
|
||||
// ignore_for_file: use_super_parameters
|
||||
// ignore_for_file: invalid_use_of_internal_member
|
||||
|
||||
// ignore_for_file: no_leading_underscores_for_library_prefixes
|
||||
import 'dart:typed_data' as _idt;
|
||||
import 'package:serverpod_client/serverpod_client.dart' as _isc;
|
||||
|
||||
/// An account's private keys sealed under one key (ADR 0017), as
|
||||
/// halkyon_keys' `WrappedAccountKeys` has them: only a device opens them.
|
||||
abstract class WrappedKeys
|
||||
implements _isc.SerializableModel, _isc.ProtocolSerialization {
|
||||
WrappedKeys._({
|
||||
required this.nonce,
|
||||
required this.cipherText,
|
||||
});
|
||||
|
||||
factory WrappedKeys({
|
||||
required _idt.ByteData nonce,
|
||||
required _idt.ByteData cipherText,
|
||||
}) = _WrappedKeysImpl;
|
||||
|
||||
factory WrappedKeys.fromJson(Map<String, dynamic> jsonSerialization) {
|
||||
return WrappedKeys(
|
||||
nonce: _isc.ByteDataJsonExtension.fromJson(jsonSerialization['nonce']),
|
||||
cipherText: _isc.ByteDataJsonExtension.fromJson(
|
||||
jsonSerialization['cipherText'],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// XChaCha20-Poly1305's nonce (24 bytes).
|
||||
_idt.ByteData nonce;
|
||||
|
||||
/// The sealed keys with their tag.
|
||||
_idt.ByteData cipherText;
|
||||
|
||||
/// Returns a shallow copy of this [WrappedKeys]
|
||||
/// with some or all fields replaced by the given arguments.
|
||||
@_isc.useResult
|
||||
WrappedKeys copyWith({
|
||||
_idt.ByteData? nonce,
|
||||
_idt.ByteData? cipherText,
|
||||
});
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'__className__': 'halkyon_base.WrappedKeys',
|
||||
'nonce': nonce.toJson(),
|
||||
'cipherText': cipherText.toJson(),
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJsonForProtocol() {
|
||||
return {
|
||||
'__className__': 'halkyon_base.WrappedKeys',
|
||||
'nonce': nonce.toJson(),
|
||||
'cipherText': cipherText.toJson(),
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return _isc.SerializationManager.encode(this);
|
||||
}
|
||||
}
|
||||
|
||||
class _WrappedKeysImpl extends WrappedKeys {
|
||||
_WrappedKeysImpl({
|
||||
required _idt.ByteData nonce,
|
||||
required _idt.ByteData cipherText,
|
||||
}) : super._(
|
||||
nonce: nonce,
|
||||
cipherText: cipherText,
|
||||
);
|
||||
|
||||
/// Returns a shallow copy of this [WrappedKeys]
|
||||
/// with some or all fields replaced by the given arguments.
|
||||
@_isc.useResult
|
||||
@override
|
||||
WrappedKeys copyWith({
|
||||
_idt.ByteData? nonce,
|
||||
_idt.ByteData? cipherText,
|
||||
}) {
|
||||
return WrappedKeys(
|
||||
nonce: nonce ?? this.nonce.clone(),
|
||||
cipherText: cipherText ?? this.cipherText.clone(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -11,6 +11,8 @@
|
|||
// ignore_for_file: dead_code, unnecessary_type_check
|
||||
|
||||
// ignore_for_file: no_leading_underscores_for_library_prefixes
|
||||
import 'package:halkyon_base_client/src/protocol/password/authenticator.dart'
|
||||
as _ivfmflch;
|
||||
import 'package:serverpod_auth_core_client/serverpod_auth_core_client.dart'
|
||||
as _iacc;
|
||||
import 'package:serverpod_auth_idp_client/serverpod_auth_idp_client.dart'
|
||||
|
|
@ -23,6 +25,20 @@ import 'auth/github_sign_in_refusal.dart' as _ir1gd9p5;
|
|||
import 'auth/github_sign_in_refused_exception.dart' as _i0xfcu5n;
|
||||
import 'auth/sign_in_ways.dart' as _ie6tbh85;
|
||||
import 'instance/instance_basics.dart' as _i8jixqx6;
|
||||
import 'password/account_reset_kind.dart' as _i91ka1it;
|
||||
import 'password/authenticator.dart' as _icpzuvvi;
|
||||
import 'password/authenticator_enrolment.dart' as _iv7tra7v;
|
||||
import 'password/key_proof_challenge.dart' as _iehtx95q;
|
||||
import 'password/new_password.dart' as _itvvd6m6;
|
||||
import 'password/password_challenge.dart' as _iuxisac7;
|
||||
import 'password/password_costs.dart' as _izp492e5;
|
||||
import 'password/password_refusal.dart' as _ibfrwdhm;
|
||||
import 'password/password_refused_exception.dart' as _i4froq5y;
|
||||
import 'password/password_setup.dart' as _igpggy1y;
|
||||
import 'password/password_signed_in.dart' as _ipk7gvzy;
|
||||
import 'password/reset_pending.dart' as _i3y6qzi3;
|
||||
import 'password/sign_in_challenge_purpose.dart' as _izijxzng;
|
||||
import 'password/wrapped_keys.dart' as _i6v10ugm;
|
||||
import 'profile/profile.dart' as _ia5j8fch;
|
||||
import 'profile/profile_not_found_exception.dart' as _iim3hfcf;
|
||||
import 'profile/profile_refusal.dart' as _i6j6efd1;
|
||||
|
|
@ -34,6 +50,20 @@ export 'auth/github_sign_in_refusal.dart';
|
|||
export 'auth/github_sign_in_refused_exception.dart';
|
||||
export 'auth/sign_in_ways.dart';
|
||||
export 'instance/instance_basics.dart';
|
||||
export 'password/account_reset_kind.dart';
|
||||
export 'password/authenticator.dart';
|
||||
export 'password/authenticator_enrolment.dart';
|
||||
export 'password/key_proof_challenge.dart';
|
||||
export 'password/new_password.dart';
|
||||
export 'password/password_challenge.dart';
|
||||
export 'password/password_costs.dart';
|
||||
export 'password/password_refusal.dart';
|
||||
export 'password/password_refused_exception.dart';
|
||||
export 'password/password_setup.dart';
|
||||
export 'password/password_signed_in.dart';
|
||||
export 'password/reset_pending.dart';
|
||||
export 'password/sign_in_challenge_purpose.dart';
|
||||
export 'password/wrapped_keys.dart';
|
||||
export 'profile/profile.dart';
|
||||
export 'profile/profile_not_found_exception.dart';
|
||||
export 'profile/profile_refusal.dart';
|
||||
|
|
@ -106,6 +136,48 @@ class Protocol extends _isc.SerializationManager {
|
|||
if (t == _i8jixqx6.InstanceBasics) {
|
||||
return _i8jixqx6.InstanceBasics.fromJson(data) as T;
|
||||
}
|
||||
if (t == _i91ka1it.AccountResetKind) {
|
||||
return _i91ka1it.AccountResetKind.fromJson(data) as T;
|
||||
}
|
||||
if (t == _icpzuvvi.Authenticator) {
|
||||
return _icpzuvvi.Authenticator.fromJson(data) as T;
|
||||
}
|
||||
if (t == _iv7tra7v.AuthenticatorEnrolment) {
|
||||
return _iv7tra7v.AuthenticatorEnrolment.fromJson(data) as T;
|
||||
}
|
||||
if (t == _iehtx95q.KeyProofChallenge) {
|
||||
return _iehtx95q.KeyProofChallenge.fromJson(data) as T;
|
||||
}
|
||||
if (t == _itvvd6m6.NewPassword) {
|
||||
return _itvvd6m6.NewPassword.fromJson(data) as T;
|
||||
}
|
||||
if (t == _iuxisac7.PasswordChallenge) {
|
||||
return _iuxisac7.PasswordChallenge.fromJson(data) as T;
|
||||
}
|
||||
if (t == _izp492e5.PasswordCosts) {
|
||||
return _izp492e5.PasswordCosts.fromJson(data) as T;
|
||||
}
|
||||
if (t == _ibfrwdhm.PasswordRefusal) {
|
||||
return _ibfrwdhm.PasswordRefusal.fromJson(data) as T;
|
||||
}
|
||||
if (t == _i4froq5y.PasswordRefusedException) {
|
||||
return _i4froq5y.PasswordRefusedException.fromJson(data) as T;
|
||||
}
|
||||
if (t == _igpggy1y.PasswordSetup) {
|
||||
return _igpggy1y.PasswordSetup.fromJson(data) as T;
|
||||
}
|
||||
if (t == _ipk7gvzy.PasswordSignedIn) {
|
||||
return _ipk7gvzy.PasswordSignedIn.fromJson(data) as T;
|
||||
}
|
||||
if (t == _i3y6qzi3.ResetPending) {
|
||||
return _i3y6qzi3.ResetPending.fromJson(data) as T;
|
||||
}
|
||||
if (t == _izijxzng.SignInChallengePurpose) {
|
||||
return _izijxzng.SignInChallengePurpose.fromJson(data) as T;
|
||||
}
|
||||
if (t == _i6v10ugm.WrappedKeys) {
|
||||
return _i6v10ugm.WrappedKeys.fromJson(data) as T;
|
||||
}
|
||||
if (t == _ia5j8fch.Profile) {
|
||||
return _ia5j8fch.Profile.fromJson(data) as T;
|
||||
}
|
||||
|
|
@ -151,6 +223,65 @@ class Protocol extends _isc.SerializationManager {
|
|||
return (data != null ? _i8jixqx6.InstanceBasics.fromJson(data) : null)
|
||||
as T;
|
||||
}
|
||||
if (t == _isc.getType<_i91ka1it.AccountResetKind?>()) {
|
||||
return (data != null ? _i91ka1it.AccountResetKind.fromJson(data) : null)
|
||||
as T;
|
||||
}
|
||||
if (t == _isc.getType<_icpzuvvi.Authenticator?>()) {
|
||||
return (data != null ? _icpzuvvi.Authenticator.fromJson(data) : null)
|
||||
as T;
|
||||
}
|
||||
if (t == _isc.getType<_iv7tra7v.AuthenticatorEnrolment?>()) {
|
||||
return (data != null
|
||||
? _iv7tra7v.AuthenticatorEnrolment.fromJson(data)
|
||||
: null)
|
||||
as T;
|
||||
}
|
||||
if (t == _isc.getType<_iehtx95q.KeyProofChallenge?>()) {
|
||||
return (data != null ? _iehtx95q.KeyProofChallenge.fromJson(data) : null)
|
||||
as T;
|
||||
}
|
||||
if (t == _isc.getType<_itvvd6m6.NewPassword?>()) {
|
||||
return (data != null ? _itvvd6m6.NewPassword.fromJson(data) : null) as T;
|
||||
}
|
||||
if (t == _isc.getType<_iuxisac7.PasswordChallenge?>()) {
|
||||
return (data != null ? _iuxisac7.PasswordChallenge.fromJson(data) : null)
|
||||
as T;
|
||||
}
|
||||
if (t == _isc.getType<_izp492e5.PasswordCosts?>()) {
|
||||
return (data != null ? _izp492e5.PasswordCosts.fromJson(data) : null)
|
||||
as T;
|
||||
}
|
||||
if (t == _isc.getType<_ibfrwdhm.PasswordRefusal?>()) {
|
||||
return (data != null ? _ibfrwdhm.PasswordRefusal.fromJson(data) : null)
|
||||
as T;
|
||||
}
|
||||
if (t == _isc.getType<_i4froq5y.PasswordRefusedException?>()) {
|
||||
return (data != null
|
||||
? _i4froq5y.PasswordRefusedException.fromJson(data)
|
||||
: null)
|
||||
as T;
|
||||
}
|
||||
if (t == _isc.getType<_igpggy1y.PasswordSetup?>()) {
|
||||
return (data != null ? _igpggy1y.PasswordSetup.fromJson(data) : null)
|
||||
as T;
|
||||
}
|
||||
if (t == _isc.getType<_ipk7gvzy.PasswordSignedIn?>()) {
|
||||
return (data != null ? _ipk7gvzy.PasswordSignedIn.fromJson(data) : null)
|
||||
as T;
|
||||
}
|
||||
if (t == _isc.getType<_i3y6qzi3.ResetPending?>()) {
|
||||
return (data != null ? _i3y6qzi3.ResetPending.fromJson(data) : null) as T;
|
||||
}
|
||||
if (t == _isc.getType<_izijxzng.SignInChallengePurpose?>()) {
|
||||
return (data != null
|
||||
? _izijxzng.SignInChallengePurpose.fromJson(data)
|
||||
: null)
|
||||
as T;
|
||||
}
|
||||
if (t == _isc.getType<_i6v10ugm.WrappedKeys?>()) {
|
||||
return (data != null ? _i6v10ugm.WrappedKeys.fromJson(data) : null) as T;
|
||||
}
|
||||
if (t == _isc.getType<_ia5j8fch.Profile?>()) {
|
||||
return (data != null ? _ia5j8fch.Profile.fromJson(data) : null) as T;
|
||||
}
|
||||
|
|
@ -170,6 +301,9 @@ class Protocol extends _isc.SerializationManager {
|
|||
: null)
|
||||
as T;
|
||||
}
|
||||
if (t == Set<String>) {
|
||||
return (data as List).map((e) => deserialize<String>(e)).toSet() as T;
|
||||
}
|
||||
if (t == List<String>) {
|
||||
return (data as List).map((e) => deserialize<String>(e)).toList() as T;
|
||||
}
|
||||
|
|
@ -182,6 +316,12 @@ class Protocol extends _isc.SerializationManager {
|
|||
if (t == List<String>) {
|
||||
return (data as List).map((e) => deserialize<String>(e)).toList() as T;
|
||||
}
|
||||
if (t == List<_ivfmflch.Authenticator>) {
|
||||
return (data as List)
|
||||
.map((e) => deserialize<_ivfmflch.Authenticator>(e))
|
||||
.toList()
|
||||
as T;
|
||||
}
|
||||
try {
|
||||
return _iaic.Protocol().deserialize<T>(data, t);
|
||||
} on _isc.DeserializationTypeNotFoundException catch (_) {}
|
||||
|
|
@ -200,6 +340,20 @@ class Protocol extends _isc.SerializationManager {
|
|||
_i0xfcu5n.GitHubSignInRefusedException => 'GitHubSignInRefusedException',
|
||||
_ie6tbh85.SignInWays => 'SignInWays',
|
||||
_i8jixqx6.InstanceBasics => 'InstanceBasics',
|
||||
_i91ka1it.AccountResetKind => 'AccountResetKind',
|
||||
_icpzuvvi.Authenticator => 'Authenticator',
|
||||
_iv7tra7v.AuthenticatorEnrolment => 'AuthenticatorEnrolment',
|
||||
_iehtx95q.KeyProofChallenge => 'KeyProofChallenge',
|
||||
_itvvd6m6.NewPassword => 'NewPassword',
|
||||
_iuxisac7.PasswordChallenge => 'PasswordChallenge',
|
||||
_izp492e5.PasswordCosts => 'PasswordCosts',
|
||||
_ibfrwdhm.PasswordRefusal => 'PasswordRefusal',
|
||||
_i4froq5y.PasswordRefusedException => 'PasswordRefusedException',
|
||||
_igpggy1y.PasswordSetup => 'PasswordSetup',
|
||||
_ipk7gvzy.PasswordSignedIn => 'PasswordSignedIn',
|
||||
_i3y6qzi3.ResetPending => 'ResetPending',
|
||||
_izijxzng.SignInChallengePurpose => 'SignInChallengePurpose',
|
||||
_i6v10ugm.WrappedKeys => 'WrappedKeys',
|
||||
_ia5j8fch.Profile => 'Profile',
|
||||
_iim3hfcf.ProfileNotFoundException => 'ProfileNotFoundException',
|
||||
_i6j6efd1.ProfileRefusal => 'ProfileRefusal',
|
||||
|
|
@ -235,6 +389,34 @@ class Protocol extends _isc.SerializationManager {
|
|||
return 'SignInWays';
|
||||
case _i8jixqx6.InstanceBasics():
|
||||
return 'InstanceBasics';
|
||||
case _i91ka1it.AccountResetKind():
|
||||
return 'AccountResetKind';
|
||||
case _icpzuvvi.Authenticator():
|
||||
return 'Authenticator';
|
||||
case _iv7tra7v.AuthenticatorEnrolment():
|
||||
return 'AuthenticatorEnrolment';
|
||||
case _iehtx95q.KeyProofChallenge():
|
||||
return 'KeyProofChallenge';
|
||||
case _itvvd6m6.NewPassword():
|
||||
return 'NewPassword';
|
||||
case _iuxisac7.PasswordChallenge():
|
||||
return 'PasswordChallenge';
|
||||
case _izp492e5.PasswordCosts():
|
||||
return 'PasswordCosts';
|
||||
case _ibfrwdhm.PasswordRefusal():
|
||||
return 'PasswordRefusal';
|
||||
case _i4froq5y.PasswordRefusedException():
|
||||
return 'PasswordRefusedException';
|
||||
case _igpggy1y.PasswordSetup():
|
||||
return 'PasswordSetup';
|
||||
case _ipk7gvzy.PasswordSignedIn():
|
||||
return 'PasswordSignedIn';
|
||||
case _i3y6qzi3.ResetPending():
|
||||
return 'ResetPending';
|
||||
case _izijxzng.SignInChallengePurpose():
|
||||
return 'SignInChallengePurpose';
|
||||
case _i6v10ugm.WrappedKeys():
|
||||
return 'WrappedKeys';
|
||||
case _ia5j8fch.Profile():
|
||||
return 'Profile';
|
||||
case _iim3hfcf.ProfileNotFoundException():
|
||||
|
|
@ -274,6 +456,48 @@ class Protocol extends _isc.SerializationManager {
|
|||
if (dataClassName == 'InstanceBasics') {
|
||||
return deserialize<_i8jixqx6.InstanceBasics>(data['data']);
|
||||
}
|
||||
if (dataClassName == 'AccountResetKind') {
|
||||
return deserialize<_i91ka1it.AccountResetKind>(data['data']);
|
||||
}
|
||||
if (dataClassName == 'Authenticator') {
|
||||
return deserialize<_icpzuvvi.Authenticator>(data['data']);
|
||||
}
|
||||
if (dataClassName == 'AuthenticatorEnrolment') {
|
||||
return deserialize<_iv7tra7v.AuthenticatorEnrolment>(data['data']);
|
||||
}
|
||||
if (dataClassName == 'KeyProofChallenge') {
|
||||
return deserialize<_iehtx95q.KeyProofChallenge>(data['data']);
|
||||
}
|
||||
if (dataClassName == 'NewPassword') {
|
||||
return deserialize<_itvvd6m6.NewPassword>(data['data']);
|
||||
}
|
||||
if (dataClassName == 'PasswordChallenge') {
|
||||
return deserialize<_iuxisac7.PasswordChallenge>(data['data']);
|
||||
}
|
||||
if (dataClassName == 'PasswordCosts') {
|
||||
return deserialize<_izp492e5.PasswordCosts>(data['data']);
|
||||
}
|
||||
if (dataClassName == 'PasswordRefusal') {
|
||||
return deserialize<_ibfrwdhm.PasswordRefusal>(data['data']);
|
||||
}
|
||||
if (dataClassName == 'PasswordRefusedException') {
|
||||
return deserialize<_i4froq5y.PasswordRefusedException>(data['data']);
|
||||
}
|
||||
if (dataClassName == 'PasswordSetup') {
|
||||
return deserialize<_igpggy1y.PasswordSetup>(data['data']);
|
||||
}
|
||||
if (dataClassName == 'PasswordSignedIn') {
|
||||
return deserialize<_ipk7gvzy.PasswordSignedIn>(data['data']);
|
||||
}
|
||||
if (dataClassName == 'ResetPending') {
|
||||
return deserialize<_i3y6qzi3.ResetPending>(data['data']);
|
||||
}
|
||||
if (dataClassName == 'SignInChallengePurpose') {
|
||||
return deserialize<_izijxzng.SignInChallengePurpose>(data['data']);
|
||||
}
|
||||
if (dataClassName == 'WrappedKeys') {
|
||||
return deserialize<_i6v10ugm.WrappedKeys>(data['data']);
|
||||
}
|
||||
if (dataClassName == 'Profile') {
|
||||
return deserialize<_ia5j8fch.Profile>(data['data']);
|
||||
}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue