diff --git a/webapp/packages/core-authentication/src/UserInfoResource.ts b/webapp/packages/core-authentication/src/UserInfoResource.ts index 4b966ed071..0624566ffd 100644 --- a/webapp/packages/core-authentication/src/UserInfoResource.ts +++ b/webapp/packages/core-authentication/src/UserInfoResource.ts @@ -38,6 +38,7 @@ export interface ILoginOptions { @injectable() export class UserInfoResource extends CachedDataResource { readonly onUserChange: ISyncExecutor; + readonly onException: ISyncExecutor; get authRole(): ELMRole | undefined { return this.data?.authRole as ELMRole | undefined; @@ -56,6 +57,7 @@ export class UserInfoResource extends CachedDataResource null, undefined, ['customIncludeOriginDetails', 'includeConfigurationParameters']); this.onUserChange = new SyncExecutor(); + this.onException = new SyncExecutor(); this.sync( sessionResource, @@ -234,12 +236,20 @@ export class UserInfoResource extends CachedDataResource): Promise { - const { user } = await this.graphQLService.sdk.getActiveUser({ - ...this.getDefaultIncludes(), - ...this.getIncludesMap(key, includes), - }); + try { + const { user } = await this.graphQLService.sdk.getActiveUser({ + ...this.getDefaultIncludes(), + ...this.getIncludesMap(key, includes), + }); - return (user as UserInfo | null) || null; + return (user as UserInfo | null) || null; + } catch (exception: any) { + if (this.onException.isEmpty) { + throw exception; + } + this.onException.execute(exception); + return null; + } } protected setData(data: UserInfo | null): void { diff --git a/webapp/packages/core-executor/src/ExecutorHandlersCollection.ts b/webapp/packages/core-executor/src/ExecutorHandlersCollection.ts index 53530a3357..6ec3b178b0 100644 --- a/webapp/packages/core-executor/src/ExecutorHandlersCollection.ts +++ b/webapp/packages/core-executor/src/ExecutorHandlersCollection.ts @@ -12,9 +12,14 @@ import type { IExecutorHandler } from './IExecutorHandler'; import type { ExecutorDataFilter, ExecutorDataMap, IChainLink, IExecutorHandlersCollection } from './IExecutorHandlersCollection'; export class ExecutorHandlersCollection> implements IExecutorHandlersCollection { - handlers: Array> = []; - postHandlers: Array> = []; - chain: Array> = []; + handlers: Array>; + postHandlers: Array>; + chain: Array>; + + get isEmpty(): boolean { + return this.handlers.length === 0 && this.postHandlers.length === 0 && this.chain.length === 0; + } + readonly contextCreators: Map, IContextLoader>; readonly collections: Array>; protected initialDataGetter: (() => T) | null; @@ -25,6 +30,9 @@ export class ExecutorHandlersCollection(this, { handlers: observable.shallow, diff --git a/webapp/packages/core-executor/src/IExecutorHandlersCollection.ts b/webapp/packages/core-executor/src/IExecutorHandlersCollection.ts index f756c5fa51..c993d5fb0d 100644 --- a/webapp/packages/core-executor/src/IExecutorHandlersCollection.ts +++ b/webapp/packages/core-executor/src/IExecutorHandlersCollection.ts @@ -20,6 +20,7 @@ export interface IChainLink { } export interface IExecutorHandlersCollection> { + readonly isEmpty: boolean; readonly handlers: Array>; readonly postHandlers: Array>; readonly chain: Array>; diff --git a/webapp/packages/plugin-authentication/src/UserLoadingErrorDialogBootstrap.ts b/webapp/packages/plugin-authentication/src/UserLoadingErrorDialogBootstrap.ts new file mode 100644 index 0000000000..a5518c3a34 --- /dev/null +++ b/webapp/packages/plugin-authentication/src/UserLoadingErrorDialogBootstrap.ts @@ -0,0 +1,38 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2023 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ +import { UserInfoResource } from '@cloudbeaver/core-authentication'; +import { Bootstrap, injectable } from '@cloudbeaver/core-di'; +import { CommonDialogService, ConfirmationDialog, DialogueStateResult } from '@cloudbeaver/core-dialogs'; +import { NotificationService } from '@cloudbeaver/core-events'; + +@injectable() +export class UserLoadingErrorDialogBootstrap extends Bootstrap { + constructor( + private readonly userInfoResource: UserInfoResource, + private readonly commonDialogService: CommonDialogService, + private readonly notificationService: NotificationService, + ) { + super(); + userInfoResource.onException.addHandler(this.handleException.bind(this)); + } + + register(): void | Promise {} + load(): void | Promise {} + + private async handleException(exception: Error) { + this.notificationService.logException(exception, 'plugin_authentication_user_loading_error'); + const result = await this.commonDialogService.open(ConfirmationDialog, { + title: 'plugin_authentication_loading_error_dialog_title', + message: 'plugin_authentication_loading_error_dialog_message', + }); + + if (result === DialogueStateResult.Resolved) { + await this.userInfoResource.logout(); + } + } +} diff --git a/webapp/packages/plugin-authentication/src/locales/en.ts b/webapp/packages/plugin-authentication/src/locales/en.ts index 268017a9c5..b7312b0611 100644 --- a/webapp/packages/plugin-authentication/src/locales/en.ts +++ b/webapp/packages/plugin-authentication/src/locales/en.ts @@ -31,4 +31,8 @@ export default [ ['authentication_user_login_cant_be_used', 'Sorry, that name cannot be used'], ['authentication_user_icon_tooltip', 'User'], ['authentication_team_icon_tooltip', 'Team'], + + ['plugin_authentication_user_loading_error', "Can't load user data"], + ['plugin_authentication_loading_error_dialog_title', 'Authentication error'], + ['plugin_authentication_loading_error_dialog_message', 'An error occurred while loading user data. Do you want to logout?'], ]; diff --git a/webapp/packages/plugin-authentication/src/locales/it.ts b/webapp/packages/plugin-authentication/src/locales/it.ts index f60e06745e..118f2fb605 100644 --- a/webapp/packages/plugin-authentication/src/locales/it.ts +++ b/webapp/packages/plugin-authentication/src/locales/it.ts @@ -22,4 +22,8 @@ export default [ ['authentication_user_login_already_exists', 'Esiste già un utente con quel nome'], ['authentication_user_login_cant_be_used', 'Quel nome non può essere usato'], ['authentication_user_icon_tooltip', 'Utente'], + + ['plugin_authentication_user_loading_error', "Can't load user data"], + ['plugin_authentication_loading_error_dialog_title', 'Authentication error'], + ['plugin_authentication_loading_error_dialog_message', 'An error occurred while loading user data. Do you want to logout?'], ]; diff --git a/webapp/packages/plugin-authentication/src/locales/ru.ts b/webapp/packages/plugin-authentication/src/locales/ru.ts index e2269f862b..7dc30a7354 100644 --- a/webapp/packages/plugin-authentication/src/locales/ru.ts +++ b/webapp/packages/plugin-authentication/src/locales/ru.ts @@ -31,4 +31,8 @@ export default [ ['authentication_user_login_cant_be_used', 'Данное имя нельзя использовать'], ['authentication_user_icon_tooltip', 'Пользователь'], ['authentication_team_icon_tooltip', 'Команда'], + + ['plugin_authentication_user_loading_error', 'Не удалось загрузить данные пользователя'], + ['plugin_authentication_loading_error_dialog_title', 'Ошибка аутентификации'], + ['plugin_authentication_loading_error_dialog_message', 'Произошла ошибка при загрузке данных пользователя. Выйти?'], ]; diff --git a/webapp/packages/plugin-authentication/src/locales/zh.ts b/webapp/packages/plugin-authentication/src/locales/zh.ts index d6e29002ef..02ebf5e752 100644 --- a/webapp/packages/plugin-authentication/src/locales/zh.ts +++ b/webapp/packages/plugin-authentication/src/locales/zh.ts @@ -28,4 +28,8 @@ export default [ ['authentication_user_login_already_exists', '同名用户已存在'], ['authentication_user_login_cant_be_used', '抱歉,不能使用该名称'], ['authentication_user_icon_tooltip', '用户'], + + ['plugin_authentication_user_loading_error', "Can't load user data"], + ['plugin_authentication_loading_error_dialog_title', 'Authentication error'], + ['plugin_authentication_loading_error_dialog_message', 'An error occurred while loading user data. Do you want to logout?'], ]; diff --git a/webapp/packages/plugin-authentication/src/manifest.ts b/webapp/packages/plugin-authentication/src/manifest.ts index 11ec90f8bf..d9aabb275c 100644 --- a/webapp/packages/plugin-authentication/src/manifest.ts +++ b/webapp/packages/plugin-authentication/src/manifest.ts @@ -11,11 +11,12 @@ import { AuthenticationLocaleService } from './AuthenticationLocaleService'; import { AuthenticationService } from './AuthenticationService'; import { AuthDialogService } from './Dialog/AuthDialogService'; import { PluginBootstrap } from './PluginBootstrap'; +import { UserLoadingErrorDialogBootstrap } from './UserLoadingErrorDialogBootstrap'; export const manifest: PluginManifest = { info: { name: 'Plugin Authentication', }, - providers: [AuthenticationService, AuthDialogService, PluginBootstrap, AuthenticationLocaleService], + providers: [AuthenticationService, AuthDialogService, PluginBootstrap, AuthenticationLocaleService, UserLoadingErrorDialogBootstrap], };