diff --git a/lib/logic/api_maps/server.dart b/lib/logic/api_maps/server.dart index 6302611e..7554f46b 100644 --- a/lib/logic/api_maps/server.dart +++ b/lib/logic/api_maps/server.dart @@ -5,9 +5,12 @@ import 'dart:io'; import 'package:dio/dio.dart'; import 'package:selfprivacy/config/get_it_config.dart'; import 'package:selfprivacy/logic/common_enum/common_enum.dart'; +import 'package:selfprivacy/logic/models/api_token.dart'; import 'package:selfprivacy/logic/models/auto_upgrade_settings.dart'; import 'package:selfprivacy/logic/models/backblaze_bucket.dart'; import 'package:selfprivacy/logic/models/backup.dart'; +import 'package:selfprivacy/logic/models/recovery_token_status.dart'; +import 'package:selfprivacy/logic/models/device_token.dart'; import 'package:selfprivacy/logic/models/timezone_settings.dart'; import 'package:selfprivacy/logic/models/user.dart'; @@ -431,6 +434,244 @@ class ServerApi extends ApiMap { .split(')')[0] .replaceAll('"', ''); } + + Future> getRecoveryTokenStatus() async { + var client = await getClient(); + Response response = await client.get( + '/auth/recovery_token', + options: Options( + contentType: 'application/json', + receiveDataWhenStatusError: true, + followRedirects: false, + validateStatus: (status) { + return (status != null) && + (status < HttpStatus.internalServerError); + }), + ); + client.close(); + + if (response.statusCode != null) { + return ApiResponse( + statusCode: response.statusCode!, + data: response.data != null + ? response.data.fromJson(response.data) + : null); + } + + return ApiResponse( + statusCode: HttpStatus.internalServerError, + data: RecoveryTokenStatus(exists: false, valid: false)); + } + + Future> generateRecoveryToken( + DateTime expiration, int uses) async { + var client = await getClient(); + Response response = await client.post( + '/auth/recovery_token', + data: { + 'expiration': expiration.toIso8601String(), + 'uses': uses, + }, + options: Options( + contentType: 'application/json', + receiveDataWhenStatusError: true, + followRedirects: false, + validateStatus: (status) { + return (status != null) && + (status < HttpStatus.internalServerError); + }), + ); + client.close(); + + if (response.statusCode != null) { + return ApiResponse( + statusCode: response.statusCode!, + data: response.data != null ? response.data["token"] : ''); + } + + return ApiResponse(statusCode: HttpStatus.internalServerError, data: ''); + } + + Future> useRecoveryToken(DeviceToken token) async { + var client = await getClient(); + Response response = await client.post( + '/auth/recovery_token/use', + data: { + 'token': token.token, + 'device': token.device, + }, + options: Options( + contentType: 'application/json', + receiveDataWhenStatusError: true, + followRedirects: false, + validateStatus: (status) { + return (status != null) && + (status < HttpStatus.internalServerError); + }), + ); + client.close(); + + if (response.statusCode != null) { + return ApiResponse( + statusCode: response.statusCode!, + data: response.data != null ? response.data["token"] : ''); + } + + return ApiResponse(statusCode: HttpStatus.internalServerError, data: ''); + } + + Future> authorizeDevice(DeviceToken token) async { + var client = await getClient(); + Response response = await client.post( + '/auth/new_device/authorize', + data: { + 'token': token.token, + 'device': token.device, + }, + options: Options( + contentType: 'application/json', + receiveDataWhenStatusError: true, + followRedirects: false, + validateStatus: (status) { + return (status != null) && + (status < HttpStatus.internalServerError); + }), + ); + client.close(); + + if (response.statusCode != null) { + return ApiResponse( + statusCode: response.statusCode!, + data: response.data != null ? response.data : ''); + } + + return ApiResponse(statusCode: HttpStatus.internalServerError, data: ''); + } + + Future> createDeviceToken() async { + var client = await getClient(); + Response response = await client.post( + '/auth/new_device', + options: Options( + contentType: 'application/json', + receiveDataWhenStatusError: true, + followRedirects: false, + validateStatus: (status) { + return (status != null) && + (status < HttpStatus.internalServerError); + }), + ); + client.close(); + + if (response.statusCode != null) { + return ApiResponse( + statusCode: response.statusCode!, + data: response.data != null ? response.data["token"] : ''); + } + + return ApiResponse(statusCode: HttpStatus.internalServerError, data: ''); + } + + Future> deleteDeviceToken() async { + var client = await getClient(); + Response response = await client.delete( + '/auth/new_device', + options: Options( + contentType: 'application/json', + receiveDataWhenStatusError: true, + followRedirects: false, + validateStatus: (status) { + return (status != null) && + (status < HttpStatus.internalServerError); + }), + ); + client.close(); + + if (response.statusCode != null) { + return ApiResponse( + statusCode: response.statusCode!, + data: response.data != null ? response.data : ''); + } + + return ApiResponse(statusCode: HttpStatus.internalServerError, data: ''); + } + + Future>> getApiTokens() async { + var client = await getClient(); + Response response = await client.get( + '/auth/tokens', + options: Options( + contentType: 'application/json', + receiveDataWhenStatusError: true, + followRedirects: false, + validateStatus: (status) { + return (status != null) && + (status < HttpStatus.internalServerError); + }), + ); + client.close(); + + if (response.statusCode != null) { + return ApiResponse( + statusCode: response.statusCode!, + data: (response.data != null) + ? response.data + .map((e) => ApiToken.fromJson(e)) + .toList() + : []); + } + + return ApiResponse(statusCode: HttpStatus.internalServerError, data: []); + } + + Future> refreshCurrentApiToken() async { + var client = await getClient(); + Response response = await client.post( + '/auth/tokens', + options: Options( + contentType: 'application/json', + receiveDataWhenStatusError: true, + followRedirects: false, + validateStatus: (status) { + return (status != null) && + (status < HttpStatus.internalServerError); + }), + ); + client.close(); + + if (response.statusCode != null) { + return ApiResponse( + statusCode: response.statusCode!, + data: (response.data != null) ? response.data["token"] : ''); + } + + return ApiResponse(statusCode: HttpStatus.internalServerError, data: ''); + } + + Future> deleteApiToken(String device) async { + var client = await getClient(); + Response response = await client.delete( + '/auth/tokens', + data: { + 'device': device, + }, + options: Options( + contentType: 'application/json', + receiveDataWhenStatusError: true, + followRedirects: false, + validateStatus: (status) { + return (status != null) && + (status < HttpStatus.internalServerError); + }), + ); + client.close(); + + if (response.statusCode != null) { + return ApiResponse(statusCode: response.statusCode!, data: null); + } + + return ApiResponse(statusCode: HttpStatus.internalServerError, data: null); + } } extension UrlServerExt on ServiceTypes { diff --git a/lib/logic/models/api_token.dart b/lib/logic/models/api_token.dart new file mode 100644 index 00000000..25556399 --- /dev/null +++ b/lib/logic/models/api_token.dart @@ -0,0 +1,20 @@ +import 'package:easy_localization/easy_localization.dart'; +import 'package:json_annotation/json_annotation.dart'; + +part 'api_token.g.dart'; + +@JsonSerializable() +class ApiToken { + ApiToken({ + required this.name, + required this.date, + required this.is_caller, + }); + + final String name; + final DateTime date; + final bool is_caller; + + factory ApiToken.fromJson(Map json) => + _$ApiTokenFromJson(json); +} diff --git a/lib/logic/models/api_token.g.dart b/lib/logic/models/api_token.g.dart new file mode 100644 index 00000000..c009f58b --- /dev/null +++ b/lib/logic/models/api_token.g.dart @@ -0,0 +1,13 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'api_token.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +ApiToken _$ApiTokenFromJson(Map json) => ApiToken( + name: json['name'] as String, + date: DateTime.parse(json['date'] as String), + is_caller: json['is_caller'] as bool, + ); diff --git a/lib/logic/models/device_token.dart b/lib/logic/models/device_token.dart new file mode 100644 index 00000000..d53299c5 --- /dev/null +++ b/lib/logic/models/device_token.dart @@ -0,0 +1,17 @@ +import 'package:json_annotation/json_annotation.dart'; + +part 'device_token.g.dart'; + +@JsonSerializable() +class DeviceToken { + DeviceToken({ + required this.device, + required this.token, + }); + + final String device; + final String token; + + factory DeviceToken.fromJson(Map json) => + _$DeviceTokenFromJson(json); +} diff --git a/lib/logic/models/device_token.g.dart b/lib/logic/models/device_token.g.dart new file mode 100644 index 00000000..efe976c5 --- /dev/null +++ b/lib/logic/models/device_token.g.dart @@ -0,0 +1,12 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'device_token.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +DeviceToken _$DeviceTokenFromJson(Map json) => DeviceToken( + device: json['device'] as String, + token: json['token'] as String, + ); diff --git a/lib/logic/models/recovery_token_status.dart b/lib/logic/models/recovery_token_status.dart new file mode 100644 index 00000000..9c94b41a --- /dev/null +++ b/lib/logic/models/recovery_token_status.dart @@ -0,0 +1,23 @@ +import 'package:json_annotation/json_annotation.dart'; + +part 'recovery_token_status.g.dart'; + +@JsonSerializable() +class RecoveryTokenStatus { + RecoveryTokenStatus({ + required this.exists, + required this.valid, + this.date, + this.expiration, + this.uses_left, + }); + + final bool exists; + final DateTime? date; + final DateTime? expiration; + final int? uses_left; + final bool valid; + + factory RecoveryTokenStatus.fromJson(Map json) => + _$RecoveryTokenStatusFromJson(json); +} diff --git a/lib/logic/models/recovery_token_status.g.dart b/lib/logic/models/recovery_token_status.g.dart new file mode 100644 index 00000000..3f213364 --- /dev/null +++ b/lib/logic/models/recovery_token_status.g.dart @@ -0,0 +1,19 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'recovery_token_status.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +RecoveryTokenStatus _$RecoveryTokenStatusFromJson(Map json) => + RecoveryTokenStatus( + exists: json['exists'] as bool, + valid: json['valid'] as bool, + date: + json['date'] == null ? null : DateTime.parse(json['date'] as String), + expiration: json['expiration'] == null + ? null + : DateTime.parse(json['expiration'] as String), + uses_left: json['uses_left'] as int?, + );