feat: open appflowy from admin web (#4047)

* feat: open appflowy from admin web

* feat: add loading indicator
This commit is contained in:
Nathan.fooo
2023-11-29 12:55:13 -08:00
committed by GitHub
parent 8665a25b39
commit 64aa2ba7e4
13 changed files with 259 additions and 126 deletions

View File

@ -8,6 +8,7 @@ import 'package:appflowy/plugins/document/presentation/editor_plugins/openai/ser
import 'package:appflowy/plugins/document/presentation/editor_plugins/stability_ai/stability_ai_client.dart'; import 'package:appflowy/plugins/document/presentation/editor_plugins/stability_ai/stability_ai_client.dart';
import 'package:appflowy/plugins/trash/application/prelude.dart'; import 'package:appflowy/plugins/trash/application/prelude.dart';
import 'package:appflowy/startup/startup.dart'; import 'package:appflowy/startup/startup.dart';
import 'package:appflowy/startup/tasks/appflowy_cloud_task.dart';
import 'package:appflowy/user/application/auth/af_cloud_auth_service.dart'; import 'package:appflowy/user/application/auth/af_cloud_auth_service.dart';
import 'package:appflowy/user/application/auth/auth_service.dart'; import 'package:appflowy/user/application/auth/auth_service.dart';
import 'package:appflowy/user/application/auth/supabase_auth_service.dart'; import 'package:appflowy/user/application/auth/supabase_auth_service.dart';
@ -57,6 +58,15 @@ class DependencyResolver {
Future<void> _resolveCloudDeps(GetIt getIt) async { Future<void> _resolveCloudDeps(GetIt getIt) async {
final env = await AppFlowyCloudSharedEnv.fromEnv(); final env = await AppFlowyCloudSharedEnv.fromEnv();
getIt.registerFactory<AppFlowyCloudSharedEnv>(() => env); getIt.registerFactory<AppFlowyCloudSharedEnv>(() => env);
if (isAppFlowyCloudEnabled) {
getIt.registerSingleton(
AppFlowyCloudDeepLink(),
dispose: (obj) async {
await obj.dispose();
},
);
}
} }
void _resolveCommonService( void _resolveCommonService(

View File

@ -1,6 +1,7 @@
import 'dart:async'; import 'dart:async';
import 'dart:io'; import 'dart:io';
import 'package:appflowy/env/cloud_env.dart';
import 'package:appflowy/startup/tasks/memory_leak_detector.dart'; import 'package:appflowy/startup/tasks/memory_leak_detector.dart';
import 'package:appflowy/workspace/application/settings/prelude.dart'; import 'package:appflowy/workspace/application/settings/prelude.dart';
import 'package:appflowy_backend/appflowy_backend.dart'; import 'package:appflowy_backend/appflowy_backend.dart';
@ -94,8 +95,8 @@ class FlowyRunner {
// ignore in test mode // ignore in test mode
if (!mode.isUnitTest) ...[ if (!mode.isUnitTest) ...[
const HotKeyTask(), const HotKeyTask(),
InitSupabaseTask(), if (isSupabaseEnabled) InitSupabaseTask(),
InitAppFlowyCloudTask(), if (isAppFlowyCloudEnabled) InitAppFlowyCloudTask(),
const InitAppWidgetTask(), const InitAppWidgetTask(),
const InitPlatformServiceTask(), const InitPlatformServiceTask(),
], ],

View File

@ -156,6 +156,7 @@ class _ApplicationWidgetState extends State<ApplicationWidget> {
} }
class AppGlobals { class AppGlobals {
// static GlobalKey<ScaffoldMessengerState> scaffoldMessengerKey = GlobalKey();
static GlobalKey<NavigatorState> rootNavKey = GlobalKey(); static GlobalKey<NavigatorState> rootNavKey = GlobalKey();
static NavigatorState get nav => rootNavKey.currentState!; static NavigatorState get nav => rootNavKey.currentState!;
} }

View File

@ -2,10 +2,138 @@ import 'dart:io';
import 'package:appflowy/env/cloud_env.dart'; import 'package:appflowy/env/cloud_env.dart';
import 'package:appflowy/startup/startup.dart'; import 'package:appflowy/startup/startup.dart';
import 'package:appflowy/startup/tasks/app_widget.dart';
import 'package:appflowy/startup/tasks/supabase_task.dart'; import 'package:appflowy/startup/tasks/supabase_task.dart';
import 'package:appflowy/user/application/auth/auth_error.dart';
import 'package:appflowy/user/application/auth/device_id.dart';
import 'package:appflowy/user/application/user_auth_listener.dart'; import 'package:appflowy/user/application/user_auth_listener.dart';
import 'package:appflowy/workspace/presentation/home/toast.dart';
import 'package:appflowy_backend/log.dart'; import 'package:appflowy_backend/log.dart';
import 'package:flutter/material.dart';
import 'package:url_protocol/url_protocol.dart'; import 'package:url_protocol/url_protocol.dart';
import 'dart:async';
import 'package:app_links/app_links.dart';
import 'package:appflowy/user/application/auth/auth_service.dart';
import 'package:appflowy_backend/dispatch/dispatch.dart';
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart';
import 'package:dartz/dartz.dart';
class AppFlowyCloudDeepLink {
final _appLinks = AppLinks();
StreamSubscription<Uri?>? _deeplinkSubscription;
final ValueNotifier<DeepLinkResult?> stateNotifier = ValueNotifier(null);
Completer<Either<FlowyError, UserProfilePB>>? _completer;
AppFlowyCloudDeepLink() {
if (Platform.isWindows) {
// register deep link for Windows
registerProtocolHandler(appflowyDeepLinkSchema);
}
_deeplinkSubscription = _appLinks.uriLinkStream.listen(
(Uri? uri) async {
Log.info('onDeepLink: ${uri.toString()}');
await _handleUri(uri);
},
onError: (Object err, StackTrace stackTrace) {
Log.error('on deeplink stream error: ${err.toString()}', stackTrace);
_deeplinkSubscription?.cancel();
},
);
}
Future<void> dispose() async {
await _deeplinkSubscription?.cancel();
}
void resigerCompleter(
Completer<Either<FlowyError, UserProfilePB>> completer,
) {
_completer = completer;
}
VoidCallback subscribeDeepLinkLoadingState(
ValueChanged<DeepLinkResult> listener,
) {
listenerFn() {
if (stateNotifier.value != null) {
listener(stateNotifier.value!);
}
}
stateNotifier.addListener(listenerFn);
return listenerFn;
}
void unsubscribeDeepLinkLoadingState(
VoidCallback listener,
) {
stateNotifier.removeListener(listener);
}
Future<void> _handleUri(
Uri? uri,
) async {
stateNotifier.value = DeepLinkResult(state: DeepLinkState.none);
if (uri != null) {
if (_isAuthCallbackDeeplink(uri)) {
final deviceId = await getDeviceId();
final payload = OauthSignInPB(
authType: AuthTypePB.AFCloud,
map: {
AuthServiceMapKeys.signInURL: uri.toString(),
AuthServiceMapKeys.deviceId: deviceId,
},
);
stateNotifier.value = DeepLinkResult(state: DeepLinkState.loading);
final result = await UserEventOauthSignIn(payload)
.send()
.then((value) => value.swap());
stateNotifier.value = DeepLinkResult(
state: DeepLinkState.finish,
result: result,
);
// If there is no completer, runAppFlowy() will be called.
if (_completer == null) {
result.fold(
(err) {
Log.error(err);
final context = AppGlobals.rootNavKey.currentState?.context;
if (context != null) {
showSnackBarMessage(
context,
err.msg,
);
}
},
(err) async {
Log.error(err);
await runAppFlowy();
},
);
} else {
_completer?.complete(result);
_completer = null;
}
} else {
Log.error('onDeepLinkError: Unexpect deep link: ${uri.toString()}');
_completer?.complete(left(AuthError.signInWithOauthError));
_completer = null;
}
} else {
Log.error('onDeepLinkError: Unexpect empty deep link callback');
_completer?.complete(left(AuthError.emptyDeeplink));
_completer = null;
}
}
bool _isAuthCallbackDeeplink(Uri uri) {
return (uri.fragment.contains('access_token'));
}
}
class InitAppFlowyCloudTask extends LaunchTask { class InitAppFlowyCloudTask extends LaunchTask {
UserAuthStateListener? _authStateListener; UserAuthStateListener? _authStateListener;
@ -29,11 +157,6 @@ class InitAppFlowyCloudTask extends LaunchTask {
} }
}, },
); );
if (Platform.isWindows) {
// register deep link for Windows
registerProtocolHandler(appflowyDeepLinkSchema);
}
} }
@override @override
@ -42,3 +165,16 @@ class InitAppFlowyCloudTask extends LaunchTask {
_authStateListener = null; _authStateListener = null;
} }
} }
class DeepLinkResult {
final DeepLinkState state;
final Either<FlowyError, UserProfilePB>? result;
DeepLinkResult({required this.state, this.result});
}
enum DeepLinkState {
none,
loading,
finish,
}

