OAuth Support #53

Merged
Henry-Hiles merged 17 commits from quad/feat/oauth-login into main 2026-07-20 19:46:19 -04:00
12 changed files with 55 additions and 68 deletions
Showing only changes of commit 79671409de - Show all commits

more progress, rename nexus.federated.Nexus -> nexus.federated.nexus

Henry Hiles 2026-07-19 19:06:47 -04:00
Signed by: Henry-Hiles
SSH key fingerprint: SHA256:VKQUdS31Q90KvX7EkKMHMBpUspcmItAh86a+v7PGiIs

View file

@ -34,4 +34,4 @@ jobs:
uses: actions/upload-artifact@v6
with:
name: flatpak-${{ matrix.arch }}
path: result/nexus.federated.Nexus.flatpak
path: result/nexus.federated.nexus.flatpak

View file

@ -30,7 +30,7 @@ if (keystorePropertiesFile.exists()) {
}
android {
namespace = "nexus.federated.Nexus"
namespace = "nexus.federated.nexus"
ndkVersion = flutter.ndkVersion
compileSdk = 34
@ -45,7 +45,7 @@ android {
}
defaultConfig {
applicationId = "nexus.federated.Nexus"
applicationId = "nexus.federated.nexus"
minSdk = 29
targetSdkVersion flutter.targetSdkVersion
versionCode = flutterVersionCode.toInteger()

View file

@ -1,4 +1,4 @@
package nexus.federated.Nexus
package nexus.federated.nexus
import io.flutter.embedding.android.FlutterActivity

View file

@ -52,7 +52,7 @@
flatpak = inputs.nix2flatpak.lib.${system}.mkFlatpak {
appName = "Nexus";
developer = "QuadRadical";
appId = "nexus.federated.Nexus";
appId = "nexus.federated.nexus";
package = default;
runtime = "org.gnome.Platform/49";
permissions = {

View file

@ -7,7 +7,7 @@
<key>CFBundleExecutable</key>
<string>App</string>
<key>CFBundleIdentifier</key>
<string>nexus.federated.Nexus</string>
<string>nexus.federated.nexus</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>

View file

@ -387,7 +387,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = nexus.federated.Nexus;
PRODUCT_BUNDLE_IDENTIFIER = nexus.federated.nexus;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
@ -519,7 +519,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = nexus.federated.Nexus;
PRODUCT_BUNDLE_IDENTIFIER = nexus.federated.nexus;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
@ -545,7 +545,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = nexus.federated.Nexus;
PRODUCT_BUNDLE_IDENTIFIER = nexus.federated.nexus;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;

View file

@ -1,32 +1,31 @@
import "package:flutter_riverpod/flutter_riverpod.dart";
import "package:nexus/controllers/client.dart";
import "package:nexus/controllers/client_id.dart";
import "package:nexus/models/oauth_auth_code_response.dart";
class AuthUrlController extends AsyncNotifier<Uri> {
static const prefString = "auth_url";
class AuthUrlController extends AsyncNotifier<OAuthAuthCodeResponse> {
final Uri homeserver;
AuthUrlController(this.homeserver);
@override
Future<Uri> build() async {
final fetched = await ref
.watch(ClientController.provider.notifier)
.getAuthUrl(
.new(
homeserverUrl: homeserver,
redirectUri: Uri.https("nexus.federated.nexus"),
responseMode: .query,
scopes: .new([.clientApi]),
clientId: await ref.watch(
ClientIdController.provider(homeserver).future,
),
Future<OAuthAuthCodeResponse> build() async => ref
.watch(ClientController.provider.notifier)
.getAuthUrl(
.new(
homeserverUrl: homeserver,
redirectUri: .new(scheme: "nexus.federated.nexus"),
responseMode: .query,
scopes: .new([.clientApi]),
clientId: await ref.watch(
ClientIdController.provider(homeserver).future,
),
);
),
);
return fetched.url;
}
static final provider = AsyncNotifierProvider.autoDispose
.family<AuthUrlController, Uri, Uri>(AuthUrlController.new);
static final provider =
AsyncNotifierProvider.family<
AuthUrlController,
OAuthAuthCodeResponse,
Uri
>(AuthUrlController.new);
}

View file

@ -1,43 +1,31 @@
import "package:flutter_riverpod/flutter_riverpod.dart";
import "package:nexus/controllers/client.dart";
import "package:nexus/controllers/shared_prefs.dart";
class ClientIdController extends AsyncNotifier<String> {
static const prefString = "client_id";
final Uri homeserver;
ClientIdController(this.homeserver);
@override
Future<String> build() async {
final prefs = await ref.watch(SharedPrefsController.provider.future);
final fromPref = prefs.getString(prefString);
if (fromPref != null) return fromPref;
final fetched = await ref
.watch(ClientController.provider.notifier)
.registerClient(
.new(
clientName: "Nexus",
applicationType: .native,
grantTypes: .new([.authorizationCode, .refreshToken]),
responseTypes: .new([.code]),
logoUri: Uri.https(
"nexus.federated.nexus",
"raw/branch/main/assets/mobile.svg",
),
homeserverUrl: homeserver,
clientUri: Uri.https("nexus.federated.nexus"),
redirectUris: .new([.https("nexus.federated.nexus")]),
Future<String> build() => ref
.watch(ClientController.provider.notifier)
.registerClient(
.new(
clientName: "Nexus",
applicationType: .native,
grantTypes: .new([.authorizationCode, .refreshToken]),
responseTypes: .new([.code]),
logoUri: Uri.https(
"nexus.federated.nexus",
"raw/branch/main/assets/mobile.svg",
),
);
homeserverUrl: homeserver,
clientUri: Uri.https("nexus.federated.nexus"),
redirectUris: .new([.new(scheme: "nexus.federated.nexus")]),
),
);
await prefs.setString(prefString, fetched);
return fetched;
}
static final provider = AsyncNotifierProvider.autoDispose
.family<ClientIdController, String, Uri>(ClientIdController.new);
static final provider =
AsyncNotifierProvider.family<ClientIdController, String, Uri>(
ClientIdController.new,
);
}

View file

@ -52,7 +52,7 @@ class SelectServerPage extends HookConsumerWidget {
AuthUrlController.provider(newUrl).future,
);
print(authUrl);
await ref.watch(LaunchHelper.provider).launchUrl(authUrl.url);
// await Navigator.of(context).push(
// MaterialPageRoute(builder: (_) => LoginPage(homeserver: newUrl)),
// );

View file

@ -7,7 +7,7 @@ project(runner LANGUAGES CXX)
set(BINARY_NAME "nexus")
# The unique GTK application identifier for this application. See:
# https://wiki.gnome.org/HowDoI/ChooseApplicationID
set(APPLICATION_ID "nexus.federated.Nexus")
set(APPLICATION_ID "nexus.federated.nexus")
# Explicitly opt in to modern CMake behaviors to avoid warnings with recent
# versions of CMake.

View file

@ -37,7 +37,7 @@ flutter.buildFlutterApplication {
postInstall = ''
install -D assets/icon.svg $out/share/icons/hicolor/scalable/apps/nexus.svg
install -Dm755 linux/nexus.federated.Nexus.desktop -t $out/share/applications
install -Dm755 linux/nexus.federated.nexus.desktop -t $out/share/applications
wrapProgram $out/bin/nexus \
--suffix LD_LIBRARY_PATH : $out/app/nexus/lib
'';

View file

@ -89,11 +89,11 @@ BEGIN
BEGIN
BLOCK "040904e4"
BEGIN
VALUE "CompanyName", "nexus.federated.Nexus" "\0"
VALUE "CompanyName", "nexus.federated.nexus" "\0"
VALUE "FileDescription", "nexus" "\0"
VALUE "FileVersion", VERSION_AS_STRING "\0"
VALUE "InternalName", "nexus" "\0"
VALUE "LegalCopyright", "Copyright (C) 2025 nexus.federated.Nexus. All rights reserved." "\0"
VALUE "LegalCopyright", "Copyright (C) 2025 nexus.federated.nexus. All rights reserved." "\0"
VALUE "OriginalFilename", "nexus.exe" "\0"
VALUE "ProductName", "nexus" "\0"
VALUE "ProductVersion", VERSION_AS_STRING "\0"