feat(auth): a session ended for its wrong proofs warns its owner
The tenth wrong owner proof in a row ends a session (the third reading); someone holding that session tried the password or its codes. The register now keeps the moment with the account's password (`account_password.sessionEndedForProofsAt`): the account's sign-in ways and its next password sign-in carry it, until the owner dismisses it (`password.dismissSessionEndedWarning`, their session alone: it hides a warning and secures nothing) or sets a new password. A member ending its own session tells the register (`noteSessionEndedForProofs`); a register out of reach leaves the owner unwarned, the session ended all the same. Migration (module, Learn's and Todo's servers, Learn's device schema): ALTER TABLE "account_password" ADD COLUMN "sessionEndedForProofsAt" timestamp without time zone; nullable, so every row keeps its values and has no warning. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
parent
858fffdce3
commit
5e7d7f4e36
50 changed files with 41919 additions and 34 deletions
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,33 @@
|
||||||
|
{
|
||||||
|
"__className__": "serverpod.DatabaseMigration",
|
||||||
|
"actions": [
|
||||||
|
{
|
||||||
|
"__className__": "serverpod.DatabaseMigrationAction",
|
||||||
|
"type": "alterTable",
|
||||||
|
"alterTable": {
|
||||||
|
"__className__": "serverpod.TableMigration",
|
||||||
|
"name": "account_password",
|
||||||
|
"schema": "public",
|
||||||
|
"addColumns": [
|
||||||
|
{
|
||||||
|
"__className__": "serverpod.ColumnDefinition",
|
||||||
|
"name": "sessionEndedForProofsAt",
|
||||||
|
"fieldName": "sessionEndedForProofsAt",
|
||||||
|
"columnType": 4,
|
||||||
|
"isNullable": true,
|
||||||
|
"dartType": "DateTime?"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"deleteColumns": [],
|
||||||
|
"modifyColumns": [],
|
||||||
|
"addIndexes": [],
|
||||||
|
"deleteIndexes": [],
|
||||||
|
"addForeignKeys": [],
|
||||||
|
"deleteForeignKeys": [],
|
||||||
|
"warnings": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"warnings": [],
|
||||||
|
"migrationApiVersion": 1
|
||||||
|
}
|
||||||
|
|
@ -24,6 +24,7 @@ part '20261020185750538-recovery-proof-key/migration.dart';
|
||||||
part '20261020194228286-second-factor-waits/migration.dart';
|
part '20261020194228286-second-factor-waits/migration.dart';
|
||||||
part '20261020204619104-session-code-tries/migration.dart';
|
part '20261020204619104-session-code-tries/migration.dart';
|
||||||
part '20261020211224692-email-code-purpose/migration.dart';
|
part '20261020211224692-email-code-purpose/migration.dart';
|
||||||
|
part '20261021100422048-session-ended-warning/migration.dart';
|
||||||
|
|
||||||
/// Migration registry for the client-side database.
|
/// Migration registry for the client-side database.
|
||||||
class MigrationRegistry {
|
class MigrationRegistry {
|
||||||
|
|
@ -50,6 +51,7 @@ class MigrationRegistry {
|
||||||
_Migration20261020194228286_second_factor_waits(),
|
_Migration20261020194228286_second_factor_waits(),
|
||||||
_Migration20261020204619104_session_code_tries(),
|
_Migration20261020204619104_session_code_tries(),
|
||||||
_Migration20261020211224692_email_code_purpose(),
|
_Migration20261020211224692_email_code_purpose(),
|
||||||
|
_Migration20261021100422048_session_ended_warning(),
|
||||||
];
|
];
|
||||||
|
|
||||||
/// List of all client-side database migration versions.
|
/// List of all client-side database migration versions.
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,33 @@
|
||||||
|
{
|
||||||
|
"__className__": "serverpod.DatabaseMigration",
|
||||||
|
"actions": [
|
||||||
|
{
|
||||||
|
"__className__": "serverpod.DatabaseMigrationAction",
|
||||||
|
"type": "alterTable",
|
||||||
|
"alterTable": {
|
||||||
|
"__className__": "serverpod.TableMigration",
|
||||||
|
"name": "account_password",
|
||||||
|
"schema": "public",
|
||||||
|
"addColumns": [
|
||||||
|
{
|
||||||
|
"__className__": "serverpod.ColumnDefinition",
|
||||||
|
"name": "sessionEndedForProofsAt",
|
||||||
|
"fieldName": "sessionEndedForProofsAt",
|
||||||
|
"columnType": 4,
|
||||||
|
"isNullable": true,
|
||||||
|
"dartType": "DateTime?"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"deleteColumns": [],
|
||||||
|
"modifyColumns": [],
|
||||||
|
"addIndexes": [],
|
||||||
|
"deleteIndexes": [],
|
||||||
|
"addForeignKeys": [],
|
||||||
|
"deleteForeignKeys": [],
|
||||||
|
"warnings": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"warnings": [],
|
||||||
|
"migrationApiVersion": 1
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,57 @@
|
||||||
|
BEGIN;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- ACTION ALTER TABLE
|
||||||
|
--
|
||||||
|
ALTER TABLE "account_password" ADD COLUMN "sessionEndedForProofsAt" timestamp without time zone;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- MIGRATION VERSION FOR halkyon_learn
|
||||||
|
--
|
||||||
|
INSERT INTO "serverpod_migrations" ("module", "version", "timestamp")
|
||||||
|
VALUES ('halkyon_learn', '20261021100422048-session-ended-warning', now())
|
||||||
|
ON CONFLICT ("module")
|
||||||
|
DO UPDATE SET "version" = '20261021100422048-session-ended-warning', "timestamp" = now();
|
||||||
|
|
||||||
|
--
|
||||||
|
-- MIGRATION VERSION FOR halkyon_base
|
||||||
|
--
|
||||||
|
INSERT INTO "serverpod_migrations" ("module", "version", "timestamp")
|
||||||
|
VALUES ('halkyon_base', '20261021100319502-session-ended-warning', now())
|
||||||
|
ON CONFLICT ("module")
|
||||||
|
DO UPDATE SET "version" = '20261021100319502-session-ended-warning', "timestamp" = now();
|
||||||
|
|
||||||
|
--
|
||||||
|
-- MIGRATION VERSION FOR serverpod
|
||||||
|
--
|
||||||
|
INSERT INTO "serverpod_migrations" ("module", "version", "timestamp")
|
||||||
|
VALUES ('serverpod', '20260824182259319', now())
|
||||||
|
ON CONFLICT ("module")
|
||||||
|
DO UPDATE SET "version" = '20260824182259319', "timestamp" = now();
|
||||||
|
|
||||||
|
--
|
||||||
|
-- MIGRATION VERSION FOR serverpod_auth_idp
|
||||||
|
--
|
||||||
|
INSERT INTO "serverpod_migrations" ("module", "version", "timestamp")
|
||||||
|
VALUES ('serverpod_auth_idp', '20260924105404509', now())
|
||||||
|
ON CONFLICT ("module")
|
||||||
|
DO UPDATE SET "version" = '20260924105404509', "timestamp" = now();
|
||||||
|
|
||||||
|
--
|
||||||
|
-- MIGRATION VERSION FOR serverpod_offline_sync
|
||||||
|
--
|
||||||
|
INSERT INTO "serverpod_migrations" ("module", "version", "timestamp")
|
||||||
|
VALUES ('serverpod_offline_sync', '20260914143806119', now())
|
||||||
|
ON CONFLICT ("module")
|
||||||
|
DO UPDATE SET "version" = '20260914143806119', "timestamp" = now();
|
||||||
|
|
||||||
|
--
|
||||||
|
-- MIGRATION VERSION FOR serverpod_auth_core
|
||||||
|
--
|
||||||
|
INSERT INTO "serverpod_migrations" ("module", "version", "timestamp")
|
||||||
|
VALUES ('serverpod_auth_core', '20260924105232991', now())
|
||||||
|
ON CONFLICT ("module")
|
||||||
|
DO UPDATE SET "version" = '20260924105232991', "timestamp" = now();
|
||||||
|
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
|
|
@ -41,3 +41,4 @@
|
||||||
20261020194228286-second-factor-waits
|
20261020194228286-second-factor-waits
|
||||||
20261020204619104-session-code-tries
|
20261020204619104-session-code-tries
|
||||||
20261020211224692-email-code-purpose
|
20261020211224692-email-code-purpose
|
||||||
|
20261021100422048-session-ended-warning
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,29 @@
|
||||||
|
{
|
||||||
|
"__className__": "serverpod.DatabaseDefinition",
|
||||||
|
"schemaVersion": 2,
|
||||||
|
"moduleName": "halkyon_todo",
|
||||||
|
"tables": [],
|
||||||
|
"installedModules": [
|
||||||
|
{
|
||||||
|
"__className__": "serverpod.DatabaseMigrationVersion",
|
||||||
|
"module": "halkyon_base",
|
||||||
|
"version": "20261021100319502-session-ended-warning"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"__className__": "serverpod.DatabaseMigrationVersion",
|
||||||
|
"module": "serverpod",
|
||||||
|
"version": "20260824182259319"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"__className__": "serverpod.DatabaseMigrationVersion",
|
||||||
|
"module": "serverpod_auth_idp",
|
||||||
|
"version": "20260924105404509"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"__className__": "serverpod.DatabaseMigrationVersion",
|
||||||
|
"module": "serverpod_auth_core",
|
||||||
|
"version": "20260924105232991"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"migrationApiVersion": 1
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
{
|
||||||
|
"__className__": "serverpod.DatabaseMigration",
|
||||||
|
"actions": [
|
||||||
|
{
|
||||||
|
"__className__": "serverpod.DatabaseMigrationAction",
|
||||||
|
"type": "alterTable",
|
||||||
|
"alterTable": {
|
||||||
|
"__className__": "serverpod.TableMigration",
|
||||||
|
"name": "account_password",
|
||||||
|
"schema": "public",
|
||||||
|
"addColumns": [
|
||||||
|
{
|
||||||
|
"__className__": "serverpod.ColumnDefinition",
|
||||||
|
"name": "sessionEndedForProofsAt",
|
||||||
|
"fieldName": "sessionEndedForProofsAt",
|
||||||
|
"columnType": 4,
|
||||||
|
"isNullable": true,
|
||||||
|
"dartType": "DateTime?"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"deleteColumns": [],
|
||||||
|
"modifyColumns": [],
|
||||||
|
"addIndexes": [],
|
||||||
|
"deleteIndexes": [],
|
||||||
|
"addForeignKeys": [],
|
||||||
|
"deleteForeignKeys": [],
|
||||||
|
"warnings": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"warnings": [],
|
||||||
|
"migrationApiVersion": 1
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
BEGIN;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- ACTION ALTER TABLE
|
||||||
|
--
|
||||||
|
ALTER TABLE "account_password" ADD COLUMN "sessionEndedForProofsAt" timestamp without time zone;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- MIGRATION VERSION FOR halkyon_todo
|
||||||
|
--
|
||||||
|
INSERT INTO "serverpod_migrations" ("module", "version", "timestamp")
|
||||||
|
VALUES ('halkyon_todo', '20261021100422779-session-ended-warning', now())
|
||||||
|
ON CONFLICT ("module")
|
||||||
|
DO UPDATE SET "version" = '20261021100422779-session-ended-warning', "timestamp" = now();
|
||||||
|
|
||||||
|
--
|
||||||
|
-- MIGRATION VERSION FOR halkyon_base
|
||||||
|
--
|
||||||
|
INSERT INTO "serverpod_migrations" ("module", "version", "timestamp")
|
||||||
|
VALUES ('halkyon_base', '20261021100319502-session-ended-warning', now())
|
||||||
|
ON CONFLICT ("module")
|
||||||
|
DO UPDATE SET "version" = '20261021100319502-session-ended-warning', "timestamp" = now();
|
||||||
|
|
||||||
|
--
|
||||||
|
-- MIGRATION VERSION FOR serverpod
|
||||||
|
--
|
||||||
|
INSERT INTO "serverpod_migrations" ("module", "version", "timestamp")
|
||||||
|
VALUES ('serverpod', '20260824182259319', now())
|
||||||
|
ON CONFLICT ("module")
|
||||||
|
DO UPDATE SET "version" = '20260824182259319', "timestamp" = now();
|
||||||
|
|
||||||
|
--
|
||||||
|
-- MIGRATION VERSION FOR serverpod_auth_idp
|
||||||
|
--
|
||||||
|
INSERT INTO "serverpod_migrations" ("module", "version", "timestamp")
|
||||||
|
VALUES ('serverpod_auth_idp', '20260924105404509', now())
|
||||||
|
ON CONFLICT ("module")
|
||||||
|
DO UPDATE SET "version" = '20260924105404509', "timestamp" = now();
|
||||||
|
|
||||||
|
--
|
||||||
|
-- MIGRATION VERSION FOR serverpod_auth_core
|
||||||
|
--
|
||||||
|
INSERT INTO "serverpod_migrations" ("module", "version", "timestamp")
|
||||||
|
VALUES ('serverpod_auth_core', '20260924105232991', now())
|
||||||
|
ON CONFLICT ("module")
|
||||||
|
DO UPDATE SET "version" = '20260924105232991', "timestamp" = now();
|
||||||
|
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
|
|
@ -13,3 +13,4 @@
|
||||||
20261020194229631-second-factor-waits
|
20261020194229631-second-factor-waits
|
||||||
20261020204619863-session-code-tries
|
20261020204619863-session-code-tries
|
||||||
20261020211225101-email-code-purpose
|
20261020211225101-email-code-purpose
|
||||||
|
20261021100422779-session-ended-warning
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ abstract class SignInWays
|
||||||
bool? authenticator,
|
bool? authenticator,
|
||||||
bool? passwordOnly,
|
bool? passwordOnly,
|
||||||
bool? secondFactorWorks,
|
bool? secondFactorWorks,
|
||||||
|
this.sessionEndedForProofsAt,
|
||||||
}) : password = password ?? false,
|
}) : password = password ?? false,
|
||||||
authenticator = authenticator ?? false,
|
authenticator = authenticator ?? false,
|
||||||
passwordOnly = passwordOnly ?? false,
|
passwordOnly = passwordOnly ?? false,
|
||||||
|
|
@ -34,6 +35,7 @@ abstract class SignInWays
|
||||||
bool? authenticator,
|
bool? authenticator,
|
||||||
bool? passwordOnly,
|
bool? passwordOnly,
|
||||||
bool? secondFactorWorks,
|
bool? secondFactorWorks,
|
||||||
|
DateTime? sessionEndedForProofsAt,
|
||||||
}) = _SignInWaysImpl;
|
}) = _SignInWaysImpl;
|
||||||
|
|
||||||
factory SignInWays.fromJson(Map<String, dynamic> jsonSerialization) {
|
factory SignInWays.fromJson(Map<String, dynamic> jsonSerialization) {
|
||||||
|
|
@ -54,6 +56,12 @@ abstract class SignInWays
|
||||||
: _isc.BoolJsonExtension.fromJson(
|
: _isc.BoolJsonExtension.fromJson(
|
||||||
jsonSerialization['secondFactorWorks'],
|
jsonSerialization['secondFactorWorks'],
|
||||||
),
|
),
|
||||||
|
sessionEndedForProofsAt:
|
||||||
|
jsonSerialization['sessionEndedForProofsAt'] == null
|
||||||
|
? null
|
||||||
|
: _isc.DateTimeJsonExtension.fromJson(
|
||||||
|
jsonSerialization['sessionEndedForProofsAt'],
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -77,6 +85,11 @@ abstract class SignInWays
|
||||||
/// takes a code by mail in place of a TOTP or recovery code.
|
/// takes a code by mail in place of a TOTP or recovery code.
|
||||||
bool secondFactorWorks;
|
bool secondFactorWorks;
|
||||||
|
|
||||||
|
/// When a session of the account was last ended for ten wrong proofs in
|
||||||
|
/// a row, the owner's warning until they dismiss it or set a new
|
||||||
|
/// password (ADR 0017, the fourth reading); null for none.
|
||||||
|
DateTime? sessionEndedForProofsAt;
|
||||||
|
|
||||||
/// Returns a shallow copy of this [SignInWays]
|
/// Returns a shallow copy of this [SignInWays]
|
||||||
/// with some or all fields replaced by the given arguments.
|
/// with some or all fields replaced by the given arguments.
|
||||||
@_isc.useResult
|
@_isc.useResult
|
||||||
|
|
@ -87,6 +100,7 @@ abstract class SignInWays
|
||||||
bool? authenticator,
|
bool? authenticator,
|
||||||
bool? passwordOnly,
|
bool? passwordOnly,
|
||||||
bool? secondFactorWorks,
|
bool? secondFactorWorks,
|
||||||
|
DateTime? sessionEndedForProofsAt,
|
||||||
});
|
});
|
||||||
@override
|
@override
|
||||||
Map<String, dynamic> toJson() {
|
Map<String, dynamic> toJson() {
|
||||||
|
|
@ -98,6 +112,8 @@ abstract class SignInWays
|
||||||
'authenticator': authenticator,
|
'authenticator': authenticator,
|
||||||
'passwordOnly': passwordOnly,
|
'passwordOnly': passwordOnly,
|
||||||
'secondFactorWorks': secondFactorWorks,
|
'secondFactorWorks': secondFactorWorks,
|
||||||
|
if (sessionEndedForProofsAt != null)
|
||||||
|
'sessionEndedForProofsAt': sessionEndedForProofsAt?.toJson(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -111,6 +127,8 @@ abstract class SignInWays
|
||||||
'authenticator': authenticator,
|
'authenticator': authenticator,
|
||||||
'passwordOnly': passwordOnly,
|
'passwordOnly': passwordOnly,
|
||||||
'secondFactorWorks': secondFactorWorks,
|
'secondFactorWorks': secondFactorWorks,
|
||||||
|
if (sessionEndedForProofsAt != null)
|
||||||
|
'sessionEndedForProofsAt': sessionEndedForProofsAt?.toJson(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -120,6 +138,8 @@ abstract class SignInWays
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class _Undefined {}
|
||||||
|
|
||||||
class _SignInWaysImpl extends SignInWays {
|
class _SignInWaysImpl extends SignInWays {
|
||||||
_SignInWaysImpl({
|
_SignInWaysImpl({
|
||||||
required bool gitHub,
|
required bool gitHub,
|
||||||
|
|
@ -128,6 +148,7 @@ class _SignInWaysImpl extends SignInWays {
|
||||||
bool? authenticator,
|
bool? authenticator,
|
||||||
bool? passwordOnly,
|
bool? passwordOnly,
|
||||||
bool? secondFactorWorks,
|
bool? secondFactorWorks,
|
||||||
|
DateTime? sessionEndedForProofsAt,
|
||||||
}) : super._(
|
}) : super._(
|
||||||
gitHub: gitHub,
|
gitHub: gitHub,
|
||||||
email: email,
|
email: email,
|
||||||
|
|
@ -135,6 +156,7 @@ class _SignInWaysImpl extends SignInWays {
|
||||||
authenticator: authenticator,
|
authenticator: authenticator,
|
||||||
passwordOnly: passwordOnly,
|
passwordOnly: passwordOnly,
|
||||||
secondFactorWorks: secondFactorWorks,
|
secondFactorWorks: secondFactorWorks,
|
||||||
|
sessionEndedForProofsAt: sessionEndedForProofsAt,
|
||||||
);
|
);
|
||||||
|
|
||||||
/// Returns a shallow copy of this [SignInWays]
|
/// Returns a shallow copy of this [SignInWays]
|
||||||
|
|
@ -148,6 +170,7 @@ class _SignInWaysImpl extends SignInWays {
|
||||||
bool? authenticator,
|
bool? authenticator,
|
||||||
bool? passwordOnly,
|
bool? passwordOnly,
|
||||||
bool? secondFactorWorks,
|
bool? secondFactorWorks,
|
||||||
|
Object? sessionEndedForProofsAt = _Undefined,
|
||||||
}) {
|
}) {
|
||||||
return SignInWays(
|
return SignInWays(
|
||||||
gitHub: gitHub ?? this.gitHub,
|
gitHub: gitHub ?? this.gitHub,
|
||||||
|
|
@ -156,6 +179,9 @@ class _SignInWaysImpl extends SignInWays {
|
||||||
authenticator: authenticator ?? this.authenticator,
|
authenticator: authenticator ?? this.authenticator,
|
||||||
passwordOnly: passwordOnly ?? this.passwordOnly,
|
passwordOnly: passwordOnly ?? this.passwordOnly,
|
||||||
secondFactorWorks: secondFactorWorks ?? this.secondFactorWorks,
|
secondFactorWorks: secondFactorWorks ?? this.secondFactorWorks,
|
||||||
|
sessionEndedForProofsAt: sessionEndedForProofsAt is DateTime?
|
||||||
|
? sessionEndedForProofsAt
|
||||||
|
: this.sessionEndedForProofsAt,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -506,6 +506,17 @@ class EndpointPassword extends _isc.EndpointRef {
|
||||||
'recoveryProofKey': recoveryProofKey,
|
'recoveryProofKey': recoveryProofKey,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/// Dismisses the caller's warning that a session of theirs was ended for
|
||||||
|
/// ten wrong proofs in a row (`account.signInWays`'
|
||||||
|
/// `sessionEndedForProofsAt`). Their session alone does: it hides a
|
||||||
|
/// warning and changes nothing about how the account is secured.
|
||||||
|
_ida.Future<void> dismissSessionEndedWarning() =>
|
||||||
|
caller.callServerEndpoint<void>(
|
||||||
|
'halkyon_base.password',
|
||||||
|
'dismissSessionEndedWarning',
|
||||||
|
{},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Signing in with an address, a password and a code from an authenticator
|
/// Signing in with an address, a password and a code from an authenticator
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ abstract class PasswordSignedIn
|
||||||
required this.signingPublicKey,
|
required this.signingPublicKey,
|
||||||
required this.passwordKeys,
|
required this.passwordKeys,
|
||||||
required this.needsAuthenticator,
|
required this.needsAuthenticator,
|
||||||
|
this.sessionEndedForProofsAt,
|
||||||
required this.authStrategy,
|
required this.authStrategy,
|
||||||
required this.token,
|
required this.token,
|
||||||
this.tokenExpiresAt,
|
this.tokenExpiresAt,
|
||||||
|
|
@ -43,6 +44,7 @@ abstract class PasswordSignedIn
|
||||||
required _idt.ByteData signingPublicKey,
|
required _idt.ByteData signingPublicKey,
|
||||||
required _i2rxumte.WrappedKeys passwordKeys,
|
required _i2rxumte.WrappedKeys passwordKeys,
|
||||||
required bool needsAuthenticator,
|
required bool needsAuthenticator,
|
||||||
|
DateTime? sessionEndedForProofsAt,
|
||||||
required String authStrategy,
|
required String authStrategy,
|
||||||
required String token,
|
required String token,
|
||||||
DateTime? tokenExpiresAt,
|
DateTime? tokenExpiresAt,
|
||||||
|
|
@ -68,6 +70,12 @@ abstract class PasswordSignedIn
|
||||||
needsAuthenticator: _isc.BoolJsonExtension.fromJson(
|
needsAuthenticator: _isc.BoolJsonExtension.fromJson(
|
||||||
jsonSerialization['needsAuthenticator'],
|
jsonSerialization['needsAuthenticator'],
|
||||||
),
|
),
|
||||||
|
sessionEndedForProofsAt:
|
||||||
|
jsonSerialization['sessionEndedForProofsAt'] == null
|
||||||
|
? null
|
||||||
|
: _isc.DateTimeJsonExtension.fromJson(
|
||||||
|
jsonSerialization['sessionEndedForProofsAt'],
|
||||||
|
),
|
||||||
authStrategy: jsonSerialization['authStrategy'] as String,
|
authStrategy: jsonSerialization['authStrategy'] as String,
|
||||||
token: jsonSerialization['token'] as String,
|
token: jsonSerialization['token'] as String,
|
||||||
tokenExpiresAt: jsonSerialization['tokenExpiresAt'] == null
|
tokenExpiresAt: jsonSerialization['tokenExpiresAt'] == null
|
||||||
|
|
@ -95,6 +103,11 @@ abstract class PasswordSignedIn
|
||||||
|
|
||||||
bool needsAuthenticator;
|
bool needsAuthenticator;
|
||||||
|
|
||||||
|
/// When a session of the account was last ended for ten wrong proofs in
|
||||||
|
/// a row (someone with a session tried the password or its codes), until
|
||||||
|
/// the owner dismisses the warning or sets a new password; null for none.
|
||||||
|
DateTime? sessionEndedForProofsAt;
|
||||||
|
|
||||||
/// The session, as Serverpod's `AuthSuccess` has it (the device makes one
|
/// The session, as Serverpod's `AuthSuccess` has it (the device makes one
|
||||||
/// of these fields for its session manager).
|
/// of these fields for its session manager).
|
||||||
String authStrategy;
|
String authStrategy;
|
||||||
|
|
@ -118,6 +131,7 @@ abstract class PasswordSignedIn
|
||||||
_idt.ByteData? signingPublicKey,
|
_idt.ByteData? signingPublicKey,
|
||||||
_i2rxumte.WrappedKeys? passwordKeys,
|
_i2rxumte.WrappedKeys? passwordKeys,
|
||||||
bool? needsAuthenticator,
|
bool? needsAuthenticator,
|
||||||
|
DateTime? sessionEndedForProofsAt,
|
||||||
String? authStrategy,
|
String? authStrategy,
|
||||||
String? token,
|
String? token,
|
||||||
DateTime? tokenExpiresAt,
|
DateTime? tokenExpiresAt,
|
||||||
|
|
@ -134,6 +148,8 @@ abstract class PasswordSignedIn
|
||||||
'signingPublicKey': signingPublicKey.toJson(),
|
'signingPublicKey': signingPublicKey.toJson(),
|
||||||
'passwordKeys': passwordKeys.toJson(),
|
'passwordKeys': passwordKeys.toJson(),
|
||||||
'needsAuthenticator': needsAuthenticator,
|
'needsAuthenticator': needsAuthenticator,
|
||||||
|
if (sessionEndedForProofsAt != null)
|
||||||
|
'sessionEndedForProofsAt': sessionEndedForProofsAt?.toJson(),
|
||||||
'authStrategy': authStrategy,
|
'authStrategy': authStrategy,
|
||||||
'token': token,
|
'token': token,
|
||||||
if (tokenExpiresAt != null) 'tokenExpiresAt': tokenExpiresAt?.toJson(),
|
if (tokenExpiresAt != null) 'tokenExpiresAt': tokenExpiresAt?.toJson(),
|
||||||
|
|
@ -152,6 +168,8 @@ abstract class PasswordSignedIn
|
||||||
'signingPublicKey': signingPublicKey.toJson(),
|
'signingPublicKey': signingPublicKey.toJson(),
|
||||||
'passwordKeys': passwordKeys.toJsonForProtocol(),
|
'passwordKeys': passwordKeys.toJsonForProtocol(),
|
||||||
'needsAuthenticator': needsAuthenticator,
|
'needsAuthenticator': needsAuthenticator,
|
||||||
|
if (sessionEndedForProofsAt != null)
|
||||||
|
'sessionEndedForProofsAt': sessionEndedForProofsAt?.toJson(),
|
||||||
'authStrategy': authStrategy,
|
'authStrategy': authStrategy,
|
||||||
'token': token,
|
'token': token,
|
||||||
if (tokenExpiresAt != null) 'tokenExpiresAt': tokenExpiresAt?.toJson(),
|
if (tokenExpiresAt != null) 'tokenExpiresAt': tokenExpiresAt?.toJson(),
|
||||||
|
|
@ -176,6 +194,7 @@ class _PasswordSignedInImpl extends PasswordSignedIn {
|
||||||
required _idt.ByteData signingPublicKey,
|
required _idt.ByteData signingPublicKey,
|
||||||
required _i2rxumte.WrappedKeys passwordKeys,
|
required _i2rxumte.WrappedKeys passwordKeys,
|
||||||
required bool needsAuthenticator,
|
required bool needsAuthenticator,
|
||||||
|
DateTime? sessionEndedForProofsAt,
|
||||||
required String authStrategy,
|
required String authStrategy,
|
||||||
required String token,
|
required String token,
|
||||||
DateTime? tokenExpiresAt,
|
DateTime? tokenExpiresAt,
|
||||||
|
|
@ -188,6 +207,7 @@ class _PasswordSignedInImpl extends PasswordSignedIn {
|
||||||
signingPublicKey: signingPublicKey,
|
signingPublicKey: signingPublicKey,
|
||||||
passwordKeys: passwordKeys,
|
passwordKeys: passwordKeys,
|
||||||
needsAuthenticator: needsAuthenticator,
|
needsAuthenticator: needsAuthenticator,
|
||||||
|
sessionEndedForProofsAt: sessionEndedForProofsAt,
|
||||||
authStrategy: authStrategy,
|
authStrategy: authStrategy,
|
||||||
token: token,
|
token: token,
|
||||||
tokenExpiresAt: tokenExpiresAt,
|
tokenExpiresAt: tokenExpiresAt,
|
||||||
|
|
@ -206,6 +226,7 @@ class _PasswordSignedInImpl extends PasswordSignedIn {
|
||||||
_idt.ByteData? signingPublicKey,
|
_idt.ByteData? signingPublicKey,
|
||||||
_i2rxumte.WrappedKeys? passwordKeys,
|
_i2rxumte.WrappedKeys? passwordKeys,
|
||||||
bool? needsAuthenticator,
|
bool? needsAuthenticator,
|
||||||
|
Object? sessionEndedForProofsAt = _Undefined,
|
||||||
String? authStrategy,
|
String? authStrategy,
|
||||||
String? token,
|
String? token,
|
||||||
Object? tokenExpiresAt = _Undefined,
|
Object? tokenExpiresAt = _Undefined,
|
||||||
|
|
@ -220,6 +241,9 @@ class _PasswordSignedInImpl extends PasswordSignedIn {
|
||||||
signingPublicKey: signingPublicKey ?? this.signingPublicKey.clone(),
|
signingPublicKey: signingPublicKey ?? this.signingPublicKey.clone(),
|
||||||
passwordKeys: passwordKeys ?? this.passwordKeys.copyWith(),
|
passwordKeys: passwordKeys ?? this.passwordKeys.copyWith(),
|
||||||
needsAuthenticator: needsAuthenticator ?? this.needsAuthenticator,
|
needsAuthenticator: needsAuthenticator ?? this.needsAuthenticator,
|
||||||
|
sessionEndedForProofsAt: sessionEndedForProofsAt is DateTime?
|
||||||
|
? sessionEndedForProofsAt
|
||||||
|
: this.sessionEndedForProofsAt,
|
||||||
authStrategy: authStrategy ?? this.authStrategy,
|
authStrategy: authStrategy ?? this.authStrategy,
|
||||||
token: token ?? this.token,
|
token: token ?? this.token,
|
||||||
tokenExpiresAt: tokenExpiresAt is DateTime?
|
tokenExpiresAt: tokenExpiresAt is DateTime?
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue