dbeaver/pro#6364 add option to set default view for project

This commit is contained in:
Ruslan
2025-10-16 01:06:19 +02:00
parent 9267e65300
commit 28809be5f4
7 changed files with 281 additions and 103 deletions
@@ -17,25 +17,32 @@
package io.cloudbeaver;
import io.cloudbeaver.model.WebConnectionConfig;
import io.cloudbeaver.model.app.WebAppConfiguration;
import io.cloudbeaver.model.session.WebSession;
import io.cloudbeaver.utils.ServletAppUtils;
import io.cloudbeaver.utils.WebDataSourceUtils;
import org.jkiss.code.NotNull;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.model.app.DBPDataSourceRegistry;
import org.jkiss.dbeaver.model.app.DBPProject;
import org.jkiss.dbeaver.model.connection.DBPConnectionConfiguration;
import org.jkiss.dbeaver.model.connection.DBPDriver;
import org.jkiss.dbeaver.model.security.SMObjectType;
import org.jkiss.dbeaver.registry.DataSourceDescriptor;
import org.jkiss.dbeaver.registry.DataSourceNavigatorSettings;
import org.jkiss.utils.CommonUtils;
import java.util.Map;
public class WebConnectionConfigInputHandler<T extends WebConnectionConfig, C extends DataSourceDescriptor> {
private static final Log log = Log.getLog(WebConnectionConfigInputHandler.class);
protected final T input;
protected final DBPDataSourceRegistry registry;
protected final WebSession webSession;
public WebConnectionConfigInputHandler(@NotNull DBPDataSourceRegistry registry, T configInput) {
public WebConnectionConfigInputHandler(@NotNull DBPDataSourceRegistry registry, T configInput, WebSession webSession) {
this.registry = registry;
this.input = configInput;
this.webSession = webSession;
}
public C createDataSourceContainer() throws DBWebException {
@@ -47,9 +54,7 @@ public class WebConnectionConfigInputHandler<T extends WebConnectionConfig, C ex
C newDataSource = createDataSourceContainerFromInput(driver);
if (ServletAppUtils.getServletApplication().getAppConfiguration() instanceof WebAppConfiguration webAppConfiguration) {
newDataSource.setNavigatorSettings(webAppConfiguration.getDefaultNavigatorSettings());
}
presetNavigatorSettings(newDataSource);
WebDataSourceUtils.saveAuthProperties(
newDataSource,
@@ -61,6 +66,29 @@ public class WebConnectionConfigInputHandler<T extends WebConnectionConfig, C ex
return newDataSource;
}
private <C extends DataSourceDescriptor> void presetNavigatorSettings(C newDataSource) {
// if (ServletAppUtils.getServletApplication().getAppConfiguration() instanceof WebAppConfiguration webAppConfiguration) {
// newDataSource.setNavigatorSettings(webAppConfiguration.getDefaultNavigatorSettings());
// }
try {
DBPProject project = newDataSource.getProject();
String projectId = project.getId();
Map<String, Object> projectNavigatorSettings = webSession.getUserContext().getSecurityController().getObjectSettings(
projectId, SMObjectType.project,
ServletAppUtils.getServletApplication().getAppConfiguration().getDefaultUserTeam(),
DataSourceNavigatorSettings.getSettingsKeySet()
);
if (!CommonUtils.isEmpty(projectNavigatorSettings)) {
DataSourceNavigatorSettings navigatorSettings = new DataSourceNavigatorSettings();
navigatorSettings.loadSettings(projectNavigatorSettings);
newDataSource.setNavigatorSettings(navigatorSettings);
}
} catch (Exception e) {
log.warn("Error loading navigator settings", e);
}
}
public void updateDataSource(@NotNull C dataSource) throws DBWebException {
dataSource.setId(dataSource.getId());
if (!CommonUtils.isEmpty(input.getName())) {
@@ -19,6 +19,7 @@ package io.cloudbeaver;
import io.cloudbeaver.model.WebConnectionConfig;
import io.cloudbeaver.model.WebConnectionInfo;
import io.cloudbeaver.model.session.WebSession;
import io.cloudbeaver.utils.ServletAppUtils;
import io.cloudbeaver.utils.WebDataSourceUtils;
import org.jkiss.code.NotNull;
import org.jkiss.code.Nullable;
@@ -252,6 +253,7 @@ public class WebSessionProjectImpl extends WebProjectImpl {
Map<String, Object> loadedSettings = webSession.getSecurityController().getObjectSettings(
getId(),
SMObjectType.project,
ServletAppUtils.getServletApplication().getAppConfiguration().getDefaultUserTeam(),
null
);
projectSettings.clear();
@@ -359,7 +361,7 @@ public class WebSessionProjectImpl extends WebProjectImpl {
@NotNull
protected WebConnectionConfigInputHandler getInputConfigHandler(@NotNull Map<String, Object> configMap) {
return new WebConnectionConfigInputHandler<>(getDataSourceRegistry(), getConnectionConfigInput(configMap));
return new WebConnectionConfigInputHandler<>(getDataSourceRegistry(), getConnectionConfigInput(configMap), webSession);
}
@@ -69,6 +69,9 @@ extend type Query {
"Returns project settings that are specified for a current user"
rmUserProjectSettings(projectId: ID!): Object @since(version: "25.2.1")
"Returns project settings that are specified for a subject"
rmAdminUserProjectSettings(projectId: ID!, subjectID: String!): Object @since(version: "25.2.3")
}
extend type Mutation {
@@ -137,4 +140,9 @@ extend type Mutation {
rmAddUserProjectSettings(projectId: ID!, settings: Object!): Boolean! @since(version: "25.2.1")
"Deletes project settings that are specified for a current user"
rmDeleteUserProjectSettings(projectId: ID!, settingIds: [String!]!): Boolean! @since(version: "25.2.1")
"Adds project settings (e.g. enables simple view for a project) for a subject"
rmAdminAddUserProjectSettings(projectId: ID!, subjectId:String!, settings: Object!): Boolean! @since(version: "25.2.3")
"Deletes project settings that are specified for a subject"
rmAdminDeleteUserProjectSettings(projectId: ID!, subjectId:String!, settingIds: [String!]!): Boolean! @since(version: "25.2.3")
}
@@ -214,4 +214,29 @@ public interface DBWServiceRM extends DBWService {
@NotNull @WebObjectId String projectId,
@Nullable List<String> settings
) throws DBWebException;
@NotNull
@WebProjectAction(requireProjectPermissions = DBWConstants.PERMISSION_ADMIN)
Map<String, Object> getProjectSettings(
@NotNull WebSession webSession,
@NotNull @WebObjectId String projectId,
@NotNull String subjectId,
@Nullable String settingId
) throws DBWebException;
@WebProjectAction(requireProjectPermissions = DBWConstants.PERMISSION_ADMIN)
boolean addProjectSettings(
@NotNull WebSession webSession,
@NotNull @WebObjectId String projectId,
@NotNull String subjectId,
@NotNull Map<String, Object> settings
) throws DBWebException;
@WebProjectAction(requireProjectPermissions = DBWConstants.PERMISSION_ADMIN)
boolean deleteProjectSettings(
@NotNull WebSession webSession,
@NotNull @WebObjectId String projectId,
@NotNull String subjectId,
@Nullable List<String> settings
) throws DBWebException;
}
@@ -70,6 +70,14 @@ public class WebServiceBindingRM extends WebServiceBindingBase<DBWServiceRM> {
getArgument(env, "settingId")
)
)
.dataFetcher(
"rmAdminUserProjectSettings", env -> getService(env).getProjectSettings(
getWebSession(env),
getArgumentVal(env, "projectId"),
getArgumentVal(env, "subjectId"),
getArgument(env, "settingId")
)
)
;
model.getMutationType()
.dataFetcher("rmCreateResource",
@@ -152,6 +160,22 @@ public class WebServiceBindingRM extends WebServiceBindingBase<DBWServiceRM> {
getArgument(env, "settingIds")
)
)
.dataFetcher(
"rmAdminAddUserProjectSettings", env -> getService(env).addProjectSettings(
getWebSession(env),
getArgumentVal(env, "projectId"),
getArgumentVal(env, "subjectId"),
getArgumentVal(env, "settings")
)
)
.dataFetcher(
"rmAdminDeleteUserProjectSettings", env -> getService(env).deleteProjectSettings(
getWebSession(env),
getArgumentVal(env, "projectId"),
getArgumentVal(env, "subjectId"),
getArgument(env, "settingIds")
)
)
;
}
@@ -469,22 +469,72 @@ public class WebServiceRM implements DBWServiceRM {
}
}
@Override
public boolean addProjectSettings(@NotNull WebSession webSession, @NotNull String projectId, @NotNull Map<String, Object> settings)
throws DBWebException {
try {
validateProject(webSession, projectId);
webSession.getSecurityController().setObjectSettings(
projectId,
SMObjectType.project,
settings
);
return true;
} catch (DBException e) {
throw new DBWebException("Error adding object settings", e);
}
}
@NotNull
@Override
public Map<String, Object> getProjectSettings(@NotNull WebSession webSession, @NotNull String projectId, @Nullable String settingId)
throws DBWebException {
try {
validateProject(webSession, projectId);
//todo accumulate settings from user and team
return webSession.getSecurityController().getObjectSettings(
projectId,
SMObjectType.project,
ServletAppUtils.getServletApplication().getAppConfiguration().getDefaultUserTeam(),
settingId == null ? null : Set.of(settingId)
);
} catch (DBException e) {
throw new DBWebException("Error getting project settings", e);
}
}
@Override
public boolean deleteProjectSettings(@NotNull WebSession webSession, @NotNull String projectId, @Nullable List<String> settings)
throws DBWebException {
try {
validateProject(webSession, projectId);
webSession.getSecurityController().deleteObjectSettings(
projectId,
SMObjectType.project,
settings == null ? null : new HashSet<>(settings)
);
return true;
} catch (DBException e) {
throw new DBWebException("Error deleting object settings", e);
}
}
@NotNull
@Override
public Map<String, Object> getProjectSettings(
@NotNull WebSession webSession,
@NotNull String projectId,
@Nullable String subjectId,
@Nullable String settingId
) throws DBWebException {
try {
var project = webSession.getProjectById(projectId);
if (project == null) {
throw new DBWebException("Project '" + projectId + "' not found");
}
validateProject(webSession, projectId);
return webSession.getSecurityController().getObjectSettings(
projectId,
SMObjectType.project,
settingId
subjectId,
settingId == null ? null : Set.of(settingId)
);
} catch (DBException e) {
throw new DBWebException("Error getting project settings", e);
@@ -495,16 +545,15 @@ public class WebServiceRM implements DBWServiceRM {
public boolean addProjectSettings(
@NotNull WebSession webSession,
@NotNull String projectId,
@NotNull String subjectId,
@NotNull Map<String, Object> settings
) throws DBWebException {
try {
var project = webSession.getProjectById(projectId);
if (project == null) {
throw new DBWebException("Project '" + projectId + "' not found");
}
webSession.getSecurityController().setObjectSettings(
validateProject(webSession, projectId);
webSession.getAdminSecurityController().setObjectSettings(
projectId,
SMObjectType.project,
subjectId,
settings
);
return true;
@@ -517,16 +566,15 @@ public class WebServiceRM implements DBWServiceRM {
public boolean deleteProjectSettings(
@NotNull WebSession webSession,
@NotNull String projectId,
@NotNull String subjectId,
@Nullable List<String> settings
) throws DBWebException {
try {
var project = webSession.getProjectById(projectId);
if (project == null) {
throw new DBWebException("Project '" + projectId + "' not found");
}
webSession.getSecurityController().deleteObjectSettings(
validateProject(webSession, projectId);
webSession.getAdminSecurityController().deleteObjectSettings(
projectId,
SMObjectType.project,
subjectId,
settings == null ? null : new HashSet<>(settings)
);
return true;
@@ -535,6 +583,13 @@ public class WebServiceRM implements DBWServiceRM {
}
}
private void validateProject(@NotNull WebSession webSession, @NotNull String projectId) throws DBWebException {
var project = webSession.getProjectById(projectId);
if (project == null) {
throw new DBWebException("Project '" + projectId + "' not found");
}
}
private RMController getResourceController(WebSession webSession) {
return webSession.getRmController();
}
@@ -111,70 +111,19 @@ public class CBEmbeddedSecurityController<T extends ServletAuthApplication>
@NotNull Map<String, Object> settings
) throws DBException {
String userId = getUserIdOrThrow();
try (Connection dbCon = database.openConnection()) {
try (JDBCTransaction txn = new JDBCTransaction(dbCon)) {
deleteObjectSettings(objectId, objectType, settings.keySet());
try (
PreparedStatement dbStat = dbCon.prepareStatement(
"INSERT INTO {table_prefix}CB_OBJECT_SETTINGS" +
"(OBJECT_ID,OBJECT_TYPE,SUBJECT_ID,SETTING_ID,SETTING_VALUE,UPDATED_BY,UPDATE_TIME) " +
"VALUES(?,?,?,?,?,?,CURRENT_TIMESTAMP)")
) {
for (Map.Entry<String, Object> entry : settings.entrySet()) {
dbStat.setString(1, objectId);
dbStat.setString(2, objectType.name());
dbStat.setString(3, userId);
dbStat.setString(4, entry.getKey());
dbStat.setString(5, CommonUtils.toString(entry.getValue()));
dbStat.setString(6, userId);
dbStat.addBatch();
}
dbStat.executeBatch();
}
txn.commit();
}
} catch (SQLException e) {
throw new DBCException("Error while adding object settings", e);
}
setObjectSettings(objectId, objectType, userId, settings);
}
@NotNull
@Override
public Map<String, Object> getObjectSettings(
@NotNull String objectId,
@NotNull SMObjectType objectType,
@Nullable String settingId
) throws DBException {
String userId = getUserIdOrThrow();
try (Connection dbCon = database.openConnection()) {
try (
PreparedStatement dbStat = dbCon.prepareStatement("SELECT SETTING_ID,SETTING_VALUE " +
"FROM {table_prefix}CB_OBJECT_SETTINGS " +
"WHERE OBJECT_ID=? AND OBJECT_TYPE=? AND SUBJECT_ID=?" +
(settingId == null ? "" : " AND SETTING_ID=?"))
) {
int index = 1;
dbStat.setString(index++, objectId);
dbStat.setString(index++, objectType.name());
dbStat.setString(index++, userId);
if (settingId != null) {
dbStat.setString(index++, settingId);
}
try (ResultSet dbResult = dbStat.executeQuery()) {
Map<String, Object> result = new LinkedHashMap<>();
while (dbResult.next()) {
result.put(
dbResult.getString(1),
dbResult.getString(2)
);
}
return result;
}
}
} catch (SQLException e) {
throw new DBCException("Error while getting object settings", e);
}
}
// @NotNull
// @Override
// public Map<String, Object> getObjectSettings(
// @NotNull String objectId,
// @NotNull SMObjectType objectType,
// @NotNull String subjectId,
// @Nullable Set<String> settingIds
// ) throws DBException {
// return getObjectSettings(objectId, objectType, subjectId, settingIds);
// }
@Override
public void deleteObjectSettings(
@@ -183,26 +132,7 @@ public class CBEmbeddedSecurityController<T extends ServletAuthApplication>
@Nullable Set<String> settingIds
) throws DBException {
String userId = getUserIdOrThrow();
String sql = "DELETE FROM {table_prefix}CB_OBJECT_SETTINGS WHERE OBJECT_ID=? AND OBJECT_TYPE=? AND SUBJECT_ID=?";
if (settingIds != null && !settingIds.isEmpty()) {
sql += " AND SETTING_ID IN (" + SQLUtils.generateParamList(settingIds.size()) + ")";
}
try (Connection dbCon = database.openConnection()) {
try (PreparedStatement dbStat = dbCon.prepareStatement(sql)) {
int index = 1;
dbStat.setString(index++, objectId);
dbStat.setString(index++, objectType.name());
dbStat.setString(index++, userId);
if (settingIds != null) {
for (String settingId : settingIds) {
dbStat.setString(index++, settingId);
}
}
dbStat.executeUpdate();
}
} catch (SQLException e) {
throw new DBCException("Error while deleting object settings", e);
}
deleteObjectSettings(objectId, objectType, userId, settingIds);
}
protected boolean isSubjectExists(String subjectId) throws DBCException {
@@ -1359,6 +1289,112 @@ public class CBEmbeddedSecurityController<T extends ServletAuthApplication>
}
}
@NotNull
@Override
public Map<String, Object> getObjectSettings(
@NotNull String objectId,
@NotNull SMObjectType objectType,
@Nullable String subjectId,
@Nullable Set<String> settingIds
) throws DBException {
try (Connection dbCon = database.openConnection()) {
try (
PreparedStatement dbStat = dbCon.prepareStatement("SELECT SETTING_ID,SETTING_VALUE " +
"FROM {table_prefix}CB_OBJECT_SETTINGS " +
"WHERE OBJECT_ID=? AND OBJECT_TYPE=? "
+ subjectId == null ? "" : " AND SUBJECT_ID=?" +
(CommonUtils.isEmpty(settingIds) ? "" : " AND SETTING_ID IN (" + SQLUtils.generateParamList(settingIds.size()) + ")"))
) {
int index = 1;
dbStat.setString(index++, objectId);
dbStat.setString(index++, objectType.name());
if (subjectId != null) {
dbStat.setString(index++, subjectId);
}
if (!CommonUtils.isEmpty(settingIds)) {
for (String settingId : settingIds) {
dbStat.setString(index++, settingId);
}
}
try (ResultSet dbResult = dbStat.executeQuery()) {
Map<String, Object> result = new LinkedHashMap<>();
while (dbResult.next()) {
result.put(
dbResult.getString(1),
dbResult.getString(2)
);
}
return result;
}
}
} catch (SQLException e) {
throw new DBCException("Error while getting object settings", e);
}
}
@Override
public void setObjectSettings(
@NotNull String objectId,
@NotNull SMObjectType objectType,
@NotNull String subjectId,
@NotNull Map<String, Object> settings
) throws DBException {
try (Connection dbCon = database.openConnection()) {
try (JDBCTransaction txn = new JDBCTransaction(dbCon)) {
deleteObjectSettings(objectId, objectType, settings.keySet());
try (
PreparedStatement dbStat = dbCon.prepareStatement(
"INSERT INTO {table_prefix}CB_OBJECT_SETTINGS" +
"(OBJECT_ID,OBJECT_TYPE,SUBJECT_ID,SETTING_ID,SETTING_VALUE,UPDATED_BY,UPDATE_TIME) " +
"VALUES(?,?,?,?,?,?,CURRENT_TIMESTAMP)")
) {
for (Map.Entry<String, Object> entry : settings.entrySet()) {
dbStat.setString(1, objectId);
dbStat.setString(2, objectType.name());
dbStat.setString(3, subjectId);
dbStat.setString(4, entry.getKey());
dbStat.setString(5, CommonUtils.toString(entry.getValue()));
dbStat.setString(6, subjectId);
dbStat.addBatch();
}
dbStat.executeBatch();
}
txn.commit();
}
} catch (SQLException e) {
throw new DBCException("Error while adding object settings", e);
}
}
@Override
public void deleteObjectSettings(
@NotNull String objectId,
@NotNull SMObjectType objectType,
@NotNull String subjectId,
@Nullable Set<String> settingIds
) throws DBException {
String sql = "DELETE FROM {table_prefix}CB_OBJECT_SETTINGS WHERE OBJECT_ID=? AND OBJECT_TYPE=? AND SUBJECT_ID=?";
if (settingIds != null && !settingIds.isEmpty()) {
sql += " AND SETTING_ID IN (" + SQLUtils.generateParamList(settingIds.size()) + ")";
}
try (Connection dbCon = database.openConnection()) {
try (PreparedStatement dbStat = dbCon.prepareStatement(sql)) {
int index = 1;
dbStat.setString(index++, objectId);
dbStat.setString(index++, objectType.name());
dbStat.setString(index++, subjectId);
if (settingIds != null) {
for (String settingId : settingIds) {
dbStat.setString(index++, settingId);
}
}
dbStat.executeUpdate();
}
} catch (SQLException e) {
throw new DBCException("Error while deleting object settings", e);
}
}
@NotNull
private SMTeam fetchTeam(ResultSet dbResult) throws SQLException {
return new SMTeam(