Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CB-4535. Remove Ability to edit all users team #2341

Merged
merged 20 commits into from
Feb 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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();

Expand All @@ -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() {

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,6 @@
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)) {
Expand All @@ -230,6 +229,10 @@
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" +
Expand All @@ -246,6 +249,51 @@
}
}

public void addAllUsersToDefaultTeam() throws DBCException {

Check warning on line 252 in server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/service/security/CBEmbeddedSecurityController.java

View check run for this annotation

Jenkins-CI-integration / CheckStyle Java Report

server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/service/security/CBEmbeddedSecurityController.java#L252

Missing a Javadoc comment.
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<String> 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)" +

Check warning on line 282 in server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/service/security/CBEmbeddedSecurityController.java

View check run for this annotation

Jenkins-CI-integration / CheckStyle Java Report

server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/service/security/CBEmbeddedSecurityController.java#L282

Line is longer than 140 characters (found 141).
" 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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -38,20 +39,33 @@ export const GrantedUsers: TabContainerPanelComponent<ITeamFormProps> = 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<AdminUser>((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 (
<ColoredContainer className={s(styles, { box: true })} parent gap vertical>
<Group className={s(styles, { placeholderBox: true })} keepSize large>
<TextPlaceholder>{translate('plugin_authentication_administration_team_default_users_tooltip')}</TextPlaceholder>
</Group>
</ColoredContainer>
);
}

return (
<Loader className={s(styles, { loader: true })} state={[state.state]}>
{() => (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ export class UserFormInfoPart extends FormPart<IUserFormInfoState, IUserFormStat
let grantedTeams: string[] = [];

if (this.state.userId) {
grantedTeams = this.usersResource.get(this.state.userId)?.grantedTeams ?? [];
grantedTeams = toJS(this.usersResource.get(this.state.userId)?.grantedTeams ?? []);
}

if (isArraysEqual(this.state.teams, grantedTeams)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { observer } from 'mobx-react-lite';
import { compareTeams, TeamsResource } from '@cloudbeaver/core-authentication';
import { FieldCheckbox, Group, GroupTitle, useResource, useTranslate } from '@cloudbeaver/core-blocks';
import { CachedMapAllKey } from '@cloudbeaver/core-resource';
import { ServerConfigResource } from '@cloudbeaver/core-root';
import { isDefined } from '@cloudbeaver/core-utils';

import type { UserFormProps } from '../AdministrationUserFormService';
Expand All @@ -23,27 +24,33 @@ interface Props extends UserFormProps {

export const UserFormInfoTeams = observer<Props>(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 (
<>
<GroupTitle>{translate('authentication_user_team')}</GroupTitle>
<Group boxNoOverflow gap dense>
{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 (
<FieldCheckbox
key={team.teamId}
id={`${formState.id}_${team.teamId}`}
title={tooltip}
label={label}
name="teams"
state={tabState.state}
value={team.teamId}
caption={isDefault ? translate('plugin_authentication_administration_user_team_default_readonly_tooltip') : undefined}
readOnly={isDefault}
disabled={disabled}
>
{label}
</FieldCheckbox>
/>
);
})}
</Group>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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'],
];
Original file line number Diff line number Diff line change
Expand Up @@ -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'],
];
Original file line number Diff line number Diff line change
Expand Up @@ -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', 'Команда по умолчанию. Содержит всех пользователей'],
];
Original file line number Diff line number Diff line change
Expand Up @@ -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'],
];
Loading