Add user type to the User model

pull/111/head
Inex Code 2022-09-04 14:29:05 +03:00
parent 894cd9524f
commit c1bb617ca7
8 changed files with 127 additions and 167 deletions

View File

@ -37,12 +37,9 @@ mixin UsersApi on ApiMap {
if (response.hasException) {
print(response.exception.toString());
}
if (response.parsedData?.users.getUser != null) {
user = User(
login: response.parsedData!.users.getUser!.username,
sshKeys: response.parsedData!.users.getUser?.sshKeys ?? const [],
isFoundOnServer: true,
);
final responseUser = response.parsedData?.users.getUser;
if (responseUser != null) {
user = User.fromGraphQL(responseUser);
}
} catch (e) {
print(e);

View File

@ -4,6 +4,7 @@ import 'dart:io';
import 'package:dio/dio.dart';
import 'package:selfprivacy/config/get_it_config.dart';
import 'package:selfprivacy/logic/api_maps/rest_maps/api_map.dart';
import 'package:selfprivacy/logic/common_enum/common_enum.dart';
import 'package:selfprivacy/logic/models/hive/backblaze_bucket.dart';
import 'package:selfprivacy/logic/models/hive/server_domain.dart';
@ -15,8 +16,6 @@ import 'package:selfprivacy/logic/models/json/device_token.dart';
import 'package:selfprivacy/logic/models/json/recovery_token_status.dart';
import 'package:selfprivacy/logic/models/timezone_settings.dart';
import 'package:selfprivacy/logic/api_maps/rest_maps/api_map.dart';
class ApiResponse<D> {
ApiResponse({
required this.statusCode,
@ -71,9 +70,7 @@ class ServerApi extends ApiMap {
baseUrl: 'https://api.$overrideDomain',
connectTimeout: 10000,
receiveTimeout: 10000,
headers: customToken != null
? {'Authorization': 'Bearer $customToken'}
: null,
headers: customToken != null ? {'Authorization': 'Bearer $customToken'} : null,
);
}
@ -132,6 +129,7 @@ class ServerApi extends ApiMap {
statusCode: e.response?.statusCode ?? HttpStatus.internalServerError,
data: User(
login: user.login,
type: UserType.normal,
password: user.password,
isFoundOnServer: false,
),
@ -143,8 +141,7 @@ class ServerApi extends ApiMap {
bool isFoundOnServer = false;
int code = 0;
final bool isUserCreated = (response.statusCode != null) &&
(response.statusCode == HttpStatus.created);
final bool isUserCreated = (response.statusCode != null) && (response.statusCode == HttpStatus.created);
if (isUserCreated) {
isFoundOnServer = true;
@ -158,6 +155,7 @@ class ServerApi extends ApiMap {
statusCode: code,
data: User(
login: user.login,
type: UserType.normal,
password: user.password,
isFoundOnServer: isFoundOnServer,
),
@ -273,9 +271,7 @@ class ServerApi extends ApiMap {
final Dio client = await getClient();
try {
response = await client.get('/services/ssh/keys/${user.login}');
res = (response.data as List<dynamic>)
.map((final e) => e as String)
.toList();
res = (response.data as List<dynamic>).map((final e) => e as String).toList();
} on DioError catch (e) {
print(e.message);
return ApiResponse<List<String>>(
@ -334,9 +330,7 @@ class ServerApi extends ApiMap {
return ApiResponse<void>(
statusCode: code,
data: null,
errorMessage: response.data?.containsKey('error') ?? false
? response.data['error']
: null,
errorMessage: response.data?.containsKey('error') ?? false ? response.data['error'] : null,
);
}
@ -347,8 +341,7 @@ class ServerApi extends ApiMap {
final Dio client = await getClient();
try {
response = await client.delete('/users/${user.login}');
res = response.statusCode == HttpStatus.ok ||
response.statusCode == HttpStatus.notFound;
res = response.statusCode == HttpStatus.ok || response.statusCode == HttpStatus.notFound;
} on DioError catch (e) {
print(e.message);
res = false;
@ -359,8 +352,7 @@ class ServerApi extends ApiMap {
}
@override
String get rootAddress =>
throw UnimplementedError('not used in with implementation');
String get rootAddress => throw UnimplementedError('not used in with implementation');
Future<bool> apply() async {
bool res = false;
@ -453,8 +445,7 @@ class ServerApi extends ApiMap {
final Dio client = await getClient();
try {
response = await client.get('/services/restic/backup/list');
backups =
response.data.map<Backup>((final e) => Backup.fromJson(e)).toList();
backups = response.data.map<Backup>((final e) => Backup.fromJson(e)).toList();
} on DioError catch (e) {
print(e.message);
} catch (e) {
@ -517,9 +508,7 @@ class ServerApi extends ApiMap {
final Dio client = await getClient();
try {
response = await client.get('/system/configuration/pull');
result = (response.statusCode != null)
? (response.statusCode == HttpStatus.ok)
: false;
result = (response.statusCode != null) ? (response.statusCode == HttpStatus.ok) : false;
} on DioError catch (e) {
print(e.message);
} finally {
@ -535,9 +524,7 @@ class ServerApi extends ApiMap {
final Dio client = await getClient();
try {
response = await client.get('/system/reboot');
result = (response.statusCode != null)
? (response.statusCode == HttpStatus.ok)
: false;
result = (response.statusCode != null) ? (response.statusCode == HttpStatus.ok) : false;
} on DioError catch (e) {
print(e.message);
} finally {
@ -553,9 +540,7 @@ class ServerApi extends ApiMap {
final Dio client = await getClient();
try {
response = await client.get('/system/configuration/upgrade');
result = (response.statusCode != null)
? (response.statusCode == HttpStatus.ok)
: false;
result = (response.statusCode != null) ? (response.statusCode == HttpStatus.ok) : false;
} on DioError catch (e) {
print(e.message);
} finally {
@ -604,8 +589,7 @@ class ServerApi extends ApiMap {
Future<TimeZoneSettings> getServerTimezone() async {
// I am not sure how to initialize TimeZoneSettings with default value...
final Dio client = await getClient();
final Response response =
await client.get('/system/configuration/timezone');
final Response response = await client.get('/system/configuration/timezone');
close(client);
return TimeZoneSettings.fromString(response.data);
@ -632,11 +616,7 @@ class ServerApi extends ApiMap {
try {
response = await client.get('/services/mailserver/dkim');
final Codec<String, String> base64toString = utf8.fuse(base64);
dkim = base64toString
.decode(response.data)
.split('(')[1]
.split(')')[0]
.replaceAll('"', '');
dkim = base64toString.decode(response.data).split('(')[1].split(')')[0].replaceAll('"', '');
} on DioError catch (e) {
print(e.message);
} finally {
@ -667,9 +647,7 @@ class ServerApi extends ApiMap {
return ApiResponse(
statusCode: code,
data: response.data != null
? RecoveryKeyStatus.fromJson(response.data)
: null,
data: response.data != null ? RecoveryKeyStatus.fromJson(response.data) : null,
);
}
@ -839,11 +817,7 @@ class ServerApi extends ApiMap {
return ApiResponse(
statusCode: code,
data: (response.data != null)
? response.data
.map<ApiToken>((final e) => ApiToken.fromJson(e))
.toList()
: [],
data: (response.data != null) ? response.data.map<ApiToken>((final e) => ApiToken.fromJson(e)).toList() : [],
);
}

View File

@ -1,8 +1,8 @@
import 'dart:async';
import 'package:cubit_form/cubit_form.dart';
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
import 'package:selfprivacy/logic/cubit/forms/factories/field_cubit_factory.dart';
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
import 'package:selfprivacy/logic/models/hive/user.dart';
class RootUserFormCubit extends FormCubit {
@ -22,6 +22,7 @@ class RootUserFormCubit extends FormCubit {
FutureOr<void> onSubmit() async {
final User user = User(
login: userName.state.value,
type: UserType.primary,
password: password.state.value,
);
serverInstallationCubit.setRootUser(user);

View File

@ -1,10 +1,10 @@
import 'dart:async';
import 'package:cubit_form/cubit_form.dart';
import 'package:selfprivacy/logic/cubit/forms/factories/field_cubit_factory.dart';
import 'package:selfprivacy/logic/cubit/client_jobs/client_jobs_cubit.dart';
import 'package:selfprivacy/logic/models/job.dart';
import 'package:selfprivacy/logic/cubit/forms/factories/field_cubit_factory.dart';
import 'package:selfprivacy/logic/models/hive/user.dart';
import 'package:selfprivacy/logic/models/job.dart';
import 'package:selfprivacy/utils/password_generator.dart';
class UserFormCubit extends FormCubit {
@ -29,6 +29,7 @@ class UserFormCubit extends FormCubit {
FutureOr<void> onSubmit() {
final User user = User(
login: login.state.value,
type: UserType.normal,
password: password.state.value,
);
jobsCubit.addJob(CreateUserJob(user: user));

View File

@ -12,10 +12,11 @@ import 'package:selfprivacy/config/hive_config.dart';
import 'package:selfprivacy/logic/api_maps/rest_maps/api_factory_creator.dart';
import 'package:selfprivacy/logic/api_maps/rest_maps/dns_providers/dns_provider.dart';
import 'package:selfprivacy/logic/api_maps/rest_maps/dns_providers/dns_provider_factory.dart';
import 'package:selfprivacy/logic/api_maps/rest_maps/server.dart';
import 'package:selfprivacy/logic/api_maps/rest_maps/server_providers/server_provider.dart';
import 'package:selfprivacy/logic/api_maps/rest_maps/server_providers/server_provider_factory.dart';
import 'package:selfprivacy/logic/api_maps/rest_maps/server.dart';
import 'package:selfprivacy/logic/common_enum/common_enum.dart';
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
import 'package:selfprivacy/logic/models/hive/backblaze_credential.dart';
import 'package:selfprivacy/logic/models/hive/server_details.dart';
import 'package:selfprivacy/logic/models/hive/server_domain.dart';
@ -26,8 +27,6 @@ import 'package:selfprivacy/logic/models/server_basic_info.dart';
import 'package:selfprivacy/ui/components/action_button/action_button.dart';
import 'package:selfprivacy/ui/components/brand_alert/brand_alert.dart';
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
class IpNotFoundException implements Exception {
IpNotFoundException(this.message);
final String message;
@ -41,12 +40,10 @@ class ServerAuthorizationException implements Exception {
class ServerInstallationRepository {
Box box = Hive.box(BNames.serverInstallationBox);
Box<User> usersBox = Hive.box(BNames.usersBox);
ServerProviderApiFactory? serverProviderApiFactory =
ApiFactoryCreator.createServerProviderApiFactory(
ServerProviderApiFactory? serverProviderApiFactory = ApiFactoryCreator.createServerProviderApiFactory(
ServerProvider.hetzner, // TODO: HARDCODE FOR NOW!!!
); // TODO: Remove when provider selection is implemented.
DnsProviderApiFactory? dnsProviderApiFactory =
ApiFactoryCreator.createDnsProviderApiFactory(
DnsProviderApiFactory? dnsProviderApiFactory = ApiFactoryCreator.createDnsProviderApiFactory(
DnsProvider.cloudflare, // TODO: HARDCODE FOR NOW!!!
);
@ -54,15 +51,11 @@ class ServerInstallationRepository {
final String? providerApiToken = getIt<ApiConfigModel>().hetznerKey;
final String? cloudflareToken = getIt<ApiConfigModel>().cloudFlareKey;
final ServerDomain? serverDomain = getIt<ApiConfigModel>().serverDomain;
final BackblazeCredential? backblazeCredential =
getIt<ApiConfigModel>().backblazeCredential;
final ServerHostingDetails? serverDetails =
getIt<ApiConfigModel>().serverDetails;
final BackblazeCredential? backblazeCredential = getIt<ApiConfigModel>().backblazeCredential;
final ServerHostingDetails? serverDetails = getIt<ApiConfigModel>().serverDetails;
if (serverDetails != null &&
serverDetails.provider != ServerProvider.unknown) {
serverProviderApiFactory =
ApiFactoryCreator.createServerProviderApiFactory(
if (serverDetails != null && serverDetails.provider != ServerProvider.unknown) {
serverProviderApiFactory = ApiFactoryCreator.createServerProviderApiFactory(
serverDetails.provider,
);
}
@ -82,15 +75,12 @@ class ServerInstallationRepository {
serverDetails: serverDetails!,
rootUser: box.get(BNames.rootUser),
isServerStarted: box.get(BNames.isServerStarted, defaultValue: false),
isServerResetedFirstTime:
box.get(BNames.isServerResetedFirstTime, defaultValue: false),
isServerResetedSecondTime:
box.get(BNames.isServerResetedSecondTime, defaultValue: false),
isServerResetedFirstTime: box.get(BNames.isServerResetedFirstTime, defaultValue: false),
isServerResetedSecondTime: box.get(BNames.isServerResetedSecondTime, defaultValue: false),
);
}
if (box.get(BNames.isRecoveringServer, defaultValue: false) &&
serverDomain != null) {
if (box.get(BNames.isRecoveringServer, defaultValue: false) && serverDomain != null) {
return ServerInstallationRecovery(
providerApiToken: providerApiToken,
cloudFlareKey: cloudflareToken,
@ -116,10 +106,8 @@ class ServerInstallationRepository {
serverDetails: serverDetails,
rootUser: box.get(BNames.rootUser),
isServerStarted: box.get(BNames.isServerStarted, defaultValue: false),
isServerResetedFirstTime:
box.get(BNames.isServerResetedFirstTime, defaultValue: false),
isServerResetedSecondTime:
box.get(BNames.isServerResetedSecondTime, defaultValue: false),
isServerResetedFirstTime: box.get(BNames.isServerResetedFirstTime, defaultValue: false),
isServerResetedSecondTime: box.get(BNames.isServerResetedSecondTime, defaultValue: false),
isLoading: box.get(BNames.isLoading, defaultValue: false),
dnsMatches: null,
);
@ -183,13 +171,7 @@ class ServerInstallationRepository {
final String? ip4,
final Map<String, bool> skippedMatches,
) async {
final List<String> addresses = <String>[
'$domainName',
'api.$domainName',
'cloud.$domainName',
'meet.$domainName',
'password.$domainName'
];
final List<String> addresses = <String>['$domainName', 'api.$domainName', 'cloud.$domainName', 'meet.$domainName', 'password.$domainName'];
final Map<String, bool> matches = <String, bool>{};
@ -205,19 +187,15 @@ class ServerInstallationRepository {
);
getIt.get<ConsoleModel>().addMessage(
Message(
text:
'DnsLookup: address: $address, $RRecordType, provider: CLOUDFLARE, ip4: $ip4',
text: 'DnsLookup: address: $address, $RRecordType, provider: CLOUDFLARE, ip4: $ip4',
),
);
getIt.get<ConsoleModel>().addMessage(
Message(
text:
'DnsLookup: ${lookupRecordRes == null ? 'empty' : (lookupRecordRes[0].data != ip4 ? 'wrong ip4' : 'right ip4')}',
text: 'DnsLookup: ${lookupRecordRes == null ? 'empty' : (lookupRecordRes[0].data != ip4 ? 'wrong ip4' : 'right ip4')}',
),
);
if (lookupRecordRes == null ||
lookupRecordRes.isEmpty ||
lookupRecordRes[0].data != ip4) {
if (lookupRecordRes == null || lookupRecordRes.isEmpty || lookupRecordRes[0].data != ip4) {
matches[address] = false;
} else {
matches[address] = true;
@ -233,8 +211,7 @@ class ServerInstallationRepository {
final String cloudFlareKey,
final BackblazeCredential backblazeCredential, {
required final void Function() onCancel,
required final Future<void> Function(ServerHostingDetails serverDetails)
onSuccess,
required final Future<void> Function(ServerHostingDetails serverDetails) onSuccess,
}) async {
final ServerProviderApi api = serverProviderApiFactory!.getServerProvider();
try {
@ -338,10 +315,8 @@ class ServerInstallationRepository {
final ServerDomain domain, {
required final void Function() onCancel,
}) async {
final DnsProviderApi dnsProviderApi =
dnsProviderApiFactory!.getDnsProvider();
final ServerProviderApi serverApi =
serverProviderApiFactory!.getServerProvider();
final DnsProviderApi dnsProviderApi = dnsProviderApiFactory!.getDnsProvider();
final ServerProviderApi serverApi = serverProviderApiFactory!.getServerProvider();
await dnsProviderApi.removeSimilarRecords(
ip4: serverDetails.ip4,
@ -357,9 +332,7 @@ class ServerInstallationRepository {
final NavigationService nav = getIt.get<NavigationService>();
nav.showPopUpDialog(
BrandAlert(
title: e.response!.data['errors'][0]['code'] == 1038
? 'modals.10'.tr()
: 'providers.domain.states.error'.tr(),
title: e.response!.data['errors'][0]['code'] == 1038 ? 'modals.10'.tr() : 'providers.domain.states.error'.tr(),
contentText: 'modals.6'.tr(),
actions: [
ActionButton(
@ -392,8 +365,7 @@ class ServerInstallationRepository {
}
Future<void> createDkimRecord(final ServerDomain cloudFlareDomain) async {
final DnsProviderApi dnsProviderApi =
dnsProviderApiFactory!.getDnsProvider();
final DnsProviderApi dnsProviderApi = dnsProviderApiFactory!.getDnsProvider();
final ServerApi api = ServerApi();
String dkimRecordString = '';
@ -460,31 +432,25 @@ class ServerInstallationRepository {
final DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();
if (kIsWeb) {
return deviceInfo.webBrowserInfo.then(
(final WebBrowserInfo value) =>
'${value.browserName} ${value.platform}',
(final WebBrowserInfo value) => '${value.browserName} ${value.platform}',
);
} else {
if (Platform.isAndroid) {
return deviceInfo.androidInfo.then(
(final AndroidDeviceInfo value) =>
'${value.model} ${value.version.release}',
(final AndroidDeviceInfo value) => '${value.model} ${value.version.release}',
);
} else if (Platform.isIOS) {
return deviceInfo.iosInfo.then(
(final IosDeviceInfo value) =>
'${value.utsname.machine} ${value.systemName} ${value.systemVersion}',
(final IosDeviceInfo value) => '${value.utsname.machine} ${value.systemName} ${value.systemVersion}',
);
} else if (Platform.isLinux) {
return deviceInfo.linuxInfo
.then((final LinuxDeviceInfo value) => value.prettyName);
return deviceInfo.linuxInfo.then((final LinuxDeviceInfo value) => value.prettyName);
} else if (Platform.isMacOS) {
return deviceInfo.macOsInfo.then(
(final MacOsDeviceInfo value) =>
'${value.hostName} ${value.computerName}',
(final MacOsDeviceInfo value) => '${value.hostName} ${value.computerName}',
);
} else if (Platform.isWindows) {
return deviceInfo.windowsInfo
.then((final WindowsDeviceInfo value) => value.computerName);
return deviceInfo.windowsInfo.then((final WindowsDeviceInfo value) => value.computerName);
}
}
return 'Unidentified';
@ -576,8 +542,7 @@ class ServerInstallationRepository {
);
final String serverIp = await getServerIpFromDomain(serverDomain);
if (recoveryCapabilities == ServerRecoveryCapabilities.legacy) {
final Map<ServiceTypes, bool> apiResponse =
await serverApi.servicesPowerCheck();
final Map<ServiceTypes, bool> apiResponse = await serverApi.servicesPowerCheck();
if (apiResponse.isNotEmpty) {
return ServerHostingDetails(
apiToken: apiToken,
@ -600,8 +565,7 @@ class ServerInstallationRepository {
);
}
}
final ApiResponse<String> deviceAuthKey =
await serverApi.createDeviceToken();
final ApiResponse<String> deviceAuthKey = await serverApi.createDeviceToken();
final ApiResponse<String> apiResponse = await serverApi.authorizeDevice(
DeviceToken(device: await getDeviceName(), token: deviceAuthKey.data),
);
@ -633,14 +597,14 @@ class ServerInstallationRepository {
final ServerApi serverApi = ServerApi();
const User fallbackUser = User(
isFoundOnServer: false,
type: UserType.primary,
note: "Couldn't find main user on server, API is outdated",
login: 'UNKNOWN',
sshKeys: [],
);
final String? serverApiVersion = await serverApi.getApiVersion();
final ApiResponse<List<String>> users =
await serverApi.getUsersList(withMainUser: true);
final ApiResponse<List<String>> users = await serverApi.getUsersList(withMainUser: true);
if (serverApiVersion == null || !users.isSuccess) {
return fallbackUser;
}
@ -652,6 +616,7 @@ class ServerInstallationRepository {
return User(
isFoundOnServer: true,
login: users.data[0],
type: UserType.primary,
);
} on FormatException {
return fallbackUser;
@ -739,8 +704,7 @@ class ServerInstallationRepository {
Future<void> deleteServer(final ServerDomain serverDomain) async {
final ServerProviderApi api = serverProviderApiFactory!.getServerProvider();
final DnsProviderApi dnsProviderApi =
dnsProviderApiFactory!.getDnsProvider();
final DnsProviderApi dnsProviderApi = dnsProviderApiFactory!.getDnsProvider();
await api.deleteServer(
domainName: serverDomain.domainName,

View File

@ -1,10 +1,9 @@
import 'package:hive/hive.dart';
import 'package:selfprivacy/config/hive_config.dart';
import 'package:selfprivacy/logic/api_maps/rest_maps/server.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';
@ -15,8 +14,8 @@ class UsersCubit extends ServerInstallationDependendCubit<UsersState> {
serverInstallationCubit,
const UsersState(
<User>[],
User(login: 'root'),
User(login: 'loading...'),
User(login: 'root', type: UserType.root),
User(login: 'loading...', type: UserType.primary),
),
);
Box<User> box = Hive.box<User>(BNames.usersBox);
@ -30,30 +29,26 @@ class UsersCubit extends ServerInstallationDependendCubit<UsersState> {
final List<User> loadedUsers = box.values.toList();
final primaryUser = serverInstallationBox.get(
BNames.rootUser,
defaultValue: const User(login: 'loading...'),
defaultValue: const User(login: 'loading...', type: UserType.primary),
);
final List<String> rootKeys = [
...serverInstallationBox.get(BNames.rootKeys, defaultValue: [])
];
final List<String> rootKeys = [...serverInstallationBox.get(BNames.rootKeys, defaultValue: [])];
if (loadedUsers.isNotEmpty) {
emit(
UsersState(
loadedUsers,
User(login: 'root', sshKeys: rootKeys),
User(login: 'root', sshKeys: rootKeys, type: UserType.root),
primaryUser,
),
);
}
final ApiResponse<List<String>> usersFromServer =
await api.getUsersList();
final ApiResponse<List<String>> usersFromServer = await api.getUsersList();
if (usersFromServer.isSuccess) {
final List<User> updatedList =
mergeLocalAndServerUsers(loadedUsers, usersFromServer.data);
final List<User> updatedList = mergeLocalAndServerUsers(loadedUsers, usersFromServer.data);
emit(
UsersState(
updatedList,
User(login: 'root', sshKeys: rootKeys),
User(login: 'root', sshKeys: rootKeys, type: UserType.root),
primaryUser,
),
);
@ -64,11 +59,9 @@ class UsersCubit extends ServerInstallationDependendCubit<UsersState> {
box.clear();
box.addAll(usersWithSshKeys);
final User rootUserWithSshKeys =
(await loadSshKeys([state.rootUser])).first;
final User rootUserWithSshKeys = (await loadSshKeys([state.rootUser])).first;
serverInstallationBox.put(BNames.rootKeys, rootUserWithSshKeys.sshKeys);
final User primaryUserWithSshKeys =
(await loadSshKeys([state.primaryUser])).first;
final User primaryUserWithSshKeys = (await loadSshKeys([state.primaryUser])).first;
serverInstallationBox.put(BNames.rootUser, primaryUserWithSshKeys);
emit(
UsersState(
@ -95,6 +88,7 @@ class UsersCubit extends ServerInstallationDependendCubit<UsersState> {
mergedUsers.add(
User(
login: localUser.login,
type: UserType.normal,
isFoundOnServer: true,
password: localUser.password,
sshKeys: localUser.sshKeys,
@ -105,6 +99,7 @@ class UsersCubit extends ServerInstallationDependendCubit<UsersState> {
mergedUsers.add(
User(
login: localUser.login,
type: UserType.normal,
isFoundOnServer: false,
password: localUser.password,
note: localUser.note,
@ -117,6 +112,7 @@ class UsersCubit extends ServerInstallationDependendCubit<UsersState> {
mergedUsers.add(
User(
login: serverUser,
type: UserType.normal,
isFoundOnServer: true,
),
);
@ -129,16 +125,14 @@ class UsersCubit extends ServerInstallationDependendCubit<UsersState> {
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);
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,
type: user.type,
isFoundOnServer: true,
password: user.password,
sshKeys: sshKeys.data,
@ -149,6 +143,7 @@ class UsersCubit extends ServerInstallationDependendCubit<UsersState> {
updatedUsers.add(
User(
login: user.login,
type: user.type,
isFoundOnServer: true,
password: user.password,
note: user.note,
@ -159,6 +154,7 @@ class UsersCubit extends ServerInstallationDependendCubit<UsersState> {
updatedUsers.add(
User(
login: user.login,
type: user.type,
isFoundOnServer: false,
password: user.password,
note: user.note,
@ -173,17 +169,14 @@ class UsersCubit extends ServerInstallationDependendCubit<UsersState> {
List<User> updatedUsers = List<User>.from(state.users);
final ApiResponse<List<String>> usersFromServer = await api.getUsersList();
if (usersFromServer.isSuccess) {
updatedUsers =
mergeLocalAndServerUsers(updatedUsers, usersFromServer.data);
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;
final User rootUserWithSshKeys = (await loadSshKeys([state.rootUser])).first;
serverInstallationBox.put(BNames.rootKeys, rootUserWithSshKeys.sshKeys);
final User primaryUserWithSshKeys =
(await loadSshKeys([state.primaryUser])).first;
final User primaryUserWithSshKeys = (await loadSshKeys([state.primaryUser])).first;
serverInstallationBox.put(BNames.rootUser, primaryUserWithSshKeys);
emit(
UsersState(
@ -197,8 +190,7 @@ class UsersCubit extends ServerInstallationDependendCubit<UsersState> {
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)) {
if (state.users.any((final User u) => u.login == user.login && u.isFoundOnServer)) {
return;
}
// If user is root or primary user, do nothing
@ -240,14 +232,14 @@ class UsersCubit extends ServerInstallationDependendCubit<UsersState> {
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>;
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,
type: UserType.root,
isFoundOnServer: true,
password: state.rootUser.password,
sshKeys: rootKeys,
@ -261,11 +253,11 @@ class UsersCubit extends ServerInstallationDependendCubit<UsersState> {
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);
final List<String> primaryUserKeys = List<String>.from(state.primaryUser.sshKeys);
primaryUserKeys.add(publicKey);
final User updatedUser = User(
login: state.primaryUser.login,
type: UserType.primary,
isFoundOnServer: true,
password: state.primaryUser.password,
sshKeys: primaryUserKeys,
@ -283,6 +275,7 @@ class UsersCubit extends ServerInstallationDependendCubit<UsersState> {
userKeys.add(publicKey);
final User updatedUser = User(
login: user.login,
type: UserType.normal,
isFoundOnServer: true,
password: user.password,
sshKeys: userKeys,
@ -302,22 +295,21 @@ class UsersCubit extends ServerInstallationDependendCubit<UsersState> {
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);
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>;
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,
type: UserType.root,
isFoundOnServer: true,
password: state.rootUser.password,
sshKeys: rootKeys,
@ -328,11 +320,11 @@ class UsersCubit extends ServerInstallationDependendCubit<UsersState> {
return;
}
if (user.login == state.primaryUser.login) {
final List<String> primaryUserKeys =
List<String>.from(state.primaryUser.sshKeys);
final List<String> primaryUserKeys = List<String>.from(state.primaryUser.sshKeys);
primaryUserKeys.remove(publicKey);
final User updatedUser = User(
login: state.primaryUser.login,
type: UserType.primary,
isFoundOnServer: true,
password: state.primaryUser.password,
sshKeys: primaryUserKeys,
@ -350,6 +342,7 @@ class UsersCubit extends ServerInstallationDependendCubit<UsersState> {
userKeys.remove(publicKey);
final User updatedUser = User(
login: user.login,
type: UserType.normal,
isFoundOnServer: true,
password: user.password,
sshKeys: userKeys,
@ -369,8 +362,8 @@ class UsersCubit extends ServerInstallationDependendCubit<UsersState> {
emit(
const UsersState(
<User>[],
User(login: 'root'),
User(login: 'loading...'),
User(login: 'root', type: UserType.root),
User(login: 'loading...', type: UserType.primary),
),
);
}

View File

@ -7,7 +7,8 @@
5. ServerVolume
6. BackblazeBucket
## Enums
100. DnsProvider
101. ServerProvider
101. ServerProvider
102. UserType

View File

@ -2,6 +2,7 @@ import 'dart:ui';
import 'package:equatable/equatable.dart';
import 'package:hive/hive.dart';
import 'package:selfprivacy/logic/api_maps/graphql_maps/schema/schema.graphql.dart';
import 'package:selfprivacy/logic/api_maps/graphql_maps/schema/users.graphql.dart';
import 'package:selfprivacy/utils/color_utils.dart';
@ -11,6 +12,7 @@ part 'user.g.dart';
class User extends Equatable {
const User({
required this.login,
required this.type,
this.password,
this.sshKeys = const [],
this.isFoundOnServer = true,
@ -20,6 +22,7 @@ class User extends Equatable {
User.fromGraphQL(final Fragment$userFields user)
: this(
login: user.username,
type: UserType.fromGraphQL(user.userType),
sshKeys: user.sshKeys,
isFoundOnServer: true,
);
@ -39,6 +42,9 @@ class User extends Equatable {
@HiveField(4)
final String? note;
@HiveField(5, defaultValue: UserType.normal)
final UserType type;
@override
List<Object?> get props => [login, password, sshKeys, isFoundOnServer, note];
@ -47,3 +53,26 @@ class User extends Equatable {
@override
String toString() => '$login, ${isFoundOnServer ? 'found' : 'not found'}, ${sshKeys.length} ssh keys, note: $note';
}
@HiveType(typeId: 102)
enum UserType {
@HiveField(0)
root,
@HiveField(1)
primary,
@HiveField(2)
normal;
factory UserType.fromGraphQL(final Enum$UserType type) {
switch (type) {
case Enum$UserType.ROOT:
return root;
case Enum$UserType.PRIMARY:
return primary;
case Enum$UserType.NORMAL:
return normal;
case Enum$UserType.$unknown:
return normal;
}
}
}