mirror of
https://github.com/Xevion/paperless-mobile.git
synced 2025-12-11 00:07:59 -06:00
feat: Rework error handling, upgrade dio, fixed bugs
- Fix grey screen bug when adding labels from documnet upload - Add more permission checks to conditionally show widgets
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
import 'package:dio/dio.dart';
|
||||
|
||||
extension DioExceptionUnravelExtension on DioException {
|
||||
Object unravel({Object? orElse}) {
|
||||
return error ?? orElse ?? Exception("Unknown");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
export 'paperless_server_message_exception.dart';
|
||||
export 'paperless_form_validation_exception.dart';
|
||||
export 'paperless_unauthorized_exception.dart';
|
||||
@@ -0,0 +1,42 @@
|
||||
class PaperlessFormValidationException implements Exception {
|
||||
final Map<String, String> validationMessages;
|
||||
|
||||
PaperlessFormValidationException(this.validationMessages);
|
||||
|
||||
bool hasMessageForField(String formKey) {
|
||||
return validationMessages.containsKey(formKey);
|
||||
}
|
||||
|
||||
bool hasUnspecificErrorMessage() {
|
||||
return validationMessages.containsKey("non_field_errors");
|
||||
}
|
||||
|
||||
String? unspecificErrorMessage() {
|
||||
return validationMessages["non_field_errors"];
|
||||
}
|
||||
|
||||
String? messageForField(String formKey) {
|
||||
return validationMessages[formKey];
|
||||
}
|
||||
|
||||
static bool canParse(Map<String, dynamic> json) {
|
||||
return json.values.every((element) => element is String);
|
||||
}
|
||||
|
||||
factory PaperlessFormValidationException.fromJson(Map<String, dynamic> json) {
|
||||
final Map<String, String> validationMessages = {};
|
||||
for (final entry in json.entries) {
|
||||
if (entry.value is List) {
|
||||
validationMessages.putIfAbsent(
|
||||
entry.key,
|
||||
() => (entry.value as List).first as String,
|
||||
);
|
||||
} else if (entry.value is String) {
|
||||
validationMessages.putIfAbsent(entry.key, () => entry.value);
|
||||
} else {
|
||||
validationMessages.putIfAbsent(entry.key, () => entry.value.toString());
|
||||
}
|
||||
}
|
||||
return PaperlessFormValidationException(validationMessages);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import 'package:json_annotation/json_annotation.dart';
|
||||
|
||||
part 'paperless_server_exception.g.dart';
|
||||
|
||||
@JsonSerializable(createToJson: false)
|
||||
class PaperlessServerMessageException implements Exception {
|
||||
final String detail;
|
||||
|
||||
PaperlessServerMessageException(this.detail);
|
||||
|
||||
static bool canParse(Map<String, dynamic> json) {
|
||||
return json.containsKey('detail') && json.length == 1;
|
||||
}
|
||||
|
||||
factory PaperlessServerMessageException.fromJson(Map<String, dynamic> json) =>
|
||||
_$PaperlessServerExceptionFromJson(json);
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
class PaperlessUnauthorizedException implements Exception {
|
||||
final String? message;
|
||||
|
||||
PaperlessUnauthorizedException(this.message);
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -12,7 +12,7 @@ export 'labels/matching_algorithm.dart';
|
||||
export 'labels/storage_path_model.dart';
|
||||
export 'labels/tag_model.dart';
|
||||
export 'paged_search_result.dart';
|
||||
export 'paperless_server_exception.dart';
|
||||
export 'paperless_api_exception.dart';
|
||||
export 'paperless_server_information_model.dart';
|
||||
export 'paperless_server_statistics_model.dart';
|
||||
export 'permissions/inherited_permissions.dart';
|
||||
@@ -31,3 +31,4 @@ export 'saved_view_model.dart';
|
||||
export 'task/task.dart';
|
||||
export 'task/task_status.dart';
|
||||
export 'user_model.dart';
|
||||
export 'exception/exceptions.dart';
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
class PaperlessServerException implements Exception {
|
||||
class PaperlessApiException implements Exception {
|
||||
final ErrorCode code;
|
||||
final String? details;
|
||||
final StackTrace? stackTrace;
|
||||
final int? httpStatusCode;
|
||||
|
||||
const PaperlessServerException(
|
||||
const PaperlessApiException(
|
||||
this.code, {
|
||||
this.details,
|
||||
this.stackTrace,
|
||||
this.httpStatusCode,
|
||||
});
|
||||
|
||||
const PaperlessServerException.unknown() : this(ErrorCode.unknown);
|
||||
const PaperlessApiException.unknown() : this(ErrorCode.unknown);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
@@ -53,5 +53,6 @@ enum ErrorCode {
|
||||
requestTimedOut,
|
||||
unsupportedFileFormat,
|
||||
missingClientCertificate,
|
||||
acknowledgeTasksError;
|
||||
acknowledgeTasksError,
|
||||
correspondentDeleteFailed, documentTypeDeleteFailed, tagDeleteFailed, correspondentUpdateFailed, documentTypeUpdateFailed, tagUpdateFailed, storagePathDeleteFailed, storagePathUpdateFailed, serverInformationLoadFailed, serverStatisticsLoadFailed, uiSettingsLoadFailed, loadTasksError, userNotFound;
|
||||
}
|
||||
@@ -6,13 +6,15 @@ extension UserPermissionExtension on UserModel {
|
||||
v3: (user) {
|
||||
final permission = [action.value, target.value].join("_");
|
||||
return user.userPermissions.any((element) => element == permission) ||
|
||||
user.inheritedPermissions.any((element) => element.split(".").last == permission);
|
||||
user.inheritedPermissions
|
||||
.any((element) => element.split(".").last == permission);
|
||||
},
|
||||
v2: (_) => true,
|
||||
);
|
||||
}
|
||||
|
||||
bool hasPermissions(List<PermissionAction> actions, List<PermissionTarget> targets) {
|
||||
bool hasPermissions(
|
||||
List<PermissionAction> actions, List<PermissionTarget> targets) {
|
||||
return map(
|
||||
v3: (user) {
|
||||
final permissions = [
|
||||
@@ -21,10 +23,62 @@ extension UserPermissionExtension on UserModel {
|
||||
];
|
||||
return permissions.every((requestedPermission) =>
|
||||
user.userPermissions.contains(requestedPermission) ||
|
||||
user.inheritedPermissions
|
||||
.any((element) => element.split(".").last == requestedPermission));
|
||||
user.inheritedPermissions.any(
|
||||
(element) => element.split(".").last == requestedPermission));
|
||||
},
|
||||
v2: (_) => true,
|
||||
);
|
||||
}
|
||||
|
||||
bool get canViewDocuments =>
|
||||
hasPermission(PermissionAction.view, PermissionTarget.document);
|
||||
bool get canViewCorrespondents =>
|
||||
hasPermission(PermissionAction.view, PermissionTarget.correspondent);
|
||||
bool get canViewDocumentTypes =>
|
||||
hasPermission(PermissionAction.view, PermissionTarget.documentType);
|
||||
bool get canViewTags =>
|
||||
hasPermission(PermissionAction.view, PermissionTarget.tag);
|
||||
bool get canViewStoragePaths =>
|
||||
hasPermission(PermissionAction.view, PermissionTarget.storagePath);
|
||||
bool get canViewSavedViews =>
|
||||
hasPermission(PermissionAction.view, PermissionTarget.savedView);
|
||||
|
||||
bool get canEditDocuments =>
|
||||
hasPermission(PermissionAction.change, PermissionTarget.document);
|
||||
bool get canEditCorrespondents =>
|
||||
hasPermission(PermissionAction.change, PermissionTarget.correspondent);
|
||||
bool get canEditDocumentTypes =>
|
||||
hasPermission(PermissionAction.change, PermissionTarget.documentType);
|
||||
bool get canEditTags =>
|
||||
hasPermission(PermissionAction.change, PermissionTarget.tag);
|
||||
bool get canEditStoragePaths =>
|
||||
hasPermission(PermissionAction.change, PermissionTarget.storagePath);
|
||||
bool get canEditavedViews =>
|
||||
hasPermission(PermissionAction.change, PermissionTarget.savedView);
|
||||
|
||||
bool get canDeleteDocuments =>
|
||||
hasPermission(PermissionAction.delete, PermissionTarget.document);
|
||||
bool get canDeleteCorrespondents =>
|
||||
hasPermission(PermissionAction.delete, PermissionTarget.correspondent);
|
||||
bool get canDeleteDocumentTypes =>
|
||||
hasPermission(PermissionAction.delete, PermissionTarget.documentType);
|
||||
bool get canDeleteTags =>
|
||||
hasPermission(PermissionAction.delete, PermissionTarget.tag);
|
||||
bool get canDeleteStoragePaths =>
|
||||
hasPermission(PermissionAction.delete, PermissionTarget.storagePath);
|
||||
bool get canDeleteSavedViews =>
|
||||
hasPermission(PermissionAction.delete, PermissionTarget.savedView);
|
||||
|
||||
bool get canCreateDocuments =>
|
||||
hasPermission(PermissionAction.add, PermissionTarget.document);
|
||||
bool get canCreateCorrespondents =>
|
||||
hasPermission(PermissionAction.add, PermissionTarget.correspondent);
|
||||
bool get canCreateDocumentTypes =>
|
||||
hasPermission(PermissionAction.add, PermissionTarget.documentType);
|
||||
bool get canCreateTags =>
|
||||
hasPermission(PermissionAction.add, PermissionTarget.tag);
|
||||
bool get canCreateStoragePaths =>
|
||||
hasPermission(PermissionAction.add, PermissionTarget.storagePath);
|
||||
bool get canCreateSavedViews =>
|
||||
hasPermission(PermissionAction.add, PermissionTarget.savedView);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
import 'package:paperless_api/src/models/exception/exceptions.dart';
|
||||
|
||||
abstract class PaperlessAuthenticationApi {
|
||||
///
|
||||
/// @throws [PaperlessUnauthorizedException]
|
||||
///
|
||||
Future<String> login({
|
||||
required String username,
|
||||
required String password,
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:paperless_api/src/models/paperless_server_exception.dart';
|
||||
import 'package:paperless_api/src/extensions/dio_exception_extension.dart';
|
||||
import 'package:paperless_api/src/modules/authentication_api/authentication_api.dart';
|
||||
|
||||
class PaperlessAuthenticationApiImpl implements PaperlessAuthenticationApi {
|
||||
@@ -13,34 +12,20 @@ class PaperlessAuthenticationApiImpl implements PaperlessAuthenticationApi {
|
||||
required String username,
|
||||
required String password,
|
||||
}) async {
|
||||
late Response response;
|
||||
try {
|
||||
response = await client.post(
|
||||
final response = await client.post(
|
||||
"/api/token/",
|
||||
data: {
|
||||
"username": username,
|
||||
"password": password,
|
||||
},
|
||||
options: Options(
|
||||
validateStatus: (status) => status == 200,
|
||||
),
|
||||
);
|
||||
} on DioError catch (error) {
|
||||
if (error.error is PaperlessServerException ||
|
||||
error.error is Map<String, String>) {
|
||||
throw error.error as Map<String, String>;
|
||||
} else {
|
||||
throw PaperlessServerException(
|
||||
ErrorCode.authenticationFailed,
|
||||
details: error.message,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
return response.data['token'];
|
||||
} else {
|
||||
throw PaperlessServerException(
|
||||
ErrorCode.authenticationFailed,
|
||||
httpStatusCode: response.statusCode,
|
||||
);
|
||||
} on DioException catch (exception) {
|
||||
throw exception.unravel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ abstract class PaperlessDocumentsApi {
|
||||
Future<DocumentModel> update(DocumentModel doc);
|
||||
Future<int> findNextAsn();
|
||||
Future<PagedSearchResult<DocumentModel>> findAll(DocumentFilter filter);
|
||||
Future<DocumentModel?> find(int id);
|
||||
Future<DocumentModel> find(int id);
|
||||
Future<int> delete(DocumentModel doc);
|
||||
Future<DocumentMetaData> getMetaData(DocumentModel document);
|
||||
Future<Iterable<int>> bulkAction(BulkAction action);
|
||||
|
||||
@@ -4,6 +4,8 @@ import 'package:dio/dio.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:paperless_api/paperless_api.dart';
|
||||
import 'package:paperless_api/src/constants.dart';
|
||||
import 'package:paperless_api/src/extensions/dio_exception_extension.dart';
|
||||
import 'package:paperless_api/src/models/paperless_api_exception.dart';
|
||||
|
||||
class PaperlessDocumentsApiImpl implements PaperlessDocumentsApi {
|
||||
final Dio client;
|
||||
@@ -55,20 +57,17 @@ class PaperlessDocumentsApiImpl implements PaperlessDocumentsApi {
|
||||
onSendProgress: (count, total) {
|
||||
debugPrint("Uploading ${(count / total) * 100}%...");
|
||||
},
|
||||
options: Options(validateStatus: (status) => status == 200),
|
||||
);
|
||||
if (response.statusCode == 200) {
|
||||
if (response.data is String && response.data != "OK") {
|
||||
return response.data;
|
||||
}
|
||||
return null;
|
||||
if (response.data != "OK") {
|
||||
return response.data as String;
|
||||
} else {
|
||||
throw PaperlessServerException(
|
||||
ErrorCode.documentUploadFailed,
|
||||
httpStatusCode: response.statusCode,
|
||||
);
|
||||
return null;
|
||||
}
|
||||
} on DioError catch (err) {
|
||||
throw err.error ?? const PaperlessServerException.unknown();
|
||||
} on DioException catch (exception) {
|
||||
throw exception.unravel(
|
||||
orElse: const PaperlessApiException(ErrorCode.documentUploadFailed),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,14 +77,13 @@ class PaperlessDocumentsApiImpl implements PaperlessDocumentsApi {
|
||||
final response = await client.put(
|
||||
"/api/documents/${doc.id}/",
|
||||
data: doc.toJson(),
|
||||
options: Options(validateStatus: (status) => status == 200),
|
||||
);
|
||||
return DocumentModel.fromJson(response.data);
|
||||
} on DioException catch (exception) {
|
||||
throw exception.unravel(
|
||||
orElse: const PaperlessApiException(ErrorCode.documentUpdateFailed),
|
||||
);
|
||||
if (response.statusCode == 200) {
|
||||
return DocumentModel.fromJson(response.data);
|
||||
} else {
|
||||
throw const PaperlessServerException(ErrorCode.documentUpdateFailed);
|
||||
}
|
||||
} on DioError catch (err) {
|
||||
throw err.error ?? const PaperlessServerException.unknown();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,39 +91,41 @@ class PaperlessDocumentsApiImpl implements PaperlessDocumentsApi {
|
||||
Future<PagedSearchResult<DocumentModel>> findAll(
|
||||
DocumentFilter filter,
|
||||
) async {
|
||||
final filterParams = filter.toQueryParameters()..addAll({'truncate_content': "true"});
|
||||
final filterParams = filter.toQueryParameters()
|
||||
..addAll({'truncate_content': "true"});
|
||||
try {
|
||||
final response = await client.get(
|
||||
"/api/documents/",
|
||||
queryParameters: filterParams,
|
||||
options: Options(validateStatus: (status) => status == 200),
|
||||
);
|
||||
return compute(
|
||||
PagedSearchResult.fromJsonSingleParam,
|
||||
PagedSearchResultJsonSerializer<DocumentModel>(
|
||||
response.data,
|
||||
DocumentModelJsonConverter(),
|
||||
),
|
||||
);
|
||||
} on DioException catch (exception) {
|
||||
throw exception.unravel(
|
||||
orElse: const PaperlessApiException(ErrorCode.documentLoadFailed),
|
||||
);
|
||||
if (response.statusCode == 200) {
|
||||
return compute(
|
||||
PagedSearchResult.fromJsonSingleParam,
|
||||
PagedSearchResultJsonSerializer<DocumentModel>(
|
||||
response.data,
|
||||
DocumentModelJsonConverter(),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
throw const PaperlessServerException(ErrorCode.documentLoadFailed);
|
||||
}
|
||||
} on DioError catch (err) {
|
||||
throw err.error ?? const PaperlessServerException.unknown();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<int> delete(DocumentModel doc) async {
|
||||
try {
|
||||
final response = await client.delete("/api/documents/${doc.id}/");
|
||||
await client.delete(
|
||||
"/api/documents/${doc.id}/",
|
||||
options: Options(validateStatus: (status) => status == 204),
|
||||
);
|
||||
|
||||
if (response.statusCode == 204) {
|
||||
return Future.value(doc.id);
|
||||
}
|
||||
throw const PaperlessServerException(ErrorCode.documentDeleteFailed);
|
||||
} on DioError catch (err) {
|
||||
throw err.error ?? const PaperlessServerException.unknown();
|
||||
return Future.value(doc.id);
|
||||
} on DioException catch (exception) {
|
||||
throw exception.unravel(
|
||||
orElse: const PaperlessApiException(ErrorCode.documentDeleteFailed),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,15 +143,16 @@ class PaperlessDocumentsApiImpl implements PaperlessDocumentsApi {
|
||||
try {
|
||||
final response = await client.get(
|
||||
getPreviewUrl(documentId),
|
||||
options:
|
||||
Options(responseType: ResponseType.bytes), //TODO: Check if bytes or stream is required
|
||||
options: Options(
|
||||
responseType: ResponseType.bytes,
|
||||
validateStatus: (status) => status == 200,
|
||||
), //TODO: Check if bytes or stream is required
|
||||
);
|
||||
return response.data;
|
||||
} on DioException catch (exception) {
|
||||
throw exception.unravel(
|
||||
orElse: const PaperlessApiException(ErrorCode.documentPreviewFailed),
|
||||
);
|
||||
if (response.statusCode == 200) {
|
||||
return response.data;
|
||||
}
|
||||
throw const PaperlessServerException(ErrorCode.documentPreviewFailed);
|
||||
} on DioError catch (err) {
|
||||
throw err.error ?? const PaperlessServerException.unknown();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,29 +171,30 @@ class PaperlessDocumentsApiImpl implements PaperlessDocumentsApi {
|
||||
.map((e) => e.archiveSerialNumber)
|
||||
.firstWhere((asn) => asn != null, orElse: () => 0)! +
|
||||
1;
|
||||
} on PaperlessServerException {
|
||||
throw const PaperlessServerException(ErrorCode.documentAsnQueryFailed);
|
||||
} on DioError catch (err) {
|
||||
throw err.error ?? const PaperlessServerException.unknown();
|
||||
} on PaperlessApiException {
|
||||
throw const PaperlessApiException(ErrorCode.documentAsnQueryFailed);
|
||||
} on DioException catch (exception) {
|
||||
throw exception.unravel(
|
||||
orElse: const PaperlessApiException(ErrorCode.documentAsnQueryFailed),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Iterable<int>> bulkAction(BulkAction action) async {
|
||||
try {
|
||||
final response = await client.post(
|
||||
await client.post(
|
||||
"/api/documents/bulk_edit/",
|
||||
data: action.toJson(),
|
||||
options: Options(validateStatus: (status) => status == 200),
|
||||
);
|
||||
if (response.statusCode == 200) {
|
||||
return action.documentIds;
|
||||
} else {
|
||||
throw const PaperlessServerException(
|
||||
return action.documentIds;
|
||||
} on DioException catch (exception) {
|
||||
throw exception.unravel(
|
||||
orElse: const PaperlessApiException(
|
||||
ErrorCode.documentBulkActionFailed,
|
||||
);
|
||||
}
|
||||
} on DioError catch (err) {
|
||||
throw err.error ?? const PaperlessServerException.unknown();
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -208,8 +210,10 @@ class PaperlessDocumentsApiImpl implements PaperlessDocumentsApi {
|
||||
options: Options(responseType: ResponseType.bytes),
|
||||
);
|
||||
return response.data;
|
||||
} on DioError catch (err) {
|
||||
throw err.error ?? const PaperlessServerException.unknown();
|
||||
} on DioException catch (exception) {
|
||||
throw exception.unravel(
|
||||
orElse: const PaperlessApiException.unknown(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -224,25 +228,31 @@ class PaperlessDocumentsApiImpl implements PaperlessDocumentsApi {
|
||||
final response = await client.download(
|
||||
"/api/documents/${document.id}/download/",
|
||||
localFilePath,
|
||||
onReceiveProgress: (count, total) => onProgressChanged?.call(count / total),
|
||||
onReceiveProgress: (count, total) =>
|
||||
onProgressChanged?.call(count / total),
|
||||
queryParameters: {'original': original},
|
||||
);
|
||||
return response.data;
|
||||
} on DioError catch (err) {
|
||||
throw err.error ?? const PaperlessServerException.unknown();
|
||||
} on DioException catch (exception) {
|
||||
throw exception.unravel(
|
||||
orElse: const PaperlessApiException.unknown(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<DocumentMetaData> getMetaData(DocumentModel document) async {
|
||||
try {
|
||||
final response = await client.get("/api/documents/${document.id}/metadata/");
|
||||
final response =
|
||||
await client.get("/api/documents/${document.id}/metadata/");
|
||||
return compute(
|
||||
DocumentMetaData.fromJson,
|
||||
response.data as Map<String, dynamic>,
|
||||
);
|
||||
} on DioError catch (err) {
|
||||
throw err.error ?? const PaperlessServerException.unknown();
|
||||
} on DioException catch (exception) {
|
||||
throw exception.unravel(
|
||||
orElse: const PaperlessApiException.unknown(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -255,40 +265,46 @@ class PaperlessDocumentsApiImpl implements PaperlessDocumentsApi {
|
||||
'term': query,
|
||||
'limit': limit,
|
||||
},
|
||||
options: Options(validateStatus: (status) => status == 200),
|
||||
);
|
||||
return (response.data as List).cast<String>();
|
||||
} on DioException catch (exception) {
|
||||
throw exception.unravel(
|
||||
orElse: const PaperlessApiException(
|
||||
ErrorCode.autocompleteQueryError,
|
||||
),
|
||||
);
|
||||
if (response.statusCode == 200) {
|
||||
return (response.data as List).cast<String>();
|
||||
}
|
||||
throw const PaperlessServerException(ErrorCode.autocompleteQueryError);
|
||||
} on DioError catch (err) {
|
||||
throw err.error ?? const PaperlessServerException.unknown();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<FieldSuggestions> findSuggestions(DocumentModel document) async {
|
||||
try {
|
||||
final response = await client.get("/api/documents/${document.id}/suggestions/");
|
||||
if (response.statusCode == 200) {
|
||||
return FieldSuggestions.fromJson(response.data).forDocumentId(document.id);
|
||||
}
|
||||
throw const PaperlessServerException(ErrorCode.suggestionsQueryError);
|
||||
} on DioError catch (err) {
|
||||
throw err.error ?? const PaperlessServerException.unknown();
|
||||
final response = await client.get(
|
||||
"/api/documents/${document.id}/suggestions/",
|
||||
options: Options(validateStatus: (status) => status == 200),
|
||||
);
|
||||
return FieldSuggestions.fromJson(response.data)
|
||||
.forDocumentId(document.id);
|
||||
} on DioException catch (exception) {
|
||||
throw exception.unravel(
|
||||
orElse: const PaperlessApiException(ErrorCode.suggestionsQueryError),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<DocumentModel?> find(int id) async {
|
||||
Future<DocumentModel> find(int id) async {
|
||||
try {
|
||||
final response = await client.get("/api/documents/$id/");
|
||||
if (response.statusCode == 200) {
|
||||
return DocumentModel.fromJson(response.data);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} on DioError catch (err) {
|
||||
throw err.error ?? const PaperlessServerException.unknown();
|
||||
final response = await client.get(
|
||||
"/api/documents/$id/",
|
||||
options: Options(validateStatus: (status) => status == 200),
|
||||
);
|
||||
return DocumentModel.fromJson(response.data);
|
||||
} on DioException catch (exception) {
|
||||
throw exception.unravel(
|
||||
orElse: const PaperlessApiException.unknown(),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,11 +2,12 @@ import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:paperless_api/src/extensions/dio_exception_extension.dart';
|
||||
import 'package:paperless_api/src/models/labels/correspondent_model.dart';
|
||||
import 'package:paperless_api/src/models/labels/document_type_model.dart';
|
||||
import 'package:paperless_api/src/models/labels/storage_path_model.dart';
|
||||
import 'package:paperless_api/src/models/labels/tag_model.dart';
|
||||
import 'package:paperless_api/src/models/paperless_server_exception.dart';
|
||||
import 'package:paperless_api/src/models/paperless_api_exception.dart';
|
||||
import 'package:paperless_api/src/modules/labels_api/paperless_labels_api.dart';
|
||||
import 'package:paperless_api/src/request_utils.dart';
|
||||
|
||||
@@ -94,16 +95,15 @@ class PaperlessLabelApiImpl implements PaperlessLabelsApi {
|
||||
final response = await _client.post(
|
||||
'/api/correspondents/',
|
||||
data: correspondent.toJson(),
|
||||
options: Options(validateStatus: (status) => status == 201),
|
||||
);
|
||||
if (response.statusCode == HttpStatus.created) {
|
||||
return Correspondent.fromJson(response.data);
|
||||
}
|
||||
throw PaperlessServerException(
|
||||
ErrorCode.correspondentCreateFailed,
|
||||
httpStatusCode: response.statusCode,
|
||||
return Correspondent.fromJson(response.data);
|
||||
} on DioException catch (exception) {
|
||||
throw exception.unravel(
|
||||
orElse: const PaperlessApiException(
|
||||
ErrorCode.correspondentCreateFailed,
|
||||
),
|
||||
);
|
||||
} on DioError catch (err) {
|
||||
throw err.error!;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,16 +113,17 @@ class PaperlessLabelApiImpl implements PaperlessLabelsApi {
|
||||
final response = await _client.post(
|
||||
'/api/document_types/',
|
||||
data: type.toJson(),
|
||||
options: Options(
|
||||
validateStatus: (status) => status == 201,
|
||||
),
|
||||
);
|
||||
if (response.statusCode == HttpStatus.created) {
|
||||
return DocumentType.fromJson(response.data);
|
||||
}
|
||||
throw PaperlessServerException(
|
||||
ErrorCode.documentTypeCreateFailed,
|
||||
httpStatusCode: response.statusCode,
|
||||
return DocumentType.fromJson(response.data);
|
||||
} on DioException catch (exception) {
|
||||
throw exception.unravel(
|
||||
orElse: const PaperlessApiException(
|
||||
ErrorCode.documentTypeCreateFailed,
|
||||
),
|
||||
);
|
||||
} on DioError catch (err) {
|
||||
throw err.error!;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,17 +133,18 @@ class PaperlessLabelApiImpl implements PaperlessLabelsApi {
|
||||
final response = await _client.post(
|
||||
'/api/tags/',
|
||||
data: tag.toJson(),
|
||||
options: Options(headers: {"Accept": "application/json; version=2"}),
|
||||
options: Options(
|
||||
headers: {"Accept": "application/json; version=2"},
|
||||
validateStatus: (status) => status == 201,
|
||||
),
|
||||
);
|
||||
if (response.statusCode == HttpStatus.created) {
|
||||
return Tag.fromJson(response.data);
|
||||
}
|
||||
throw PaperlessServerException(
|
||||
ErrorCode.tagCreateFailed,
|
||||
httpStatusCode: response.statusCode,
|
||||
return Tag.fromJson(response.data);
|
||||
} on DioException catch (exception) {
|
||||
throw exception.unravel(
|
||||
orElse: const PaperlessApiException(
|
||||
ErrorCode.tagCreateFailed,
|
||||
),
|
||||
);
|
||||
} on DioError catch (err) {
|
||||
throw err.error!;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,17 +152,17 @@ class PaperlessLabelApiImpl implements PaperlessLabelsApi {
|
||||
Future<int> deleteCorrespondent(Correspondent correspondent) async {
|
||||
assert(correspondent.id != null);
|
||||
try {
|
||||
final response =
|
||||
await _client.delete('/api/correspondents/${correspondent.id}/');
|
||||
if (response.statusCode == HttpStatus.noContent) {
|
||||
return correspondent.id!;
|
||||
}
|
||||
throw PaperlessServerException(
|
||||
ErrorCode.unknown,
|
||||
httpStatusCode: response.statusCode,
|
||||
await _client.delete(
|
||||
'/api/correspondents/${correspondent.id}/',
|
||||
options: Options(validateStatus: (status) => status == 204),
|
||||
);
|
||||
return correspondent.id!;
|
||||
} on DioException catch (exception) {
|
||||
throw exception.unravel(
|
||||
orElse: const PaperlessApiException(
|
||||
ErrorCode.correspondentDeleteFailed,
|
||||
),
|
||||
);
|
||||
} on DioError catch (err) {
|
||||
throw err.error!;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -168,17 +170,17 @@ class PaperlessLabelApiImpl implements PaperlessLabelsApi {
|
||||
Future<int> deleteDocumentType(DocumentType documentType) async {
|
||||
assert(documentType.id != null);
|
||||
try {
|
||||
final response =
|
||||
await _client.delete('/api/document_types/${documentType.id}/');
|
||||
if (response.statusCode == HttpStatus.noContent) {
|
||||
return documentType.id!;
|
||||
}
|
||||
throw PaperlessServerException(
|
||||
ErrorCode.unknown,
|
||||
httpStatusCode: response.statusCode,
|
||||
final response = await _client.delete(
|
||||
'/api/document_types/${documentType.id}/',
|
||||
options: Options(validateStatus: (status) => status == 204),
|
||||
);
|
||||
return documentType.id!;
|
||||
} on DioException catch (exception) {
|
||||
throw exception.unravel(
|
||||
orElse: const PaperlessApiException(
|
||||
ErrorCode.documentTypeDeleteFailed,
|
||||
),
|
||||
);
|
||||
} on DioError catch (err) {
|
||||
throw err.error!;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,16 +188,17 @@ class PaperlessLabelApiImpl implements PaperlessLabelsApi {
|
||||
Future<int> deleteTag(Tag tag) async {
|
||||
assert(tag.id != null);
|
||||
try {
|
||||
final response = await _client.delete('/api/tags/${tag.id}/');
|
||||
if (response.statusCode == HttpStatus.noContent) {
|
||||
return tag.id!;
|
||||
}
|
||||
throw PaperlessServerException(
|
||||
ErrorCode.unknown,
|
||||
httpStatusCode: response.statusCode,
|
||||
await _client.delete(
|
||||
'/api/tags/${tag.id}/',
|
||||
options: Options(validateStatus: (status) => status == 204),
|
||||
);
|
||||
return tag.id!;
|
||||
} on DioException catch (exception) {
|
||||
throw exception.unravel(
|
||||
orElse: const PaperlessApiException(
|
||||
ErrorCode.tagDeleteFailed,
|
||||
),
|
||||
);
|
||||
} on DioError catch (err) {
|
||||
throw err.error!;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -206,16 +209,15 @@ class PaperlessLabelApiImpl implements PaperlessLabelsApi {
|
||||
final response = await _client.put(
|
||||
'/api/correspondents/${correspondent.id}/',
|
||||
data: json.encode(correspondent.toJson()),
|
||||
options: Options(validateStatus: (status) => status == 200),
|
||||
);
|
||||
if (response.statusCode == HttpStatus.ok) {
|
||||
return Correspondent.fromJson(response.data);
|
||||
}
|
||||
throw PaperlessServerException(
|
||||
ErrorCode.unknown, //TODO: Add correct error code mapping.
|
||||
httpStatusCode: response.statusCode,
|
||||
return Correspondent.fromJson(response.data);
|
||||
} on DioException catch (exception) {
|
||||
throw exception.unravel(
|
||||
orElse: const PaperlessApiException(
|
||||
ErrorCode.correspondentUpdateFailed,
|
||||
),
|
||||
);
|
||||
} on DioError catch (err) {
|
||||
throw err.error!;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -226,16 +228,15 @@ class PaperlessLabelApiImpl implements PaperlessLabelsApi {
|
||||
final response = await _client.put(
|
||||
'/api/document_types/${documentType.id}/',
|
||||
data: documentType.toJson(),
|
||||
options: Options(validateStatus: (status) => status == 200),
|
||||
);
|
||||
if (response.statusCode == HttpStatus.ok) {
|
||||
return DocumentType.fromJson(response.data);
|
||||
}
|
||||
throw PaperlessServerException(
|
||||
ErrorCode.unknown,
|
||||
httpStatusCode: response.statusCode,
|
||||
return DocumentType.fromJson(response.data);
|
||||
} on DioException catch (exception) {
|
||||
throw exception.unravel(
|
||||
orElse: const PaperlessApiException(
|
||||
ErrorCode.documentTypeUpdateFailed,
|
||||
),
|
||||
);
|
||||
} on DioError catch (err) {
|
||||
throw err.error!;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -245,18 +246,19 @@ class PaperlessLabelApiImpl implements PaperlessLabelsApi {
|
||||
try {
|
||||
final response = await _client.put(
|
||||
'/api/tags/${tag.id}/',
|
||||
options: Options(headers: {"Accept": "application/json; version=2"}),
|
||||
options: Options(
|
||||
headers: {"Accept": "application/json; version=2"},
|
||||
validateStatus: (status) => status == 200,
|
||||
),
|
||||
data: tag.toJson(),
|
||||
);
|
||||
if (response.statusCode == HttpStatus.ok) {
|
||||
return Tag.fromJson(response.data);
|
||||
}
|
||||
throw PaperlessServerException(
|
||||
ErrorCode.unknown,
|
||||
httpStatusCode: response.statusCode,
|
||||
return Tag.fromJson(response.data);
|
||||
} on DioException catch (exception) {
|
||||
throw exception.unravel(
|
||||
orElse: const PaperlessApiException(
|
||||
ErrorCode.tagUpdateFailed,
|
||||
),
|
||||
);
|
||||
} on DioError catch (err) {
|
||||
throw err.error!;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -264,16 +266,17 @@ class PaperlessLabelApiImpl implements PaperlessLabelsApi {
|
||||
Future<int> deleteStoragePath(StoragePath path) async {
|
||||
assert(path.id != null);
|
||||
try {
|
||||
final response = await _client.delete('/api/storage_paths/${path.id}/');
|
||||
if (response.statusCode == HttpStatus.noContent) {
|
||||
return path.id!;
|
||||
}
|
||||
throw PaperlessServerException(
|
||||
ErrorCode.unknown,
|
||||
httpStatusCode: response.statusCode,
|
||||
final response = await _client.delete(
|
||||
'/api/storage_paths/${path.id}/',
|
||||
options: Options(validateStatus: (status) => status == 204),
|
||||
);
|
||||
return path.id!;
|
||||
} on DioException catch (exception) {
|
||||
throw exception.unravel(
|
||||
orElse: const PaperlessApiException(
|
||||
ErrorCode.storagePathDeleteFailed,
|
||||
),
|
||||
);
|
||||
} on DioError catch (err) {
|
||||
throw err.error!;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -307,16 +310,15 @@ class PaperlessLabelApiImpl implements PaperlessLabelsApi {
|
||||
final response = await _client.post(
|
||||
'/api/storage_paths/',
|
||||
data: path.toJson(),
|
||||
options: Options(validateStatus: (status) => status == 201),
|
||||
);
|
||||
if (response.statusCode == HttpStatus.created) {
|
||||
return StoragePath.fromJson(response.data);
|
||||
}
|
||||
throw PaperlessServerException(
|
||||
ErrorCode.storagePathCreateFailed,
|
||||
httpStatusCode: response.statusCode,
|
||||
return StoragePath.fromJson(response.data);
|
||||
} on DioException catch (exception) {
|
||||
throw exception.unravel(
|
||||
orElse: const PaperlessApiException(
|
||||
ErrorCode.storagePathCreateFailed,
|
||||
),
|
||||
);
|
||||
} on DioError catch (err) {
|
||||
throw err.error!;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -327,13 +329,15 @@ class PaperlessLabelApiImpl implements PaperlessLabelsApi {
|
||||
final response = await _client.put(
|
||||
'/api/storage_paths/${path.id}/',
|
||||
data: path.toJson(),
|
||||
options: Options(validateStatus: (status) => status == 200),
|
||||
);
|
||||
return StoragePath.fromJson(response.data);
|
||||
} on DioException catch (exception) {
|
||||
throw exception.unravel(
|
||||
orElse: const PaperlessApiException(
|
||||
ErrorCode.storagePathUpdateFailed,
|
||||
),
|
||||
);
|
||||
if (response.statusCode == HttpStatus.ok) {
|
||||
return StoragePath.fromJson(response.data);
|
||||
}
|
||||
throw const PaperlessServerException(ErrorCode.unknown);
|
||||
} on DioError catch (err) {
|
||||
throw err.error!;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:paperless_api/src/models/paperless_server_exception.dart';
|
||||
import 'package:paperless_api/src/extensions/dio_exception_extension.dart';
|
||||
import 'package:paperless_api/src/models/paperless_api_exception.dart';
|
||||
import 'package:paperless_api/src/models/saved_view_model.dart';
|
||||
import 'package:paperless_api/src/request_utils.dart';
|
||||
|
||||
@@ -30,32 +31,28 @@ class PaperlessSavedViewsApiImpl implements PaperlessSavedViewsApi {
|
||||
final response = await _client.post(
|
||||
"/api/saved_views/",
|
||||
data: view.toJson(),
|
||||
options: Options(validateStatus: (status) => status == 201),
|
||||
);
|
||||
if (response.statusCode == HttpStatus.created) {
|
||||
return SavedView.fromJson(response.data);
|
||||
}
|
||||
throw PaperlessServerException(
|
||||
ErrorCode.createSavedViewError,
|
||||
httpStatusCode: response.statusCode,
|
||||
return SavedView.fromJson(response.data);
|
||||
} on DioException catch (exception) {
|
||||
throw exception.unravel(
|
||||
orElse: const PaperlessApiException(ErrorCode.createSavedViewError),
|
||||
);
|
||||
} on DioError catch (err) {
|
||||
throw err.error!;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<int> delete(SavedView view) async {
|
||||
try {
|
||||
final response = await _client.delete("/api/saved_views/${view.id}/");
|
||||
if (response.statusCode == HttpStatus.noContent) {
|
||||
return view.id!;
|
||||
}
|
||||
throw PaperlessServerException(
|
||||
ErrorCode.deleteSavedViewError,
|
||||
httpStatusCode: response.statusCode,
|
||||
await _client.delete(
|
||||
"/api/saved_views/${view.id}/",
|
||||
options: Options(validateStatus: (status) => status == 204),
|
||||
);
|
||||
return view.id!;
|
||||
} on DioException catch (exception) {
|
||||
throw exception.unravel(
|
||||
orElse: const PaperlessApiException(ErrorCode.deleteSavedViewError),
|
||||
);
|
||||
} on DioError catch (err) {
|
||||
throw err.error!;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:paperless_api/src/models/paperless_server_exception.dart';
|
||||
import 'package:paperless_api/src/extensions/dio_exception_extension.dart';
|
||||
import 'package:paperless_api/src/models/paperless_api_exception.dart';
|
||||
import 'package:paperless_api/src/models/paperless_server_information_model.dart';
|
||||
import 'package:paperless_api/src/models/paperless_server_statistics_model.dart';
|
||||
import 'package:paperless_api/src/models/paperless_ui_settings_model.dart';
|
||||
@@ -18,8 +19,11 @@ class PaperlessServerStatsApiImpl implements PaperlessServerStatsApi {
|
||||
|
||||
@override
|
||||
Future<PaperlessServerInformationModel> getServerInformation() async {
|
||||
final response = await client.get("/api/remote_version/");
|
||||
if (response.statusCode == 200) {
|
||||
try {
|
||||
final response = await client.get(
|
||||
"/api/remote_version/",
|
||||
options: Options(validateStatus: (status) => status == 200),
|
||||
);
|
||||
final version = response.data["version"] as String;
|
||||
final updateAvailable = response.data["update_available"] as bool;
|
||||
return PaperlessServerInformationModel(
|
||||
@@ -27,25 +31,44 @@ class PaperlessServerStatsApiImpl implements PaperlessServerStatsApi {
|
||||
version: version,
|
||||
isUpdateAvailable: updateAvailable,
|
||||
);
|
||||
} on DioException catch (exception) {
|
||||
throw exception.unravel(
|
||||
orElse: const PaperlessApiException(
|
||||
ErrorCode.serverInformationLoadFailed,
|
||||
),
|
||||
);
|
||||
}
|
||||
throw const PaperlessServerException.unknown();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<PaperlessServerStatisticsModel> getServerStatistics() async {
|
||||
final response = await client.get('/api/statistics/');
|
||||
if (response.statusCode == 200) {
|
||||
try {
|
||||
final response = await client.get(
|
||||
'/api/statistics/',
|
||||
options: Options(validateStatus: (status) => status == 200),
|
||||
);
|
||||
return PaperlessServerStatisticsModel.fromJson(response.data);
|
||||
} on DioException catch (exception) {
|
||||
throw exception.unravel(
|
||||
orElse: const PaperlessApiException(
|
||||
ErrorCode.serverStatisticsLoadFailed,
|
||||
),
|
||||
);
|
||||
}
|
||||
throw const PaperlessServerException.unknown();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<PaperlessUiSettingsModel> getUiSettings() async {
|
||||
final response = await client.get("/api/ui_settings/");
|
||||
if (response.statusCode == 200) {
|
||||
try {
|
||||
final response = await client.get(
|
||||
"/api/ui_settings/",
|
||||
options: Options(validateStatus: (status) => status == 200),
|
||||
);
|
||||
return PaperlessUiSettingsModel.fromJson(response.data);
|
||||
} on DioException catch (exception) {
|
||||
throw exception.unravel(
|
||||
orElse: const PaperlessApiException(ErrorCode.uiSettingsLoadFailed),
|
||||
);
|
||||
}
|
||||
throw const PaperlessServerException.unknown();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@ import 'dart:developer';
|
||||
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:paperless_api/paperless_api.dart';
|
||||
import 'package:paperless_api/src/extensions/dio_exception_extension.dart';
|
||||
import 'package:paperless_api/src/models/paperless_api_exception.dart';
|
||||
|
||||
class PaperlessTasksApiImpl implements PaperlessTasksApi {
|
||||
final Dio _client;
|
||||
@@ -41,11 +43,17 @@ class PaperlessTasksApiImpl implements PaperlessTasksApi {
|
||||
|
||||
@override
|
||||
Future<Iterable<Task>> findAll([Iterable<int>? ids]) async {
|
||||
final response = await _client.get("/api/tasks/");
|
||||
if (response.statusCode == 200) {
|
||||
try {
|
||||
final response = await _client.get(
|
||||
"/api/tasks/",
|
||||
options: Options(validateStatus: (status) => status == 200),
|
||||
);
|
||||
return (response.data as List).map((e) => Task.fromJson(e));
|
||||
} on DioException catch (exception) {
|
||||
throw exception.unravel(
|
||||
orElse: const PaperlessApiException(ErrorCode.loadTasksError),
|
||||
);
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -74,15 +82,22 @@ class PaperlessTasksApiImpl implements PaperlessTasksApi {
|
||||
|
||||
@override
|
||||
Future<Iterable<Task>> acknowledgeTasks(Iterable<Task> tasks) async {
|
||||
final response = await _client.post("/api/acknowledge_tasks/", data: {
|
||||
'tasks': tasks.map((e) => e.id).toList(),
|
||||
});
|
||||
if (response.statusCode == 200) {
|
||||
try {
|
||||
final response = await _client.post(
|
||||
"/api/acknowledge_tasks/",
|
||||
data: {
|
||||
'tasks': tasks.map((e) => e.id).toList(),
|
||||
},
|
||||
options: Options(validateStatus: (status) => status == 200),
|
||||
);
|
||||
if (response.data['result'] != tasks.length) {
|
||||
throw const PaperlessServerException(ErrorCode.acknowledgeTasksError);
|
||||
throw const PaperlessApiException(ErrorCode.acknowledgeTasksError);
|
||||
}
|
||||
return tasks.map((e) => e.copyWith(acknowledged: true)).toList();
|
||||
} on DioException catch (exception) {
|
||||
throw exception.unravel(
|
||||
orElse: const PaperlessApiException(ErrorCode.acknowledgeTasksError),
|
||||
);
|
||||
}
|
||||
throw const PaperlessServerException(ErrorCode.acknowledgeTasksError);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:paperless_api/paperless_api.dart';
|
||||
import 'package:paperless_api/src/extensions/dio_exception_extension.dart';
|
||||
import 'package:paperless_api/src/models/paperless_api_exception.dart';
|
||||
|
||||
class PaperlessUserApiV2Impl implements PaperlessUserApi {
|
||||
final Dio client;
|
||||
@@ -8,19 +10,33 @@ class PaperlessUserApiV2Impl implements PaperlessUserApi {
|
||||
|
||||
@override
|
||||
Future<int> findCurrentUserId() async {
|
||||
final response = await client.get("/api/ui_settings/");
|
||||
if (response.statusCode == 200) {
|
||||
try {
|
||||
final response = await client.get(
|
||||
"/api/ui_settings/",
|
||||
options: Options(
|
||||
validateStatus: (status) => status == 200,
|
||||
),
|
||||
);
|
||||
return response.data['user_id'];
|
||||
} on DioException catch (exception) {
|
||||
throw exception.unravel(
|
||||
orElse: const PaperlessApiException(ErrorCode.userNotFound),
|
||||
);
|
||||
}
|
||||
throw const PaperlessServerException.unknown();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<UserModel> findCurrentUser() async {
|
||||
final response = await client.get("/api/ui_settings/");
|
||||
if (response.statusCode == 200) {
|
||||
try {
|
||||
final response = await client.get(
|
||||
"/api/ui_settings/",
|
||||
options: Options(validateStatus: (status) => status == 200),
|
||||
);
|
||||
return UserModelV2.fromJson(response.data);
|
||||
} on DioException catch (exception) {
|
||||
throw exception.unravel(
|
||||
orElse: const PaperlessApiException(ErrorCode.userNotFound),
|
||||
);
|
||||
}
|
||||
throw const PaperlessServerException.unknown();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:paperless_api/paperless_api.dart';
|
||||
import 'package:paperless_api/src/extensions/dio_exception_extension.dart';
|
||||
import 'package:paperless_api/src/models/paperless_api_exception.dart';
|
||||
|
||||
class PaperlessUserApiV3Impl implements PaperlessUserApi, PaperlessUserApiV3 {
|
||||
final Dio dio;
|
||||
@@ -8,11 +10,17 @@ class PaperlessUserApiV3Impl implements PaperlessUserApi, PaperlessUserApiV3 {
|
||||
|
||||
@override
|
||||
Future<UserModelV3> find(int id) async {
|
||||
final response = await dio.get("/api/users/$id/");
|
||||
if (response.statusCode == 200) {
|
||||
try {
|
||||
final response = await dio.get(
|
||||
"/api/users/$id/",
|
||||
options: Options(validateStatus: (status) => status == 200),
|
||||
);
|
||||
return UserModelV3.fromJson(response.data);
|
||||
} on DioException catch (exception) {
|
||||
throw exception.unravel(
|
||||
orElse: const PaperlessApiException(ErrorCode.userNotFound),
|
||||
);
|
||||
}
|
||||
throw const PaperlessServerException.unknown();
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -22,40 +30,59 @@ class PaperlessUserApiV3Impl implements PaperlessUserApi, PaperlessUserApiV3 {
|
||||
String contains = '',
|
||||
String username = '',
|
||||
}) async {
|
||||
final response = await dio.get("/api/users/", queryParameters: {
|
||||
"username__istartswith": startsWith,
|
||||
"username__iendswith": endsWith,
|
||||
"username__icontains": contains,
|
||||
"username__iexact": username,
|
||||
});
|
||||
if (response.statusCode == 200) {
|
||||
try {
|
||||
final response = await dio.get(
|
||||
"/api/users/",
|
||||
queryParameters: {
|
||||
"username__istartswith": startsWith,
|
||||
"username__iendswith": endsWith,
|
||||
"username__icontains": contains,
|
||||
"username__iexact": username,
|
||||
},
|
||||
options: Options(validateStatus: (status) => status == 200),
|
||||
);
|
||||
return PagedSearchResult<UserModelV3>.fromJson(
|
||||
response.data,
|
||||
UserModelV3.fromJson as UserModelV3 Function(Object?),
|
||||
).results;
|
||||
} on DioException catch (exception) {
|
||||
throw exception.unravel(
|
||||
orElse: const PaperlessApiException(ErrorCode.userNotFound),
|
||||
);
|
||||
}
|
||||
throw const PaperlessServerException.unknown();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<int> findCurrentUserId() async {
|
||||
final response = await dio.get("/api/ui_settings/");
|
||||
if (response.statusCode == 200) {
|
||||
try {
|
||||
final response = await dio.get(
|
||||
"/api/ui_settings/",
|
||||
options: Options(validateStatus: (status) => status == 200),
|
||||
);
|
||||
return response.data['user']['id'];
|
||||
} on DioException catch (exception) {
|
||||
throw exception.unravel(
|
||||
orElse: const PaperlessApiException(ErrorCode.userNotFound),
|
||||
);
|
||||
}
|
||||
throw const PaperlessServerException.unknown();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Iterable<UserModelV3>> findAll() async {
|
||||
final response = await dio.get("/api/users/");
|
||||
if (response.statusCode == 200) {
|
||||
try {
|
||||
final response = await dio.get(
|
||||
"/api/users/",
|
||||
options: Options(validateStatus: (status) => status == 200),
|
||||
);
|
||||
return PagedSearchResult<UserModelV3>.fromJson(
|
||||
response.data,
|
||||
(json) => UserModelV3.fromJson(json as dynamic),
|
||||
).results;
|
||||
} on DioException catch (exception) {
|
||||
throw exception.unravel(
|
||||
orElse: const PaperlessApiException(ErrorCode.userNotFound),
|
||||
);
|
||||
}
|
||||
throw const PaperlessServerException.unknown();
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@@ -2,7 +2,8 @@ import 'dart:io';
|
||||
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:paperless_api/src/models/paperless_server_exception.dart';
|
||||
import 'package:paperless_api/src/extensions/dio_exception_extension.dart';
|
||||
import 'package:paperless_api/src/models/paperless_api_exception.dart';
|
||||
|
||||
Future<T?> getSingleResult<T>(
|
||||
String url,
|
||||
@@ -16,20 +17,15 @@ Future<T?> getSingleResult<T>(
|
||||
url,
|
||||
options: Options(
|
||||
headers: {'accept': 'application/json; version=$minRequiredApiVersion'},
|
||||
validateStatus: (status) => status == 200,
|
||||
),
|
||||
);
|
||||
if (response.statusCode == HttpStatus.ok) {
|
||||
return compute(
|
||||
fromJson,
|
||||
response.data as Map<String, dynamic>,
|
||||
);
|
||||
}
|
||||
throw PaperlessServerException(
|
||||
errorCode,
|
||||
httpStatusCode: response.statusCode,
|
||||
return compute(
|
||||
fromJson,
|
||||
response.data as Map<String, dynamic>,
|
||||
);
|
||||
} on DioError catch (err) {
|
||||
throw err.error!;
|
||||
} on DioException catch (exception) {
|
||||
throw exception.unravel(orElse: PaperlessApiException(errorCode));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,30 +39,25 @@ Future<List<T>> getCollection<T>(
|
||||
try {
|
||||
final response = await client.get(
|
||||
url,
|
||||
options: Options(headers: {
|
||||
'accept': 'application/json; version=$minRequiredApiVersion'
|
||||
}),
|
||||
options: Options(
|
||||
headers: {'accept': 'application/json; version=$minRequiredApiVersion'},
|
||||
validateStatus: (status) => status == 200,
|
||||
),
|
||||
);
|
||||
if (response.statusCode == HttpStatus.ok) {
|
||||
final Map<String, dynamic> body = response.data;
|
||||
if (body.containsKey('count')) {
|
||||
if (body['count'] == 0) {
|
||||
return <T>[];
|
||||
} else {
|
||||
return compute(
|
||||
_collectionFromJson,
|
||||
_CollectionFromJsonSerializationParams(fromJson,
|
||||
(body['results'] as List).cast<Map<String, dynamic>>()),
|
||||
);
|
||||
}
|
||||
}
|
||||
final Map<String, dynamic> body = response.data;
|
||||
if (body['count'] == 0) {
|
||||
return <T>[];
|
||||
} else {
|
||||
return compute(
|
||||
_collectionFromJson,
|
||||
_CollectionFromJsonSerializationParams(
|
||||
fromJson,
|
||||
(body['results'] as List).cast<Map<String, dynamic>>(),
|
||||
),
|
||||
);
|
||||
}
|
||||
throw PaperlessServerException(
|
||||
errorCode,
|
||||
httpStatusCode: response.statusCode,
|
||||
);
|
||||
} on DioError catch (err) {
|
||||
throw err.error!;
|
||||
} on DioException catch (exception) {
|
||||
throw exception.unravel(orElse: PaperlessApiException(errorCode));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user