Skip to content

Commit

Permalink
switched to HttpClient so CertificateErrors can be ignored
Browse files Browse the repository at this point in the history
added option to ignore CertificateErrors
  • Loading branch information
Benimautner committed Jul 18, 2022
1 parent 6a2e41b commit 6f43c93
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 46 deletions.
18 changes: 0 additions & 18 deletions ios/Flutter/Flutter.podspec

This file was deleted.

80 changes: 56 additions & 24 deletions lib/api/client.dart
Expand Up @@ -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';
Expand All @@ -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' : '',
Expand All @@ -46,6 +52,8 @@ class Client {
this.authenticated = authenticated;
}



void reset() {
_token = _base = null;
authenticated = false;
Expand All @@ -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) {
Expand All @@ -105,15 +110,44 @@ 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) {
Map<String, dynamic> error = _decoder.convert(response.body);
if (response.statusCode ~/ 100 == 4) {
throw new InvalidRequestApiException(
response.statusCode,
response.request.url.toString(),
"",
error["message"] ?? "Unknown Error");
}
final SnackBar snackBar = SnackBar(
Expand All @@ -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);
}
}

Expand Down
1 change: 1 addition & 0 deletions lib/api/task_implementation.dart
@@ -1,4 +1,5 @@
import 'dart:async';
import 'dart:developer';

import 'package:vikunja_app/api/client.dart';
import 'package:vikunja_app/api/response.dart';
Expand Down
4 changes: 4 additions & 0 deletions lib/global.dart
Expand Up @@ -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);
Expand Down Expand Up @@ -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();
Expand All @@ -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 {
Expand Down
7 changes: 4 additions & 3 deletions lib/pages/list/task_edit.dart
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
});
}

Expand Down
12 changes: 11 additions & 1 deletion lib/pages/settings.dart
Expand Up @@ -12,13 +12,17 @@ class SettingsPage extends StatefulWidget {
class SettingsPageState extends State<SettingsPage> {
List<TaskList> taskListList;
int defaultList;
bool ignoreCertificates;

@override
Widget build(BuildContext context) {
if(taskListList == null)
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(
Expand All @@ -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("..."))
],
),
);
Expand Down
24 changes: 24 additions & 0 deletions lib/service/services.dart
@@ -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';
Expand Down Expand Up @@ -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");
}
}

0 comments on commit 6f43c93

Please sign in to comment.