mirror of
https://github.com/Xevion/paperless-mobile.git
synced 2025-12-08 18:08:07 -06:00
Fixed login and error handling
This commit is contained in:
157
lib/main.dart
157
lib/main.dart
@@ -1,4 +1,5 @@
|
||||
import 'dart:io';
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:connectivity_plus/connectivity_plus.dart';
|
||||
import 'package:encrypted_shared_preferences/encrypted_shared_preferences.dart';
|
||||
@@ -10,9 +11,7 @@ import 'package:flutter_localizations/flutter_localizations.dart';
|
||||
import 'package:flutter_native_splash/flutter_native_splash.dart';
|
||||
import 'package:fluttertoast/fluttertoast.dart';
|
||||
import 'package:form_builder_validators/form_builder_validators.dart';
|
||||
import 'package:http/http.dart';
|
||||
import 'package:http/io_client.dart';
|
||||
import 'package:http_interceptor/http/intercepted_client.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:hydrated_bloc/hydrated_bloc.dart';
|
||||
import 'package:intl/date_symbol_data_local.dart';
|
||||
import 'package:intl/intl_standalone.dart';
|
||||
@@ -22,7 +21,9 @@ import 'package:paperless_mobile/core/bloc/bloc_changes_observer.dart';
|
||||
import 'package:paperless_mobile/core/bloc/connectivity_cubit.dart';
|
||||
import 'package:paperless_mobile/core/bloc/paperless_server_information_cubit.dart';
|
||||
import 'package:paperless_mobile/core/global/constants.dart';
|
||||
import 'package:paperless_mobile/core/interceptor/authentication.interceptor.dart';
|
||||
import 'package:paperless_mobile/core/interceptor/dio_http_error_interceptor.dart';
|
||||
import 'package:paperless_mobile/core/interceptor/language_header.interceptor.dart';
|
||||
import 'package:paperless_mobile/core/interceptor/retry_on_connection_change_interceptor.dart';
|
||||
import 'package:paperless_mobile/core/logic/error_code_localization_mapper.dart';
|
||||
import 'package:paperless_mobile/core/repository/impl/correspondent_repository_impl.dart';
|
||||
import 'package:paperless_mobile/core/repository/impl/document_type_repository_impl.dart';
|
||||
@@ -33,17 +34,16 @@ import 'package:paperless_mobile/core/repository/label_repository.dart';
|
||||
import 'package:paperless_mobile/core/repository/saved_view_repository.dart';
|
||||
import 'package:paperless_mobile/core/security/authentication_aware_dio_manager.dart';
|
||||
import 'package:paperless_mobile/core/service/connectivity_status.service.dart';
|
||||
import 'package:paperless_mobile/core/service/dio_file_service.dart';
|
||||
import 'package:paperless_mobile/core/service/file_service.dart';
|
||||
import 'package:paperless_mobile/core/store/local_vault.dart';
|
||||
import 'package:paperless_mobile/extensions/flutter_extensions.dart';
|
||||
import 'package:paperless_mobile/extensions/security_context_extension.dart';
|
||||
import 'package:paperless_mobile/features/app_intro/application_intro_slideshow.dart';
|
||||
import 'package:paperless_mobile/features/document_upload/cubit/document_upload_cubit.dart';
|
||||
import 'package:paperless_mobile/features/document_upload/view/document_upload_preparation_page.dart';
|
||||
import 'package:paperless_mobile/features/home/view/home_page.dart';
|
||||
import 'package:paperless_mobile/features/login/bloc/authentication_cubit.dart';
|
||||
import 'package:paperless_mobile/features/login/bloc/authentication_state.dart';
|
||||
import 'package:paperless_mobile/features/login/model/authentication_information.dart';
|
||||
import 'package:paperless_mobile/features/login/services/authentication_service.dart';
|
||||
import 'package:paperless_mobile/features/login/view/login_page.dart';
|
||||
import 'package:paperless_mobile/features/settings/bloc/application_settings_cubit.dart';
|
||||
@@ -53,24 +53,48 @@ import 'package:paperless_mobile/util.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:receive_sharing_intent/receive_sharing_intent.dart';
|
||||
import 'package:pretty_dio_logger/pretty_dio_logger.dart';
|
||||
|
||||
void main() async {
|
||||
Bloc.observer = BlocChangesObserver();
|
||||
final widgetsBinding = WidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
HydratedBloc.storage = await HydratedStorage.build(
|
||||
storageDirectory: await getApplicationDocumentsDirectory(),
|
||||
);
|
||||
FlutterNativeSplash.preserve(widgetsBinding: widgetsBinding);
|
||||
await findSystemLocale();
|
||||
|
||||
// Required for self signed client certificates
|
||||
final dioWrapper = AuthenticationAwareDioManager();
|
||||
|
||||
// Initialize External dependencies
|
||||
final connectivity = Connectivity();
|
||||
final encryptedSharedPreferences = EncryptedSharedPreferences();
|
||||
final localAuthentication = LocalAuthentication();
|
||||
// Initialize other utility classes
|
||||
final connectivityStatusService = ConnectivityStatusServiceImpl(connectivity);
|
||||
final localVault = LocalVaultImpl(encryptedSharedPreferences);
|
||||
final localAuthService =
|
||||
LocalAuthenticationService(localVault, localAuthentication);
|
||||
|
||||
final hiveDir = await getApplicationDocumentsDirectory();
|
||||
HydratedBloc.storage = await HydratedStorage.build(
|
||||
storageDirectory: hiveDir,
|
||||
);
|
||||
|
||||
final appSettingsCubit = ApplicationSettingsCubit(localAuthService);
|
||||
FlutterNativeSplash.preserve(widgetsBinding: widgetsBinding);
|
||||
|
||||
final languageHeaderInterceptor = LanguageHeaderInterceptor(
|
||||
appSettingsCubit.state.preferredLocaleSubtag,
|
||||
);
|
||||
// Required for self signed client certificates
|
||||
final dioWrapper = AuthenticationAwareDioManager([
|
||||
DioHttpErrorInterceptor(),
|
||||
PrettyDioLogger(
|
||||
compact: true,
|
||||
responseBody: false,
|
||||
responseHeader: false,
|
||||
request: false,
|
||||
requestBody: false,
|
||||
requestHeader: false,
|
||||
),
|
||||
languageHeaderInterceptor,
|
||||
]);
|
||||
|
||||
// Initialize Paperless APIs
|
||||
final authApi = PaperlessAuthenticationApiImpl(dioWrapper.client);
|
||||
@@ -79,14 +103,6 @@ void main() async {
|
||||
final statsApi = PaperlessServerStatsApiImpl(dioWrapper.client);
|
||||
final savedViewsApi = PaperlessSavedViewsApiImpl(dioWrapper.client);
|
||||
|
||||
// Initialize other utility classes
|
||||
final connectivityStatusService = ConnectivityStatusServiceImpl(connectivity);
|
||||
final localVault = LocalVaultImpl(encryptedSharedPreferences);
|
||||
final localAuthService =
|
||||
LocalAuthenticationService(localVault, localAuthentication);
|
||||
|
||||
// Initialize Repositories
|
||||
|
||||
// Initialize Blocs/Cubits
|
||||
final connectivityCubit = ConnectivityCubit(connectivityStatusService);
|
||||
// Remove temporarily downloaded files.
|
||||
@@ -95,15 +111,21 @@ void main() async {
|
||||
// Load application settings and stored authentication data
|
||||
await connectivityCubit.initialize();
|
||||
|
||||
// Create repositories
|
||||
final tagRepository = TagRepositoryImpl(labelsApi);
|
||||
final correspondentRepository = CorrespondentRepositoryImpl(labelsApi);
|
||||
final documentTypeRepository = DocumentTypeRepositoryImpl(labelsApi);
|
||||
final storagePathRepository = StoragePathRepositoryImpl(labelsApi);
|
||||
final savedViewRepository = SavedViewRepositoryImpl(savedViewsApi);
|
||||
|
||||
//Create cubits/blocs
|
||||
final authCubit = AuthenticationCubit(
|
||||
localVault,
|
||||
localAuthService,
|
||||
authApi,
|
||||
dioWrapper,
|
||||
);
|
||||
|
||||
String? currentServerUrl;
|
||||
String? currentAuthToken;
|
||||
await authCubit
|
||||
.restoreSessionState(appSettingsCubit.state.isLocalAuthenticationEnabled);
|
||||
|
||||
if (authCubit.state.isAuthenticated) {
|
||||
final auth = authCubit.state.authentication!;
|
||||
@@ -112,31 +134,11 @@ void main() async {
|
||||
authToken: auth.token,
|
||||
clientCertificate: auth.clientCertificate,
|
||||
);
|
||||
currentServerUrl = auth.serverUrl;
|
||||
currentAuthToken = auth.token;
|
||||
}
|
||||
|
||||
SecurityContext securityContext = SecurityContext();
|
||||
authCubit.stream.asBroadcastStream().listen((event) {
|
||||
if (event.isAuthenticated) {
|
||||
final auth = event.authentication!;
|
||||
securityContext =
|
||||
SecurityContext().withClientCertificate(auth.clientCertificate);
|
||||
currentServerUrl = auth.serverUrl;
|
||||
currentAuthToken = auth.token;
|
||||
} else {
|
||||
securityContext = SecurityContext();
|
||||
currentServerUrl = null;
|
||||
currentAuthToken = null;
|
||||
}
|
||||
});
|
||||
|
||||
// Create repositories
|
||||
final tagRepository = TagRepositoryImpl(labelsApi);
|
||||
final correspondentRepository = CorrespondentRepositoryImpl(labelsApi);
|
||||
final documentTypeRepository = DocumentTypeRepositoryImpl(labelsApi);
|
||||
final storagePathRepository = StoragePathRepositoryImpl(labelsApi);
|
||||
final savedViewRepository = SavedViewRepositoryImpl(savedViewsApi);
|
||||
//Update language header in interceptor on language change.
|
||||
appSettingsCubit.stream.listen((event) => languageHeaderInterceptor
|
||||
.preferredLocaleSubtag = event.preferredLocaleSubtag);
|
||||
|
||||
runApp(
|
||||
MultiProvider(
|
||||
@@ -146,44 +148,11 @@ void main() async {
|
||||
Provider<PaperlessLabelsApi>.value(value: labelsApi),
|
||||
Provider<PaperlessServerStatsApi>.value(value: statsApi),
|
||||
Provider<PaperlessSavedViewsApi>.value(value: savedViewsApi),
|
||||
ProxyProvider<SecurityContext, cm.CacheManager>(
|
||||
Provider<cm.CacheManager>(
|
||||
create: (context) => cm.CacheManager(
|
||||
cm.Config(
|
||||
'cacheKey',
|
||||
fileService: cm.HttpFileService(
|
||||
httpClient: InterceptedClient.build(
|
||||
interceptors: [
|
||||
AuthenticationInterceptor(
|
||||
serverUrl: currentServerUrl,
|
||||
token: currentAuthToken,
|
||||
),
|
||||
],
|
||||
client: IOClient(
|
||||
HttpClient(
|
||||
context: securityContext,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
update: (context, securityContext, previous) => cm.CacheManager(
|
||||
cm.Config(
|
||||
'cacheKey',
|
||||
fileService: cm.HttpFileService(
|
||||
httpClient: InterceptedClient.build(
|
||||
interceptors: [
|
||||
AuthenticationInterceptor(
|
||||
serverUrl: currentServerUrl,
|
||||
token: currentAuthToken,
|
||||
),
|
||||
],
|
||||
client: IOClient(
|
||||
HttpClient(
|
||||
context: securityContext,
|
||||
),
|
||||
),
|
||||
)),
|
||||
fileService: DioFileService(dioWrapper.client),
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -214,6 +183,8 @@ void main() async {
|
||||
providers: [
|
||||
BlocProvider<AuthenticationCubit>.value(value: authCubit),
|
||||
BlocProvider<ConnectivityCubit>.value(value: connectivityCubit),
|
||||
BlocProvider<ApplicationSettingsCubit>.value(
|
||||
value: appSettingsCubit),
|
||||
],
|
||||
child: const PaperlessMobileEntrypoint(),
|
||||
),
|
||||
@@ -282,9 +253,6 @@ class _PaperlessMobileEntrypointState extends State<PaperlessMobileEntrypoint> {
|
||||
BlocProvider(
|
||||
create: (context) => PaperlessServerInformationCubit(context.read()),
|
||||
),
|
||||
BlocProvider(
|
||||
create: (context) => ApplicationSettingsCubit(),
|
||||
),
|
||||
],
|
||||
child: BlocBuilder<ApplicationSettingsCubit, ApplicationSettingsState>(
|
||||
builder: (context, settings) {
|
||||
@@ -423,7 +391,8 @@ class _AuthenticationWrapperState extends State<AuthenticationWrapper> {
|
||||
}
|
||||
},
|
||||
builder: (context, authentication) {
|
||||
if (authentication.isAuthenticated) {
|
||||
if (authentication.isAuthenticated &&
|
||||
(authentication.wasLocalAuthenticationSuccessful ?? true)) {
|
||||
return const HomePage();
|
||||
} else {
|
||||
if (authentication.wasLoginStored &&
|
||||
@@ -461,12 +430,20 @@ class BiometricAuthenticationPage extends StatelessWidget {
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
ElevatedButton(
|
||||
onPressed: () => context.read<AuthenticationCubit>().logout(),
|
||||
onPressed: () {
|
||||
context.read<AuthenticationCubit>().logout();
|
||||
context.read();
|
||||
HydratedBloc.storage.clear();
|
||||
},
|
||||
child: const Text("Log out"),
|
||||
),
|
||||
ElevatedButton(
|
||||
onPressed: () =>
|
||||
context.read<AuthenticationCubit>().restoreSessionState(),
|
||||
onPressed: () => context
|
||||
.read<AuthenticationCubit>()
|
||||
.restoreSessionState(context
|
||||
.read<ApplicationSettingsCubit>()
|
||||
.state
|
||||
.isLocalAuthenticationEnabled),
|
||||
child: const Text("Authenticate"),
|
||||
),
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user