Skip to content

Commit

Permalink
fix: Resolve mTLS issue, update changelogs, bump version number
Browse files Browse the repository at this point in the history
  • Loading branch information
astubenbord committed Jan 7, 2024
1 parent 18d8d34 commit c5db5df
Show file tree
Hide file tree
Showing 11 changed files with 89 additions and 140 deletions.
2 changes: 2 additions & 0 deletions android/fastlane/metadata/android/de-DE/changelogs/4053.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- Beheben eines Problems mit mTLS
- Kleinere Fehlerbehebungen
2 changes: 2 additions & 0 deletions android/fastlane/metadata/android/en-US/changelogs/4053.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- Fix issue with mTLS
- Some minor bug fixes
32 changes: 24 additions & 8 deletions lib/core/factory/paperless_api_factory.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,29 @@ import 'package:dio/dio.dart';
import 'package:paperless_api/paperless_api.dart';

abstract class PaperlessApiFactory {
PaperlessDocumentsApi createDocumentsApi(Dio dio, {required int apiVersion});
PaperlessSavedViewsApi createSavedViewsApi(Dio dio,
{required int apiVersion});
PaperlessLabelsApi createLabelsApi(Dio dio, {required int apiVersion});
PaperlessServerStatsApi createServerStatsApi(Dio dio,
{required int apiVersion});
PaperlessTasksApi createTasksApi(Dio dio, {required int apiVersion});
PaperlessDocumentsApi createDocumentsApi(
Dio dio, {
required int apiVersion,
});
PaperlessSavedViewsApi createSavedViewsApi(
Dio dio, {
required int apiVersion,
});
PaperlessLabelsApi createLabelsApi(
Dio dio, {
required int apiVersion,
});
PaperlessServerStatsApi createServerStatsApi(
Dio dio, {
required int apiVersion,
});
PaperlessTasksApi createTasksApi(
Dio dio, {
required int apiVersion,
});
PaperlessAuthenticationApi createAuthenticationApi(Dio dio);
PaperlessUserApi createUserApi(Dio dio, {required int apiVersion});
PaperlessUserApi createUserApi(
Dio dio, {
required int apiVersion,
});
}
1 change: 1 addition & 0 deletions lib/features/changelogs/view/changelog_dialog.dart
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ class ChangelogDialog extends StatelessWidget {
}

const _versionNumbers = {
"4053": "3.2.1",
"4043": "3.2.0",
"4033": "3.1.8",
"4023": "3.1.7",
Expand Down
20 changes: 17 additions & 3 deletions lib/features/login/model/client_certificate.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,27 @@ part 'client_certificate.g.dart';
@HiveType(typeId: HiveTypeIds.clientCertificate)
class ClientCertificate {
@HiveField(0)
Uint8List bytes;
final Uint8List bytes;
@HiveField(2, defaultValue: "cert.pfx")
final String filename;
@HiveField(1)
String? passphrase;

final String? passphrase;

ClientCertificate({
required this.bytes,
required this.filename,
this.passphrase,
});

ClientCertificate copyWith({
Uint8List? bytes,
String? filename,
String? passphrase,
}) {
return ClientCertificate(
bytes: bytes ?? this.bytes,
filename: filename ?? this.filename,
passphrase: passphrase ?? this.passphrase,
);
}
}
25 changes: 0 additions & 25 deletions lib/features/login/model/client_certificate_form_model.dart

This file was deleted.

85 changes: 6 additions & 79 deletions lib/features/login/view/add_account_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import 'package:paperless_mobile/core/model/info_message_exception.dart';
import 'package:paperless_mobile/core/service/connectivity_status_service.dart';
import 'package:paperless_mobile/core/extensions/flutter_extensions.dart';
import 'package:paperless_mobile/features/login/model/client_certificate.dart';
import 'package:paperless_mobile/features/login/model/client_certificate_form_model.dart';
import 'package:paperless_mobile/features/login/model/login_form_credentials.dart';
import 'package:paperless_mobile/features/login/model/reachability_status.dart';
import 'package:paperless_mobile/features/login/view/widgets/form_fields/client_certificate_form_field.dart';
Expand Down Expand Up @@ -230,75 +229,14 @@ class _AddAccountPageState extends State<AddAccountPage> {
),
),
);
return Scaffold(
appBar: AppBar(
title: Text(widget.titleText),
),
bottomNavigationBar: BottomAppBar(
child: Row(
mainAxisAlignment: widget.bottomLeftButton != null
? MainAxisAlignment.spaceBetween
: MainAxisAlignment.end,
children: [
if (widget.bottomLeftButton != null) widget.bottomLeftButton!,
FilledButton(
child: Text(S.of(context)!.loginPageSignInTitle),
onPressed: _reachabilityStatus == ReachabilityStatus.reachable &&
!_isFormSubmitted
? _onSubmit
: null,
),
],
),
),
resizeToAvoidBottomInset: true,
body: AutofillGroup(
child: FormBuilder(
key: _formKey,
child: ListView(
children: [
ServerAddressFormField(
initialValue: widget.initialServerUrl,
onChanged: (address) {
_updateReachability(address);
},
).padded(),
ClientCertificateFormField(
initialBytes: widget.initialClientCertificate?.bytes,
initialPassphrase: widget.initialClientCertificate?.passphrase,
onChanged: (_) => _updateReachability(),
).padded(),
_buildStatusIndicator(),
if (_reachabilityStatus == ReachabilityStatus.reachable) ...[
UserCredentialsFormField(
formKey: _formKey,
initialUsername: widget.initialUsername,
initialPassword: widget.initialPassword,
onFieldsSubmitted: _onSubmit,
),
Text(
S.of(context)!.loginRequiredPermissionsHint,
style: Theme.of(context).textTheme.bodySmall?.apply(
color: Theme.of(context)
.colorScheme
.onBackground
.withOpacity(0.6),
),
).padded(16),
],
],
),
),
),
);
}

