diff --git a/README.md b/README.md
index 3e42e01cbb..95fbf24601 100644
--- a/README.md
+++ b/README.md
@@ -22,6 +22,12 @@ You can see live demo of CloudBeaver here: https://demo.cloudbeaver.io
## Changelog
+### CloudBeaver 22.2.3 - 2022-10-14
+- Users can specify the connection for the saved script in the Resource Manager. This connection will be selected by default when a user opens this script.
+- The connection configuration through URL has been added for generic drivers.
+- User access information can be stored in an SQL Server database.
+- Different bugs have been fixed.
+
### CloudBeaver 22.2.2 - 2022-10-10
- Administrators now:
- have permission to create connections in both projects, Shared and Private, when it’s restricted for other users,
diff --git a/config/core/initial-data.conf b/config/core/initial-data.conf
index a33187160f..fe8f9db507 100644
--- a/config/core/initial-data.conf
+++ b/config/core/initial-data.conf
@@ -1,13 +1,13 @@
{
teams: [
{
- teamId: "admin",
+ subjectId: "admin",
name: "Admin",
description: "Administrative access. Has all permissions.",
permissions: [ "public", "admin" ]
},
{
- teamId: "user",
+ subjectId: "user",
name: "User",
description: "Standard user",
permissions: [ "public" ]
diff --git a/server/bundles/io.cloudbeaver.model/META-INF/MANIFEST.MF b/server/bundles/io.cloudbeaver.model/META-INF/MANIFEST.MF
index d3f160a993..13faa28d65 100644
--- a/server/bundles/io.cloudbeaver.model/META-INF/MANIFEST.MF
+++ b/server/bundles/io.cloudbeaver.model/META-INF/MANIFEST.MF
@@ -18,7 +18,6 @@ Require-Bundle: org.jkiss.dbeaver.model;visibility:=reexport,
Export-Package: io.cloudbeaver,
io.cloudbeaver.auth,
io.cloudbeaver.auth.provider,
- io.cloudbeaver.auth.provider.fa,
io.cloudbeaver.auth.provider.local,
io.cloudbeaver.events,
io.cloudbeaver.model,
diff --git a/server/bundles/io.cloudbeaver.model/plugin.xml b/server/bundles/io.cloudbeaver.model/plugin.xml
index 1bbc06fb18..96847f47d7 100644
--- a/server/bundles/io.cloudbeaver.model/plugin.xml
+++ b/server/bundles/io.cloudbeaver.model/plugin.xml
@@ -3,5 +3,8 @@
+
+
+
diff --git a/server/bundles/io.cloudbeaver.server/schema/io.cloudbeaver.feature.exsd b/server/bundles/io.cloudbeaver.model/schema/io.cloudbeaver.feature.exsd
similarity index 87%
rename from server/bundles/io.cloudbeaver.server/schema/io.cloudbeaver.feature.exsd
rename to server/bundles/io.cloudbeaver.model/schema/io.cloudbeaver.feature.exsd
index 69cfc62e5c..c49cec3881 100644
--- a/server/bundles/io.cloudbeaver.server/schema/io.cloudbeaver.feature.exsd
+++ b/server/bundles/io.cloudbeaver.model/schema/io.cloudbeaver.feature.exsd
@@ -2,7 +2,7 @@
-
+
Web feature
diff --git a/server/bundles/io.cloudbeaver.server/schema/io.cloudbeaver.valueSerializer.exsd b/server/bundles/io.cloudbeaver.model/schema/io.cloudbeaver.valueSerializer.exsd
similarity index 100%
rename from server/bundles/io.cloudbeaver.server/schema/io.cloudbeaver.valueSerializer.exsd
rename to server/bundles/io.cloudbeaver.model/schema/io.cloudbeaver.valueSerializer.exsd
diff --git a/server/bundles/io.cloudbeaver.model/schema/org.jkiss.dbeaver.authProvider.exsd b/server/bundles/io.cloudbeaver.model/schema/org.jkiss.dbeaver.authProvider.exsd
new file mode 100644
index 0000000000..222af0fe9d
--- /dev/null
+++ b/server/bundles/io.cloudbeaver.model/schema/org.jkiss.dbeaver.authProvider.exsd
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+ DBeaver auth provider
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Data source auth model description
+
+
+
+
+
+
+
+
+
+ [Enter API information here.]
+
+
+
+
+
+
+
+
+ [Enter information about supplied implementation of this extension point.]
+
+
+
+
+
diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/DBWUserIdentity.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/DBWUserIdentity.java
index de76364aeb..498b5fffbe 100644
--- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/DBWUserIdentity.java
+++ b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/DBWUserIdentity.java
@@ -17,8 +17,9 @@
package io.cloudbeaver;
import org.jkiss.code.NotNull;
+import org.jkiss.code.Nullable;
-import java.util.HashMap;
+import java.util.LinkedHashMap;
import java.util.Map;
/**
@@ -30,13 +31,21 @@ public class DBWUserIdentity {
@NotNull
private final String displayName;
- private final Map metaParameters = new HashMap<>();
+ private final Map metaParameters = new LinkedHashMap<>();
+ @Nullable
+ private String providedUserRole;
+ @Nullable
+ private String[] providedTeamIds;
public DBWUserIdentity(@NotNull String id, @NotNull String displayName) {
this(id, displayName, Map.of());
}
- public DBWUserIdentity(@NotNull String id, @NotNull String displayName, @NotNull Map metaParameters) {
+ public DBWUserIdentity(
+ @NotNull String id,
+ @NotNull String displayName,
+ @NotNull Map metaParameters
+ ) {
this.id = id;
this.displayName = displayName;
this.metaParameters.putAll(metaParameters);
@@ -56,4 +65,30 @@ public class DBWUserIdentity {
public Map getMetaParameters() {
return Map.copyOf(metaParameters);
}
+
+ public void setMetaParameter(@NotNull String name, @Nullable String value) {
+ if (value == null) {
+ metaParameters.remove(name);
+ } else {
+ metaParameters.put(name, value);
+ }
+ }
+
+ @Nullable
+ public String getProvidedUserRole() {
+ return providedUserRole;
+ }
+
+ public void setProvidedUserRole(@Nullable String providedUserRole) {
+ this.providedUserRole = providedUserRole;
+ }
+
+ @Nullable
+ public String[] getProvidedTeamIds() {
+ return providedTeamIds;
+ }
+
+ public void setProvidedTeamIds(@Nullable String[] providedTeamIds) {
+ this.providedTeamIds = providedTeamIds;
+ }
}
diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/WebDataSourceRegistryProxy.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/WebDataSourceRegistryProxy.java
index 2bc52588d3..7c781afdd2 100644
--- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/WebDataSourceRegistryProxy.java
+++ b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/WebDataSourceRegistryProxy.java
@@ -41,7 +41,7 @@ public class WebDataSourceRegistryProxy implements DBPDataSourceRegistry, DataSo
@Override
public DBPDataSourceContainer getDataSource(String id) {
DBPDataSourceContainer dataSource = dataSourceRegistry.getDataSource(id);
- if (dataSourceFilter != null && !dataSourceFilter.filter(dataSource)) {
+ if (dataSource == null || dataSourceFilter != null && !dataSourceFilter.filter(dataSource)) {
return null;
}
return dataSource;
diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/user/WebUserCredentials.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/auth/SMAuthProviderAssigner.java
similarity index 54%
rename from server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/user/WebUserCredentials.java
rename to server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/auth/SMAuthProviderAssigner.java
index 9b769d2d85..6bd08092b8 100644
--- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/user/WebUserCredentials.java
+++ b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/auth/SMAuthProviderAssigner.java
@@ -14,11 +14,27 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package io.cloudbeaver.model.user;
+package io.cloudbeaver.auth;
+
+import org.jkiss.code.NotNull;
+import org.jkiss.dbeaver.DBException;
+import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
+
+import java.util.Map;
/**
- * Web user.
+ * Auth
+ * Authenticates user using external user identity
*/
-public class WebUserCredentials {
+public interface SMAuthProviderAssigner {
+
+ @NotNull
+ SMAutoAssign detectAutoAssignments(
+ @NotNull DBRProgressMonitor monitor,
+ @NotNull Map providerConfig,
+ @NotNull Map authParameters
+ ) throws DBException;
+
+ String getExternalTeamIdMetadataFieldName();
}
diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/auth/SMAuthProviderExternal.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/auth/SMAuthProviderExternal.java
index 6bae9f9469..a68d5d7ac4 100644
--- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/auth/SMAuthProviderExternal.java
+++ b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/auth/SMAuthProviderExternal.java
@@ -50,7 +50,7 @@ public interface SMAuthProviderExternal extends
DBWUserIdentity getUserIdentity(
@NotNull DBRProgressMonitor monitor,
@NotNull Map providerConfig,
- @NotNull Map credentials) throws DBException;
+ @NotNull Map authParameters) throws DBException;
/**
* Get specified user details.
diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/auth/SMWAuthProviderFederated.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/auth/SMAuthProviderFederated.java
similarity index 97%
rename from server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/auth/SMWAuthProviderFederated.java
rename to server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/auth/SMAuthProviderFederated.java
index f2a42ac129..c6d7044edb 100644
--- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/auth/SMWAuthProviderFederated.java
+++ b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/auth/SMAuthProviderFederated.java
@@ -26,7 +26,7 @@ import java.util.Map;
* Federated auth provider.
* Provides links to external auth resource
*/
-public interface SMWAuthProviderFederated {
+public interface SMAuthProviderFederated {
/**
* Returns new identifying credentials which can be used to find/create user in database
diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/auth/SMAutoAssign.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/auth/SMAutoAssign.java
new file mode 100644
index 0000000000..f697fae7ff
--- /dev/null
+++ b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/auth/SMAutoAssign.java
@@ -0,0 +1,50 @@
+/*
+ * DBeaver - Universal Database Manager
+ * Copyright (C) 2010-2022 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.auth;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class SMAutoAssign {
+ private String authRole;
+ private List externalTeamIds = new ArrayList<>();
+
+ public SMAutoAssign() {
+ }
+
+ public SMAutoAssign(String authRole, List externalRolesIds) {
+ this.authRole = authRole;
+ this.externalTeamIds = externalRolesIds;
+ }
+
+ public String getAuthRole() {
+ return authRole;
+ }
+
+ public void setAuthRole(String authRole) {
+ this.authRole = authRole;
+ }
+
+ public List getExternalTeamIds() {
+ return externalTeamIds;
+ }
+
+ public void addExternalTeamId(String externalRoleId) {
+ this.externalTeamIds.add(externalRoleId);
+ }
+}
diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/auth/provider/fa/AbstractSessionFederated.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/auth/provider/fa/AbstractSessionFederated.java
deleted file mode 100644
index fa81030504..0000000000
--- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/auth/provider/fa/AbstractSessionFederated.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * DBeaver - Universal Database Manager
- * Copyright (C) 2010-2022 DBeaver Corp
- *
- * All Rights Reserved.
- *
- * NOTICE: All information contained herein is, and remains
- * the property of DBeaver Corp and its suppliers, if any.
- * The intellectual and technical concepts contained
- * herein are proprietary to DBeaver Corp and its suppliers
- * and may be covered by U.S. and Foreign Patents,
- * patents in process, and are protected by trade secret or copyright law.
- * Dissemination of this information or reproduction of this material
- * is strictly forbidden unless prior written permission is obtained
- * from DBeaver Corp.
- */
-
-package io.cloudbeaver.auth.provider.fa;
-
-import org.jkiss.code.NotNull;
-import org.jkiss.dbeaver.model.auth.*;
-
-import java.time.LocalDateTime;
-import java.util.Map;
-
-public abstract class AbstractSessionFederated implements SMSessionFederated {
-
- @NotNull
- protected final Map authParameters;
- @NotNull
- protected final SMSession parentSession;
- @NotNull
- protected final SMAuthSpace space;
-
- protected AbstractSessionFederated(@NotNull SMSession parentSession, @NotNull SMAuthSpace space, @NotNull Map authParameters) {
- this.parentSession = parentSession;
- this.space = space;
- this.authParameters = authParameters;
- }
-
- @NotNull
- @Override
- public SMAuthSpace getSessionSpace() {
- return space;
- }
-
- @NotNull
- @Override
- public SMSessionContext getSessionContext() {
- return this.parentSession.getSessionContext();
- }
-
- @Override
- public SMSessionPrincipal getSessionPrincipal() {
- return parentSession.getSessionPrincipal();
- }
-
- @NotNull
- @Override
- public LocalDateTime getSessionStart() {
- return parentSession.getSessionStart();
- }
-
- @Override
- public void close() {
- // do nothing
- }
-
-}
diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/auth/provider/fa/FederatedUserDetails.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/auth/provider/fa/FederatedUserDetails.java
deleted file mode 100644
index b45a2c398a..0000000000
--- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/auth/provider/fa/FederatedUserDetails.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * DBeaver - Universal Database Manager
- * Copyright (C) 2010-2022 DBeaver Corp
- *
- * All Rights Reserved.
- *
- * NOTICE: All information contained herein is, and remains
- * the property of DBeaver Corp and its suppliers, if any.
- * The intellectual and technical concepts contained
- * herein are proprietary to DBeaver Corp and its suppliers
- * and may be covered by U.S. and Foreign Patents,
- * patents in process, and are protected by trade secret or copyright law.
- * Dissemination of this information or reproduction of this material
- * is strictly forbidden unless prior written permission is obtained
- * from DBeaver Corp.
- */
-
-package io.cloudbeaver.auth.provider.fa;
-
-import io.cloudbeaver.model.user.WebUser;
-import org.jkiss.code.NotNull;
-import org.jkiss.dbeaver.model.DBPObject;
-import org.jkiss.dbeaver.model.meta.Property;
-
-public class FederatedUserDetails implements DBPObject {
-
- @NotNull
- private AbstractSessionFederated session;
- @NotNull
- private WebUser user;
-
- public FederatedUserDetails(@NotNull AbstractSessionFederated session, @NotNull WebUser user) {
- this.session = session;
- this.user = user;
- }
-
- @NotNull
- public AbstractSessionFederated getSession() {
- return session;
- }
-
- @Property
- public String getEmail() {
- return user.getUserId();
- }
-
-}
diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/app/BaseAuthWebAppConfiguration.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/app/BaseAuthWebAppConfiguration.java
index ae5b7db8f2..567c05e7b8 100644
--- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/app/BaseAuthWebAppConfiguration.java
+++ b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/app/BaseAuthWebAppConfiguration.java
@@ -19,11 +19,11 @@ package io.cloudbeaver.model.app;
import com.google.gson.annotations.Expose;
import io.cloudbeaver.auth.provider.local.LocalAuthProviderConstants;
+import io.cloudbeaver.registry.WebAuthProviderDescriptor;
+import io.cloudbeaver.registry.WebAuthProviderRegistry;
import org.jkiss.code.NotNull;
import org.jkiss.code.Nullable;
import org.jkiss.dbeaver.model.security.SMAuthProviderCustomConfiguration;
-import org.jkiss.dbeaver.registry.auth.AuthProviderDescriptor;
-import org.jkiss.dbeaver.registry.auth.AuthProviderRegistry;
import org.jkiss.utils.ArrayUtils;
import java.util.*;
@@ -65,8 +65,8 @@ public abstract class BaseAuthWebAppConfiguration extends BaseWebAppConfiguratio
public String[] getEnabledAuthProviders() {
if (enabledAuthProviders == null) {
// No config - enable all providers (+backward compatibility)
- return AuthProviderRegistry.getInstance().getAuthProviders()
- .stream().map(AuthProviderDescriptor::getId).toArray(String[]::new);
+ return WebAuthProviderRegistry.getInstance().getAuthProviders()
+ .stream().map(WebAuthProviderDescriptor::getId).toArray(String[]::new);
}
return enabledAuthProviders;
}
@@ -78,7 +78,7 @@ public abstract class BaseAuthWebAppConfiguration extends BaseWebAppConfiguratio
@Override
public boolean isAuthProviderEnabled(String id) {
- var authProviderDescriptor = AuthProviderRegistry.getInstance().getAuthProvider(id);
+ var authProviderDescriptor = WebAuthProviderRegistry.getInstance().getAuthProvider(id);
if (authProviderDescriptor == null) {
return false;
}
diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/session/WebAuthInfo.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/session/WebAuthInfo.java
index 06663c190d..a651608295 100644
--- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/session/WebAuthInfo.java
+++ b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/session/WebAuthInfo.java
@@ -17,16 +17,16 @@
package io.cloudbeaver.model.session;
import io.cloudbeaver.DBWUserIdentity;
-import io.cloudbeaver.model.user.WebAuthProviderConfiguration;
import io.cloudbeaver.model.user.WebUser;
import io.cloudbeaver.model.user.WebUserOriginInfo;
+import io.cloudbeaver.registry.WebAuthProviderConfiguration;
+import io.cloudbeaver.registry.WebAuthProviderDescriptor;
import org.jkiss.code.NotNull;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.model.auth.SMAuthProvider;
import org.jkiss.dbeaver.model.auth.SMSession;
import org.jkiss.dbeaver.model.auth.SMSessionPrincipal;
import org.jkiss.dbeaver.model.meta.Property;
-import org.jkiss.dbeaver.registry.auth.AuthProviderDescriptor;
import java.time.OffsetDateTime;
import java.util.Map;
@@ -40,7 +40,7 @@ public class WebAuthInfo implements SMSessionPrincipal {
private final WebSession session;
private final WebUser user;
- private final AuthProviderDescriptor authProvider;
+ private final WebAuthProviderDescriptor authProvider;
private WebAuthProviderConfiguration authProviderConfiguration;
private SMSession authSession;
private final OffsetDateTime loginTime;
@@ -52,7 +52,7 @@ public class WebAuthInfo implements SMSessionPrincipal {
public WebAuthInfo(
@NotNull WebSession session,
@NotNull WebUser user,
- @NotNull AuthProviderDescriptor authProvider,
+ @NotNull WebAuthProviderDescriptor authProvider,
@NotNull DBWUserIdentity userIdentity,
@NotNull SMSession authSession,
@NotNull OffsetDateTime loginTime) {
@@ -112,7 +112,7 @@ public class WebAuthInfo implements SMSessionPrincipal {
return userIdentity;
}
- public AuthProviderDescriptor getAuthProviderDescriptor() {
+ public WebAuthProviderDescriptor getAuthProviderDescriptor() {
return authProvider;
}
diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/session/WebSession.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/session/WebSession.java
index 99f2d8d325..7d203fb14b 100644
--- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/session/WebSession.java
+++ b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/session/WebSession.java
@@ -329,6 +329,10 @@ public class WebSession extends AbstractSessionPersistent
private void loadProjects() {
WebUser user = userContext.getUser();
+ if (user == null && DBWorkbench.isDistributed()) {
+ // No anonymous mode in distributed apps
+ return;
+ }
refreshAccessibleConnectionIds();
try {
RMController controller = application.getResourceController(this, getSecurityController());
diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/session/WebSessionAuthProcessor.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/session/WebSessionAuthProcessor.java
index d8eeedb840..d731b6bbdd 100644
--- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/session/WebSessionAuthProcessor.java
+++ b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/session/WebSessionAuthProcessor.java
@@ -23,6 +23,8 @@ import io.cloudbeaver.DBWebException;
import io.cloudbeaver.auth.SMAuthProviderExternal;
import io.cloudbeaver.model.app.WebAuthConfiguration;
import io.cloudbeaver.model.user.WebUser;
+import io.cloudbeaver.registry.WebAuthProviderDescriptor;
+import io.cloudbeaver.registry.WebAuthProviderRegistry;
import io.cloudbeaver.utils.WebAppUtils;
import org.jkiss.code.NotNull;
import org.jkiss.dbeaver.DBException;
@@ -31,8 +33,6 @@ import org.jkiss.dbeaver.model.auth.SMAuthInfo;
import org.jkiss.dbeaver.model.auth.SMAuthProvider;
import org.jkiss.dbeaver.model.auth.SMSession;
import org.jkiss.dbeaver.model.exec.DBCException;
-import org.jkiss.dbeaver.registry.auth.AuthProviderDescriptor;
-import org.jkiss.dbeaver.registry.auth.AuthProviderRegistry;
import org.jkiss.utils.CommonUtils;
import java.time.OffsetDateTime;
@@ -192,8 +192,8 @@ public class WebSessionAuthProcessor {
}
}
- private AuthProviderDescriptor getAuthProvider(String providerId) throws DBWebException {
- AuthProviderDescriptor authProvider = AuthProviderRegistry.getInstance().getAuthProvider(providerId);
+ private WebAuthProviderDescriptor getAuthProvider(String providerId) throws DBWebException {
+ WebAuthProviderDescriptor authProvider = WebAuthProviderRegistry.getInstance().getAuthProvider(providerId);
if (authProvider == null) {
throw new DBWebException("Invalid auth provider '" + providerId + "'");
}
diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/user/WebUserConstants.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/user/WebUserConstants.java
deleted file mode 100644
index a792f182b1..0000000000
--- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/user/WebUserConstants.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * DBeaver - Universal Database Manager
- * Copyright (C) 2010-2022 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.model.user;
-
-public interface WebUserConstants {
- String META_FIRST_NAME = "firstName";
- String META_LAST_NAME = "lastName";
-}
diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/user/WebUserOriginInfo.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/user/WebUserOriginInfo.java
index 333066c37b..ef02b350e3 100644
--- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/user/WebUserOriginInfo.java
+++ b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/user/WebUserOriginInfo.java
@@ -22,6 +22,7 @@ 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;
import org.jkiss.code.NotNull;
import org.jkiss.code.Nullable;
@@ -31,7 +32,6 @@ 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.meta.Property;
-import org.jkiss.dbeaver.registry.auth.AuthProviderDescriptor;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
@@ -48,10 +48,10 @@ public class WebUserOriginInfo implements WebObjectOrigin {
private final WebSession session;
private final WebUser user;
@NotNull
- private final AuthProviderDescriptor authProvider;
+ private final WebAuthProviderDescriptor authProvider;
private boolean selfIdentity;
- public WebUserOriginInfo(WebSession session, WebUser user, @NotNull AuthProviderDescriptor authProvider, boolean selfIdentity) {
+ public WebUserOriginInfo(WebSession session, WebUser user, @NotNull WebAuthProviderDescriptor authProvider, boolean selfIdentity) {
this.session = session;
this.user = user;
this.authProvider = authProvider;
diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/user/WebAuthProviderConfiguration.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/registry/WebAuthProviderConfiguration.java
similarity index 72%
rename from server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/user/WebAuthProviderConfiguration.java
rename to server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/registry/WebAuthProviderConfiguration.java
index 411dc322fd..6e49b819cb 100644
--- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/user/WebAuthProviderConfiguration.java
+++ b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/registry/WebAuthProviderConfiguration.java
@@ -14,29 +14,28 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package io.cloudbeaver.model.user;
+package io.cloudbeaver.registry;
-import io.cloudbeaver.auth.SMWAuthProviderFederated;
+import io.cloudbeaver.auth.SMAuthProviderFederated;
import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.model.auth.SMAuthProvider;
import org.jkiss.dbeaver.model.meta.Property;
import org.jkiss.dbeaver.model.security.SMAuthProviderCustomConfiguration;
-import org.jkiss.dbeaver.registry.auth.AuthProviderDescriptor;
import java.util.Map;
/**
- * WebAuthProviderInfo.
+ * WebAuthProviderConfiguration.
*/
public class WebAuthProviderConfiguration {
private static final Log log = Log.getLog(WebAuthProviderConfiguration.class);
- private final AuthProviderDescriptor providerDescriptor;
+ private final WebAuthProviderDescriptor providerDescriptor;
private final SMAuthProviderCustomConfiguration config;
- public WebAuthProviderConfiguration(AuthProviderDescriptor providerDescriptor, SMAuthProviderCustomConfiguration config) {
+ public WebAuthProviderConfiguration(WebAuthProviderDescriptor providerDescriptor, SMAuthProviderCustomConfiguration config) {
this.providerDescriptor = providerDescriptor;
this.config = config;
}
@@ -72,25 +71,25 @@ public class WebAuthProviderConfiguration {
@Property
public String getSignInLink() throws DBException {
SMAuthProvider> instance = providerDescriptor.getInstance();
- return instance instanceof SMWAuthProviderFederated ? ((SMWAuthProviderFederated) instance).getSignInLink(getId(), config.getParameters()) : null;
+ return instance instanceof SMAuthProviderFederated ? ((SMAuthProviderFederated) instance).getSignInLink(getId(), config.getParameters()) : null;
}
@Property
public String getSignOutLink() throws DBException {
SMAuthProvider> instance = providerDescriptor.getInstance();
- return instance instanceof SMWAuthProviderFederated ? ((SMWAuthProviderFederated) instance).getSignOutLink(getId(), config.getParameters()) : null;
+ return instance instanceof SMAuthProviderFederated ? ((SMAuthProviderFederated) instance).getSignOutLink(getId(), config.getParameters()) : null;
}
@Property
public String getRedirectLink() throws DBException {
SMAuthProvider> instance = providerDescriptor.getInstance();
- return instance instanceof SMWAuthProviderFederated ? ((SMWAuthProviderFederated) instance).getRedirectLink(getId(), config.getParameters()) : null;
+ return instance instanceof SMAuthProviderFederated ? ((SMAuthProviderFederated) instance).getRedirectLink(getId(), config.getParameters()) : null;
}
@Property
public String getMetadataLink() throws DBException {
SMAuthProvider> instance = providerDescriptor.getInstance();
- return instance instanceof SMWAuthProviderFederated ? ((SMWAuthProviderFederated) instance).getMetadataLink(getId(), config.getParameters()) : null;
+ return instance instanceof SMAuthProviderFederated ? ((SMAuthProviderFederated) instance).getMetadataLink(getId(), config.getParameters()) : null;
}
@Override
diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/registry/WebAuthProviderDescriptor.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/registry/WebAuthProviderDescriptor.java
new file mode 100644
index 0000000000..a6c46bebc1
--- /dev/null
+++ b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/registry/WebAuthProviderDescriptor.java
@@ -0,0 +1,189 @@
+/*
+ * DBeaver - Universal Database Manager
+ * Copyright (C) 2010-2022 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.registry;
+
+import org.eclipse.core.runtime.IConfigurationElement;
+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.DBPImage;
+import org.jkiss.dbeaver.model.auth.AuthPropertyDescriptor;
+import org.jkiss.dbeaver.model.auth.SMAuthProvider;
+import org.jkiss.dbeaver.model.impl.AbstractDescriptor;
+import org.jkiss.dbeaver.model.impl.PropertyDescriptor;
+import org.jkiss.dbeaver.model.preferences.DBPPropertyDescriptor;
+import org.jkiss.dbeaver.model.security.SMAuthCredentialsProfile;
+import org.jkiss.dbeaver.model.security.SMAuthProviderDescriptor;
+import org.jkiss.dbeaver.model.security.SMSubjectType;
+import org.jkiss.utils.ArrayUtils;
+import org.jkiss.utils.CommonUtils;
+
+import java.util.*;
+
+/**
+ * Auth provider descriptor
+ */
+public class WebAuthProviderDescriptor extends AbstractDescriptor {
+
+ public static final String EXTENSION_ID = "org.jkiss.dbeaver.auth.provider"; //$NON-NLS-1$
+ private static final Log log = Log.getLog(WebAuthProviderDescriptor.class);
+
+ private final IConfigurationElement cfg;
+
+ private final ObjectType implType;
+ private final Map> metaProperties = new HashMap<>();
+ private SMAuthProvider> instance;
+ private final DBPImage icon;
+ private final Map configurationParameters = new LinkedHashMap<>();
+ private final List credentialProfiles = new ArrayList<>();
+ private final boolean configurable;
+ private final boolean trusted;
+ private final String[] requiredFeatures;
+
+ public WebAuthProviderDescriptor(IConfigurationElement cfg) {
+ super(cfg);
+ this.cfg = cfg;
+ this.implType = new ObjectType(cfg, "class");
+ this.icon = iconToImage(cfg.getAttribute("icon"));
+ this.configurable = CommonUtils.toBoolean(cfg.getAttribute("configurable"));
+ this.trusted = CommonUtils.toBoolean(cfg.getAttribute("trusted"));
+
+ for (IConfigurationElement cfgElement : cfg.getChildren("configuration")) {
+ for (IConfigurationElement propGroup : ArrayUtils.safeArray(cfgElement.getChildren(PropertyDescriptor.TAG_PROPERTY_GROUP))) {
+ String category = propGroup.getAttribute(PropertyDescriptor.ATTR_LABEL);
+ IConfigurationElement[] propElements = propGroup.getChildren(PropertyDescriptor.TAG_PROPERTY);
+ for (IConfigurationElement prop : propElements) {
+ PropertyDescriptor propertyDescriptor = new PropertyDescriptor(category, prop);
+ configurationParameters.put(CommonUtils.toString(propertyDescriptor.getId()), propertyDescriptor);
+ }
+ }
+ }
+ for (IConfigurationElement credElement : cfg.getChildren("credentials")) {
+ credentialProfiles.add(new SMAuthCredentialsProfile(credElement));
+ }
+ for (IConfigurationElement mpElement : cfg.getChildren("metaProperties")) {
+ SMSubjectType subjectType = CommonUtils.valueOf(SMSubjectType.class, mpElement.getAttribute("type"), SMSubjectType.user);
+ List metaProps = new ArrayList<>();
+ for (IConfigurationElement propGroup : ArrayUtils.safeArray(mpElement.getChildren(PropertyDescriptor.TAG_PROPERTY_GROUP))) {
+ metaProps.addAll(PropertyDescriptor.extractProperties(propGroup));
+ }
+ metaProperties.put(subjectType, metaProps);
+ }
+
+ String rfList = cfg.getAttribute("requiredFeatures");
+ if (!CommonUtils.isEmpty(rfList)) {
+ requiredFeatures = rfList.split(",");
+ } else {
+ requiredFeatures = null;
+ }
+ }
+
+ @NotNull
+ public String getId() {
+ return cfg.getAttribute("id");
+ }
+
+ public String getLabel() {
+ return cfg.getAttribute("label");
+ }
+
+ public String getDescription() {
+ return cfg.getAttribute("description");
+ }
+
+ public DBPImage getIcon() {
+ return icon;
+ }
+
+ public boolean isConfigurable() {
+ return configurable;
+ }
+
+ public boolean isTrusted() {
+ return trusted;
+ }
+
+ public List getConfigurationParameters() {
+ return new ArrayList<>(configurationParameters.values());
+ }
+
+ public List getCredentialProfiles() {
+ return new ArrayList<>(credentialProfiles);
+ }
+
+ public List getCredentialParameters(String[] propNames) {
+ if (credentialProfiles.size() > 1) {
+ for (SMAuthCredentialsProfile profile : credentialProfiles) {
+ if (profile.getCredentialParameters().size() == propNames.length) {
+ boolean matches = true;
+ for (String paramName : propNames) {
+ if (profile.getCredentialParameter(paramName) == null) {
+ matches = false;
+ break;
+ }
+ }
+ if (matches) {
+ return profile.getCredentialParameters();
+ }
+ }
+ }
+ }
+ return credentialProfiles.get(0).getCredentialParameters();
+ }
+
+ @NotNull
+ public SMAuthProvider> getInstance() {
+ if (instance == null) {
+ try {
+ instance = implType.createInstance(SMAuthProvider.class);
+ } catch (DBException e) {
+ throw new IllegalStateException("Can not instantiate auth provider '" + implType.getImplName() + "'", e);
+ }
+ }
+ return instance;
+ }
+
+ public String[] getRequiredFeatures() {
+ return requiredFeatures;
+ }
+
+ @Override
+ public String toString() {
+ return getId();
+ }
+
+ public SMAuthProviderDescriptor createDescriptorBean() {
+ SMAuthProviderDescriptor smInfo = new SMAuthProviderDescriptor();
+ smInfo.setId(this.getId());
+ smInfo.setLabel(this.getLabel());
+ smInfo.setDescription(this.getDescription());
+ smInfo.setCredentialProfiles(this.getCredentialProfiles());
+
+ if (this.icon != null) {
+ smInfo.setIcon(icon.getLocation());
+ }
+
+ return smInfo;
+ }
+
+ @Nullable
+ public List getMetaProperties(SMSubjectType subjectType) {
+ return metaProperties.get(subjectType);
+ }
+
+}
diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/registry/WebAuthProviderRegistry.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/registry/WebAuthProviderRegistry.java
new file mode 100644
index 0000000000..3aba8bcfc0
--- /dev/null
+++ b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/registry/WebAuthProviderRegistry.java
@@ -0,0 +1,85 @@
+/*
+ * DBeaver - Universal Database Manager
+ * Copyright (C) 2010-2022 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.registry;
+
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtensionRegistry;
+import org.eclipse.core.runtime.Platform;
+import org.jkiss.dbeaver.Log;
+import org.jkiss.dbeaver.registry.RegistryConstants;
+
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+public class WebAuthProviderRegistry {
+
+ private static final Log log = Log.getLog(WebAuthProviderRegistry.class);
+
+ private static final String TAG_AUTH_PROVIDER = "authProvider"; //$NON-NLS-1$
+ private static final String TAG_AUTH_PROVIDER_DISABLE = "authProviderDisable"; //$NON-NLS-1$
+
+ private static WebAuthProviderRegistry instance = null;
+
+ public synchronized static WebAuthProviderRegistry getInstance() {
+ if (instance == null) {
+ instance = new WebAuthProviderRegistry();
+ instance.loadExtensions(Platform.getExtensionRegistry());
+ }
+ return instance;
+ }
+
+ private final Map authProviders = new LinkedHashMap<>();
+
+ private WebAuthProviderRegistry() {
+ }
+
+ private void loadExtensions(IExtensionRegistry registry) {
+ {
+ IConfigurationElement[] extConfigs = registry.getConfigurationElementsFor(WebAuthProviderDescriptor.EXTENSION_ID);
+ for (IConfigurationElement ext : extConfigs) {
+ // Load webServices
+ if (TAG_AUTH_PROVIDER.equals(ext.getName())) {
+ WebAuthProviderDescriptor providerDescriptor = new WebAuthProviderDescriptor(ext);
+ this.authProviders.put(providerDescriptor.getId(), providerDescriptor);
+ }
+ }
+
+ for (IConfigurationElement ext : extConfigs) {
+ // Disable auth providers
+ if (TAG_AUTH_PROVIDER_DISABLE.equals(ext.getName())) {
+ String providerId = ext.getAttribute(RegistryConstants.ATTR_ID);
+ if (!this.authProviders.containsKey(providerId)) {
+ log.warn("Can't disable auth provider '" + providerId + "' - no such provider found");
+ } else {
+ this.authProviders.remove(providerId);
+ }
+ }
+ }
+ }
+ }
+
+ public List getAuthProviders() {
+ return new ArrayList<>(authProviders.values());
+ }
+
+ public WebAuthProviderDescriptor getAuthProvider(String id) {
+ return authProviders.get(id);
+ }
+
+}
diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/registry/WebServiceRegistry.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/registry/WebServiceRegistry.java
index e8009cf16f..26cb24dab0 100644
--- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/registry/WebServiceRegistry.java
+++ b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/registry/WebServiceRegistry.java
@@ -23,7 +23,6 @@ import org.eclipse.core.runtime.IExtensionRegistry;
import org.eclipse.core.runtime.Platform;
import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.Log;
-import org.jkiss.dbeaver.registry.auth.AuthProviderDescriptor;
import java.util.*;
@@ -46,7 +45,7 @@ public class WebServiceRegistry {
private final List webServices = new ArrayList<>();
private DBWServiceBinding[] webServiceInstances;
- private final Map authProviders = new LinkedHashMap<>();
+ private final Map authProviders = new LinkedHashMap<>();
private final Map valueSerializers = new HashMap<>();
private WebServiceRegistry() {
diff --git a/server/bundles/io.cloudbeaver.server/OSGI-INF/l10n/bundle.properties b/server/bundles/io.cloudbeaver.server/OSGI-INF/l10n/bundle.properties
index 61e0f48e8c..bd1c38a678 100644
--- a/server/bundles/io.cloudbeaver.server/OSGI-INF/l10n/bundle.properties
+++ b/server/bundles/io.cloudbeaver.server/OSGI-INF/l10n/bundle.properties
@@ -1,4 +1,3 @@
Bundle-Vendor = DBeaver Corp
Bundle-Name = Cloudbeaver Web Server
-meta.io.cloudbeaver.auth.provider.fa.FederatedUserDetails.email.name = E-Mail
diff --git a/server/bundles/io.cloudbeaver.server/plugin.xml b/server/bundles/io.cloudbeaver.server/plugin.xml
index 7e5a924ae6..ec3704d572 100644
--- a/server/bundles/io.cloudbeaver.server/plugin.xml
+++ b/server/bundles/io.cloudbeaver.server/plugin.xml
@@ -3,9 +3,7 @@
-
-
diff --git a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/WebServiceUtils.java b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/WebServiceUtils.java
index 8dee743f17..6f2a43060c 100644
--- a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/WebServiceUtils.java
+++ b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/WebServiceUtils.java
@@ -24,6 +24,9 @@ import io.cloudbeaver.model.WebConnectionFolderInfo;
import io.cloudbeaver.model.WebNetworkHandlerConfigInput;
import io.cloudbeaver.model.session.WebActionParameters;
import io.cloudbeaver.model.session.WebSession;
+import io.cloudbeaver.registry.WebAuthProviderDescriptor;
+import io.cloudbeaver.registry.WebAuthProviderRegistry;
+import io.cloudbeaver.server.CBAppConfig;
import io.cloudbeaver.server.CBApplication;
import io.cloudbeaver.utils.WebAppUtils;
import io.cloudbeaver.utils.WebCommonUtils;
@@ -55,9 +58,7 @@ import org.jkiss.dbeaver.registry.network.NetworkHandlerRegistry;
import org.jkiss.utils.CommonUtils;
import java.io.InputStream;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.Map;
+import java.util.*;
/**
* Various constants
@@ -338,5 +339,17 @@ public class WebServiceUtils extends WebCommonUtils {
return project.getId().equals(RMProjectType.GLOBAL.getPrefix() + "_" + CBApplication.getInstance().getDefaultProjectName());
}
+ public static List getEnabledAuthProviders() {
+ List result = new ArrayList<>();
+ CBAppConfig appConfig = CBApplication.getInstance().getAppConfiguration();
+ String[] authProviders = appConfig.getEnabledAuthProviders();
+ for (String apId : authProviders) {
+ WebAuthProviderDescriptor authProvider = WebAuthProviderRegistry.getInstance().getAuthProvider(apId);
+ if (authProvider != null) {
+ result.add(authProvider);
+ }
+ }
+ return result;
+ }
}
diff --git a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/model/user/WebAuthProviderInfo.java b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/model/user/WebAuthProviderInfo.java
index 9d6ccfd0e3..cb94bcbe3a 100644
--- a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/model/user/WebAuthProviderInfo.java
+++ b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/model/user/WebAuthProviderInfo.java
@@ -17,12 +17,13 @@
package io.cloudbeaver.model.user;
import io.cloudbeaver.WebServiceUtils;
+import io.cloudbeaver.registry.WebAuthProviderConfiguration;
+import io.cloudbeaver.registry.WebAuthProviderDescriptor;
import io.cloudbeaver.server.CBApplication;
import io.cloudbeaver.server.CBPlatform;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.model.security.SMAuthCredentialsProfile;
import org.jkiss.dbeaver.model.security.SMAuthProviderCustomConfiguration;
-import org.jkiss.dbeaver.registry.auth.AuthProviderDescriptor;
import java.util.ArrayList;
import java.util.List;
@@ -34,13 +35,13 @@ public class WebAuthProviderInfo {
private static final Log log = Log.getLog(WebAuthProviderInfo.class);
- private final AuthProviderDescriptor descriptor;
+ private final WebAuthProviderDescriptor descriptor;
- public WebAuthProviderInfo(AuthProviderDescriptor descriptor) {
+ public WebAuthProviderInfo(WebAuthProviderDescriptor descriptor) {
this.descriptor = descriptor;
}
- AuthProviderDescriptor getDescriptor() {
+ WebAuthProviderDescriptor getDescriptor() {
return descriptor;
}
diff --git a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBAppConfig.java b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBAppConfig.java
index 7682ae1a2f..a907666c4b 100644
--- a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBAppConfig.java
+++ b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBAppConfig.java
@@ -20,12 +20,12 @@ import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import io.cloudbeaver.model.app.BaseAuthWebAppConfiguration;
import io.cloudbeaver.model.app.WebAuthConfiguration;
+import io.cloudbeaver.registry.WebAuthProviderDescriptor;
+import io.cloudbeaver.registry.WebAuthProviderRegistry;
import org.jkiss.code.NotNull;
import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.model.navigator.DBNBrowseSettings;
import org.jkiss.dbeaver.registry.DataSourceNavigatorSettings;
-import org.jkiss.dbeaver.registry.auth.AuthProviderDescriptor;
-import org.jkiss.dbeaver.registry.auth.AuthProviderRegistry;
import org.jkiss.utils.CommonUtils;
import java.util.LinkedHashMap;
@@ -171,8 +171,8 @@ public class CBAppConfig extends BaseAuthWebAppConfiguration implements WebAuthC
}
public String[] getAllAuthProviders() {
- return AuthProviderRegistry.getInstance().getAuthProviders()
- .stream().map(AuthProviderDescriptor::getId).toArray(String[]::new);
+ return WebAuthProviderRegistry.getInstance().getAuthProviders()
+ .stream().map(WebAuthProviderDescriptor::getId).toArray(String[]::new);
}
public DBNBrowseSettings getDefaultNavigatorSettings() {
diff --git a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/servlets/CBStaticServlet.java b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/servlets/CBStaticServlet.java
index ee23e45c5d..1b80c95528 100644
--- a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/servlets/CBStaticServlet.java
+++ b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/servlets/CBStaticServlet.java
@@ -2,9 +2,11 @@ package io.cloudbeaver.server.servlets;
import io.cloudbeaver.DBWConstants;
import io.cloudbeaver.DBWebException;
-import io.cloudbeaver.auth.SMWAuthProviderFederated;
+import io.cloudbeaver.auth.SMAuthProviderFederated;
import io.cloudbeaver.model.session.WebActionParameters;
import io.cloudbeaver.model.session.WebSession;
+import io.cloudbeaver.registry.WebAuthProviderDescriptor;
+import io.cloudbeaver.registry.WebAuthProviderRegistry;
import io.cloudbeaver.registry.WebHandlerRegistry;
import io.cloudbeaver.registry.WebServletHandlerDescriptor;
import io.cloudbeaver.server.CBAppConfig;
@@ -21,8 +23,6 @@ import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.model.auth.SMAuthInfo;
import org.jkiss.dbeaver.model.auth.SMAuthProvider;
import org.jkiss.dbeaver.model.security.SMAuthProviderCustomConfiguration;
-import org.jkiss.dbeaver.registry.auth.AuthProviderDescriptor;
-import org.jkiss.dbeaver.registry.auth.AuthProviderRegistry;
import org.jkiss.utils.CommonUtils;
import org.jkiss.utils.IOUtils;
@@ -86,7 +86,7 @@ public class CBStaticServlet extends DefaultServlet {
String[] authProviders = appConfig.getEnabledAuthProviders();
if (authProviders.length == 1) {
String authProviderId = authProviders[0];
- AuthProviderDescriptor authProvider = AuthProviderRegistry.getInstance().getAuthProvider(authProviderId);
+ WebAuthProviderDescriptor authProvider = WebAuthProviderRegistry.getInstance().getAuthProvider(authProviderId);
if (authProvider != null && authProvider.isConfigurable()) {
SMAuthProviderCustomConfiguration activeAuthConfig = null;
for (SMAuthProviderCustomConfiguration cfg : appConfig.getAuthCustomConfigurations()) {
@@ -105,7 +105,7 @@ public class CBStaticServlet extends DefaultServlet {
// We have the only provider
// Forward to signon URL
SMAuthProvider> authProviderInstance = authProvider.getInstance();
- if (authProviderInstance instanceof SMWAuthProviderFederated) {
+ if (authProviderInstance instanceof SMAuthProviderFederated) {
if (webSession.getUser() == null) {
var securityController = webSession.getSecurityController();
SMAuthInfo authInfo = securityController.authenticate(
diff --git a/server/bundles/io.cloudbeaver.service.admin/src/io/cloudbeaver/service/admin/AdminUserInfo.java b/server/bundles/io.cloudbeaver.service.admin/src/io/cloudbeaver/service/admin/AdminUserInfo.java
index ab8dae7a28..15d68683fc 100644
--- a/server/bundles/io.cloudbeaver.service.admin/src/io/cloudbeaver/service/admin/AdminUserInfo.java
+++ b/server/bundles/io.cloudbeaver.service.admin/src/io/cloudbeaver/service/admin/AdminUserInfo.java
@@ -20,13 +20,13 @@ import io.cloudbeaver.DBWebException;
import io.cloudbeaver.model.session.WebSession;
import io.cloudbeaver.model.user.WebUser;
import io.cloudbeaver.model.user.WebUserOriginInfo;
+import io.cloudbeaver.registry.WebAuthProviderDescriptor;
+import io.cloudbeaver.registry.WebAuthProviderRegistry;
import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.model.meta.Property;
import org.jkiss.dbeaver.model.security.SMDataSourceGrant;
import org.jkiss.dbeaver.model.security.SMObjects;
-import org.jkiss.dbeaver.registry.auth.AuthProviderDescriptor;
-import org.jkiss.dbeaver.registry.auth.AuthProviderRegistry;
import java.util.ArrayList;
import java.util.List;
@@ -96,7 +96,7 @@ public class AdminUserInfo {
public WebUserOriginInfo[] getOrigins() throws DBWebException {
List result = new ArrayList<>();
for (String provider : getUserLinkedProviders()) {
- AuthProviderDescriptor authProvider = AuthProviderRegistry.getInstance().getAuthProvider(provider);
+ WebAuthProviderDescriptor authProvider = WebAuthProviderRegistry.getInstance().getAuthProvider(provider);
if (authProvider == null) {
log.error("Auth provider '" + provider + "' not found");
} else {
diff --git a/server/bundles/io.cloudbeaver.service.admin/src/io/cloudbeaver/service/admin/DBWServiceAdmin.java b/server/bundles/io.cloudbeaver.service.admin/src/io/cloudbeaver/service/admin/DBWServiceAdmin.java
index 249090e947..0e9f3e548c 100644
--- a/server/bundles/io.cloudbeaver.service.admin/src/io/cloudbeaver/service/admin/DBWServiceAdmin.java
+++ b/server/bundles/io.cloudbeaver.service.admin/src/io/cloudbeaver/service/admin/DBWServiceAdmin.java
@@ -24,7 +24,7 @@ import io.cloudbeaver.model.WebConnectionConfig;
import io.cloudbeaver.model.WebConnectionInfo;
import io.cloudbeaver.model.WebPropertyInfo;
import io.cloudbeaver.model.session.WebSession;
-import io.cloudbeaver.model.user.WebAuthProviderConfiguration;
+import io.cloudbeaver.registry.WebAuthProviderConfiguration;
import io.cloudbeaver.service.DBWService;
import org.jkiss.code.NotNull;
import org.jkiss.code.Nullable;
@@ -189,8 +189,7 @@ public interface DBWServiceAdmin extends DBWService {
Boolean deleteUserMetaParameter(WebSession webSession, String id) throws DBWebException;
@WebAction(requirePermissions = DBWConstants.PERMISSION_ADMIN)
- Boolean setUserMetaParameterValues(WebSession webSession, String userId, Map parameters) throws DBWebException;
-
+ Boolean setUserMetaParameterValues(WebSession webSession, String userId, Map parameters) throws DBWebException;
@WebAction(requirePermissions = DBWConstants.PERMISSION_ADMIN)
Boolean enableUser(WebSession webSession, String userId, Boolean enabled) throws DBWebException;
diff --git a/server/bundles/io.cloudbeaver.service.admin/src/io/cloudbeaver/service/admin/impl/WebServiceAdmin.java b/server/bundles/io.cloudbeaver.service.admin/src/io/cloudbeaver/service/admin/impl/WebServiceAdmin.java
index 0071eacfa3..493af768e4 100644
--- a/server/bundles/io.cloudbeaver.service.admin/src/io/cloudbeaver/service/admin/impl/WebServiceAdmin.java
+++ b/server/bundles/io.cloudbeaver.service.admin/src/io/cloudbeaver/service/admin/impl/WebServiceAdmin.java
@@ -25,11 +25,8 @@ import io.cloudbeaver.model.WebConnectionInfo;
import io.cloudbeaver.model.WebPropertyInfo;
import io.cloudbeaver.model.session.WebAuthInfo;
import io.cloudbeaver.model.session.WebSession;
-import io.cloudbeaver.model.user.WebAuthProviderConfiguration;
import io.cloudbeaver.model.user.WebUser;
-import io.cloudbeaver.registry.WebFeatureRegistry;
-import io.cloudbeaver.registry.WebPermissionDescriptor;
-import io.cloudbeaver.registry.WebServiceRegistry;
+import io.cloudbeaver.registry.*;
import io.cloudbeaver.server.CBAppConfig;
import io.cloudbeaver.server.CBApplication;
import io.cloudbeaver.server.CBConstants;
@@ -56,8 +53,6 @@ import org.jkiss.dbeaver.model.security.SMObjects;
import org.jkiss.dbeaver.model.security.user.SMTeam;
import org.jkiss.dbeaver.model.security.user.SMUser;
import org.jkiss.dbeaver.registry.DataSourceDescriptor;
-import org.jkiss.dbeaver.registry.auth.AuthProviderDescriptor;
-import org.jkiss.dbeaver.registry.auth.AuthProviderRegistry;
import org.jkiss.utils.CommonUtils;
import java.text.MessageFormat;
@@ -293,7 +288,7 @@ public class WebServiceAdmin implements DBWServiceAdmin {
@Override
public boolean setUserCredentials(@NotNull WebSession webSession, @NotNull String userID, @NotNull String providerId, @NotNull Map credentials) throws DBWebException {
- AuthProviderDescriptor authProvider = AuthProviderRegistry.getInstance().getAuthProvider(providerId);
+ WebAuthProviderDescriptor authProvider = WebAuthProviderRegistry.getInstance().getAuthProvider(providerId);
if (authProvider == null) {
throw new DBWebException("Invalid auth provider '" + providerId + "'");
}
@@ -492,11 +487,16 @@ public class WebServiceAdmin implements DBWServiceAdmin {
@Override
public List listAuthProviderConfigurationParameters(@NotNull WebSession webSession, @NotNull String providerId) throws DBWebException {
- AuthProviderDescriptor authProvider = AuthProviderRegistry.getInstance().getAuthProvider(providerId);
+ WebAuthProviderDescriptor authProvider = WebAuthProviderRegistry.getInstance().getAuthProvider(providerId);
if (authProvider == null) {
throw new DBWebException("Invalid provider ID " + providerId);
}
- return authProvider.getConfigurationParameters().stream().map(p -> new WebPropertyInfo(webSession, p)).collect(Collectors.toList());
+ return authProvider.getConfigurationParameters().stream().filter(p -> {
+ if (p.hasFeature("distributed")) {
+ return CBApplication.getInstance().isDistributed();
+ }
+ return true;
+ }).map(p -> new WebPropertyInfo(webSession, p)).collect(Collectors.toList());
}
@Override
@@ -506,7 +506,7 @@ public class WebServiceAdmin implements DBWServiceAdmin {
if (providerId != null && !providerId.equals(cfg.getProvider())) {
continue;
}
- AuthProviderDescriptor authProvider = AuthProviderRegistry.getInstance().getAuthProvider(cfg.getProvider());
+ WebAuthProviderDescriptor authProvider = WebAuthProviderRegistry.getInstance().getAuthProvider(cfg.getProvider());
if (authProvider != null) {
result.add(new WebAuthProviderConfiguration(authProvider, cfg));
}
@@ -524,7 +524,7 @@ public class WebServiceAdmin implements DBWServiceAdmin {
@Nullable String iconURL,
@Nullable String description,
@Nullable Map parameters) throws DBWebException {
- AuthProviderDescriptor authProvider = AuthProviderRegistry.getInstance().getAuthProvider(providerId);
+ WebAuthProviderDescriptor authProvider = WebAuthProviderRegistry.getInstance().getAuthProvider(providerId);
if (authProvider == null) {
throw new DBWebException("Auth provider '" + providerId + "' not found");
}
@@ -779,9 +779,9 @@ public class WebServiceAdmin implements DBWServiceAdmin {
}
@Override
- public Boolean setUserMetaParameterValues(WebSession webSession, String userId, Map parameters) throws DBWebException {
+ public Boolean setUserMetaParameterValues(WebSession webSession, String userId, Map parameters) throws DBWebException {
try {
- webSession.getAdminSecurityController().setUserMeta(userId, parameters);
+ webSession.getAdminSecurityController().setSubjectMetas(userId, parameters);
return true;
} catch (DBException e) {
throw new DBWebException("Error changing user '" + userId + "' meta parameters", e);
diff --git a/server/bundles/io.cloudbeaver.service.auth/src/io/cloudbeaver/service/auth/RPSessionHandler.java b/server/bundles/io.cloudbeaver.service.auth/src/io/cloudbeaver/service/auth/RPSessionHandler.java
index 93b1ada087..0bcec0ee52 100644
--- a/server/bundles/io.cloudbeaver.service.auth/src/io/cloudbeaver/service/auth/RPSessionHandler.java
+++ b/server/bundles/io.cloudbeaver.service.auth/src/io/cloudbeaver/service/auth/RPSessionHandler.java
@@ -22,6 +22,8 @@ import io.cloudbeaver.auth.provider.rp.RPAuthProvider;
import io.cloudbeaver.model.app.WebAuthConfiguration;
import io.cloudbeaver.model.session.WebSession;
import io.cloudbeaver.model.session.WebSessionAuthProcessor;
+import io.cloudbeaver.registry.WebAuthProviderDescriptor;
+import io.cloudbeaver.registry.WebAuthProviderRegistry;
import io.cloudbeaver.server.CBApplication;
import io.cloudbeaver.service.DBWSessionHandler;
import io.cloudbeaver.utils.WebAppUtils;
@@ -32,8 +34,6 @@ import org.jkiss.dbeaver.model.auth.SMAuthInfo;
import org.jkiss.dbeaver.model.security.SMConstants;
import org.jkiss.dbeaver.model.security.SMController;
import org.jkiss.dbeaver.model.security.exception.SMException;
-import org.jkiss.dbeaver.registry.auth.AuthProviderDescriptor;
-import org.jkiss.dbeaver.registry.auth.AuthProviderRegistry;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@@ -61,7 +61,7 @@ public class RPSessionHandler implements DBWSessionHandler {
public void reverseProxyAuthentication(@NotNull HttpServletRequest request, @NotNull WebSession webSession) throws DBWebException {
SMController securityController = webSession.getSecurityController();
- AuthProviderDescriptor authProvider = AuthProviderRegistry.getInstance().getAuthProvider(RPAuthProvider.AUTH_PROVIDER);
+ WebAuthProviderDescriptor authProvider = WebAuthProviderRegistry.getInstance().getAuthProvider(RPAuthProvider.AUTH_PROVIDER);
if (authProvider == null) {
throw new DBWebException("Auth provider " + RPAuthProvider.AUTH_PROVIDER + " not found");
}
diff --git a/server/bundles/io.cloudbeaver.service.auth/src/io/cloudbeaver/service/auth/impl/WebServiceAuthImpl.java b/server/bundles/io.cloudbeaver.service.auth/src/io/cloudbeaver/service/auth/impl/WebServiceAuthImpl.java
index e937043663..c764e472a5 100644
--- a/server/bundles/io.cloudbeaver.service.auth/src/io/cloudbeaver/service/auth/impl/WebServiceAuthImpl.java
+++ b/server/bundles/io.cloudbeaver.service.auth/src/io/cloudbeaver/service/auth/impl/WebServiceAuthImpl.java
@@ -17,6 +17,7 @@
package io.cloudbeaver.service.auth.impl;
import io.cloudbeaver.DBWebException;
+import io.cloudbeaver.WebServiceUtils;
import io.cloudbeaver.auth.provider.local.LocalAuthProvider;
import io.cloudbeaver.model.WebPropertyInfo;
import io.cloudbeaver.model.session.WebAuthInfo;
@@ -24,6 +25,8 @@ import io.cloudbeaver.model.session.WebSession;
import io.cloudbeaver.model.session.WebSessionAuthProcessor;
import io.cloudbeaver.model.user.WebAuthProviderInfo;
import io.cloudbeaver.model.user.WebUser;
+import io.cloudbeaver.registry.WebAuthProviderDescriptor;
+import io.cloudbeaver.registry.WebAuthProviderRegistry;
import io.cloudbeaver.registry.WebUserProfileRegistry;
import io.cloudbeaver.server.CBApplication;
import io.cloudbeaver.service.auth.DBWServiceAuth;
@@ -35,11 +38,13 @@ import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.model.auth.SMAuthInfo;
import org.jkiss.dbeaver.model.auth.SMAuthStatus;
+import org.jkiss.dbeaver.model.preferences.DBPPropertyDescriptor;
import org.jkiss.dbeaver.model.security.SMController;
+import org.jkiss.dbeaver.model.security.SMSubjectType;
import org.jkiss.dbeaver.model.security.user.SMUser;
-import org.jkiss.dbeaver.registry.auth.AuthProviderRegistry;
import org.jkiss.utils.CommonUtils;
+import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@@ -158,7 +163,7 @@ public class WebServiceAuthImpl implements DBWServiceAuth {
@Override
public WebAuthProviderInfo[] getAuthProviders() {
- return AuthProviderRegistry.getInstance().getAuthProviders()
+ return WebAuthProviderRegistry.getInstance().getAuthProviders()
.stream().map(WebAuthProviderInfo::new)
.toArray(WebAuthProviderInfo[]::new);
}
@@ -177,7 +182,20 @@ public class WebServiceAuthImpl implements DBWServiceAuth {
@Override
public WebPropertyInfo[] listUserProfileProperties(@NotNull WebSession webSession) {
- return WebUserProfileRegistry.getInstance().getProperties().stream()
+ List props = new ArrayList<>();
+
+ // First add user profile properties
+ props.addAll(WebUserProfileRegistry.getInstance().getProperties());
+
+ // Add metas from enabled auth providers
+ for (WebAuthProviderDescriptor ap : WebServiceUtils.getEnabledAuthProviders()) {
+ List metaProps = ap.getMetaProperties(SMSubjectType.user);
+ if (!CommonUtils.isEmpty(metaProps)) {
+ props.addAll(metaProps);
+ }
+ }
+
+ return props.stream()
.map(p -> new WebPropertyInfo(webSession, p, null))
.toArray(WebPropertyInfo[]::new);
}
diff --git a/server/bundles/io.cloudbeaver.service.security/db/cb_schema_create.sql b/server/bundles/io.cloudbeaver.service.security/db/cb_schema_create.sql
index e5fb68c092..58e841360b 100644
--- a/server/bundles/io.cloudbeaver.service.security/db/cb_schema_create.sql
+++ b/server/bundles/io.cloudbeaver.service.security/db/cb_schema_create.sql
@@ -66,6 +66,18 @@ CREATE TABLE CB_AUTH_SUBJECT
PRIMARY KEY (SUBJECT_ID)
);
+CREATE TABLE CB_SUBJECT_META
+(
+ SUBJECT_ID VARCHAR(128) NOT NULL,
+ META_ID VARCHAR(32) NOT NULL,
+ META_VALUE VARCHAR(1024),
+
+ UPDATE_TIME TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
+
+ PRIMARY KEY (SUBJECT_ID, META_ID),
+ FOREIGN KEY (SUBJECT_ID) REFERENCES CB_AUTH_SUBJECT(SUBJECT_ID) ON DELETE CASCADE
+);
+
CREATE TABLE CB_AUTH_PERMISSIONS
(
SUBJECT_ID VARCHAR(128) NOT NULL,
@@ -106,15 +118,6 @@ CREATE TABLE CB_USER
);
-- Additional user properties (profile)
-CREATE TABLE CB_USER_META
-(
- USER_ID VARCHAR(128) NOT NULL,
- META_ID VARCHAR(32) NOT NULL,
- META_VALUE VARCHAR(1024),
-
- PRIMARY KEY (USER_ID, META_ID),
- FOREIGN KEY (USER_ID) REFERENCES CB_USER (USER_ID) ON DELETE CASCADE
-);
CREATE TABLE CB_USER_PARAMETERS
(
@@ -299,9 +302,9 @@ CREATE INDEX CB_SESSION_LOG_INDEX ON CB_SESSION_LOG (SESSION_ID, LOG_TIME);
CREATE TABLE CB_USER_SECRETS
(
- USER_ID VARCHAR(128) NOT NULL,
- SECRET_ID VARCHAR(512) NOT NULL,
- SECRET_VALUE TEXT NOT NULL,
+ USER_ID VARCHAR(128) NOT NULL,
+ SECRET_ID VARCHAR(512) NOT NULL,
+ SECRET_VALUE TEXT NOT NULL,
SECRET_LABEL VARCHAR(128),
SECRET_DESCRIPTION VARCHAR(1024),
diff --git a/server/bundles/io.cloudbeaver.service.security/db/cb_schema_update_12.sql b/server/bundles/io.cloudbeaver.service.security/db/cb_schema_update_12.sql
new file mode 100644
index 0000000000..b0b70fc32b
--- /dev/null
+++ b/server/bundles/io.cloudbeaver.service.security/db/cb_schema_update_12.sql
@@ -0,0 +1,16 @@
+CREATE TABLE CB_SUBJECT_META
+(
+ SUBJECT_ID VARCHAR(128) NOT NULL,
+ META_ID VARCHAR(32) NOT NULL,
+ META_VALUE VARCHAR(1024),
+
+ UPDATE_TIME TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
+
+ PRIMARY KEY (SUBJECT_ID, META_ID),
+ FOREIGN KEY (SUBJECT_ID) REFERENCES CB_AUTH_SUBJECT(SUBJECT_ID) ON DELETE CASCADE
+);
+
+INSERT INTO CB_SUBJECT_META (SUBJECT_ID, META_ID, META_VALUE)
+SELECT USER_ID, META_ID, META_VALUE FROM CB_USER_META;
+
+DROP TABLE CB_USER_META;
diff --git a/server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/auth/provider/local/LocalAuthProvider.java b/server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/auth/provider/local/LocalAuthProvider.java
index 4896f14621..40a6b19080 100644
--- a/server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/auth/provider/local/LocalAuthProvider.java
+++ b/server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/auth/provider/local/LocalAuthProvider.java
@@ -17,6 +17,8 @@
package io.cloudbeaver.auth.provider.local;
import io.cloudbeaver.model.session.WebSession;
+import io.cloudbeaver.registry.WebAuthProviderDescriptor;
+import io.cloudbeaver.registry.WebAuthProviderRegistry;
import org.jkiss.code.NotNull;
import org.jkiss.code.Nullable;
import org.jkiss.dbeaver.DBException;
@@ -25,8 +27,6 @@ import org.jkiss.dbeaver.model.auth.SMAuthProvider;
import org.jkiss.dbeaver.model.auth.SMSession;
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
import org.jkiss.dbeaver.model.security.SMController;
-import org.jkiss.dbeaver.registry.auth.AuthProviderDescriptor;
-import org.jkiss.dbeaver.registry.auth.AuthProviderRegistry;
import org.jkiss.utils.CommonUtils;
import java.util.Map;
@@ -51,7 +51,7 @@ public class LocalAuthProvider implements SMAuthProvider {
String userName = CommonUtils.toString(userCredentials.get(CRED_USER), null);
- AuthProviderDescriptor authProvider = AuthProviderRegistry.getInstance().getAuthProvider(PROVIDER_ID);
+ WebAuthProviderDescriptor authProvider = WebAuthProviderRegistry.getInstance().getAuthProvider(PROVIDER_ID);
Map storedCredentials = securityController.getUserCredentials(userName, authProvider.getId());
if (storedCredentials == null) {
throw new DBException("Invalid user name or password");
@@ -95,7 +95,7 @@ public class LocalAuthProvider implements SMAuthProvider {
public static boolean changeUserPassword(@NotNull WebSession webSession, @NotNull String oldPassword, @NotNull String newPassword) throws DBException {
String userName = webSession.getUser().getUserId();
- AuthProviderDescriptor authProvider = AuthProviderRegistry.getInstance().getAuthProvider(PROVIDER_ID);
+ WebAuthProviderDescriptor authProvider = WebAuthProviderRegistry.getInstance().getAuthProvider(PROVIDER_ID);
Map storedCredentials = webSession.getSecurityController().getUserCredentials(userName, authProvider.getId());
if (storedCredentials == null) {
throw new DBException("Invalid user name or password");
diff --git a/server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/auth/provider/rp/RPAuthProvider.java b/server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/auth/provider/rp/RPAuthProvider.java
index b652caa400..bfadbd672f 100644
--- a/server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/auth/provider/rp/RPAuthProvider.java
+++ b/server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/auth/provider/rp/RPAuthProvider.java
@@ -65,8 +65,8 @@ public class RPAuthProvider implements SMAuthProviderExternal {
@NotNull
@Override
- public DBWUserIdentity getUserIdentity(@NotNull DBRProgressMonitor monitor, @NotNull Map providerConfig, @NotNull Map credentials) throws DBException {
- String userName = String.valueOf(credentials.get("user"));
+ public DBWUserIdentity getUserIdentity(@NotNull DBRProgressMonitor monitor, @NotNull Map providerConfig, @NotNull Map authParameters) throws DBException {
+ String userName = String.valueOf(authParameters.get("user"));
return new DBWUserIdentity(userName, userName);
}
diff --git a/server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/service/security/CBEmbeddedSecurityController.java b/server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/service/security/CBEmbeddedSecurityController.java
index ca075801bd..9ad8f041b8 100644
--- a/server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/service/security/CBEmbeddedSecurityController.java
+++ b/server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/service/security/CBEmbeddedSecurityController.java
@@ -20,12 +20,16 @@ import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import io.cloudbeaver.DBWConstants;
+import io.cloudbeaver.auth.SMAuthProviderAssigner;
import io.cloudbeaver.auth.SMAuthProviderExternal;
-import io.cloudbeaver.auth.SMWAuthProviderFederated;
+import io.cloudbeaver.auth.SMAuthProviderFederated;
+import io.cloudbeaver.auth.SMAutoAssign;
import io.cloudbeaver.model.app.WebApplication;
import io.cloudbeaver.model.app.WebAuthApplication;
import io.cloudbeaver.model.app.WebAuthConfiguration;
import io.cloudbeaver.model.session.WebAuthInfo;
+import io.cloudbeaver.registry.WebAuthProviderDescriptor;
+import io.cloudbeaver.registry.WebAuthProviderRegistry;
import io.cloudbeaver.service.security.db.CBDatabase;
import io.cloudbeaver.service.security.internal.AuthAttemptSessionInfo;
import io.cloudbeaver.service.security.internal.SMTokenInfo;
@@ -40,17 +44,11 @@ import org.jkiss.dbeaver.model.impl.jdbc.JDBCUtils;
import org.jkiss.dbeaver.model.impl.jdbc.exec.JDBCTransaction;
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
import org.jkiss.dbeaver.model.runtime.LoggingProgressMonitor;
-import org.jkiss.dbeaver.model.runtime.VoidProgressMonitor;
import org.jkiss.dbeaver.model.security.*;
import org.jkiss.dbeaver.model.security.exception.SMAccessTokenExpiredException;
import org.jkiss.dbeaver.model.security.exception.SMException;
import org.jkiss.dbeaver.model.security.exception.SMRefreshTokenExpiredException;
-import org.jkiss.dbeaver.model.security.user.SMAuthPermissions;
-import org.jkiss.dbeaver.model.security.user.SMObjectPermissions;
-import org.jkiss.dbeaver.model.security.user.SMTeam;
-import org.jkiss.dbeaver.model.security.user.SMUser;
-import org.jkiss.dbeaver.registry.auth.AuthProviderDescriptor;
-import org.jkiss.dbeaver.registry.auth.AuthProviderRegistry;
+import org.jkiss.dbeaver.model.security.user.*;
import org.jkiss.dbeaver.runtime.DBWorkbench;
import org.jkiss.utils.ArrayUtils;
import org.jkiss.utils.CommonUtils;
@@ -139,16 +137,7 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
}
dbStat.execute();
}
- if (!CommonUtils.isEmpty(metaParameters)) {
- try (PreparedStatement dbStat = dbCon.prepareStatement("INSERT INTO CB_USER_META(USER_ID,META_ID,META_VALUE) VALUES(?,?,?)")) {
- dbStat.setString(1, userId);
- for (Map.Entry mp : metaParameters.entrySet()) {
- dbStat.setString(2, mp.getKey());
- dbStat.setString(3, mp.getValue());
- dbStat.execute();
- }
- }
- }
+ saveSubjectMetas(dbCon, userId, metaParameters);
txn.commit();
}
} catch (SQLException e) {
@@ -158,6 +147,7 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
@Override
public void deleteUser(String userId) throws DBCException {
+ invalidateAllUserTokens(userId);
try (Connection dbCon = database.openConnection()) {
try (JDBCTransaction txn = new JDBCTransaction(dbCon)) {
deleteAuthSubject(dbCon, userId);
@@ -232,18 +222,7 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
}
}
}
- // Metas
- try (PreparedStatement dbStat = dbCon.prepareStatement("SELECT META_ID,META_VALUE FROM CB_USER_META WHERE USER_ID=?")) {
- dbStat.setString(1, userId);
- try (ResultSet dbResult = dbStat.executeQuery()) {
- while (dbResult.next()) {
- user.setMetaParameter(
- dbResult.getString(1),
- dbResult.getString(2)
- );
- }
- }
- }
+ readSubjectMetas(dbCon, user);
// Teams
try (PreparedStatement dbStat = dbCon.prepareStatement("SELECT TEAM_ID FROM CB_USER_TEAM WHERE USER_ID=?")) {
dbStat.setString(1, userId);
@@ -282,25 +261,7 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
}
}
}
- // Read metas
- try (PreparedStatement dbStat = dbCon.prepareStatement("SELECT USER_ID,META_ID,META_VALUE FROM CB_USER_META" +
- (CommonUtils.isEmpty(userNameMask) ? "" : " WHERE USER_ID=?"))) {
- if (!CommonUtils.isEmpty(userNameMask)) {
- dbStat.setString(1, userNameMask);
- }
- try (ResultSet dbResult = dbStat.executeQuery()) {
- while (dbResult.next()) {
- String userId = dbResult.getString(1);
- SMUser user = result.get(userId);
- if (user != null) {
- user.setMetaParameter(
- dbResult.getString(2),
- dbResult.getString(3)
- );
- }
- }
- }
- }
+ readSubjectsMetas(dbCon, SMSubjectType.user, userNameMask, result);
// Read teams
try (PreparedStatement dbStat = dbCon.prepareStatement("SELECT USER_ID,TEAM_ID FROM CB_USER_TEAM" +
(CommonUtils.isEmpty(userNameMask) ? "" : " WHERE USER_ID=?"))) {
@@ -325,30 +286,67 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
}
}
- @Override
- public void setUserMeta(String userId, Map metaParameters) throws DBCException {
- try (Connection dbCon = database.openConnection()) {
- try (JDBCTransaction txn = new JDBCTransaction(dbCon)) {
- // Delete old metas
- try (PreparedStatement dbStat = dbCon.prepareStatement("DELETE FROM CB_USER_META WHERE USER_ID=?")) {
- dbStat.setString(1, userId);
- dbStat.execute();
+ private void cleanupSubjectMeta(Connection dbCon, String subjectId) throws SQLException {
+ // Delete old metas
+ try (PreparedStatement dbStat = dbCon.prepareStatement(
+ "DELETE FROM CB_SUBJECT_META WHERE SUBJECT_ID=?")) {
+ dbStat.setString(1, subjectId);
+ dbStat.execute();
+ }
+ }
+
+ private void readSubjectMetas(Connection dbCon, SMSubject subject) throws SQLException {
+ // Metas
+ try (PreparedStatement dbStat = dbCon.prepareStatement(
+ "SELECT META_ID,META_VALUE FROM CB_SUBJECT_META WHERE SUBJECT_ID=?")) {
+ dbStat.setString(1, subject.getSubjectId());
+ try (ResultSet dbResult = dbStat.executeQuery()) {
+ while (dbResult.next()) {
+ subject.setMetaParameter(
+ dbResult.getString(1),
+ dbResult.getString(2)
+ );
}
- if (!metaParameters.isEmpty()) {
- // Insert new metas
- try (PreparedStatement dbStat = dbCon.prepareStatement("INSERT INTO CB_USER_META(USER_ID,META_ID,META_VALUE) VALUES(?,?,?)")) {
- dbStat.setString(1, userId);
- for (Map.Entry mpe : metaParameters.entrySet()) {
- dbStat.setString(2, mpe.getKey());
- dbStat.setString(3, CommonUtils.toString(mpe.getValue()));
- dbStat.execute();
- }
+ }
+ }
+ }
+
+ private void readSubjectsMetas(Connection dbCon, SMSubjectType subjectType, String nameMask, Map result) throws SQLException {
+ // Read metas
+ try (PreparedStatement dbStat = dbCon.prepareStatement(
+ "SELECT m.SUBJECT_ID,m.META_ID,m.META_VALUE FROM CB_AUTH_SUBJECT s, CB_SUBJECT_META m\n" +
+ "WHERE s.SUBJECT_TYPE=? AND s.SUBJECT_ID=m.SUBJECT_ID" +
+ (CommonUtils.isEmpty(nameMask) ? "" : " AND s.SUBJECT_ID=?"))) {
+ dbStat.setString(1, subjectType.getCode());
+ if (!CommonUtils.isEmpty(nameMask)) {
+ dbStat.setString(2, nameMask);
+ }
+ try (ResultSet dbResult = dbStat.executeQuery()) {
+ while (dbResult.next()) {
+ String subjectId = dbResult.getString(1);
+ SMSubject subject = result.get(subjectId);
+ if (subject != null) {
+ subject.setMetaParameter(
+ dbResult.getString(2),
+ dbResult.getString(3)
+ );
}
}
- txn.commit();
}
- } catch (SQLException e) {
- throw new DBCException("Error while loading users", e);
+ }
+ }
+
+ private void saveSubjectMetas(Connection dbCon, String subjectId, Map metaParameters) throws SQLException {
+ if (!CommonUtils.isEmpty(metaParameters)) {
+ try (PreparedStatement dbStat = dbCon.prepareStatement(
+ "INSERT INTO CB_SUBJECT_META(SUBJECT_ID,META_ID,META_VALUE) VALUES(?,?,?)")) {
+ dbStat.setString(1, subjectId);
+ for (Map.Entry mp : metaParameters.entrySet()) {
+ dbStat.setString(2, mp.getKey());
+ dbStat.setString(3, mp.getValue());
+ dbStat.execute();
+ }
+ }
}
}
@@ -439,7 +437,7 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
///////////////////////////////////////////
// Credentials
- private static SMAuthCredentialsProfile getCredentialProfileByParameters(AuthProviderDescriptor authProvider, Set keySet) {
+ private static SMAuthCredentialsProfile getCredentialProfileByParameters(WebAuthProviderDescriptor authProvider, Set keySet) {
List credentialProfiles = authProvider.getCredentialProfiles();
if (credentialProfiles.size() > 1) {
for (SMAuthCredentialsProfile profile : credentialProfiles) {
@@ -462,12 +460,12 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
@Override
public void setUserCredentials(@NotNull String userId, @NotNull String authProviderId, @NotNull Map credentials) throws DBException {
- var existUserByCredentials = findUserByCredentials(authProviderId, credentials);
+ var existUserByCredentials = findUserByCredentials(getAuthProvider(authProviderId), credentials);
if (existUserByCredentials != null && !existUserByCredentials.equals(userId)) {
throw new DBException("Another user is already linked to the specified credentials");
}
List transformedCredentials;
- AuthProviderDescriptor authProvider = getAuthProvider(authProviderId);
+ WebAuthProviderDescriptor authProvider = getAuthProvider(authProviderId);
try {
SMAuthCredentialsProfile credProfile = getCredentialProfileByParameters(authProvider, credentials.keySet());
transformedCredentials = credentials.entrySet().stream().map(cred -> {
@@ -508,10 +506,10 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
}
@Nullable
- private String findUserByCredentials(String authProviderId, Map authParameters) throws DBCException {
- AuthProviderDescriptor authProvider = getAuthProvider(authProviderId);
+ private String findUserByCredentials(WebAuthProviderDescriptor authProvider, Map authParameters) throws DBCException {
Map identCredentials = new LinkedHashMap<>();
- for (AuthPropertyDescriptor prop : authProvider.getCredentialParameters(authParameters.keySet())) {
+ String[] propNames = authParameters.keySet().toArray(new String[0]);
+ for (AuthPropertyDescriptor prop : authProvider.getCredentialParameters(propNames)) {
if (prop.isIdentifying()) {
String propId = CommonUtils.toString(prop.getId());
Object paramValue = authParameters.get(propId);
@@ -577,7 +575,7 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
@Override
public Map getUserCredentials(String userId, String authProviderId) throws DBCException {
- AuthProviderDescriptor authProvider = getAuthProvider(authProviderId);
+ WebAuthProviderDescriptor authProvider = getAuthProvider(authProviderId);
try (Connection dbCon = database.openConnection()) {
try (PreparedStatement dbStat = dbCon.prepareStatement(
"SELECT CRED_ID,CRED_VALUE FROM CB_USER_CREDENTIALS\n" +
@@ -650,6 +648,7 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
}
}
}
+ readSubjectsMetas(dbCon, SMSubjectType.team,null, teams);
return teams.values().toArray(new SMTeam[0]);
} catch (SQLException e) {
throw new DBCException("Error reading teams from database", e);
@@ -773,7 +772,22 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
}
///////////////////////////////////////////
- // Permissions
+ // Subject functions
+
+ @Override
+ public void setSubjectMetas(String userId, Map metaParameters) throws DBCException {
+ try (Connection dbCon = database.openConnection()) {
+ try (JDBCTransaction txn = new JDBCTransaction(dbCon)) {
+ cleanupSubjectMeta(dbCon, userId);
+ if (!metaParameters.isEmpty()) {
+ saveSubjectMetas(dbCon, userId, metaParameters);
+ }
+ txn.commit();
+ }
+ } catch (SQLException e) {
+ throw new DBCException("Error while loading users", e);
+ }
+ }
@Override
public void setSubjectPermissions(String subjectId, List permissionIds, String grantorId) throws DBException {
@@ -920,7 +934,8 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
smTokens.getSmAccessToken(),
smTokens.getSmRefreshToken(),
new SMAuthPermissions(null, smSessionId, permissions),
- Map.of()
+ Map.of(),
+ smConfig.getDefaultAuthRole()
);
}
} catch (SQLException e) {
@@ -943,11 +958,11 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
@Nullable String authProviderConfigurationId,
@NotNull Map userCredentials
) throws DBException {
- var authProgressMonitor = new VoidProgressMonitor();
+ var authProgressMonitor = new LoggingProgressMonitor(log);
try (Connection dbCon = database.openConnection()) {
try (JDBCTransaction txn = new JDBCTransaction(dbCon)) {
Map securedUserIdentifyingCredentials = userCredentials;
- AuthProviderDescriptor authProviderDescriptor = getAuthProvider(authProviderId);
+ WebAuthProviderDescriptor authProviderDescriptor = getAuthProvider(authProviderId);
var authProviderInstance = authProviderDescriptor.getInstance();
if (SMAuthProviderExternal.class.isAssignableFrom(authProviderInstance.getClass())) {
var authProviderExternal = (SMAuthProviderExternal>) authProviderInstance;
@@ -970,9 +985,9 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
sessionParameters
);
- if (SMWAuthProviderFederated.class.isAssignableFrom(authProviderInstance.getClass())) {
+ if (SMAuthProviderFederated.class.isAssignableFrom(authProviderInstance.getClass())) {
//async auth
- var authProviderFederated = (SMWAuthProviderFederated) authProviderInstance;
+ var authProviderFederated = (SMAuthProviderFederated) authProviderInstance;
var redirectUrl = buildRedirectLink(
authProviderFederated.getSignInLink(authProviderConfigurationId, Map.of()),
authAttemptId);
@@ -980,7 +995,11 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
}
txn.commit();
return finishAuthentication(
- SMAuthInfo.inProgress(authAttemptId, null, Map.of(authProviderId, securedUserIdentifyingCredentials)),
+ SMAuthInfo.inProgress(
+ authAttemptId,
+ null,
+ Map.of(authProviderId, securedUserIdentifyingCredentials)
+ ),
true,
false
);
@@ -992,7 +1011,7 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
private Map filterSecuredUserData(
Map userIdentifyingCredentials,
- AuthProviderDescriptor authProviderDescriptor
+ WebAuthProviderDescriptor authProviderDescriptor
) {
SMAuthCredentialsProfile credProfile = getCredentialProfileByParameters(authProviderDescriptor, userIdentifyingCredentials.keySet());
return userIdentifyingCredentials.entrySet()
@@ -1133,8 +1152,10 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
}
Map authData = new LinkedHashMap<>();
String redirectUrl = null;
+
try (PreparedStatement dbStat = dbCon.prepareStatement(
- "SELECT AUTH_PROVIDER_ID,AUTH_PROVIDER_CONFIGURATION_ID,AUTH_STATE FROM CB_AUTH_ATTEMPT_INFO "
+ "SELECT AUTH_PROVIDER_ID,AUTH_PROVIDER_CONFIGURATION_ID,AUTH_STATE " +
+ "FROM CB_AUTH_ATTEMPT_INFO "
+ "WHERE AUTH_ID=? ORDER BY CREATE_TIME"
)) {
dbStat.setString(1, authId);
@@ -1144,13 +1165,15 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
String authProviderConfiguration = dbResult.getString(2);
Map authProviderData = gson.fromJson(dbResult.getString(3), MAP_STRING_OBJECT_TYPE);
if (authProviderConfiguration != null) {
- var authProviderInstance = getAuthProvider(authProviderId).getInstance();
- if (SMWAuthProviderFederated.class.isAssignableFrom(authProviderInstance.getClass())) {
+ WebAuthProviderDescriptor authProviderDescriptor = getAuthProvider(authProviderId);
+ var authProviderInstance = authProviderDescriptor.getInstance();
+ if (SMAuthProviderFederated.class.isAssignableFrom(authProviderInstance.getClass())) {
redirectUrl = buildRedirectLink(
- ((SMWAuthProviderFederated) authProviderInstance).getRedirectLink(authProviderConfiguration, Map.of()),
+ ((SMAuthProviderFederated) authProviderInstance).getRedirectLink(authProviderConfiguration, Map.of()),
authId
);
}
+
}
authData.put(authProviderId, authProviderData);
}
@@ -1172,12 +1195,15 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
SMTokens smTokens = findTokenBySmSession(smSessionId);
SMAuthPermissions authPermissions = getTokenPermissions(smTokens.getSmAccessToken());
+ String userId = authPermissions.getUserId();
+ String authRole = readTokenAuthRole(smTokens.getSmAccessToken());
var successAuthStatus = SMAuthInfo.success(
authId,
smTokens.getSmAccessToken(),
smTokens.getSmRefreshToken(),
authPermissions,
- authData
+ authData,
+ authRole
);
updateAuthStatus(authId, SMAuthStatus.EXPIRED, authData, null, authPermissions.getSessionId());
return successAuthStatus;
@@ -1221,6 +1247,14 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
}
}
+ private void invalidateAllUserTokens(String userId) throws DBCException {
+ try (Connection dbCon = database.openConnection()) {
+ JDBCUtils.executeStatement(dbCon, "DELETE FROM CB_AUTH_TOKEN WHERE USER_ID=?", userId);
+ } catch (SQLException e) {
+ throw new DBCException("Session invalidation failed", e);
+ }
+ }
+
private SMCredentials getCurrentUserCreds() throws SMException {
var currentUserCreds = credentialsProvider.getActiveUserCredentials();
if (currentUserCreds == null) {
@@ -1305,16 +1339,24 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
String activeUserId = permissions == null ? null : permissions.getUserId();
Map storedUserData = new LinkedHashMap<>();
+ SMTeam[] allTeams = null;
+ String detectedAuthRole = null;
for (String authProviderId : authProviderIds) {
+ WebAuthProviderDescriptor authProvider = getAuthProvider(authProviderId);
var userAuthData = (Map) authInfo.getAuthData().get(authProviderId);
+ SMAutoAssign autoAssign = getAutoAssignUserData(authId, authProvider, userAuthData, finishAuthMonitor);
+ if (autoAssign != null) {
+ detectedAuthRole = autoAssign.getAuthRole();
+ }
+
var userIdFromCreds = findOrCreateExternalUserByCredentials(
- authProviderId,
+ authProvider,
authAttemptSessionInfo.getSessionParams(),
userAuthData,
finishAuthMonitor,
activeUserId,
activeUserId == null,
- authInfo.getAuthRole()
+ detectedAuthRole
);
if (userIdFromCreds == null) {
@@ -1322,6 +1364,14 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
updateAuthStatus(authId, SMAuthStatus.ERROR, storedUserData, error);
return SMAuthInfo.error(authId, error);
}
+
+ if (autoAssign != null && !CommonUtils.isEmpty(autoAssign.getExternalTeamIds())) {
+ if (allTeams == null) {
+ allTeams = readAllTeams();
+ }
+ autoUpdateUserTeams(authProvider, autoAssign, userIdFromCreds, allTeams);
+ }
+
if (activeUserId == null) {
activeUserId = userIdFromCreds;
}
@@ -1331,7 +1381,7 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
);
}
- String tokenAuthRole = updateUserAuthRoleIfNeeded(activeUserId, authInfo.getAuthRole());
+ String tokenAuthRole = updateUserAuthRoleIfNeeded(activeUserId, detectedAuthRole);
if (smTokens == null && permissions == null) {
try (Connection dbCon = database.openConnection()) {
try (JDBCTransaction txn = new JDBCTransaction(dbCon)) {
@@ -1368,10 +1418,101 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
//refresh token must be sent only once
isMainAuthSession ? smTokens.getSmRefreshToken() : null,
permissions,
- authInfo.getAuthData()
+ authInfo.getAuthData(),
+ tokenAuthRole
);
}
+ private void autoUpdateUserTeams(
+ WebAuthProviderDescriptor authProvider,
+ SMAutoAssign autoAssign,
+ String userId,
+ SMTeam[] allTeams
+ ) throws DBCException {
+ if (!(authProvider.getInstance() instanceof SMAuthProviderAssigner)) {
+ return;
+ }
+ SMAuthProviderAssigner authProviderAssigner = (SMAuthProviderAssigner) authProvider.getInstance();
+
+ String[] newTeamIds = autoAssign.getExternalTeamIds()
+ .stream()
+ .map(externalTeamId -> findTeamByExternalTeamId(
+ allTeams,
+ authProviderAssigner.getExternalTeamIdMetadataFieldName(),
+ externalTeamId
+ ))
+ .filter(Objects::nonNull)
+ .map(SMTeam::getTeamId)
+ .toArray(String[]::new);
+ if (!ArrayUtils.isEmpty(newTeamIds)) {
+ setUserTeams(
+ userId,
+ newTeamIds,
+ userId
+ );
+ }
+ }
+
+ @Nullable
+ private SMAutoAssign getAutoAssignUserData(
+ String authAttemptId,
+ WebAuthProviderDescriptor authProvider,
+ Map userData,
+ DBRProgressMonitor monitor
+ ) throws DBException {
+ var authProviderInstance = authProvider.getInstance();
+ if (!(authProviderInstance instanceof SMAuthProviderAssigner)) {
+ return null;
+ }
+ var authProviderAssigner = (SMAuthProviderAssigner) authProviderInstance;
+ String providerConfigId = readProviderConfigId(authAttemptId, authProvider.getId());
+ if (providerConfigId == null) {
+ return null;
+ }
+ var providerConfig =
+ application.getAuthConfiguration().getAuthProviderConfiguration(providerConfigId);
+ return authProviderAssigner.detectAutoAssignments(
+ monitor,
+ providerConfig == null ? Map.of() : providerConfig.getParameters(),
+ userData
+ );
+ }
+
+ @Nullable
+ private SMTeam findTeamByExternalTeamId(SMTeam[] allTeams, String externalGroupParameterName, String groupId) {
+ for (SMTeam team : allTeams) {
+ String teamGroupId = team.getMetaParameters().get(externalGroupParameterName);
+ if (CommonUtils.equalObjects(teamGroupId, groupId)) {
+ return team;
+ }
+ }
+ return null;
+ }
+
+
+ private String readProviderConfigId(String authAttemptId, String authProviderId) throws DBException {
+ try (Connection dbCon = database.openConnection()) {
+ try (PreparedStatement dbStat = dbCon.prepareStatement(
+ "SELECT AUTH_PROVIDER_CONFIGURATION_ID " +
+ "FROM CB_AUTH_ATTEMPT_INFO "
+ + "WHERE AUTH_ID=? AND AUTH_PROVIDER_ID=?"
+ )) {
+ dbStat.setString(1, authAttemptId);
+ dbStat.setString(2, authProviderId);
+ try (ResultSet dbResult = dbStat.executeQuery()) {
+ if (!dbResult.next()) {
+ return null;
+ }
+ return dbResult.getString(1);
+
+ }
+ }
+ } catch (SQLException e) {
+ throw new DBException("Failed to read auth provider configuration", e);
+ }
+ }
+
+
@Nullable
protected String readUserAuthRole(String userId) throws DBException {
try (Connection dbCon = database.openConnection()) {
@@ -1430,7 +1571,7 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
}
private String findOrCreateExternalUserByCredentials(
- @NotNull String authProviderId,
+ @NotNull WebAuthProviderDescriptor authProvider,
@NotNull Map sessionParameters,
@NotNull Map userCredentials,
@NotNull DBRProgressMonitor progressMonitor,
@@ -1438,9 +1579,8 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
boolean createNewUserIfNotExist,
String authRole
) throws DBException {
- AuthProviderDescriptor authProvider = getAuthProvider(authProviderId);
SMAuthProvider> smAuthProviderInstance = authProvider.getInstance();
- String userId = findUserByCredentials(authProviderId, userCredentials);
+ String userId = findUserByCredentials(authProvider, userCredentials);
String userIdFromCredentials;
try {
userIdFromCredentials = smAuthProviderInstance.validateLocalAuth(progressMonitor, this, Map.of(), userCredentials, null);
@@ -1450,7 +1590,7 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
}
if (activeUserId != null && userId != null && !activeUserId.equals(userId)) {
log.debug("User '" + activeUserId + "' is authenticated in '"
- + authProviderId + "' auth provider with credentials of user '"
+ + authProvider.getId() + "' auth provider with credentials of user '"
+ userIdFromCredentials + "'");
}
if (userId == null && createNewUserIfNotExist) {
@@ -1470,7 +1610,7 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
setUserTeams(userId, new String[]{defaultTeamName}, userId);
}
}
- setUserCredentials(userId, authProviderId, userCredentials);
+ setUserCredentials(userId, authProvider.getId(), userCredentials);
} else if (userId == null) {
userId = userIdFromCredentials;
}
@@ -1564,12 +1704,12 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
}
WebAuthConfiguration appConfiguration = (WebAuthConfiguration) application.getAppConfiguration();
Set customConfigurations = appConfiguration.getAuthCustomConfigurations();
- List providers = AuthProviderRegistry.getInstance().getAuthProviders().stream()
+ List providers = WebAuthProviderRegistry.getInstance().getAuthProviders().stream()
.filter(ap ->
!ap.isTrusted() &&
appConfiguration.isAuthProviderEnabled(ap.getId()) &&
(!ap.isConfigurable() || hasProviderConfiguration(ap, customConfigurations)))
- .map(AuthProviderDescriptor::createDescriptorBean).collect(Collectors.toList());
+ .map(WebAuthProviderDescriptor::createDescriptorBean).collect(Collectors.toList());
if (!CommonUtils.isEmpty(customConfigurations)) {
// Attach custom configs to providers
@@ -1587,7 +1727,7 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
return providers.toArray(new SMAuthProviderDescriptor[0]);
}
- private static boolean hasProviderConfiguration(AuthProviderDescriptor ap, Set customConfigurations) {
+ private static boolean hasProviderConfiguration(WebAuthProviderDescriptor ap, Set customConfigurations) {
for (SMAuthProviderCustomConfiguration cc : customConfigurations) {
if (!cc.isDisabled() && cc.getProvider().equals(ap.getId())) {
return true;
@@ -1895,7 +2035,7 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
}
try (PreparedStatement dbStat = dbCon.prepareStatement(
"INSERT INTO CB_AUTH_PROVIDER(PROVIDER_ID,IS_ENABLED) VALUES(?,'Y')")) {
- for (AuthProviderDescriptor authProvider : AuthProviderRegistry.getInstance().getAuthProviders()) {
+ for (WebAuthProviderDescriptor authProvider : WebAuthProviderRegistry.getInstance().getAuthProviders()) {
if (!registeredProviders.contains(authProvider.getId())) {
dbStat.setString(1, authProvider.getId());
dbStat.executeUpdate();
@@ -1925,8 +2065,8 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
}
}
- private AuthProviderDescriptor getAuthProvider(String authProviderId) throws DBCException {
- AuthProviderDescriptor authProvider = AuthProviderRegistry.getInstance().getAuthProvider(authProviderId);
+ private WebAuthProviderDescriptor getAuthProvider(String authProviderId) throws DBCException {
+ WebAuthProviderDescriptor authProvider = WebAuthProviderRegistry.getInstance().getAuthProvider(authProviderId);
if (authProvider == null) {
throw new DBCException("Auth provider not found: " + authProviderId);
}
diff --git a/server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/service/security/db/CBDatabase.java b/server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/service/security/db/CBDatabase.java
index 6459df0f9f..64c97112c9 100644
--- a/server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/service/security/db/CBDatabase.java
+++ b/server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/service/security/db/CBDatabase.java
@@ -21,6 +21,8 @@ import com.google.gson.GsonBuilder;
import io.cloudbeaver.auth.provider.local.LocalAuthProviderConstants;
import io.cloudbeaver.model.app.WebApplication;
import io.cloudbeaver.model.session.WebAuthInfo;
+import io.cloudbeaver.registry.WebAuthProviderDescriptor;
+import io.cloudbeaver.registry.WebAuthProviderRegistry;
import io.cloudbeaver.utils.WebAppUtils;
import org.apache.commons.dbcp2.*;
import org.apache.commons.pool2.impl.GenericObjectPool;
@@ -42,8 +44,6 @@ import org.jkiss.dbeaver.model.sql.schema.ClassLoaderScriptSource;
import org.jkiss.dbeaver.model.sql.schema.SQLSchemaManager;
import org.jkiss.dbeaver.model.sql.schema.SQLSchemaVersionManager;
import org.jkiss.dbeaver.registry.DataSourceProviderRegistry;
-import org.jkiss.dbeaver.registry.auth.AuthProviderDescriptor;
-import org.jkiss.dbeaver.registry.auth.AuthProviderRegistry;
import org.jkiss.dbeaver.runtime.DBWorkbench;
import org.jkiss.dbeaver.utils.GeneralUtils;
import org.jkiss.dbeaver.utils.RuntimeUtils;
@@ -68,7 +68,7 @@ public class CBDatabase {
public static final String SCHEMA_UPDATE_SQL_PATH = "db/cb_schema_update_";
private static final int LEGACY_SCHEMA_VERSION = 1;
- private static final int CURRENT_SCHEMA_VERSION = 11;
+ private static final int CURRENT_SCHEMA_VERSION = 12;
private static final String DEFAULT_DB_USER_NAME = "cb-data";
private static final String DEFAULT_DB_PWD_FILE = ".database-credentials.dat";
@@ -219,7 +219,7 @@ public class CBDatabase {
// Associate all auth credentials with admin user
for (WebAuthInfo ai : authInfoList) {
if (!ai.getAuthProvider().equals(LocalAuthProviderConstants.PROVIDER_ID)) {
- AuthProviderDescriptor authProvider = ai.getAuthProviderDescriptor();
+ WebAuthProviderDescriptor authProvider = ai.getAuthProviderDescriptor();
Map userCredentials = ai.getUserCredentials();
if (!CommonUtils.isEmpty(userCredentials)) {
adminSecurityController.setUserCredentials(adminName, authProvider.getId(), userCredentials);
@@ -266,7 +266,7 @@ public class CBDatabase {
credentials.put(LocalAuthProviderConstants.CRED_USER, adminUser.getUserId());
credentials.put(LocalAuthProviderConstants.CRED_PASSWORD, clientPassword);
- AuthProviderDescriptor authProvider = AuthProviderRegistry.getInstance().getAuthProvider(LocalAuthProviderConstants.PROVIDER_ID);
+ WebAuthProviderDescriptor authProvider = WebAuthProviderRegistry.getInstance().getAuthProvider(LocalAuthProviderConstants.PROVIDER_ID);
if (authProvider != null) {
adminSecurityController.setUserCredentials(adminUser.getUserId(), authProvider.getId(), credentials);
}
diff --git a/server/test/io.cloudbeaver.test.platform/workspace/conf/initial-data.conf b/server/test/io.cloudbeaver.test.platform/workspace/conf/initial-data.conf
index 718fa039bc..1aa23bdcc3 100644
--- a/server/test/io.cloudbeaver.test.platform/workspace/conf/initial-data.conf
+++ b/server/test/io.cloudbeaver.test.platform/workspace/conf/initial-data.conf
@@ -3,13 +3,13 @@
adminPassword: "test",
teams: [
{
- teamId: "admin",
+ subjectId: "admin",
name: "Admin",
description: "Administrative access. Has all permissions.",
permissions: [ "public", "admin" ]
},
{
- teamId: "user",
+ subjectId: "user",
name: "User",
description: "Standard user",
permissions: [ "public" ]