mirror of
https://github.com/dbeaver/cloudbeaver.git
synced 2026-09-24 16:04:36 +08:00
CB-3740 fix: handle authentication errors (#1844)
* CB-3740 fix: handle authentication errors * CB-3740 chore: add localization
This commit is contained in:
@@ -38,6 +38,7 @@ export interface ILoginOptions {
|
||||
@injectable()
|
||||
export class UserInfoResource extends CachedDataResource<UserInfo | null, void, UserInfoIncludes> {
|
||||
readonly onUserChange: ISyncExecutor<string>;
|
||||
readonly onException: ISyncExecutor<Error>;
|
||||
|
||||
get authRole(): ELMRole | undefined {
|
||||
return this.data?.authRole as ELMRole | undefined;
|
||||
@@ -56,6 +57,7 @@ export class UserInfoResource extends CachedDataResource<UserInfo | null, void,
|
||||
super(() => null, undefined, ['customIncludeOriginDetails', 'includeConfigurationParameters']);
|
||||
|
||||
this.onUserChange = new SyncExecutor();
|
||||
this.onException = new SyncExecutor();
|
||||
|
||||
this.sync(
|
||||
sessionResource,
|
||||
@@ -234,12 +236,20 @@ export class UserInfoResource extends CachedDataResource<UserInfo | null, void,
|
||||
}
|
||||
|
||||
protected async loader(key: void, includes?: ReadonlyArray<string>): Promise<UserInfo | null> {
|
||||
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 {
|
||||
|
||||
@@ -12,9 +12,14 @@ import type { IExecutorHandler } from './IExecutorHandler';
|
||||
import type { ExecutorDataFilter, ExecutorDataMap, IChainLink, IExecutorHandlersCollection } from './IExecutorHandlersCollection';
|
||||
|
||||
export class ExecutorHandlersCollection<T = unknown, TResult = any | Promise<any>> implements IExecutorHandlersCollection<T, TResult> {
|
||||
handlers: Array<IExecutorHandler<T, TResult>> = [];
|
||||
postHandlers: Array<IExecutorHandler<T, TResult>> = [];
|
||||
chain: Array<IChainLink<T, TResult>> = [];
|
||||
handlers: Array<IExecutorHandler<T, TResult>>;
|
||||
postHandlers: Array<IExecutorHandler<T, TResult>>;
|
||||
chain: Array<IChainLink<T, TResult>>;
|
||||
|
||||
get isEmpty(): boolean {
|
||||
return this.handlers.length === 0 && this.postHandlers.length === 0 && this.chain.length === 0;
|
||||
}
|
||||
|
||||
readonly contextCreators: Map<IContextLoader<any, T>, IContextLoader<any, T>>;
|
||||
readonly collections: Array<IExecutorHandlersCollection<T, TResult>>;
|
||||
protected initialDataGetter: (() => T) | null;
|
||||
@@ -25,6 +30,9 @@ export class ExecutorHandlersCollection<T = unknown, TResult = any | Promise<any
|
||||
this.contextCreators = new Map();
|
||||
this.collections = [];
|
||||
this.initialDataGetter = null;
|
||||
this.handlers = [];
|
||||
this.postHandlers = [];
|
||||
this.chain = [];
|
||||
|
||||
makeObservable<this, 'links'>(this, {
|
||||
handlers: observable.shallow,
|
||||
|
||||
@@ -20,6 +20,7 @@ export interface IChainLink<T, TResult> {
|
||||
}
|
||||
|
||||
export interface IExecutorHandlersCollection<T = unknown, TResult = any | Promise<any>> {
|
||||
readonly isEmpty: boolean;
|
||||
readonly handlers: Array<IExecutorHandler<T, TResult>>;
|
||||
readonly postHandlers: Array<IExecutorHandler<T, TResult>>;
|
||||
readonly chain: Array<IChainLink<T, TResult>>;
|
||||
|
||||
@@ -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<void> {}
|
||||
load(): void | Promise<void> {}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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?'],
|
||||
];
|
||||
|
||||
@@ -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?'],
|
||||
];
|
||||
|
||||
@@ -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', 'Произошла ошибка при загрузке данных пользователя. Выйти?'],
|
||||
];
|
||||
|
||||
@@ -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?'],
|
||||
];
|
||||
|
||||
@@ -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],
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user