View File

@ -1,23 +1,19 @@
import 'dart:async'; import 'dart:async';
import 'package:app_links/app_links.dart'; import 'package:appflowy/startup/startup.dart';
import 'package:appflowy/startup/tasks/appflowy_cloud_task.dart';
import 'package:appflowy/user/application/auth/backend_auth_service.dart'; import 'package:appflowy/user/application/auth/backend_auth_service.dart';
import 'package:appflowy/user/application/auth/auth_service.dart'; import 'package:appflowy/user/application/auth/auth_service.dart';
import 'package:appflowy/user/application/user_service.dart'; import 'package:appflowy/user/application/user_service.dart';
import 'package:appflowy_backend/dispatch/dispatch.dart'; import 'package:appflowy_backend/dispatch/dispatch.dart';
import 'package:appflowy_backend/log.dart';
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart'; import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart';
import 'package:dartz/dartz.dart'; import 'package:dartz/dartz.dart';
import 'package:url_launcher/url_launcher.dart'; import 'package:url_launcher/url_launcher.dart';
import 'auth_error.dart'; import 'auth_error.dart';
import 'device_id.dart';
class AppFlowyCloudAuthService implements AuthService { class AppFlowyCloudAuthService implements AuthService {
final _appLinks = AppLinks();
StreamSubscription<Uri?>? _deeplinkSubscription;
AppFlowyCloudAuthService(); AppFlowyCloudAuthService();
final BackendAuthService _backendAuthService = BackendAuthService( final BackendAuthService _backendAuthService = BackendAuthService(
@ -66,20 +62,15 @@ class AppFlowyCloudAuthService implements AuthService {
); );
final completer = Completer<Either<FlowyError, UserProfilePB>>(); final completer = Completer<Either<FlowyError, UserProfilePB>>();
_deeplinkSubscription = _appLinks.uriLinkStream.listen( if (isSuccess) {
(Uri? uri) async { // The [AppFlowyCloudDeepLink] must be registered before using the
Log.info('onDeepLink: ${uri.toString()}'); // [AppFlowyCloudAuthService].
await _handleUri(uri, completer); if (getIt.isRegistered<AppFlowyCloudDeepLink>()) {
}, getIt<AppFlowyCloudDeepLink>().resigerCompleter(completer);
onError: (Object err, StackTrace stackTrace) { } else {
Log.error('onDeepLinkError: ${err.toString()}', stackTrace); throw Exception('AppFlowyCloudDeepLink is not registered');
_deeplinkSubscription?.cancel(); }
completer.complete(left(AuthError.deeplinkError)); } else {
},
);
if (!isSuccess) {
_deeplinkSubscription?.cancel();
completer.complete(left(AuthError.signInWithOauthError)); completer.complete(left(AuthError.signInWithOauthError));
} }
@ -89,37 +80,6 @@ class AppFlowyCloudAuthService implements AuthService {
); );
} }
Future<void> _handleUri(
Uri? uri,
Completer<Either<FlowyError, UserProfilePB>> completer,
) async {
if (uri != null) {
if (_isAuthCallbackDeeplink(uri)) {
// Sign in with url
final deviceId = await getDeviceId();
final payload = OauthSignInPB(
authType: AuthTypePB.AFCloud,
map: {
AuthServiceMapKeys.signInURL: uri.toString(),
AuthServiceMapKeys.deviceId: deviceId,
},
);
final result = await UserEventOauthSignIn(payload)
.send()
.then((value) => value.swap());
_deeplinkSubscription?.cancel();
completer.complete(result);
} else {
Log.error('onDeepLinkError: Unexpect deep link: ${uri.toString()}');
completer.complete(left(AuthError.signInWithOauthError));
}
} else {
Log.error('onDeepLinkError: Unexpect empty deep link callback');
_deeplinkSubscription?.cancel();
completer.complete(left(AuthError.emptyDeeplink));
}
}
@override @override
Future<void> signOut() async { Future<void> signOut() async {
await _backendAuthService.signOut(); await _backendAuthService.signOut();
@ -160,7 +120,3 @@ extension ProviderTypePBExtension on ProviderTypePB {
} }
} }
} }
bool _isAuthCallbackDeeplink(Uri uri) {
return (uri.fragment.contains('access_token'));
}

