CB-3511 display correct user's origin info (#1691)

* CB-3511 display correct user's origin info

* CB-3511 fix: remove origin auth request for users form

---------

Co-authored-by: Aleksey Potsetsuev <wrouds@gmail.com>
This commit is contained in:
Alexander Skoblikov
2023-05-24 23:34:30 +03:00
committed by GitHub
co-authored by Aleksey Potsetsuev
parent a2c18f78a7
commit 0fb82dc6e1
7 changed files with 92 additions and 66 deletions
@@ -123,7 +123,7 @@ public class WebPropertyInfo {
public Object getValue() throws DBException {
Object value = propertySource == null ? null : propertySource.getPropertyValue(session.getProgressMonitor(), property.getId());
if (property instanceof ObjectPropertyDescriptor) {
ObjectPropertyDescriptor opd = (ObjectPropertyDescriptor)property;
ObjectPropertyDescriptor opd = (ObjectPropertyDescriptor) property;
if (!showProtected && opd.isPassword() || opd.isHidden()) {
if (value == null || value.toString().isEmpty()) {
return "";
@@ -80,7 +80,7 @@ public class WebAuthInfo implements SMSessionPrincipal {
@Property
public WebUserOriginInfo getOrigin() {
return new WebUserOriginInfo(session, user, authProvider, true);
return new WebUserOriginInfo(session, user, authProvider);
}
@Property
@@ -20,7 +20,6 @@ import io.cloudbeaver.DBWebException;
import io.cloudbeaver.auth.SMAuthProviderExternal;
import io.cloudbeaver.model.WebObjectOrigin;
import io.cloudbeaver.model.WebPropertyInfo;
import io.cloudbeaver.model.session.WebAuthInfo;
import io.cloudbeaver.model.session.WebSession;
import io.cloudbeaver.registry.WebAuthProviderDescriptor;
import io.cloudbeaver.utils.WebCommonUtils;
@@ -28,13 +27,12 @@ import org.jkiss.code.NotNull;
import org.jkiss.code.Nullable;
import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.model.DBPObject;
import org.jkiss.dbeaver.model.auth.SMAuthProvider;
import org.jkiss.dbeaver.model.auth.SMSession;
import org.jkiss.dbeaver.model.impl.PropertyDescriptor;
import org.jkiss.dbeaver.model.meta.Property;
import org.jkiss.dbeaver.runtime.properties.PropertySourceMap;
import org.jkiss.utils.CommonUtils;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collections;
import java.util.Map;
@@ -45,23 +43,21 @@ public class WebUserOriginInfo implements WebObjectOrigin {
private static final Log log = Log.getLog(WebUserOriginInfo.class);
private final WebSession session;
private final WebUser user;
protected final WebSession session;
protected final WebUser user;
@NotNull
private final WebAuthProviderDescriptor authProvider;
private boolean selfIdentity;
protected final WebAuthProviderDescriptor authProviderDescriptor;
public WebUserOriginInfo(WebSession session, WebUser user, @NotNull WebAuthProviderDescriptor authProvider, boolean selfIdentity) {
public WebUserOriginInfo(WebSession session, WebUser user, @NotNull WebAuthProviderDescriptor authProvider) {
this.session = session;
this.user = user;
this.authProvider = authProvider;
this.selfIdentity = selfIdentity;
this.authProviderDescriptor = authProvider;
}
@NotNull
@Override
public String getType() {
return authProvider.getId();
return authProviderDescriptor.getId();
}
@Nullable
@@ -73,13 +69,13 @@ public class WebUserOriginInfo implements WebObjectOrigin {
@NotNull
@Override
public String getDisplayName() {
return authProvider.getLabel();
return authProviderDescriptor.getLabel();
}
@Nullable
@Override
public String getIcon() {
return WebCommonUtils.makeIconId(authProvider.getIcon());
return WebCommonUtils.makeIconId(authProviderDescriptor.getIcon());
}
@NotNull
@@ -95,25 +91,12 @@ public class WebUserOriginInfo implements WebObjectOrigin {
return new WebPropertyInfo[0];
}
try {
WebAuthInfo authInfo = session.getAuthInfo(authProvider.getId());
if (authInfo == null) {
throw new DBException("Session not authorized in auth provider '" + authProvider.getId() + "'");
}
SMSession authSession = authInfo.getAuthSession();
SMAuthProvider<?> authProvider = this.authProvider.getInstance();
if (authSession != null && authProvider instanceof SMAuthProviderExternal) {
if (!isValidSessionType(authSession, authProvider)) {
return new WebPropertyInfo[0];
}
DBPObject userDetails = ((SMAuthProviderExternal) authProvider).getUserDetails(
session.getProgressMonitor(),
session,
authSession,
user,
selfIdentity);
if (userDetails != null) {
return WebCommonUtils.getObjectProperties(session, userDetails);
}
SMAuthProvider<?> authProvider = this.authProviderDescriptor.getInstance();
if (authProvider instanceof SMAuthProviderExternal) {
// read user's info from credentials, previously we tried to read data from external service using
// SMAuthProviderExternal#getUserDetails
var creds = loadCredentials();
return mapCredsToProperties(session, creds);
}
} catch (Exception e) {
log.error(e);
@@ -121,16 +104,32 @@ public class WebUserOriginInfo implements WebObjectOrigin {
return new WebPropertyInfo[0];
}
private static boolean isValidSessionType(SMSession authSession, SMAuthProvider<?> authProvider) {
Type providerSuperClass = authProvider.getClass().getGenericSuperclass();
if (providerSuperClass instanceof ParameterizedType) {
Type[] typeArguments = ((ParameterizedType) providerSuperClass).getActualTypeArguments();
if (typeArguments.length == 1 && typeArguments[0] instanceof Class) {
// Wrong session type for this auth provider
return ((Class<?>) typeArguments[0]).isInstance(authSession);
}
protected Map<String, Object> loadCredentials() throws DBException {
return session.getSecurityController().getCurrentUserCredentials(this.authProviderDescriptor.getId());
}
private static WebPropertyInfo[] mapCredsToProperties(
WebSession session, Map<String, Object> creds
) {
if (CommonUtils.isEmpty(creds)) {
return new WebPropertyInfo[0];
}
return true;
var propSource = new PropertySourceMap(creds);
return creds.entrySet()
.stream()
.map(entry -> new PropertyDescriptor(
null,
entry.getKey(),
entry.getKey(),
null,
true,
entry.getValue().getClass(),
null,
new Object[0]
)
)
.map(propDescriptor -> new WebPropertyInfo(session, propDescriptor, propSource))
.toArray(WebPropertyInfo[]::new);
}
}
@@ -0,0 +1,41 @@
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2023 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.cloudbeaver.service.admin;
import io.cloudbeaver.model.session.WebSession;
import io.cloudbeaver.model.user.WebUser;
import io.cloudbeaver.model.user.WebUserOriginInfo;
import io.cloudbeaver.registry.WebAuthProviderDescriptor;
import org.jkiss.code.NotNull;
import org.jkiss.dbeaver.DBException;
import java.util.Map;
public class AdminOriginInfo extends WebUserOriginInfo {
public AdminOriginInfo(
WebSession session,
WebUser user,
@NotNull WebAuthProviderDescriptor authProvider
) {
super(session, user, authProvider);
}
@Override
protected Map<String, Object> loadCredentials() throws DBException {
return session.getAdminSecurityController().getUserCredentials(user.getUserId(), authProviderDescriptor.getId());
}
}
@@ -94,16 +94,16 @@ public class AdminUserInfo {
@Property
public WebUserOriginInfo[] getOrigins() throws DBWebException {
List<WebUserOriginInfo> result = new ArrayList<>();
List<AdminOriginInfo> result = new ArrayList<>();
for (String provider : getUserLinkedProviders()) {
WebAuthProviderDescriptor authProvider = WebAuthProviderRegistry.getInstance().getAuthProvider(provider);
if (authProvider == null) {
log.error("Auth provider '" + provider + "' not found");
} else {
result.add(new WebUserOriginInfo(session, user, authProvider, false));
result.add(new AdminOriginInfo(session, user, authProvider));
}
}
return result.toArray(new WebUserOriginInfo[0]);
return result.toArray(new AdminOriginInfo[0]);
}
@Property
@@ -71,7 +71,7 @@ public class WebUserAuthToken {
@NotNull
public WebUserOriginInfo getOrigin() {
return new WebUserOriginInfo(session, user, authInfo.getAuthProviderDescriptor(), true);
return new WebUserOriginInfo(session, user, authInfo.getAuthProviderDescriptor());
}
}
@@ -9,11 +9,11 @@
import { observer } from 'mobx-react-lite';
import styled from 'reshadow';
import { UserInfoResource, UsersResource } from '@cloudbeaver/core-authentication';
import { UsersResource } from '@cloudbeaver/core-authentication';
import { TextPlaceholder, Loader, ExceptionMessage, BASE_CONTAINERS_STYLES, ColoredContainer, ObjectPropertyInfoForm, Group, useAutoLoad, useObjectRef, IAutoLoadable, useTranslate, useStyles } from '@cloudbeaver/core-blocks';
import { useService } from '@cloudbeaver/core-di';
import type { AdminUserInfo, ObjectPropertyInfo } from '@cloudbeaver/core-sdk';
import { AuthenticationProvider, TabContainerPanelComponent, useTab, useTabState } from '@cloudbeaver/core-ui';
import { TabContainerPanelComponent, useTab, useTabState } from '@cloudbeaver/core-ui';
import { getOriginTabId } from './getOriginTabId';
import type { IUserFormProps } from './UserFormService';
@@ -38,7 +38,6 @@ export const OriginInfoPanel: TabContainerPanelComponent<IUserFormProps> = obser
const style = useStyles(BASE_CONTAINERS_STYLES);
const translate = useTranslate();
const usersResource = useService(UsersResource);
const userInfoService = useService(UserInfoResource);
const state = useTabState<IState>(() => ({
origin: null,
properties: [],
@@ -54,9 +53,6 @@ export const OriginInfoPanel: TabContainerPanelComponent<IUserFormProps> = obser
origin = user.origins[0];
}
const providerId = origin.subType ?? origin.type;
const authorized = userInfoService.hasToken(providerId);
const loadableState = useObjectRef<IInnerState>(() => ({
get exception(): Error | null {
return this.state.exception;
@@ -109,7 +105,7 @@ export const OriginInfoPanel: TabContainerPanelComponent<IUserFormProps> = obser
const { selected } = useTab(tabId);
useAutoLoad(loadableState, selected && authorized);
useAutoLoad(loadableState, selected);
if (!selected) {
return null;
@@ -135,16 +131,6 @@ export const OriginInfoPanel: TabContainerPanelComponent<IUserFormProps> = obser
);
}
if (!authorized) {
return styled(style)(
<ColoredContainer parent>
<Group large>
<AuthenticationProvider providerId={providerId} onAuthenticate={() => loadableState.reload?.()} />
</Group>
</ColoredContainer>
);
}
if (!origin || (state.loaded && state.properties.length === 0)) {
return styled(style)(
<ColoredContainer parent>