Future<ReachabilityStatus> _updateReachability([String? address]) async {
setState(() {
_isCheckingConnection = true;
});
final certForm =
_formKey.currentState?.getRawValue<ClientCertificateFormModel>(
final selectedCertificate =
_formKey.currentState?.getRawValue<ClientCertificate>(
ClientCertificateFormField.fkClientCertificate,
);
final status = await context
Expand All @@ -307,12 +245,7 @@ class _AddAccountPageState extends State<AddAccountPage> {
address ??
_formKey.currentState!
.getRawValue(ServerAddressFormField.fkServerAddress),
certForm != null
? ClientCertificate(
bytes: certForm.bytes,
passphrase: certForm.passphrase,
)
: null,
selectedCertificate,
);
setState(() {
_isCheckingConnection = false;
Expand Down Expand Up @@ -383,16 +316,10 @@ class _AddAccountPageState extends State<AddAccountPage> {
});
if (_formKey.currentState?.saveAndValidate() ?? false) {
final form = _formKey.currentState!.value;
ClientCertificate? clientCert;
final clientCertFormModel =
form[ClientCertificateFormField.fkClientCertificate]
as ClientCertificateFormModel?;
if (clientCertFormModel != null) {
clientCert = ClientCertificate(
bytes: clientCertFormModel.bytes,
passphrase: clientCertFormModel.passphrase,
);
}
as ClientCertificate?;

final credentials =
form[UserCredentialsFormField.fkCredentials] as LoginFormCredentials;
try {
Expand All @@ -401,7 +328,7 @@ class _AddAccountPageState extends State<AddAccountPage> {
credentials.username!,
credentials.password!,
form[ServerAddressFormField.fkServerAddress],
clientCert,
clientCertFormModel,
);
} on PaperlessApiException catch (error) {
showErrorMessage(context, error);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:flutter_form_builder/flutter_form_builder.dart';
import 'package:paperless_mobile/core/extensions/flutter_extensions.dart';
import 'package:paperless_mobile/features/login/model/client_certificate_form_model.dart';
import 'package:paperless_mobile/features/login/model/client_certificate.dart';
import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
import 'package:paperless_mobile/helpers/message_helpers.dart';
import 'package:path/path.dart' as p;
Expand All @@ -15,14 +15,16 @@ class ClientCertificateFormField extends StatefulWidget {
static const fkClientCertificate = 'clientCertificate';

final String? initialPassphrase;
final String? initialFilename;
final Uint8List? initialBytes;

final ValueChanged<ClientCertificateFormModel?>? onChanged;
final ValueChanged<ClientCertificate?>? onChanged;
const ClientCertificateFormField({
super.key,
this.onChanged,
this.initialPassphrase,
this.initialBytes,
this.initialFilename,
});

@override
Expand All @@ -32,23 +34,23 @@ class ClientCertificateFormField extends StatefulWidget {

class _ClientCertificateFormFieldState extends State<ClientCertificateFormField>
with AutomaticKeepAliveClientMixin {
File? _selectedFile;
@override
Widget build(BuildContext context) {
super.build(context);
return FormBuilderField<ClientCertificateFormModel?>(
return FormBuilderField<ClientCertificate?>(
key: const ValueKey('login-client-cert'),
name: ClientCertificateFormField.fkClientCertificate,
onChanged: widget.onChanged,
initialValue: widget.initialBytes != null
? ClientCertificateFormModel(
? ClientCertificate(
bytes: widget.initialBytes!,
filename: widget.initialFilename!,
passphrase: widget.initialPassphrase,
)
: null,
builder: (field) {
final theme =
Theme.of(context).copyWith(dividerColor: Colors.transparent); //new
Theme.of(context).copyWith(dividerColor: Colors.transparent);
return Theme(
data: theme,
child: ExpansionTile(
Expand All @@ -74,11 +76,10 @@ class _ClientCertificateFormFieldState extends State<ClientCertificateFormField>
_buildSelectedFileText(field).paddedOnly(left: 8),
],
),
if (_selectedFile != null)
if (field.value?.filename != null)
IconButton(
icon: const Icon(Icons.close),
onPressed: () => setState(() {
_selectedFile = null;
field.didChange(null);
}),
)
Expand All @@ -103,7 +104,7 @@ class _ClientCertificateFormFieldState extends State<ClientCertificateFormField>
// : null,
// ),
// ),
if (_selectedFile != null) ...[
if (field.value?.filename != null) ...[
ObscuredInputTextFormField(
key: const ValueKey('login-client-cert-passphrase'),
initialValue: field.value?.passphrase,
Expand All @@ -124,7 +125,7 @@ class _ClientCertificateFormFieldState extends State<ClientCertificateFormField>
}

Future<void> _onSelectFile(
FormFieldState<ClientCertificateFormModel?> field,
FormFieldState<ClientCertificate?> field,
) async {
final result = await FilePicker.platform.pickFiles(
allowMultiple: false,
Expand All @@ -137,31 +138,27 @@ class _ClientCertificateFormFieldState extends State<ClientCertificateFormField>
showSnackBar(context, S.of(context)!.invalidCertificateFormat);
return;
}
File file = File(result.files.single.path!);
setState(() {
_selectedFile = file;
});
File file = File(path);
final bytes = await file.readAsBytes();

final changedValue = field.value?.copyWith(bytes: bytes) ??
ClientCertificateFormModel(bytes: bytes);
final changedValue = ClientCertificate(
bytes: bytes,
filename: p.basename(path),
);
field.didChange(changedValue);
}

Widget _buildSelectedFileText(
FormFieldState<ClientCertificateFormModel?> field) {
Widget _buildSelectedFileText(FormFieldState<ClientCertificate?> field) {
if (field.value == null) {
assert(_selectedFile == null);
return Text(
S.of(context)!.selectFile,
style: Theme.of(context).textTheme.labelMedium?.apply(
color: Theme.of(context).hintColor,
),
);
} else {
assert(_selectedFile != null);
return Text(
_selectedFile!.path.split("/").last,
p.basename(field.value!.filename),
style: const TextStyle(
overflow: TextOverflow.ellipsis,
),
Expand Down
17 changes: 16 additions & 1 deletion packages/paperless_api/lib/src/models/custom_field_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ part 'custom_field_model.g.dart';
@JsonSerializable()
class CustomFieldModel with EquatableMixin {
final int? id;
final String name;
final String? name;
final CustomFieldDataType dataType;

CustomFieldModel({
Expand All @@ -24,3 +24,18 @@ class CustomFieldModel with EquatableMixin {

Map<String, dynamic> toJson() => _$CustomFieldModelToJson(this);
}

/// An instance of the [CustomFieldModel].
@JsonSerializable()
class CustomFieldInstance {
final int? id;
final dynamic value;

const CustomFieldInstance({
this.id,
this.value,
});

factory CustomFieldInstance.fromJson(Map<String, dynamic> json) =>
_$CustomFieldInstanceFromJson(json);
}
Loading

0 comments on commit c5db5df

Please sign in to comment.