From d0acdc7264a4fcca2bb35ce43f2fda3633d6a796 Mon Sep 17 00:00:00 2001 From: Wroud Date: Mon, 11 May 2020 15:33:13 +0300 Subject: [PATCH] feat(authentication): implementation CB-63 --- .../schema/service.auth.graphqls | 2 +- .../authentication/src/AuthInfoService.ts | 56 +++++ .../authentication/src/AuthProviderService.ts | 29 +++ .../src/AuthenticationService.ts | 26 ++- .../packages/authentication/src/Bootstrap.ts | 4 +- .../authentication/src/Dialog/AuthDialog.tsx | 142 +++++++++++++ .../src/Dialog/AuthDialogController.ts | 107 ++++++++++ .../src/Dialog/AuthDialogFooter.tsx | 57 ++++++ .../src/Dialog/AuthDialogService.ts | 23 +++ .../AuthProviderForm/AuthProviderForm.tsx | 53 +++++ .../src/Dialog/AuthProviderForm/formStyles.ts | 29 +++ webapp/packages/authentication/src/index.ts | 3 + .../packages/authentication/src/manifest.ts | 6 + webapp/packages/core/codegen.yml | 1 + .../src/queries/Authentication/authLogin.gql | 12 ++ .../src/queries/Authentication/authLogout.gql | 3 + .../Authentication/getAuthProviders.gql | 33 +++ .../queries/Authentication/getSessionUser.gql | 9 + .../core/src/root/queries/serverConfig.gql | 2 + webapp/packages/core/src/sdk/sdk.ts | 191 ++++++++++++++++++ 20 files changed, 782 insertions(+), 6 deletions(-) create mode 100644 webapp/packages/authentication/src/AuthInfoService.ts create mode 100644 webapp/packages/authentication/src/AuthProviderService.ts create mode 100644 webapp/packages/authentication/src/Dialog/AuthDialog.tsx create mode 100644 webapp/packages/authentication/src/Dialog/AuthDialogController.ts create mode 100644 webapp/packages/authentication/src/Dialog/AuthDialogFooter.tsx create mode 100644 webapp/packages/authentication/src/Dialog/AuthDialogService.ts create mode 100644 webapp/packages/authentication/src/Dialog/AuthProviderForm/AuthProviderForm.tsx create mode 100644 webapp/packages/authentication/src/Dialog/AuthProviderForm/formStyles.ts create mode 100644 webapp/packages/core/src/queries/Authentication/authLogin.gql create mode 100644 webapp/packages/core/src/queries/Authentication/authLogout.gql create mode 100644 webapp/packages/core/src/queries/Authentication/getAuthProviders.gql create mode 100644 webapp/packages/core/src/queries/Authentication/getSessionUser.gql diff --git a/server/bundles/io.cloudbeaver.service.auth/schema/service.auth.graphqls b/server/bundles/io.cloudbeaver.service.auth/schema/service.auth.graphqls index 69960d28d3..176ccb5432 100644 --- a/server/bundles/io.cloudbeaver.service.auth/schema/service.auth.graphqls +++ b/server/bundles/io.cloudbeaver.service.auth/schema/service.auth.graphqls @@ -15,7 +15,7 @@ type AuthCredentialInfo { admin: Boolean # This field must be shown in login form user: Boolean - possibleValues: [String]! + possibleValues: [String] encryption: AuthCredentialEncryption } diff --git a/webapp/packages/authentication/src/AuthInfoService.ts b/webapp/packages/authentication/src/AuthInfoService.ts new file mode 100644 index 0000000000..71cbd25861 --- /dev/null +++ b/webapp/packages/authentication/src/AuthInfoService.ts @@ -0,0 +1,56 @@ +/* + * cloudbeaver - Cloud Database Manager + * Copyright (C) 2020 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 { observable } from 'mobx'; + +import { injectable } from '@dbeaver/core/di'; +import { NotificationService } from '@dbeaver/core/eventsLog'; +import { GraphQLService, UserAuthInfo } from '@dbeaver/core/sdk'; + +@injectable() +export class AuthInfoService { + @observable private user: UserAuthInfo | null = null; + + constructor( + private graphQLService: GraphQLService, + private notificationService: NotificationService, + ) { } + + get userInfo() { + return this.user; + } + + async login(provider: string, credentials: object): Promise { + if (this.user) { + throw new Error('User already logged in'); + } + + const { user } = await this.graphQLService.gql.authLogin({ provider, credentials }); + this.user = user; + + return this.user; + } + + async logout() { + if (this.user) { + await this.graphQLService.gql.authLogout(); + this.user = null; + } + } + + async updateAuthInfo(): Promise { + try { + const { user } = await this.graphQLService.gql.getSessionUser(); + this.user = user || null; + } catch (exception) { + this.notificationService.logException(exception, 'Can\'t load session user'); + } + + return this.user; + } +} diff --git a/webapp/packages/authentication/src/AuthProviderService.ts b/webapp/packages/authentication/src/AuthProviderService.ts new file mode 100644 index 0000000000..163b6d420e --- /dev/null +++ b/webapp/packages/authentication/src/AuthProviderService.ts @@ -0,0 +1,29 @@ +/* + * cloudbeaver - Cloud Database Manager + * Copyright (C) 2020 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 { injectable } from '@dbeaver/core/di'; +import { + GraphQLService, CachedResource, AuthProviderInfo +} from '@dbeaver/core/sdk'; + +export type AuthProvider = Omit + +@injectable() +export class AuthProviderService { + readonly providers = new CachedResource([], this.refreshAsync.bind(this), data => !!data.length) + + constructor( + private graphQLService: GraphQLService, + ) { } + + private async refreshAsync(data: AuthProvider[]): Promise { + const { providers } = await this.graphQLService.gql.getAuthProviders(); + + return providers; + } +} diff --git a/webapp/packages/authentication/src/AuthenticationService.ts b/webapp/packages/authentication/src/AuthenticationService.ts index 2b7f8cc1ed..75e06c9da3 100644 --- a/webapp/packages/authentication/src/AuthenticationService.ts +++ b/webapp/packages/authentication/src/AuthenticationService.ts @@ -7,14 +7,34 @@ */ import { injectable } from '@dbeaver/core/di'; -import { PermissionsService } from '@dbeaver/core/root'; +import { ServerService } from '@dbeaver/core/root'; + +import { AuthInfoService } from './AuthInfoService'; +import { AuthDialogService } from './Dialog/AuthDialogService'; @injectable() export class AuthenticationService { constructor( - private permissionsService: PermissionsService, + private serverService: ServerService, + private authDialogService: AuthDialogService, + private authInfoService: AuthInfoService, ) { } - register() { + async auth() { + if (this.isForceAuthentication()) { + await this.authDialogService.showLoginForm(); + } + } + + async isForceAuthentication() { + const config = await this.serverService.config.load(); + if (!config) { + throw new Error('Can\'t configure Authentication'); + } + const userInfo = await this.authInfoService.updateAuthInfo(); + + return !config.anonymousAccessEnabled + && config.authenticationEnabled + && !userInfo; } } diff --git a/webapp/packages/authentication/src/Bootstrap.ts b/webapp/packages/authentication/src/Bootstrap.ts index 76c0a6c067..e5b668e710 100644 --- a/webapp/packages/authentication/src/Bootstrap.ts +++ b/webapp/packages/authentication/src/Bootstrap.ts @@ -14,7 +14,7 @@ import { AuthenticationService } from './AuthenticationService'; export class Bootstrap { constructor(private authenticationService: AuthenticationService) { } - bootstrap() { - this.authenticationService.register(); + async bootstrap() { + return this.authenticationService.auth(); } } diff --git a/webapp/packages/authentication/src/Dialog/AuthDialog.tsx b/webapp/packages/authentication/src/Dialog/AuthDialog.tsx new file mode 100644 index 0000000000..23a60e052c --- /dev/null +++ b/webapp/packages/authentication/src/Dialog/AuthDialog.tsx @@ -0,0 +1,142 @@ +/* + * cloudbeaver - Cloud Database Manager + * Copyright (C) 2020 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 { observer } from 'mobx-react'; +import { useTabState, Tab as BaseTab, TabList } from 'reakit/Tab'; +import styled, { css } from 'reshadow'; + +import { SubmittingForm, ErrorMessage } from '@dbeaver/core/blocks'; +import { useController } from '@dbeaver/core/di'; +import { DialogComponent, CommonDialogWrapper } from '@dbeaver/core/dialogs'; +import { useTranslate } from '@dbeaver/core/localization'; +import { composes, useStyles } from '@dbeaver/core/theming'; + +import { AuthDialogController } from './AuthDialogController'; +import { AuthDialogFooter } from './AuthDialogFooter'; +import { AuthProviderForm } from './AuthProviderForm/AuthProviderForm'; + +const styles = composes( + css` + BaseTab { + composes: theme-ripple theme-background-secondary theme-text-on-secondary from global; + } + ErrorMessage { + composes: theme-background-secondary from global; + } + `, + css` + custom-connection { + display: flex; + flex-direction: column; + box-sizing: border-box; + } + CommonDialogWrapper { + display: flex; + flex-direction: column; + max-height: 330px; + min-height: 330px; + } + SubmittingForm { + overflow: auto; + } + SubmittingForm, AuthProviderForm { + flex: 1; + display: flex; + flex-direction: column; + } + + BaseTab { + outline: none; + } + + TabList { + box-sizing: border-box; + display: inline-flex; + width: 100%; + padding-left: 24px; + } + BaseTab { + composes: theme-typography--body2 from global; + text-transform: uppercase; + padding: 12px 16px; + border-top: solid 2px transparent; + height: 48px; + + &:global([aria-selected='true']) { + border-top-color: #fd1d48; + + &:before { + display: none; + } + } + + &:not(:global([aria-selected='true'])) { + cursor: pointer; + background-color: transparent !important; + } + } + AuthProviderForm { + flex-direction: column; + padding: 18px 24px; + } + ErrorMessage { + position: sticky; + bottom: 0; + padding: 8px 24px; + } + ` +); + +export const AuthDialog: DialogComponent = observer( + function AuthDialog(props) { + const controller = useController(AuthDialogController, props.rejectDialog); + const translate = useTranslate(); + const tab = useTabState({ + selectedId: controller.provider?.id, + }); + tab.selectedId = controller.provider?.id || null; + + return styled(useStyles(styles))( + + {controller.providers.map(provider => ( + {provider.label} + ))} + + )} + footer={( + + )} + onReject={props.rejectDialog} + > + + {controller.provider && ( + + )} + + {controller.error.responseMessage && ( + + )} + + ); + } +); diff --git a/webapp/packages/authentication/src/Dialog/AuthDialogController.ts b/webapp/packages/authentication/src/Dialog/AuthDialogController.ts new file mode 100644 index 0000000000..065cdd7fa5 --- /dev/null +++ b/webapp/packages/authentication/src/Dialog/AuthDialogController.ts @@ -0,0 +1,107 @@ +/* + * cloudbeaver - Cloud Database Manager + * Copyright (C) 2020 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 { observable, computed } from 'mobx'; + +import { injectable, IInitializableController, IDestructibleController } from '@dbeaver/core/di'; +import { CommonDialogService } from '@dbeaver/core/dialogs'; +import { NotificationService } from '@dbeaver/core/eventsLog'; +import { GQLErrorCatcher } from '@dbeaver/core/sdk'; +import { ErrorDetailsDialog } from '@dbeaver/core/src/app'; + +import { AuthInfoService } from '../AuthInfoService'; +import { AuthProviderService, AuthProvider } from '../AuthProviderService'; + +@injectable() +export class AuthDialogController implements IInitializableController, IDestructibleController { + @observable provider: AuthProvider | null = null + @observable isAuthenticating = false; + @observable credentials = {}; + + get isLoading() { + return this.authProviderService.providers.isLoading(); + } + + @computed get providers(): AuthProvider[] { + return this.authProviderService + .providers + .data + .concat() + .sort(this.compareProviders); + } + + readonly error = new GQLErrorCatcher(); + private isDistructed = false; + private close!: () => void; + + constructor( + private notificationService: NotificationService, + private authProviderService: AuthProviderService, + private authInfoService: AuthInfoService, + private commonDialogService: CommonDialogService, + ) { } + + init(onClose: () => void) { + this.close = onClose; + this.loadProviders(); + } + + destruct(): void { + this.isDistructed = true; + } + + login = async () => { + if (!this.provider || this.isAuthenticating) { + return; + } + + this.isAuthenticating = true; + try { + await this.authInfoService.login(this.provider.id, this.credentials); + this.close(); + } catch (exception) { + if (!this.error.catch(exception) || this.isDistructed) { + this.notificationService.logException(exception, 'Login failed'); + } + } finally { + this.isAuthenticating = false; + } + } + + selectProvider = (providerId: string) => { + this.provider = this.authProviderService + .providers.data.find(provider => provider.id === providerId) || null; + this.credentials = {}; + } + + showDetails = () => { + if (this.error.exception) { + this.commonDialogService.open(ErrorDetailsDialog, this.error.exception); + } + } + + private async loadProviders() { + try { + await this.authProviderService.providers.load(); + if (this.providers.length > 0) { + this.provider = this.providers[0]; + } + } catch (exception) { + this.notificationService.logException(exception, 'Can\'t load auth providers'); + } + } + + private compareProviders = (providerA: AuthProvider, providerB: AuthProvider): number => { + if (providerA.isDefault === providerB.isDefault) + { + return providerA.label.localeCompare(providerB.label); + } + + return +!!providerA.isDefault - +!!providerB.isDefault; + } +} diff --git a/webapp/packages/authentication/src/Dialog/AuthDialogFooter.tsx b/webapp/packages/authentication/src/Dialog/AuthDialogFooter.tsx new file mode 100644 index 0000000000..23e1ee9d4e --- /dev/null +++ b/webapp/packages/authentication/src/Dialog/AuthDialogFooter.tsx @@ -0,0 +1,57 @@ +/* + * cloudbeaver - Cloud Database Manager + * Copyright (C) 2020 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 { observer } from 'mobx-react'; +import styled, { css } from 'reshadow'; + +import { Button } from '@dbeaver/core/blocks'; +import { useTranslate } from '@dbeaver/core/localization'; + +const styles = css` + controls { + display: flex; + height: 100%; + align-items: center; + } + + fill { + flex: 1; + } + + Button:not(:first-child) { + margin-left: 24px; + } +`; + +export type Props = { + isAuthenticating: boolean; + onLogin(): void; +} + +export const AuthDialogFooter = observer( + function AuthDialogFooter({ + isAuthenticating, + onLogin, + }: Props) { + const translate = useTranslate(); + + return styled(styles)( + + + + + ); + } +); diff --git a/webapp/packages/authentication/src/Dialog/AuthDialogService.ts b/webapp/packages/authentication/src/Dialog/AuthDialogService.ts new file mode 100644 index 0000000000..602846ece6 --- /dev/null +++ b/webapp/packages/authentication/src/Dialog/AuthDialogService.ts @@ -0,0 +1,23 @@ +/* + * cloudbeaver - Cloud Database Manager + * Copyright (C) 2020 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 { injectable } from '@dbeaver/core/di'; +import { CommonDialogService } from '@dbeaver/core/dialogs'; + +import { AuthDialog } from './AuthDialog'; + +@injectable() +export class AuthDialogService { + constructor( + private commonDialogService: CommonDialogService, + ) { } + + async showLoginForm() { + await this.commonDialogService.open(AuthDialog, null); + } +} diff --git a/webapp/packages/authentication/src/Dialog/AuthProviderForm/AuthProviderForm.tsx b/webapp/packages/authentication/src/Dialog/AuthProviderForm/AuthProviderForm.tsx new file mode 100644 index 0000000000..dd8ed03060 --- /dev/null +++ b/webapp/packages/authentication/src/Dialog/AuthProviderForm/AuthProviderForm.tsx @@ -0,0 +1,53 @@ +/* + * cloudbeaver - Cloud Database Manager + * Copyright (C) 2020 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 { observer } from 'mobx-react'; +import { useCallback } from 'react'; +import styled from 'reshadow'; + +import { InputField } from '@dbeaver/core/blocks'; +import { useStyles } from '@dbeaver/core/theming'; + +import { AuthProvider } from '../../AuthProviderService'; +import { formStyles } from './formStyles'; + +type Props = { + provider: AuthProvider; + credentials: any; + authenticate: boolean; +} + +export const AuthProviderForm = observer(function AuthProviderForm({ + provider, + credentials, + authenticate, +}: Props) { + // const translate = useTranslate(); + const handleChange = useCallback((key: string, value: string) => { + credentials[key] = value; + }, [credentials]); + + return styled(useStyles(formStyles))( + <> + {provider.credentialParameters.map(parameter => parameter.user && ( + + handleChange(parameter.id, value)} + disabled={authenticate} + mod='surface' + > + {parameter.displayName} + + + ))} + + ); +}); diff --git a/webapp/packages/authentication/src/Dialog/AuthProviderForm/formStyles.ts b/webapp/packages/authentication/src/Dialog/AuthProviderForm/formStyles.ts new file mode 100644 index 0000000000..57bfd6867f --- /dev/null +++ b/webapp/packages/authentication/src/Dialog/AuthProviderForm/formStyles.ts @@ -0,0 +1,29 @@ +/* + * cloudbeaver - Cloud Database Manager + * Copyright (C) 2020 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 { css } from 'reshadow'; + +export const formStyles = css` + sub-label { + composes: theme-typography--caption from global; + line-height: 14px; + } + group { + box-sizing: border-box; + display: flex; + margin: 0 12px; + } + InputField[|short] { + min-width: unset; + max-width: 250px; + } + hr { + margin-left: 24px; + margin-right: 24px; + } +`; diff --git a/webapp/packages/authentication/src/index.ts b/webapp/packages/authentication/src/index.ts index eb55554528..86b1aba5f9 100644 --- a/webapp/packages/authentication/src/index.ts +++ b/webapp/packages/authentication/src/index.ts @@ -3,3 +3,6 @@ import { manifest } from './manifest'; export default manifest; export * from './AuthenticationService'; +export * from './AuthInfoService'; +export * from './AuthProviderService'; +export * from './Dialog/AuthDialogService'; diff --git a/webapp/packages/authentication/src/manifest.ts b/webapp/packages/authentication/src/manifest.ts index 2c419eb976..55b0afa13c 100644 --- a/webapp/packages/authentication/src/manifest.ts +++ b/webapp/packages/authentication/src/manifest.ts @@ -9,7 +9,10 @@ import { IServiceInjector, PluginManifest } from '@dbeaver/core/di'; import { AuthenticationService } from './AuthenticationService'; +import { AuthInfoService } from './AuthInfoService'; +import { AuthProviderService } from './AuthProviderService'; import { Bootstrap } from './Bootstrap'; +import { AuthDialogService } from './Dialog/AuthDialogService'; export const manifest: PluginManifest = { info: { @@ -18,6 +21,9 @@ export const manifest: PluginManifest = { providers: [ AuthenticationService, + AuthInfoService, + AuthProviderService, + AuthDialogService, ], async initialize(services: IServiceInjector) { diff --git a/webapp/packages/core/codegen.yml b/webapp/packages/core/codegen.yml index e97ca32468..4fcc3d461d 100644 --- a/webapp/packages/core/codegen.yml +++ b/webapp/packages/core/codegen.yml @@ -5,6 +5,7 @@ schema: - ../../../server/bundles/io.cloudbeaver.server/schema/service.sql.graphqls - ../../../server/bundles/io.cloudbeaver.service.metadata/schema/service.metadata.graphqls - ../../../server/bundles/io.cloudbeaver.service.data.transfer/schema/service.data.transfer.graphqls + - ../../../server/bundles/io.cloudbeaver.service.auth/schema/service.auth.graphqls documents: - ./src/**/*.gql generates: diff --git a/webapp/packages/core/src/queries/Authentication/authLogin.gql b/webapp/packages/core/src/queries/Authentication/authLogin.gql new file mode 100644 index 0000000000..58d62196da --- /dev/null +++ b/webapp/packages/core/src/queries/Authentication/authLogin.gql @@ -0,0 +1,12 @@ +query authLogin( + $provider: ID! + $credentials: Object! +) { + user: authLogin(provider: $provider, credentials: $credentials) { + userId + displayName + authProvider + loginTime + message + } +} \ No newline at end of file diff --git a/webapp/packages/core/src/queries/Authentication/authLogout.gql b/webapp/packages/core/src/queries/Authentication/authLogout.gql new file mode 100644 index 0000000000..842069abfa --- /dev/null +++ b/webapp/packages/core/src/queries/Authentication/authLogout.gql @@ -0,0 +1,3 @@ +query authLogout { + authLogout +} \ No newline at end of file diff --git a/webapp/packages/core/src/queries/Authentication/getAuthProviders.gql b/webapp/packages/core/src/queries/Authentication/getAuthProviders.gql new file mode 100644 index 0000000000..035dc77814 --- /dev/null +++ b/webapp/packages/core/src/queries/Authentication/getAuthProviders.gql @@ -0,0 +1,33 @@ +query getAuthProviders { + providers: authProviders { + id + label + icon + description + isDefault + + #configurationParameters { + # id + # displayName + # description + # category + # dataType + # value + # validValues + # defaultValue + # features + #} + + credentialParameters { + id + displayName + description + editable + identifying + admin + user + possibleValues + encryption + } + } +} \ No newline at end of file diff --git a/webapp/packages/core/src/queries/Authentication/getSessionUser.gql b/webapp/packages/core/src/queries/Authentication/getSessionUser.gql new file mode 100644 index 0000000000..ee457061b2 --- /dev/null +++ b/webapp/packages/core/src/queries/Authentication/getSessionUser.gql @@ -0,0 +1,9 @@ +query getSessionUser { + user: sessionUser { + userId + displayName + authProvider + loginTime + message + } +} \ No newline at end of file diff --git a/webapp/packages/core/src/root/queries/serverConfig.gql b/webapp/packages/core/src/root/queries/serverConfig.gql index 44ef426a82..c67adc5aa2 100644 --- a/webapp/packages/core/src/root/queries/serverConfig.gql +++ b/webapp/packages/core/src/root/queries/serverConfig.gql @@ -8,6 +8,8 @@ query serverConfig { supportsCustomConnections supportsConnectionBrowser supportsWorkspaces + anonymousAccessEnabled + authenticationEnabled supportedLanguages { isoCode displayName diff --git a/webapp/packages/core/src/sdk/sdk.ts b/webapp/packages/core/src/sdk/sdk.ts index be3a18b4cc..9248b093ac 100644 --- a/webapp/packages/core/src/sdk/sdk.ts +++ b/webapp/packages/core/src/sdk/sdk.ts @@ -31,6 +31,36 @@ export type AsyncTaskInfo = { taskResult?: Maybe; }; +export enum AuthCredentialEncryption { + None = "none", + Plain = "plain", + Hash = "hash", +} + +export type AuthCredentialInfo = { + id: Scalars["ID"]; + displayName: Scalars["String"]; + description?: Maybe; + editable?: Maybe; + identifying?: Maybe; + /** This field must be shown in admin panel */ + admin?: Maybe; + /** This field must be shown in login form */ + user?: Maybe; + possibleValues?: Maybe>>; + encryption?: Maybe; +}; + +export type AuthProviderInfo = { + id: Scalars["ID"]; + label: Scalars["String"]; + icon?: Maybe; + description?: Maybe; + isDefault?: Maybe; + configurationParameters: Array>; + credentialParameters: Array>; +}; + /** Configuration of particular connection. Used for new connection create. Includes auth info */ export type ConnectionConfig = { name?: Maybe; @@ -387,6 +417,10 @@ export type Query = { sqlDialectInfo?: Maybe; sqlListContexts?: Maybe>>; sqlCompletionProposals?: Maybe>>; + authLogin?: Maybe; + authLogout?: Maybe; + sessionUser?: Maybe; + authProviders: Array>; /** Available transfer processors */ dataTransferAvailableStreamProcessors?: Maybe< Array> @@ -447,6 +481,11 @@ export type QuerySqlCompletionProposalsArgs = { maxResults?: Maybe; }; +export type QueryAuthLoginArgs = { + provider: Scalars["ID"]; + credentials: Scalars["Object"]; +}; + export type QueryDataTransferExportDataFromContainerArgs = { connectionId: Scalars["ID"]; containerNodePath: Scalars["ID"]; @@ -594,6 +633,18 @@ export type SqlResultSet = { hasMoreData?: Maybe; }; +export type UserAuthInfo = { + /** User unique identifier */ + userId: Scalars["String"]; + /** Human readable display name. May be null */ + displayName?: Maybe; + /** Auth provider ID */ + authProvider: Scalars["String"]; + loginTime: Scalars["DateTime"]; + /** Optional login message */ + message?: Maybe; +}; + export type WebServiceConfig = { id: Scalars["String"]; name: Scalars["String"]; @@ -855,6 +906,65 @@ export type ChangeSessionLanguageMutation = Pick< "changeSessionLanguage" >; +export type AuthLoginQueryVariables = { + provider: Scalars["ID"]; + credentials: Scalars["Object"]; +}; + +export type AuthLoginQuery = { + user: Maybe< + Pick< + UserAuthInfo, + "userId" | "displayName" | "authProvider" | "loginTime" | "message" + > + >; +}; + +export type AuthLogoutQueryVariables = {}; + +export type AuthLogoutQuery = Pick; + +export type GetAuthProvidersQueryVariables = {}; + +export type GetAuthProvidersQuery = { + providers: Array< + Maybe< + Pick< + AuthProviderInfo, + "id" | "label" | "icon" | "description" | "isDefault" + > & { + credentialParameters: Array< + Maybe< + Pick< + AuthCredentialInfo, + | "id" + | "displayName" + | "description" + | "editable" + | "identifying" + | "admin" + | "user" + | "possibleValues" + | "encryption" + > + > + >; + } + > + >; +}; + +export type GetSessionUserQueryVariables = {}; + +export type GetSessionUserQuery = { + user: Maybe< + Pick< + UserAuthInfo, + "userId" | "displayName" | "authProvider" | "loginTime" | "message" + > + >; +}; + export type AsyncExportTaskStatusMutationVariables = { taskId: Scalars["String"]; }; @@ -1278,6 +1388,8 @@ export type ServerConfigQuery = { | "supportsCustomConnections" | "supportsConnectionBrowser" | "supportsWorkspaces" + | "anonymousAccessEnabled" + | "authenticationEnabled" > & { supportedLanguages: Array< Maybe> @@ -1513,6 +1625,55 @@ export const ChangeSessionLanguageDocument = gql` changeSessionLanguage(locale: $locale) } `; +export const AuthLoginDocument = gql` + query authLogin($provider: ID!, $credentials: Object!) { + user: authLogin(provider: $provider, credentials: $credentials) { + userId + displayName + authProvider + loginTime + message + } + } +`; +export const AuthLogoutDocument = gql` + query authLogout { + authLogout + } +`; +export const GetAuthProvidersDocument = gql` + query getAuthProviders { + providers: authProviders { + id + label + icon + description + isDefault + credentialParameters { + id + displayName + description + editable + identifying + admin + user + possibleValues + encryption + } + } + } +`; +export const GetSessionUserDocument = gql` + query getSessionUser { + user: sessionUser { + userId + displayName + authProvider + loginTime + message + } + } +`; export const AsyncExportTaskStatusDocument = gql` mutation asyncExportTaskStatus($taskId: String!) { taskInfo: asyncTaskStatus(id: $taskId) { @@ -1926,6 +2087,8 @@ export const ServerConfigDocument = gql` supportsCustomConnections supportsConnectionBrowser supportsWorkspaces + anonymousAccessEnabled + authenticationEnabled supportedLanguages { isoCode displayName @@ -2089,6 +2252,34 @@ export function getSdk(client: GraphQLClient) { variables, ); }, + authLogin(variables: AuthLoginQueryVariables): Promise { + return client.request( + print(AuthLoginDocument), + variables, + ); + }, + authLogout(variables?: AuthLogoutQueryVariables): Promise { + return client.request( + print(AuthLogoutDocument), + variables, + ); + }, + getAuthProviders( + variables?: GetAuthProvidersQueryVariables, + ): Promise { + return client.request( + print(GetAuthProvidersDocument), + variables, + ); + }, + getSessionUser( + variables?: GetSessionUserQueryVariables, + ): Promise { + return client.request( + print(GetSessionUserDocument), + variables, + ); + }, asyncExportTaskStatus( variables: AsyncExportTaskStatusMutationVariables, ): Promise {