Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support User CAs #72

Merged
merged 3 commits into from
Apr 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ if (keystorePropertiesFile.exists()) {
}

android {
compileSdkVersion 33
compileSdkVersion 34

sourceSets {
main.java.srcDirs += 'src/main/kotlin'
Expand All @@ -42,7 +42,7 @@ android {
defaultConfig {
applicationId "io.vikunja.app"
minSdkVersion 21
targetSdkVersion 33
targetSdkVersion 34
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
Expand Down
6 changes: 4 additions & 2 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@
android:label="Vikunja"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher"
android:usesCleartextTraffic="true">
android:networkSecurityConfig="@xml/network_security_config"
>
<meta-data android:name="io.flutter.network-policy" android:resource="@xml/network_security_config"/>
<activity
android:name=".MainActivity"
android:launchMode="singleTop"
Expand Down Expand Up @@ -106,4 +108,4 @@
</provider>
</application>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
</manifest>
</manifest>
9 changes: 9 additions & 0 deletions android/app/src/main/res/xml/network_security_config.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<certificates src="system" />
<certificates src="user" />
</trust-anchors>
</base-config>
</network-security-config>
2 changes: 1 addition & 1 deletion android/build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
buildscript {
ext.kotlin_version = '1.7.20'
ext.kotlin_version = '1.9.23'
repositories {
google()
mavenCentral()
Expand Down
Empty file modified android/gradlew
100644 → 100755
Empty file.
59 changes: 45 additions & 14 deletions lib/api/client.dart
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import 'dart:async';
import 'dart:convert';
import 'dart:core';
import 'dart:io';
import 'package:cronet_http/cronet_http.dart' as cronet_http;
import 'package:cupertino_http/cupertino_http.dart' as cupertino_http;
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:http/io_client.dart' as io_client;
import 'package:vikunja_app/api/response.dart';
import 'package:vikunja_app/components/string_extension.dart';
import 'package:vikunja_app/global.dart';
Expand All @@ -25,16 +27,42 @@ class Client {

String? post_body;

bool operator ==(dynamic otherClient) {
@override
bool operator ==(Object otherClient) {
if (otherClient is! Client) return false;
return otherClient._token == _token;
}

Client(this.global_scaffold_key,
{String? token, String? base, bool authenticated = false}) {
configure(token: token, base: base, authenticated: authenticated);
Client(
this.global_scaffold_key, {
String? token,
String? base,
bool authenticated = false,
}) {
configure(
token: token,
base: base,
authenticated: authenticated,
);
}

http.Client get httpClient {
if (Platform.isAndroid) {
final engine = cronet_http.CronetEngine.build(
cacheMode: cronet_http.CacheMode.memory, cacheMaxSize: 1000000);
return cronet_http.CronetClient.fromCronetEngine(engine);
}
if (Platform.isIOS || Platform.isMacOS) {
final config =
cupertino_http.URLSessionConfiguration.ephemeralSessionConfiguration()
..cache =
cupertino_http.URLCache.withCapacity(memoryCapacity: 1000000);
return cupertino_http.CupertinoClient.fromSessionConfiguration(config);
}
return io_client.IOClient();
}

void reload_ignore_certs(bool? val) {
void reloadIgnoreCerts(bool? val) {
ignoreCertificates = val ?? false;
HttpOverrides.global = new IgnoreCertHttpOverrides(ignoreCertificates);
if (global_scaffold_key == null ||
Expand All @@ -47,15 +75,19 @@ class Client {
get _headers => {
'Authorization': _token != '' ? 'Bearer $_token' : '',
'Content-Type': 'application/json',
'User-Agent': 'Vikunja Mobile App'
'User-Agent': 'Vikunja Mobile App',
};

get headers => _headers;

@override
int get hashCode => _token.hashCode;

void configure({String? token, String? base, bool? authenticated}) {
void configure({
String? token,
String? base,
bool? authenticated,
}) {
if (token != null) _token = token;
if (base != null) {
base = base.replaceAll(" ", "");
Expand All @@ -66,7 +98,6 @@ class Client {
}

void reset() {
_token = _base = '';
authenticated = false;
}

Expand All @@ -85,14 +116,14 @@ class Client {
queryParameters: queryParameters,
fragment: uri.fragment);

return http
return httpClient
.get(uri, headers: _headers)
.then(_handleResponse)
.onError((error, stackTrace) => _handleError(error, stackTrace));
}

Future<Response?> delete(String url) {
return http
return httpClient
.delete(
'${this.base}$url'.toUri()!,
headers: _headers,
Expand All @@ -102,7 +133,7 @@ class Client {
}

Future<Response?> post(String url, {dynamic body}) {
return http
return httpClient
.post(
'${this.base}$url'.toUri()!,
headers: _headers,
Expand All @@ -113,7 +144,7 @@ class Client {
}

Future<Response?> put(String url, {dynamic body}) {
return http
return httpClient
.put(
'${this.base}$url'.toUri()!,
headers: _headers,
Expand Down Expand Up @@ -183,7 +214,7 @@ class Client {
}

Response? _handleResponse(http.Response response) {
Error? error = _handleResponseErrors(response);
_handleResponseErrors(response);
return Response(
_decoder.convert(response.body), response.statusCode, response.headers);
}
Expand Down
2 changes: 1 addition & 1 deletion lib/global.dart
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ class VikunjaGlobalState extends State<VikunjaGlobal> {
_client = Client(snackbarKey);
settingsManager
.getIgnoreCertificates()
.then((value) => client.reload_ignore_certs(value == "1"));
.then((value) => client.reloadIgnoreCerts(value == "1"));
_newUserService = UserAPIService(client);
_loadCurrentUser();
tz.initializeTimeZones();
Expand Down
2 changes: 1 addition & 1 deletion lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ void callbackDispatcher() {
.getIgnoreCertificates()
.then((value) async {
print("ignoring: $value");
client.reload_ignore_certs(value == "1");
client.reloadIgnoreCerts(value == "1");

TaskAPIService taskService = TaskAPIService(client);
NotificationClass nc = NotificationClass();
Expand Down
13 changes: 7 additions & 6 deletions lib/managers/notifications.dart
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class NotificationClass {
channelDescription: "description",
icon: 'vikunja_notification_logo',
importance: notifs.Importance.high);
late notifs.IOSNotificationDetails iOSSpecifics;
late notifs.DarwinNotificationDetails iOSSpecifics;
late notifs.NotificationDetails platformChannelSpecificsDueDate;
late notifs.NotificationDetails platformChannelSpecificsReminders;

Expand All @@ -48,7 +48,7 @@ class NotificationClass {
Future<void> _initNotifications() async {
var initializationSettingsAndroid =
notifs.AndroidInitializationSettings('vikunja_logo');
var initializationSettingsIOS = notifs.IOSInitializationSettings(
var initializationSettingsIOS = notifs.DarwinInitializationSettings(
requestAlertPermission: false,
requestBadgePermission: false,
requestSoundPermission: false,
Expand All @@ -60,17 +60,18 @@ class NotificationClass {
var initializationSettings = notifs.InitializationSettings(
android: initializationSettingsAndroid, iOS: initializationSettingsIOS);
await notificationsPlugin.initialize(initializationSettings,
onSelectNotification: (String? payload) async {
onDidReceiveNotificationResponse:
(notifs.NotificationResponse resp) async {
if (payload != null) {
print('notification payload: ' + payload);
selectNotificationSubject.add(payload);
print('notification payload: ' + resp.payload!);
selectNotificationSubject.add(resp.payload!);
}
});
print("Notifications initialised successfully");
}

Future<void> notificationInitializer() async {
iOSSpecifics = notifs.IOSNotificationDetails();
iOSSpecifics = notifs.DarwinNotificationDetails();
platformChannelSpecificsDueDate = notifs.NotificationDetails(
android: androidSpecificsDueDate, iOS: iOSSpecifics);
platformChannelSpecificsReminders = notifs.NotificationDetails(
Expand Down
2 changes: 1 addition & 1 deletion lib/pages/settings.dart
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ class SettingsPageState extends State<SettingsPage> {
value: ignoreCertificates,
onChanged: (value) {
setState(() => ignoreCertificates = value);
VikunjaGlobal.of(context).client.reload_ignore_certs(value);
VikunjaGlobal.of(context).client.reloadIgnoreCerts(value);
})
: ListTile(title: Text("...")),
Divider(),
Expand Down
2 changes: 1 addition & 1 deletion lib/pages/user/login.dart
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ class _LoginPageState extends State<LoginPage> {
value: client.ignoreCertificates,
onChanged: (value) {
setState(
() => client.reload_ignore_certs(value ?? false));
() => client.reloadIgnoreCerts(value ?? false));
VikunjaGlobal.of(context)
.settingsManager
.setIgnoreCertificates(value ?? false);
Expand Down
Loading
Loading