Skip to content

Commit

Permalink
Merge branch 'devel' into CB-5640-update-fileds-ui-for-dark-and-light…
Browse files Browse the repository at this point in the history
…-themes
  • Loading branch information
EvgeniaBzzz authored Oct 10, 2024
2 parents c1221fb + 2e5b092 commit 178f7e7
Show file tree
Hide file tree
Showing 23 changed files with 178 additions and 146 deletions.
4 changes: 2 additions & 2 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,10 @@
"label": "Build CE",
"type": "shell",
"windows": {
"command": "./build-sqlite.bat"
"command": "./build.bat"
},
"osx": {
"command": "./build-sqlite.sh"
"command": "./build.sh"
},
"options": {
"cwd": "${workspaceFolder}/deploy"
Expand Down
24 changes: 2 additions & 22 deletions config/GlobalConfiguration/.dbeaver/data-sources.json
Original file line number Diff line number Diff line change
@@ -1,24 +1,4 @@
{
"folders": {},
"connections": {
"postgresql-template-1": {
"provider": "postgresql",
"driver": "postgres-jdbc",
"name": "PostgreSQL (Template)",
"save-password": false,
"show-system-objects": false,
"read-only": true,
"template": true,
"configuration": {
"host": "localhost",
"port": "5432",
"database": "postgres",
"url": "jdbc:postgresql://localhost:5432/postgres",
"type": "dev",
"provider-properties": {
"@dbeaver-show-non-default-db@": "false"
}
}
}
}
"folders": {},
"connections": {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ public List<BaseProjectImpl> getProjects() {
@Nullable
@Override
public BaseProjectImpl getProject(@NotNull String projectName) {
if (globalProject.getId().equals(projectName)) {
if (globalProject != null && globalProject.getId().equals(projectName)) {
return globalProject;
}
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,100 +19,162 @@
import io.cloudbeaver.WebSessionGlobalProjectImpl;
import io.cloudbeaver.model.session.BaseWebSession;
import io.cloudbeaver.model.session.WebSession;
import io.cloudbeaver.server.CBApplication;
import io.cloudbeaver.server.CBPlatform;
import io.cloudbeaver.service.security.SMUtils;
import io.cloudbeaver.utils.WebAppUtils;
import org.jkiss.code.NotNull;
import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.model.security.SMObjectType;
import org.jkiss.dbeaver.model.security.SMAdminController;
import org.jkiss.dbeaver.model.security.SMObjectPermissionsGrant;
import org.jkiss.dbeaver.model.websocket.event.WSEventType;
import org.jkiss.dbeaver.model.websocket.event.WSProjectUpdateEvent;
import org.jkiss.dbeaver.model.websocket.event.datasource.WSDataSourceEvent;
import org.jkiss.dbeaver.model.websocket.event.datasource.WSDataSourceProperty;
import org.jkiss.dbeaver.model.websocket.event.permissions.WSObjectPermissionEvent;

import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Consumer;
import java.util.stream.Collectors;

public class WSObjectPermissionUpdatedEventHandler extends WSDefaultEventHandler<WSObjectPermissionEvent> {
private static final Log log = Log.getLog(WSObjectPermissionUpdatedEventHandler.class);

@Override
protected void updateSessionData(@NotNull BaseWebSession activeUserSession, @NotNull WSObjectPermissionEvent event) {
try {
public void handleEvent(@NotNull WSObjectPermissionEvent event) {
String objectId = event.getObjectId();
Consumer<BaseWebSession> runnable = switch (event.getSmObjectType()) {
case project:
yield getUpdateUserProjectsInfoConsumer(event, objectId);
case datasource:
try {
SMAdminController smController = CBApplication.getInstance().getSecurityController();
Set<String> dataSourcePermissions = smController.getObjectPermissionGrants(event.getObjectId(), event.getSmObjectType())
.stream()
.map(SMObjectPermissionsGrant::getSubjectId).collect(Collectors.toSet());
yield getUpdateUserDataSourcesInfoConsumer(event, objectId, dataSourcePermissions);
} catch (DBException e) {
log.error("Error getting permissions for data source " + objectId, e);
yield null;
}
};
if (runnable == null) {
return;
}
log.debug(event.getTopicId() + " event handled");
Collection<BaseWebSession> allSessions = CBPlatform.getInstance().getSessionManager().getAllActiveSessions();
for (var activeUserSession : allSessions) {
if (!isAcceptableInSession(activeUserSession, event)) {
log.debug("Cannot handle %s event '%s' in session %s".formatted(
event.getTopicId(),
event.getId(),
activeUserSession.getSessionId()
));
continue;
}
log.debug("%s event '%s' handled".formatted(event.getTopicId(), event.getId()));
runnable.accept(activeUserSession);
}
}

@NotNull
private Consumer<BaseWebSession> getUpdateUserDataSourcesInfoConsumer(
@NotNull WSObjectPermissionEvent event,
@NotNull String dataSourceId,
@NotNull Set<String> dataSourcePermissions
) {
return (activeUserSession) -> {
// we have accessible data sources only in web session
if (event.getSmObjectType() == SMObjectType.datasource && !(activeUserSession instanceof WebSession)) {
// admins already have access for all shared connections
if (!(activeUserSession instanceof WebSession webSession) || SMUtils.isAdmin(webSession)) {
return;
}
var objectId = event.getObjectId();

boolean isAccessibleNow;
switch (event.getSmObjectType()) {
case project:
if (WSEventType.OBJECT_PERMISSIONS_UPDATED.getEventId().equals(event.getId())) {
var accessibleProjectIds = activeUserSession.getUserContext().getAccessibleProjectIds();
if (accessibleProjectIds.contains(event.getObjectId())) {
return;
}
activeUserSession.addSessionProject(objectId);
activeUserSession.addSessionEvent(
WSProjectUpdateEvent.create(
event.getSessionId(),
event.getUserId(),
objectId
)
);
} else if (WSEventType.OBJECT_PERMISSIONS_DELETED.getEventId().equals(event.getId())) {
activeUserSession.removeSessionProject(objectId);
activeUserSession.addSessionEvent(
WSProjectUpdateEvent.delete(
event.getSessionId(),
event.getUserId(),
objectId
)
);
}
break;
case datasource:
var webSession = (WebSession) activeUserSession;
var dataSources = List.of(objectId);
if (!isAcceptableInSession(webSession, event)) {
return;
}
var user = activeUserSession.getUserContext().getUser();
var userSubjects = new HashSet<>(Set.of(user.getTeams()));
userSubjects.add(user.getUserId());
boolean shouldBeAccessible = dataSourcePermissions.stream().anyMatch(userSubjects::contains);
List<String> dataSources = List.of(dataSourceId);
WebSessionGlobalProjectImpl project = webSession.getGlobalProject();
if (project == null) {
log.error("Project " + WebAppUtils.getGlobalProjectId() +
" is not found in session " + activeUserSession.getSessionId());
return;
}
boolean isAccessibleNow = project.findWebConnectionInfo(dataSourceId) != null;
if (WSEventType.OBJECT_PERMISSIONS_UPDATED.getEventId().equals(event.getId())) {
if (isAccessibleNow || !shouldBeAccessible) {
return;
}
project.addAccessibleConnectionToCache(dataSourceId);
webSession.addSessionEvent(
WSDataSourceEvent.create(
event.getSessionId(),
event.getUserId(),
project.getId(),
dataSources,
WSDataSourceProperty.CONFIGURATION
)
);
} else if (WSEventType.OBJECT_PERMISSIONS_DELETED.getEventId().equals(event.getId())) {
if (!isAccessibleNow || shouldBeAccessible) {
return;
}
project.removeAccessibleConnectionFromCache(dataSourceId);
webSession.addSessionEvent(
WSDataSourceEvent.delete(
event.getSessionId(),
event.getUserId(),
project.getId(),
dataSources,
WSDataSourceProperty.CONFIGURATION
)
);
}
};
}

WebSessionGlobalProjectImpl project = webSession.getGlobalProject();
if (project == null) {
log.error("Project " + WebAppUtils.getGlobalProjectId() +
" is not found in session " + activeUserSession.getSessionId());
@NotNull
private Consumer<BaseWebSession> getUpdateUserProjectsInfoConsumer(
@NotNull WSObjectPermissionEvent event,
@NotNull String projectId
) {
return (activeUserSession) -> {
try {
if (WSEventType.OBJECT_PERMISSIONS_UPDATED.getEventId().equals(event.getId())) {
var accessibleProjectIds = activeUserSession.getUserContext().getAccessibleProjectIds();
if (accessibleProjectIds.contains(event.getObjectId())) {
return;
}
if (WSEventType.OBJECT_PERMISSIONS_UPDATED.getEventId().equals(event.getId())) {
isAccessibleNow = project.findWebConnectionInfo(objectId) != null;
if (isAccessibleNow) {
return;
}
project.addAccessibleConnectionToCache(objectId);
webSession.addSessionEvent(
WSDataSourceEvent.create(
event.getSessionId(),
event.getUserId(),
project.getId(),
dataSources,
WSDataSourceProperty.CONFIGURATION
)
);
} else if (WSEventType.OBJECT_PERMISSIONS_DELETED.getEventId().equals(event.getId())) {
project.removeAccessibleConnectionFromCache(objectId);
webSession.addSessionEvent(
WSDataSourceEvent.delete(
event.getSessionId(),
event.getUserId(),
project.getId(),
dataSources,
WSDataSourceProperty.CONFIGURATION
)
);
}
activeUserSession.addSessionProject(projectId);
activeUserSession.addSessionEvent(
WSProjectUpdateEvent.create(
event.getSessionId(),
event.getUserId(),
projectId
)
);
} else if (WSEventType.OBJECT_PERMISSIONS_DELETED.getEventId().equals(event.getId())) {
activeUserSession.removeSessionProject(projectId);
activeUserSession.addSessionEvent(
WSProjectUpdateEvent.delete(
event.getSessionId(),
event.getUserId(),
projectId
)
);
}
} catch (DBException e) {
log.error("Error on changing permissions for project " +
event.getObjectId() + " in session " + activeUserSession.getSessionId(), e);
}
} catch (DBException e) {
log.error("Error on changing permissions for project " +
event.getObjectId() + " in session " + activeUserSession.getSessionId(), e);
}
};
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -198,8 +198,7 @@ private void getObjectFeatures(DBSObject object, List<String> features) {
features.add(OBJECT_FEATURE_OBJECT_CONTAINER);
try {
Class<? extends DBSObject> childType = objectContainer.getPrimaryChildType(null);
Collection<? extends DBSObject> childrenCollection = objectContainer.getChildren(session.getProgressMonitor());
if (DBSTable.class.isAssignableFrom(childType) && childrenCollection != null) {
if (DBSTable.class.isAssignableFrom(childType)) {
features.add(OBJECT_FEATURE_ENTITY_CONTAINER);
}
} catch (Exception e) {
Expand Down
7 changes: 0 additions & 7 deletions webapp/packages/core-blocks/src/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,12 +72,6 @@ export const Button = observer<ButtonProps>(function Button({
['click'],
);

function handleEnter(event: React.KeyboardEvent<HTMLElement>) {
if (event.key === 'Enter') {
event.currentTarget.click();
}
}

loading = state.loading || loading;

if (loading) {
Expand All @@ -89,7 +83,6 @@ export const Button = observer<ButtonProps>(function Button({
<Button
role="button"
tabIndex={0}
onKeyDown={handleEnter}
{...rest}
type={type}
disabled={disabled}
Expand Down
7 changes: 7 additions & 0 deletions webapp/packages/core-blocks/src/InfoItem.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,15 @@
align-items: center;
flex: 0 0 auto;
}

.iconOrImage {
width: 24px;
height: 24px;
margin-right: 16px;

&.compact {
width: 18px;
height: 18px;
margin-right: 8px;
}
}
5 changes: 3 additions & 2 deletions webapp/packages/core-blocks/src/InfoItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,20 @@ import { useS } from './useS.js';
export interface IInfoItem {
info: TLocalizationToken;
icon?: string;
compact?: boolean;
}

interface Props extends IInfoItem {
className?: string;
}

export const InfoItem = observer<Props>(function InfoItem({ info, icon = '/icons/info_icon.svg', className }) {
export const InfoItem = observer<Props>(function InfoItem({ info, compact, icon = '/icons/info_icon.svg', className }) {
const styles = useS(style);

const translate = useTranslate();
return (
<div className={s(styles, { infoItem: true }, className)}>
<IconOrImage className={s(styles, { iconOrImage: true })} icon={icon} />
<IconOrImage className={s(styles, { iconOrImage: true, compact })} icon={icon} />
{translate(info)}
</div>
);
Expand Down
1 change: 1 addition & 0 deletions webapp/packages/core-connections/src/locales/de.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,5 @@ export default [

['core_connections_settings_disable', 'Disable'],
['core_connections_settings_disable_description', 'Disable the ability to create new connections'],
['connections_templates_deprecated_message', 'Template connections are deprecated and will be removed in future releases'],
];
1 change: 1 addition & 0 deletions webapp/packages/core-connections/src/locales/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,4 +102,5 @@ export default [

['core_connections_settings_disable', 'Disable'],
['core_connections_settings_disable_description', 'Disable the ability to create new connections'],
['connections_templates_deprecated_message', 'Template connections are deprecated and will be removed in future releases'],
];
1 change: 1 addition & 0 deletions webapp/packages/core-connections/src/locales/fr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,4 +111,5 @@ export default [

['core_connections_settings_disable', 'Disable'],
['core_connections_settings_disable_description', 'Disable the ability to create new connections'],
['connections_templates_deprecated_message', 'Template connections are deprecated and will be removed in future releases'],
];
1 change: 1 addition & 0 deletions webapp/packages/core-connections/src/locales/it.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,4 +100,5 @@ export default [

['core_connections_settings_disable', 'Disable'],
['core_connections_settings_disable_description', 'Disable the ability to create new connections'],
['connections_templates_deprecated_message', 'Template connections are deprecated and will be removed in future releases'],
];
1 change: 1 addition & 0 deletions webapp/packages/core-connections/src/locales/ru.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,4 +103,5 @@ export default [

['core_connections_settings_disable', 'Отключить'],
['core_connections_settings_disable_description', 'Отключить возможность создания новых подключений'],
['connections_templates_deprecated_message', 'Шаблоны подключений больше не поддерживаются и будут удалены в будущих релизах'],
];
Loading

0 comments on commit 178f7e7

Please sign in to comment.