diff --git a/lib/logic/api_maps/graphql_maps/server_api/server.dart b/lib/logic/api_maps/graphql_maps/server_api/server.dart index 5fdf495a..31ee89fe 100644 --- a/lib/logic/api_maps/graphql_maps/server_api/server.dart +++ b/lib/logic/api_maps/graphql_maps/server_api/server.dart @@ -8,8 +8,12 @@ import 'package:selfprivacy/logic/api_maps/graphql_maps/schema/server_settings.g import 'package:selfprivacy/logic/api_maps/graphql_maps/schema/services.graphql.dart'; import 'package:selfprivacy/logic/api_maps/graphql_maps/schema/users.graphql.dart'; import 'package:selfprivacy/logic/models/auto_upgrade_settings.dart'; +import 'package:selfprivacy/logic/models/hive/backblaze_bucket.dart'; import 'package:selfprivacy/logic/models/hive/user.dart'; import 'package:selfprivacy/logic/models/json/api_token.dart'; +import 'package:selfprivacy/logic/models/json/backup.dart'; +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/server_disk_volume.dart'; import 'package:selfprivacy/logic/models/json/server_job.dart'; import 'package:selfprivacy/logic/models/service.dart'; @@ -43,12 +47,27 @@ class GenericJobMutationReturn extends GenericMutationResult { final ServerJob? job; } +@Deprecated( + 'Extend GenericMutationResult for mutations, return data for queries', +) +class ApiResponse { + ApiResponse({ + required this.success, + required this.data, + this.message, + }); + final bool success; + final String? message; + final D data; +} + class ServerApi extends ApiMap with VolumeApi, JobsApi, ServerActionsApi, ServicesApi, UsersApi { ServerApi({ this.hasLogger = false, this.isWithToken = true, this.customToken = '', + this.overrideDomain, }); @override @@ -58,7 +77,9 @@ class ServerApi extends ApiMap @override String customToken; @override - String? get rootAddress => getIt().serverDomain?.domainName; + String? get rootAddress => + overrideDomain ?? getIt().serverDomain?.domainName; + String? overrideDomain; Future getApiVersion() async { QueryResult response; @@ -94,25 +115,6 @@ class ServerApi extends ApiMap return usesBinds; } - Future> getApiTokens() async { - QueryResult response; - List tokens = []; - - try { - final GraphQLClient client = await getClient(); - response = await client.query$GetApiTokens(); - if (response.hasException) { - print(response.exception.toString()); - } - tokens = response.data!['api']['devices'] - .map((final e) => ApiToken.fromJson(e)) - .toList(); - } catch (e) { - print(e); - } - return tokens; - } - Future switchService(final String uid, final bool needTurnOn) async { try { final GraphQLClient client = await getClient(); @@ -193,4 +195,334 @@ class ServerApi extends ApiMap return settings; } + + Future> getRecoveryTokenStatus() async { + RecoveryKeyStatus? key; + QueryResult response; + String? error; + + try { + final GraphQLClient client = await getClient(); + response = await client.query$RecoveryKey(); + if (response.hasException) { + print(response.exception.toString()); + error = response.exception.toString(); + } + key = RecoveryKeyStatus.fromGraphQL(response.parsedData!.api.recoveryKey); + } catch (e) { + print(e); + } + + return ApiResponse( + success: error == null, + data: key, + message: error, + ); + } + + Future> generateRecoveryToken( + final DateTime? expirationDate, + final int? numberOfUses, + ) async { + ApiResponse key; + QueryResult response; + + try { + final GraphQLClient client = await getClient(); + + final input = Input$RecoveryKeyLimitsInput( + expirationDate: expirationDate, + uses: numberOfUses, + ); + final variables = Variables$Mutation$GetNewRecoveryApiKey( + limits: input, + ); + final mutation = Options$Mutation$GetNewRecoveryApiKey( + variables: variables, + ); + response = await client.mutate$GetNewRecoveryApiKey( + mutation, + ); + if (response.hasException) { + print(response.exception.toString()); + key = ApiResponse( + success: false, + data: '', + message: response.exception.toString(), + ); + } + key = ApiResponse( + success: true, + data: response.parsedData!.getNewRecoveryApiKey.key!, + ); + } catch (e) { + print(e); + key = ApiResponse( + success: false, + data: '', + message: e.toString(), + ); + } + + return key; + } + + @Deprecated( + 'Server now aware of all required DNS records. More general approach has to be implemented', + ) + Future getDkim() async { + String? dkim; + QueryResult response; + + try { + final GraphQLClient client = await getClient(); + response = await client.query$DomainInfo(); + if (response.hasException) { + print(response.exception.toString()); + } + dkim = response.parsedData!.system.domainInfo.requiredDnsRecords + .firstWhere( + ( + final Query$DomainInfo$system$domainInfo$requiredDnsRecords + dnsRecord, + ) => + dnsRecord.name == 'selector._domainkey' && + dnsRecord.recordType == 'TXT', + ) + .content; + } catch (e) { + print(e); + } + + return dkim; + } + + Future>> getApiTokens() async { + ApiResponse> tokens; + QueryResult response; + + try { + final GraphQLClient client = await getClient(); + response = await client.query$GetApiTokens(); + if (response.hasException) { + final message = response.exception.toString(); + print(message); + tokens = ApiResponse>( + success: false, + data: [], + message: message, + ); + } + final List parsed = response.parsedData!.api.devices + .map( + ( + final Query$GetApiTokens$api$devices device, + ) => + ApiToken.fromGraphQL(device), + ) + .toList(); + tokens = ApiResponse>( + success: true, + data: parsed, + ); + } catch (e) { + print(e); + tokens = ApiResponse>( + success: false, + data: [], + message: e.toString(), + ); + } + + return tokens; + } + + Future> deleteApiToken(final String name) async { + ApiResponse returnable; + QueryResult response; + + try { + final GraphQLClient client = await getClient(); + + final variables = Variables$Mutation$DeleteDeviceApiToken( + device: name, + ); + final mutation = Options$Mutation$DeleteDeviceApiToken( + variables: variables, + ); + response = await client.mutate$DeleteDeviceApiToken( + mutation, + ); + if (response.hasException) { + print(response.exception.toString()); + returnable = ApiResponse( + success: false, + data: null, + message: response.exception.toString(), + ); + } + returnable = ApiResponse( + success: true, + data: null, + ); + } catch (e) { + print(e); + returnable = ApiResponse( + success: false, + data: null, + message: e.toString(), + ); + } + + return returnable; + } + + Future> createDeviceToken() async { + ApiResponse token; + QueryResult response; + + try { + final GraphQLClient client = await getClient(); + + final mutation = Options$Mutation$GetNewDeviceApiKey(); + response = await client.mutate$GetNewDeviceApiKey( + mutation, + ); + if (response.hasException) { + print(response.exception.toString()); + token = ApiResponse( + success: false, + data: '', + message: response.exception.toString(), + ); + } + token = ApiResponse( + success: true, + data: response.parsedData!.getNewDeviceApiKey.key!, + ); + } catch (e) { + print(e); + token = ApiResponse( + success: false, + data: '', + message: e.toString(), + ); + } + + return token; + } + + Future isHttpServerWorking() async => (await getApiVersion()) != null; + + Future> authorizeDevice( + final DeviceToken deviceToken, + ) async { + ApiResponse token; + QueryResult response; + + try { + final GraphQLClient client = await getClient(); + + final input = Input$UseNewDeviceKeyInput( + deviceName: deviceToken.device, + key: deviceToken.token, + ); + + final variables = Variables$Mutation$AuthorizeWithNewDeviceApiKey( + input: input, + ); + final mutation = Options$Mutation$AuthorizeWithNewDeviceApiKey( + variables: variables, + ); + response = await client.mutate$AuthorizeWithNewDeviceApiKey( + mutation, + ); + if (response.hasException) { + print(response.exception.toString()); + token = ApiResponse( + success: false, + data: '', + message: response.exception.toString(), + ); + } + token = ApiResponse( + success: true, + data: response.parsedData!.authorizeWithNewDeviceApiKey.token!, + ); + } catch (e) { + print(e); + token = ApiResponse( + success: false, + data: '', + message: e.toString(), + ); + } + + return token; + } + + Future> useRecoveryToken( + final DeviceToken deviceToken, + ) async { + ApiResponse token; + QueryResult response; + + try { + final GraphQLClient client = await getClient(); + + final input = Input$UseRecoveryKeyInput( + deviceName: deviceToken.device, + key: deviceToken.token, + ); + + final variables = Variables$Mutation$UseRecoveryApiKey( + input: input, + ); + final mutation = Options$Mutation$UseRecoveryApiKey( + variables: variables, + ); + response = await client.mutate$UseRecoveryApiKey( + mutation, + ); + if (response.hasException) { + print(response.exception.toString()); + token = ApiResponse( + success: false, + data: '', + message: response.exception.toString(), + ); + } + token = ApiResponse( + success: true, + data: response.parsedData!.useRecoveryApiKey.token!, + ); + } catch (e) { + print(e); + token = ApiResponse( + success: false, + data: '', + message: e.toString(), + ); + } + + return token; + } + + /// TODO: backups're not implemented on server side + + Future getBackupStatus() async => BackupStatus( + progress: 0.0, + status: BackupStatusEnum.error, + errorMessage: null, + ); + + Future> getBackups() async => []; + + Future uploadBackblazeConfig(final BackblazeBucket bucket) async {} + + Future forceBackupListReload() async {} + + Future startBackup() async {} + + Future restoreBackup(final String backupId) async {} } diff --git a/lib/logic/api_maps/rest_maps/server.dart b/lib/logic/api_maps/rest_maps/server.dart deleted file mode 100644 index 67c88e05..00000000 --- a/lib/logic/api_maps/rest_maps/server.dart +++ /dev/null @@ -1,869 +0,0 @@ -import 'dart:async'; -import 'dart:convert'; -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/models/hive/backblaze_bucket.dart'; -import 'package:selfprivacy/logic/models/hive/server_domain.dart'; -import 'package:selfprivacy/logic/models/hive/user.dart'; -import 'package:selfprivacy/logic/models/json/api_token.dart'; -import 'package:selfprivacy/logic/models/json/backup.dart'; -import 'package:selfprivacy/logic/models/json/device_token.dart'; -import 'package:selfprivacy/logic/models/json/recovery_token_status.dart'; -import 'package:selfprivacy/logic/models/service.dart'; -import 'package:selfprivacy/logic/models/timezone_settings.dart'; - -class ApiResponse { - ApiResponse({ - required this.statusCode, - required this.data, - this.errorMessage, - }); - final int statusCode; - final String? errorMessage; - final D data; - - bool get isSuccess => statusCode >= 200 && statusCode < 300; -} - -class ServerApi extends ApiMap { - ServerApi({ - this.hasLogger = false, - this.isWithToken = true, - this.overrideDomain, - this.customToken, - }); - @override - bool hasLogger; - @override - bool isWithToken; - String? overrideDomain; - String? customToken; - - @override - BaseOptions get options { - BaseOptions options = BaseOptions( - connectTimeout: 10000, - receiveTimeout: 10000, - ); - - if (isWithToken) { - final ServerDomain? serverDomain = getIt().serverDomain; - final String domainName = serverDomain!.domainName; - final String? apiToken = getIt().serverDetails?.apiToken; - - options = BaseOptions( - baseUrl: 'https://api.$domainName', - connectTimeout: 10000, - receiveTimeout: 10000, - headers: { - 'Authorization': 'Bearer $apiToken', - }, - ); - } - - if (overrideDomain != null) { - options = BaseOptions( - baseUrl: 'https://api.$overrideDomain', - connectTimeout: 10000, - receiveTimeout: 10000, - headers: customToken != null - ? {'Authorization': 'Bearer $customToken'} - : null, - ); - } - - return options; - } - - Future getApiVersion() async { - Response response; - - final Dio client = await getClient(); - String? apiVersion; - - try { - response = await client.get('/api/version'); - apiVersion = response.data['version']; - } on DioError catch (e) { - print(e.message); - } finally { - close(client); - } - return apiVersion; - } - - Future isHttpServerWorking() async { - bool res = false; - Response response; - - final Dio client = await getClient(); - try { - response = await client.get('/services/status'); - res = response.statusCode == HttpStatus.ok; - } catch (e) { - print(e); - } finally { - close(client); - } - return res; - } - - Future> createUser(final User user) async { - Response response; - - final Dio client = await getClient(); - try { - response = await client.post( - '/users', - data: { - 'username': user.login, - 'password': user.password, - }, - ); - } on DioError catch (e) { - print(e.message); - return ApiResponse( - errorMessage: e.error.toString(), - statusCode: e.response?.statusCode ?? HttpStatus.internalServerError, - data: User( - login: user.login, - type: UserType.normal, - password: user.password, - isFoundOnServer: false, - ), - ); - } finally { - close(client); - } - - bool isFoundOnServer = false; - int code = 0; - - final bool isUserCreated = (response.statusCode != null) && - (response.statusCode == HttpStatus.created); - - if (isUserCreated) { - isFoundOnServer = true; - code = response.statusCode!; - } else { - isFoundOnServer = false; - code = HttpStatus.notAcceptable; - } - - return ApiResponse( - statusCode: code, - data: User( - login: user.login, - type: UserType.normal, - password: user.password, - isFoundOnServer: isFoundOnServer, - ), - ); - } - - Future>> getUsersList({ - final withMainUser = false, - }) async { - final List res = []; - Response response; - - final Dio client = await getClient(); - try { - response = await client.get( - '/users', - queryParameters: withMainUser ? {'withMainUser': 'true'} : null, - ); - for (final user in response.data) { - res.add(user.toString()); - } - } on DioError catch (e) { - print(e.message); - return ApiResponse( - errorMessage: e.message, - statusCode: e.response?.statusCode ?? HttpStatus.internalServerError, - data: [], - ); - } catch (e) { - print(e); - return ApiResponse( - errorMessage: e.toString(), - statusCode: HttpStatus.internalServerError, - data: [], - ); - } finally { - close(client); - } - - final int code = response.statusCode ?? HttpStatus.internalServerError; - - return ApiResponse( - statusCode: code, - data: res, - ); - } - - Future> addUserSshKey( - final User user, - final String sshKey, - ) async { - late Response response; - - final Dio client = await getClient(); - try { - response = await client.post( - '/services/ssh/keys/${user.login}', - data: { - 'public_key': sshKey, - }, - ); - } on DioError catch (e) { - print(e.message); - return ApiResponse( - errorMessage: e.message, - statusCode: e.response?.statusCode ?? HttpStatus.internalServerError, - data: null, - ); - } finally { - close(client); - } - - final int code = response.statusCode ?? HttpStatus.internalServerError; - - return ApiResponse( - statusCode: code, - data: null, - ); - } - - Future> addRootSshKey(final String ssh) async { - late Response response; - - final Dio client = await getClient(); - try { - response = await client.put( - '/services/ssh/key/send', - data: {'public_key': ssh}, - ); - } on DioError catch (e) { - print(e.message); - return ApiResponse( - errorMessage: e.message, - statusCode: e.response?.statusCode ?? HttpStatus.internalServerError, - data: null, - ); - } finally { - close(client); - } - - final int code = response.statusCode ?? HttpStatus.internalServerError; - - return ApiResponse( - statusCode: code, - data: null, - ); - } - - Future>> getUserSshKeys(final User user) async { - List res; - Response response; - - final Dio client = await getClient(); - try { - response = await client.get('/services/ssh/keys/${user.login}'); - res = (response.data as List) - .map((final e) => e as String) - .toList(); - } on DioError catch (e) { - print(e.message); - return ApiResponse>( - errorMessage: e.message, - statusCode: e.response?.statusCode ?? HttpStatus.internalServerError, - data: [], - ); - } catch (e) { - return ApiResponse>( - errorMessage: e.toString(), - statusCode: HttpStatus.internalServerError, - data: [], - ); - } finally { - close(client); - } - - final int code = response.statusCode ?? HttpStatus.internalServerError; - - return ApiResponse>( - statusCode: code, - data: res, - errorMessage: response.data is List - ? null - : response.data?.containsKey('error') ?? false - ? response.data['error'] - : null, - ); - } - - Future> deleteUserSshKey( - final User user, - final String sshKey, - ) async { - Response response; - - final Dio client = await getClient(); - try { - response = await client.delete( - '/services/ssh/keys/${user.login}', - data: {'public_key': sshKey}, - ); - } on DioError catch (e) { - print(e.message); - return ApiResponse( - errorMessage: e.message, - statusCode: e.response?.statusCode ?? HttpStatus.internalServerError, - data: null, - ); - } finally { - close(client); - } - - final int code = response.statusCode ?? HttpStatus.internalServerError; - - return ApiResponse( - statusCode: code, - data: null, - errorMessage: response.data?.containsKey('error') ?? false - ? response.data['error'] - : null, - ); - } - - Future deleteUser(final User user) async { - bool res = false; - Response response; - - final Dio client = await getClient(); - try { - response = await client.delete('/users/${user.login}'); - res = response.statusCode == HttpStatus.ok || - response.statusCode == HttpStatus.notFound; - } on DioError catch (e) { - print(e.message); - res = false; - } finally { - close(client); - } - return res; - } - - @override - String get rootAddress => - throw UnimplementedError('not used in with implementation'); - - Future apply() async { - bool res = false; - Response response; - - final Dio client = await getClient(); - try { - response = await client.get('/system/configuration/apply'); - res = response.statusCode == HttpStatus.ok; - } on DioError catch (e) { - print(e.message); - res = false; - } finally { - close(client); - } - return res; - } - - Future switchService( - final Service service, - final bool needToTurnOn, - ) async { - final Dio client = await getClient(); - try { - client.post( - '/services/${service.id}/${needToTurnOn ? 'enable' : 'disable'}', - ); - } on DioError catch (e) { - print(e.message); - } finally { - close(client); - } - } - - Future> servicesPowerCheck() async { - Response response; - - final Dio client = await getClient(); - try { - response = await client.get('/services/status'); - } on DioError catch (e) { - print(e.message); - return {}; - } finally { - close(client); - } - - return { - 'bitwarden': response.data['bitwarden'] == 0, - 'gitea': response.data['gitea'] == 0, - 'nextcloud': response.data['nextcloud'] == 0, - 'ocserv': response.data['ocserv'] == 0, - 'pleroma': response.data['pleroma'] == 0, - }; - } - - Future uploadBackblazeConfig(final BackblazeBucket bucket) async { - final Dio client = await getClient(); - try { - client.put( - '/services/restic/backblaze/config', - data: { - 'accountId': bucket.applicationKeyId, - 'accountKey': bucket.applicationKey, - 'bucket': bucket.bucketName, - }, - ); - } on DioError catch (e) { - print(e.message); - } finally { - close(client); - } - } - - Future startBackup() async { - final Dio client = await getClient(); - try { - client.put('/services/restic/backup/create'); - } on DioError catch (e) { - print(e.message); - } finally { - close(client); - } - } - - Future> getBackups() async { - Response response; - List backups = []; - - final Dio client = await getClient(); - try { - response = await client.get('/services/restic/backup/list'); - backups = - response.data.map((final e) => Backup.fromJson(e)).toList(); - } on DioError catch (e) { - print(e.message); - } catch (e) { - print(e); - } finally { - close(client); - } - return backups; - } - - Future getBackupStatus() async { - Response response; - BackupStatus status = BackupStatus( - status: BackupStatusEnum.error, - errorMessage: 'Network error', - progress: 0, - ); - - final Dio client = await getClient(); - try { - response = await client.get('/services/restic/backup/status'); - status = BackupStatus.fromJson(response.data); - } on DioError catch (e) { - print(e.message); - } finally { - close(client); - } - return status; - } - - Future forceBackupListReload() async { - final Dio client = await getClient(); - try { - client.get('/services/restic/backup/reload'); - } on DioError catch (e) { - print(e.message); - } finally { - close(client); - } - } - - Future restoreBackup(final String backupId) async { - final Dio client = await getClient(); - try { - client.put( - '/services/restic/backup/restore', - data: {'backupId': backupId}, - ); - } on DioError catch (e) { - print(e.message); - } finally { - close(client); - } - } - - Future pullConfigurationUpdate() async { - Response response; - bool result = false; - - final Dio client = await getClient(); - try { - response = await client.get('/system/configuration/pull'); - result = (response.statusCode != null) - ? (response.statusCode == HttpStatus.ok) - : false; - } on DioError catch (e) { - print(e.message); - } finally { - close(client); - } - return result; - } - - Future reboot() async { - Response response; - bool result = false; - - final Dio client = await getClient(); - try { - response = await client.get('/system/reboot'); - result = (response.statusCode != null) - ? (response.statusCode == HttpStatus.ok) - : false; - } on DioError catch (e) { - print(e.message); - } finally { - close(client); - } - return result; - } - - Future upgrade() async { - Response response; - bool result = false; - - final Dio client = await getClient(); - try { - response = await client.get('/system/configuration/upgrade'); - result = (response.statusCode != null) - ? (response.statusCode == HttpStatus.ok) - : false; - } on DioError catch (e) { - print(e.message); - } finally { - close(client); - } - return result; - } - - Future getServerTimezone() async { - TimeZoneSettings settings = TimeZoneSettings(); - final Dio client = await getClient(); - try { - final Response response = await client.get( - '/system/configuration/timezone', - ); - settings = TimeZoneSettings.fromString(response.data); - } catch (e) { - print(e); - } finally { - close(client); - } - - return settings; - } - - Future updateServerTimezone(final TimeZoneSettings settings) async { - final Dio client = await getClient(); - try { - await client.put( - '/system/configuration/timezone', - data: settings.toString(), - ); - } on DioError catch (e) { - print(e.message); - } finally { - close(client); - } - } - - Future getDkim() async { - Response response; - String? dkim; - final Dio client = await getClient(); - try { - response = await client.get('/services/mailserver/dkim'); - final Codec base64toString = utf8.fuse(base64); - dkim = base64toString - .decode(response.data) - .split('(')[1] - .split(')')[0] - .replaceAll('"', ''); - } on DioError catch (e) { - print(e.message); - } finally { - close(client); - } - - return dkim; - } - - Future> getRecoveryTokenStatus() async { - Response response; - - final Dio client = await getClient(); - try { - response = await client.get('/auth/recovery_token'); - } on DioError catch (e) { - print(e.message); - return ApiResponse( - errorMessage: e.message, - statusCode: e.response?.statusCode ?? HttpStatus.internalServerError, - data: const RecoveryKeyStatus(exists: false, valid: false), - ); - } finally { - close(client); - } - - final int code = response.statusCode ?? HttpStatus.internalServerError; - - return ApiResponse( - statusCode: code, - data: response.data != null - ? RecoveryKeyStatus.fromJson(response.data) - : null, - ); - } - - Future> generateRecoveryToken( - final DateTime? expiration, - final int? uses, - ) async { - Response response; - - final Dio client = await getClient(); - final Map data = {}; - if (expiration != null) { - data['expiration'] = '${expiration.toIso8601String()}Z'; - print(data['expiration']); - } - if (uses != null) { - data['uses'] = uses; - } - try { - response = await client.post( - '/auth/recovery_token', - data: data, - ); - } on DioError catch (e) { - print(e.message); - return ApiResponse( - errorMessage: e.message, - statusCode: e.response?.statusCode ?? HttpStatus.internalServerError, - data: '', - ); - } finally { - close(client); - } - - final int code = response.statusCode ?? HttpStatus.internalServerError; - - return ApiResponse( - statusCode: code, - data: response.data != null ? response.data['token'] : '', - ); - } - - Future> useRecoveryToken(final DeviceToken token) async { - Response response; - - final Dio client = await getClient(); - try { - response = await client.post( - '/auth/recovery_token/use', - data: { - 'token': token.token, - 'device': token.device, - }, - ); - } on DioError catch (e) { - print(e.message); - return ApiResponse( - errorMessage: e.message, - statusCode: e.response?.statusCode ?? HttpStatus.internalServerError, - data: '', - ); - } finally { - client.close(); - } - - final int code = response.statusCode ?? HttpStatus.internalServerError; - - return ApiResponse( - statusCode: code, - data: response.data != null ? response.data['token'] : '', - ); - } - - Future> authorizeDevice(final DeviceToken token) async { - Response response; - - final Dio client = await getClient(); - try { - response = await client.post( - '/auth/new_device/authorize', - data: { - 'token': token.token, - 'device': token.device, - }, - ); - } on DioError catch (e) { - print(e.message); - return ApiResponse( - errorMessage: e.message, - statusCode: e.response?.statusCode ?? HttpStatus.internalServerError, - data: '', - ); - } finally { - client.close(); - } - - final int code = response.statusCode ?? HttpStatus.internalServerError; - - return ApiResponse(statusCode: code, data: response.data['token'] ?? ''); - } - - Future> createDeviceToken() async { - Response response; - - final Dio client = await getClient(); - try { - response = await client.post('/auth/new_device'); - } on DioError catch (e) { - print(e.message); - return ApiResponse( - errorMessage: e.message, - statusCode: e.response?.statusCode ?? HttpStatus.internalServerError, - data: '', - ); - } finally { - client.close(); - } - - final int code = response.statusCode ?? HttpStatus.internalServerError; - - return ApiResponse( - statusCode: code, - data: response.data != null ? response.data['token'] : '', - ); - } - - Future> deleteDeviceToken() async { - Response response; - - final Dio client = await getClient(); - try { - response = await client.delete('/auth/new_device'); - } on DioError catch (e) { - print(e.message); - return ApiResponse( - errorMessage: e.message, - statusCode: e.response?.statusCode ?? HttpStatus.internalServerError, - data: '', - ); - } finally { - client.close(); - } - - final int code = response.statusCode ?? HttpStatus.internalServerError; - - return ApiResponse(statusCode: code, data: response.data ?? ''); - } - - Future>> getApiTokens() async { - Response response; - - final Dio client = await getClient(); - try { - response = await client.get('/auth/tokens'); - } on DioError catch (e) { - print(e.message); - return ApiResponse( - errorMessage: e.message, - statusCode: e.response?.statusCode ?? HttpStatus.internalServerError, - data: [], - ); - } finally { - client.close(); - } - - final int code = response.statusCode ?? HttpStatus.internalServerError; - - return ApiResponse( - statusCode: code, - data: (response.data != null) - ? response.data - .map((final e) => ApiToken.fromJson(e)) - .toList() - : [], - ); - } - - Future> refreshCurrentApiToken() async { - Response response; - - final Dio client = await getClient(); - try { - response = await client.post('/auth/tokens'); - } on DioError catch (e) { - print(e.message); - return ApiResponse( - errorMessage: e.message, - statusCode: e.response?.statusCode ?? HttpStatus.internalServerError, - data: '', - ); - } finally { - client.close(); - } - - final int code = response.statusCode ?? HttpStatus.internalServerError; - - return ApiResponse( - statusCode: code, - data: response.data != null ? response.data['token'] : '', - ); - } - - Future> deleteApiToken(final String device) async { - Response response; - final Dio client = await getClient(); - try { - response = await client.delete( - '/auth/tokens', - data: { - 'token_name': device, - }, - ); - } on DioError catch (e) { - print(e.message); - return ApiResponse( - errorMessage: e.message, - statusCode: e.response?.statusCode ?? HttpStatus.internalServerError, - data: null, - ); - } finally { - client.close(); - } - - final int code = response.statusCode ?? HttpStatus.internalServerError; - return ApiResponse(statusCode: code, data: null); - } -} diff --git a/lib/logic/cubit/backups/backups_cubit.dart b/lib/logic/cubit/backups/backups_cubit.dart index 084a2b47..5f72f2e2 100644 --- a/lib/logic/cubit/backups/backups_cubit.dart +++ b/lib/logic/cubit/backups/backups_cubit.dart @@ -3,7 +3,7 @@ import 'dart:async'; import 'package:easy_localization/easy_localization.dart'; import 'package:selfprivacy/config/get_it_config.dart'; import 'package:selfprivacy/logic/api_maps/rest_maps/backblaze.dart'; -import 'package:selfprivacy/logic/api_maps/rest_maps/server.dart'; +import 'package:selfprivacy/logic/api_maps/graphql_maps/server_api/server.dart'; import 'package:selfprivacy/logic/cubit/app_config_dependent/authentication_dependend_cubit.dart'; import 'package:selfprivacy/logic/models/hive/backblaze_bucket.dart'; import 'package:selfprivacy/logic/models/json/backup.dart'; diff --git a/lib/logic/cubit/devices/devices_cubit.dart b/lib/logic/cubit/devices/devices_cubit.dart index 6aa71400..3c552c23 100644 --- a/lib/logic/cubit/devices/devices_cubit.dart +++ b/lib/logic/cubit/devices/devices_cubit.dart @@ -1,5 +1,5 @@ import 'package:selfprivacy/config/get_it_config.dart'; -import 'package:selfprivacy/logic/api_maps/rest_maps/server.dart'; +import 'package:selfprivacy/logic/api_maps/graphql_maps/server_api/server.dart'; import 'package:selfprivacy/logic/common_enum/common_enum.dart'; import 'package:selfprivacy/logic/cubit/app_config_dependent/authentication_dependend_cubit.dart'; import 'package:selfprivacy/logic/models/json/api_token.dart'; @@ -36,7 +36,7 @@ class ApiDevicesCubit Future?> _getApiTokens() async { final ApiResponse> response = await api.getApiTokens(); - if (response.isSuccess) { + if (response.success) { return response.data; } else { return null; @@ -45,7 +45,7 @@ class ApiDevicesCubit Future deleteDevice(final ApiToken device) async { final ApiResponse response = await api.deleteApiToken(device.name); - if (response.isSuccess) { + if (response.success) { emit( ApiDevicesState( state.devices.where((final d) => d.name != device.name).toList(), @@ -54,17 +54,17 @@ class ApiDevicesCubit ); } else { getIt() - .showSnackBar(response.errorMessage ?? 'Error deleting device'); + .showSnackBar(response.message ?? 'Error deleting device'); } } Future getNewDeviceKey() async { final ApiResponse response = await api.createDeviceToken(); - if (response.isSuccess) { + if (response.success) { return response.data; } else { getIt().showSnackBar( - response.errorMessage ?? 'Error getting new device key', + response.message ?? 'Error getting new device key', ); return null; } diff --git a/lib/logic/cubit/dns_records/dns_records_cubit.dart b/lib/logic/cubit/dns_records/dns_records_cubit.dart index f1c41351..059ed230 100644 --- a/lib/logic/cubit/dns_records/dns_records_cubit.dart +++ b/lib/logic/cubit/dns_records/dns_records_cubit.dart @@ -7,7 +7,7 @@ import 'package:selfprivacy/logic/cubit/app_config_dependent/authentication_depe import 'package:selfprivacy/logic/models/hive/server_domain.dart'; import 'package:selfprivacy/logic/models/json/dns_records.dart'; -import 'package:selfprivacy/logic/api_maps/rest_maps/server.dart'; +import 'package:selfprivacy/logic/api_maps/graphql_maps/server_api/server.dart'; part 'dns_records_state.dart'; diff --git a/lib/logic/cubit/forms/setup/recovering/recovery_domain_form_cubit.dart b/lib/logic/cubit/forms/setup/recovering/recovery_domain_form_cubit.dart index 400fdff4..dbfc7259 100644 --- a/lib/logic/cubit/forms/setup/recovering/recovery_domain_form_cubit.dart +++ b/lib/logic/cubit/forms/setup/recovering/recovery_domain_form_cubit.dart @@ -2,7 +2,7 @@ import 'dart:async'; import 'package:cubit_form/cubit_form.dart'; import 'package:easy_localization/easy_localization.dart'; -import 'package:selfprivacy/logic/api_maps/rest_maps/server.dart'; +import 'package:selfprivacy/logic/api_maps/graphql_maps/server_api/server.dart'; import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart'; import 'package:selfprivacy/logic/cubit/forms/factories/field_cubit_factory.dart'; diff --git a/lib/logic/cubit/recovery_key/recovery_key_cubit.dart b/lib/logic/cubit/recovery_key/recovery_key_cubit.dart index 9692ca4b..90f5330d 100644 --- a/lib/logic/cubit/recovery_key/recovery_key_cubit.dart +++ b/lib/logic/cubit/recovery_key/recovery_key_cubit.dart @@ -1,4 +1,4 @@ -import 'package:selfprivacy/logic/api_maps/rest_maps/server.dart'; +import 'package:selfprivacy/logic/api_maps/graphql_maps/server_api/server.dart'; import 'package:selfprivacy/logic/common_enum/common_enum.dart'; import 'package:selfprivacy/logic/cubit/app_config_dependent/authentication_dependend_cubit.dart'; import 'package:selfprivacy/logic/models/json/recovery_token_status.dart'; @@ -34,7 +34,7 @@ class RecoveryKeyCubit Future _getRecoveryKeyStatus() async { final ApiResponse response = await api.getRecoveryTokenStatus(); - if (response.isSuccess) { + if (response.success) { return response.data; } else { return null; @@ -59,11 +59,11 @@ class RecoveryKeyCubit }) async { final ApiResponse response = await api.generateRecoveryToken(expirationDate, numberOfUses); - if (response.isSuccess) { + if (response.success) { refresh(); return response.data; } else { - throw GenerationError(response.errorMessage ?? 'Unknown error'); + throw GenerationError(response.message ?? 'Unknown error'); } } diff --git a/lib/logic/cubit/server_installation/server_installation_repository.dart b/lib/logic/cubit/server_installation/server_installation_repository.dart index 9946482d..9d0145f5 100644 --- a/lib/logic/cubit/server_installation/server_installation_repository.dart +++ b/lib/logic/cubit/server_installation/server_installation_repository.dart @@ -14,7 +14,7 @@ import 'package:selfprivacy/logic/api_maps/rest_maps/api_factory_settings.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_api_settings.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/graphql_maps/server_api/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/cubit/server_installation/server_installation_cubit.dart'; @@ -514,7 +514,7 @@ class ServerInstallationRepository { DeviceToken(device: await getDeviceName(), token: newDeviceKey), ); - if (apiResponse.isSuccess) { + if (apiResponse.success) { return ServerHostingDetails( apiToken: apiResponse.data, volume: ServerVolume( @@ -533,7 +533,7 @@ class ServerInstallationRepository { } throw ServerAuthorizationException( - apiResponse.errorMessage ?? apiResponse.data, + apiResponse.message ?? apiResponse.data, ); } @@ -551,7 +551,7 @@ class ServerInstallationRepository { DeviceToken(device: await getDeviceName(), token: recoveryKey), ); - if (apiResponse.isSuccess) { + if (apiResponse.success) { return ServerHostingDetails( apiToken: apiResponse.data, volume: ServerVolume( @@ -570,7 +570,7 @@ class ServerInstallationRepository { } throw ServerAuthorizationException( - apiResponse.errorMessage ?? apiResponse.data, + apiResponse.message ?? apiResponse.data, ); } @@ -586,9 +586,7 @@ class ServerInstallationRepository { ); final String serverIp = await getServerIpFromDomain(serverDomain); if (recoveryCapabilities == ServerRecoveryCapabilities.legacy) { - final Map apiResponse = - await serverApi.servicesPowerCheck(); - if (apiResponse.isNotEmpty) { + if (await serverApi.isHttpServerWorking()) { return ServerHostingDetails( apiToken: apiToken, volume: ServerVolume( @@ -616,7 +614,7 @@ class ServerInstallationRepository { DeviceToken(device: await getDeviceName(), token: deviceAuthKey.data), ); - if (apiResponse.isSuccess) { + if (apiResponse.success) { return ServerHostingDetails( apiToken: apiResponse.data, volume: ServerVolume( @@ -635,7 +633,7 @@ class ServerInstallationRepository { } throw ServerAuthorizationException( - apiResponse.errorMessage ?? apiResponse.data, + apiResponse.message ?? apiResponse.data, ); } @@ -650,9 +648,8 @@ class ServerInstallationRepository { ); final String? serverApiVersion = await serverApi.getApiVersion(); - final ApiResponse> users = - await serverApi.getUsersList(withMainUser: true); - if (serverApiVersion == null || !users.isSuccess) { + final users = await serverApi.getAllUsers(); + if (serverApiVersion == null || users.isEmpty) { return fallbackUser; } try { @@ -660,10 +657,8 @@ class ServerInstallationRepository { if (!VersionConstraint.parse('>=1.2.5').allows(parsedVersion)) { return fallbackUser; } - return User( - isFoundOnServer: true, - login: users.data[0], - type: UserType.primary, + return users.firstWhere( + (final User user) => user.type == UserType.primary, ); } on FormatException { return fallbackUser; diff --git a/lib/logic/models/json/api_token.dart b/lib/logic/models/json/api_token.dart index 980d5132..f53f7f02 100644 --- a/lib/logic/models/json/api_token.dart +++ b/lib/logic/models/json/api_token.dart @@ -1,4 +1,5 @@ import 'package:json_annotation/json_annotation.dart'; +import 'package:selfprivacy/logic/api_maps/graphql_maps/schema/server_api.graphql.dart'; part 'api_token.g.dart'; @@ -12,6 +13,14 @@ class ApiToken { required this.isCaller, }); + ApiToken.fromGraphQL( + final Query$GetApiTokens$api$devices device, + ) : this( + name: device.name, + date: device.creationDate, + isCaller: device.isCaller, + ); + final String name; final DateTime date; @JsonKey(name: 'is_caller') diff --git a/lib/logic/models/json/recovery_token_status.dart b/lib/logic/models/json/recovery_token_status.dart index 6e59b57d..b56ae4e6 100644 --- a/lib/logic/models/json/recovery_token_status.dart +++ b/lib/logic/models/json/recovery_token_status.dart @@ -1,5 +1,6 @@ import 'package:equatable/equatable.dart'; import 'package:json_annotation/json_annotation.dart'; +import 'package:selfprivacy/logic/api_maps/graphql_maps/schema/server_api.graphql.dart'; part 'recovery_token_status.g.dart'; @@ -15,6 +16,16 @@ class RecoveryKeyStatus extends Equatable { this.usesLeft, }); + RecoveryKeyStatus.fromGraphQL( + final Query$RecoveryKey$api$recoveryKey recoveryKey, + ) : this( + exists: recoveryKey.exists, + date: recoveryKey.creationDate, + expiration: recoveryKey.expirationDate, + usesLeft: recoveryKey.usesLeft, + valid: recoveryKey.valid, + ); + final bool exists; final DateTime? date; final DateTime? expiration;