mirror of
https://github.com/dbeaver/cloudbeaver.git
synced 2026-09-24 16:04:36 +08:00
dbeaver/pro#1257 Subject mata parameters API (#1325)
* dbeaver/pro#1257 Subject mata parameters API * dbeaver/pro#1257 Access and teams membership view. Project access editor. * dbeaver/pro#1257 Project permission editor. Permission read performance * dbeaver/pro#1257 Teams and users membership edit. Security controller refactoring of current user specific functions. * dbeaver/pro#1257 Users create/delete
This commit is contained in:
@@ -9,4 +9,13 @@
|
||||
<extension-point id="io.cloudbeaver.event.handler" name="Wev event handler" schema="schema/io.cloudbeaver.event.handler.exsd"/>
|
||||
<extension-point id="io.cloudbeaver.metaParameters" name="Meta parameters" schema="schema/io.cloudbeaver.metaParameters.exsd"/>
|
||||
|
||||
<extension point="io.cloudbeaver.metaParameters">
|
||||
<metaParameters type="user">
|
||||
<propertyGroup label="Main">
|
||||
<property id="firstName" label="First Name" type="string" description="User first name"/>
|
||||
<property id="lastName" label="Last Name" type="string" description="User last name"/>
|
||||
</propertyGroup>
|
||||
</metaParameters>
|
||||
</extension>
|
||||
|
||||
</plugin>
|
||||
|
||||
+1
-1
@@ -127,7 +127,7 @@ public class WebSessionAuthProcessor {
|
||||
if (authProviderExternal != null && !configMode && !alreadyLoggedIn) {
|
||||
// We may need to associate new credentials with active user
|
||||
if (linkWithActiveUser) {
|
||||
securityController.setUserCredentials(authProviderDescriptor.getId(), authAttrs);
|
||||
securityController.setCurrentUserCredentials(authProviderDescriptor.getId(), authAttrs);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+5
@@ -22,6 +22,7 @@ import org.eclipse.core.runtime.Platform;
|
||||
import org.jkiss.dbeaver.Log;
|
||||
import org.jkiss.dbeaver.model.impl.PropertyDescriptor;
|
||||
import org.jkiss.dbeaver.model.preferences.DBPPropertyDescriptor;
|
||||
import org.jkiss.dbeaver.model.security.SMSubjectType;
|
||||
import org.jkiss.utils.ArrayUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -56,6 +57,10 @@ public class WebMetaParametersRegistry {
|
||||
return teamParameters;
|
||||
}
|
||||
|
||||
public List<DBPPropertyDescriptor> getMetaParameters(SMSubjectType subjectType) {
|
||||
return subjectType == SMSubjectType.user ? userParameters : teamParameters;
|
||||
}
|
||||
|
||||
private void loadExtensions(IExtensionRegistry registry) {
|
||||
IConfigurationElement[] extConfigs = registry.getConfigurationElementsFor(EXTENSION_ID);
|
||||
for (IConfigurationElement ext : extConfigs) {
|
||||
|
||||
@@ -8,14 +8,6 @@
|
||||
|
||||
</service>
|
||||
</extension>
|
||||
<extension point="io.cloudbeaver.metaParameters">
|
||||
<metaParameters type="user">
|
||||
<propertyGroup label="Main">
|
||||
<property id="firstName" label="First Name" type="string" description="User first name"/>
|
||||
<property id="lastName" label="Last Name" type="string" description="User last name"/>
|
||||
</propertyGroup>
|
||||
</metaParameters>
|
||||
</extension>
|
||||
<extension point="io.cloudbeaver.handler">
|
||||
<sessionHandler id="RPSessionHandler" class="io.cloudbeaver.service.auth.RPSessionHandler"/>
|
||||
</extension>
|
||||
|
||||
+2
-2
@@ -70,7 +70,7 @@ public class WebUserInfo {
|
||||
public List<String> getLinkedAuthProviders() throws DBWebException {
|
||||
if (linkedProviders == null) {
|
||||
try {
|
||||
linkedProviders = session.getSecurityController().getUserLinkedProviders();
|
||||
linkedProviders = session.getSecurityController().getCurrentUserLinkedProviders();
|
||||
} catch (DBException e) {
|
||||
throw new DBWebException("Error reading user linked providers", e);
|
||||
}
|
||||
@@ -86,7 +86,7 @@ public class WebUserInfo {
|
||||
@Property
|
||||
public Map<String, Object> getConfigurationParameters() throws DBWebException {
|
||||
try {
|
||||
return session.getSecurityController().getUserParameters();
|
||||
return session.getSecurityController().getCurrentUserParameters();
|
||||
} catch (DBException e) {
|
||||
throw new DBWebException("Error reading user parameters", e);
|
||||
}
|
||||
|
||||
+1
-1
@@ -216,7 +216,7 @@ public class WebServiceAuthImpl implements DBWServiceAuth {
|
||||
) throws DBWebException {
|
||||
webSession.addInfoMessage("Set user parameter - " + name);
|
||||
try {
|
||||
webSession.getSecurityController().setUserParameter(name, value);
|
||||
webSession.getSecurityController().setCurrentUserParameter(name, value);
|
||||
return true;
|
||||
} catch (DBException e) {
|
||||
throw new DBWebException("Error setting user parameter", e);
|
||||
|
||||
+1
-1
@@ -115,7 +115,7 @@ public class LocalAuthProvider implements SMAuthProvider<LocalAuthSession> {
|
||||
//String newPasswordHash = WebAuthProviderPropertyEncryption.hash.encrypt(userName, newPassword);
|
||||
|
||||
storedCredentials.put(CRED_PASSWORD, newPassword);
|
||||
webSession.getSecurityController().setUserCredentials(authProvider.getId(), storedCredentials);
|
||||
webSession.getSecurityController().setCurrentUserCredentials(authProvider.getId(), storedCredentials);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
+71
-31
@@ -24,12 +24,14 @@ import io.cloudbeaver.auth.SMAuthProviderAssigner;
|
||||
import io.cloudbeaver.auth.SMAuthProviderExternal;
|
||||
import io.cloudbeaver.auth.SMAuthProviderFederated;
|
||||
import io.cloudbeaver.auth.SMAutoAssign;
|
||||
import io.cloudbeaver.model.app.WebAppConfiguration;
|
||||
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.registry.WebMetaParametersRegistry;
|
||||
import io.cloudbeaver.service.security.db.CBDatabase;
|
||||
import io.cloudbeaver.service.security.internal.AuthAttemptSessionInfo;
|
||||
import io.cloudbeaver.service.security.internal.SMTokenInfo;
|
||||
@@ -42,6 +44,7 @@ import org.jkiss.dbeaver.model.auth.*;
|
||||
import org.jkiss.dbeaver.model.exec.DBCException;
|
||||
import org.jkiss.dbeaver.model.impl.jdbc.JDBCUtils;
|
||||
import org.jkiss.dbeaver.model.impl.jdbc.exec.JDBCTransaction;
|
||||
import org.jkiss.dbeaver.model.preferences.DBPPropertyDescriptor;
|
||||
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
|
||||
import org.jkiss.dbeaver.model.runtime.LoggingProgressMonitor;
|
||||
import org.jkiss.dbeaver.model.security.*;
|
||||
@@ -118,6 +121,9 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
|
||||
boolean enabled,
|
||||
@Nullable String defaultAuthRole
|
||||
) throws DBException {
|
||||
if (CommonUtils.isEmpty(userId)) {
|
||||
throw new DBCException("Empty user name is not allowed");
|
||||
}
|
||||
if (isSubjectExists(userId)) {
|
||||
throw new DBCException("User or team '" + userId + "' already exists");
|
||||
}
|
||||
@@ -203,9 +209,23 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
|
||||
}
|
||||
}
|
||||
|
||||
private static Set<String> getAllLinkedSubjects(Connection dbCon, String subjectId) throws SQLException {
|
||||
Set<String> allSubjects = new HashSet<>();
|
||||
allSubjects.add(subjectId);
|
||||
try (PreparedStatement dbStat = dbCon.prepareStatement("SELECT TEAM_ID FROM CB_USER_TEAM UR WHERE USER_ID=?")) {
|
||||
dbStat.setString(1, subjectId);
|
||||
try (ResultSet dbResult = dbStat.executeQuery()) {
|
||||
while (dbResult.next()) {
|
||||
allSubjects.add(dbResult.getString(1));
|
||||
}
|
||||
}
|
||||
}
|
||||
return allSubjects;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public SMTeam[] getUserTeams() throws DBException {
|
||||
public SMTeam[] getCurrentUserTeams() throws DBException {
|
||||
return getUserTeams(getUserIdOrThrow());
|
||||
}
|
||||
|
||||
@@ -363,7 +383,7 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> getUserParameters() throws DBCException {
|
||||
public Map<String, Object> getCurrentUserParameters() throws DBCException {
|
||||
String userId = getUserIdOrThrow();
|
||||
try (Connection dbCon = database.openConnection()) {
|
||||
Map<String, Object> result = new LinkedHashMap<>();
|
||||
@@ -385,7 +405,7 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUserParameter(String name, Object value) throws DBException {
|
||||
public void setCurrentUserParameter(String name, Object value) throws DBException {
|
||||
String userId = getUserIdOrThrow();
|
||||
try (Connection dbCon = database.openConnection()) {
|
||||
try (JDBCTransaction txn = new JDBCTransaction(dbCon)) {
|
||||
@@ -478,7 +498,7 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUserCredentials(
|
||||
public void setCurrentUserCredentials(
|
||||
@NotNull String authProviderId,
|
||||
@NotNull Map<String, Object> credentials
|
||||
) throws DBException {
|
||||
@@ -639,12 +659,12 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Map<String, Object> getUserCredentials(@NotNull String authProviderId) throws DBException {
|
||||
public Map<String, Object> getCurrentUserCredentials(@NotNull String authProviderId) throws DBException {
|
||||
return getUserCredentials(getUserIdOrThrow(), authProviderId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getUserLinkedProviders() throws DBException {
|
||||
public String[] getCurrentUserLinkedProviders() throws DBException {
|
||||
return getUserLinkedProviders(getUserIdOrThrow());
|
||||
}
|
||||
|
||||
@@ -671,6 +691,32 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public SMPropertyDescriptor[] getMetaParametersBySubjectType(SMSubjectType subjectType) throws DBException {
|
||||
// First add global metas
|
||||
List<DBPPropertyDescriptor> props = new ArrayList<>(
|
||||
WebMetaParametersRegistry.getInstance().getMetaParameters(subjectType));
|
||||
|
||||
// Add metas from enabled auth providers
|
||||
WebAppConfiguration appConfiguration = WebAppUtils.getWebApplication().getAppConfiguration();
|
||||
if (appConfiguration instanceof WebAuthConfiguration) {
|
||||
for (String apId : ((WebAuthConfiguration)appConfiguration).getEnabledAuthProviders()) {
|
||||
WebAuthProviderDescriptor ap = WebAuthProviderRegistry.getInstance().getAuthProvider(apId);
|
||||
if (ap != null) {
|
||||
List<DBPPropertyDescriptor> metaProps = ap.getMetaParameters(SMSubjectType.team);
|
||||
if (!CommonUtils.isEmpty(metaProps)) {
|
||||
props.addAll(metaProps);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return props.stream()
|
||||
.map(SMPropertyDescriptor::new)
|
||||
.toArray(SMPropertyDescriptor[]::new);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////
|
||||
// Teams
|
||||
|
||||
@@ -742,6 +788,9 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
|
||||
|
||||
@Override
|
||||
public void createTeam(String teamId, String name, String description, String grantor) throws DBCException {
|
||||
if (CommonUtils.isEmpty(teamId)) {
|
||||
throw new DBCException("Empty team name is not allowed");
|
||||
}
|
||||
if (isSubjectExists(teamId)) {
|
||||
throw new DBCException("User or team '" + teamId + "' already exists");
|
||||
}
|
||||
@@ -831,12 +880,12 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
|
||||
// Subject functions
|
||||
|
||||
@Override
|
||||
public void setSubjectMetas(String userId, Map<String, String> metaParameters) throws DBCException {
|
||||
public void setSubjectMetas(@NotNull String subjectId, @NotNull Map<String, String> metaParameters) throws DBCException {
|
||||
try (Connection dbCon = database.openConnection()) {
|
||||
try (JDBCTransaction txn = new JDBCTransaction(dbCon)) {
|
||||
cleanupSubjectMeta(dbCon, userId);
|
||||
cleanupSubjectMeta(dbCon, subjectId);
|
||||
if (!metaParameters.isEmpty()) {
|
||||
saveSubjectMetas(dbCon, userId, metaParameters);
|
||||
saveSubjectMetas(dbCon, subjectId, metaParameters);
|
||||
}
|
||||
txn.commit();
|
||||
}
|
||||
@@ -1943,10 +1992,10 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
|
||||
try (Connection dbCon = database.openConnection()) {
|
||||
try (JDBCTransaction txn = new JDBCTransaction(dbCon)) {
|
||||
var sqlBuilder = new StringBuilder("DELETE FROM CB_OBJECT_PERMISSIONS WHERE SUBJECT_ID IN (");
|
||||
appendStringParameters(sqlBuilder, subjectIds.toArray(String[]::new));
|
||||
appendStringParameters(sqlBuilder, subjectIds);
|
||||
sqlBuilder.append(") AND OBJECT_TYPE=? ")
|
||||
.append("AND OBJECT_ID IN (");
|
||||
appendStringParameters(sqlBuilder, objectIds.toArray(String[]::new));
|
||||
appendStringParameters(sqlBuilder, objectIds);
|
||||
sqlBuilder.append(")");
|
||||
JDBCUtils.executeStatement(dbCon, sqlBuilder.toString(), objectType.getObjectType());
|
||||
if (!CommonUtils.isEmpty(permissions)) {
|
||||
@@ -2019,12 +2068,12 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
|
||||
public List<SMObjectPermissions> getAllAvailableObjectsPermissions(@NotNull SMObjectType objectType) throws DBException {
|
||||
|
||||
String subjectId = getSubjectId();
|
||||
Set<String> allSubjects = getAllLinkedSubjects(subjectId);
|
||||
try (Connection dbCon = database.openConnection()) {
|
||||
Set<String> allSubjects = getAllLinkedSubjects(dbCon, subjectId);
|
||||
{
|
||||
var sqlBuilder = new StringBuilder("SELECT OBJECT_ID,PERMISSION FROM CB_OBJECT_PERMISSIONS ");
|
||||
sqlBuilder.append("WHERE SUBJECT_ID IN (");
|
||||
appendStringParameters(sqlBuilder, allSubjects.toArray(String[]::new));
|
||||
appendStringParameters(sqlBuilder, allSubjects);
|
||||
sqlBuilder.append(") AND OBJECT_TYPE=?");
|
||||
try (PreparedStatement dbStat = dbCon.prepareStatement(sqlBuilder.toString())) {
|
||||
dbStat.setString(1, objectType.getObjectType());
|
||||
@@ -2047,16 +2096,6 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
|
||||
}
|
||||
}
|
||||
|
||||
private Set<String> getAllLinkedSubjects(String subjectId) throws DBException {
|
||||
Set<String> allSubjects = new HashSet<>();
|
||||
allSubjects.add(subjectId);
|
||||
var userTeamIds = Arrays.stream(getUserTeams(subjectId))
|
||||
.map(SMTeam::getTeamId)
|
||||
.collect(Collectors.toSet());
|
||||
allSubjects.addAll(userTeamIds);
|
||||
return allSubjects;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public SMObjectPermissions getObjectPermissions(
|
||||
@@ -2064,12 +2103,12 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
|
||||
@NotNull String objectId,
|
||||
@NotNull SMObjectType objectType
|
||||
) throws DBException {
|
||||
Set<String> allSubjects = getAllLinkedSubjects(subjectId);
|
||||
try (Connection dbCon = database.openConnection()) {
|
||||
Set<String> allSubjects = getAllLinkedSubjects(dbCon, subjectId);
|
||||
{
|
||||
var sqlBuilder = new StringBuilder("SELECT PERMISSION FROM CB_OBJECT_PERMISSIONS ");
|
||||
sqlBuilder.append("WHERE SUBJECT_ID IN (");
|
||||
appendStringParameters(sqlBuilder, allSubjects.toArray(String[]::new));
|
||||
appendStringParameters(sqlBuilder, allSubjects);
|
||||
sqlBuilder.append(") AND OBJECT_TYPE=? AND OBJECT_ID=?");
|
||||
|
||||
try (PreparedStatement dbStat = dbCon.prepareStatement(sqlBuilder.toString())) {
|
||||
@@ -2128,14 +2167,14 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
|
||||
|
||||
@Override
|
||||
public List<SMObjectPermissionsGrant> getSubjectObjectPermissionGrants(@NotNull String subjectId, @NotNull SMObjectType smObjectType) throws DBException {
|
||||
var allLinkedSubjects = getAllLinkedSubjects(subjectId);
|
||||
var grantedPermissionsByObjectId = new HashMap<String, SMObjectPermissionsGrant.Builder>();
|
||||
try (Connection dbCon = database.openConnection()) {
|
||||
var allLinkedSubjects = getAllLinkedSubjects(dbCon, subjectId);
|
||||
var sqlBuilder =
|
||||
new StringBuilder("SELECT OP.OBJECT_ID,S.SUBJECT_TYPE,S.SUBJECT_ID,OP.PERMISSION\n")
|
||||
.append("FROM CB_OBJECT_PERMISSIONS OP,CB_AUTH_SUBJECT S\n")
|
||||
.append("WHERE S.SUBJECT_ID = OP.SUBJECT_ID AND OP.SUBJECT_ID IN (");
|
||||
appendStringParameters(sqlBuilder, allLinkedSubjects.toArray(String[]::new));
|
||||
appendStringParameters(sqlBuilder, allLinkedSubjects);
|
||||
sqlBuilder.append(") AND OP.OBJECT_TYPE=?");
|
||||
try (PreparedStatement dbStat = dbCon.prepareStatement(sqlBuilder.toString())) {
|
||||
dbStat.setString(1, smObjectType.getObjectType());
|
||||
@@ -2161,10 +2200,11 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
|
||||
}
|
||||
}
|
||||
|
||||
private void appendStringParameters(StringBuilder sql, @NotNull String[] subjectIds) {
|
||||
for (int i = 0; i < subjectIds.length; i++) {
|
||||
String id = subjectIds[i];
|
||||
if (i > 0) sql.append(",");
|
||||
private static void appendStringParameters(StringBuilder sql, @NotNull Collection<String> subjectIds) {
|
||||
boolean first = true;
|
||||
for (String id : subjectIds) {
|
||||
if (!first) sql.append(",");
|
||||
first = false;
|
||||
sql.append("'").append(id.replace("'", "''")).append("'");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user