mirror of
https://git.selfprivacy.org/kherel/selfprivacy.org.app.git
synced 2024-11-01 06:27:17 +00:00
378 lines
11 KiB
Dart
378 lines
11 KiB
Dart
import 'package:hive/hive.dart';
|
|
import 'package:selfprivacy/config/hive_config.dart';
|
|
import 'package:selfprivacy/logic/cubit/app_config_dependent/authentication_dependend_cubit.dart';
|
|
import 'package:selfprivacy/logic/models/hive/user.dart';
|
|
|
|
import 'package:selfprivacy/logic/api_maps/rest_maps/server.dart';
|
|
|
|
export 'package:provider/provider.dart';
|
|
|
|
part 'users_state.dart';
|
|
|
|
class UsersCubit extends ServerInstallationDependendCubit<UsersState> {
|
|
UsersCubit(final ServerInstallationCubit serverInstallationCubit)
|
|
: super(
|
|
serverInstallationCubit,
|
|
const UsersState(
|
|
<User>[],
|
|
User(login: 'root'),
|
|
User(login: 'loading...'),
|
|
),
|
|
);
|
|
Box<User> box = Hive.box<User>(BNames.usersBox);
|
|
Box serverInstallationBox = Hive.box(BNames.serverInstallationBox);
|
|
|
|
final ServerApi api = ServerApi();
|
|
|
|
@override
|
|
Future<void> load() async {
|
|
if (serverInstallationCubit.state is ServerInstallationFinished) {
|
|
final List<User> loadedUsers = box.values.toList();
|
|
final primaryUser = serverInstallationBox.get(
|
|
BNames.rootUser,
|
|
defaultValue: const User(login: 'loading...'),
|
|
);
|
|
final List<String> rootKeys = [
|
|
...serverInstallationBox.get(BNames.rootKeys, defaultValue: [])
|
|
];
|
|
if (loadedUsers.isNotEmpty) {
|
|
emit(
|
|
UsersState(
|
|
loadedUsers,
|
|
User(login: 'root', sshKeys: rootKeys),
|
|
primaryUser,
|
|
),
|
|
);
|
|
}
|
|
|
|
final ApiResponse<List<String>> usersFromServer =
|
|
await api.getUsersList();
|
|
if (usersFromServer.isSuccess) {
|
|
final List<User> updatedList =
|
|
mergeLocalAndServerUsers(loadedUsers, usersFromServer.data);
|
|
emit(
|
|
UsersState(
|
|
updatedList,
|
|
User(login: 'root', sshKeys: rootKeys),
|
|
primaryUser,
|
|
),
|
|
);
|
|
}
|
|
|
|
final List<User> usersWithSshKeys = await loadSshKeys(state.users);
|
|
// Update the users it the box
|
|
box.clear();
|
|
box.addAll(usersWithSshKeys);
|
|
|
|
final User rootUserWithSshKeys =
|
|
(await loadSshKeys([state.rootUser])).first;
|
|
serverInstallationBox.put(BNames.rootKeys, rootUserWithSshKeys.sshKeys);
|
|
final User primaryUserWithSshKeys =
|
|
(await loadSshKeys([state.primaryUser])).first;
|
|
serverInstallationBox.put(BNames.rootUser, primaryUserWithSshKeys);
|
|
emit(
|
|
UsersState(
|
|
usersWithSshKeys,
|
|
rootUserWithSshKeys,
|
|
primaryUserWithSshKeys,
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
List<User> mergeLocalAndServerUsers(
|
|
final List<User> localUsers,
|
|
final List<String> serverUsers,
|
|
) {
|
|
// If local user not exists on server, add it with isFoundOnServer = false
|
|
// If server user not exists on local, add it
|
|
|
|
final List<User> mergedUsers = [];
|
|
final List<String> serverUsersCopy = List.from(serverUsers);
|
|
|
|
for (final User localUser in localUsers) {
|
|
if (serverUsersCopy.contains(localUser.login)) {
|
|
mergedUsers.add(
|
|
User(
|
|
login: localUser.login,
|
|
isFoundOnServer: true,
|
|
password: localUser.password,
|
|
sshKeys: localUser.sshKeys,
|
|
),
|
|
);
|
|
serverUsersCopy.remove(localUser.login);
|
|
} else {
|
|
mergedUsers.add(
|
|
User(
|
|
login: localUser.login,
|
|
isFoundOnServer: false,
|
|
password: localUser.password,
|
|
note: localUser.note,
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
for (final String serverUser in serverUsersCopy) {
|
|
mergedUsers.add(
|
|
User(
|
|
login: serverUser,
|
|
isFoundOnServer: true,
|
|
),
|
|
);
|
|
}
|
|
|
|
return mergedUsers;
|
|
}
|
|
|
|
Future<List<User>> loadSshKeys(final List<User> users) async {
|
|
final List<User> updatedUsers = [];
|
|
|
|
for (final User user in users) {
|
|
if (user.isFoundOnServer ||
|
|
user.login == 'root' ||
|
|
user.login == state.primaryUser.login) {
|
|
final ApiResponse<List<String>> sshKeys =
|
|
await api.getUserSshKeys(user);
|
|
print('sshKeys for $user: ${sshKeys.data}');
|
|
if (sshKeys.isSuccess) {
|
|
updatedUsers.add(
|
|
User(
|
|
login: user.login,
|
|
isFoundOnServer: true,
|
|
password: user.password,
|
|
sshKeys: sshKeys.data,
|
|
note: user.note,
|
|
),
|
|
);
|
|
} else {
|
|
updatedUsers.add(
|
|
User(
|
|
login: user.login,
|
|
isFoundOnServer: true,
|
|
password: user.password,
|
|
note: user.note,
|
|
),
|
|
);
|
|
}
|
|
} else {
|
|
updatedUsers.add(
|
|
User(
|
|
login: user.login,
|
|
isFoundOnServer: false,
|
|
password: user.password,
|
|
note: user.note,
|
|
),
|
|
);
|
|
}
|
|
}
|
|
return updatedUsers;
|
|
}
|
|
|
|
Future<void> refresh() async {
|
|
List<User> updatedUsers = List<User>.from(state.users);
|
|
final ApiResponse<List<String>> usersFromServer = await api.getUsersList();
|
|
if (usersFromServer.isSuccess) {
|
|
updatedUsers =
|
|
mergeLocalAndServerUsers(updatedUsers, usersFromServer.data);
|
|
}
|
|
final List<User> usersWithSshKeys = await loadSshKeys(updatedUsers);
|
|
box.clear();
|
|
box.addAll(usersWithSshKeys);
|
|
final User rootUserWithSshKeys =
|
|
(await loadSshKeys([state.rootUser])).first;
|
|
serverInstallationBox.put(BNames.rootKeys, rootUserWithSshKeys.sshKeys);
|
|
final User primaryUserWithSshKeys =
|
|
(await loadSshKeys([state.primaryUser])).first;
|
|
serverInstallationBox.put(BNames.rootUser, primaryUserWithSshKeys);
|
|
emit(
|
|
UsersState(
|
|
usersWithSshKeys,
|
|
rootUserWithSshKeys,
|
|
primaryUserWithSshKeys,
|
|
),
|
|
);
|
|
return;
|
|
}
|
|
|
|
Future<void> createUser(final User user) async {
|
|
// If user exists on server, do nothing
|
|
if (state.users
|
|
.any((final User u) => u.login == user.login && u.isFoundOnServer)) {
|
|
return;
|
|
}
|
|
// If user is root or primary user, do nothing
|
|
if (user.login == 'root' || user.login == state.primaryUser.login) {
|
|
return;
|
|
}
|
|
// If API returned error, do nothing
|
|
final ApiResponse<User> result = await api.createUser(user);
|
|
if (!result.isSuccess) {
|
|
return;
|
|
}
|
|
|
|
final List<User> loadedUsers = List<User>.from(state.users);
|
|
loadedUsers.add(result.data);
|
|
await box.clear();
|
|
await box.addAll(loadedUsers);
|
|
emit(state.copyWith(users: loadedUsers));
|
|
}
|
|
|
|
Future<void> deleteUser(final User user) async {
|
|
// If user is primary or root, don't delete
|
|
if (user.login == state.primaryUser.login || user.login == 'root') {
|
|
return;
|
|
}
|
|
final List<User> loadedUsers = List<User>.from(state.users);
|
|
final bool result = await api.deleteUser(user);
|
|
if (result) {
|
|
loadedUsers.removeWhere((final User u) => u.login == user.login);
|
|
await box.clear();
|
|
await box.addAll(loadedUsers);
|
|
emit(state.copyWith(users: loadedUsers));
|
|
}
|
|
}
|
|
|
|
Future<void> addSshKey(final User user, final String publicKey) async {
|
|
// If adding root key, use api.addRootSshKey
|
|
// Otherwise, use api.addUserSshKey
|
|
if (user.login == 'root') {
|
|
final ApiResponse<void> result = await api.addRootSshKey(publicKey);
|
|
if (result.isSuccess) {
|
|
// Add ssh key to the array of root keys
|
|
final List<String> rootKeys = serverInstallationBox
|
|
.get(BNames.rootKeys, defaultValue: []) as List<String>;
|
|
rootKeys.add(publicKey);
|
|
serverInstallationBox.put(BNames.rootKeys, rootKeys);
|
|
emit(
|
|
state.copyWith(
|
|
rootUser: User(
|
|
login: state.rootUser.login,
|
|
isFoundOnServer: true,
|
|
password: state.rootUser.password,
|
|
sshKeys: rootKeys,
|
|
note: state.rootUser.note,
|
|
),
|
|
),
|
|
);
|
|
}
|
|
} else {
|
|
final ApiResponse<void> result = await api.addUserSshKey(user, publicKey);
|
|
if (result.isSuccess) {
|
|
// If it is primary user, update primary user
|
|
if (user.login == state.primaryUser.login) {
|
|
final List<String> primaryUserKeys =
|
|
List<String>.from(state.primaryUser.sshKeys);
|
|
primaryUserKeys.add(publicKey);
|
|
final User updatedUser = User(
|
|
login: state.primaryUser.login,
|
|
isFoundOnServer: true,
|
|
password: state.primaryUser.password,
|
|
sshKeys: primaryUserKeys,
|
|
note: state.primaryUser.note,
|
|
);
|
|
serverInstallationBox.put(BNames.rootUser, updatedUser);
|
|
emit(
|
|
state.copyWith(
|
|
primaryUser: updatedUser,
|
|
),
|
|
);
|
|
} else {
|
|
// If it is not primary user, update user
|
|
final List<String> userKeys = List<String>.from(user.sshKeys);
|
|
userKeys.add(publicKey);
|
|
final User updatedUser = User(
|
|
login: user.login,
|
|
isFoundOnServer: true,
|
|
password: user.password,
|
|
sshKeys: userKeys,
|
|
note: user.note,
|
|
);
|
|
await box.putAt(box.values.toList().indexOf(user), updatedUser);
|
|
emit(
|
|
state.copyWith(
|
|
users: box.values.toList(),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Future<void> deleteSshKey(final User user, final String publicKey) async {
|
|
// All keys are deleted via api.deleteUserSshKey
|
|
|
|
final ApiResponse<void> result =
|
|
await api.deleteUserSshKey(user, publicKey);
|
|
if (result.isSuccess) {
|
|
// If it is root user, delete key from root keys
|
|
// If it is primary user, update primary user
|
|
// If it is not primary user, update user
|
|
|
|
if (user.login == 'root') {
|
|
final List<String> rootKeys = serverInstallationBox
|
|
.get(BNames.rootKeys, defaultValue: []) as List<String>;
|
|
rootKeys.remove(publicKey);
|
|
serverInstallationBox.put(BNames.rootKeys, rootKeys);
|
|
emit(
|
|
state.copyWith(
|
|
rootUser: User(
|
|
login: state.rootUser.login,
|
|
isFoundOnServer: true,
|
|
password: state.rootUser.password,
|
|
sshKeys: rootKeys,
|
|
note: state.rootUser.note,
|
|
),
|
|
),
|
|
);
|
|
return;
|
|
}
|
|
if (user.login == state.primaryUser.login) {
|
|
final List<String> primaryUserKeys =
|
|
List<String>.from(state.primaryUser.sshKeys);
|
|
primaryUserKeys.remove(publicKey);
|
|
final User updatedUser = User(
|
|
login: state.primaryUser.login,
|
|
isFoundOnServer: true,
|
|
password: state.primaryUser.password,
|
|
sshKeys: primaryUserKeys,
|
|
note: state.primaryUser.note,
|
|
);
|
|
serverInstallationBox.put(BNames.rootUser, updatedUser);
|
|
emit(
|
|
state.copyWith(
|
|
primaryUser: updatedUser,
|
|
),
|
|
);
|
|
return;
|
|
}
|
|
final List<String> userKeys = List<String>.from(user.sshKeys);
|
|
userKeys.remove(publicKey);
|
|
final User updatedUser = User(
|
|
login: user.login,
|
|
isFoundOnServer: true,
|
|
password: user.password,
|
|
sshKeys: userKeys,
|
|
note: user.note,
|
|
);
|
|
await box.putAt(box.values.toList().indexOf(user), updatedUser);
|
|
emit(
|
|
state.copyWith(
|
|
users: box.values.toList(),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
@override
|
|
void clear() async {
|
|
emit(
|
|
const UsersState(
|
|
<User>[],
|
|
User(login: 'root'),
|
|
User(login: 'loading...'),
|
|
),
|
|
);
|
|
}
|
|
}
|