switched to HttpClient so CertificateErrors can be ignored

added option to ignore CertificateErrors
This commit is contained in:
benimautner 2022-07-18 23:25:47 +02:00
parent 6a2e41bc86
commit 6f43c9357d
7 changed files with 100 additions and 46 deletions

View File

@ -1,18 +0,0 @@
#
# NOTE: This podspec is NOT to be published. It is only used as a local source!
#
Pod::Spec.new do |s|
s.name = 'Flutter'
s.version = '1.0.0'
s.summary = 'High-performance, high-fidelity mobile apps.'
s.description = <<-DESC
Flutter provides an easy and productive way to build and deploy high-performance mobile apps for Android and iOS.
DESC
s.homepage = 'https://flutter.io'
s.license = { :type => 'MIT' }
s.author = { 'Flutter Dev Team' => 'flutter-dev@googlegroups.com' }
s.source = { :git => 'https://github.com/flutter/engine', :tag => s.version.to_s }
s.ios.deployment_target = '8.0'
s.vendored_frameworks = 'Flutter.framework'
end

View File

@ -2,6 +2,7 @@ import 'dart:async';
import 'dart:convert';
import 'dart:core';
import 'dart:developer';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:vikunja_app/api/response.dart';
@ -15,19 +16,24 @@ class Client {
String _token;
String _base;
bool authenticated;
bool ignoreCertificates = false;
String get base => _base;
String get token => _token;
//Client(this._token, String base, {this.authenticated = true})
// : _base = base.endsWith('/api/v1') ? base : '$base/api/v1';
String post_body;
HttpClient client = new HttpClient();
bool operator ==(dynamic otherClient) {
return otherClient._token == _token;
}
Client(this.global, {String token, String base, bool authenticated = false})
{ configure(token: token, base: base, authenticated: authenticated);}
{
configure(token: token, base: base, authenticated: authenticated);
client.badCertificateCallback = (_,__,___) => ignoreCertificates;
}
get _headers => {
'Authorization': _token != null ? 'Bearer $_token' : '',
@ -46,6 +52,8 @@ class Client {
this.authenticated = authenticated;
}
void reset() {
_token = _base = null;
authenticated = false;
@ -66,37 +74,34 @@ class Client {
queryParameters: queryParameters,
// Because dart takes a Map<String, String> here, it is only possible to sort by one parameter while the api supports n parameters.
fragment: uri.fragment);
return http.get(newUri, headers: _headers)
.then(_handleResponse, onError: _handleError);
return client.getUrl(newUri)
.then(_handleResponseF, onError: _handleError);
}
Future<Response> delete(String url) {
return http
.delete(
return client
.deleteUrl(
'${this.base}$url'.toUri(),
headers: _headers,
)
.then(_handleResponse, onError: _handleError);
.then(_handleResponseF, onError: _handleError);
}
Future<Response> post(String url, {dynamic body}) {
return http
.post(
post_body = _encoder.convert(body);
return client
.postUrl(
'${this.base}$url'.toUri(),
headers: _headers,
body: _encoder.convert(body),
)
.then(_handleResponse, onError: _handleError);
.then(_handleResponseF, onError: _handleError);
}
Future<Response> put(String url, {dynamic body}) {
return http
.put(
post_body = _encoder.convert(body);
return client
.putUrl(
'${this.base}$url'.toUri(),
headers: _headers,
body: _encoder.convert(body),
)
.then(_handleResponse, onError: _handleError);
.then(_handleResponseF, onError: _handleError);
}
void _handleError(dynamic e) {
@ -105,7 +110,36 @@ class Client {
global.currentState?.showSnackBar(snackBar);
}
Response _handleResponse(http.Response response) {
Map<String,String> headersToMap(HttpHeaders headers) {
Map<String,String> map = {};
headers.forEach((name, values) {map[name] = values[0].toString();});
return map;
}
Future<Response> _handleResponseF(HttpClientRequest request) {
_headers.forEach((k, v) => request.headers.set(k, v));
if(post_body != "") {
request.write(post_body);
post_body = "";
}
return request.close().then((response) {
final completer = Completer<String>();
final contents = StringBuffer();
response.transform(utf8.decoder).listen((data) {
contents.write(data);
}, onDone: () => completer.complete(contents.toString()));
return completer.future.then((body) {
Response res = Response(json.decode(body), response.statusCode, headersToMap(response.headers));
_handleResponseErrors(res);
return res;
});
});
//return Response(body, statusCode, headers)
}
void _handleResponseErrors(Response response) {
if (response.statusCode < 200 ||
response.statusCode >= 400 ||
json == null) {
@ -113,7 +147,7 @@ class Client {
if (response.statusCode ~/ 100 == 4) {
throw new InvalidRequestApiException(
response.statusCode,
response.request.url.toString(),
"",
error["message"] ?? "Unknown Error");
}
final SnackBar snackBar = SnackBar(
@ -132,10 +166,8 @@ class Client {
);
global.currentState?.showSnackBar(snackBar);
throw new ApiException(
response.statusCode, response.request.url.toString());
response.statusCode, "");
}
return Response(
_decoder.convert(response.body), response.statusCode, response.headers);
}
}

View File

@ -1,4 +1,5 @@
import 'dart:async';
import 'dart:developer';
import 'package:vikunja_app/api/client.dart';
import 'package:vikunja_app/api/response.dart';

View File

@ -61,6 +61,8 @@ class VikunjaGlobalState extends State<VikunjaGlobal> {
ServerService get serverService => new ServerAPIService(client);
SettingsManager get settingsManager => new SettingsManager(_storage);
NamespaceService get namespaceService => new NamespaceAPIService(client);
TaskService get taskService => new TaskAPIService(client);
@ -108,6 +110,7 @@ class VikunjaGlobalState extends State<VikunjaGlobal> {
void initState() {
super.initState();
_client = Client(snackbarKey);
settingsManager.getIgnoreCertificates().then((value) => value == "1" ? client.ignoreCertificates = true : client.ignoreCertificates = false);
_newUserService = UserAPIService(client);
_loadCurrentUser();
tz.initializeTimeZones();
@ -117,6 +120,7 @@ class VikunjaGlobalState extends State<VikunjaGlobal> {
platformChannelSpecificsReminders = notifs.NotificationDetails(
android: androidSpecificsReminders, iOS: iOSSpecifics);
notificationInitializer();
}
void changeUser(User newUser, {String token, String base}) async {

View File

@ -262,7 +262,8 @@ class _TaskEditPageState extends State<TaskEditPage> {
InputDecoration(labelText: 'Add a new label')),
suggestionsCallback: (pattern) => _searchLabel(pattern),
itemBuilder: (context, suggestion) {
return Text(suggestion);
print(suggestion);
return new ListTile(title: Text(suggestion));
},
transitionBuilder: (context, suggestionsBox, controller) {
return suggestionsBox;
@ -364,11 +365,11 @@ class _TaskEditPageState extends State<TaskEditPage> {
.labelService
.getAll(query: query)
.then((labels) {
log("searched");
// Only show those labels which aren't already added to the task
labels.removeWhere((labelToRemove) => _labels.contains(labelToRemove));
_suggestedLabels = labels;
return labels.map((label) => label.title).toList();
List<String> labelText = labels.map((label) => label.title).toList();
return labelText;
});
}

View File

@ -12,6 +12,7 @@ class SettingsPage extends StatefulWidget {
class SettingsPageState extends State<SettingsPage> {
List<TaskList> taskListList;
int defaultList;
bool ignoreCertificates;
@override
Widget build(BuildContext context) {
@ -19,6 +20,9 @@ class SettingsPageState extends State<SettingsPage> {
VikunjaGlobal.of(context).listService.getAll().then((value) => setState(() => taskListList = value));
if(defaultList == null)
VikunjaGlobal.of(context).listService.getDefaultList().then((value) => setState(() => defaultList = value == null ? null : int.tryParse(value)));
VikunjaGlobal.of(context).settingsManager.getIgnoreCertificates().then((value) => setState(() => ignoreCertificates = value == "1" ? true:false));
return new Scaffold(
appBar: AppBar(title: Text("Settings"),),
body: Column(
@ -33,7 +37,13 @@ class SettingsPageState extends State<SettingsPage> {
setState(() => defaultList = value);
VikunjaGlobal.of(context).listService.setDefaultList(value);
},
),) : ListTile(title: Text("..."),)
),) : ListTile(title: Text("..."),),
ignoreCertificates != null ?
CheckboxListTile(title: Text("Ignore Certificates"), value: ignoreCertificates, onChanged: (value) {
setState(() => ignoreCertificates = value);
VikunjaGlobal.of(context).settingsManager.setIgnoreCertificates(value);
VikunjaGlobal.of(context).client.ignoreCertificates = value;
}) : ListTile(title: Text("..."))
],
),
);

View File

@ -1,6 +1,7 @@
import 'dart:async';
import 'dart:developer';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:vikunja_app/api/response.dart';
import 'package:vikunja_app/models/label.dart';
import 'package:vikunja_app/models/labelTask.dart';
@ -138,4 +139,27 @@ abstract class LabelTaskBulkService {
abstract class ServerService {
Future<Server> getInfo();
}
class SettingsManager {
final FlutterSecureStorage _storage;
Map<String,String> defaults = {
"ignore-certificates" : "0"
};
SettingsManager(this._storage) {
defaults.forEach((key, value) {
_storage.containsKey(key: key).then((is_created) {
if (!is_created)
_storage.write(key: key, value: value);
});});}
Future<String> getIgnoreCertificates() {
return _storage.read(key: "ignore-certificates");
}
void setIgnoreCertificates(bool value) {
_storage.write(key: "ignore-certificates", value: value ? "1" : "0");
}
}