View File

@ -1,3 +1,6 @@
import 'package:appflowy/env/cloud_env.dart';
import 'package:appflowy/startup/startup.dart';
import 'package:appflowy/startup/tasks/appflowy_cloud_task.dart';
import 'package:appflowy/user/application/auth/auth_service.dart'; import 'package:appflowy/user/application/auth/auth_service.dart';
import 'package:dartz/dartz.dart'; import 'package:dartz/dartz.dart';
import 'package:appflowy_backend/protobuf/flowy-error/code.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-error/code.pb.dart';
@ -11,7 +14,29 @@ part 'sign_in_bloc.freezed.dart';
class SignInBloc extends Bloc<SignInEvent, SignInState> { class SignInBloc extends Bloc<SignInEvent, SignInState> {
final AuthService authService; final AuthService authService;
void Function()? deepLinkStateListener;
@override
Future<void> close() {
deepLinkStateListener?.call();
if (isAppFlowyCloudEnabled && deepLinkStateListener != null) {
getIt<AppFlowyCloudDeepLink>().unsubscribeDeepLinkLoadingState(
deepLinkStateListener!,
);
}
return super.close();
}
SignInBloc(this.authService) : super(SignInState.initial()) { SignInBloc(this.authService) : super(SignInState.initial()) {
if (isAppFlowyCloudEnabled) {
deepLinkStateListener =
getIt<AppFlowyCloudDeepLink>().subscribeDeepLinkLoadingState((value) {
if (isClosed) return;
add(SignInEvent.deepLinkStateChange(value));
});
}
on<SignInEvent>((event, emit) async { on<SignInEvent>((event, emit) async {
await event.map( await event.map(
signedInWithUserEmailAndPassword: (e) async { signedInWithUserEmailAndPassword: (e) async {
@ -51,6 +76,35 @@ class SignInBloc extends Bloc<SignInEvent, SignInState> {
signedWithMagicLink: (SignedWithMagicLink value) async { signedWithMagicLink: (SignedWithMagicLink value) async {
await _performActionOnSignInWithMagicLink(state, emit, value.email); await _performActionOnSignInWithMagicLink(state, emit, value.email);
}, },
deepLinkStateChange: (_DeepLinkStateChange value) {
final deepLinkState = value.result.state;
switch (deepLinkState) {
case DeepLinkState.none:
break;
case DeepLinkState.loading:
emit(
state.copyWith(
isSubmitting: true,
emailError: none(),
passwordError: none(),
successOrFail: none(),
),
);
case DeepLinkState.finish:
if (value.result.result != null) {
emit(
value.result.result!.fold(
(error) => stateFromCode(error),
(userProfile) => state.copyWith(
isSubmitting: false,
successOrFail: some(left(userProfile)),
),
),
);
}
}
},
); );
}); });
} }
@ -189,6 +243,8 @@ class SignInEvent with _$SignInEvent {
SignedWithMagicLink; SignedWithMagicLink;
const factory SignInEvent.emailChanged(String email) = EmailChanged; const factory SignInEvent.emailChanged(String email) = EmailChanged;
const factory SignInEvent.passwordChanged(String password) = PasswordChanged; const factory SignInEvent.passwordChanged(String password) = PasswordChanged;
const factory SignInEvent.deepLinkStateChange(DeepLinkResult result) =
_DeepLinkStateChange;
} }
@freezed @freezed

View File

@ -139,7 +139,7 @@ checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6"
[[package]] [[package]]
name = "app-error" name = "app-error"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=58ffae16b145b87a1b47f818936d80e6d6f8794c#58ffae16b145b87a1b47f818936d80e6d6f8794c" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d76a0642e1787dc2d15c1848fa4a245f8922d7ab#d76a0642e1787dc2d15c1848fa4a245f8922d7ab"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"reqwest", "reqwest",
@ -786,7 +786,7 @@ dependencies = [
[[package]] [[package]]
name = "client-api" name = "client-api"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=58ffae16b145b87a1b47f818936d80e6d6f8794c#58ffae16b145b87a1b47f818936d80e6d6f8794c" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d76a0642e1787dc2d15c1848fa4a245f8922d7ab#d76a0642e1787dc2d15c1848fa4a245f8922d7ab"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"app-error", "app-error",
@ -1328,7 +1328,7 @@ dependencies = [
"cssparser-macros", "cssparser-macros",
"dtoa-short", "dtoa-short",
"itoa 1.0.6", "itoa 1.0.6",
"phf 0.11.2", "phf 0.8.0",
"smallvec", "smallvec",
] ]
@ -1474,7 +1474,7 @@ checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308"
[[package]] [[package]]
name = "database-entity" name = "database-entity"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=58ffae16b145b87a1b47f818936d80e6d6f8794c#58ffae16b145b87a1b47f818936d80e6d6f8794c" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d76a0642e1787dc2d15c1848fa4a245f8922d7ab#d76a0642e1787dc2d15c1848fa4a245f8922d7ab"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"app-error", "app-error",
@ -2833,7 +2833,7 @@ dependencies = [
[[package]] [[package]]
name = "gotrue" name = "gotrue"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=58ffae16b145b87a1b47f818936d80e6d6f8794c#58ffae16b145b87a1b47f818936d80e6d6f8794c" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d76a0642e1787dc2d15c1848fa4a245f8922d7ab#d76a0642e1787dc2d15c1848fa4a245f8922d7ab"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"futures-util", "futures-util",
@ -2849,7 +2849,7 @@ dependencies = [
[[package]] [[package]]
name = "gotrue-entity" name = "gotrue-entity"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=58ffae16b145b87a1b47f818936d80e6d6f8794c#58ffae16b145b87a1b47f818936d80e6d6f8794c" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d76a0642e1787dc2d15c1848fa4a245f8922d7ab#d76a0642e1787dc2d15c1848fa4a245f8922d7ab"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"app-error", "app-error",
@ -3271,7 +3271,7 @@ dependencies = [
[[package]] [[package]]
name = "infra" name = "infra"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=58ffae16b145b87a1b47f818936d80e6d6f8794c#58ffae16b145b87a1b47f818936d80e6d6f8794c" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d76a0642e1787dc2d15c1848fa4a245f8922d7ab#d76a0642e1787dc2d15c1848fa4a245f8922d7ab"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"reqwest", "reqwest",
@ -4367,7 +4367,6 @@ version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc"
dependencies = [ dependencies = [
"phf_macros 0.11.2",
"phf_shared 0.11.2", "phf_shared 0.11.2",
] ]
@ -4459,19 +4458,6 @@ dependencies = [
"syn 1.0.109", "syn 1.0.109",
] ]
[[package]]
name = "phf_macros"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b"
dependencies = [
"phf_generator 0.11.2",
"phf_shared 0.11.2",
"proc-macro2",
"quote",
"syn 2.0.32",
]
[[package]] [[package]]
name = "phf_shared" name = "phf_shared"
version = "0.8.0" version = "0.8.0"
@ -4713,7 +4699,7 @@ checksum = "8bdf592881d821b83d471f8af290226c8d51402259e9bb5be7f9f8bdebbb11ac"
dependencies = [ dependencies = [
"bytes", "bytes",
"heck 0.4.1", "heck 0.4.1",
"itertools 0.11.0", "itertools 0.10.5",
"log", "log",
"multimap", "multimap",
"once_cell", "once_cell",
@ -4734,7 +4720,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "265baba7fabd416cf5078179f7d2cbeca4ce7a9041111900675ea7c4cb8a4c32" checksum = "265baba7fabd416cf5078179f7d2cbeca4ce7a9041111900675ea7c4cb8a4c32"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"itertools 0.11.0", "itertools 0.10.5",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.32", "syn 2.0.32",
@ -5029,7 +5015,7 @@ dependencies = [
[[package]] [[package]]
name = "realtime-entity" name = "realtime-entity"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=58ffae16b145b87a1b47f818936d80e6d6f8794c#58ffae16b145b87a1b47f818936d80e6d6f8794c" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d76a0642e1787dc2d15c1848fa4a245f8922d7ab#d76a0642e1787dc2d15c1848fa4a245f8922d7ab"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"bincode", "bincode",
@ -5782,7 +5768,7 @@ dependencies = [
[[package]] [[package]]
name = "shared_entity" name = "shared_entity"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=58ffae16b145b87a1b47f818936d80e6d6f8794c#58ffae16b145b87a1b47f818936d80e6d6f8794c" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d76a0642e1787dc2d15c1848fa4a245f8922d7ab#d76a0642e1787dc2d15c1848fa4a245f8922d7ab"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"app-error", "app-error",
@ -7668,7 +7654,7 @@ dependencies = [
[[package]] [[package]]
name = "workspace-template" name = "workspace-template"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=58ffae16b145b87a1b47f818936d80e6d6f8794c#58ffae16b145b87a1b47f818936d80e6d6f8794c" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d76a0642e1787dc2d15c1848fa4a245f8922d7ab#d76a0642e1787dc2d15c1848fa4a245f8922d7ab"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"async-trait", "async-trait",

View File

@ -57,7 +57,7 @@ custom-protocol = ["tauri/custom-protocol"]
# Run the script: # Run the script:
# scripts/tool/update_client_api_rev.sh new_rev_id # scripts/tool/update_client_api_rev.sh new_rev_id
# ⚠️⚠️⚠️️ # ⚠️⚠️⚠️️
client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "58ffae16b145b87a1b47f818936d80e6d6f8794c" } client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "d76a0642e1787dc2d15c1848fa4a245f8922d7ab" }
# Please use the following script to update collab. # Please use the following script to update collab.
# Working directory: frontend # Working directory: frontend
# #

View File

@ -125,7 +125,7 @@ checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6"
[[package]] [[package]]
name = "app-error" name = "app-error"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=58ffae16b145b87a1b47f818936d80e6d6f8794c#58ffae16b145b87a1b47f818936d80e6d6f8794c" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d76a0642e1787dc2d15c1848fa4a245f8922d7ab#d76a0642e1787dc2d15c1848fa4a245f8922d7ab"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"reqwest", "reqwest",
@ -667,7 +667,7 @@ dependencies = [
[[package]] [[package]]
name = "client-api" name = "client-api"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=58ffae16b145b87a1b47f818936d80e6d6f8794c#58ffae16b145b87a1b47f818936d80e6d6f8794c" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d76a0642e1787dc2d15c1848fa4a245f8922d7ab#d76a0642e1787dc2d15c1848fa4a245f8922d7ab"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"app-error", "app-error",
@ -1152,7 +1152,7 @@ dependencies = [
"cssparser-macros", "cssparser-macros",
"dtoa-short", "dtoa-short",
"itoa", "itoa",
"phf 0.11.2", "phf 0.8.0",
"smallvec", "smallvec",
] ]
@ -1280,7 +1280,7 @@ checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308"
[[package]] [[package]]
name = "database-entity" name = "database-entity"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=58ffae16b145b87a1b47f818936d80e6d6f8794c#58ffae16b145b87a1b47f818936d80e6d6f8794c" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d76a0642e1787dc2d15c1848fa4a245f8922d7ab#d76a0642e1787dc2d15c1848fa4a245f8922d7ab"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"app-error", "app-error",
@ -2474,7 +2474,7 @@ dependencies = [
[[package]] [[package]]
name = "gotrue" name = "gotrue"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=58ffae16b145b87a1b47f818936d80e6d6f8794c#58ffae16b145b87a1b47f818936d80e6d6f8794c" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d76a0642e1787dc2d15c1848fa4a245f8922d7ab#d76a0642e1787dc2d15c1848fa4a245f8922d7ab"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"futures-util", "futures-util",
@ -2490,7 +2490,7 @@ dependencies = [
[[package]] [[package]]
name = "gotrue-entity" name = "gotrue-entity"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=58ffae16b145b87a1b47f818936d80e6d6f8794c#58ffae16b145b87a1b47f818936d80e6d6f8794c" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d76a0642e1787dc2d15c1848fa4a245f8922d7ab#d76a0642e1787dc2d15c1848fa4a245f8922d7ab"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"app-error", "app-error",
@ -2851,7 +2851,7 @@ dependencies = [
[[package]] [[package]]
name = "infra" name = "infra"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=58ffae16b145b87a1b47f818936d80e6d6f8794c#58ffae16b145b87a1b47f818936d80e6d6f8794c" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d76a0642e1787dc2d15c1848fa4a245f8922d7ab#d76a0642e1787dc2d15c1848fa4a245f8922d7ab"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"reqwest", "reqwest",
@ -3667,7 +3667,7 @@ version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12" checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12"
dependencies = [ dependencies = [
"phf_macros 0.8.0", "phf_macros",
"phf_shared 0.8.0", "phf_shared 0.8.0",
"proc-macro-hack", "proc-macro-hack",
] ]
@ -3687,7 +3687,6 @@ version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc"
dependencies = [ dependencies = [
"phf_macros 0.11.2",
"phf_shared 0.11.2", "phf_shared 0.11.2",
] ]
@ -3755,19 +3754,6 @@ dependencies = [
"syn 1.0.109", "syn 1.0.109",
] ]
[[package]]
name = "phf_macros"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b"
dependencies = [
"phf_generator 0.11.2",
"phf_shared 0.11.2",
"proc-macro2",
"quote",
"syn 2.0.31",
]
[[package]] [[package]]
name = "phf_shared" name = "phf_shared"
version = "0.8.0" version = "0.8.0"
@ -3971,7 +3957,7 @@ checksum = "8bdf592881d821b83d471f8af290226c8d51402259e9bb5be7f9f8bdebbb11ac"
dependencies = [ dependencies = [
"bytes", "bytes",
"heck 0.4.1", "heck 0.4.1",
"itertools 0.11.0", "itertools 0.10.5",
"log", "log",
"multimap", "multimap",
"once_cell", "once_cell",
@ -3992,7 +3978,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "265baba7fabd416cf5078179f7d2cbeca4ce7a9041111900675ea7c4cb8a4c32" checksum = "265baba7fabd416cf5078179f7d2cbeca4ce7a9041111900675ea7c4cb8a4c32"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"itertools 0.11.0", "itertools 0.10.5",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.31", "syn 2.0.31",
@ -4331,7 +4317,7 @@ dependencies = [
[[package]] [[package]]
name = "realtime-entity" name = "realtime-entity"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=58ffae16b145b87a1b47f818936d80e6d6f8794c#58ffae16b145b87a1b47f818936d80e6d6f8794c" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d76a0642e1787dc2d15c1848fa4a245f8922d7ab#d76a0642e1787dc2d15c1848fa4a245f8922d7ab"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"bincode", "bincode",
@ -4997,7 +4983,7 @@ dependencies = [
[[package]] [[package]]
name = "shared_entity" name = "shared_entity"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=58ffae16b145b87a1b47f818936d80e6d6f8794c#58ffae16b145b87a1b47f818936d80e6d6f8794c" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d76a0642e1787dc2d15c1848fa4a245f8922d7ab#d76a0642e1787dc2d15c1848fa4a245f8922d7ab"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"app-error", "app-error",
@ -6334,7 +6320,7 @@ dependencies = [
[[package]] [[package]]
name = "workspace-template" name = "workspace-template"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=58ffae16b145b87a1b47f818936d80e6d6f8794c#58ffae16b145b87a1b47f818936d80e6d6f8794c" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d76a0642e1787dc2d15c1848fa4a245f8922d7ab#d76a0642e1787dc2d15c1848fa4a245f8922d7ab"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"async-trait", "async-trait",

View File

@ -99,7 +99,7 @@ incremental = false
# Run the script: # Run the script:
# scripts/tool/update_client_api_rev.sh new_rev_id # scripts/tool/update_client_api_rev.sh new_rev_id
# ⚠️⚠️⚠️️ # ⚠️⚠️⚠️️
client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "58ffae16b145b87a1b47f818936d80e6d6f8794c" } client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "d76a0642e1787dc2d15c1848fa4a245f8922d7ab" }
# Please use the following script to update collab. # Please use the following script to update collab.
# Working directory: frontend # Working directory: frontend
# #

View File

@ -249,7 +249,7 @@ pub async fn get_user_setting(
} }
#[tracing::instrument(level = "debug", skip(data, manager), err)] #[tracing::instrument(level = "debug", skip(data, manager), err)]
pub async fn oauth_handler( pub async fn oauth_sign_in_handler(
data: AFPluginData<OauthSignInPB>, data: AFPluginData<OauthSignInPB>,
manager: AFPluginState<Weak<UserManager>>, manager: AFPluginState<Weak<UserManager>>,
) -> DataResult<UserProfilePB, FlowyError> { ) -> DataResult<UserProfilePB, FlowyError> {

View File

@ -38,7 +38,7 @@ pub fn init(user_session: Weak<UserManager>) -> AFPlugin {
.event(UserEvent::GetCloudConfig, get_cloud_config_handler) .event(UserEvent::GetCloudConfig, get_cloud_config_handler)
.event(UserEvent::SetEncryptionSecret, set_encrypt_secret_handler) .event(UserEvent::SetEncryptionSecret, set_encrypt_secret_handler)
.event(UserEvent::CheckEncryptionSign, check_encrypt_secret_handler) .event(UserEvent::CheckEncryptionSign, check_encrypt_secret_handler)
.event(UserEvent::OauthSignIn, oauth_handler) .event(UserEvent::OauthSignIn, oauth_sign_in_handler)
.event(UserEvent::GenerateSignInURL, gen_sign_in_url_handler) .event(UserEvent::GenerateSignInURL, gen_sign_in_url_handler)
.event(UserEvent::GetOauthURLWithProvider, sign_in_with_provider_handler) .event(UserEvent::GetOauthURLWithProvider, sign_in_with_provider_handler)
.event(UserEvent::GetAllWorkspace, get_all_workspace_handler) .event(UserEvent::GetAllWorkspace, get_all_workspace_handler)

View File

@ -356,8 +356,10 @@ impl UserManager {
authenticator: Authenticator, authenticator: Authenticator,
params: BoxAny, params: BoxAny,
) -> Result<UserProfile, FlowyError> { ) -> Result<UserProfile, FlowyError> {
self.update_authenticator(&authenticator).await; // sign out the current user if there is one
let _ = self.sign_out().await;
self.update_authenticator(&authenticator).await;
let migration_user = self.get_migration_user(&authenticator).await; let migration_user = self.get_migration_user(&authenticator).await;
let auth_service = self.cloud_services.get_user_service()?; let auth_service = self.cloud_services.get_user_service()?;
let response: AuthResponse = auth_service.sign_up(params).await?; let response: AuthResponse = auth_service.sign_up(params).await?;
@ -468,16 +470,15 @@ impl UserManager {
#[tracing::instrument(level = "info", skip(self))] #[tracing::instrument(level = "info", skip(self))]
pub async fn sign_out(&self) -> Result<(), FlowyError> { pub async fn sign_out(&self) -> Result<(), FlowyError> {
let session = self.get_session()?; if let Ok(session) = self.get_session() {
self.database.close(session.user_id)?; self.database.close(session.user_id)?;
self.set_session(None)?; self.set_session(None)?;
let server = self.cloud_services.get_user_service()?; let server = self.cloud_services.get_user_service()?;
af_spawn(async move {
if let Err(err) = server.sign_out(None).await { if let Err(err) = server.sign_out(None).await {
event!(tracing::Level::ERROR, "{:?}", err); event!(tracing::Level::ERROR, "{:?}", err);
} }
}); }
Ok(()) Ok(())
} }