mirror of
https://github.com/Xevion/paperless-mobile.git
synced 2025-12-15 02:12:25 -06:00
feat: Add login integration test (WIP), update notes feature
This commit is contained in:
25
lib/core/database/hive/hive_initialization.dart
Normal file
25
lib/core/database/hive/hive_initialization.dart
Normal file
@@ -0,0 +1,25 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:hive_flutter/adapters.dart';
|
||||
import 'package:paperless_mobile/core/database/hive/hive_config.dart';
|
||||
import 'package:paperless_mobile/core/database/tables/global_settings.dart';
|
||||
import 'package:paperless_mobile/core/database/tables/local_user_account.dart';
|
||||
import 'package:paperless_mobile/core/database/tables/local_user_app_state.dart';
|
||||
|
||||
Future<void> initHive(Directory directory, String defaultLocale) async {
|
||||
Hive.init(directory.path);
|
||||
registerHiveAdapters();
|
||||
await Hive.openBox<LocalUserAccount>(HiveBoxes.localUserAccount);
|
||||
await Hive.openBox<LocalUserAppState>(HiveBoxes.localUserAppState);
|
||||
await Hive.openBox<bool>(HiveBoxes.hintStateBox);
|
||||
await Hive.openBox<String>(HiveBoxes.hosts);
|
||||
final globalSettingsBox =
|
||||
await Hive.openBox<GlobalSettings>(HiveBoxes.globalSettings);
|
||||
|
||||
if (!globalSettingsBox.hasValue) {
|
||||
await globalSettingsBox.setValue(
|
||||
GlobalSettings(preferredLocaleSubtag: defaultLocale),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,16 @@
|
||||
import 'package:dio/dio.dart';
|
||||
|
||||
class LanguageHeaderInterceptor extends Interceptor {
|
||||
String preferredLocaleSubtag;
|
||||
LanguageHeaderInterceptor(this.preferredLocaleSubtag);
|
||||
final String Function() preferredLocaleSubtagBuilder;
|
||||
LanguageHeaderInterceptor(this.preferredLocaleSubtagBuilder);
|
||||
|
||||
@override
|
||||
void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
|
||||
late String languages;
|
||||
if (preferredLocaleSubtag == "en") {
|
||||
if (preferredLocaleSubtagBuilder() == "en") {
|
||||
languages = "en";
|
||||
} else {
|
||||
languages = "$preferredLocaleSubtag,en;q=0.7,en-US;q=0.6";
|
||||
languages = "${preferredLocaleSubtagBuilder()},en;q=0.7,en-US;q=0.6";
|
||||
}
|
||||
options.headers.addAll({"Accept-Language": languages});
|
||||
handler.next(options);
|
||||
|
||||
@@ -1,93 +1,14 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:dio/io.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:paperless_api/src/interceptor/dio_http_error_interceptor.dart';
|
||||
import 'package:paperless_mobile/core/interceptor/dio_offline_interceptor.dart';
|
||||
import 'package:paperless_mobile/core/interceptor/dio_unauthorized_interceptor.dart';
|
||||
import 'package:paperless_mobile/core/interceptor/retry_on_connection_change_interceptor.dart';
|
||||
import 'package:paperless_mobile/features/login/model/client_certificate.dart';
|
||||
import 'package:pretty_dio_logger/pretty_dio_logger.dart';
|
||||
|
||||
/// Manages the security context, authentication and base request URL for
|
||||
/// an underlying [Dio] client which is injected into all services
|
||||
/// requiring authenticated access to the Paperless REST API.
|
||||
class SessionManager extends ValueNotifier<Dio> {
|
||||
Dio get client => value;
|
||||
|
||||
SessionManager([List<Interceptor> interceptors = const []])
|
||||
: super(_initDio(interceptors));
|
||||
|
||||
static Dio _initDio(List<Interceptor> interceptors) {
|
||||
//en- and decoded by utf8 by default
|
||||
final Dio dio = Dio(
|
||||
BaseOptions(
|
||||
contentType: Headers.jsonContentType,
|
||||
followRedirects: true,
|
||||
maxRedirects: 10,
|
||||
),
|
||||
);
|
||||
dio.options
|
||||
..receiveTimeout = const Duration(seconds: 30)
|
||||
..sendTimeout = const Duration(seconds: 60)
|
||||
..responseType = ResponseType.json;
|
||||
(dio.httpClientAdapter as IOHttpClientAdapter).createHttpClient =
|
||||
() => HttpClient()..badCertificateCallback = (cert, host, port) => true;
|
||||
dio.interceptors.addAll([
|
||||
...interceptors,
|
||||
DioUnauthorizedInterceptor(),
|
||||
DioHttpErrorInterceptor(),
|
||||
DioOfflineInterceptor(),
|
||||
RetryOnConnectionChangeInterceptor(dio: dio)
|
||||
]);
|
||||
return dio;
|
||||
}
|
||||
abstract interface class SessionManager implements ChangeNotifier {
|
||||
Dio get client;
|
||||
|
||||
void updateSettings({
|
||||
String? baseUrl,
|
||||
String? authToken,
|
||||
ClientCertificate? clientCertificate,
|
||||
}) {
|
||||
if (clientCertificate != null) {
|
||||
final context = SecurityContext()
|
||||
..usePrivateKeyBytes(
|
||||
clientCertificate.bytes,
|
||||
password: clientCertificate.passphrase,
|
||||
)
|
||||
..useCertificateChainBytes(
|
||||
clientCertificate.bytes,
|
||||
password: clientCertificate.passphrase,
|
||||
)
|
||||
..setTrustedCertificatesBytes(
|
||||
clientCertificate.bytes,
|
||||
password: clientCertificate.passphrase,
|
||||
);
|
||||
final adapter = IOHttpClientAdapter()
|
||||
..createHttpClient = () => HttpClient(context: context)
|
||||
..badCertificateCallback =
|
||||
(X509Certificate cert, String host, int port) => true;
|
||||
|
||||
client.httpClientAdapter = adapter;
|
||||
}
|
||||
|
||||
if (baseUrl != null) {
|
||||
client.options.baseUrl = baseUrl;
|
||||
}
|
||||
|
||||
if (authToken != null) {
|
||||
client.options.headers.addAll({
|
||||
HttpHeaders.authorizationHeader: 'Token $authToken',
|
||||
});
|
||||
}
|
||||
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
void resetSettings() {
|
||||
client.httpClientAdapter = IOHttpClientAdapter();
|
||||
client.options.baseUrl = '';
|
||||
client.options.headers.remove(HttpHeaders.authorizationHeader);
|
||||
notifyListeners();
|
||||
}
|
||||
});
|
||||
void resetSettings();
|
||||
}
|
||||
|
||||
96
lib/core/security/session_manager_impl.dart
Normal file
96
lib/core/security/session_manager_impl.dart
Normal file
@@ -0,0 +1,96 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:dio/io.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:paperless_api/paperless_api.dart';
|
||||
import 'package:paperless_mobile/core/interceptor/dio_offline_interceptor.dart';
|
||||
import 'package:paperless_mobile/core/interceptor/dio_unauthorized_interceptor.dart';
|
||||
import 'package:paperless_mobile/core/interceptor/retry_on_connection_change_interceptor.dart';
|
||||
import 'package:paperless_mobile/core/security/session_manager.dart';
|
||||
import 'package:paperless_mobile/features/login/model/client_certificate.dart';
|
||||
|
||||
/// Manages the security context, authentication and base request URL for
|
||||
/// an underlying [Dio] client which is injected into all services
|
||||
/// requiring authenticated access to the Paperless REST API.
|
||||
class SessionManagerImpl extends ValueNotifier<Dio> implements SessionManager {
|
||||
@override
|
||||
Dio get client => value;
|
||||
|
||||
SessionManagerImpl([List<Interceptor> interceptors = const []])
|
||||
: super(_initDio(interceptors));
|
||||
|
||||
static Dio _initDio(List<Interceptor> interceptors) {
|
||||
//en- and decoded by utf8 by default
|
||||
final Dio dio = Dio(
|
||||
BaseOptions(
|
||||
contentType: Headers.jsonContentType,
|
||||
followRedirects: true,
|
||||
maxRedirects: 10,
|
||||
),
|
||||
);
|
||||
dio.options
|
||||
..receiveTimeout = const Duration(seconds: 30)
|
||||
..sendTimeout = const Duration(seconds: 60)
|
||||
..responseType = ResponseType.json;
|
||||
(dio.httpClientAdapter as IOHttpClientAdapter).createHttpClient =
|
||||
() => HttpClient()..badCertificateCallback = (cert, host, port) => true;
|
||||
dio.interceptors.addAll([
|
||||
...interceptors,
|
||||
DioUnauthorizedInterceptor(),
|
||||
DioHttpErrorInterceptor(),
|
||||
DioOfflineInterceptor(),
|
||||
RetryOnConnectionChangeInterceptor(dio: dio)
|
||||
]);
|
||||
return dio;
|
||||
}
|
||||
|
||||
@override
|
||||
void updateSettings({
|
||||
String? baseUrl,
|
||||
String? authToken,
|
||||
ClientCertificate? clientCertificate,
|
||||
}) {
|
||||
if (clientCertificate != null) {
|
||||
final context = SecurityContext()
|
||||
..usePrivateKeyBytes(
|
||||
clientCertificate.bytes,
|
||||
password: clientCertificate.passphrase,
|
||||
)
|
||||
..useCertificateChainBytes(
|
||||
clientCertificate.bytes,
|
||||
password: clientCertificate.passphrase,
|
||||
)
|
||||
..setTrustedCertificatesBytes(
|
||||
clientCertificate.bytes,
|
||||
password: clientCertificate.passphrase,
|
||||
);
|
||||
final adapter = IOHttpClientAdapter()
|
||||
..createHttpClient = () => HttpClient(context: context)
|
||||
..badCertificateCallback =
|
||||
(X509Certificate cert, String host, int port) => true;
|
||||
|
||||
client.httpClientAdapter = adapter;
|
||||
}
|
||||
|
||||
if (baseUrl != null) {
|
||||
client.options.baseUrl = baseUrl;
|
||||
}
|
||||
|
||||
if (authToken != null) {
|
||||
client.options.headers.addAll({
|
||||
HttpHeaders.authorizationHeader: 'Token $authToken',
|
||||
});
|
||||
}
|
||||
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
@override
|
||||
void resetSettings() {
|
||||
client.httpClientAdapter = IOHttpClientAdapter();
|
||||
client.options.baseUrl = '';
|
||||
client.options.headers.remove(HttpHeaders.authorizationHeader);
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import 'package:dio/dio.dart';
|
||||
import 'package:paperless_mobile/core/global/os_error_codes.dart';
|
||||
import 'package:paperless_mobile/core/interceptor/server_reachability_error_interceptor.dart';
|
||||
import 'package:paperless_mobile/core/security/session_manager.dart';
|
||||
import 'package:paperless_mobile/core/security/session_manager_impl.dart';
|
||||
import 'package:paperless_mobile/features/login/model/client_certificate.dart';
|
||||
import 'package:paperless_mobile/features/login/model/reachability_status.dart';
|
||||
import 'package:rxdart/subjects.dart';
|
||||
@@ -79,7 +80,7 @@ class ConnectivityStatusServiceImpl implements ConnectivityStatusService {
|
||||
}
|
||||
try {
|
||||
SessionManager manager =
|
||||
SessionManager([ServerReachabilityErrorInterceptor()])
|
||||
SessionManagerImpl([ServerReachabilityErrorInterceptor()])
|
||||
..updateSettings(clientCertificate: clientCertificate)
|
||||
..client.options.connectTimeout = const Duration(seconds: 5)
|
||||
..client.options.receiveTimeout = const Duration(seconds: 5);
|
||||
|
||||
Reference in New Issue
Block a user