mirror of
https://gitlab.com/veilid/veilidchat.git
synced 2024-12-16 19:44:28 -05:00
148 lines
4.5 KiB
Dart
148 lines
4.5 KiB
Dart
import 'package:freezed_annotation/freezed_annotation.dart';
|
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
|
|
|
import '../../entities/local_account.dart';
|
|
import '../../entities/user_login.dart';
|
|
import '../../proto/proto.dart' as proto;
|
|
import '../../../packages/veilid_support/veilid_support.dart';
|
|
import '../../local_accounts/local_accounts.dart';
|
|
import 'logins.dart';
|
|
|
|
part 'account.g.dart';
|
|
|
|
enum AccountInfoStatus {
|
|
noAccount,
|
|
accountInvalid,
|
|
accountLocked,
|
|
accountReady,
|
|
}
|
|
|
|
@immutable
|
|
class AccountInfo {
|
|
const AccountInfo({
|
|
required this.status,
|
|
required this.active,
|
|
this.account,
|
|
});
|
|
|
|
final AccountInfoStatus status;
|
|
final bool active;
|
|
final proto.Account? account;
|
|
}
|
|
|
|
/// Get an account from the identity key and if it is logged in and we
|
|
/// have its secret available, return the account record contents
|
|
@riverpod
|
|
Future<AccountInfo> fetchAccountInfo(FetchAccountInfoRef ref,
|
|
{required TypedKey accountMasterRecordKey}) async {
|
|
// Get which local account we want to fetch the profile for
|
|
final localAccount = await ref.watch(
|
|
fetchLocalAccountProvider(accountMasterRecordKey: accountMasterRecordKey)
|
|
.future);
|
|
if (localAccount == null) {
|
|
// Local account does not exist
|
|
return const AccountInfo(
|
|
status: AccountInfoStatus.noAccount, active: false);
|
|
}
|
|
|
|
// See if we've logged into this account or if it is locked
|
|
final activeUserLogin = await ref.watch(loginsProvider.future
|
|
.select((value) async => (await value).activeUserLogin));
|
|
final active = activeUserLogin == accountMasterRecordKey;
|
|
|
|
final login = await ref.watch(
|
|
fetchLoginProvider(accountMasterRecordKey: accountMasterRecordKey)
|
|
.future);
|
|
if (login == null) {
|
|
// Account was locked
|
|
return AccountInfo(status: AccountInfoStatus.accountLocked, active: active);
|
|
}
|
|
|
|
xxx login should open this key and leave it open, logout should close it
|
|
|
|
// Pull the account DHT key, decode it and return it
|
|
final pool = await DHTRecordPool.instance();
|
|
final account = await (await pool.openOwned(
|
|
login.accountRecordInfo.accountRecord,
|
|
parent: localAccount.identityMaster.identityRecordKey))
|
|
.scope((accountRec) => accountRec.getProtobuf(proto.Account.fromBuffer));
|
|
if (account == null) {
|
|
// Account could not be read or decrypted from DHT
|
|
ref.invalidateSelf();
|
|
return AccountInfo(
|
|
status: AccountInfoStatus.accountInvalid, active: active);
|
|
}
|
|
|
|
// Got account, decrypted and decoded
|
|
return AccountInfo(
|
|
status: AccountInfoStatus.accountReady, active: active, account: account);
|
|
}
|
|
|
|
@immutable
|
|
class ActiveAccountInfo {
|
|
const ActiveAccountInfo({
|
|
required this.localAccount,
|
|
required this.userLogin,
|
|
required this.account,
|
|
});
|
|
//
|
|
|
|
KeyPair getConversationWriter() {
|
|
final identityKey = localAccount.identityMaster.identityPublicKey;
|
|
final identitySecret = userLogin.identitySecret;
|
|
return KeyPair(key: identityKey, secret: identitySecret.value);
|
|
}
|
|
|
|
//
|
|
final LocalAccount localAccount;
|
|
final UserLogin userLogin;
|
|
final proto.Account account;
|
|
}
|
|
|
|
/// Get the active account info
|
|
@riverpod
|
|
Future<ActiveAccountInfo?> fetchActiveAccountInfo(
|
|
FetchActiveAccountInfoRef ref) async {
|
|
// See if we've logged into this account or if it is locked
|
|
final activeUserLogin = await ref.watch(loginsProvider.future
|
|
.select((value) async => (await value).activeUserLogin));
|
|
if (activeUserLogin == null) {
|
|
return null;
|
|
}
|
|
|
|
// Get the user login
|
|
final userLogin = await ref.watch(
|
|
fetchLoginProvider(accountMasterRecordKey: activeUserLogin).future);
|
|
if (userLogin == null) {
|
|
// Account was locked
|
|
return null;
|
|
}
|
|
|
|
// Get which local account we want to fetch the profile for
|
|
final localAccount = await ref.watch(
|
|
fetchLocalAccountProvider(accountMasterRecordKey: activeUserLogin)
|
|
.future);
|
|
if (localAccount == null) {
|
|
// Local account does not exist
|
|
return null;
|
|
}
|
|
|
|
// Pull the account DHT key, decode it and return it
|
|
final pool = await DHTRecordPool.instance();
|
|
final account = await (await pool.openOwned(
|
|
userLogin.accountRecordInfo.accountRecord,
|
|
parent: localAccount.identityMaster.identityRecordKey))
|
|
.scope((accountRec) => accountRec.getProtobuf(proto.Account.fromBuffer));
|
|
if (account == null) {
|
|
ref.invalidateSelf();
|
|
return null;
|
|
}
|
|
|
|
// Got account, decrypted and decoded
|
|
return ActiveAccountInfo(
|
|
localAccount: localAccount,
|
|
userLogin: userLogin,
|
|
account: account,
|
|
);
|
|
}
|