Skip to content
This repository was archived by the owner on Sep 14, 2024. It is now read-only.

Commit 6521a3a

Browse files
committed
migrate to appPassword
1 parent 97b44d8 commit 6521a3a

File tree

12 files changed

+39
-173
lines changed

12 files changed

+39
-173
lines changed

lib/src/blocs/login/login_bloc.dart

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import 'package:equatable/equatable.dart';
22
import 'package:flutter_bloc/flutter_bloc.dart';
33
import 'package:nextcloud_cookbook_flutter/src/blocs/authentication/authentication_bloc.dart';
4-
import 'package:nextcloud_cookbook_flutter/src/models/app_authentication.dart';
54
import 'package:nextcloud_cookbook_flutter/src/services/services.dart';
65
import 'package:nextcloud_cookbook_flutter/src/util/url_validator.dart';
76

@@ -24,24 +23,14 @@ class LoginBloc extends Bloc<LoginEvent, LoginState> {
2423
emit(LoginState(status: LoginStatus.loading));
2524

2625
try {
27-
AppAuthentication appAuthentication;
2826
assert(URLUtils.isSanitized(event.serverURL));
2927

30-
if (!event.isAppPassword) {
31-
appAuthentication = await userRepository.authenticate(
32-
event.serverURL,
33-
event.username,
34-
event.originalBasicAuth,
35-
isSelfSignedCertificate: event.isSelfSignedCertificate,
36-
);
37-
} else {
38-
appAuthentication = await userRepository.authenticateAppPassword(
39-
event.serverURL,
40-
event.username,
41-
event.originalBasicAuth,
42-
isSelfSignedCertificate: event.isSelfSignedCertificate,
43-
);
44-
}
28+
final appAuthentication = await userRepository.authenticateAppPassword(
29+
event.serverURL,
30+
event.username,
31+
event.appPassword,
32+
isSelfSignedCertificate: event.isSelfSignedCertificate,
33+
);
4534

4635
authenticationBloc.add(LoggedIn(appAuthentication: appAuthentication));
4736
emit(LoginState());

lib/src/blocs/login/login_event.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@ class LoginButtonPressed extends LoginEvent {
1111
const LoginButtonPressed({
1212
required this.serverURL,
1313
required this.username,
14-
required this.originalBasicAuth,
14+
required this.appPassword,
1515
required this.isAppPassword,
1616
required this.isSelfSignedCertificate,
1717
});
1818
final String serverURL;
1919
final String username;
20-
final String originalBasicAuth;
20+
final String appPassword;
2121
final bool isAppPassword;
2222
final bool isSelfSignedCertificate;
2323

Lines changed: 11 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,18 @@
11
import 'dart:convert';
22

3-
import 'package:dio/dio.dart';
4-
import 'package:dio/io.dart';
53
import 'package:equatable/equatable.dart';
64
import 'package:json_annotation/json_annotation.dart';
75

86
part 'app_authentication.g.dart';
97

108
@JsonSerializable()
119
class AppAuthentication extends Equatable {
12-
AppAuthentication({
10+
const AppAuthentication({
1311
required this.server,
1412
required this.loginName,
15-
required this.basicAuth,
13+
required this.appPassword,
1614
required this.isSelfSignedCertificate,
17-
}) {
18-
authenticatedClient.options
19-
..headers['authorization'] = basicAuth
20-
..headers['User-Agent'] = 'Cookbook App'
21-
..responseType = ResponseType.plain;
22-
23-
if (isSelfSignedCertificate) {
24-
authenticatedClient.httpClientAdapter = IOHttpClientAdapter(
25-
onHttpClientCreate: (client) {
26-
client.badCertificateCallback = (cert, host, port) => true;
27-
return client;
28-
},
29-
);
30-
}
31-
}
15+
});
3216

3317
factory AppAuthentication.fromJsonString(String jsonString) =>
3418
AppAuthentication.fromJson(
@@ -40,40 +24,37 @@ class AppAuthentication extends Equatable {
4024
return _$AppAuthenticationFromJson(jsonData);
4125
// ignore: avoid_catching_errors
4226
} on TypeError {
43-
final basicAuth = parseBasicAuth(
44-
jsonData['loginName'] as String,
45-
jsonData['appPassword'] as String,
46-
);
27+
final basicAuth = jsonData['basicAuth'] as String?;
28+
final appPassword =
29+
jsonData['appPassword'] as String? ?? parseBasicAuth(basicAuth!);
4730

4831
final selfSignedCertificate =
4932
jsonData['isSelfSignedCertificate'] as bool? ?? false;
5033

5134
return AppAuthentication(
5235
server: jsonData['server'] as String,
5336
loginName: jsonData['loginName'] as String,
54-
basicAuth: basicAuth,
37+
appPassword: appPassword,
5538
isSelfSignedCertificate: selfSignedCertificate,
5639
);
5740
}
5841
}
5942
final String server;
6043
final String loginName;
61-
final String basicAuth;
44+
final String appPassword;
6245
final bool isSelfSignedCertificate;
6346

64-
final Dio authenticatedClient = Dio();
65-
6647
String toJsonString() => json.encode(toJson());
6748
Map<String, dynamic> toJson() => _$AppAuthenticationToJson(this);
6849

69-
String get password {
50+
static String parseBasicAuth(String basicAuth) {
7051
final base64 = basicAuth.substring(6);
7152
final string = utf8.decode(base64Decode(base64));
7253
final auth = string.split(':');
7354
return auth[1];
7455
}
7556

76-
static String parseBasicAuth(String loginName, String appPassword) {
57+
static String parsePassword(String loginName, String appPassword) {
7758
return 'Basic ${base64Encode(utf8.encode('$loginName:$appPassword'))}';
7859
}
7960

@@ -85,7 +66,7 @@ class AppAuthentication extends Equatable {
8566
List<Object?> get props => [
8667
server,
8768
loginName,
88-
basicAuth,
69+
appPassword,
8970
isSelfSignedCertificate,
9071
];
9172
}

lib/src/models/app_authentication.g.dart

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/src/screens/form/login_form.dart

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import 'package:flutter_bloc/flutter_bloc.dart';
33
import 'package:flutter_spinkit/flutter_spinkit.dart';
44
import 'package:flutter_translate/flutter_translate.dart';
55
import 'package:nextcloud_cookbook_flutter/src/blocs/login/login_bloc.dart';
6-
import 'package:nextcloud_cookbook_flutter/src/models/app_authentication.dart';
76
import 'package:nextcloud_cookbook_flutter/src/services/services.dart';
87
import 'package:nextcloud_cookbook_flutter/src/util/url_validator.dart';
98
import 'package:nextcloud_cookbook_flutter/src/widget/checkbox_form_field.dart';
@@ -66,14 +65,12 @@ class _LoginFormState extends State<LoginForm> with WidgetsBindingObserver {
6665
final serverUrl = URLUtils.sanitizeUrl(_serverUrl.text);
6766
final username = _username.text.trim();
6867
final password = _password.text.trim();
69-
final originalBasicAuth =
70-
AppAuthentication.parseBasicAuth(username, password);
7168

7269
BlocProvider.of<LoginBloc>(context).add(
7370
LoginButtonPressed(
7471
serverURL: serverUrl,
7572
username: username,
76-
originalBasicAuth: originalBasicAuth,
73+
appPassword: password,
7774
isAppPassword: advancedIsAppPassword,
7875
isSelfSignedCertificate: advancedIsSelfSignedCertificate,
7976
),

lib/src/services/api_provider.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ class ApiProvider {
1212
ncCookbookApi.setBasicAuth(
1313
'app_password',
1414
auth.loginName,
15-
auth.password,
15+
auth.appPassword,
1616
);
1717
recipeApi = ncCookbookApi.getRecipesApi();
1818
categoryApi = ncCookbookApi.getCategoriesApi();

lib/src/services/authentication_provider.dart

Lines changed: 6 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -6,91 +6,6 @@ class AuthenticationProvider {
66
AppAuthentication? currentAppAuthentication;
77
dio.CancelToken? _cancelToken;
88

9-
Future<AppAuthentication> authenticate({
10-
required String serverUrl,
11-
required String username,
12-
required String originalBasicAuth,
13-
required bool isSelfSignedCertificate,
14-
}) async {
15-
assert(URLUtils.isSanitized(serverUrl));
16-
17-
final urlInitialCall = '$serverUrl/ocs/v2.php/core/getapppassword';
18-
19-
dio.Response response;
20-
try {
21-
final client = dio.Dio();
22-
if (isSelfSignedCertificate) {
23-
client.httpClientAdapter = IOHttpClientAdapter(
24-
onHttpClientCreate: (client) {
25-
client.badCertificateCallback = (cert, host, port) => true;
26-
return client;
27-
},
28-
);
29-
}
30-
31-
response = await client.get(
32-
urlInitialCall,
33-
options: dio.Options(
34-
headers: {
35-
'OCS-APIREQUEST': 'true',
36-
'User-Agent': 'Cookbook App',
37-
'authorization': originalBasicAuth
38-
},
39-
validateStatus: (status) => status! < 500,
40-
),
41-
cancelToken: _cancelToken,
42-
);
43-
} on dio.DioError catch (e) {
44-
if (e.message?.contains('SocketException') ?? false) {
45-
throw translate(
46-
'login.errors.not_reachable',
47-
args: {'server_url': serverUrl, 'error_msg': e},
48-
);
49-
} else if (e.message?.contains('CERTIFICATE_VERIFY_FAILED') ?? false) {
50-
throw translate(
51-
'login.errors.certificate_failed',
52-
args: {'server_url': serverUrl, 'error_msg': e},
53-
);
54-
}
55-
throw translate('login.errors.request_failed', args: {'error_msg': e});
56-
}
57-
_cancelToken = null;
58-
59-
if (response.statusCode == 200) {
60-
String appPassword;
61-
try {
62-
appPassword = XmlDocument.parse(response.data as String)
63-
.findAllElements('apppassword')
64-
.first
65-
.text;
66-
} on XmlParserException catch (e) {
67-
throw translate('login.errors.parse_failed', args: {'error_msg': e});
68-
// ignore: avoid_catching_errors
69-
} on StateError catch (e) {
70-
throw translate('login.errors.parse_missing', args: {'error_msg': e});
71-
}
72-
73-
final basicAuth = AppAuthentication.parseBasicAuth(username, appPassword);
74-
75-
return AppAuthentication(
76-
server: serverUrl,
77-
loginName: username,
78-
basicAuth: basicAuth,
79-
isSelfSignedCertificate: isSelfSignedCertificate,
80-
);
81-
} else if (response.statusCode == 401) {
82-
throw translate('login.errors.auth_failed');
83-
} else {
84-
throw translate(
85-
'login.errors.failure',
86-
args: {
87-
'status_code': response.statusCode,
88-
'status_message': response.statusMessage,
89-
},
90-
);
91-
}
92-
}
93-
949
Future<AppAuthentication> authenticateAppPassword({
9510
required String serverUrl,
9611
required String username,
@@ -125,7 +40,7 @@ class AuthenticationProvider {
12540
return AppAuthentication(
12641
server: serverUrl,
12742
loginName: username,
128-
basicAuth: basicAuth,
43+
appPassword: basicAuth,
12944
isSelfSignedCertificate: isSelfSignedCertificate,
13045
);
13146
} else {
@@ -221,10 +136,14 @@ class AuthenticationProvider {
221136
Future<void> deleteAppAuthentication() async {
222137
dio.Response? response;
223138
try {
224-
response = await currentAppAuthentication?.authenticatedClient.delete(
139+
response = await Dio().delete(
225140
'${currentAppAuthentication!.server}/ocs/v2.php/core/apppassword',
226141
options: dio.Options(
227142
headers: {
143+
'Authorization': AppAuthentication.parsePassword(
144+
currentAppAuthentication!.loginName,
145+
currentAppAuthentication!.appPassword,
146+
),
228147
'OCS-APIREQUEST': 'true',
229148
},
230149
),

lib/src/services/services.dart

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import 'package:nextcloud_cookbook_flutter/src/screens/recipe_import_screen.dart
1818
import 'package:nextcloud_cookbook_flutter/src/util/url_validator.dart';
1919
import 'package:timezone/data/latest_10y.dart' as tz;
2020
import 'package:timezone/timezone.dart' as tz;
21-
import 'package:xml/xml.dart';
2221

2322
part 'api_provider.dart';
2423
part 'authentication_provider.dart';

lib/src/services/user_repository.dart

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,6 @@ class UserRepository {
99

1010
AuthenticationProvider authenticationProvider = AuthenticationProvider();
1111

12-
Future<AppAuthentication> authenticate(
13-
String serverUrl,
14-
String username,
15-
String originalBasicAuth, {
16-
required bool isSelfSignedCertificate,
17-
}) async {
18-
return authenticationProvider.authenticate(
19-
serverUrl: serverUrl,
20-
username: username,
21-
originalBasicAuth: originalBasicAuth,
22-
isSelfSignedCertificate: isSelfSignedCertificate,
23-
);
24-
}
25-
2612
Future<AppAuthentication> authenticateAppPassword(
2713
String serverUrl,
2814
String username,
@@ -45,10 +31,6 @@ class UserRepository {
4531
return authenticationProvider.currentAppAuthentication!;
4632
}
4733

48-
Dio get authenticatedClient {
49-
return currentAppAuthentication.authenticatedClient;
50-
}
51-
5234
Future<bool> hasAppAuthentication() async {
5335
return authenticationProvider.hasAppAuthentication();
5436
}
@@ -60,7 +42,7 @@ class UserRepository {
6042
Future<bool> checkAppAuthentication() async {
6143
return authenticationProvider.checkAppAuthentication(
6244
currentAppAuthentication.server,
63-
currentAppAuthentication.basicAuth,
45+
currentAppAuthentication.appPassword,
6446
isSelfSignedCertificate: currentAppAuthentication.isSelfSignedCertificate,
6547
);
6648
}

lib/src/widget/user_image.dart

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import 'package:cached_network_image/cached_network_image.dart';
22
import 'package:flutter/material.dart';
3+
import 'package:nextcloud_cookbook_flutter/src/models/app_authentication.dart';
34
import 'package:nextcloud_cookbook_flutter/src/services/services.dart';
45

56
class UserImage extends StatelessWidget {
@@ -10,15 +11,15 @@ class UserImage extends StatelessWidget {
1011
@override
1112
Widget build(BuildContext context) {
1213
final url = DataRepository().getUserAvatarUrl();
13-
final appAuthentication = UserRepository().currentAppAuthentication;
14+
final auth = UserRepository().currentAppAuthentication;
1415

1516
return CircleAvatar(
1617
backgroundColor: Colors.grey[400],
1718
child: ClipOval(
1819
child: CachedNetworkImage(
1920
fit: BoxFit.fill,
2021
httpHeaders: {
21-
'Authorization': appAuthentication.basicAuth,
22+
'Authorization': AppAuthentication.parsePassword(auth.loginName, auth.appPassword),
2223
'Accept': 'image/jpeg'
2324
},
2425
imageUrl: url,

0 commit comments

Comments
 (0)