Fix password login profile handling

This commit is contained in:
klockky
2026-07-05 23:06:16 +03:00
parent 815e41648a
commit 4e35e3d176
6 changed files with 73 additions and 24 deletions
+37 -10
View File
@@ -228,7 +228,9 @@ class AccountModule {
throw Exception('completeRegistration: отсутствует id аккаунта');
}
final profile = ProfileData.fromServerMap(contact.cast<dynamic, dynamic>());
final profile = ProfileData.fromServerProfile(
profileMap.cast<dynamic, dynamic>(),
);
await AppDatabase.saveProfile(profile, isActive: true);
await TokenStorage.setActiveAccount(accountId);
await SpoofingService.commitPendingSpoof(accountId);
@@ -446,8 +448,25 @@ class AccountModule {
throw Exception('checkPassword: отсутствует токен в ответе');
}
final accountId = extractAccountId(data);
if (accountId == null) {
throw Exception('checkPassword: отсутствует accountId в ответе');
}
final profileMap = data['profile'];
if (profileMap is Map) {
final profile = ProfileData.fromServerProfile(
profileMap.cast<dynamic, dynamic>(),
);
await AppDatabase.saveProfile(profile, isActive: true);
}
await TokenStorage.saveToken(loginToken, accountId);
await TokenStorage.setActiveAccount(accountId);
await SpoofingService.commitPendingSpoof(accountId);
logger.i('2FA пройдена, получен login-токен');
return TwoFactorResult(loginToken: loginToken);
return TwoFactorResult(loginToken: loginToken, accountId: accountId);
}
Map<dynamic, dynamic> buildLoginPayload(
@@ -500,16 +519,24 @@ class AccountModule {
await TokenStorage.saveToken(updatedToken, accountId);
}
ProfileData profile;
final profileMap = data['profile'];
if (profileMap is! Map) {
throw Exception('login: отсутствует profile в ответе');
if (profileMap is Map) {
final contact = profileMap['contact'];
if (contact is! Map) {
throw Exception('login: отсутствует profile.contact в ответе');
}
profile = ProfileData.fromServerProfile(
profileMap.cast<dynamic, dynamic>(),
);
await AppDatabase.saveProfile(profile, isActive: true);
} else {
final cachedProfile = await AppDatabase.loadProfile(accountId);
if (cachedProfile == null) {
throw Exception('login: отсутствует profile в ответе');
}
profile = cachedProfile;
}
final contact = profileMap['contact'];
if (contact is! Map) {
throw Exception('login: отсутствует profile.contact в ответе');
}
final profile = ProfileData.fromServerMap(contact.cast<dynamic, dynamic>());
await AppDatabase.saveProfile(profile, isActive: true);
await AppDatabase.setActiveAccount(profile.id);
await _saveSyncState(data, serverTime, profile.id);
@@ -372,8 +372,9 @@ class VerifyCodeResult {
class TwoFactorResult {
final String loginToken;
final int accountId;
const TwoFactorResult({required this.loginToken});
const TwoFactorResult({required this.loginToken, required this.accountId});
}
class LoginSyncParams {
@@ -18,8 +18,8 @@ class ProfileModule extends AccountApiBase {
if (profile == null) throw Exception('No profile in response');
final contact = profile['contact'] as Map?;
if (contact == null) throw Exception('No contact in response');
final newProfile = ProfileData.fromServerMap(
contact.cast<dynamic, dynamic>(),
final newProfile = ProfileData.fromServerProfile(
profile.cast<dynamic, dynamic>(),
);
await AppDatabase.saveProfile(newProfile, isActive: true);
return newProfile;
@@ -88,7 +88,7 @@ class ProfileModule extends AccountApiBase {
final contact = profile['contact'];
if (contact is! Map) return;
completer.complete(
ProfileData.fromServerMap(contact.cast<dynamic, dynamic>()),
ProfileData.fromServerProfile(profile.cast<dynamic, dynamic>()),
);
});
final timer = Timer(const Duration(seconds: 15), () {
+26 -8
View File
@@ -36,7 +36,21 @@ class ProfileData {
this.profileOptions,
});
factory ProfileData.fromServerMap(Map<dynamic, dynamic> contact) {
factory ProfileData.fromServerProfile(Map<dynamic, dynamic> profile) {
final contact = profile['contact'];
if (contact is! Map) {
throw const FormatException('No contact in profile');
}
return ProfileData.fromServerMap(
contact.cast<dynamic, dynamic>(),
profileOptions: _parseProfileOptions(profile['profileOptions']),
);
}
factory ProfileData.fromServerMap(
Map<dynamic, dynamic> contact, {
List<int>? profileOptions,
}) {
final names = contact['names'];
String firstName = '';
String? lastName;
@@ -52,12 +66,6 @@ class ProfileData {
lastName = name['lastName'] as String?;
}
final profileOptionsRaw = contact['profileOptions'];
List<int>? profileOptions;
if (profileOptionsRaw is List) {
profileOptions = profileOptionsRaw.map((e) => e as int).toList();
}
return ProfileData(
id: contact['id'] as int,
firstName: firstName,
@@ -69,10 +77,20 @@ class ProfileData {
country: (contact['country'] as String?) ?? '',
accountStatus: (contact['accountStatus'] as int?) ?? 0,
updateTime: (contact['updateTime'] as int?) ?? 0,
profileOptions: profileOptions,
profileOptions:
profileOptions ?? _parseProfileOptions(contact['profileOptions']),
);
}
static List<int>? _parseProfileOptions(dynamic raw) {
if (raw is! List) return null;
final options = raw
.map((e) => e is int ? e : int.tryParse(e.toString()))
.whereType<int>()
.toList();
return options.isEmpty ? null : options;
}
factory ProfileData.fromDbRow(Map<String, dynamic> row) {
final profileOptionsStr = row['profile_options'] as String?;
List<int>? profileOptions;
@@ -67,7 +67,10 @@ class _Password2FAScreenState extends State<Password2FAScreen>
if (!mounted) return;
final loginResult = await accountModule.login(token: result.loginToken);
final loginResult = await accountModule.login(
accountId: result.accountId,
token: result.loginToken,
);
if (!mounted) return;
+1 -1
View File
@@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
# In Windows, build-name is used as the major, minor, and patch parts
# of the product and file versions while build-number is used as the build suffix.
version: 0.5.0+13
version: 0.5.0+14
environment:
sdk: ^3.10.4