Skip to content

Commit

Permalink
Make non-admin user read-only with a config
Browse files Browse the repository at this point in the history
Make non-admin user read-only with a config. Fixes: wso2/product-micro-integrator#3729
  • Loading branch information
DedunuKarunarathne committed Nov 5, 2024
1 parent e67e6b0 commit 1c6f899
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import com.nimbusds.oauth2.sdk.id.ClientID;
import com.nimbusds.oauth2.sdk.id.Issuer;
import io.asgardeo.java.oidc.sdk.config.model.OIDCAgentConfig;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.eclipse.jetty.server.Connector;
Expand Down Expand Up @@ -120,6 +121,9 @@ public class DashboardServer {
private static SSOConfig ssoConfig;
private static Thread shutdownHook;
private static SecretResolver secretResolver = new SecretResolver();
private static boolean makeNonAdminUsersReadOnly;
private static final String TOML_MAKE_NON_ADMIN_USERS_READ_ONLY = "user_access.make_non_admin_users_read_only";
private static final String MAKE_NON_ADMIN_USERS_READ_ONLY = "make_non_admin_users_read_only";

private static final Logger logger = LogManager.getLogger(DashboardServer.class);

Expand Down Expand Up @@ -313,6 +317,15 @@ private void loadConfigurations(Map<String, Object> parsedConfigs) {
properties.put(IS_USER_STORE_FILE_BASED, String.valueOf(isFileBased));
}

String makeNonAdminUsersReadOnlySystemValue = System.getProperty(MAKE_NON_ADMIN_USERS_READ_ONLY);
if (StringUtils.isNotEmpty(makeNonAdminUsersReadOnlySystemValue)) {
makeNonAdminUsersReadOnly = Boolean.parseBoolean(makeNonAdminUsersReadOnlySystemValue);
} else {
makeNonAdminUsersReadOnly = Boolean.parseBoolean(
String.valueOf(parsedConfigs.get(TOML_MAKE_NON_ADMIN_USERS_READ_ONLY)));
}
properties.put(MAKE_NON_ADMIN_USERS_READ_ONLY, String.valueOf(makeNonAdminUsersReadOnly));

System.setProperties(properties);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ public class AuthenticationFilter implements ContainerRequestFilter {
private static final String AUTHENTICATION_SCHEME = "Bearer";
private static final List<String> adminOnlyPaths = Arrays.asList("/log-configs",
"/users");
private static final String MAKE_NON_ADMIN_USERS_READ_ONLY = "make_non_admin_users_read_only";

@Context
private HttpServletRequest servletRequest;
Expand All @@ -63,6 +64,8 @@ public void filter(ContainerRequestContext requestContext) {
Map<String, Cookie> cookies = requestContext.getCookies();
String token;
SecurityHandler securityHandler;
Boolean makeNonAdminUsersReadOnly = Boolean.valueOf(System.getProperty(MAKE_NON_ADMIN_USERS_READ_ONLY));
String httpMethod = requestContext.getMethod();

if (isTokenBasedAuthentication(authorizationHeader)) {
token = authorizationHeader.substring(AUTHENTICATION_SCHEME.length()).trim();
Expand All @@ -87,6 +90,11 @@ public void filter(ContainerRequestContext requestContext) {

if (isAdminResource(requestContext) && !securityHandler.isAuthorized(config, token)) {
abortWithUnauthorized(requestContext);
} else if (!"GET".equalsIgnoreCase(httpMethod) && makeNonAdminUsersReadOnly &&
!securityHandler.isAuthorized(config, token)) {
// For non-admin resources, request except GET are blocked
// if the 'makeNonAdminUsersReadOnly' is set to 'true'
abortWithUnauthorized(requestContext);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -172,4 +172,33 @@ export default class AuthManager {
static getBasePath() {
return window.location.protocol+'//'+window.location.hostname+(window.location.port ? ':'+window.location.port: '') + "/dashboard/api";
}

/**
* Check whether the user is an admin user.
* @returns {boolean} true if the user is an admin user
*/
static isAdminUser() {
const userName = AuthManager.getUser();
return userName?.scope === "admin";
}

/**
* Check if non-admin users are read-only based on a config.
* @returns {boolean} true if non-admin users are read-only
*/
static isNonAdminUserReadOnly() {
const makeNonAdminUsersReadOnly = window.userAccess.makeNonAdminUsersReadOnly;
return makeNonAdminUsersReadOnly === true;
}

/**
* Check if the current user has edit permissions.
* All the admin users can edit and if the 'isNonAdminUserReadOnly' is false,
* non-admin users also can edit
* @returns {boolean} true if the user has edit permissions
*/
static hasEditPermission() {
return AuthManager.isAdminUser() || !AuthManager.isNonAdminUserReadOnly();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,7 @@ function SwitchStatusCell(props) {
const { pageId, artifactName, nodeId, status, retrieveData} = props;
var isActive = status;
const globalGroupId = useSelector(state => state.groupId);
const hasEditPermission = AuthManager.hasEditPermission();

const changeState = () => {
isActive = !isActive
Expand All @@ -254,7 +255,7 @@ function SwitchStatusCell(props) {
});
}

return <tr><td><Switch checked={isActive} onChange={changeState} height={16} width={36} /></td></tr>
return <tr><td><Switch checked={isActive} onChange={changeState} height={16} width={36} disabled={!hasEditPermission}/></td></tr>
}

function LogConfigLevelDropDown(props) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,12 @@ import { TableCell, TableRow } from '@material-ui/core';
import { useSelector } from 'react-redux';
import Switch from "react-switch";
import HTTPClient from '../../../utils/HTTPClient';
import AuthManager from "../../../auth/AuthManager";

export default function TracingRow(props) {
const {pageId, artifactName, nodeId, tracing, retrieveUpdatedArtifact} = props;
var isTracingEnabled = false;
const hasEditPermission = AuthManager.hasEditPermission();

if(tracing === 'enabled') {
isTracingEnabled = true;
Expand Down Expand Up @@ -63,7 +65,7 @@ export default function TracingRow(props) {
<TableCell>Tracing</TableCell>
<TableCell>
<label>
<Switch checked={tracingState} onChange={changeTracingStatus} height={16} width={36} />
<Switch checked={tracingState} onChange={changeTracingStatus} height={16} width={36} disabled={!hasEditPermission} />
</label>
</TableCell>
</TableRow>
Expand Down

0 comments on commit 1c6f899

Please sign in to comment.