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.
|
||||
///
|
||||
/// Input: [schema://]host[:port][/path]
|
||||
/// Input: [schema://][basicAuth:password@]host[:port][/path]
|
||||
/// schema - optional (default: https)
|
||||
/// userInfo - optional
|
||||
/// host - required
|
||||
/// port - optional (default: based on schema)
|
||||
/// path - optional
|
||||
|
|
|
|||
|
|
@ -16,12 +16,15 @@ String? getServerUrl() {
|
|||
if (serverUri == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return Uri.decodeFull(
|
||||
serverUri.hasPort
|
||||
? "${serverUri.scheme}://${serverUri.host}:${serverUri.port}"
|
||||
: "${serverUri.scheme}://${serverUri.host}",
|
||||
);
|
||||
var URIToDecodeFull = "${serverUri.scheme}://";
|
||||
if (serverUri.userInfo.isNotEmpty){
|
||||
URIToDecodeFull += "${serverUri.userInfo}@";
|
||||
}
|
||||
URIToDecodeFull += "${serverUri.host}";
|
||||
if(serverUri.hasPort){
|
||||
URIToDecodeFull += ":${serverUri.port}";
|
||||
}
|
||||
return Uri.decodeFull(URIToDecodeFull);
|
||||
}
|
||||
|
||||
/// Converts a Unicode URL to its ASCII-compatible encoding (Punycode).
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ void main() {
|
|||
db.writeTxnSync(() => db.clearSync());
|
||||
await StoreService.init(storeRepository: IsarStoreRepository(db));
|
||||
});
|
||||
|
||||
// add test here
|
||||
test('Should resolve HTTP endpoint', () async {
|
||||
const testUrl = 'http://ip:2283';
|
||||
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