Merge remote-tracking branch 'origin/devel' into CB-2194-support-events-pulling

This commit is contained in:
Wroud
2022-10-14 17:36:17 +03:00
143 changed files with 1715 additions and 1592 deletions
+6
View File
@@ -22,6 +22,12 @@ You can see live demo of CloudBeaver here: https://demo.cloudbeaver.io
## Changelog
### CloudBeaver 22.2.2 - 2022-10-10
- Administrators now:
- have permission to create connections in both projects, Shared and Private, when it’s restricted for other users,
- can enable a reverse proxy for user authentication in the Administration.
- Different bugs have been fixed.
### CloudBeaver 22.2.1 - 2022-09-26
- Connection:
+3 -3
View File
@@ -1,13 +1,13 @@
{
roles: [
teams: [
{
roleId: "admin",
teamId: "admin",
name: "Admin",
description: "Administrative access. Has all permissions.",
permissions: [ "public", "admin" ]
},
{
roleId: "user",
teamId: "user",
name: "User",
description: "Standard user",
permissions: [ "public" ]
+1 -1
View File
@@ -1,4 +1,4 @@
FROM eclipse-temurin:11.0.14.1_1-jre-focal
FROM eclipse-temurin:17.0.4.1_1-jre
#adoptopenjdk/openjdk11:jdk-11.0.12_7-ubuntu-slim
COPY cloudbeaver /opt/cloudbeaver
@@ -26,30 +26,30 @@ import java.util.LinkedHashMap;
import java.util.Map;
public abstract class BaseWebAppConfiguration implements WebAppConfiguration {
public static final String DEFAULT_APP_ANONYMOUS_ROLE_NAME = "user";
public static final String DEFAULT_APP_ANONYMOUS_TEAM_NAME = "user";
protected final Map<String, Object> plugins;
protected String defaultUserRole;
protected String defaultUserTeam;
protected boolean resourceManagerEnabled;
protected String[] enabledFeatures;
public BaseWebAppConfiguration() {
this.plugins = new LinkedHashMap<>();
this.defaultUserRole = DEFAULT_APP_ANONYMOUS_ROLE_NAME;
this.defaultUserTeam = DEFAULT_APP_ANONYMOUS_TEAM_NAME;
this.resourceManagerEnabled = true;
this.enabledFeatures = null;
}
public BaseWebAppConfiguration(BaseWebAppConfiguration src) {
this.plugins = new LinkedHashMap<>(src.plugins);
this.defaultUserRole = src.defaultUserRole;
this.defaultUserTeam = src.defaultUserTeam;
this.resourceManagerEnabled = src.resourceManagerEnabled;
this.enabledFeatures = src.enabledFeatures;
}
@Override
public String getDefaultUserRole() {
return defaultUserRole;
public String getDefaultUserTeam() {
return defaultUserTeam;
}
@Override
@@ -24,13 +24,13 @@ import java.util.Map;
* Application configuration
*/
public interface WebAppConfiguration {
String getAnonymousUserRole();
String getAnonymousUserTeam();
boolean isAnonymousAccessEnabled();
<T> T getResourceQuota(String quotaId);
String getDefaultUserRole();
String getDefaultUserTeam();
<T> T getPluginOption(@NotNull String pluginId, @NotNull String option);
@@ -167,6 +167,7 @@ public class LocalResourceController implements RMController {
RMProjectType.SHARED, true)
)
.filter(Objects::nonNull)
.sorted(Comparator.comparing(RMProject::getDisplayName))
.collect(Collectors.toList());
}
@@ -364,6 +365,7 @@ public class LocalResourceController implements RMController {
) throws IOException {
try (Stream<Path> files = Files.list(folderPath)) {
return files.filter(path -> !path.getFileName().toString().startsWith(".")) // skip hidden files
.sorted(Comparator.comparing(path -> path.getFileName().toString(), String.CASE_INSENSITIVE_ORDER))
.map((Path path) -> makeResourceFromPath(projectId, path, readProperties, readHistory, recursive))
.filter(Objects::nonNull)
.toArray(RMResource[]::new);
@@ -410,7 +410,7 @@ public class WebSession extends AbstractSessionPersistent
private Set<String> readAccessibleConnectionIds() {
WebUser user = getUser();
String subjectId = user == null ?
application.getAppConfiguration().getAnonymousUserRole() : user.getUserId();
application.getAppConfiguration().getAnonymousUserTeam() : user.getUserId();
try {
return getSecurityController()
@@ -161,7 +161,7 @@ public class WebSessionAuthProcessor {
providerConfig,
userCredentials);
if (!configMode && securityController.getUserPermissions(userId).isEmpty()) {
if (!configMode && securityController.getUserPermissions(userId, authInfo.getAuthRole()).isEmpty()) {
throw new DBWebException("Access denied (no permissions)");
}
if (!configMode && !securityController.getUserById(userId).isEnabled()) {
@@ -17,38 +17,26 @@
package io.cloudbeaver.model.user;
import org.jkiss.code.NotNull;
import org.jkiss.dbeaver.model.security.user.SMRole;
import org.jkiss.dbeaver.model.security.user.SMUser;
import java.util.*;
import java.util.Collections;
import java.util.Map;
/**
* Web user.
*/
public class WebUser {
@NotNull
private final String userId;
private final SMUser user;
private String displayName;
private final Map<String, String> metaParameters = new LinkedHashMap<>();
private final Map<String, Object> configurationParameters = new LinkedHashMap<>();
private boolean enabled;
private SMRole[] roles = null;
private String activeAuthModel;
private final Map<String, Map<String, Object>> authCredentials = new HashMap<>();
public WebUser(@NotNull SMUser smUser) {
this.userId = smUser.getUserId();
this.metaParameters.putAll(smUser.getMetaParameters());
this.enabled = smUser.isEnabled();
this.user = smUser;
}
@NotNull
public String getUserId() {
return userId;
return user.getUserId();
}
/**
@@ -63,61 +51,41 @@ public class WebUser {
}
public boolean getEnabled() {
return enabled;
return user.isEnabled();
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public String[] getGrantedRoles() {
return Arrays.stream(roles).map(SMRole::getRoleId).toArray(String[]::new);
}
public boolean hasRole(String roleId) {
return Arrays.stream(roles).anyMatch(r -> r.getRoleId().equals(roleId));
user.enableUser(enabled);
}
public Map<String, String> getMetaParameters() {
return Collections.unmodifiableMap(metaParameters);
}
public String getMetaParameter(String name) {
return metaParameters.get(name);
return Collections.unmodifiableMap(user.getMetaParameters());
}
public void setMetaParameter(String name, String value) {
metaParameters.put(name, value);
}
public void removeMetaParameter(String name) {
metaParameters.remove(name);
user.setMetaParameter(name, value);
}
public Map<String, Object> getConfigurationParameters() {
return Collections.unmodifiableMap(configurationParameters);
return Collections.emptyMap();
}
public SMRole[] getRoles() {
return roles;
}
public void setRoles(SMRole[] roles) {
this.roles = roles;
public String[] getTeams() {
return user.getUserTeams();
}
@Override
public int hashCode() {
return userId.hashCode();
return user.getUserId().hashCode();
}
@Override
public boolean equals(Object obj) {
return obj instanceof WebUser && ((WebUser) obj).userId.equals(this.userId);
return obj instanceof WebUser && ((WebUser) obj).user.getUserId().equals(this.user.getUserId());
}
@Override
public String toString() {
return userId;
return user.getUserId();
}
}
@@ -50,7 +50,9 @@ public class CBAppConfig extends BaseAuthWebAppConfiguration implements WebAuthC
private boolean redirectOnFederatedAuth;
private boolean anonymousAccessEnabled;
@Deprecated
private String anonymousUserRole;
private String anonymousUserTeam;
private String[] enabledDrivers;
private String[] disabledDrivers;
@@ -61,7 +63,8 @@ public class CBAppConfig extends BaseAuthWebAppConfiguration implements WebAuthC
public CBAppConfig() {
super();
this.anonymousAccessEnabled = false;
this.anonymousUserRole = DEFAULT_APP_ANONYMOUS_ROLE_NAME;
this.anonymousUserRole = DEFAULT_APP_ANONYMOUS_TEAM_NAME;
this.anonymousUserTeam = DEFAULT_APP_ANONYMOUS_TEAM_NAME;
this.supportsCustomConnections = true;
this.supportsConnectionBrowser = false;
this.supportsUserWorkspaces = false;
@@ -81,6 +84,7 @@ public class CBAppConfig extends BaseAuthWebAppConfiguration implements WebAuthC
super(src);
this.anonymousAccessEnabled = src.anonymousAccessEnabled;
this.anonymousUserRole = src.anonymousUserRole;
this.anonymousUserTeam = src.anonymousUserTeam;
this.supportsCustomConnections = src.supportsCustomConnections;
this.supportsConnectionBrowser = src.supportsConnectionBrowser;
this.supportsUserWorkspaces = src.supportsUserWorkspaces;
@@ -102,8 +106,8 @@ public class CBAppConfig extends BaseAuthWebAppConfiguration implements WebAuthC
}
@Override
public String getAnonymousUserRole() {
return anonymousUserRole;
public String getAnonymousUserTeam() {
return CommonUtils.notNull(anonymousUserTeam, anonymousUserRole);
}
public void setAnonymousAccessEnabled(boolean anonymousAccessEnabled) {
@@ -820,15 +820,15 @@ public class CBApplication extends BaseWebApplication implements WebAuthApplicat
private void grantAnonymousAccessToConnections(CBAppConfig appConfig, String adminName) {
try {
String anonymousRoleId = appConfig.getAnonymousUserRole();
String anonymousTeamId = appConfig.getAnonymousUserTeam();
var securityController = getSecurityController();
for (DBPDataSourceContainer ds : WebServiceUtils.getGlobalDataSourceRegistry().getDataSources()) {
var datasourcePermissions = securityController.getObjectPermissions(anonymousRoleId, ds.getId(), SMObjects.DATASOURCE);
var datasourcePermissions = securityController.getObjectPermissions(anonymousTeamId, ds.getId(), SMObjects.DATASOURCE);
if (CommonUtils.isEmpty(datasourcePermissions.getPermissions())) {
securityController.setObjectPermissions(
Set.of(ds.getId()),
SMObjects.DATASOURCE,
Set.of(anonymousRoleId),
Set.of(anonymousTeamId),
Set.of(SMConstants.DATA_SOURCE_ACCESS_PERMISSION),
adminName
);
@@ -58,7 +58,7 @@ public class CBConstants {
public static final String DEFAULT_WORKSPACE_LOCATION = DEFAULT_DEPLOY_LOCATION + "/workspace";
public static final String DEFAULT_PRODUCT_CONFIGURATION = "conf/product.conf";
public static final String DEFAULT_ADMIN_NAME = "cbadmin";
public static final String DEFAULT_ADMIN_ROLE = "admin";
public static final String DEFAULT_ADMIN_TEAM = "admin";
// Default max idle time (10 minutes)
public static final long MAX_SESSION_IDLE_TIME = 10 * 60 * 1000;
@@ -364,6 +364,10 @@ public class WebServiceCore implements DBWServiceCore {
webSession.addInfoMessage("Create new connection");
DBPDataSourceRegistry sessionRegistry = webSession.getProjectById(projectId).getDataSourceRegistry();
// we don't need to save credentials for templates
if (connectionConfig.isTemplate()) {
connectionConfig.setSaveCredentials(false);
}
DBPDataSourceContainer newDataSource = WebServiceUtils.createConnectionFromConfig(connectionConfig, sessionRegistry);
if (CommonUtils.isEmpty(newDataSource.getName())) {
newDataSource.setName(CommonUtils.notNull(connectionConfig.getName(), "NewConnection"));
@@ -82,7 +82,8 @@ public class WebNavigatorNodeInfo {
@Property
public String getProjectId() {
return node.getOwnerProject().getId();
DBPProject ownerProject = node.getOwnerProject();
return ownerProject == null ? null : ownerProject.getId();
}
@Property
@@ -1,7 +1,7 @@
enum AdminSubjectType {
user,
role
team
}
type AdminConnectionGrantInfo {
@@ -35,7 +35,7 @@ type AdminUserInfo {
metaParameters: Object!
configurationParameters: Object!
grantedRoles: [ID!]!
grantedTeams: [ID!]!
grantedConnections: [AdminConnectionGrantInfo!]!
origins: [ObjectOrigin!]!
@@ -44,15 +44,15 @@ type AdminUserInfo {
enabled: Boolean!
}
type AdminRoleInfo {
roleId: ID!
roleName: String
type AdminTeamInfo {
teamId: ID!
teamName: String
description: String
grantedUsers: [ID!]!
grantedConnections: [AdminConnectionGrantInfo!]!
rolePermissions: [ID!]!
teamPermissions: [ID!]!
}
type AdminPermissionInfo {
@@ -113,23 +113,23 @@ input ServerConfigInput {
extend type Query {
#### Users and roles
#### Users and teams
listUsers(userId: ID): [AdminUserInfo!]!
listRoles(roleId: ID): [AdminRoleInfo!]!
listTeams(teamId: ID): [AdminTeamInfo!]!
listPermissions: [AdminPermissionInfo!]!
createUser(userId: ID!, enabled: Boolean!): AdminUserInfo!
deleteUser(userId: ID!): Boolean
createRole(roleId: ID!, roleName: String, description: String): AdminRoleInfo!
updateRole(roleId: ID!, roleName: String, description: String): AdminRoleInfo!
deleteRole(roleId: ID!): Boolean
createTeam(teamId: ID!, teamName: String, description: String): AdminTeamInfo!
updateTeam(teamId: ID!, teamName: String, description: String): AdminTeamInfo!
deleteTeam(teamId: ID!): Boolean
grantUserRole(userId: ID!, roleId: ID!): Boolean
revokeUserRole(userId: ID!, roleId: ID!): Boolean
grantUserTeam(userId: ID!, teamId: ID!): Boolean
revokeUserTeam(userId: ID!, teamId: ID!): Boolean
setSubjectPermissions(roleId: ID!, permissions: [ID!]!): [AdminPermissionInfo!]!
setSubjectPermissions(subjectId: ID!, permissions: [ID!]!): [AdminPermissionInfo!]!
setUserCredentials(userId: ID!, providerId: ID!, credentials: Object!): Boolean
@@ -21,54 +21,54 @@ import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.model.meta.Property;
import org.jkiss.dbeaver.model.security.SMDataSourceGrant;
import org.jkiss.dbeaver.model.security.SMObjects;
import org.jkiss.dbeaver.model.security.user.SMRole;
import org.jkiss.dbeaver.model.security.user.SMTeam;
import java.util.ArrayList;
import java.util.List;
/**
* Web role info
* Web team info
*/
public class AdminRoleInfo {
public class AdminTeamInfo {
private final WebSession session;
private final SMRole role;
private List<String> rolePermissions;
private final SMTeam team;
private List<String> teamPermissions;
public AdminRoleInfo(WebSession session, SMRole role) {
this.role = role;
public AdminTeamInfo(WebSession session, SMTeam team) {
this.team = team;
this.session = session;
this.rolePermissions = new ArrayList<>(role.getPermissions());
this.teamPermissions = new ArrayList<>(team.getPermissions());
}
public String getRoleId() {
return role.getRoleId();
public String getTeamId() {
return team.getTeamId();
}
public String getRoleName() {
return role.getName();
public String getTeamName() {
return team.getName();
}
public String getDescription() {
return role.getDescription();
return team.getDescription();
}
public List<String> getRolePermissions() {
return rolePermissions;
public List<String> getTeamPermissions() {
return teamPermissions;
}
public void setRolePermissions(List<String> rolePermissions) {
this.rolePermissions = rolePermissions;
public void setTeamPermissions(List<String> teamPermissions) {
this.teamPermissions = teamPermissions;
}
@Property
public SMDataSourceGrant[] getGrantedConnections() throws DBException {
return session.getAdminSecurityController()
.getSubjectObjectPermissionGrants(getRoleId(), SMObjects.DATASOURCE)
.getSubjectObjectPermissionGrants(getTeamId(), SMObjects.DATASOURCE)
.stream()
.map(objectPermission -> new SMDataSourceGrant(
objectPermission.getObjectPermissions().getObjectId(),
getRoleId(),
getTeamId(),
objectPermission.getSubjectType()
))
.toArray(SMDataSourceGrant[]::new);
@@ -76,7 +76,7 @@ public class AdminRoleInfo {
@Property
public String[] getGrantedUsers() throws DBException {
return session.getAdminSecurityController().getRoleSubjects(getRoleId());
return session.getAdminSecurityController().getTeamMembers(getTeamId());
}
}
@@ -25,7 +25,6 @@ import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.model.meta.Property;
import org.jkiss.dbeaver.model.security.SMDataSourceGrant;
import org.jkiss.dbeaver.model.security.SMObjects;
import org.jkiss.dbeaver.model.security.user.SMRole;
import org.jkiss.dbeaver.registry.auth.AuthProviderDescriptor;
import org.jkiss.dbeaver.registry.auth.AuthProviderRegistry;
@@ -71,12 +70,8 @@ public class AdminUserInfo {
}
@Property
public String[] getGrantedRoles() throws DBException {
if (user.getRoles() == null) {
SMRole[] userRoles = session.getSecurityController().getUserRoles(getUserId());
user.setRoles(userRoles);
}
return user.getGrantedRoles();
public String[] getGrantedTeams() {
return user.getTeams();
}
@Property
@@ -45,7 +45,7 @@ public interface DBWServiceAdmin extends DBWService {
@WebAction(requirePermissions = DBWConstants.PERMISSION_ADMIN)
@NotNull
List<AdminRoleInfo> listRoles(@NotNull WebSession webSession, @Nullable String roleName) throws DBWebException;
List<AdminTeamInfo> listTeams(@NotNull WebSession webSession, @Nullable String teamName) throws DBWebException;
@WebAction(requirePermissions = DBWConstants.PERMISSION_ADMIN)
@NotNull
@@ -60,23 +60,23 @@ public interface DBWServiceAdmin extends DBWService {
@WebAction(requirePermissions = DBWConstants.PERMISSION_ADMIN)
@NotNull
AdminRoleInfo createRole(@NotNull WebSession webSession, String roleId, String roleName, String description) throws DBWebException;
AdminTeamInfo createTeam(@NotNull WebSession webSession, String teamId, String teamName, String description) throws DBWebException;
@WebAction(requirePermissions = DBWConstants.PERMISSION_ADMIN)
@NotNull
AdminRoleInfo updateRole(@NotNull WebSession webSession, String roleId, String roleName, String description) throws DBWebException;
AdminTeamInfo updateTeam(@NotNull WebSession webSession, String teamId, String teamName, String description) throws DBWebException;
@WebAction(requirePermissions = DBWConstants.PERMISSION_ADMIN)
boolean deleteRole(@NotNull WebSession webSession, String roleId) throws DBWebException;
boolean deleteTeam(@NotNull WebSession webSession, String teamId) throws DBWebException;
@WebAction(requirePermissions = DBWConstants.PERMISSION_ADMIN)
boolean grantUserRole(@NotNull WebSession webSession, String user, String role) throws DBWebException;
boolean grantUserTeam(@NotNull WebSession webSession, String user, String team) throws DBWebException;
@WebAction(requirePermissions = DBWConstants.PERMISSION_ADMIN)
boolean revokeUserRole(@NotNull WebSession webSession, String user, String role) throws DBWebException;
boolean revokeUserTeam(@NotNull WebSession webSession, String user, String team) throws DBWebException;
@WebAction(requirePermissions = DBWConstants.PERMISSION_ADMIN)
List<AdminPermissionInfo> setSubjectPermissions(@NotNull WebSession webSession, String roleID, List<String> permissions) throws DBWebException;
List<AdminPermissionInfo> setSubjectPermissions(@NotNull WebSession webSession, String subjectID, List<String> permissions) throws DBWebException;
@WebAction(requirePermissions = DBWConstants.PERMISSION_ADMIN)
boolean setUserCredentials(@NotNull WebSession webSession, @NotNull String userID, @NotNull String providerId, @NotNull Map<String, Object> credentials) throws DBWebException;
@@ -45,35 +45,35 @@ public class WebServiceBindingAdmin extends WebServiceBindingBase<DBWServiceAdmi
model.getQueryType()
.dataFetcher("listUsers",
env -> getService(env).listUsers(getWebSession(env), env.getArgument("userId")))
.dataFetcher("listRoles",
env -> getService(env).listRoles(getWebSession(env), env.getArgument("roleId")))
.dataFetcher("listTeams",
env -> getService(env).listTeams(getWebSession(env), env.getArgument("teamId")))
.dataFetcher("listPermissions",
env -> getService(env).listPermissions(getWebSession(env)))
.dataFetcher("createUser",
env -> getService(env).createUser(getWebSession(env), env.getArgument("userId"), env.getArgument("enabled")))
.dataFetcher("deleteUser",
env -> getService(env).deleteUser(getWebSession(env), env.getArgument("userId")))
.dataFetcher("createRole",
env -> getService(env).createRole(
.dataFetcher("createTeam",
env -> getService(env).createTeam(
getWebSession(env),
env.getArgument("roleId"),
env.getArgument("roleName"),
env.getArgument("teamId"),
env.getArgument("teamName"),
env.getArgument("description")))
.dataFetcher("updateRole",
env -> getService(env).updateRole(
.dataFetcher("updateTeam",
env -> getService(env).updateTeam(
getWebSession(env),
env.getArgument("roleId"),
env.getArgument("roleName"),
env.getArgument("teamId"),
env.getArgument("teamName"),
env.getArgument("description")))
.dataFetcher("deleteRole",
env -> getService(env).deleteRole(getWebSession(env), env.getArgument("roleId")))
.dataFetcher("deleteTeam",
env -> getService(env).deleteTeam(getWebSession(env), env.getArgument("teamId")))
.dataFetcher("grantUserRole",
env -> getService(env).grantUserRole(getWebSession(env), env.getArgument("userId"), env.getArgument("roleId")))
.dataFetcher("revokeUserRole",
env -> getService(env).revokeUserRole(getWebSession(env), env.getArgument("userId"), env.getArgument("roleId")))
.dataFetcher("grantUserTeam",
env -> getService(env).grantUserTeam(getWebSession(env), env.getArgument("userId"), env.getArgument("teamId")))
.dataFetcher("revokeUserTeam",
env -> getService(env).revokeUserTeam(getWebSession(env), env.getArgument("userId"), env.getArgument("teamId")))
.dataFetcher("setSubjectPermissions",
env -> getService(env).setSubjectPermissions(getWebSession(env), env.getArgument("roleId"), env.getArgument("permissions")))
env -> getService(env).setSubjectPermissions(getWebSession(env), env.getArgument("subjectId"), env.getArgument("permissions")))
.dataFetcher("setUserCredentials",
env -> getService(env).setUserCredentials(getWebSession(env), env.getArgument("userId"), env.getArgument("providerId"), env.getArgument("credentials")))
.dataFetcher("enableUser",
@@ -53,7 +53,7 @@ import org.jkiss.dbeaver.model.security.SMAuthProviderCustomConfiguration;
import org.jkiss.dbeaver.model.security.SMConstants;
import org.jkiss.dbeaver.model.security.SMDataSourceGrant;
import org.jkiss.dbeaver.model.security.SMObjects;
import org.jkiss.dbeaver.model.security.user.SMRole;
import org.jkiss.dbeaver.model.security.user.SMTeam;
import org.jkiss.dbeaver.model.security.user.SMUser;
import org.jkiss.dbeaver.registry.DataSourceDescriptor;
import org.jkiss.dbeaver.registry.auth.AuthProviderDescriptor;
@@ -95,22 +95,22 @@ public class WebServiceAdmin implements DBWServiceAdmin {
@NotNull
@Override
public List<AdminRoleInfo> listRoles(@NotNull WebSession webSession, String roleId) throws DBWebException {
public List<AdminTeamInfo> listTeams(@NotNull WebSession webSession, String teamName) throws DBWebException {
try {
List<AdminRoleInfo> roles = new ArrayList<>();
if (CommonUtils.isEmpty(roleId)) {
for (SMRole role : webSession.getAdminSecurityController().readAllRoles()) {
roles.add(new AdminRoleInfo(webSession, role));
List<AdminTeamInfo> teams = new ArrayList<>();
if (CommonUtils.isEmpty(teamName)) {
for (SMTeam team : webSession.getAdminSecurityController().readAllTeams()) {
teams.add(new AdminTeamInfo(webSession, team));
}
} else {
SMRole role = webSession.getAdminSecurityController().findRole(roleId);
if (role != null) {
roles.add(new AdminRoleInfo(webSession, role));
SMTeam team = webSession.getAdminSecurityController().findTeam(teamName);
if (team != null) {
teams.add(new AdminTeamInfo(webSession, team));
}
}
return roles;
return teams;
} catch (Exception e) {
throw new DBWebException("Error reading roles", e);
throw new DBWebException("Error reading teams", e);
}
}
@@ -158,126 +158,126 @@ public class WebServiceAdmin implements DBWServiceAdmin {
@NotNull
@Override
public AdminRoleInfo createRole(@NotNull WebSession webSession, String roleId, String roleName, String description) throws DBWebException {
if (roleId.isEmpty()) {
throw new DBWebException("Empty role ID");
public AdminTeamInfo createTeam(@NotNull WebSession webSession, String teamId, String teamName, String description) throws DBWebException {
if (teamId.isEmpty()) {
throw new DBWebException("Empty team ID");
}
webSession.addInfoMessage("Create new role - " + roleId);
webSession.addInfoMessage("Create new team - " + teamId);
try {
webSession.getAdminSecurityController().createRole(roleId, roleName, description, webSession.getUser().getUserId());
SMRole newRole = webSession.getAdminSecurityController().findRole(roleId);
return new AdminRoleInfo(webSession, newRole);
webSession.getAdminSecurityController().createTeam(teamId, teamName, description, webSession.getUser().getUserId());
SMTeam newTeam = webSession.getAdminSecurityController().findTeam(teamId);
return new AdminTeamInfo(webSession, newTeam);
} catch (Exception e) {
throw new DBWebException("Error creating new role", e);
throw new DBWebException("Error creating new team", e);
}
}
@NotNull
@Override
public AdminRoleInfo updateRole(@NotNull WebSession webSession, String roleId, String roleName, String description) throws DBWebException {
if (roleId.isEmpty()) {
throw new DBWebException("Empty role ID");
public AdminTeamInfo updateTeam(@NotNull WebSession webSession, String teamId, String teamName, String description) throws DBWebException {
if (teamId.isEmpty()) {
throw new DBWebException("Empty team ID");
}
webSession.addInfoMessage("Update role - " + roleId);
webSession.addInfoMessage("Update team - " + teamId);
try {
webSession.getAdminSecurityController().updateRole(roleId, roleName, description);
SMRole newRole = webSession.getAdminSecurityController().findRole(roleId);
return new AdminRoleInfo(webSession, newRole);
webSession.getAdminSecurityController().updateTeam(teamId, teamName, description);
SMTeam newTeam = webSession.getAdminSecurityController().findTeam(teamId);
return new AdminTeamInfo(webSession, newTeam);
} catch (Exception e) {
throw new DBWebException("Error updating role " + roleId, e);
throw new DBWebException("Error updating team " + teamId, e);
}
}
@Override
public boolean deleteRole(@NotNull WebSession webSession, String roleId) throws DBWebException {
public boolean deleteTeam(@NotNull WebSession webSession, String teamId) throws DBWebException {
try {
webSession.addInfoMessage("Delete role - " + roleId);
webSession.addInfoMessage("Delete team - " + teamId);
var adminSecurityController = webSession.getAdminSecurityController();
SMRole[] userRoles = adminSecurityController.getUserRoles(webSession.getUser().getUserId());
if (Arrays.stream(userRoles).anyMatch(DBRole -> DBRole.getRoleId().equals(roleId))) {
throw new DBWebException("You can not delete your own role");
SMTeam[] userTeams = adminSecurityController.getUserTeams(webSession.getUser().getUserId());
if (Arrays.stream(userTeams).anyMatch(team -> team.getTeamId().equals(teamId))) {
throw new DBWebException("You can not delete your own team");
}
adminSecurityController.deleteRole(roleId);
adminSecurityController.deleteTeam(teamId);
return true;
} catch (Exception e) {
throw new DBWebException("Error deleting role", e);
throw new DBWebException("Error deleting team", e);
}
}
@Override
public boolean grantUserRole(@NotNull WebSession webSession, String user, String role) throws DBWebException {
public boolean grantUserTeam(@NotNull WebSession webSession, String user, String team) throws DBWebException {
WebUser grantor = webSession.getUser();
if (grantor == null) {
throw new DBWebException("Cannot grant role in anonymous mode");
throw new DBWebException("Cannot grant team in anonymous mode");
}
if (CommonUtils.equalObjects(user, webSession.getUser().getUserId())) {
throw new DBWebException("You cannot edit your own permissions");
}
try {
var adminSecurityController = webSession.getAdminSecurityController();
SMRole[] userRoles = adminSecurityController.getUserRoles(user);
List<String> roleIds = Arrays.stream(userRoles).map(SMRole::getRoleId).collect(Collectors.toList());
if (!roleIds.contains(role)) {
roleIds.add(role);
adminSecurityController.setUserRoles(user, roleIds.toArray(new String[0]), grantor.getUserId());
SMTeam[] userTeams = adminSecurityController.getUserTeams(user);
List<String> teamIds = Arrays.stream(userTeams).map(SMTeam::getTeamId).collect(Collectors.toList());
if (!teamIds.contains(team)) {
teamIds.add(team);
adminSecurityController.setUserTeams(user, teamIds.toArray(new String[0]), grantor.getUserId());
} else {
throw new DBWebException("User '" + user + "' already has role '" + role + "'");
throw new DBWebException("User '" + user + "' already has team '" + team + "'");
}
return true;
} catch (Exception e) {
throw new DBWebException("Error granting role", e);
throw new DBWebException("Error granting team", e);
}
}
@Override
public boolean revokeUserRole(@NotNull WebSession webSession, String user, String role) throws DBWebException {
public boolean revokeUserTeam(@NotNull WebSession webSession, String user, String team) throws DBWebException {
WebUser grantor = webSession.getUser();
if (grantor == null) {
throw new DBWebException("Cannot grant role in anonymous mode");
throw new DBWebException("Cannot revoke team in anonymous mode");
}
if (CommonUtils.equalObjects(user, webSession.getUser().getUserId())) {
throw new DBWebException("You cannot edit your own permissions");
}
try {
var adminSecurityController = webSession.getAdminSecurityController();
SMRole[] userRoles = adminSecurityController.getUserRoles(user);
List<String> roleIds = Arrays.stream(userRoles).map(SMRole::getRoleId).collect(Collectors.toList());
if (roleIds.contains(role)) {
roleIds.remove(role);
adminSecurityController.setUserRoles(user, roleIds.toArray(new String[0]), grantor.getUserId());
SMTeam[] userTeams = adminSecurityController.getUserTeams(user);
List<String> teamIds = Arrays.stream(userTeams).map(SMTeam::getTeamId).collect(Collectors.toList());
if (teamIds.contains(team)) {
teamIds.remove(team);
adminSecurityController.setUserTeams(user, teamIds.toArray(new String[0]), grantor.getUserId());
} else {
throw new DBWebException("User '" + user + "' doesn't have role '" + role + "'");
throw new DBWebException("User '" + user + "' doesn't have team '" + team + "'");
}
return true;
} catch (Exception e) {
throw new DBWebException("Error revoking role", e);
throw new DBWebException("Error revoking team", e);
}
}
@Override
public List<AdminPermissionInfo> setSubjectPermissions(@NotNull WebSession webSession, String roleID, List<String> permissions) throws DBWebException {
public List<AdminPermissionInfo> setSubjectPermissions(@NotNull WebSession webSession, String subjectID, List<String> permissions) throws DBWebException {
validatePermissions(SMConstants.SUBJECT_PERMISSION_SCOPE, permissions);
WebUser grantor = webSession.getUser();
if (grantor == null) {
throw new DBWebException("Cannot change permissions in anonymous mode");
}
if (CommonUtils.equalObjects(roleID, CBConstants.DEFAULT_ADMIN_ROLE)) {
throw new DBWebException("Cannot change permissions for role '" + roleID + "'");
if (CommonUtils.equalObjects(subjectID, CBConstants.DEFAULT_ADMIN_TEAM)) {
throw new DBWebException("Cannot change permissions for team '" + subjectID + "'");
}
webSession.addInfoMessage("Set permissions to subject - " + roleID);
webSession.addInfoMessage("Set permissions to subject - " + subjectID);
try {
webSession.getAdminSecurityController().setSubjectPermissions(roleID, permissions, grantor.getUserId());
Set<String> subjectPermissions = webSession.getAdminSecurityController().getSubjectPermissions(roleID);
webSession.getAdminSecurityController().setSubjectPermissions(subjectID, permissions, grantor.getUserId());
Set<String> subjectPermissions = webSession.getAdminSecurityController().getSubjectPermissions(subjectID);
webSession.refreshUserData();
return listPermissions(webSession).stream()
.filter(p -> subjectPermissions.contains(p.getId()))
.collect(Collectors.toList());
} catch (Exception e) {
throw new DBWebException("Error setting role permissions", e);
throw new DBWebException("Error setting subject permissions", e);
}
}
@@ -690,7 +690,7 @@ public class WebServiceAdmin implements DBWServiceAdmin {
}
WebUser grantor = webSession.getUser();
if (grantor == null) {
throw new DBWebException("Cannot grant role in anonymous mode");
throw new DBWebException("Cannot grant connection access in anonymous mode");
}
try {
var adminSM = webSession.getAdminSecurityController();
@@ -67,14 +67,14 @@ public class RPSessionHandler implements DBWSessionHandler {
}
SMAuthProviderExternal<?> authProviderExternal = (SMAuthProviderExternal<?>) authProvider.getInstance();
String userName = request.getHeader(RPAuthProvider.X_USER);
String roles = request.getHeader(RPAuthProvider.X_ROLE);
List<String> userRoles = roles == null ? Collections.emptyList() : List.of(roles.split("\\|"));
String teams = request.getHeader(RPAuthProvider.X_ROLE);
List<String> userTeams = teams == null ? Collections.emptyList() : List.of(teams.split("\\|"));
if (userName != null) {
try {
Map<String, Object> credentials = new HashMap<>();
credentials.put("user", userName);
Map<String, Object> sessionParameters = webSession.getSessionParameters();
sessionParameters.put(SMConstants.SESSION_PARAM_TRUSTED_USER_ROLES, userRoles);
sessionParameters.put(SMConstants.SESSION_PARAM_TRUSTED_USER_TEAMS, userTeams);
Map<String, Object> userCredentials = authProviderExternal.authExternalUser(
webSession.getProgressMonitor(), sessionParameters, credentials);
String currentSmSessionId = webSession.getUser() == null ? null : webSession.getUserContext().getSmSessionId();
@@ -99,6 +99,7 @@ CREATE TABLE CB_USER
IS_ACTIVE CHAR(1) NOT NULL,
CREATE_TIME TIMESTAMP NOT NULL,
DEFAULT_AUTH_ROLE VARCHAR(32) NULL,
PRIMARY KEY (USER_ID),
FOREIGN KEY (USER_ID) REFERENCES CB_AUTH_SUBJECT (SUBJECT_ID) ON DELETE CASCADE
@@ -125,29 +126,39 @@ CREATE TABLE CB_USER_PARAMETERS
FOREIGN KEY (USER_ID) REFERENCES CB_USER (USER_ID) ON DELETE CASCADE
);
CREATE TABLE CB_ROLE
CREATE TABLE CB_TEAM
(
ROLE_ID VARCHAR(128) NOT NULL,
ROLE_NAME VARCHAR(100) NOT NULL,
ROLE_DESCRIPTION VARCHAR(255) NOT NULL,
TEAM_ID VARCHAR(128) NOT NULL,
TEAM_NAME VARCHAR(100) NOT NULL,
TEAM_DESCRIPTION VARCHAR(255) NOT NULL,
CREATE_TIME TIMESTAMP NOT NULL,
PRIMARY KEY (ROLE_ID),
FOREIGN KEY (ROLE_ID) REFERENCES CB_AUTH_SUBJECT (SUBJECT_ID) ON DELETE CASCADE
PRIMARY KEY (TEAM_ID),
FOREIGN KEY (TEAM_ID) REFERENCES CB_AUTH_SUBJECT (SUBJECT_ID) ON DELETE CASCADE
);
CREATE TABLE CB_USER_ROLE
CREATE TABLE CB_EXTERNAL_TEAM
(
TEAM_ID VARCHAR(128) NOT NULL,
EXTERNAL_TEAM_ID VARCHAR(128) NOT NULL,
PRIMARY KEY (TEAM_ID,EXTERNAL_TEAM_ID),
FOREIGN KEY (TEAM_ID) REFERENCES CB_TEAM (TEAM_ID) ON DELETE CASCADE
);
CREATE TABLE CB_USER_TEAM
(
USER_ID VARCHAR(128) NOT NULL,
ROLE_ID VARCHAR(128) NOT NULL,
TEAM_ID VARCHAR(128) NOT NULL,
GRANT_TIME TIMESTAMP NOT NULL,
GRANTED_BY VARCHAR(128) NOT NULL,
PRIMARY KEY (USER_ID, ROLE_ID),
PRIMARY KEY (USER_ID, TEAM_ID),
FOREIGN KEY (USER_ID) REFERENCES CB_USER (USER_ID) ON DELETE CASCADE,
FOREIGN KEY (ROLE_ID) REFERENCES CB_ROLE (ROLE_ID) ON DELETE CASCADE
FOREIGN KEY (TEAM_ID) REFERENCES CB_TEAM (TEAM_ID) ON DELETE NO ACTION
);
CREATE TABLE CB_AUTH_PROVIDER
@@ -175,7 +186,7 @@ CREATE TABLE CB_USER_CREDENTIALS
CRED_ID VARCHAR(32) NOT NULL,
CRED_VALUE VARCHAR(1024) NOT NULL,
UPDATE_TIME TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
UPDATE_TIME TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
PRIMARY KEY (USER_ID, PROVIDER_ID, CRED_ID),
FOREIGN KEY (USER_ID) REFERENCES CB_USER (USER_ID) ON DELETE CASCADE
@@ -189,7 +200,7 @@ CREATE TABLE CB_USER_STATE
USER_CONFIGURATION TEXT NULL,
UPDATE_TIME TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
UPDATE_TIME TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
PRIMARY KEY (USER_ID),
FOREIGN KEY (USER_ID) REFERENCES CB_USER (USER_ID) ON DELETE CASCADE
@@ -242,14 +253,15 @@ CREATE TABLE CB_AUTH_TOKEN
REFRESH_TOKEN_ID VARCHAR(128),
SESSION_ID VARCHAR(64) NOT NULL,
USER_ID VARCHAR(128),
AUTH_ROLE VARCHAR(32),
EXPIRATION_TIME TIMESTAMP NOT NULL,
REFRESH_TOKEN_EXPIRATION_TIME TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
CREATE_TIME TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
REFRESH_TOKEN_EXPIRATION_TIME TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
CREATE_TIME TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
PRIMARY KEY (TOKEN_ID),
FOREIGN KEY (SESSION_ID) REFERENCES CB_SESSION (SESSION_ID) ON DELETE CASCADE,
FOREIGN KEY (USER_ID) REFERENCES CB_USER (USER_ID) ON DELETE CASCADE
FOREIGN KEY (USER_ID) REFERENCES CB_USER (USER_ID) ON DELETE NO ACTION
);
CREATE TABLE CB_AUTH_ATTEMPT
@@ -262,7 +274,7 @@ CREATE TABLE CB_AUTH_ATTEMPT
SESSION_TYPE VARCHAR(64) NOT NULL,
APP_SESSION_STATE TEXT NOT NULL,
CREATE_TIME TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
CREATE_TIME TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
PRIMARY KEY (AUTH_ID),
FOREIGN KEY (SESSION_ID) REFERENCES CB_SESSION (SESSION_ID) ON DELETE CASCADE
@@ -275,7 +287,7 @@ CREATE TABLE CB_AUTH_ATTEMPT_INFO
AUTH_PROVIDER_CONFIGURATION_ID VARCHAR(128),
AUTH_STATE TEXT NOT NULL,
CREATE_TIME TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
CREATE_TIME TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
PRIMARY KEY (AUTH_ID, AUTH_PROVIDER_ID),
FOREIGN KEY (AUTH_ID) REFERENCES CB_AUTH_ATTEMPT (AUTH_ID) ON DELETE CASCADE
@@ -287,18 +299,15 @@ CREATE INDEX CB_SESSION_LOG_INDEX ON CB_SESSION_LOG (SESSION_ID, LOG_TIME);
CREATE TABLE CB_USER_SECRETS
(
USER_ID VARCHAR(128) NOT NULL,
SECRET_ID VARCHAR(512) NOT NULL,
SECRET_VALUE VARCHAR(65000) NOT NULL,
USER_ID VARCHAR(128) NOT NULL,
SECRET_ID VARCHAR(512) NOT NULL,
SECRET_VALUE TEXT NOT NULL,
SECRET_LABEL VARCHAR(128),
SECRET_DESCRIPTION VARCHAR(1024),
UPDATE_TIME TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
UPDATE_TIME TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
PRIMARY KEY (USER_ID, SECRET_ID),
FOREIGN KEY (USER_ID) REFERENCES CB_USER (USER_ID) ON DELETE CASCADE
);
CREATE INDEX CB_USER_SECRETS_ID ON CB_USER_SECRETS (USER_ID,SECRET_ID);
@@ -0,0 +1,46 @@
ALTER TABLE CB_AUTH_TOKEN ADD COLUMN AUTH_ROLE VARCHAR(32);
ALTER TABLE CB_USER ADD COLUMN DEFAULT_AUTH_ROLE VARCHAR(32) NULL;
CREATE TABLE CB_TEAM
(
TEAM_ID VARCHAR(128) NOT NULL,
TEAM_NAME VARCHAR(100) NOT NULL,
TEAM_DESCRIPTION VARCHAR(255) NOT NULL,
CREATE_TIME TIMESTAMP NOT NULL,
PRIMARY KEY (TEAM_ID),
FOREIGN KEY (TEAM_ID) REFERENCES CB_AUTH_SUBJECT (SUBJECT_ID) ON DELETE CASCADE
);
INSERT INTO CB_TEAM (TEAM_ID, TEAM_NAME, TEAM_DESCRIPTION, CREATE_TIME)
SELECT ROLE_ID, ROLE_NAME, ROLE_DESCRIPTION, CREATE_TIME FROM CB_ROLE;
CREATE TABLE CB_USER_TEAM
(
USER_ID VARCHAR(128) NOT NULL,
TEAM_ID VARCHAR(128) NOT NULL,
GRANT_TIME TIMESTAMP NOT NULL,
GRANTED_BY VARCHAR(128) NOT NULL,
PRIMARY KEY (USER_ID, TEAM_ID),
FOREIGN KEY (USER_ID) REFERENCES CB_USER (USER_ID) ON DELETE CASCADE,
FOREIGN KEY (TEAM_ID) REFERENCES CB_TEAM (TEAM_ID) ON DELETE NO ACTION
);
INSERT INTO CB_USER_TEAM (USER_ID, TEAM_ID, GRANT_TIME, GRANTED_BY)
SELECT USER_ID, ROLE_ID, GRANT_TIME, GRANTED_BY FROM CB_USER_ROLE;
CREATE TABLE CB_EXTERNAL_TEAM
(
TEAM_ID VARCHAR(128) NOT NULL,
EXTERNAL_TEAM_ID VARCHAR(128) NOT NULL,
PRIMARY KEY (TEAM_ID,EXTERNAL_TEAM_ID),
FOREIGN KEY (TEAM_ID) REFERENCES CB_TEAM (TEAM_ID) ON DELETE CASCADE
);
DROP TABLE CB_USER_ROLE;
DROP TABLE CB_ROLE;
@@ -38,6 +38,7 @@ 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.runtime.DBRProgressMonitor;
import org.jkiss.dbeaver.model.runtime.LoggingProgressMonitor;
import org.jkiss.dbeaver.model.runtime.VoidProgressMonitor;
import org.jkiss.dbeaver.model.security.*;
import org.jkiss.dbeaver.model.security.exception.SMAccessTokenExpiredException;
@@ -45,7 +46,7 @@ import org.jkiss.dbeaver.model.security.exception.SMException;
import org.jkiss.dbeaver.model.security.exception.SMRefreshTokenExpiredException;
import org.jkiss.dbeaver.model.security.user.SMAuthPermissions;
import org.jkiss.dbeaver.model.security.user.SMObjectPermissions;
import org.jkiss.dbeaver.model.security.user.SMRole;
import org.jkiss.dbeaver.model.security.user.SMTeam;
import org.jkiss.dbeaver.model.security.user.SMUser;
import org.jkiss.dbeaver.registry.auth.AuthProviderDescriptor;
import org.jkiss.dbeaver.registry.auth.AuthProviderRegistry;
@@ -72,7 +73,7 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
protected static final String CHAR_BOOL_FALSE = "N";
private static final String SUBJECT_USER = "U";
private static final String SUBJECT_ROLE = "R";
private static final String SUBJECT_TEAM = "R";
private static final Type MAP_STRING_OBJECT_TYPE = new TypeToken<Map<String, Object>>() {
}.getType();
private static final Gson gson = new GsonBuilder().create();
@@ -114,7 +115,7 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
@Override
public void createUser(String userId, Map<String, String> metaParameters, boolean enabled) throws DBException {
if (isSubjectExists(userId)) {
throw new DBCException("User or role '" + userId + "' already exists");
throw new DBCException("User or team '" + userId + "' already exists");
}
try (Connection dbCon = database.openConnection()) {
try (JDBCTransaction txn = new JDBCTransaction(dbCon)) {
@@ -156,15 +157,15 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
}
@Override
public void setUserRoles(String userId, String[] roleIds, String grantorId) throws DBCException {
public void setUserTeams(String userId, String[] teamIds, String grantorId) throws DBCException {
try (Connection dbCon = database.openConnection()) {
try (JDBCTransaction txn = new JDBCTransaction(dbCon)) {
JDBCUtils.executeStatement(dbCon, "DELETE FROM CB_USER_ROLE WHERE USER_ID=?", userId);
if (!ArrayUtils.isEmpty(roleIds)) {
try (PreparedStatement dbStat = dbCon.prepareStatement("INSERT INTO CB_USER_ROLE(USER_ID,ROLE_ID,GRANT_TIME,GRANTED_BY) VALUES(?,?,?,?)")) {
for (String roleId : roleIds) {
JDBCUtils.executeStatement(dbCon, "DELETE FROM CB_USER_TEAM WHERE USER_ID=?", userId);
if (!ArrayUtils.isEmpty(teamIds)) {
try (PreparedStatement dbStat = dbCon.prepareStatement("INSERT INTO CB_USER_TEAM(USER_ID,TEAM_ID,GRANT_TIME,GRANTED_BY) VALUES(?,?,?,?)")) {
for (String teamId : teamIds) {
dbStat.setString(1, userId);
dbStat.setString(2, roleId);
dbStat.setString(2, teamId);
dbStat.setTimestamp(3, new Timestamp(System.currentTimeMillis()));
dbStat.setString(4, grantorId);
dbStat.execute();
@@ -174,28 +175,28 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
txn.commit();
}
} catch (SQLException e) {
throw new DBCException("Error saving user roles in database", e);
throw new DBCException("Error saving user teams in database", e);
}
}
@NotNull
@Override
public SMRole[] getUserRoles(String userId) throws DBException {
public SMTeam[] getUserTeams(String userId) throws DBException {
try (Connection dbCon = database.openConnection()) {
try (PreparedStatement dbStat = dbCon.prepareStatement(
"SELECT R.* FROM CB_USER_ROLE UR,CB_ROLE R " +
"WHERE UR.USER_ID=? AND UR.ROLE_ID=R.ROLE_ID")) {
"SELECT R.* FROM CB_USER_TEAM UR,CB_TEAM R " +
"WHERE UR.USER_ID=? AND UR.TEAM_ID=R.TEAM_ID")) {
dbStat.setString(1, userId);
List<SMRole> roles = new ArrayList<>();
List<SMTeam> teams = new ArrayList<>();
try (ResultSet dbResult = dbStat.executeQuery()) {
while (dbResult.next()) {
roles.add(fetchRole(dbResult));
teams.add(fetchTeam(dbResult));
}
}
return roles.toArray(new SMRole[0]);
return teams.toArray(new SMTeam[0]);
}
} catch (SQLException e) {
throw new DBCException("Error while reading user roles", e);
throw new DBCException("Error while reading user teams", e);
}
}
@@ -215,6 +216,7 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
}
}
}
// Metas
try (PreparedStatement dbStat = dbCon.prepareStatement("SELECT META_ID,META_VALUE FROM CB_USER_META WHERE USER_ID=?")) {
dbStat.setString(1, userId);
try (ResultSet dbResult = dbStat.executeQuery()) {
@@ -226,6 +228,17 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
}
}
}
// Teams
try (PreparedStatement dbStat = dbCon.prepareStatement("SELECT TEAM_ID FROM CB_USER_TEAM WHERE USER_ID=?")) {
dbStat.setString(1, userId);
try (ResultSet dbResult = dbStat.executeQuery()) {
List<String> teamIDs = new ArrayList<>();
while (dbResult.next()) {
teamIDs.add(dbResult.getString(1));
}
user.setUserTeams(teamIDs.toArray(new String[0]));
}
}
return user;
} catch (SQLException e) {
throw new DBCException("Error while searching credentials", e);
@@ -270,6 +283,24 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
}
}
}
// Read teams
try (PreparedStatement dbStat = dbCon.prepareStatement("SELECT USER_ID,TEAM_ID FROM CB_USER_TEAM" +
(CommonUtils.isEmpty(userNameMask) ? "" : " WHERE USER_ID=?"))) {
if (!CommonUtils.isEmpty(userNameMask)) {
dbStat.setString(1, userNameMask);
}
try (ResultSet dbResult = dbStat.executeQuery()) {
while (dbResult.next()) {
String userId = dbResult.getString(1);
String teamId = dbResult.getString(2);
SMUser user = result.get(userId);
if (user != null) {
String[] teams = ArrayUtils.add(String.class, user.getUserTeams(), teamId);
user.setUserTeams(teams);
}
}
}
}
return result.values().toArray(new SMUser[0]);
} catch (SQLException e) {
throw new DBCException("Error while loading users", e);
@@ -533,7 +564,7 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
}
}
} catch (SQLException e) {
throw new DBCException("Error saving role in database", e);
throw new DBCException("Error reading user credentials", e);
}
}
@@ -556,56 +587,56 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
}
}
} catch (SQLException e) {
throw new DBCException("Error saving role in database", e);
throw new DBCException("Error reading user linked providers", e);
}
}
///////////////////////////////////////////
// Roles
// Teams
@NotNull
@Override
public SMRole[] readAllRoles() throws DBCException {
public SMTeam[] readAllTeams() throws DBCException {
try (Connection dbCon = database.openConnection()) {
Map<String, SMRole> roles = new LinkedHashMap<>();
Map<String, SMTeam> teams = new LinkedHashMap<>();
try (Statement dbStat = dbCon.createStatement()) {
try (ResultSet dbResult = dbStat.executeQuery("SELECT * FROM CB_ROLE ORDER BY ROLE_ID")) {
try (ResultSet dbResult = dbStat.executeQuery("SELECT * FROM CB_TEAM ORDER BY TEAM_ID")) {
while (dbResult.next()) {
SMRole role = fetchRole(dbResult);
roles.put(role.getRoleId(), role);
SMTeam team = fetchTeam(dbResult);
teams.put(team.getTeamId(), team);
}
}
try (ResultSet dbResult = dbStat.executeQuery("SELECT SUBJECT_ID,PERMISSION_ID\n" +
"FROM CB_AUTH_PERMISSIONS AP,CB_ROLE R\n" +
"WHERE AP.SUBJECT_ID=R.ROLE_ID\n")) {
"FROM CB_AUTH_PERMISSIONS AP,CB_TEAM R\n" +
"WHERE AP.SUBJECT_ID=R.TEAM_ID\n")) {
while (dbResult.next()) {
SMRole role = roles.get(dbResult.getString(1));
if (role != null) {
role.addPermission(dbResult.getString(2));
SMTeam team = teams.get(dbResult.getString(1));
if (team != null) {
team.addPermission(dbResult.getString(2));
}
}
}
}
return roles.values().toArray(new SMRole[0]);
return teams.values().toArray(new SMTeam[0]);
} catch (SQLException e) {
throw new DBCException("Error reading roles from database", e);
throw new DBCException("Error reading teams from database", e);
}
}
@Override
public SMRole findRole(String roleId) throws DBCException {
return Arrays.stream(readAllRoles())
.filter(r -> r.getRoleId().equals(roleId))
public SMTeam findTeam(String teamId) throws DBCException {
return Arrays.stream(readAllTeams())
.filter(r -> r.getTeamId().equals(teamId))
.findFirst().orElse(null);
}
@NotNull
@Override
public String[] getRoleSubjects(String roleId) throws DBCException {
public String[] getTeamMembers(String teamId) throws DBCException {
try (Connection dbCon = database.openConnection()) {
try (PreparedStatement dbStat = dbCon.prepareStatement(
"SELECT USER_ID FROM CB_USER_ROLE WHERE ROLE_ID=?")) {
dbStat.setString(1, roleId);
"SELECT USER_ID FROM CB_USER_TEAM WHERE TEAM_ID=?")) {
dbStat.setString(1, teamId);
List<String> subjects = new ArrayList<>();
try (ResultSet dbResult = dbStat.executeQuery()) {
while (dbResult.next()) {
@@ -615,95 +646,96 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
return subjects.toArray(new String[0]);
}
} catch (SQLException e) {
throw new DBCException("Error while reading role subjects", e);
throw new DBCException("Error while reading team members", e);
}
}
@NotNull
private SMRole fetchRole(ResultSet dbResult) throws SQLException {
return new SMRole(dbResult.getString("ROLE_ID"),
dbResult.getString("ROLE_NAME"),
dbResult.getString("ROLE_DESCRIPTION")
private SMTeam fetchTeam(ResultSet dbResult) throws SQLException {
return new SMTeam(
dbResult.getString("TEAM_ID"),
dbResult.getString("TEAM_NAME"),
dbResult.getString("TEAM_DESCRIPTION")
);
}
@Override
public void createRole(String roleId, String name, String description, String grantor) throws DBCException {
if (isSubjectExists(roleId)) {
throw new DBCException("User or role '" + roleId + "' already exists");
public void createTeam(String teamId, String name, String description, String grantor) throws DBCException {
if (isSubjectExists(teamId)) {
throw new DBCException("User or team '" + teamId + "' already exists");
}
try (Connection dbCon = database.openConnection()) {
try (JDBCTransaction txn = new JDBCTransaction(dbCon)) {
createAuthSubject(dbCon, roleId, SUBJECT_ROLE);
createAuthSubject(dbCon, teamId, SUBJECT_TEAM);
try (PreparedStatement dbStat = dbCon.prepareStatement(
"INSERT INTO CB_ROLE(ROLE_ID,ROLE_NAME,ROLE_DESCRIPTION,CREATE_TIME) VALUES(?,?,?,?)")) {
dbStat.setString(1, roleId);
"INSERT INTO CB_TEAM(TEAM_ID,TEAM_NAME,TEAM_DESCRIPTION,CREATE_TIME) VALUES(?,?,?,?)")) {
dbStat.setString(1, teamId);
dbStat.setString(2, CommonUtils.notEmpty(name));
dbStat.setString(3, CommonUtils.notEmpty(description));
dbStat.setTimestamp(4, new Timestamp(System.currentTimeMillis()));
dbStat.execute();
}
insertPermissions(dbCon, roleId,
insertPermissions(dbCon, teamId,
new String[] {DBWConstants.PERMISSION_PUBLIC} , grantor);
txn.commit();
}
} catch (SQLException e) {
throw new DBCException("Error saving role in database", e);
throw new DBCException("Error saving tem in database", e);
}
}
@Override
public void updateRole(String roleId, String name, String description) throws DBCException {
if (!isSubjectExists(roleId)) {
throw new DBCException("Role '" + roleId + "' doesn't exists");
public void updateTeam(String teamId, String name, String description) throws DBCException {
if (!isSubjectExists(teamId)) {
throw new DBCException("Team '" + teamId + "' doesn't exists");
}
try (Connection dbCon = database.openConnection()) {
try (JDBCTransaction txn = new JDBCTransaction(dbCon)) {
try (PreparedStatement dbStat = dbCon.prepareStatement(
"UPDATE CB_ROLE SET ROLE_NAME=?,ROLE_DESCRIPTION=? WHERE ROLE_ID=?")) {
"UPDATE CB_TEAM SET TEAM_NAME=?,TEAM_DESCRIPTION=? WHERE TEAM_ID=?")) {
dbStat.setString(1, CommonUtils.notEmpty(name));
dbStat.setString(2, CommonUtils.notEmpty(description));
dbStat.setString(3, roleId);
dbStat.setString(3, teamId);
if (dbStat.executeUpdate() <= 0) {
throw new DBCException("Role '" + roleId + "' doesn't exist");
throw new DBCException("Team '" + teamId + "' doesn't exist");
}
}
txn.commit();
}
} catch (SQLException e) {
throw new DBCException("Error updating role info in database", e);
throw new DBCException("Error updating team info in database", e);
}
}
@Override
public void deleteRole(String roleId) throws DBCException {
public void deleteTeam(String teamId) throws DBCException {
try (Connection dbCon = database.openConnection()) {
try (PreparedStatement dbStat = dbCon.prepareStatement(
"SELECT COUNT(*) FROM CB_USER_ROLE WHERE ROLE_ID=?")) {
dbStat.setString(1, roleId);
"SELECT COUNT(*) FROM CB_USER_TEAM WHERE TEAM_ID=?")) {
dbStat.setString(1, teamId);
try (ResultSet dbResult = dbStat.executeQuery()) {
if (dbResult.next()) {
int userCount = dbResult.getInt(1);
if (userCount > 0) {
throw new DBCException("Role can't be deleted. There are " + userCount + " user(s) who have this role. Un-assign role first.");
throw new DBCException("Team can't be deleted. There are " + userCount + " user(s) who have this team. Un-assign team first.");
}
}
}
}
try (JDBCTransaction txn = new JDBCTransaction(dbCon)) {
deleteAuthSubject(dbCon, roleId);
deleteAuthSubject(dbCon, teamId);
try (PreparedStatement dbStat = dbCon.prepareStatement(
"DELETE FROM CB_ROLE WHERE ROLE_ID=?")) {
dbStat.setString(1, roleId);
"DELETE FROM CB_TEAM WHERE TEAM_ID=?")) {
dbStat.setString(1, teamId);
dbStat.execute();
}
txn.commit();
}
} catch (SQLException e) {
throw new DBCException("Error deleting role from database", e);
throw new DBCException("Error deleting team from database", e);
}
}
@@ -720,7 +752,7 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
txn.commit();
}
} catch (SQLException e) {
throw new DBCException("Error saving role permissions in database", e);
throw new DBCException("Error saving subject permissions in database", e);
}
}
@@ -753,18 +785,18 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
}
return permissions;
} catch (SQLException e) {
throw new DBCException("Error saving role in database", e);
throw new DBCException("Error reading subject permissions", e);
}
}
@NotNull
@Override
public Set<String> getUserPermissions(String userId) throws DBException {
public Set<String> getUserPermissions(String userId, String authRole) throws DBException {
try (Connection dbCon = database.openConnection()) {
Set<String> permissions = new HashSet<>();
try (PreparedStatement dbStat = dbCon.prepareStatement(
"SELECT DISTINCT AP.PERMISSION_ID FROM CB_AUTH_PERMISSIONS AP,CB_USER_ROLE UR\n" +
"WHERE UR.ROLE_ID=AP.SUBJECT_ID AND UR.USER_ID=?")) {
"SELECT DISTINCT AP.PERMISSION_ID FROM CB_AUTH_PERMISSIONS AP,CB_USER_TEAM UR\n" +
"WHERE UR.TEAM_ID=AP.SUBJECT_ID AND UR.USER_ID=?")) {
dbStat.setString(1, userId);
try (ResultSet dbResult = dbStat.executeQuery()) {
while (dbResult.next()) {
@@ -822,25 +854,15 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
+ "VALUES(?,?,?,?,?,?,?,?,?)")) {
dbStat.setString(1, sessionId);
dbStat.setString(2, appSessionId);
if (userId != null) {
dbStat.setString(3, userId);
} else {
dbStat.setNull(3, Types.VARCHAR);
}
JDBCUtils.setStringOrNull(dbStat, 3, userId);
Timestamp currentTS = new Timestamp(System.currentTimeMillis());
dbStat.setTimestamp(4, currentTS);
dbStat.setTimestamp(5, currentTS);
if (parameters.get(SMConstants.SESSION_PARAM_LAST_REMOTE_ADDRESS) != null) {
dbStat.setString(6, parameters.get(SMConstants.SESSION_PARAM_LAST_REMOTE_ADDRESS).toString());
} else {
dbStat.setNull(6, Types.VARCHAR);
}
if (parameters.get(SMConstants.SESSION_PARAM_LAST_REMOTE_USER_AGENT) != null) {
dbStat.setString(7, parameters.get(SMConstants.SESSION_PARAM_LAST_REMOTE_USER_AGENT).toString());
} else {
dbStat.setNull(7, Types.VARCHAR);
}
JDBCUtils.setStringOrNull(dbStat, 6, CommonUtils.truncateString(CommonUtils.toString(
parameters.get(SMConstants.SESSION_PARAM_LAST_REMOTE_ADDRESS), null), 128));
JDBCUtils.setStringOrNull(dbStat, 7, CommonUtils.truncateString(CommonUtils.toString(
parameters.get(SMConstants.SESSION_PARAM_LAST_REMOTE_USER_AGENT), null), 255));
dbStat.setString(8, database.getInstanceId());
dbStat.setString(9, sessionType.getSessionType());
dbStat.execute();
@@ -853,14 +875,15 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
try (Connection dbCon = database.openConnection()) {
try (JDBCTransaction txn = new JDBCTransaction(dbCon)) {
var smSessionId = createSmSession(appSessionId, null, sessionParameters, sessionType, dbCon);
var smTokens = generateNewSessionToken(smSessionId, null, dbCon);
var smTokens = generateNewSessionToken(smSessionId, null, null, dbCon);
var permissions = getAnonymousUserPermissions();
txn.commit();
return SMAuthInfo.success(
UUID.randomUUID().toString(),
smTokens.getSmAccessToken(),
smTokens.getSmRefreshToken(),
new SMAuthPermissions(null, smSessionId, permissions), Map.of()
new SMAuthPermissions(null, smSessionId, permissions),
Map.of()
);
}
} catch (SQLException e) {
@@ -869,8 +892,8 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
}
private Set<String> getAnonymousUserPermissions() throws DBException {
var anonymousUserRole = ((WebApplication) DBWorkbench.getPlatform().getApplication()).getAppConfiguration().getAnonymousUserRole();
return getSubjectPermissions(anonymousUserRole);
var anonymousUserTeam = ((WebApplication) DBWorkbench.getPlatform().getApplication()).getAppConfiguration().getAnonymousUserTeam();
return getSubjectPermissions(anonymousUserTeam);
}
@Override
@@ -1019,16 +1042,8 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
try (PreparedStatement dbStat = dbCon.prepareStatement(
"UPDATE CB_AUTH_ATTEMPT SET AUTH_STATUS=?,AUTH_ERROR=?,SESSION_ID=? WHERE AUTH_ID=?")) {
dbStat.setString(1, authStatus.toString());
if (error != null) {
dbStat.setString(2, error);
} else {
dbStat.setNull(2, Types.VARCHAR);
}
if (smSessionId != null) {
dbStat.setString(3, smSessionId);
} else {
dbStat.setNull(3, Types.VARCHAR);
}
JDBCUtils.setStringOrNull(dbStat, 2, error);
JDBCUtils.setStringOrNull(dbStat, 3, smSessionId);
dbStat.setString(4, authId);
if (dbStat.executeUpdate() <= 0) {
throw new DBCException("Auth attempt '" + authId + "' doesn't exist");
@@ -1145,6 +1160,7 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
public SMTokens refreshSession(@NotNull String refreshToken) throws DBException {
var currentUserCreds = getCurrentUserCreds();
var currentUserAccessToken = currentUserCreds.getSmToken();
String currentUserAuthRole = null; // FIXME: read role from auth token
var expectedRefreshTokenInfo = findRefreshToken(currentUserAccessToken);
@@ -1154,7 +1170,7 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
try (var dbCon = database.openConnection()) {
invalidateUserTokens(currentUserAccessToken);
return generateNewSessionToken(expectedRefreshTokenInfo.getSessionId(), expectedRefreshTokenInfo.getUserId(), dbCon);
return generateNewSessionToken(expectedRefreshTokenInfo.getSessionId(), expectedRefreshTokenInfo.getUserId(), currentUserAuthRole, dbCon);
} catch (SQLException e) {
throw new DBException("Error refreshing sm session", e);
}
@@ -1223,7 +1239,11 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
return finishAuthentication(authInfo, false, true);
}
private SMAuthInfo finishAuthentication(@NotNull SMAuthInfo authInfo, boolean forceExpireAuthAfterSuccess, boolean saveSecuredCreds) throws DBException {
private SMAuthInfo finishAuthentication(
@NotNull SMAuthInfo authInfo,
boolean forceExpireAuthAfterSuccess,
boolean saveSecuredCreds
) throws DBException {
String authId = authInfo.getAuthAttemptId();
if (authInfo.getAuthStatus() != SMAuthStatus.IN_PROGRESS) {
throw new SMException("Authorization has already been completed with status: " + authInfo.getAuthStatus());
@@ -1233,7 +1253,7 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
throw new SMException("Authorization providers are not defined");
}
var finishAuthMonitor = new VoidProgressMonitor();
DBRProgressMonitor finishAuthMonitor = new LoggingProgressMonitor(log);
AuthAttemptSessionInfo authAttemptSessionInfo = readAuthAttemptSessionInfo(authId);
boolean isMainAuthSession = authAttemptSessionInfo.getSmSessionId() == null;
@@ -1287,8 +1307,9 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
} else {
smSessionId = authAttemptSessionInfo.getSmSessionId();
}
smTokens = generateNewSessionToken(smSessionId, activeUserId, dbCon);
permissions = new SMAuthPermissions(activeUserId, smSessionId, getUserPermissions(activeUserId));
smTokens = generateNewSessionToken(smSessionId, activeUserId, authInfo.getAuthRole(), dbCon);
permissions = new SMAuthPermissions(
activeUserId, smSessionId, getUserPermissions(activeUserId, authInfo.getAuthRole()));
txn.commit();
}
} catch (SQLException e) {
@@ -1364,11 +1385,11 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
userId = userIdFromCredentials;
if (!isSubjectExists(userId)) {
var newUser = new SMUser(userId);
var newUser = new SMUser(userId, true);
createUser(newUser.getUserId(), newUser.getMetaParameters(), true);
String defaultRoleName = WebAppUtils.getWebApplication().getAppConfiguration().getDefaultUserRole();
if (!CommonUtils.isEmpty(defaultRoleName)) {
setUserRoles(userId, new String[]{defaultRoleName}, userId);
String defaultTeamName = WebAppUtils.getWebApplication().getAppConfiguration().getDefaultUserTeam();
if (!CommonUtils.isEmpty(defaultTeamName)) {
setUserTeams(userId, new String[]{defaultTeamName}, userId);
}
}
setUserCredentials(userId, authProviderId, userCredentials);
@@ -1376,9 +1397,9 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
userId = userIdFromCredentials;
}
if (authProvider.isTrusted()) {
Object reverseProxyUserRoles = sessionParameters.get(SMConstants.SESSION_PARAM_TRUSTED_USER_ROLES);
if (reverseProxyUserRoles instanceof List) {
setUserRoles(userId, ((List<?>) reverseProxyUserRoles).stream().map(Object::toString).toArray(String[]::new), userId);
Object reverseProxyUserTeams = sessionParameters.get(SMConstants.SESSION_PARAM_TRUSTED_USER_TEAMS);
if (reverseProxyUserTeams instanceof List) {
setUserTeams(userId, ((List<?>) reverseProxyUserTeams).stream().map(Object::toString).toArray(String[]::new), userId);
}
}
return userId;
@@ -1387,34 +1408,35 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
protected SMTokens generateNewSessionToken(
@NotNull String smSessionId,
@Nullable String userId,
@Nullable String authRole,
@NotNull Connection dbCon
) throws SQLException, DBException {
JDBCUtils.executeStatement(dbCon, "DELETE FROM CB_AUTH_TOKEN WHERE SESSION_ID=?", smSessionId);
return generateNewSessionTokens(smSessionId, userId, dbCon);
return generateNewSessionTokens(smSessionId, userId, authRole, dbCon);
}
private SMTokens generateNewSessionTokens(@NotNull String smSessionId,
@Nullable String userId,
@NotNull Connection dbCon) throws SQLException {
private SMTokens generateNewSessionTokens(
@NotNull String smSessionId,
@Nullable String userId,
@Nullable String authRole,
@NotNull Connection dbCon
) throws SQLException {
try (PreparedStatement dbStat = dbCon.prepareStatement(
"INSERT INTO CB_AUTH_TOKEN(TOKEN_ID,SESSION_ID,USER_ID,EXPIRATION_TIME,REFRESH_TOKEN_ID,REFRESH_TOKEN_EXPIRATION_TIME) " +
"VALUES(?,?,?,?,?,?)")) {
"INSERT INTO CB_AUTH_TOKEN(TOKEN_ID,SESSION_ID,USER_ID,AUTH_ROLE,EXPIRATION_TIME,REFRESH_TOKEN_ID,REFRESH_TOKEN_EXPIRATION_TIME) " +
"VALUES(?,?,?,?,?,?,?)")) {
String smAccessToken = SecurityUtils.generatePassword(32);
dbStat.setString(1, smAccessToken);
dbStat.setString(2, smSessionId);
if (userId == null) {
dbStat.setNull(3, Types.VARCHAR);
} else {
dbStat.setString(3, userId);
}
JDBCUtils.setStringOrNull(dbStat, 3, userId);
JDBCUtils.setStringOrNull(dbStat, 4, authRole);
var accessTokenExpirationTime = Timestamp.valueOf(LocalDateTime.now().plusMinutes(smConfig.getAccessTokenTtl()));
dbStat.setTimestamp(4, accessTokenExpirationTime);
dbStat.setTimestamp(5, accessTokenExpirationTime);
String smRefreshToken = SecurityUtils.generatePassword(32);
dbStat.setString(5, smRefreshToken);
dbStat.setString(6, smRefreshToken);
var refreshTokenExpirationTime = Timestamp.valueOf(LocalDateTime.now().plusMinutes(smConfig.getRefreshTokenTtl()));
dbStat.setTimestamp(6, refreshTokenExpirationTime);
dbStat.setTimestamp(7, refreshTokenExpirationTime);
dbStat.execute();
return new SMTokens(smAccessToken, smRefreshToken);
@@ -1425,8 +1447,9 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
public SMAuthPermissions getTokenPermissions(String token) throws DBException {
String userId;
String sessionId;
String authRole;
try (Connection dbCon = database.openConnection();
PreparedStatement dbStat = dbCon.prepareStatement("SELECT USER_ID, EXPIRATION_TIME, SESSION_ID FROM CB_AUTH_TOKEN WHERE TOKEN_ID=?");
PreparedStatement dbStat = dbCon.prepareStatement("SELECT USER_ID, EXPIRATION_TIME, SESSION_ID, AUTH_ROLE FROM CB_AUTH_TOKEN WHERE TOKEN_ID=?");
) {
dbStat.setString(1, token);
try (var dbResult = dbStat.executeQuery()) {
@@ -1439,11 +1462,12 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
throw new SMAccessTokenExpiredException("Token expired");
}
sessionId = dbResult.getString(3);
authRole = dbResult.getString(4);
}
} catch (SQLException e) {
throw new DBCException("Error reading token info in database", e);
}
var permissions = userId == null ? getAnonymousUserPermissions() : getUserPermissions(userId);
var permissions = userId == null ? getAnonymousUserPermissions() : getUserPermissions(userId, authRole);
return new SMAuthPermissions(userId, sessionId, permissions);
}
@@ -1491,22 +1515,12 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
try (Connection dbCon = database.openConnection()) {
try (PreparedStatement dbStat = dbCon.prepareStatement(
"UPDATE CB_SESSION SET USER_ID=?,LAST_ACCESS_TIME=?,LAST_ACCESS_REMOTE_ADDRESS=?,LAST_ACCESS_USER_AGENT=?,LAST_ACCESS_INSTANCE_ID=? WHERE SESSION_ID=?")) {
if (userId == null) {
dbStat.setNull(1, Types.VARCHAR);
} else {
dbStat.setString(1, userId);
}
JDBCUtils.setStringOrNull(dbStat, 1, userId);
dbStat.setTimestamp(2, new Timestamp(System.currentTimeMillis()));
if (parameters.get(SMConstants.SESSION_PARAM_LAST_REMOTE_ADDRESS) != null) {
dbStat.setString(3, CommonUtils.truncateString(parameters.get(SMConstants.SESSION_PARAM_LAST_REMOTE_ADDRESS).toString(), 128));
} else {
dbStat.setNull(3, Types.VARCHAR);
}
if (parameters.get(SMConstants.SESSION_PARAM_LAST_REMOTE_USER_AGENT) != null) {
dbStat.setString(4, CommonUtils.truncateString(parameters.get(SMConstants.SESSION_PARAM_LAST_REMOTE_USER_AGENT).toString(), 255));
} else {
dbStat.setNull(4, Types.VARCHAR);
}
JDBCUtils.setStringOrNull(dbStat, 3, CommonUtils.truncateString(CommonUtils.toString(
parameters.get(SMConstants.SESSION_PARAM_LAST_REMOTE_ADDRESS), null), 128));
JDBCUtils.setStringOrNull(dbStat, 4, CommonUtils.truncateString(CommonUtils.toString(
parameters.get(SMConstants.SESSION_PARAM_LAST_REMOTE_USER_AGENT), null), 255));
dbStat.setString(5, database.getInstanceId());
dbStat.setString(6, sessionId);
@@ -1630,10 +1644,10 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
private Set<String> getAllLinkedSubjects(String subjectId) throws DBException {
Set<String> allSubjects = new HashSet<>();
allSubjects.add(subjectId);
var userRoleIds = Arrays.stream(getUserRoles(subjectId))
.map(SMRole::getRoleId)
var userTeamIds = Arrays.stream(getUserTeams(subjectId))
.map(SMTeam::getTeamId)
.collect(Collectors.toSet());
allSubjects.addAll(userRoleIds);
allSubjects.addAll(userTeamIds);
return allSubjects;
}
@@ -36,7 +36,7 @@ import org.jkiss.dbeaver.model.impl.jdbc.exec.JDBCTransaction;
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
import org.jkiss.dbeaver.model.runtime.LoggingProgressMonitor;
import org.jkiss.dbeaver.model.security.SMAdminController;
import org.jkiss.dbeaver.model.security.user.SMRole;
import org.jkiss.dbeaver.model.security.user.SMTeam;
import org.jkiss.dbeaver.model.security.user.SMUser;
import org.jkiss.dbeaver.model.sql.schema.ClassLoaderScriptSource;
import org.jkiss.dbeaver.model.sql.schema.SQLSchemaManager;
@@ -68,7 +68,7 @@ public class CBDatabase {
public static final String SCHEMA_UPDATE_SQL_PATH = "db/cb_schema_update_";
private static final int LEGACY_SCHEMA_VERSION = 1;
private static final int CURRENT_SCHEMA_VERSION = 10;
private static final int CURRENT_SCHEMA_VERSION = 11;
private static final String DEFAULT_DB_USER_NAME = "cb-data";
private static final String DEFAULT_DB_PWD_FILE = ".database-credentials.dat";
@@ -245,7 +245,7 @@ public class CBDatabase {
SMUser adminUser = adminSecurityController.getUserById(adminName);
if (adminUser == null) {
adminUser = new SMUser(adminName);
adminUser = new SMUser(adminName, true);
adminSecurityController.createUser(adminUser.getUserId(), adminUser.getMetaParameters(), true);
}
@@ -269,11 +269,11 @@ public class CBDatabase {
}
private void grantAdminPermissionsToUser(String userId) throws DBException {
// Grant all roles
SMRole[] allRoles = adminSecurityController.readAllRoles();
adminSecurityController.setUserRoles(
// Grant all teams
SMTeam[] allTeams = adminSecurityController.readAllTeams();
adminSecurityController.setUserTeams(
userId,
Arrays.stream(allRoles).map(SMRole::getRoleId).toArray(String[]::new),
Arrays.stream(allTeams).map(SMTeam::getTeamId).toArray(String[]::new),
userId);
}
@@ -345,12 +345,12 @@ public class CBDatabase {
String adminName = initialData.getAdminName();
String adminPassword = initialData.getAdminPassword();
if (!CommonUtils.isEmpty(initialData.getRoles())) {
// Create roles
for (SMRole role : initialData.getRoles()) {
adminSecurityController.createRole(role.getRoleId(), role.getName(), role.getDescription(), adminName);
if (!CommonUtils.isEmpty(initialData.getTeams())) {
// Create teams
for (SMTeam team : initialData.getTeams()) {
adminSecurityController.createTeam(team.getTeamId(), team.getName(), team.getDescription(), adminName);
if (adminName != null) {
adminSecurityController.setSubjectPermissions(role.getRoleId(), new ArrayList<>(role.getPermissions()), adminName);
adminSecurityController.setSubjectPermissions(team.getTeamId(), new ArrayList<>(team.getPermissions()), adminName);
}
}
}
@@ -16,14 +16,14 @@
*/
package io.cloudbeaver.service.security.db;
import org.jkiss.dbeaver.model.security.user.SMRole;
import org.jkiss.dbeaver.model.security.user.SMTeam;
import java.util.List;
class CBDatabaseInitialData {
private String adminName = "cbadmin";
private String adminPassword = "cbadmin20";
private List<SMRole> roles;
private List<SMTeam> teams;
public String getAdminName() {
return adminName;
@@ -33,11 +33,11 @@ class CBDatabaseInitialData {
return adminPassword;
}
public List<SMRole> getRoles() {
return roles;
public List<SMTeam> getTeams() {
return teams;
}
public void setRoles(List<SMRole> roles) {
this.roles = roles;
public void setTeams(List<SMTeam> teams) {
this.teams = teams;
}
}
@@ -23,7 +23,7 @@
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-os ${target.os} -ws ${target.ws} -arch ${target.arch} -nl ${target.nl} -consoleLog -web-config conf/cloudbeaver.conf"/>
<stringAttribute key="org.eclipse.jdt.launching.SOURCE_PATH_PROVIDER" value="org.eclipse.pde.ui.workbenchClasspathProvider"/>
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Dosgi.requiredJavaVersion=1.6 -Xms40m -Xmx512m"/>
<stringAttribute key="org.eclipse.jdt.launching.WORKING_DIRECTORY" value="C:\devel\my\cloudbeaver\deploy\cloudbeaver\"/>
<stringAttribute key="org.eclipse.jdt.launching.WORKING_DIRECTORY" value="${workspace_loc}/../opt/cloudbeaver"/>
<stringAttribute key="pde.version" value="3.3"/>
<stringAttribute key="product" value="io.cloudbeaver.product.ce.product"/>
<stringAttribute key="productFile" value="\web-server\DBeaverWebServer.product"/>
@@ -97,7 +97,7 @@
<setEntry value="org.jkiss.bundle.influxdb@default:default"/>
<setEntry value="org.jkiss.bundle.jaxb@default:default"/>
<setEntry value="org.jkiss.bundle.sshj@default:default"/>
<setEntry value="org.objectweb.asm*9.1.0.v20210209-1849@default:default"/>
<setEntry value="org.objectweb.asm@default:default"/>
<setEntry value="org.slf4j.api@default:default"/>
</setAttribute>
<setAttribute key="selected_workspace_bundles">
@@ -50,7 +50,9 @@ public class CEServerTestSuite {
} else {
System.out.println("Start CBApplication");
testApp = new CBApplication();
thread = new Thread(() -> testApp.start(null));
thread = new Thread(() -> {
testApp.start(null);
});
thread.start();
client = HttpClient.newBuilder()
.cookieHandler(new CookieManager())
@@ -1,15 +1,15 @@
{
adminName: "test",
adminPassword: "test",
roles: [
teams: [
{
roleId: "admin",
teamId: "admin",
name: "Admin",
description: "Administrative access. Has all permissions.",
permissions: [ "public", "admin" ]
},
{
roleId: "user",
teamId: "user",
name: "User",
description: "Standard user",
permissions: [ "public" ]
@@ -3,7 +3,7 @@
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<level>DEBUG</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
@@ -1,164 +0,0 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2022 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
import { injectable } from '@cloudbeaver/core-di';
import {
GraphQLService,
CachedMapResource,
ResourceKey,
resourceKeyList,
ResourceKeyList,
ResourceKeyUtils,
AdminRoleInfoFragment,
AdminConnectionGrantInfo,
CachedMapAllKey
} from '@cloudbeaver/core-sdk';
import { isArraysEqual } from '@cloudbeaver/core-utils';
const NEW_ROLE_SYMBOL = Symbol('new-role');
export type RoleInfo = AdminRoleInfoFragment;
type NewRole = RoleInfo & { [NEW_ROLE_SYMBOL]: boolean; timestamp: number };
@injectable()
export class RolesResource extends CachedMapResource<string, RoleInfo> {
constructor(private readonly graphQLService: GraphQLService) {
super();
}
async loadAll(): Promise<Map<string, RoleInfo>> {
await this.load(CachedMapAllKey);
return this.data;
}
async refreshAll(): Promise<Map<string, RoleInfo>> {
await this.refresh(CachedMapAllKey);
return this.data;
}
async createRole(roleInfo: RoleInfo): Promise<RoleInfo> {
const response = await this.graphQLService.sdk.createRole(roleInfo);
const newRole: NewRole = {
...response.role,
[NEW_ROLE_SYMBOL]: true,
timestamp: Date.now(),
};
this.updateRoles(newRole);
await this.setSubjectPermissions(newRole.roleId, roleInfo.rolePermissions);
return this.get(roleInfo.roleId)!;
}
async updateRole(roleInfo: RoleInfo): Promise<RoleInfo> {
const { role } = await this.graphQLService.sdk.updateRole(roleInfo);
this.updateRoles(role);
await this.setSubjectPermissions(role.roleId, roleInfo.rolePermissions);
return this.get(roleInfo.roleId)!;
}
async deleteRole(key: ResourceKey<string>): Promise<Map<string, RoleInfo>> {
await ResourceKeyUtils.forEachAsync(key, async key => {
await this.graphQLService.sdk.deleteRole({
roleId: key,
});
this.delete(key);
});
return this.data;
}
async loadGrantedUsers(roleId: string): Promise<string[]> {
const { role } = await this.graphQLService.sdk.getRoleGrantedUsers({ roleId });
return role[0].grantedUsers;
}
async getSubjectConnectionAccess(subjectId: string): Promise<AdminConnectionGrantInfo[]> {
const { grantInfo } = await this.graphQLService.sdk.getSubjectConnectionAccess({ subjectId });
return grantInfo;
}
async setSubjectPermissions(roleId: string, permissions: string[]): Promise<void> {
const role = this.get(roleId);
if (role && isArraysEqual(role.rolePermissions, permissions)) {
return;
}
const {
permissions: newPermissions,
} = await this.graphQLService.sdk.setSubjectPermissions({ roleId, permissions });
if (role) {
role.rolePermissions = newPermissions.map(permission => permission.id);
} else {
// TODO: update permissions for role instead
await this.loader(roleId);
}
}
protected async loader(key: ResourceKey<string>): Promise<Map<string, RoleInfo>> {
const all = ResourceKeyUtils.includes(key, CachedMapAllKey);
await ResourceKeyUtils.forEachAsync(all ? CachedMapAllKey : key, async key => {
const roleId = all ? undefined : key;
const { roles } = await this.graphQLService.sdk.getRolesList({
roleId,
});
if (all) {
this.data.clear();
}
this.updateRoles(...roles);
});
return this.data;
}
cleanNewFlags(): void {
for (const role of this.data.values()) {
(role as NewRole)[NEW_ROLE_SYMBOL] = false;
}
}
private updateRoles(...roles: RoleInfo[]): ResourceKeyList<string> {
const key = resourceKeyList(roles.map(role => role.roleId));
const oldRoles = this.get(key);
this.set(key, oldRoles.map((role, i) => ({ ...role, ...roles[i] })));
return key;
}
}
function isNewRole(role: RoleInfo | NewRole): role is NewRole {
return (role as NewRole)[NEW_ROLE_SYMBOL];
}
export function compareRoles(a: RoleInfo, b: RoleInfo): number {
if (isNewRole(a) && isNewRole(b)) {
return b.timestamp - a.timestamp;
}
if (isNewRole(b)) {
return 1;
}
if (isNewRole(a)) {
return -1;
}
return a.roleId.localeCompare(b.roleId);
}
@@ -8,12 +8,12 @@
import { injectable } from '@cloudbeaver/core-di';
import { RolesResource } from './RolesResource';
import { TeamsResource } from './TeamsResource';
@injectable()
export class RolesManagerService {
export class TeamsManagerService {
constructor(
readonly roles: RolesResource
readonly teams: TeamsResource
) {
}
}
@@ -0,0 +1,164 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2022 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
import { injectable } from '@cloudbeaver/core-di';
import {
GraphQLService,
CachedMapResource,
ResourceKey,
resourceKeyList,
ResourceKeyList,
ResourceKeyUtils,
AdminTeamInfoFragment,
AdminConnectionGrantInfo,
CachedMapAllKey
} from '@cloudbeaver/core-sdk';
import { isArraysEqual } from '@cloudbeaver/core-utils';
const NEW_TEAM_SYMBOL = Symbol('new-team');
export type TeamInfo = AdminTeamInfoFragment;
type NewTeam = TeamInfo & { [NEW_TEAM_SYMBOL]: boolean; timestamp: number };
@injectable()
export class TeamsResource extends CachedMapResource<string, TeamInfo> {
constructor(private readonly graphQLService: GraphQLService) {
super();
}
async loadAll(): Promise<Map<string, TeamInfo>> {
await this.load(CachedMapAllKey);
return this.data;
}
async refreshAll(): Promise<Map<string, TeamInfo>> {
await this.refresh(CachedMapAllKey);
return this.data;
}
async createTeam(teamInfo: TeamInfo): Promise<TeamInfo> {
const response = await this.graphQLService.sdk.createTeam(teamInfo);
const newTeam: NewTeam = {
...response.team,
[NEW_TEAM_SYMBOL]: true,
timestamp: Date.now(),
};
this.updateTeams(newTeam);
await this.setSubjectPermissions(newTeam.teamId, teamInfo.teamPermissions);
return this.get(teamInfo.teamId)!;
}
async updateTeam(teamInfo: TeamInfo): Promise<TeamInfo> {
const { team } = await this.graphQLService.sdk.updateTeam(teamInfo);
this.updateTeams(team);
await this.setSubjectPermissions(team.teamId, teamInfo.teamPermissions);
return this.get(teamInfo.teamId)!;
}
async deleteTeam(key: ResourceKey<string>): Promise<Map<string, TeamInfo>> {
await ResourceKeyUtils.forEachAsync(key, async key => {
await this.graphQLService.sdk.deleteTeam({
teamId: key,
});
this.delete(key);
});
return this.data;
}
async loadGrantedUsers(teamId: string): Promise<string[]> {
const { team } = await this.graphQLService.sdk.getTeamGrantedUsers({ teamId });
return team[0].grantedUsers;
}
async getSubjectConnectionAccess(subjectId: string): Promise<AdminConnectionGrantInfo[]> {
const { grantInfo } = await this.graphQLService.sdk.getSubjectConnectionAccess({ subjectId });
return grantInfo;
}
async setSubjectPermissions(subjectId: string, permissions: string[]): Promise<void> {
const team = this.get(subjectId);
if (team && isArraysEqual(team.teamPermissions, permissions)) {
return;
}
const {
permissions: newPermissions,
} = await this.graphQLService.sdk.setSubjectPermissions({ subjectId, permissions });
if (team) {
team.teamPermissions = newPermissions.map(permission => permission.id);
} else {
// TODO: update permissions for team instead
await this.loader(subjectId);
}
}
protected async loader(key: ResourceKey<string>): Promise<Map<string, TeamInfo>> {
const all = ResourceKeyUtils.includes(key, CachedMapAllKey);
await ResourceKeyUtils.forEachAsync(all ? CachedMapAllKey : key, async key => {
const teamId = all ? undefined : key;
const { teams } = await this.graphQLService.sdk.getTeamsList({
teamId,
});
if (all) {
this.data.clear();
}
this.updateTeams(...teams);
});
return this.data;
}
cleanNewFlags(): void {
for (const team of this.data.values()) {
(team as NewTeam)[NEW_TEAM_SYMBOL] = false;
}
}
private updateTeams(...teams: TeamInfo[]): ResourceKeyList<string> {
const key = resourceKeyList(teams.map(team => team.teamId));
const oldTeams = this.get(key);
this.set(key, oldTeams.map((team, i) => ({ ...team, ...teams[i] })));
return key;
}
}
function isNewTeam(team: TeamInfo | NewTeam): team is NewTeam {
return (team as NewTeam)[NEW_TEAM_SYMBOL];
}
export function compareTeams(a: TeamInfo, b: TeamInfo): number {
if (isNewTeam(a) && isNewTeam(b)) {
return b.timestamp - a.timestamp;
}
if (isNewTeam(b)) {
return 1;
}
if (isNewTeam(a)) {
return -1;
}
return a.teamId.localeCompare(b.teamId);
}
@@ -37,7 +37,7 @@ type UserResourceIncludes = Omit<GetUsersListQueryVariables, 'userId'>;
interface UserCreateOptions {
userId: string;
roles: string[];
teams: string[];
credentials: IAuthCredentials;
metaParameters: Record<string, any>;
grantedConnections: string[];
@@ -66,7 +66,7 @@ export class UsersResource extends CachedMapResource<string, AdminUser, UserReso
getEmptyUser(): AdminUserInfo {
return {
userId: '',
grantedRoles: [],
grantedTeams: [],
grantedConnections: [],
configurationParameters: {},
metaParameters: {},
@@ -94,7 +94,7 @@ export class UsersResource extends CachedMapResource<string, AdminUser, UserReso
}
async create({
userId, roles, credentials, metaParameters, grantedConnections, enabled,
userId, teams, credentials, metaParameters, grantedConnections, enabled,
}: UserCreateOptions): Promise<AdminUser> {
const { user } = await this.graphQLService.sdk.createUser({
userId,
@@ -106,8 +106,8 @@ export class UsersResource extends CachedMapResource<string, AdminUser, UserReso
try {
await this.updateCredentials(userId, credentials);
for (const roleId of roles) {
await this.grantRole(userId, roleId, true);
for (const teamId of teams) {
await this.grantTeam(userId, teamId, true);
}
await this.setConnections(userId, grantedConnections);
@@ -122,16 +122,16 @@ export class UsersResource extends CachedMapResource<string, AdminUser, UserReso
return this.get(user.userId)!;
}
async grantRole(userId: string, roleId: string, skipUpdate?: boolean): Promise<void> {
await this.graphQLService.sdk.grantUserRole({ userId, roleId });
async grantTeam(userId: string, teamId: string, skipUpdate?: boolean): Promise<void> {
await this.graphQLService.sdk.grantUserTeam({ userId, teamId });
if (!skipUpdate) {
await this.refresh(userId);
}
}
async revokeRole(userId: string, roleId: string, skipUpdate?: boolean): Promise<void> {
await this.graphQLService.sdk.revokeUserRole({ userId, roleId });
async revokeTeam(userId: string, teamId: string, skipUpdate?: boolean): Promise<void> {
await this.graphQLService.sdk.revokeUserTeam({ userId, teamId });
if (!skipUpdate) {
await this.refresh(userId);
@@ -9,8 +9,8 @@ export * from './DATA_CONTEXT_USER';
export * from './IAuthCredentials';
export * from './AuthConfigurationsResource';
export * from './AuthConfigurationParametersResource';
export * from './RolesManagerService';
export * from './RolesResource';
export * from './TeamsManagerService';
export * from './TeamsResource';
export * from './UserDataService';
export * from './UserInfoResource';
export * from './UserMetaParametersResource';
@@ -15,8 +15,8 @@ import { AuthInfoService } from './AuthInfoService';
import { AuthProviderService } from './AuthProviderService';
import { AuthProvidersResource } from './AuthProvidersResource';
import { AuthSettingsService } from './AuthSettingsService';
import { RolesManagerService } from './RolesManagerService';
import { RolesResource } from './RolesResource';
import { TeamsManagerService } from './TeamsManagerService';
import { TeamsResource } from './TeamsResource';
import { UserConfigurationBootstrap } from './UserConfigurationBootstrap';
import { UserDataService } from './UserDataService';
import { UserInfoResource } from './UserInfoResource';
@@ -36,8 +36,8 @@ export const manifest: PluginManifest = {
AuthSettingsService,
AuthConfigurationsResource,
AuthConfigurationParametersResource,
RolesManagerService,
RolesResource,
TeamsManagerService,
TeamsResource,
UserDataService,
UserInfoResource,
UsersResource,
+1
View File
@@ -146,6 +146,7 @@ export * from './Link';
export * from './Cell';
export * from './UploadArea';
export * from './ErrorMessage';
export * from './preventFocusHandler';
export * from './StatusMessage';
export * from './ExceptionMessage';
export * from './getComputed';
@@ -0,0 +1,11 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2022 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
export function preventFocusHandler(event: React.MouseEvent<HTMLElement>) {
event.preventDefault();
}

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

@@ -5,7 +5,7 @@ export default [
['connections_administration_new_connection', 'New connection'],
['connections_administration_connection_create_error', 'Create connection error'],
['connections_administration_connection_save_error', 'Save connection error'],
['connections_administration_connection_access_empty', 'No available users and roles'],
['connections_administration_connection_access_empty', 'No available users and teams'],
['connections_administration_configuration_wizard_step_title', 'Database connections'],
['connections_administration_configuration_wizard_step_description', 'Add database connections'],
['connections_administration_configuration_wizard_title', 'Add database connections'],
@@ -28,15 +28,15 @@ export default [
['connections_connection_edit_authentication', 'Authentication'],
['connections_connection_edit_access', 'Access'],
['connections_connection_edit_access_load_failed', 'Fail to get connection access'],
['connections_connection_edit_access_role', 'Role'],
['connections_connection_edit_access_team', 'Team'],
['connections_connection_edit_search', 'Search'],
['connections_connection_edit_search_hosts', 'Host names'],
['connections_connection_address', 'Address'],
['connections_connection_folder', 'Folder'],
['connections_connection_folder_validation', 'Folder\'s name may contain the following symbols "_-$.()@" and can\'t start with a dot'],
['connections_connection_name', 'Connection name'],
['connections_connection_access_user_or_role_name', 'User or Role name'],
['connections_connection_access_filter_placeholder', 'Search for user or role name'],
['connections_connection_access_user_or_team_name', 'User or Team name'],
['connections_connection_access_filter_placeholder', 'Search for user or team name'],
['connections_connection_access_admin_info', 'Administrators see all connections.'],
['connections_connection_description', 'Description'],
['connections_connection_project', 'Project'],
@@ -5,7 +5,6 @@ export default [
['connections_administration_new_connection', 'Nuova Connessione'],
['connections_administration_connection_create_error', 'Errore di creazione connessione'],
['connections_administration_connection_save_error', 'Errore di salvataggio connessione'],
['connections_administration_connection_access_empty', 'Non ci sono utenti e ruoli disponibili'],
['connections_administration_configuration_wizard_step_title', 'Connessioni ai Database'],
['connections_administration_configuration_wizard_step_description', 'Aggiungi connessione al database'],
['connections_administration_configuration_wizard_title', 'Aggiungi connessione al database'],
@@ -27,18 +26,15 @@ export default [
['connections_connection_edit_authentication', 'Autenticazione'],
['connections_connection_edit_access', 'Accesso'],
['connections_connection_edit_access_load_failed', 'Errore al recupero dell\'accesso alla connessione'],
['connections_connection_edit_access_role', 'Ruolo'],
['connections_connection_edit_search', 'Cerca'],
['connections_connection_edit_search_hosts', 'Host names'],
['connections_connection_address', 'Indirizzo'],
['connections_connection_folder', 'Folder'],
['connections_connection_folder_validation', 'Folder\'s name may contain the following symbols "_-$.()@" and can\'t start with a dot'],
['connections_connection_name', 'Nome della connessione'],
['connections_connection_access_user_or_role_name', 'Nome dell\'Utente o del ruolo'],
['connections_connection_access_revoke', 'Revoca'],
['connections_connection_access_grant', 'Permetti'],
['connections_connection_access_edit', 'Modifica'],
['connections_connection_access_filter_placeholder', 'Cerca per utente o ruolo'],
['connections_connection_access_admin_info', 'Gli amministratori vedono tutte le connessioni.'],
['connections_connection_description', 'Descrizione'],
['connections_connection_driver', 'Driver'],
@@ -25,15 +25,15 @@ export default [
['connections_connection_edit_authentication', 'Авторизация'],
['connections_connection_edit_access', 'Доступ'],
['connections_connection_edit_access_load_failed', 'Не удалось загрузить информацию доступа'],
['connections_connection_edit_access_role', 'Роль'],
['connections_connection_edit_access_team', 'Команда'],
['connections_connection_edit_search', 'Поиск'],
['connections_connection_edit_search_hosts', 'Названия хостов'],
['connections_connection_address', 'Адрес'],
['connections_connection_folder', 'Папка'],
['connections_connection_folder_validation', 'Имя папки может содержать следующие символы "_-$.()@" и не может начинаться с точки'],
['connections_connection_name', 'Название подключения'],
['connections_connection_access_user_or_role_name', 'Имя пользователя или роли'],
['connections_connection_access_filter_placeholder', 'Поиск по имени пользователя или роли'],
['connections_connection_access_user_or_team_name', 'Имя пользователя или команды'],
['connections_connection_access_filter_placeholder', 'Поиск по имени пользователя или команде'],
['connections_connection_access_admin_info', 'Администраторы видят все подключения.'],
['connections_connection_description', 'Описание'],
['connections_connection_project', 'Проект'],
@@ -5,7 +5,6 @@ export default [
['connections_administration_new_connection', '新连接'],
['connections_administration_connection_create_error', '创建连接失败'],
['connections_administration_connection_save_error', '保存链接失败'],
['connections_administration_connection_access_empty', '没有可用用户和角色'],
['connections_administration_configuration_wizard_step_title', '数据库连接'],
['connections_administration_configuration_wizard_step_description', '添加数据库连接'],
['connections_administration_configuration_wizard_title', '添加数据库连接'],
@@ -28,15 +27,12 @@ export default [
['connections_connection_edit_authentication', '认证'],
['connections_connection_edit_access', '权限'],
['connections_connection_edit_access_load_failed', '无法获取连接访问权限'],
['connections_connection_edit_access_role', '角色'],
['connections_connection_edit_search', '搜索'],
['connections_connection_edit_search_hosts', '主机名称'],
['connections_connection_address', '地址'],
['connections_connection_folder', 'Folder'],
['connections_connection_folder_validation', 'Folder\'s name may contain the following symbols "_-$.()@" and can\'t start with a dot'],
['connections_connection_name', '连接名称'],
['connections_connection_access_user_or_role_name', '用户或角色名称'],
['connections_connection_access_filter_placeholder', '搜索用户或角色名称'],
['connections_connection_access_admin_info', '管理员查看所有连接。'],
['connections_connection_description', '描述'],
['connections_connection_project', 'Project'],
@@ -1,5 +1,5 @@
query setSubjectPermissions($roleId: ID!, $permissions: [ID!]! ) {
permissions: setSubjectPermissions(roleId: $roleId, permissions: $permissions) {
query setSubjectPermissions($subjectId: ID!, $permissions: [ID!]! ) {
permissions: setSubjectPermissions(subjectId: $subjectId, permissions: $permissions) {
...AdminPermissionInfo
}
}
@@ -1,5 +0,0 @@
query createRole($roleId: ID!, $roleName: String, $description: String ) {
role: createRole(roleId: $roleId, roleName: $roleName, description: $description) {
...AdminRoleInfo
}
}
@@ -1,3 +0,0 @@
query deleteRole($roleId: ID!) {
deleteRole(roleId: $roleId)
}
@@ -1,5 +0,0 @@
query getRoleGrantedUsers($roleId: ID!) {
role: listRoles(roleId: $roleId) {
grantedUsers
}
}
@@ -1,5 +0,0 @@
query getRolesList($roleId: ID) {
roles: listRoles(roleId: $roleId) {
...AdminRoleInfo
}
}
@@ -1,5 +0,0 @@
query updateRole($roleId: ID!, $roleName: String, $description: String ) {
role: updateRole(roleId: $roleId, roleName: $roleName, description: $description) {
...AdminRoleInfo
}
}
@@ -0,0 +1,5 @@
query createTeam($teamId: ID!, $teamName: String, $description: String ) {
team: createTeam(teamId: $teamId, teamName: $teamName, description: $description) {
...AdminTeamInfo
}
}
@@ -0,0 +1,3 @@
query deleteTeam($teamId: ID!) {
deleteTeam(teamId: $teamId)
}
@@ -0,0 +1,5 @@
query getTeamGrantedUsers($teamId: ID!) {
team: listTeams(teamId: $teamId) {
grantedUsers
}
}
@@ -0,0 +1,5 @@
query getTeamsList($teamId: ID) {
teams: listTeams(teamId: $teamId) {
...AdminTeamInfo
}
}
@@ -0,0 +1,5 @@
query updateTeam($teamId: ID!, $teamName: String, $description: String ) {
team: updateTeam(teamId: $teamId, teamName: $teamName, description: $description) {
...AdminTeamInfo
}
}
@@ -1,3 +0,0 @@
query grantUserRole($userId: ID!, $roleId: ID!) {
grantUserRole(userId: $userId, roleId: $roleId)
}
@@ -0,0 +1,3 @@
query grantUserTeam($userId: ID!, $teamId: ID!) {
grantUserTeam(userId: $userId, teamId: $teamId)
}
@@ -1,3 +0,0 @@
query revokeUserRole($userId: ID!, $roleId: ID!) {
revokeUserRole(userId: $userId, roleId: $roleId)
}
@@ -0,0 +1,3 @@
query revokeUserTeam($userId: ID!, $teamId: ID!) {
revokeUserTeam(userId: $userId, teamId: $teamId)
}
@@ -1,6 +0,0 @@
fragment AdminRoleInfo on AdminRoleInfo {
roleId
roleName
description
rolePermissions
}
@@ -0,0 +1,6 @@
fragment AdminTeamInfo on AdminTeamInfo {
teamId
teamName
description
teamPermissions
}
@@ -1,6 +1,6 @@
fragment AdminUserInfo on AdminUserInfo {
userId
grantedRoles
grantedTeams
linkedAuthProviders
metaParameters @include(if: $includeMetaParameters)
+158 -155
View File
@@ -66,25 +66,25 @@ export interface AdminPermissionInfo {
provider: Scalars['String'];
}
export interface AdminRoleInfo {
export enum AdminSubjectType {
Team = 'team',
User = 'user'
}
export interface AdminTeamInfo {
description?: Maybe<Scalars['String']>;
grantedConnections: Array<AdminConnectionGrantInfo>;
grantedUsers: Array<Scalars['ID']>;
roleId: Scalars['ID'];
roleName?: Maybe<Scalars['String']>;
rolePermissions: Array<Scalars['ID']>;
}
export enum AdminSubjectType {
Role = 'role',
User = 'user'
teamId: Scalars['ID'];
teamName?: Maybe<Scalars['String']>;
teamPermissions: Array<Scalars['ID']>;
}
export interface AdminUserInfo {
configurationParameters: Scalars['Object'];
enabled: Scalars['Boolean'];
grantedConnections: Array<AdminConnectionGrantInfo>;
grantedRoles: Array<Scalars['ID']>;
grantedTeams: Array<Scalars['ID']>;
linkedAuthProviders: Array<Scalars['String']>;
metaParameters: Scalars['Object'];
origins: Array<ObjectOrigin>;
@@ -877,7 +877,7 @@ export interface Query {
connectionInfo: ConnectionInfo;
copyConnectionConfiguration: ConnectionInfo;
createConnectionConfiguration: ConnectionInfo;
createRole: AdminRoleInfo;
createTeam: AdminTeamInfo;
createUser: AdminUserInfo;
dataTransferAvailableStreamProcessors: Array<DataTransferProcessorInfo>;
dataTransferDefaultExportSettings: DataTransferDefaultExportSettings;
@@ -886,20 +886,20 @@ export interface Query {
dataTransferRemoveDataFile?: Maybe<Scalars['Boolean']>;
deleteAuthProviderConfiguration: Scalars['Boolean'];
deleteConnectionConfiguration?: Maybe<Scalars['Boolean']>;
deleteRole?: Maybe<Scalars['Boolean']>;
deleteTeam?: Maybe<Scalars['Boolean']>;
deleteUser?: Maybe<Scalars['Boolean']>;
deleteUserMetaParameter: Scalars['Boolean'];
driverList: Array<DriverInfo>;
enableUser?: Maybe<Scalars['Boolean']>;
getConnectionSubjectAccess: Array<AdminConnectionGrantInfo>;
getSubjectConnectionAccess: Array<AdminConnectionGrantInfo>;
grantUserRole?: Maybe<Scalars['Boolean']>;
grantUserTeam?: Maybe<Scalars['Boolean']>;
listAuthProviderConfigurationParameters: Array<ObjectPropertyInfo>;
listAuthProviderConfigurations: Array<AdminAuthProviderConfiguration>;
listFeatureSets: Array<WebFeatureSet>;
listPermissions: Array<AdminPermissionInfo>;
listProjects: Array<ProjectInfo>;
listRoles: Array<AdminRoleInfo>;
listTeams: Array<AdminTeamInfo>;
listUserProfileProperties: Array<ObjectPropertyInfo>;
listUsers: Array<AdminUserInfo>;
metadataGetNodeDDL?: Maybe<Scalars['String']>;
@@ -910,7 +910,7 @@ export interface Query {
navRefreshNode?: Maybe<Scalars['Boolean']>;
networkHandlers: Array<NetworkHandlerDescriptor>;
readSessionLog: Array<LogEntry>;
revokeUserRole?: Maybe<Scalars['Boolean']>;
revokeUserTeam?: Maybe<Scalars['Boolean']>;
rmListProjectGrantedPermissions: Array<AdminObjectGrantInfo>;
rmListProjectPermissions: Array<AdminPermissionInfo>;
rmListProjects: Array<RmProject>;
@@ -942,7 +942,7 @@ export interface Query {
sqlSupportedOperations: Array<DataTypeLogicalOperation>;
templateConnections: Array<ConnectionInfo>;
updateConnectionConfiguration: ConnectionInfo;
updateRole: AdminRoleInfo;
updateTeam: AdminTeamInfo;
userConnections: Array<ConnectionInfo>;
}
@@ -1006,10 +1006,10 @@ export interface QueryCreateConnectionConfigurationArgs {
}
export interface QueryCreateRoleArgs {
export interface QueryCreateTeamArgs {
description?: InputMaybe<Scalars['String']>;
roleId: Scalars['ID'];
roleName?: InputMaybe<Scalars['String']>;
teamId: Scalars['ID'];
teamName?: InputMaybe<Scalars['String']>;
}
@@ -1051,8 +1051,8 @@ export interface QueryDeleteConnectionConfigurationArgs {
}
export interface QueryDeleteRoleArgs {
roleId: Scalars['ID'];
export interface QueryDeleteTeamArgs {
teamId: Scalars['ID'];
}
@@ -1088,8 +1088,8 @@ export interface QueryGetSubjectConnectionAccessArgs {
}
export interface QueryGrantUserRoleArgs {
roleId: Scalars['ID'];
export interface QueryGrantUserTeamArgs {
teamId: Scalars['ID'];
userId: Scalars['ID'];
}
@@ -1104,8 +1104,8 @@ export interface QueryListAuthProviderConfigurationsArgs {
}
export interface QueryListRolesArgs {
roleId?: InputMaybe<Scalars['ID']>;
export interface QueryListTeamsArgs {
teamId?: InputMaybe<Scalars['ID']>;
}
@@ -1157,8 +1157,8 @@ export interface QueryReadSessionLogArgs {
}
export interface QueryRevokeUserRoleArgs {
roleId: Scalars['ID'];
export interface QueryRevokeUserTeamArgs {
teamId: Scalars['ID'];
userId: Scalars['ID'];
}
@@ -1237,7 +1237,7 @@ export interface QuerySetSubjectConnectionAccessArgs {
export interface QuerySetSubjectPermissionsArgs {
permissions: Array<Scalars['ID']>;
roleId: Scalars['ID'];
subjectId: Scalars['ID'];
}
@@ -1333,10 +1333,10 @@ export interface QueryUpdateConnectionConfigurationArgs {
}
export interface QueryUpdateRoleArgs {
export interface QueryUpdateTeamArgs {
description?: InputMaybe<Scalars['String']>;
roleId: Scalars['ID'];
roleName?: InputMaybe<Scalars['String']>;
teamId: Scalars['ID'];
teamName?: InputMaybe<Scalars['String']>;
}
@@ -1629,7 +1629,7 @@ export type GetPermissionsListQueryVariables = Exact<{ [key: string]: never; }>;
export type GetPermissionsListQuery = { permissions: Array<{ id: string, label?: string, description?: string, category?: string }> };
export type SetSubjectPermissionsQueryVariables = Exact<{
roleId: Scalars['ID'];
subjectId: Scalars['ID'];
permissions: Array<Scalars['ID']> | Scalars['ID'];
}>;
@@ -1643,45 +1643,6 @@ export type AsyncTaskCancelMutationVariables = Exact<{
export type AsyncTaskCancelMutation = { result?: boolean };
export type CreateRoleQueryVariables = Exact<{
roleId: Scalars['ID'];
roleName?: InputMaybe<Scalars['String']>;
description?: InputMaybe<Scalars['String']>;
}>;
export type CreateRoleQuery = { role: { roleId: string, roleName?: string, description?: string, rolePermissions: Array<string> } };
export type DeleteRoleQueryVariables = Exact<{
roleId: Scalars['ID'];
}>;
export type DeleteRoleQuery = { deleteRole?: boolean };
export type GetRoleGrantedUsersQueryVariables = Exact<{
roleId: Scalars['ID'];
}>;
export type GetRoleGrantedUsersQuery = { role: Array<{ grantedUsers: Array<string> }> };
export type GetRolesListQueryVariables = Exact<{
roleId?: InputMaybe<Scalars['ID']>;
}>;
export type GetRolesListQuery = { roles: Array<{ roleId: string, roleName?: string, description?: string, rolePermissions: Array<string> }> };
export type UpdateRoleQueryVariables = Exact<{
roleId: Scalars['ID'];
roleName?: InputMaybe<Scalars['String']>;
description?: InputMaybe<Scalars['String']>;
}>;
export type UpdateRoleQuery = { role: { roleId: string, roleName?: string, description?: string, rolePermissions: Array<string> } };
export type AuthChangeLocalPasswordQueryVariables = Exact<{
oldPassword: Scalars['String'];
newPassword: Scalars['String'];
@@ -1776,6 +1737,45 @@ export type SaveUserMetaParametersQueryVariables = Exact<{
export type SaveUserMetaParametersQuery = { setUserMetaParameterValues: boolean };
export type CreateTeamQueryVariables = Exact<{
teamId: Scalars['ID'];
teamName?: InputMaybe<Scalars['String']>;
description?: InputMaybe<Scalars['String']>;
}>;
export type CreateTeamQuery = { team: { teamId: string, teamName?: string, description?: string, teamPermissions: Array<string> } };
export type DeleteTeamQueryVariables = Exact<{
teamId: Scalars['ID'];
}>;
export type DeleteTeamQuery = { deleteTeam?: boolean };
export type GetTeamGrantedUsersQueryVariables = Exact<{
teamId: Scalars['ID'];
}>;
export type GetTeamGrantedUsersQuery = { team: Array<{ grantedUsers: Array<string> }> };
export type GetTeamsListQueryVariables = Exact<{
teamId?: InputMaybe<Scalars['ID']>;
}>;
export type GetTeamsListQuery = { teams: Array<{ teamId: string, teamName?: string, description?: string, teamPermissions: Array<string> }> };
export type UpdateTeamQueryVariables = Exact<{
teamId: Scalars['ID'];
teamName?: InputMaybe<Scalars['String']>;
description?: InputMaybe<Scalars['String']>;
}>;
export type UpdateTeamQuery = { team: { teamId: string, teamName?: string, description?: string, teamPermissions: Array<string> } };
export type CreateUserQueryVariables = Exact<{
userId: Scalars['ID'];
enabled: Scalars['Boolean'];
@@ -1784,7 +1784,7 @@ export type CreateUserQueryVariables = Exact<{
}>;
export type CreateUserQuery = { user: { userId: string, grantedRoles: Array<string>, linkedAuthProviders: Array<string>, metaParameters?: any, enabled: boolean, origins: Array<{ type: string, subType?: string, displayName: string, icon?: string, details?: Array<{ id?: string, displayName?: string, description?: string, category?: string, dataType?: string, defaultValue?: any, validValues?: Array<any>, value?: any, length: ObjectPropertyLength, features: Array<string>, order: number }> }> } };
export type CreateUserQuery = { user: { userId: string, grantedTeams: Array<string>, linkedAuthProviders: Array<string>, metaParameters?: any, enabled: boolean, origins: Array<{ type: string, subType?: string, displayName: string, icon?: string, details?: Array<{ id?: string, displayName?: string, description?: string, category?: string, dataType?: string, defaultValue?: any, validValues?: Array<any>, value?: any, length: ObjectPropertyLength, features: Array<string>, order: number }> }> } };
export type DeleteUserQueryVariables = Exact<{
userId: Scalars['ID'];
@@ -1822,23 +1822,23 @@ export type GetUsersListQueryVariables = Exact<{
}>;
export type GetUsersListQuery = { users: Array<{ userId: string, grantedRoles: Array<string>, linkedAuthProviders: Array<string>, metaParameters?: any, enabled: boolean, origins: Array<{ type: string, subType?: string, displayName: string, icon?: string, details?: Array<{ id?: string, displayName?: string, description?: string, category?: string, dataType?: string, defaultValue?: any, validValues?: Array<any>, value?: any, length: ObjectPropertyLength, features: Array<string>, order: number }> }> }> };
export type GetUsersListQuery = { users: Array<{ userId: string, grantedTeams: Array<string>, linkedAuthProviders: Array<string>, metaParameters?: any, enabled: boolean, origins: Array<{ type: string, subType?: string, displayName: string, icon?: string, details?: Array<{ id?: string, displayName?: string, description?: string, category?: string, dataType?: string, defaultValue?: any, validValues?: Array<any>, value?: any, length: ObjectPropertyLength, features: Array<string>, order: number }> }> }> };
export type GrantUserRoleQueryVariables = Exact<{
export type GrantUserTeamQueryVariables = Exact<{
userId: Scalars['ID'];
roleId: Scalars['ID'];
teamId: Scalars['ID'];
}>;
export type GrantUserRoleQuery = { grantUserRole?: boolean };
export type GrantUserTeamQuery = { grantUserTeam?: boolean };
export type RevokeUserRoleQueryVariables = Exact<{
export type RevokeUserTeamQueryVariables = Exact<{
userId: Scalars['ID'];
roleId: Scalars['ID'];
teamId: Scalars['ID'];
}>;
export type RevokeUserRoleQuery = { revokeUserRole?: boolean };
export type RevokeUserTeamQuery = { revokeUserTeam?: boolean };
export type SetConnectionsQueryVariables = Exact<{
userId: Scalars['ID'];
@@ -2247,9 +2247,9 @@ export type AdminObjectGrantInfoFragment = { subjectId: string, subjectType: Adm
export type AdminPermissionInfoFragment = { id: string, label?: string, description?: string, category?: string };
export type AdminRoleInfoFragment = { roleId: string, roleName?: string, description?: string, rolePermissions: Array<string> };
export type AdminTeamInfoFragment = { teamId: string, teamName?: string, description?: string, teamPermissions: Array<string> };
export type AdminUserInfoFragment = { userId: string, grantedRoles: Array<string>, linkedAuthProviders: Array<string>, metaParameters?: any, enabled: boolean, origins: Array<{ type: string, subType?: string, displayName: string, icon?: string, details?: Array<{ id?: string, displayName?: string, description?: string, category?: string, dataType?: string, defaultValue?: any, validValues?: Array<any>, value?: any, length: ObjectPropertyLength, features: Array<string>, order: number }> }> };
export type AdminUserInfoFragment = { userId: string, grantedTeams: Array<string>, linkedAuthProviders: Array<string>, metaParameters?: any, enabled: boolean, origins: Array<{ type: string, subType?: string, displayName: string, icon?: string, details?: Array<{ id?: string, displayName?: string, description?: string, category?: string, dataType?: string, defaultValue?: any, validValues?: Array<any>, value?: any, length: ObjectPropertyLength, features: Array<string>, order: number }> }> };
export type AllNavigatorSettingsFragment = { showSystemObjects: boolean, showUtilityObjects: boolean, showOnlyEntities: boolean, mergeEntities: boolean, hideFolders: boolean, hideSchemas: boolean, hideVirtualModel: boolean };
@@ -2753,12 +2753,12 @@ export const AdminPermissionInfoFragmentDoc = `
category
}
`;
export const AdminRoleInfoFragmentDoc = `
fragment AdminRoleInfo on AdminRoleInfo {
roleId
roleName
export const AdminTeamInfoFragmentDoc = `
fragment AdminTeamInfo on AdminTeamInfo {
teamId
teamName
description
rolePermissions
teamPermissions
}
`;
export const ObjectOriginInfoFragmentDoc = `
@@ -2785,7 +2785,7 @@ export const ObjectOriginInfoFragmentDoc = `
export const AdminUserInfoFragmentDoc = `
fragment AdminUserInfo on AdminUserInfo {
userId
grantedRoles
grantedTeams
linkedAuthProviders
metaParameters @include(if: $includeMetaParameters)
origins {
@@ -3111,8 +3111,11 @@ export const GetPermissionsListDocument = `
}
${AdminPermissionInfoFragmentDoc}`;
export const SetSubjectPermissionsDocument = `
query setSubjectPermissions($roleId: ID!, $permissions: [ID!]!) {
permissions: setSubjectPermissions(roleId: $roleId, permissions: $permissions) {
query setSubjectPermissions($subjectId: ID!, $permissions: [ID!]!) {
permissions: setSubjectPermissions(
subjectId: $subjectId
permissions: $permissions
) {
...AdminPermissionInfo
}
}
@@ -3122,47 +3125,6 @@ export const AsyncTaskCancelDocument = `
result: asyncTaskCancel(id: $taskId)
}
`;
export const CreateRoleDocument = `
query createRole($roleId: ID!, $roleName: String, $description: String) {
role: createRole(
roleId: $roleId
roleName: $roleName
description: $description
) {
...AdminRoleInfo
}
}
${AdminRoleInfoFragmentDoc}`;
export const DeleteRoleDocument = `
query deleteRole($roleId: ID!) {
deleteRole(roleId: $roleId)
}
`;
export const GetRoleGrantedUsersDocument = `
query getRoleGrantedUsers($roleId: ID!) {
role: listRoles(roleId: $roleId) {
grantedUsers
}
}
`;
export const GetRolesListDocument = `
query getRolesList($roleId: ID) {
roles: listRoles(roleId: $roleId) {
...AdminRoleInfo
}
}
${AdminRoleInfoFragmentDoc}`;
export const UpdateRoleDocument = `
query updateRole($roleId: ID!, $roleName: String, $description: String) {
role: updateRole(
roleId: $roleId
roleName: $roleName
description: $description
) {
...AdminRoleInfo
}
}
${AdminRoleInfoFragmentDoc}`;
export const AuthChangeLocalPasswordDocument = `
query authChangeLocalPassword($oldPassword: String!, $newPassword: String!) {
authChangeLocalPassword(oldPassword: $oldPassword, newPassword: $newPassword)
@@ -3289,6 +3251,47 @@ export const SaveUserMetaParametersDocument = `
setUserMetaParameterValues(userId: $userId, parameters: $parameters)
}
`;
export const CreateTeamDocument = `
query createTeam($teamId: ID!, $teamName: String, $description: String) {
team: createTeam(
teamId: $teamId
teamName: $teamName
description: $description
) {
...AdminTeamInfo
}
}
${AdminTeamInfoFragmentDoc}`;
export const DeleteTeamDocument = `
query deleteTeam($teamId: ID!) {
deleteTeam(teamId: $teamId)
}
`;
export const GetTeamGrantedUsersDocument = `
query getTeamGrantedUsers($teamId: ID!) {
team: listTeams(teamId: $teamId) {
grantedUsers
}
}
`;
export const GetTeamsListDocument = `
query getTeamsList($teamId: ID) {
teams: listTeams(teamId: $teamId) {
...AdminTeamInfo
}
}
${AdminTeamInfoFragmentDoc}`;
export const UpdateTeamDocument = `
query updateTeam($teamId: ID!, $teamName: String, $description: String) {
team: updateTeam(
teamId: $teamId
teamName: $teamName
description: $description
) {
...AdminTeamInfo
}
}
${AdminTeamInfoFragmentDoc}`;
export const CreateUserDocument = `
query createUser($userId: ID!, $enabled: Boolean!, $includeMetaParameters: Boolean!, $customIncludeOriginDetails: Boolean!) {
user: createUser(userId: $userId, enabled: $enabled) {
@@ -3328,14 +3331,14 @@ export const GetUsersListDocument = `
}
}
${AdminUserInfoFragmentDoc}`;
export const GrantUserRoleDocument = `
query grantUserRole($userId: ID!, $roleId: ID!) {
grantUserRole(userId: $userId, roleId: $roleId)
export const GrantUserTeamDocument = `
query grantUserTeam($userId: ID!, $teamId: ID!) {
grantUserTeam(userId: $userId, teamId: $teamId)
}
`;
export const RevokeUserRoleDocument = `
query revokeUserRole($userId: ID!, $roleId: ID!) {
revokeUserRole(userId: $userId, roleId: $roleId)
export const RevokeUserTeamDocument = `
query revokeUserTeam($userId: ID!, $teamId: ID!) {
revokeUserTeam(userId: $userId, teamId: $teamId)
}
`;
export const SetConnectionsDocument = `
@@ -4399,21 +4402,6 @@ export function getSdk(client: GraphQLClient, withWrapper: SdkFunctionWrapper =
asyncTaskCancel(variables: AsyncTaskCancelMutationVariables, requestHeaders?: Dom.RequestInit["headers"]): Promise<AsyncTaskCancelMutation> {
return withWrapper((wrappedRequestHeaders) => client.request<AsyncTaskCancelMutation>(AsyncTaskCancelDocument, variables, {...requestHeaders, ...wrappedRequestHeaders}), 'asyncTaskCancel', 'mutation');
},
createRole(variables: CreateRoleQueryVariables, requestHeaders?: Dom.RequestInit["headers"]): Promise<CreateRoleQuery> {
return withWrapper((wrappedRequestHeaders) => client.request<CreateRoleQuery>(CreateRoleDocument, variables, {...requestHeaders, ...wrappedRequestHeaders}), 'createRole', 'query');
},
deleteRole(variables: DeleteRoleQueryVariables, requestHeaders?: Dom.RequestInit["headers"]): Promise<DeleteRoleQuery> {
return withWrapper((wrappedRequestHeaders) => client.request<DeleteRoleQuery>(DeleteRoleDocument, variables, {...requestHeaders, ...wrappedRequestHeaders}), 'deleteRole', 'query');
},
getRoleGrantedUsers(variables: GetRoleGrantedUsersQueryVariables, requestHeaders?: Dom.RequestInit["headers"]): Promise<GetRoleGrantedUsersQuery> {
return withWrapper((wrappedRequestHeaders) => client.request<GetRoleGrantedUsersQuery>(GetRoleGrantedUsersDocument, variables, {...requestHeaders, ...wrappedRequestHeaders}), 'getRoleGrantedUsers', 'query');
},
getRolesList(variables?: GetRolesListQueryVariables, requestHeaders?: Dom.RequestInit["headers"]): Promise<GetRolesListQuery> {
return withWrapper((wrappedRequestHeaders) => client.request<GetRolesListQuery>(GetRolesListDocument, variables, {...requestHeaders, ...wrappedRequestHeaders}), 'getRolesList', 'query');
},
updateRole(variables: UpdateRoleQueryVariables, requestHeaders?: Dom.RequestInit["headers"]): Promise<UpdateRoleQuery> {
return withWrapper((wrappedRequestHeaders) => client.request<UpdateRoleQuery>(UpdateRoleDocument, variables, {...requestHeaders, ...wrappedRequestHeaders}), 'updateRole', 'query');
},
authChangeLocalPassword(variables: AuthChangeLocalPasswordQueryVariables, requestHeaders?: Dom.RequestInit["headers"]): Promise<AuthChangeLocalPasswordQuery> {
return withWrapper((wrappedRequestHeaders) => client.request<AuthChangeLocalPasswordQuery>(AuthChangeLocalPasswordDocument, variables, {...requestHeaders, ...wrappedRequestHeaders}), 'authChangeLocalPassword', 'query');
},
@@ -4450,6 +4438,21 @@ export function getSdk(client: GraphQLClient, withWrapper: SdkFunctionWrapper =
saveUserMetaParameters(variables: SaveUserMetaParametersQueryVariables, requestHeaders?: Dom.RequestInit["headers"]): Promise<SaveUserMetaParametersQuery> {
return withWrapper((wrappedRequestHeaders) => client.request<SaveUserMetaParametersQuery>(SaveUserMetaParametersDocument, variables, {...requestHeaders, ...wrappedRequestHeaders}), 'saveUserMetaParameters', 'query');
},
createTeam(variables: CreateTeamQueryVariables, requestHeaders?: Dom.RequestInit["headers"]): Promise<CreateTeamQuery> {
return withWrapper((wrappedRequestHeaders) => client.request<CreateTeamQuery>(CreateTeamDocument, variables, {...requestHeaders, ...wrappedRequestHeaders}), 'createTeam', 'query');
},
deleteTeam(variables: DeleteTeamQueryVariables, requestHeaders?: Dom.RequestInit["headers"]): Promise<DeleteTeamQuery> {
return withWrapper((wrappedRequestHeaders) => client.request<DeleteTeamQuery>(DeleteTeamDocument, variables, {...requestHeaders, ...wrappedRequestHeaders}), 'deleteTeam', 'query');
},
getTeamGrantedUsers(variables: GetTeamGrantedUsersQueryVariables, requestHeaders?: Dom.RequestInit["headers"]): Promise<GetTeamGrantedUsersQuery> {
return withWrapper((wrappedRequestHeaders) => client.request<GetTeamGrantedUsersQuery>(GetTeamGrantedUsersDocument, variables, {...requestHeaders, ...wrappedRequestHeaders}), 'getTeamGrantedUsers', 'query');
},
getTeamsList(variables?: GetTeamsListQueryVariables, requestHeaders?: Dom.RequestInit["headers"]): Promise<GetTeamsListQuery> {
return withWrapper((wrappedRequestHeaders) => client.request<GetTeamsListQuery>(GetTeamsListDocument, variables, {...requestHeaders, ...wrappedRequestHeaders}), 'getTeamsList', 'query');
},
updateTeam(variables: UpdateTeamQueryVariables, requestHeaders?: Dom.RequestInit["headers"]): Promise<UpdateTeamQuery> {
return withWrapper((wrappedRequestHeaders) => client.request<UpdateTeamQuery>(UpdateTeamDocument, variables, {...requestHeaders, ...wrappedRequestHeaders}), 'updateTeam', 'query');
},
createUser(variables: CreateUserQueryVariables, requestHeaders?: Dom.RequestInit["headers"]): Promise<CreateUserQuery> {
return withWrapper((wrappedRequestHeaders) => client.request<CreateUserQuery>(CreateUserDocument, variables, {...requestHeaders, ...wrappedRequestHeaders}), 'createUser', 'query');
},
@@ -4468,11 +4471,11 @@ export function getSdk(client: GraphQLClient, withWrapper: SdkFunctionWrapper =
getUsersList(variables: GetUsersListQueryVariables, requestHeaders?: Dom.RequestInit["headers"]): Promise<GetUsersListQuery> {
return withWrapper((wrappedRequestHeaders) => client.request<GetUsersListQuery>(GetUsersListDocument, variables, {...requestHeaders, ...wrappedRequestHeaders}), 'getUsersList', 'query');
},
grantUserRole(variables: GrantUserRoleQueryVariables, requestHeaders?: Dom.RequestInit["headers"]): Promise<GrantUserRoleQuery> {
return withWrapper((wrappedRequestHeaders) => client.request<GrantUserRoleQuery>(GrantUserRoleDocument, variables, {...requestHeaders, ...wrappedRequestHeaders}), 'grantUserRole', 'query');
grantUserTeam(variables: GrantUserTeamQueryVariables, requestHeaders?: Dom.RequestInit["headers"]): Promise<GrantUserTeamQuery> {
return withWrapper((wrappedRequestHeaders) => client.request<GrantUserTeamQuery>(GrantUserTeamDocument, variables, {...requestHeaders, ...wrappedRequestHeaders}), 'grantUserTeam', 'query');
},
revokeUserRole(variables: RevokeUserRoleQueryVariables, requestHeaders?: Dom.RequestInit["headers"]): Promise<RevokeUserRoleQuery> {
return withWrapper((wrappedRequestHeaders) => client.request<RevokeUserRoleQuery>(RevokeUserRoleDocument, variables, {...requestHeaders, ...wrappedRequestHeaders}), 'revokeUserRole', 'query');
revokeUserTeam(variables: RevokeUserTeamQueryVariables, requestHeaders?: Dom.RequestInit["headers"]): Promise<RevokeUserTeamQuery> {
return withWrapper((wrappedRequestHeaders) => client.request<RevokeUserTeamQuery>(RevokeUserTeamDocument, variables, {...requestHeaders, ...wrappedRequestHeaders}), 'revokeUserTeam', 'query');
},
setConnections(variables: SetConnectionsQueryVariables, requestHeaders?: Dom.RequestInit["headers"]): Promise<SetConnectionsQuery> {
return withWrapper((wrappedRequestHeaders) => client.request<SetConnectionsQuery>(SetConnectionsDocument, variables, {...requestHeaders, ...wrappedRequestHeaders}), 'setConnections', 'query');
+2 -1
View File
@@ -19,7 +19,8 @@
"@timohausmann/quadtree-ts": "~2.0.0-beta.1",
"clsx": "~1.2.1",
"md5": "~2.3.0",
"uuid": "~9.0.0"
"uuid": "~9.0.0",
"fast-deep-equal": "~3.1.3"
},
"peerDependencies": {
"mobx": "~6.x.x"
@@ -17,7 +17,7 @@ export class MetadataMap<TKey, TValue> {
private syncData: Array<[TKey, TValue]> | null;
constructor(private defaultValueGetter?: DefaultValueGetter<TKey, TValue>) {
constructor(private readonly defaultValueGetter?: DefaultValueGetter<TKey, TValue>) {
this.data = observable(new Map());
this.length = 0;
this.syncData = null;
@@ -74,7 +74,7 @@ export class MetadataMap<TKey, TValue> {
const value = provider(key, this);
untracked(() => {
this.set(key, value);
this.set(key, observable(value as any));
this.length++;
});
return this.data.get(key)!;
+1
View File
@@ -34,6 +34,7 @@ export * from './isImageFormat';
export * from './getCookies';
export * from './getUniqueName';
export * from './isMapsEqual';
export * from './isObjectsEqual';
export * from './openCenteredPopup';
export * from './download';
export * from './getTextFileReadingProcess';
@@ -0,0 +1,16 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2022 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
import isEqual from 'fast-deep-equal';
export function isObjectsEqual(
a: any,
b: any
): boolean {
return isEqual(a, b);
}
@@ -118,7 +118,7 @@ export const MetaParameters = observer<Props>(function MetaParameters({ sub, par
)}
<TableColumnHeader min />
<TableColumnHeader>{translate('authentication_user_name')}</TableColumnHeader>
<TableColumnHeader>{translate('authentication_user_role')}</TableColumnHeader>
<TableColumnHeader>{translate('authentication_user_team')}</TableColumnHeader>
<TableColumnHeader />
</TableHeader>
<TableBody>
@@ -1,25 +0,0 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2022 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
import type { RoleInfo } from '@cloudbeaver/core-authentication';
import type { IExecutionContextProvider } from '@cloudbeaver/core-executor';
import type { IRoleFormState } from '../IRoleFormProps';
export interface IRoleFormConfigureContext {
readonly info: RoleInfo | undefined;
}
export function roleFormConfigureContext(
contexts: IExecutionContextProvider<IRoleFormState>,
state: IRoleFormState
): IRoleFormConfigureContext {
return {
info: state.info,
};
}
@@ -1,149 +0,0 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2022 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
import { RolesResource } from '@cloudbeaver/core-authentication';
import { Bootstrap, injectable } from '@cloudbeaver/core-di';
import type { IExecutionContextProvider } from '@cloudbeaver/core-executor';
import { getUniqueName } from '@cloudbeaver/core-utils';
import { roleContext } from '../Contexts/roleContext';
import type { IRoleFormFillConfigData, IRoleFormSubmitData } from '../IRoleFormProps';
import { RoleFormService } from '../RoleFormService';
import { RoleOptions } from './RoleOptions';
@injectable()
export class RoleOptionsTabService extends Bootstrap {
constructor(
private readonly roleFormService: RoleFormService,
private readonly roleResource: RolesResource,
) {
super();
}
register(): void {
this.roleFormService.tabsContainer.add({
key: 'options',
name: 'ui_options',
order: 1,
panel: () => RoleOptions,
});
this.roleFormService.prepareConfigTask
.addHandler(this.prepareConfig.bind(this));
this.roleFormService.formValidationTask
.addHandler(this.validate.bind(this));
this.roleFormService.formSubmittingTask
.addHandler(this.save.bind(this));
this.roleFormService.fillConfigTask
.addHandler(this.fillConfig.bind(this));
}
load(): void { }
private async prepareConfig(
{
state,
}: IRoleFormSubmitData,
contexts: IExecutionContextProvider<IRoleFormSubmitData>
) {
const config = contexts.getContext(roleContext);
config.roleId = state.config.roleId;
if (state.config.roleName) {
config.roleName = state.config.roleName.trim();
if (state.mode === 'create') {
const roleNames = this.roleResource.values.map(role => role.roleName).filter(Boolean) as string[];
config.roleName = getUniqueName(config.roleName, roleNames);
}
}
if (state.config.description) {
config.description = state.config.description;
}
config.rolePermissions = [...state.config.rolePermissions];
}
private async validate(
{
state,
}: IRoleFormSubmitData,
contexts: IExecutionContextProvider<IRoleFormSubmitData>
) {
const validation = contexts.getContext(this.roleFormService.configurationValidationContext);
if (state.mode === 'create') {
if (!state.config.roleId.trim()) {
validation.error("Field 'Role ID' can't be empty");
}
if (this.roleResource.has(state.config.roleId)) {
validation.error(`A role with ID "${state.config.roleId}" already exists`);
}
}
}
private async save(
{
state,
}: IRoleFormSubmitData,
contexts: IExecutionContextProvider<IRoleFormSubmitData>
) {
const status = contexts.getContext(this.roleFormService.configurationStatusContext);
const config = contexts.getContext(roleContext);
const create = state.mode === 'create';
try {
if (create) {
const role = await this.roleResource.createRole(config);
status.info('Role created');
status.info(role.roleId);
} else {
const role = await this.roleResource.updateRole(config);
status.info('Role updated');
status.info(role.roleId);
}
} catch (exception: any) {
if (create) {
status.error(exception, 'administration_roles_role_create_error');
} else {
status.error(exception, 'administration_roles_role_save_error');
}
}
}
private fillConfig(
{ state, updated }: IRoleFormFillConfigData,
contexts: IExecutionContextProvider<IRoleFormFillConfigData>
) {
if (!updated) {
return;
}
if (!state.info) {
return;
}
if (state.info.roleId) {
state.config.roleId = state.info.roleId;
}
if (state.info.roleName) {
state.config.roleName = state.info.roleName;
}
if (state.info.description) {
state.config.description = state.info.description;
}
state.config.rolePermissions = [...state.info.rolePermissions];
}
}
@@ -1,36 +0,0 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2022 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
import { useState } from 'react';
import type { RoleInfo } from '@cloudbeaver/core-authentication';
import { useService } from '@cloudbeaver/core-di';
import type { CachedMapResource } from '@cloudbeaver/core-sdk';
import type { IRoleFormState } from './IRoleFormProps';
import { RoleFormService } from './RoleFormService';
import { RoleFormState } from './RoleFormState';
export function useRoleFormState(
resource: CachedMapResource<string, RoleInfo>,
configure?: (state: IRoleFormState) => any
): IRoleFormState {
const service = useService(RoleFormService);
const [state] = useState<IRoleFormState>(() => {
const state = new RoleFormState(
service,
resource,
);
configure?.(state);
state.load();
return state;
});
return state;
}
@@ -6,11 +6,11 @@
* you may not use this file except in compliance with the License.
*/
import type { RoleInfo } from '@cloudbeaver/core-authentication';
import type { TeamInfo } from '@cloudbeaver/core-authentication';
export function roleContext(): RoleInfo {
export function teamContext(): TeamInfo {
return {
roleId: '',
rolePermissions: [],
teamId: '',
teamPermissions: [],
};
}
@@ -0,0 +1,25 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2022 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
import type { TeamInfo } from '@cloudbeaver/core-authentication';
import type { IExecutionContextProvider } from '@cloudbeaver/core-executor';
import type { ITeamFormState } from '../ITeamFormProps';
export interface ITeamFormConfigureContext {
readonly info: TeamInfo | undefined;
}
export function teamFormConfigureContext(
contexts: IExecutionContextProvider<ITeamFormState>,
state: ITeamFormState
): ITeamFormConfigureContext {
return {
info: state.info,
};
}
@@ -6,18 +6,18 @@
* you may not use this file except in compliance with the License.
*/
export interface IRoleFormStateInfo {
export interface ITeamFormStateInfo {
edited: boolean;
disabled: boolean;
readonly: boolean;
statusMessage: string | null;
}
export interface IRoleFormStateContext extends IRoleFormStateInfo {
export interface ITeamFormStateContext extends ITeamFormStateInfo {
setStatusMessage: (message: string | null) => void;
}
export function roleFormStateContext(): IRoleFormStateContext {
export function teamFormStateContext(): ITeamFormStateContext {
return {
edited: false,
disabled: false,
@@ -14,11 +14,11 @@ import { useService } from '@cloudbeaver/core-di';
import { CreateRoleService } from './CreateRoleService';
import { RoleForm } from './RoleForm';
import { CreateTeamService } from './CreateTeamService';
import { TeamForm } from './TeamForm';
const styles = css`
role-create {
team-create {
display: flex;
flex-direction: column;
height: 660px;
@@ -35,7 +35,7 @@ const styles = css`
flex: auto 0 0;
}
role-create-content {
team-create-content {
composes: theme-background-secondary theme-text-on-secondary from global;
position: relative;
display: flex;
@@ -49,23 +49,23 @@ const styles = css`
}
`;
export const CreateRole: React.FC = observer(function CreateRole() {
const service = useService(CreateRoleService);
export const CreateTeam: React.FC = observer(function CreateTeam() {
const service = useService(CreateTeamService);
if (!service.data) {
return null;
}
return styled(styles)(
<role-create>
<team-create>
<title-bar>
<Translate token='administration_roles_role_creation' />
<Translate token='administration_teams_team_creation' />
<fill />
<IconButton name="cross" viewBox="0 0 16 16" onClick={service.cancelCreate} />
</title-bar>
<role-create-content>
<RoleForm state={service.data} onCancel={service.cancelCreate} onSave={service.cancelCreate} />
</role-create-content>
</role-create>
<team-create-content>
<TeamForm state={service.data} onCancel={service.cancelCreate} onSave={service.cancelCreate} />
</team-create-content>
</team-create>
);
});
@@ -8,23 +8,23 @@
import { observable, makeObservable } from 'mobx';
import { RolesResource } from '@cloudbeaver/core-authentication';
import { TeamsResource } from '@cloudbeaver/core-authentication';
import { injectable } from '@cloudbeaver/core-di';
import type { IRoleFormState } from './IRoleFormProps';
import { RoleFormService } from './RoleFormService';
import { RoleFormState } from './RoleFormState';
import { RolesAdministrationNavService } from './RolesAdministrationNavService';
import type { ITeamFormState } from './ITeamFormProps';
import { TeamFormService } from './TeamFormService';
import { TeamFormState } from './TeamFormState';
import { TeamsAdministrationNavService } from './TeamsAdministrationNavService';
@injectable()
export class CreateRoleService {
export class CreateTeamService {
disabled = false;
data: IRoleFormState | null;
data: ITeamFormState | null;
constructor(
private readonly rolesAdministrationNavService: RolesAdministrationNavService,
private readonly roleFormService: RoleFormService,
private readonly rolesResource: RolesResource
private readonly teamsAdministrationNavService: TeamsAdministrationNavService,
private readonly teamFormService: TeamFormService,
private readonly teamsResource: TeamsResource
) {
this.data = null;
@@ -38,17 +38,17 @@ export class CreateRoleService {
}
cancelCreate(): void {
this.rolesAdministrationNavService.navToRoot();
this.teamsAdministrationNavService.navToRoot();
}
fillData(): void {
this.data = new RoleFormState(
this.roleFormService,
this.rolesResource
this.data = new TeamFormState(
this.teamFormService,
this.teamsResource
);
}
create(): void {
this.rolesAdministrationNavService.navToCreate();
this.teamsAdministrationNavService.navToCreate();
}
}
@@ -21,7 +21,7 @@ import { PROJECT_GLOBAL_ID } from '@cloudbeaver/core-projects';
import { CachedMapAllKey } from '@cloudbeaver/core-sdk';
import { TabContainerPanelComponent, useTab } from '@cloudbeaver/core-ui';
import type { IRoleFormProps } from '../IRoleFormProps';
import type { ITeamFormProps } from '../ITeamFormProps';
import { ConnectionList } from './ConnectionList';
import { GrantedConnectionList } from './GrantedConnectionsList';
import { useGrantedConnections } from './useGrantedConnections';
@@ -42,7 +42,7 @@ const styles = css`
}
`;
export const GrantedConnections: TabContainerPanelComponent<IRoleFormProps> = observer(function GrantedConnections({
export const GrantedConnections: TabContainerPanelComponent<ITeamFormProps> = observer(function GrantedConnections({
tabId,
state: formState,
}) {
@@ -51,6 +51,7 @@ export const GrantedConnections: TabContainerPanelComponent<IRoleFormProps> = ob
const state = useGrantedConnections(formState.config, formState.mode);
const { selected } = useTab(tabId);
const loaded = state.state.loaded;
const dbDriverResource = useMapResource(
GrantedConnections,
@@ -70,10 +71,10 @@ export const GrantedConnections: TabContainerPanelComponent<IRoleFormProps> = ob
), [state.state.grantedSubjects, connections.resource]);
useEffect(() => {
if (selected && !state.state.loaded) {
if (selected && !loaded) {
state.load();
}
}, [selected, state.state.loaded]);
});
if (!selected) {
return null;
@@ -97,7 +98,7 @@ export const GrantedConnections: TabContainerPanelComponent<IRoleFormProps> = ob
<ColoredContainer parent gap vertical>
{!connections.resource.values.length ? (
<Group large>
<TextPlaceholder>{translate('administration_roles_role_granted_connections_empty')}</TextPlaceholder>
<TextPlaceholder>{translate('administration_teams_team_granted_connections_empty')}</TextPlaceholder>
</Group>
) : (
<>
@@ -6,26 +6,26 @@
* you may not use this file except in compliance with the License.
*/
import { RolesResource } from '@cloudbeaver/core-authentication';
import { TeamsResource } from '@cloudbeaver/core-authentication';
import { Bootstrap, injectable } from '@cloudbeaver/core-di';
import { NotificationService } from '@cloudbeaver/core-events';
import type { IExecutionContextProvider } from '@cloudbeaver/core-executor';
import { GraphQLService } from '@cloudbeaver/core-sdk';
import { isArraysEqual, MetadataValueGetter } from '@cloudbeaver/core-utils';
import { roleContext } from '../Contexts/roleContext';
import type { IRoleFormProps, IRoleFormSubmitData } from '../IRoleFormProps';
import { RoleFormService } from '../RoleFormService';
import { teamContext } from '../Contexts/teamContext';
import type { ITeamFormProps, ITeamFormSubmitData } from '../ITeamFormProps';
import { TeamFormService } from '../TeamFormService';
import { GrantedConnections } from './GrantedConnections';
import type { IGrantedConnectionsTabState } from './IGrantedConnectionsTabState';
@injectable()
export class GrantedConnectionsTabService extends Bootstrap {
private key: string;
private readonly key: string;
constructor(
private readonly roleFormService: RoleFormService,
private readonly rolesResource: RolesResource,
private readonly teamFormService: TeamFormService,
private readonly teamsResource: TeamsResource,
private readonly graphQLService: GraphQLService,
private readonly notificationService: NotificationService
) {
@@ -34,21 +34,21 @@ export class GrantedConnectionsTabService extends Bootstrap {
}
register(): void {
this.roleFormService.tabsContainer.add({
this.teamFormService.tabsContainer.add({
key: this.key,
name: 'administration_roles_role_granted_connections_tab_title',
title: 'administration_roles_role_granted_connections_tab_title',
name: 'administration_teams_team_granted_connections_tab_title',
title: 'administration_teams_team_granted_connections_tab_title',
order: 3,
stateGetter: context => this.stateGetter(context),
panel: () => GrantedConnections,
});
this.roleFormService.formSubmittingTask.addHandler(this.save.bind(this));
this.teamFormService.afterFormSubmittingTask.addHandler(this.save.bind(this));
}
load(): Promise<void> | void { }
private stateGetter(context: IRoleFormProps): MetadataValueGetter<string, IGrantedConnectionsTabState> {
private stateGetter(context: ITeamFormProps): MetadataValueGetter<string, IGrantedConnectionsTabState> {
return () => ({
loading: false,
loaded: false,
@@ -59,27 +59,27 @@ export class GrantedConnectionsTabService extends Bootstrap {
}
private async save(
data: IRoleFormSubmitData,
contexts: IExecutionContextProvider<IRoleFormSubmitData>
data: ITeamFormSubmitData,
contexts: IExecutionContextProvider<ITeamFormSubmitData>
) {
const config = contexts.getContext(roleContext);
const status = contexts.getContext(this.roleFormService.configurationStatusContext);
const config = contexts.getContext(teamContext);
const status = contexts.getContext(this.teamFormService.configurationStatusContext);
if (!status.saved) {
return;
}
const state = this.roleFormService.tabsContainer.getTabState<IGrantedConnectionsTabState>(
const state = this.teamFormService.tabsContainer.getTabState<IGrantedConnectionsTabState>(
data.state.partsState,
this.key,
{ state: data.state }
);
if (!config.roleId || !state.loaded) {
if (!config.teamId || !state.loaded) {
return;
}
const grantInfo = await this.rolesResource.getSubjectConnectionAccess(config.roleId);
const grantInfo = await this.teamsResource.getSubjectConnectionAccess(config.teamId);
const initial = grantInfo.map(info => info.connectionId);
const changed = !isArraysEqual(initial, state.grantedSubjects);
@@ -90,7 +90,7 @@ export class GrantedConnectionsTabService extends Bootstrap {
try {
await this.graphQLService.sdk.setSubjectConnectionAccess({
subjectId: config.roleId,
subjectId: config.teamId,
connections: state.grantedSubjects,
});
@@ -49,7 +49,7 @@ export const GrantedConnectionsTableHeader = observer<Props>(function GrantedCon
<header className={className}>
<Filter
disabled={disabled}
placeholder={translate('administration_roles_role_granted_connections_search_placeholder')}
placeholder={translate('administration_teams_team_granted_connections_search_placeholder')}
name='filterValue'
state={filterState}
/>
@@ -8,14 +8,14 @@
import { action, computed, observable } from 'mobx';
import { RoleInfo, RolesResource } from '@cloudbeaver/core-authentication';
import { useTabState } from '@cloudbeaver/core-ui';
import { TeamInfo, TeamsResource } from '@cloudbeaver/core-authentication';
import { useObservableRef } from '@cloudbeaver/core-blocks';
import { useService } from '@cloudbeaver/core-di';
import { NotificationService } from '@cloudbeaver/core-events';
import { useTabState } from '@cloudbeaver/core-ui';
import { isArraysEqual } from '@cloudbeaver/core-utils';
import type { RoleFormMode } from '../IRoleFormProps';
import type { TeamFormMode } from '../ITeamFormProps';
import type { IGrantedConnectionsTabState } from './IGrantedConnectionsTabState';
interface State {
@@ -27,8 +27,8 @@ interface State {
load: () => Promise<void>;
}
export function useGrantedConnections(role: RoleInfo, mode: RoleFormMode): Readonly<State> {
const resource = useService(RolesResource);
export function useGrantedConnections(team: TeamInfo, mode: TeamFormMode): Readonly<State> {
const resource = useService(TeamsResource);
const notificationService = useService(NotificationService);
const state = useTabState<IGrantedConnectionsTabState>();
@@ -54,20 +54,20 @@ export function useGrantedConnections(role: RoleInfo, mode: RoleFormMode): Reado
this.state.loading = true;
if (this.mode === 'edit') {
const grantInfo = await this.resource.getSubjectConnectionAccess(this.role.roleId);
const grantInfo = await this.resource.getSubjectConnectionAccess(this.team.teamId);
this.state.grantedSubjects = grantInfo.map(subject => subject.connectionId);
this.state.initialGrantedSubjects = this.state.grantedSubjects.slice();
}
this.state.loaded = true;
} catch (exception: any) {
this.notificationService.logException(exception, `Error getting granted connections for "${this.role.roleId}"`);
this.notificationService.logException(exception, `Error getting granted connections for "${this.team.teamId}"`);
} finally {
this.state.loading = false;
}
},
}),
{ state: observable.ref, changed: computed, grant: action.bound, revoke: action.bound, edit: action.bound },
{ state, role, mode, resource, notificationService },
{ state, team, mode, resource, notificationService },
['load']);
}
@@ -126,7 +126,7 @@ export const GrantedUserList = observer<Props>(function GrantedUserList({
key={user.userId}
id={user.userId}
name={`${user.userId}${activeUser ? ' (you)' : ''}`}
tooltip={activeUser ? translate('administration_roles_role_granted_users_permission_denied') : user.userId}
tooltip={activeUser ? translate('administration_teams_team_granted_users_permission_denied') : user.userId}
icon='/icons/user.svg'
iconTooltip={translate('authentication_user_icon_tooltip')}
disabled={disabled}
@@ -20,7 +20,7 @@ import { CachedMapAllKey } from '@cloudbeaver/core-sdk';
import { TabContainerPanelComponent, useTab } from '@cloudbeaver/core-ui';
import type { IRoleFormProps } from '../IRoleFormProps';
import type { ITeamFormProps } from '../ITeamFormProps';
import { GrantedUserList } from './GrantedUserList';
import { useGrantedUsers } from './useGrantedUsers';
import { UserList } from './UserList';
@@ -41,7 +41,7 @@ const styles = css`
}
`;
export const GrantedUsers: TabContainerPanelComponent<IRoleFormProps> = observer(function GrantedUsers({
export const GrantedUsers: TabContainerPanelComponent<ITeamFormProps> = observer(function GrantedUsers({
tabId,
state: formState,
}) {
@@ -73,7 +73,7 @@ export const GrantedUsers: TabContainerPanelComponent<IRoleFormProps> = observer
<ColoredContainer parent gap vertical>
{!users.resource.values.length ? (
<Group keepSize large>
<TextPlaceholder>{translate('administration_roles_role_granted_users_empty')}</TextPlaceholder>
<TextPlaceholder>{translate('administration_teams_team_granted_users_empty')}</TextPlaceholder>
</Group>
) : (
<>
@@ -6,26 +6,26 @@
* you may not use this file except in compliance with the License.
*/
import { RolesResource, UsersResource } from '@cloudbeaver/core-authentication';
import { TeamsResource, UsersResource } from '@cloudbeaver/core-authentication';
import { Bootstrap, injectable } from '@cloudbeaver/core-di';
import { NotificationService } from '@cloudbeaver/core-events';
import type { IExecutionContextProvider } from '@cloudbeaver/core-executor';
import { isArraysEqual, MetadataValueGetter } from '@cloudbeaver/core-utils';
import { roleContext } from '../Contexts/roleContext';
import type { IRoleFormProps, IRoleFormSubmitData } from '../IRoleFormProps';
import { RoleFormService } from '../RoleFormService';
import { teamContext } from '../Contexts/teamContext';
import type { ITeamFormProps, ITeamFormSubmitData } from '../ITeamFormProps';
import { TeamFormService } from '../TeamFormService';
import { GrantedUsers } from './GrantedUsers';
import type { IGrantedUsersTabState } from './IGrantedUsersTabState';
@injectable()
export class GrantedUsersTabService extends Bootstrap {
private key: string;
private readonly key: string;
constructor(
private readonly roleFormService: RoleFormService,
private readonly teamFormService: TeamFormService,
private readonly usersResource: UsersResource,
private readonly rolesResource: RolesResource,
private readonly teamsResource: TeamsResource,
private readonly notificationService: NotificationService
) {
super();
@@ -33,21 +33,21 @@ export class GrantedUsersTabService extends Bootstrap {
}
register(): void {
this.roleFormService.tabsContainer.add({
this.teamFormService.tabsContainer.add({
key: this.key,
name: 'administration_roles_role_granted_users_tab_title',
title: 'administration_roles_role_granted_users_tab_title',
name: 'administration_teams_team_granted_users_tab_title',
title: 'administration_teams_team_granted_users_tab_title',
order: 2,
stateGetter: context => this.stateGetter(context),
panel: () => GrantedUsers,
});
this.roleFormService.formSubmittingTask.addHandler(this.save.bind(this));
this.teamFormService.afterFormSubmittingTask.addHandler(this.save.bind(this));
}
load(): void { }
private stateGetter(context: IRoleFormProps): MetadataValueGetter<string, IGrantedUsersTabState> {
private stateGetter(context: ITeamFormProps): MetadataValueGetter<string, IGrantedUsersTabState> {
return () => ({
loading: false,
loaded: false,
@@ -58,27 +58,27 @@ export class GrantedUsersTabService extends Bootstrap {
}
private async save(
data: IRoleFormSubmitData,
contexts: IExecutionContextProvider<IRoleFormSubmitData>
data: ITeamFormSubmitData,
contexts: IExecutionContextProvider<ITeamFormSubmitData>
) {
const config = contexts.getContext(roleContext);
const status = contexts.getContext(this.roleFormService.configurationStatusContext);
const config = contexts.getContext(teamContext);
const status = contexts.getContext(this.teamFormService.configurationStatusContext);
if (!status.saved) {
return;
}
const state = this.roleFormService.tabsContainer.getTabState<IGrantedUsersTabState>(
const state = this.teamFormService.tabsContainer.getTabState<IGrantedUsersTabState>(
data.state.partsState,
this.key,
{ state: data.state }
);
if (!config.roleId || !state.loaded) {
if (!config.teamId || !state.loaded) {
return;
}
const initial = await this.rolesResource.loadGrantedUsers(config.roleId);
const initial = await this.teamsResource.loadGrantedUsers(config.teamId);
const changed = !isArraysEqual(initial, state.grantedUsers);
@@ -93,13 +93,13 @@ export class GrantedUsersTabService extends Bootstrap {
try {
for (const user of revokedUsers) {
await this.usersResource.revokeRole(user, config.roleId);
await this.usersResource.revokeTeam(user, config.teamId);
revoked.push(user);
}
for (const user of state.grantedUsers) {
if (!initial.includes(user)) {
await this.usersResource.grantRole(user, config.roleId);
await this.usersResource.grantTeam(user, config.teamId);
granted.push(user);
}
}
@@ -49,7 +49,7 @@ export const GrantedUsersTableHeader = observer<Props>(function GrantedUsersTabl
<header className={className}>
<Filter
disabled={disabled}
placeholder={translate('administration_roles_role_granted_users_search_placeholder')}
placeholder={translate('administration_teams_team_granted_users_search_placeholder')}
name='filterValue'
state={filterState}
/>
@@ -36,7 +36,7 @@ export const GrantedUsersTableInnerHeader = observer<Props>(function GrantedUser
<TableSelect id='selectUsers' disabled={disabled} />
</TableColumnHeader>
<TableColumnHeader min />
<TableColumnHeader>{translate('administration_roles_role_granted_users_user_id')}</TableColumnHeader>
<TableColumnHeader>{translate('administration_teams_team_granted_users_user_id')}</TableColumnHeader>
</TableHeader>
);
});
@@ -118,7 +118,7 @@ export const UserList = observer<Props>(function UserList({
key={user.userId}
id={user.userId}
name={`${user.userId}${activeUser ? ' (you)' : ''}`}
tooltip={activeUser ? translate('administration_roles_role_granted_users_permission_denied') : user.userId}
tooltip={activeUser ? translate('administration_teams_team_granted_users_permission_denied') : user.userId}
icon='/icons/user.svg'
iconTooltip={translate('authentication_user_icon_tooltip')}
disabled={disabled}
@@ -8,14 +8,14 @@
import { action, computed, observable } from 'mobx';
import { RoleInfo, RolesResource } from '@cloudbeaver/core-authentication';
import { useTabState } from '@cloudbeaver/core-ui';
import { TeamInfo, TeamsResource } from '@cloudbeaver/core-authentication';
import { useObservableRef } from '@cloudbeaver/core-blocks';
import { useService } from '@cloudbeaver/core-di';
import { NotificationService } from '@cloudbeaver/core-events';
import { useTabState } from '@cloudbeaver/core-ui';
import { isArraysEqual } from '@cloudbeaver/core-utils';
import type { RoleFormMode } from '../IRoleFormProps';
import type { TeamFormMode } from '../ITeamFormProps';
import type { IGrantedUsersTabState } from './IGrantedUsersTabState';
interface State {
@@ -27,8 +27,8 @@ interface State {
load: () => Promise<void>;
}
export function useGrantedUsers(role: RoleInfo, mode: RoleFormMode): Readonly<State> {
const resource = useService(RolesResource);
export function useGrantedUsers(team: TeamInfo, mode: TeamFormMode): Readonly<State> {
const resource = useService(TeamsResource);
const notificationService = useService(NotificationService);
const state = useTabState<IGrantedUsersTabState>();
@@ -54,7 +54,7 @@ export function useGrantedUsers(role: RoleInfo, mode: RoleFormMode): Readonly<St
this.state.loading = true;
if (this.mode === 'edit') {
const grantedUsers = await this.resource.loadGrantedUsers(this.role.roleId);
const grantedUsers = await this.resource.loadGrantedUsers(this.team.teamId);
this.state.grantedUsers = grantedUsers;
this.state.initialGrantedUsers = this.state.grantedUsers.slice();
}
@@ -68,6 +68,6 @@ export function useGrantedUsers(role: RoleInfo, mode: RoleFormMode): Readonly<St
},
}),
{ state: observable.ref, changed: computed, edit: action.bound, revoke: action.bound, grant: action.bound },
{ state, role, mode, resource, notificationService },
{ state, team, mode, resource, notificationService },
['load']);
}
@@ -6,45 +6,45 @@
* you may not use this file except in compliance with the License.
*/
import type { RoleInfo } from '@cloudbeaver/core-authentication';
import type { TeamInfo } from '@cloudbeaver/core-authentication';
import type { IExecutorHandlersCollection } from '@cloudbeaver/core-executor';
import type { CachedMapResource } from '@cloudbeaver/core-sdk';
import type { MetadataMap } from '@cloudbeaver/core-utils';
export type RoleFormMode = 'edit' | 'create';
export type TeamFormMode = 'edit' | 'create';
export interface IRoleFormState {
mode: RoleFormMode;
config: RoleInfo;
export interface ITeamFormState {
mode: TeamFormMode;
config: TeamInfo;
partsState: MetadataMap<string, any>;
readonly info: RoleInfo | undefined;
readonly info: TeamInfo | undefined;
readonly statusMessage: string | null;
readonly disabled: boolean;
readonly readonly: boolean;
readonly loading: boolean;
readonly submittingTask: IExecutorHandlersCollection<IRoleFormSubmitData>;
readonly resource: CachedMapResource<string, RoleInfo>;
readonly submittingTask: IExecutorHandlersCollection<ITeamFormSubmitData>;
readonly resource: CachedMapResource<string, TeamInfo>;
readonly load: () => Promise<void>;
readonly loadRoleInfo: () => Promise<RoleInfo | undefined>;
readonly loadTeamInfo: () => Promise<TeamInfo | undefined>;
readonly save: () => Promise<void>;
readonly setOptions: (
mode: RoleFormMode,
mode: TeamFormMode,
) => this;
}
export interface IRoleFormProps {
state: IRoleFormState;
export interface ITeamFormProps {
state: ITeamFormState;
onCancel?: () => void;
}
export interface IRoleFormFillConfigData {
export interface ITeamFormFillConfigData {
updated: boolean;
state: IRoleFormState;
state: ITeamFormState;
}
export interface IRoleFormSubmitData {
state: IRoleFormState;
export interface ITeamFormSubmitData {
state: ITeamFormState;
}
@@ -12,12 +12,10 @@ import styled, { css } from 'reshadow';
import { PermissionsResource } from '@cloudbeaver/core-administration';
import { BASE_CONTAINERS_STYLES, ColoredContainer, FieldCheckbox, Group, GroupTitle, InputField, SubmittingForm, Textarea, useMapResource, useTranslate, useStyles } from '@cloudbeaver/core-blocks';
import { CachedMapAllKey } from '@cloudbeaver/core-sdk';
import type { TabContainerPanelComponent } from '@cloudbeaver/core-ui';
import type { IRoleFormProps } from '../IRoleFormProps';
import type { ITeamFormProps } from '../ITeamFormProps';
const styles = css`
SubmittingForm {
@@ -29,13 +27,13 @@ const styles = css`
}
`;
export const RoleOptions: TabContainerPanelComponent<IRoleFormProps> = observer(function RoleOptions({
export const TeamOptions: TabContainerPanelComponent<ITeamFormProps> = observer(function TeamOptions({
state,
}) {
const formRef = useRef<HTMLFormElement>(null);
const translate = useTranslate();
const permissionsResource = useMapResource(RoleOptions, PermissionsResource, CachedMapAllKey);
const permissionsResource = useMapResource(TeamOptions, PermissionsResource, CachedMapAllKey);
const style = useStyles(BASE_CONTAINERS_STYLES, styles);
const edit = state.mode === 'edit';
@@ -44,7 +42,7 @@ export const RoleOptions: TabContainerPanelComponent<IRoleFormProps> = observer(
<ColoredContainer parent gap overflow>
<Group small gap>
<InputField
name='roleId'
name='teamId'
state={state.config}
readOnly={state.readonly || edit}
disabled={state.disabled}
@@ -52,17 +50,17 @@ export const RoleOptions: TabContainerPanelComponent<IRoleFormProps> = observer(
tiny
fill
>
{translate('administration_roles_role_id')}
{translate('administration_teams_team_id')}
</InputField>
<InputField
name='roleName'
name='teamName'
state={state.config}
readOnly={state.readonly}
disabled={state.disabled}
tiny
fill
>
{translate('administration_roles_role_name')}
{translate('administration_teams_team_name')}
</InputField>
<Textarea
name='description'
@@ -72,11 +70,11 @@ export const RoleOptions: TabContainerPanelComponent<IRoleFormProps> = observer(
tiny
fill
>
{translate('administration_roles_role_description')}
{translate('administration_teams_team_description')}
</Textarea>
</Group>
<Group small gap>
<GroupTitle>{translate('administration_roles_role_permissions')}</GroupTitle>
<GroupTitle>{translate('administration_teams_team_permissions')}</GroupTitle>
{permissionsResource.resource.values.map(permission => {
const label = permission.label ?? permission.id;
@@ -100,7 +98,7 @@ export const RoleOptions: TabContainerPanelComponent<IRoleFormProps> = observer(
id={permission.id}
value={permission.id}
title={tooltip}
name='rolePermissions'
name='teamPermissions'
state={state.config}
readOnly={state.readonly}
disabled={state.disabled}
@@ -0,0 +1,153 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2022 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
import { TeamsResource } from '@cloudbeaver/core-authentication';
import { Bootstrap, injectable } from '@cloudbeaver/core-di';
import type { IExecutionContextProvider } from '@cloudbeaver/core-executor';
import { LocalizationService } from '@cloudbeaver/core-localization';
import { getUniqueName } from '@cloudbeaver/core-utils';
import { teamContext } from '../Contexts/teamContext';
import type { ITeamFormFillConfigData, ITeamFormSubmitData } from '../ITeamFormProps';
import { TeamFormService } from '../TeamFormService';
import { TeamOptions } from './TeamOptions';
@injectable()
export class TeamOptionsTabService extends Bootstrap {
constructor(
private readonly teamFormService: TeamFormService,
private readonly teamResource: TeamsResource,
private readonly localizationService: LocalizationService
) {
super();
}
register(): void {
this.teamFormService.tabsContainer.add({
key: 'options',
name: 'ui_options',
order: 1,
panel: () => TeamOptions,
});
this.teamFormService.prepareConfigTask
.addHandler(this.prepareConfig.bind(this));
this.teamFormService.formValidationTask
.addHandler(this.validate.bind(this));
this.teamFormService.formSubmittingTask
.addHandler(this.save.bind(this));
this.teamFormService.fillConfigTask
.addHandler(this.fillConfig.bind(this));
}
load(): void { }
private async prepareConfig(
{
state,
}: ITeamFormSubmitData,
contexts: IExecutionContextProvider<ITeamFormSubmitData>
) {
const config = contexts.getContext(teamContext);
config.teamId = state.config.teamId;
if (state.config.teamName) {
config.teamName = state.config.teamName.trim();
if (state.mode === 'create') {
const teamNames = this.teamResource.values.map(team => team.teamName).filter(Boolean) as string[];
config.teamName = getUniqueName(config.teamName, teamNames);
}
}
if (state.config.description) {
config.description = state.config.description;
}
config.teamPermissions = [...state.config.teamPermissions];
}
private async validate(
{
state,
}: ITeamFormSubmitData,
contexts: IExecutionContextProvider<ITeamFormSubmitData>
) {
const validation = contexts.getContext(this.teamFormService.configurationValidationContext);
if (state.mode === 'create') {
if (!state.config.teamId.trim()) {
validation.error('administration_teams_team_info_id_invalid');
}
if (this.teamResource.has(state.config.teamId)) {
validation.error(this.localizationService.translate('administration_teams_team_info_exists', undefined, {
teamId: state.config.teamId,
}));
}
}
}
private async save(
{
state,
}: ITeamFormSubmitData,
contexts: IExecutionContextProvider<ITeamFormSubmitData>
) {
const status = contexts.getContext(this.teamFormService.configurationStatusContext);
const config = contexts.getContext(teamContext);
const create = state.mode === 'create';
try {
if (create) {
const team = await this.teamResource.createTeam(config);
status.info('administration_teams_team_info_created');
status.info(team.teamId);
} else {
const team = await this.teamResource.updateTeam(config);
status.info('administration_teams_team_info_updated');
status.info(team.teamId);
}
} catch (exception: any) {
if (create) {
status.error(exception, 'administration_teams_team_create_error');
} else {
status.error(exception, 'administration_teams_team_save_error');
}
}
}
private fillConfig(
{ state, updated }: ITeamFormFillConfigData,
contexts: IExecutionContextProvider<ITeamFormFillConfigData>
) {
if (!updated) {
return;
}
if (!state.info) {
return;
}
if (state.info.teamId) {
state.config.teamId = state.info.teamId;
}
if (state.info.teamName) {
state.config.teamName = state.info.teamName;
}
if (state.info.description) {
state.config.description = state.info.description;
}
state.config.teamPermissions = [...state.info.teamPermissions];
}
}
@@ -10,16 +10,14 @@ import { observer } from 'mobx-react-lite';
import { useEffect } from 'react';
import styled, { css } from 'reshadow';
import type { RoleInfo } from '@cloudbeaver/core-authentication';
import type { TeamInfo } from '@cloudbeaver/core-authentication';
import { Placeholder, useObjectRef, useExecutor, BASE_CONTAINERS_STYLES, IconOrImage, useTranslate, useStyles } from '@cloudbeaver/core-blocks';
import { useService } from '@cloudbeaver/core-di';
import { TabsState, TabList, UNDERLINE_TAB_STYLES, TabPanelList, BASE_TAB_STYLES } from '@cloudbeaver/core-ui';
import { roleContext } from './Contexts/roleContext';
import type { IRoleFormState } from './IRoleFormProps';
import { RoleFormService } from './RoleFormService';
import { teamContext } from './Contexts/teamContext';
import type { ITeamFormState } from './ITeamFormProps';
import { TeamFormService } from './TeamFormService';
const tabsStyles = css`
TabList {
@@ -35,7 +33,7 @@ const tabsStyles = css`
`;
const topBarStyles = css`
role-top-bar {
team-top-bar {
composes: theme-border-color-background theme-background-secondary theme-text-on-secondary from global;
position: relative;
display: flex;
@@ -50,18 +48,18 @@ const topBarStyles = css`
border-color: inherit;
}
}
role-top-bar-tabs {
team-top-bar-tabs {
flex: 1;
}
role-top-bar-actions {
team-top-bar-actions {
display: flex;
align-items: center;
padding: 0 24px;
gap: 16px;
}
role-status-message {
team-status-message {
composes: theme-typography--caption from global;
height: 24px;
padding: 0 16px;
@@ -96,13 +94,13 @@ const formStyles = css`
`;
interface Props {
state: IRoleFormState;
state: ITeamFormState;
onCancel?: () => void;
onSave?: (role: RoleInfo) => void;
onSave?: (team: TeamInfo) => void;
className?: string;
}
export const RoleForm = observer<Props>(function RoleForm({
export const TeamForm = observer<Props>(function TeamForm({
state,
onCancel,
onSave = () => { },
@@ -112,14 +110,14 @@ export const RoleForm = observer<Props>(function RoleForm({
const props = useObjectRef({ onSave });
const style = [BASE_TAB_STYLES, tabsStyles, UNDERLINE_TAB_STYLES];
const styles = useStyles(style, BASE_CONTAINERS_STYLES, topBarStyles, formStyles);
const service = useService(RoleFormService);
const service = useService(TeamFormService);
useExecutor({
executor: state.submittingTask,
postHandlers: [function save(data, contexts) {
const validation = contexts.getContext(service.configurationValidationContext);
const state = contexts.getContext(service.configurationStatusContext);
const config = contexts.getContext(roleContext);
const config = contexts.getContext(teamContext);
if (validation.valid && state.saved) {
props.onSave(config);
@@ -128,7 +126,7 @@ export const RoleForm = observer<Props>(function RoleForm({
});
useEffect(() => {
state.loadRoleInfo();
state.loadTeamInfo();
}, []);
return styled(styles)(
@@ -139,22 +137,22 @@ export const RoleForm = observer<Props>(function RoleForm({
onCancel={onCancel}
>
<box className={className}>
<role-top-bar>
<role-top-bar-tabs>
<role-status-message>
<team-top-bar>
<team-top-bar-tabs>
<team-status-message>
{state.statusMessage && (
<>
<IconOrImage icon='/icons/info_icon.svg' />
{translate(state.statusMessage)}
</>
)}
</role-status-message>
</team-status-message>
<TabList style={style} disabled={false} />
</role-top-bar-tabs>
<role-top-bar-actions>
</team-top-bar-tabs>
<team-top-bar-actions>
<Placeholder container={service.actionsContainer} state={state} onCancel={onCancel} />
</role-top-bar-actions>
</role-top-bar>
</team-top-bar-actions>
</team-top-bar>
<content-box>
<TabPanelList style={style} />
</content-box>
@@ -11,9 +11,9 @@ import { observer } from 'mobx-react-lite';
import { Button, PlaceholderComponent, useTranslate } from '@cloudbeaver/core-blocks';
import type { IRoleFormProps } from './IRoleFormProps';
import type { ITeamFormProps } from './ITeamFormProps';
export const RoleFormBaseActions: PlaceholderComponent<IRoleFormProps> = observer(function RoleFormBaseActions({
export const TeamFormBaseActions: PlaceholderComponent<ITeamFormProps> = observer(function TeamFormBaseActions({
state,
onCancel,
}) {

Some files were not shown because too many files have changed in this diff Show More