mirror of
https://github.com/immich-app/immich
synced 2025-11-14 17:36:12 +00:00
Add basic auth support for experimental networking features
This commit is contained in:
parent
bbfff64927
commit
d0db195339
4 changed files with 114 additions and 8 deletions
|
|
@ -92,8 +92,9 @@ class ApiService implements Authentication {
|
||||||
|
|
||||||
/// Takes a server URL and attempts to resolve the API endpoint.
|
/// Takes a server URL and attempts to resolve the API endpoint.
|
||||||
///
|
///
|
||||||
/// Input: [schema://]host[:port][/path]
|
/// Input: [schema://][basicAuth:password@]host[:port][/path]
|
||||||
/// schema - optional (default: https)
|
/// schema - optional (default: https)
|
||||||
|
/// userInfo - optional
|
||||||
/// host - required
|
/// host - required
|
||||||
/// port - optional (default: based on schema)
|
/// port - optional (default: based on schema)
|
||||||
/// path - optional
|
/// path - optional
|
||||||
|
|
|
||||||
|
|
@ -16,12 +16,15 @@ String? getServerUrl() {
|
||||||
if (serverUri == null) {
|
if (serverUri == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
var URIToDecodeFull = "${serverUri.scheme}://";
|
||||||
return Uri.decodeFull(
|
if (serverUri.userInfo.isNotEmpty){
|
||||||
serverUri.hasPort
|
URIToDecodeFull += "${serverUri.userInfo}@";
|
||||||
? "${serverUri.scheme}://${serverUri.host}:${serverUri.port}"
|
}
|
||||||
: "${serverUri.scheme}://${serverUri.host}",
|
URIToDecodeFull += "${serverUri.host}";
|
||||||
);
|
if(serverUri.hasPort){
|
||||||
|
URIToDecodeFull += ":${serverUri.port}";
|
||||||
|
}
|
||||||
|
return Uri.decodeFull(URIToDecodeFull);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts a Unicode URL to its ASCII-compatible encoding (Punycode).
|
/// Converts a Unicode URL to its ASCII-compatible encoding (Punycode).
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@ void main() {
|
||||||
db.writeTxnSync(() => db.clearSync());
|
db.writeTxnSync(() => db.clearSync());
|
||||||
await StoreService.init(storeRepository: IsarStoreRepository(db));
|
await StoreService.init(storeRepository: IsarStoreRepository(db));
|
||||||
});
|
});
|
||||||
|
// add test here
|
||||||
test('Should resolve HTTP endpoint', () async {
|
test('Should resolve HTTP endpoint', () async {
|
||||||
const testUrl = 'http://ip:2283';
|
const testUrl = 'http://ip:2283';
|
||||||
const resolvedUrl = 'http://ip:2283/api';
|
const resolvedUrl = 'http://ip:2283/api';
|
||||||
|
|
|
||||||
102
mobile/test/utils/url_helper_test.dart
Normal file
102
mobile/test/utils/url_helper_test.dart
Normal file
|
|
@ -0,0 +1,102 @@
|
||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
import 'package:immich_mobile/domain/models/store.model.dart';
|
||||||
|
import 'package:immich_mobile/domain/services/store.service.dart';
|
||||||
|
import 'package:immich_mobile/entities/store.entity.dart';
|
||||||
|
import 'package:immich_mobile/infrastructure/repositories/store.repository.dart';
|
||||||
|
import 'package:immich_mobile/utils/url_helper.dart';
|
||||||
|
import 'package:isar/isar.dart';
|
||||||
|
|
||||||
|
import '../test_utils.dart';
|
||||||
|
import '../fixtures/user.stub.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
late Isar db;
|
||||||
|
|
||||||
|
setUpAll(() async {
|
||||||
|
db = await TestUtils.initIsar();
|
||||||
|
await StoreService.init(storeRepository: IsarStoreRepository(db));
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
group('sanitizeUrl', () {
|
||||||
|
test('Should encode correctly', () {
|
||||||
|
var unEncodedURL = 'user:password@example.com/addSchemaAndRemovesSlashes////';
|
||||||
|
expect(sanitizeUrl(unEncodedURL), 'https://user:password@example.com/addSchemaAndRemovesSlashes');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('does not switch http to https', () {
|
||||||
|
var unEncodedURL = 'http://user:password@example.com/addSchemaAndRemovesSlashes////';
|
||||||
|
expect(sanitizeUrl(unEncodedURL), 'http://user:password@example.com/addSchemaAndRemovesSlashes');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
group('punycodeEncode', () {
|
||||||
|
test('malformed URL returns a blank string', () {
|
||||||
|
var badURL = 'example.com/missing a scheme';
|
||||||
|
expect(punycodeEncodeUrl(badURL), '');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Encodes IDNs correctly', () {
|
||||||
|
var idn = 'https://bücher.de';
|
||||||
|
expect(punycodeEncodeUrl(idn), 'https://xn--bcher-kva.de');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Keeps basic auth in encoding', () {
|
||||||
|
var basicAuthURL = 'https://user:password@example.com';
|
||||||
|
expect(punycodeEncodeUrl(basicAuthURL), 'https://user:password@example.com');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
group('punycodeDecode', () {
|
||||||
|
test('malformed URL returns a null', () {
|
||||||
|
var badURL = 'example.com/missing%20a%20scheme';
|
||||||
|
expect(punycodeDecodeUrl(badURL), null);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Decodes IDNs correctly', () {
|
||||||
|
var idn = 'https://xn--bcher-kva.de';
|
||||||
|
expect(punycodeDecodeUrl(idn), 'https://bücher.de');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Keeps basic auth in encoding', () {
|
||||||
|
var basicAuthURL = 'https://user:password@example.com/%20with%20spaces';
|
||||||
|
expect(punycodeDecodeUrl(basicAuthURL), 'https://user:password@example.com/ with spaces');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
group('getServerUrl', () {
|
||||||
|
test('Returns null if not set', () {
|
||||||
|
expect(getServerUrl(), null);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Returns null if what was set is not a correct url', () {
|
||||||
|
Store.put(StoreKey.serverEndpoint, 'example.com');
|
||||||
|
expect(getServerUrl(), null);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Returns decoded basic URL', () async {
|
||||||
|
var encodedURL = 'https://example.com/ clears extra paths';
|
||||||
|
await Store.put(StoreKey.serverEndpoint, encodedURL);
|
||||||
|
expect(getServerUrl(), 'https://example.com');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Returns decoded basic auth URL', () async {
|
||||||
|
var basicAuthURL = 'https://user:password@example.com';
|
||||||
|
await Store.put(StoreKey.serverEndpoint, basicAuthURL);
|
||||||
|
expect(getServerUrl(), basicAuthURL);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Returns decoded URL with a port', () async {
|
||||||
|
var portURL = 'https://example.com:1337';
|
||||||
|
await Store.put(StoreKey.serverEndpoint, portURL);
|
||||||
|
expect(getServerUrl(), portURL);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Returns decoded complex URL', () async {
|
||||||
|
var complexURL = 'https://user:password@example.com:1337/123/abc';
|
||||||
|
await Store.put(StoreKey.serverEndpoint, complexURL);
|
||||||
|
expect(getServerUrl(), 'https://user:password@example.com:1337');
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue