diff --git a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBApplication.java b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBApplication.java index 97af6a947c..f8919a5b32 100644 --- a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBApplication.java +++ b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBApplication.java @@ -22,6 +22,7 @@ import io.cloudbeaver.WebServiceUtils; import io.cloudbeaver.auth.CBAuthConstants; import io.cloudbeaver.auth.NoAuthCredentialsProvider; +import io.cloudbeaver.service.security.CBEmbeddedSecurityController; import io.cloudbeaver.service.security.PasswordPolicyConfiguration; import io.cloudbeaver.model.app.BaseWebApplication; import io.cloudbeaver.model.app.WebAuthApplication; @@ -370,6 +371,11 @@ public boolean implies(ProtectionDomain domain, Permission permission) { }); System.setSecurityManager(new SecurityManager()); } + try { + addAllUsersToDefaultTeam(); + } catch (DBException e) { + log.error("Failed insert default teams"); + } eventController.scheduleCheckJob(); @@ -380,6 +386,12 @@ public boolean implies(ProtectionDomain domain, Permission permission) { return; } + private void addAllUsersToDefaultTeam() throws DBException { + if (securityController instanceof CBEmbeddedSecurityController controller) { + controller.addAllUsersToDefaultTeam(); + } + } + protected void initializeAdditionalConfiguration() { } 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 faf058e162..a3c52855d6 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 @@ -210,7 +210,6 @@ public void deleteUser(String userId) throws DBCException { application.getEventController().addEvent(event); } - @Override public void setUserTeams(String userId, String[] teamIds, String grantorId) throws DBCException { try (Connection dbCon = database.openConnection()) { try (JDBCTransaction txn = new JDBCTransaction(dbCon)) { @@ -230,6 +229,10 @@ public void setUserTeams(@NotNull Connection dbCon, String userId, String[] team database.normalizeTableNames("DELETE FROM {table_prefix}CB_USER_TEAM WHERE USER_ID=?"), userId ); + String defaultUserTeam = application.getAppConfiguration().getDefaultUserTeam(); + if (CommonUtils.isNotEmpty(defaultUserTeam) && !ArrayUtils.contains(teamIds, defaultUserTeam)) { + teamIds = ArrayUtils.add(String.class, teamIds, defaultUserTeam); + } if (!ArrayUtils.isEmpty(teamIds)) { try (PreparedStatement dbStat = dbCon.prepareStatement( database.normalizeTableNames("INSERT INTO {table_prefix}CB_USER_TEAM" + @@ -246,6 +249,51 @@ public void setUserTeams(@NotNull Connection dbCon, String userId, String[] team } } + public void addAllUsersToDefaultTeam() throws DBCException { + if (application.isConfigurationMode()) { + return; + } + if (CommonUtils.isEmpty(application.getAppConfiguration().getDefaultUserTeam())) { + return; + } + + try (Connection dbCon = database.openConnection()) { + try (PreparedStatement dbStat = dbCon.prepareStatement( + database.normalizeTableNames("SELECT USER_ID \n" + + "FROM {table_prefix}CB_USER\n" + + "WHERE USER_ID NOT IN (\n" + + " SELECT USER_ID FROM {table_prefix}CB_USER_TEAM CUT WHERE CUT.TEAM_ID = ? \n" + + ")") + )) { + dbStat.setString(1, application.getAppConfiguration().getDefaultUserTeam()); + ResultSet dbResult = dbStat.executeQuery(); + List usersIds = new ArrayList<>(); + while (dbResult.next()) { + String userId = dbResult.getString(1); + usersIds.add(userId); + } + + if (usersIds.isEmpty()) { + return; + } + + for (String usersId : usersIds) { + try (PreparedStatement insertStat = dbCon.prepareStatement( + database.normalizeTableNames("INSERT INTO {table_prefix}CB_USER_TEAM(USER_ID, TEAM_ID, GRANT_TIME, GRANTED_BY)" + + " VALUES(?,?,?,?)"))) { + insertStat.setString(1, usersId); + insertStat.setString(2, application.getAppConfiguration().getDefaultUserTeam()); + insertStat.setTimestamp(3, new Timestamp(System.currentTimeMillis())); + insertStat.setString(4, "CloudBeaver Application"); + insertStat.executeUpdate(); + } + } + } + } catch (SQLException e) { + throw new DBCException("Error while setting default user teams", e); + } + } + @NotNull @Override diff --git a/webapp/packages/core-blocks/src/ResourcesHooks/useResource.ts b/webapp/packages/core-blocks/src/ResourcesHooks/useResource.ts index dee7488790..3f98b5b492 100644 --- a/webapp/packages/core-blocks/src/ResourcesHooks/useResource.ts +++ b/webapp/packages/core-blocks/src/ResourcesHooks/useResource.ts @@ -162,7 +162,9 @@ export function useResource< } if (key === null || propertiesRef.key === null || !propertiesRef.resource.isEqual(key, propertiesRef.key)) { - propertiesRef.key = key; + if (propertiesRef.key !== key) { + propertiesRef.key = key; + } } }); diff --git a/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/GrantedUsers/GrantedUsers.tsx b/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/GrantedUsers/GrantedUsers.tsx index 6e15fd5ebe..4977c9cb6e 100644 --- a/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/GrantedUsers/GrantedUsers.tsx +++ b/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/GrantedUsers/GrantedUsers.tsx @@ -23,6 +23,7 @@ import { useTranslate, } from '@cloudbeaver/core-blocks'; import { CachedResourceOffsetPageListKey } from '@cloudbeaver/core-resource'; +import { ServerConfigResource } from '@cloudbeaver/core-root'; import { TabContainerPanelComponent, useTab } from '@cloudbeaver/core-ui'; import type { ITeamFormProps } from '../ITeamFormProps'; @@ -38,20 +39,33 @@ export const GrantedUsers: TabContainerPanelComponent = observer const state = useGrantedUsers(formState.config, formState.mode); const { selected } = useTab(tabId); + const serverConfigResource = useResource(UserList, ServerConfigResource, undefined, { active: selected }); + const isDefaultTeam = formState.config.teamId === serverConfigResource.data?.defaultUserTeam; + const users = useResource(GrantedUsers, UsersResource, CachedResourceOffsetPageListKey(0, 1000).setTarget(UsersResourceFilterKey()), { - active: selected, + active: selected && !isDefaultTeam, }); const grantedUsers = getComputed(() => users.data.filter((user): user is AdminUser => !!user && state.state.grantedUsers.includes(user.userId)), ); - useAutoLoad(GrantedUsers, state, selected && !state.state.loaded); + useAutoLoad(GrantedUsers, state, selected && !state.state.loaded && !isDefaultTeam); if (!selected) { return null; } + if (isDefaultTeam) { + return ( + + + {translate('plugin_authentication_administration_team_default_users_tooltip')} + + + ); + } + return ( {() => ( diff --git a/webapp/packages/plugin-authentication-administration/src/Administration/Users/UserForm/Info/UserFormInfoPart.ts b/webapp/packages/plugin-authentication-administration/src/Administration/Users/UserForm/Info/UserFormInfoPart.ts index a290bb432b..b51fd1ea33 100644 --- a/webapp/packages/plugin-authentication-administration/src/Administration/Users/UserForm/Info/UserFormInfoPart.ts +++ b/webapp/packages/plugin-authentication-administration/src/Administration/Users/UserForm/Info/UserFormInfoPart.ts @@ -174,7 +174,7 @@ export class UserFormInfoPart extends FormPart(function UserFormInfoTeams({ formState, tabState, tabSelected, disabled }) { const translate = useTranslate(); + const serverConfigResource = useResource(UserFormInfoTeams, ServerConfigResource, undefined); const teamsLoader = useResource(UserFormInfoTeams, TeamsResource, CachedMapAllKey, { active: tabSelected }); const teams = teamsLoader.data.filter(isDefined).sort(compareTeams); + const defaultTeam = serverConfigResource.data?.defaultUserTeam; + return ( <> {translate('authentication_user_team')} {teams.map(team => { + const isDefault = team.teamId === defaultTeam; const label = `${team.teamId}${team.teamName && team.teamName !== team.teamId ? ' (' + team.teamName + ')' : ''}`; const tooltip = `${label}${team.description ? '\n' + team.description : ''}`; + return ( - {label} - + /> ); })} diff --git a/webapp/packages/plugin-authentication-administration/src/locales/en.ts b/webapp/packages/plugin-authentication-administration/src/locales/en.ts index 66863c4cf0..ac61b31d33 100644 --- a/webapp/packages/plugin-authentication-administration/src/locales/en.ts +++ b/webapp/packages/plugin-authentication-administration/src/locales/en.ts @@ -129,4 +129,7 @@ export default [ ['administration_teams_team_granted_connections_tab_title', 'Connections'], ['administration_teams_team_granted_connections_search_placeholder', 'Search for connection name...'], ['administration_teams_team_granted_connections_empty', 'No available connections'], + + ['plugin_authentication_administration_user_team_default_readonly_tooltip', "Default team. Can't be revoked"], + ['plugin_authentication_administration_team_default_users_tooltip', 'Default team. Contains all users'], ]; diff --git a/webapp/packages/plugin-authentication-administration/src/locales/it.ts b/webapp/packages/plugin-authentication-administration/src/locales/it.ts index 7aca35ca6b..73f71115cb 100644 --- a/webapp/packages/plugin-authentication-administration/src/locales/it.ts +++ b/webapp/packages/plugin-authentication-administration/src/locales/it.ts @@ -74,4 +74,7 @@ export default [ 'administration_configuration_wizard_configuration_authentication_description', "Permetti agli utenti di autenticarsi. In alternativa solo l'accesso anonimo sarà attivo", ], + + ['plugin_authentication_administration_user_team_default_readonly_tooltip', "Default team. Can't be revoked"], + ['plugin_authentication_administration_team_default_users_tooltip', 'Default team. Contains all users'], ]; diff --git a/webapp/packages/plugin-authentication-administration/src/locales/ru.ts b/webapp/packages/plugin-authentication-administration/src/locales/ru.ts index 33a1144dea..d67eba8146 100644 --- a/webapp/packages/plugin-authentication-administration/src/locales/ru.ts +++ b/webapp/packages/plugin-authentication-administration/src/locales/ru.ts @@ -134,4 +134,7 @@ export default [ ['administration_teams_team_granted_connections_tab_title', 'Подключения'], ['administration_teams_team_granted_connections_search_placeholder', 'Поиск по названию подключения...'], ['administration_teams_team_granted_connections_empty', 'Нет доступных подключений'], + + ['plugin_authentication_administration_user_team_default_readonly_tooltip', 'Команда по умолчанию. Не может быть отозвана'], + ['plugin_authentication_administration_team_default_users_tooltip', 'Команда по умолчанию. Содержит всех пользователей'], ]; diff --git a/webapp/packages/plugin-authentication-administration/src/locales/zh.ts b/webapp/packages/plugin-authentication-administration/src/locales/zh.ts index 9b8ec0583f..fb47f419ed 100644 --- a/webapp/packages/plugin-authentication-administration/src/locales/zh.ts +++ b/webapp/packages/plugin-authentication-administration/src/locales/zh.ts @@ -111,4 +111,7 @@ export default [ ['administration_teams_team_granted_connections_tab_title', '连接'], ['administration_teams_team_granted_connections_search_placeholder', '搜索连接名称...'], ['administration_teams_team_granted_connections_empty', '没有可用连接'], + + ['plugin_authentication_administration_user_team_default_readonly_tooltip', "Default team. Can't be revoked"], + ['plugin_authentication_administration_team_default_users_tooltip', 'Default team. Contains all users'], ];