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) { if (response.hasException) {
print(response.exception.toString()); print(response.exception.toString());
} }
if (response.parsedData?.users.getUser != null) { final responseUser = response.parsedData?.users.getUser;
user = User( if (responseUser != null) {
login: response.parsedData!.users.getUser!.username, user = User.fromGraphQL(responseUser);
sshKeys: response.parsedData!.users.getUser?.sshKeys ?? const [],
isFoundOnServer: true,
);
} }
} catch (e) { } catch (e) {
print(e); print(e);

View File

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

View File

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

View File

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

View File

@ -1,10 +1,9 @@
import 'package:hive/hive.dart'; import 'package:hive/hive.dart';
import 'package:selfprivacy/config/hive_config.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/cubit/app_config_dependent/authentication_dependend_cubit.dart';
import 'package:selfprivacy/logic/models/hive/user.dart'; import 'package:selfprivacy/logic/models/hive/user.dart';
import 'package:selfprivacy/logic/api_maps/rest_maps/server.dart';
export 'package:provider/provider.dart'; export 'package:provider/provider.dart';
part 'users_state.dart'; part 'users_state.dart';
@ -15,8 +14,8 @@ class UsersCubit extends ServerInstallationDependendCubit<UsersState> {
serverInstallationCubit, serverInstallationCubit,
const UsersState( const UsersState(
<User>[], <User>[],
User(login: 'root'), User(login: 'root', type: UserType.root),
User(login: 'loading...'), User(login: 'loading...', type: UserType.primary),
), ),
); );
Box<User> box = Hive.box<User>(BNames.usersBox); 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 List<User> loadedUsers = box.values.toList();
final primaryUser = serverInstallationBox.get( final primaryUser = serverInstallationBox.get(
BNames.rootUser, BNames.rootUser,
defaultValue: const User(login: 'loading...'), defaultValue: const User(login: 'loading...', type: UserType.primary),
); );
final List<String> rootKeys = [ final List<String> rootKeys = [...serverInstallationBox.get(BNames.rootKeys, defaultValue: [])];
...serverInstallationBox.get(BNames.rootKeys, defaultValue: [])
];
if (loadedUsers.isNotEmpty) { if (loadedUsers.isNotEmpty) {
emit( emit(
UsersState( UsersState(
loadedUsers, loadedUsers,
User(login: 'root', sshKeys: rootKeys), User(login: 'root', sshKeys: rootKeys, type: UserType.root),
primaryUser, primaryUser,
), ),
); );
} }
final ApiResponse<List<String>> usersFromServer = final ApiResponse<List<String>> usersFromServer = await api.getUsersList();
await api.getUsersList();
if (usersFromServer.isSuccess) { if (usersFromServer.isSuccess) {
final List<User> updatedList = final List<User> updatedList = mergeLocalAndServerUsers(loadedUsers, usersFromServer.data);
mergeLocalAndServerUsers(loadedUsers, usersFromServer.data);
emit( emit(
UsersState( UsersState(
updatedList, updatedList,
User(login: 'root', sshKeys: rootKeys), User(login: 'root', sshKeys: rootKeys, type: UserType.root),
primaryUser, primaryUser,
), ),
); );
@ -64,11 +59,9 @@ class UsersCubit extends ServerInstallationDependendCubit<UsersState> {
box.clear(); box.clear();
box.addAll(usersWithSshKeys); box.addAll(usersWithSshKeys);
final User rootUserWithSshKeys = final User rootUserWithSshKeys = (await loadSshKeys([state.rootUser])).first;
(await loadSshKeys([state.rootUser])).first;
serverInstallationBox.put(BNames.rootKeys, rootUserWithSshKeys.sshKeys); serverInstallationBox.put(BNames.rootKeys, rootUserWithSshKeys.sshKeys);
final User primaryUserWithSshKeys = final User primaryUserWithSshKeys = (await loadSshKeys([state.primaryUser])).first;
(await loadSshKeys([state.primaryUser])).first;
serverInstallationBox.put(BNames.rootUser, primaryUserWithSshKeys); serverInstallationBox.put(BNames.rootUser, primaryUserWithSshKeys);
emit( emit(
UsersState( UsersState(
@ -95,6 +88,7 @@ class UsersCubit extends ServerInstallationDependendCubit<UsersState> {
mergedUsers.add( mergedUsers.add(
User( User(
login: localUser.login, login: localUser.login,
type: UserType.normal,
isFoundOnServer: true, isFoundOnServer: true,
password: localUser.password, password: localUser.password,
sshKeys: localUser.sshKeys, sshKeys: localUser.sshKeys,
@ -105,6 +99,7 @@ class UsersCubit extends ServerInstallationDependendCubit<UsersState> {
mergedUsers.add( mergedUsers.add(
User( User(
login: localUser.login, login: localUser.login,
type: UserType.normal,
isFoundOnServer: false, isFoundOnServer: false,
password: localUser.password, password: localUser.password,
note: localUser.note, note: localUser.note,
@ -117,6 +112,7 @@ class UsersCubit extends ServerInstallationDependendCubit<UsersState> {
mergedUsers.add( mergedUsers.add(
User( User(
login: serverUser, login: serverUser,
type: UserType.normal,
isFoundOnServer: true, isFoundOnServer: true,
), ),
); );
@ -129,16 +125,14 @@ class UsersCubit extends ServerInstallationDependendCubit<UsersState> {
final List<User> updatedUsers = []; final List<User> updatedUsers = [];
for (final User user in users) { for (final User user in users) {
if (user.isFoundOnServer || if (user.isFoundOnServer || user.login == 'root' || user.login == state.primaryUser.login) {
user.login == 'root' || final ApiResponse<List<String>> sshKeys = await api.getUserSshKeys(user);
user.login == state.primaryUser.login) {
final ApiResponse<List<String>> sshKeys =
await api.getUserSshKeys(user);
print('sshKeys for $user: ${sshKeys.data}'); print('sshKeys for $user: ${sshKeys.data}');
if (sshKeys.isSuccess) { if (sshKeys.isSuccess) {
updatedUsers.add( updatedUsers.add(
User( User(
login: user.login, login: user.login,
type: user.type,
isFoundOnServer: true, isFoundOnServer: true,
password: user.password, password: user.password,
sshKeys: sshKeys.data, sshKeys: sshKeys.data,
@ -149,6 +143,7 @@ class UsersCubit extends ServerInstallationDependendCubit<UsersState> {
updatedUsers.add( updatedUsers.add(
User( User(
login: user.login, login: user.login,
type: user.type,
isFoundOnServer: true, isFoundOnServer: true,
password: user.password, password: user.password,
note: user.note, note: user.note,
@ -159,6 +154,7 @@ class UsersCubit extends ServerInstallationDependendCubit<UsersState> {
updatedUsers.add( updatedUsers.add(
User( User(
login: user.login, login: user.login,
type: user.type,
isFoundOnServer: false, isFoundOnServer: false,
password: user.password, password: user.password,
note: user.note, note: user.note,
@ -173,17 +169,14 @@ class UsersCubit extends ServerInstallationDependendCubit<UsersState> {
List<User> updatedUsers = List<User>.from(state.users); List<User> updatedUsers = List<User>.from(state.users);
final ApiResponse<List<String>> usersFromServer = await api.getUsersList(); final ApiResponse<List<String>> usersFromServer = await api.getUsersList();
if (usersFromServer.isSuccess) { if (usersFromServer.isSuccess) {
updatedUsers = updatedUsers = mergeLocalAndServerUsers(updatedUsers, usersFromServer.data);
mergeLocalAndServerUsers(updatedUsers, usersFromServer.data);
} }
final List<User> usersWithSshKeys = await loadSshKeys(updatedUsers); final List<User> usersWithSshKeys = await loadSshKeys(updatedUsers);
box.clear(); box.clear();
box.addAll(usersWithSshKeys); box.addAll(usersWithSshKeys);
final User rootUserWithSshKeys = final User rootUserWithSshKeys = (await loadSshKeys([state.rootUser])).first;
(await loadSshKeys([state.rootUser])).first;
serverInstallationBox.put(BNames.rootKeys, rootUserWithSshKeys.sshKeys); serverInstallationBox.put(BNames.rootKeys, rootUserWithSshKeys.sshKeys);
final User primaryUserWithSshKeys = final User primaryUserWithSshKeys = (await loadSshKeys([state.primaryUser])).first;
(await loadSshKeys([state.primaryUser])).first;
serverInstallationBox.put(BNames.rootUser, primaryUserWithSshKeys); serverInstallationBox.put(BNames.rootUser, primaryUserWithSshKeys);
emit( emit(
UsersState( UsersState(
@ -197,8 +190,7 @@ class UsersCubit extends ServerInstallationDependendCubit<UsersState> {
Future<void> createUser(final User user) async { Future<void> createUser(final User user) async {
// If user exists on server, do nothing // If user exists on server, do nothing
if (state.users if (state.users.any((final User u) => u.login == user.login && u.isFoundOnServer)) {
.any((final User u) => u.login == user.login && u.isFoundOnServer)) {
return; return;
} }
// If user is root or primary user, do nothing // 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); final ApiResponse<void> result = await api.addRootSshKey(publicKey);
if (result.isSuccess) { if (result.isSuccess) {
// Add ssh key to the array of root keys // Add ssh key to the array of root keys
final List<String> rootKeys = serverInstallationBox final List<String> rootKeys = serverInstallationBox.get(BNames.rootKeys, defaultValue: []) as List<String>;
.get(BNames.rootKeys, defaultValue: []) as List<String>;
rootKeys.add(publicKey); rootKeys.add(publicKey);
serverInstallationBox.put(BNames.rootKeys, rootKeys); serverInstallationBox.put(BNames.rootKeys, rootKeys);
emit( emit(
state.copyWith( state.copyWith(
rootUser: User( rootUser: User(
login: state.rootUser.login, login: state.rootUser.login,
type: UserType.root,
isFoundOnServer: true, isFoundOnServer: true,
password: state.rootUser.password, password: state.rootUser.password,
sshKeys: rootKeys, sshKeys: rootKeys,
@ -261,11 +253,11 @@ class UsersCubit extends ServerInstallationDependendCubit<UsersState> {
if (result.isSuccess) { if (result.isSuccess) {
// If it is primary user, update primary user // If it is primary user, update primary user
if (user.login == state.primaryUser.login) { if (user.login == state.primaryUser.login) {
final List<String> primaryUserKeys = final List<String> primaryUserKeys = List<String>.from(state.primaryUser.sshKeys);
List<String>.from(state.primaryUser.sshKeys);
primaryUserKeys.add(publicKey); primaryUserKeys.add(publicKey);
final User updatedUser = User( final User updatedUser = User(
login: state.primaryUser.login, login: state.primaryUser.login,
type: UserType.primary,
isFoundOnServer: true, isFoundOnServer: true,
password: state.primaryUser.password, password: state.primaryUser.password,
sshKeys: primaryUserKeys, sshKeys: primaryUserKeys,
@ -283,6 +275,7 @@ class UsersCubit extends ServerInstallationDependendCubit<UsersState> {
userKeys.add(publicKey); userKeys.add(publicKey);
final User updatedUser = User( final User updatedUser = User(
login: user.login, login: user.login,
type: UserType.normal,
isFoundOnServer: true, isFoundOnServer: true,
password: user.password, password: user.password,
sshKeys: userKeys, sshKeys: userKeys,
@ -302,22 +295,21 @@ class UsersCubit extends ServerInstallationDependendCubit<UsersState> {
Future<void> deleteSshKey(final User user, final String publicKey) async { Future<void> deleteSshKey(final User user, final String publicKey) async {
// All keys are deleted via api.deleteUserSshKey // All keys are deleted via api.deleteUserSshKey
final ApiResponse<void> result = final ApiResponse<void> result = await api.deleteUserSshKey(user, publicKey);
await api.deleteUserSshKey(user, publicKey);
if (result.isSuccess) { if (result.isSuccess) {
// If it is root user, delete key from root keys // If it is root user, delete key from root keys
// If it is primary user, update primary user // If it is primary user, update primary user
// If it is not primary user, update user // If it is not primary user, update user
if (user.login == 'root') { if (user.login == 'root') {
final List<String> rootKeys = serverInstallationBox final List<String> rootKeys = serverInstallationBox.get(BNames.rootKeys, defaultValue: []) as List<String>;
.get(BNames.rootKeys, defaultValue: []) as List<String>;
rootKeys.remove(publicKey); rootKeys.remove(publicKey);
serverInstallationBox.put(BNames.rootKeys, rootKeys); serverInstallationBox.put(BNames.rootKeys, rootKeys);
emit( emit(
state.copyWith( state.copyWith(
rootUser: User( rootUser: User(
login: state.rootUser.login, login: state.rootUser.login,
type: UserType.root,
isFoundOnServer: true, isFoundOnServer: true,
password: state.rootUser.password, password: state.rootUser.password,
sshKeys: rootKeys, sshKeys: rootKeys,
@ -328,11 +320,11 @@ class UsersCubit extends ServerInstallationDependendCubit<UsersState> {
return; return;
} }
if (user.login == state.primaryUser.login) { if (user.login == state.primaryUser.login) {
final List<String> primaryUserKeys = final List<String> primaryUserKeys = List<String>.from(state.primaryUser.sshKeys);
List<String>.from(state.primaryUser.sshKeys);
primaryUserKeys.remove(publicKey); primaryUserKeys.remove(publicKey);
final User updatedUser = User( final User updatedUser = User(
login: state.primaryUser.login, login: state.primaryUser.login,
type: UserType.primary,
isFoundOnServer: true, isFoundOnServer: true,
password: state.primaryUser.password, password: state.primaryUser.password,
sshKeys: primaryUserKeys, sshKeys: primaryUserKeys,
@ -350,6 +342,7 @@ class UsersCubit extends ServerInstallationDependendCubit<UsersState> {
userKeys.remove(publicKey); userKeys.remove(publicKey);
final User updatedUser = User( final User updatedUser = User(
login: user.login, login: user.login,
type: UserType.normal,
isFoundOnServer: true, isFoundOnServer: true,
password: user.password, password: user.password,
sshKeys: userKeys, sshKeys: userKeys,
@ -369,8 +362,8 @@ class UsersCubit extends ServerInstallationDependendCubit<UsersState> {
emit( emit(
const UsersState( const UsersState(
<User>[], <User>[],
User(login: 'root'), User(login: 'root', type: UserType.root),
User(login: 'loading...'), User(login: 'loading...', type: UserType.primary),
), ),
); );
} }

View File

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

View File

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