1
0
mirror of https://github.com/go-vikunja/app synced 2024-06-01 02:06:51 +00:00

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:convert';
import 'dart:core'; import 'dart:core';
import 'dart:developer'; import 'dart:developer';
import 'dart:io';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:http/http.dart' as http; import 'package:http/http.dart' as http;
import 'package:vikunja_app/api/response.dart'; import 'package:vikunja_app/api/response.dart';
@ -15,19 +16,24 @@ class Client {
String _token; String _token;
String _base; String _base;
bool authenticated; bool authenticated;
bool ignoreCertificates = false;
String get base => _base; String get base => _base;
String get token => _token; String get token => _token;
//Client(this._token, String base, {this.authenticated = true}) String post_body;
// : _base = base.endsWith('/api/v1') ? base : '$base/api/v1';
HttpClient client = new HttpClient();
bool operator ==(dynamic otherClient) { bool operator ==(dynamic otherClient) {
return otherClient._token == _token; return otherClient._token == _token;
} }
Client(this.global, {String token, String base, bool authenticated = false}) 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 => { get _headers => {
'Authorization': _token != null ? 'Bearer $_token' : '', 'Authorization': _token != null ? 'Bearer $_token' : '',
@ -46,6 +52,8 @@ class Client {
this.authenticated = authenticated; this.authenticated = authenticated;
} }
void reset() { void reset() {
_token = _base = null; _token = _base = null;
authenticated = false; authenticated = false;
@ -66,37 +74,34 @@ class Client {
queryParameters: queryParameters, 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. // 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); fragment: uri.fragment);
return http.get(newUri, headers: _headers) return client.getUrl(newUri)
.then(_handleResponse, onError: _handleError); .then(_handleResponseF, onError: _handleError);
} }
Future<Response> delete(String url) { Future<Response> delete(String url) {
return http return client
.delete( .deleteUrl(
'${this.base}$url'.toUri(), '${this.base}$url'.toUri(),
headers: _headers,
) )
.then(_handleResponse, onError: _handleError); .then(_handleResponseF, onError: _handleError);
} }
Future<Response> post(String url, {dynamic body}) { Future<Response> post(String url, {dynamic body}) {
return http post_body = _encoder.convert(body);
.post( return client
.postUrl(
'${this.base}$url'.toUri(), '${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}) { Future<Response> put(String url, {dynamic body}) {
return http post_body = _encoder.convert(body);
.put( return client
.putUrl(
'${this.base}$url'.toUri(), '${this.base}$url'.toUri(),
headers: _headers,
body: _encoder.convert(body),
) )
.then(_handleResponse, onError: _handleError); .then(_handleResponseF, onError: _handleError);
} }
void _handleError(dynamic e) { void _handleError(dynamic e) {
@ -105,7 +110,36 @@ class Client {
global.currentState?.showSnackBar(snackBar); 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 || if (response.statusCode < 200 ||
response.statusCode >= 400 || response.statusCode >= 400 ||
json == null) { json == null) {
@ -113,7 +147,7 @@ class Client {
if (response.statusCode ~/ 100 == 4) { if (response.statusCode ~/ 100 == 4) {
throw new InvalidRequestApiException( throw new InvalidRequestApiException(
response.statusCode, response.statusCode,
response.request.url.toString(), "",
error["message"] ?? "Unknown Error"); error["message"] ?? "Unknown Error");
} }
final SnackBar snackBar = SnackBar( final SnackBar snackBar = SnackBar(
@ -132,10 +166,8 @@ class Client {
); );
global.currentState?.showSnackBar(snackBar); global.currentState?.showSnackBar(snackBar);
throw new ApiException( 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:async';
import 'dart:developer';
import 'package:vikunja_app/api/client.dart'; import 'package:vikunja_app/api/client.dart';
import 'package:vikunja_app/api/response.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); ServerService get serverService => new ServerAPIService(client);
SettingsManager get settingsManager => new SettingsManager(_storage);
NamespaceService get namespaceService => new NamespaceAPIService(client); NamespaceService get namespaceService => new NamespaceAPIService(client);
TaskService get taskService => new TaskAPIService(client); TaskService get taskService => new TaskAPIService(client);
@ -108,6 +110,7 @@ class VikunjaGlobalState extends State<VikunjaGlobal> {
void initState() { void initState() {
super.initState(); super.initState();
_client = Client(snackbarKey); _client = Client(snackbarKey);
settingsManager.getIgnoreCertificates().then((value) => value == "1" ? client.ignoreCertificates = true : client.ignoreCertificates = false);
_newUserService = UserAPIService(client); _newUserService = UserAPIService(client);
_loadCurrentUser(); _loadCurrentUser();
tz.initializeTimeZones(); tz.initializeTimeZones();
@ -117,6 +120,7 @@ class VikunjaGlobalState extends State<VikunjaGlobal> {
platformChannelSpecificsReminders = notifs.NotificationDetails( platformChannelSpecificsReminders = notifs.NotificationDetails(
android: androidSpecificsReminders, iOS: iOSSpecifics); android: androidSpecificsReminders, iOS: iOSSpecifics);
notificationInitializer(); notificationInitializer();
} }
void changeUser(User newUser, {String token, String base}) async { 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')), InputDecoration(labelText: 'Add a new label')),
suggestionsCallback: (pattern) => _searchLabel(pattern), suggestionsCallback: (pattern) => _searchLabel(pattern),
itemBuilder: (context, suggestion) { itemBuilder: (context, suggestion) {
return Text(suggestion); print(suggestion);
return new ListTile(title: Text(suggestion));
}, },
transitionBuilder: (context, suggestionsBox, controller) { transitionBuilder: (context, suggestionsBox, controller) {
return suggestionsBox; return suggestionsBox;
@ -364,11 +365,11 @@ class _TaskEditPageState extends State<TaskEditPage> {
.labelService .labelService
.getAll(query: query) .getAll(query: query)
.then((labels) { .then((labels) {
log("searched");
// Only show those labels which aren't already added to the task // Only show those labels which aren't already added to the task
labels.removeWhere((labelToRemove) => _labels.contains(labelToRemove)); labels.removeWhere((labelToRemove) => _labels.contains(labelToRemove));
_suggestedLabels = labels; _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> { class SettingsPageState extends State<SettingsPage> {
List<TaskList> taskListList; List<TaskList> taskListList;
int defaultList; int defaultList;
bool ignoreCertificates;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -19,6 +20,9 @@ class SettingsPageState extends State<SettingsPage> {
VikunjaGlobal.of(context).listService.getAll().then((value) => setState(() => taskListList = value)); VikunjaGlobal.of(context).listService.getAll().then((value) => setState(() => taskListList = value));
if(defaultList == null) if(defaultList == null)
VikunjaGlobal.of(context).listService.getDefaultList().then((value) => setState(() => defaultList = value == null ? null : int.tryParse(value))); 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( return new Scaffold(
appBar: AppBar(title: Text("Settings"),), appBar: AppBar(title: Text("Settings"),),
body: Column( body: Column(
@ -33,7 +37,13 @@ class SettingsPageState extends State<SettingsPage> {
setState(() => defaultList = value); setState(() => defaultList = value);
VikunjaGlobal.of(context).listService.setDefaultList(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:async';
import 'dart:developer'; import 'dart:developer';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:vikunja_app/api/response.dart'; import 'package:vikunja_app/api/response.dart';
import 'package:vikunja_app/models/label.dart'; import 'package:vikunja_app/models/label.dart';
import 'package:vikunja_app/models/labelTask.dart'; import 'package:vikunja_app/models/labelTask.dart';
@ -138,4 +139,27 @@ abstract class LabelTaskBulkService {
abstract class ServerService { abstract class ServerService {
Future<Server> getInfo(); 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");
}
} }