mirror of
https://repository.entgra.net/community/device-mgt-core.git
synced 2025-10-06 02:01:45 +00:00
Merge branch 'master' into master
This commit is contained in:
commit
6e1e58f2ec
@ -22,11 +22,11 @@ import com.google.gson.JsonObject;
|
|||||||
import io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.api.GrafanaAPIProxyService;
|
import io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.api.GrafanaAPIProxyService;
|
||||||
import io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.api.bean.ErrorResponse;
|
import io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.api.bean.ErrorResponse;
|
||||||
import io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.api.exception.RefererNotValid;
|
import io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.api.exception.RefererNotValid;
|
||||||
|
import io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.api.impl.util.GrafanaMgtAPIUtils;
|
||||||
import io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.api.impl.util.GrafanaRequestHandlerUtil;
|
import io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.api.impl.util.GrafanaRequestHandlerUtil;
|
||||||
import io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.common.exception.GrafanaManagementException;
|
import io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.common.exception.GrafanaManagementException;
|
||||||
import io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.core.bean.GrafanaPanelIdentifier;
|
import io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.core.bean.GrafanaPanelIdentifier;
|
||||||
import io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.core.exception.MaliciousQueryAttempt;
|
import io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.core.exception.MaliciousQueryAttempt;
|
||||||
import io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.core.internal.GrafanaMgtDataHolder;
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
import io.entgra.device.mgt.core.device.mgt.common.exceptions.DBConnectionException;
|
import io.entgra.device.mgt.core.device.mgt.common.exceptions.DBConnectionException;
|
||||||
@ -57,8 +57,8 @@ public class GrafanaAPIProxyServiceImpl implements GrafanaAPIProxyService {
|
|||||||
public Response queryDatasource(JsonObject body, @Context HttpHeaders headers, @Context UriInfo requestUriInfo) {
|
public Response queryDatasource(JsonObject body, @Context HttpHeaders headers, @Context UriInfo requestUriInfo) {
|
||||||
try {
|
try {
|
||||||
GrafanaPanelIdentifier panelIdentifier = GrafanaRequestHandlerUtil.getPanelIdentifier(headers);
|
GrafanaPanelIdentifier panelIdentifier = GrafanaRequestHandlerUtil.getPanelIdentifier(headers);
|
||||||
GrafanaMgtDataHolder.getInstance().getGrafanaQueryService().
|
GrafanaMgtAPIUtils.getGrafanaQueryService().buildSafeQuery(body, panelIdentifier.getDashboardId(),
|
||||||
buildSafeQuery(body, panelIdentifier.getDashboardId(), panelIdentifier.getPanelId(), requestUriInfo.getRequestUri());
|
panelIdentifier.getPanelId(), requestUriInfo.getRequestUri());
|
||||||
return GrafanaRequestHandlerUtil.proxyPassPostRequest(body, requestUriInfo, panelIdentifier.getOrgId());
|
return GrafanaRequestHandlerUtil.proxyPassPostRequest(body, requestUriInfo, panelIdentifier.getOrgId());
|
||||||
} catch (MaliciousQueryAttempt e) {
|
} catch (MaliciousQueryAttempt e) {
|
||||||
return Response.status(Response.Status.BAD_REQUEST).entity(
|
return Response.status(Response.Status.BAD_REQUEST).entity(
|
||||||
|
|||||||
@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018 - 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
|
||||||
|
* Version 2.0 (the "License"); you may not use this file except
|
||||||
|
* in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.api.impl.util;
|
||||||
|
|
||||||
|
import io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.core.service.GrafanaQueryService;
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.wso2.carbon.context.PrivilegedCarbonContext;
|
||||||
|
|
||||||
|
public class GrafanaMgtAPIUtils {
|
||||||
|
|
||||||
|
private static final Log log = LogFactory.getLog(GrafanaMgtAPIUtils.class);
|
||||||
|
private static volatile GrafanaQueryService grafanaQueryService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accessing GrafanaQueryService from OSGI service context
|
||||||
|
* @return GrafanaQueryService instance
|
||||||
|
*/
|
||||||
|
public static GrafanaQueryService getGrafanaQueryService() {
|
||||||
|
if (grafanaQueryService == null) {
|
||||||
|
synchronized (GrafanaMgtAPIUtils.class) {
|
||||||
|
if (grafanaQueryService == null) {
|
||||||
|
PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
|
||||||
|
grafanaQueryService =
|
||||||
|
(GrafanaQueryService) ctx.getOSGiService(GrafanaQueryService.class, null);
|
||||||
|
if (grafanaQueryService == null) {
|
||||||
|
String msg = "Grafana Query service has not initialized.";
|
||||||
|
log.error(msg);
|
||||||
|
throw new IllegalStateException(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return grafanaQueryService;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -88,7 +88,7 @@
|
|||||||
io.entgra.device.mgt.core.application.mgt.core.*
|
io.entgra.device.mgt.core.application.mgt.core.*
|
||||||
</Import-Package>
|
</Import-Package>
|
||||||
<Export-Package>
|
<Export-Package>
|
||||||
!io.entgra.device.mgt.core.transport.mgt.email.sender.core.internal,
|
!io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.core.internal,
|
||||||
io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.core.*
|
io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.core.*
|
||||||
</Export-Package>
|
</Export-Package>
|
||||||
<Embed-Dependency>
|
<Embed-Dependency>
|
||||||
|
|||||||
@ -26,7 +26,6 @@ import org.apache.commons.logging.Log;
|
|||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
import org.osgi.framework.BundleContext;
|
import org.osgi.framework.BundleContext;
|
||||||
import org.osgi.service.component.ComponentContext;
|
import org.osgi.service.component.ComponentContext;
|
||||||
import org.wso2.carbon.context.PrivilegedCarbonContext;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @scr.component name="io.entgra.analytics.mgt.grafana.proxy.grafanamanagementservicecomponent" immediate="true"
|
* @scr.component name="io.entgra.analytics.mgt.grafana.proxy.grafanamanagementservicecomponent" immediate="true"
|
||||||
|
|||||||
@ -62,17 +62,18 @@ public class APIApplicationManagerExtensionDataHolder {
|
|||||||
|
|
||||||
public void setRealmService(RealmService realmService) {
|
public void setRealmService(RealmService realmService) {
|
||||||
this.realmService = realmService;
|
this.realmService = realmService;
|
||||||
this.setTenantManager(realmService);
|
setTenantManager(realmService != null ?
|
||||||
|
realmService.getTenantManager() : null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setTenantManager(RealmService realmService) {
|
private void setTenantManager(TenantManager tenantManager) {
|
||||||
if (realmService == null) {
|
this.tenantManager = tenantManager;
|
||||||
throw new IllegalStateException("Realm service is not initialized properly");
|
|
||||||
}
|
|
||||||
this.tenantManager = realmService.getTenantManager();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public TenantManager getTenantManager() {
|
public TenantManager getTenantManager() {
|
||||||
|
if (tenantManager == null) {
|
||||||
|
throw new IllegalStateException("Tenant manager is not initialized properly");
|
||||||
|
}
|
||||||
return tenantManager;
|
return tenantManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -75,17 +75,18 @@ public class APIPublisherDataHolder {
|
|||||||
|
|
||||||
public void setRealmService(RealmService realmService) {
|
public void setRealmService(RealmService realmService) {
|
||||||
this.realmService = realmService;
|
this.realmService = realmService;
|
||||||
this.setTenantManager(realmService);
|
setTenantManager(realmService != null ?
|
||||||
|
realmService.getTenantManager() : null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setTenantManager(RealmService realmService) {
|
private void setTenantManager(TenantManager tenantManager) {
|
||||||
if (realmService == null) {
|
this.tenantManager = tenantManager;
|
||||||
throw new IllegalStateException("Realm service is not initialized properly");
|
|
||||||
}
|
|
||||||
this.tenantManager = realmService.getTenantManager();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public TenantManager getTenantManager() {
|
public TenantManager getTenantManager() {
|
||||||
|
if (tenantManager == null) {
|
||||||
|
throw new IllegalStateException("Tenant manager is not initialized properly");
|
||||||
|
}
|
||||||
return tenantManager;
|
return tenantManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -29,6 +29,7 @@ import io.entgra.device.mgt.core.device.mgt.common.group.mgt.RoleDoesNotExistExc
|
|||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
import org.wso2.carbon.CarbonConstants;
|
import org.wso2.carbon.CarbonConstants;
|
||||||
|
import org.wso2.carbon.context.CarbonContext;
|
||||||
import org.wso2.carbon.context.PrivilegedCarbonContext;
|
import org.wso2.carbon.context.PrivilegedCarbonContext;
|
||||||
import io.entgra.device.mgt.core.device.mgt.common.Device;
|
import io.entgra.device.mgt.core.device.mgt.common.Device;
|
||||||
import io.entgra.device.mgt.core.device.mgt.common.DeviceIdentifier;
|
import io.entgra.device.mgt.core.device.mgt.common.DeviceIdentifier;
|
||||||
@ -48,6 +49,8 @@ import io.entgra.device.mgt.core.device.mgt.api.jaxrs.service.impl.util.RequestV
|
|||||||
import io.entgra.device.mgt.core.device.mgt.api.jaxrs.util.DeviceMgtAPIUtils;
|
import io.entgra.device.mgt.core.device.mgt.api.jaxrs.util.DeviceMgtAPIUtils;
|
||||||
import io.entgra.device.mgt.core.policy.mgt.common.PolicyAdministratorPoint;
|
import io.entgra.device.mgt.core.policy.mgt.common.PolicyAdministratorPoint;
|
||||||
import io.entgra.device.mgt.core.policy.mgt.common.PolicyManagementException;
|
import io.entgra.device.mgt.core.policy.mgt.common.PolicyManagementException;
|
||||||
|
import org.wso2.carbon.user.api.UserRealm;
|
||||||
|
import org.wso2.carbon.user.api.UserStoreException;
|
||||||
|
|
||||||
import javax.ws.rs.DefaultValue;
|
import javax.ws.rs.DefaultValue;
|
||||||
import javax.ws.rs.GET;
|
import javax.ws.rs.GET;
|
||||||
@ -56,6 +59,7 @@ import javax.ws.rs.Path;
|
|||||||
import javax.ws.rs.QueryParam;
|
import javax.ws.rs.QueryParam;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class GroupManagementServiceImpl implements GroupManagementService {
|
public class GroupManagementServiceImpl implements GroupManagementService {
|
||||||
@ -109,8 +113,18 @@ public class GroupManagementServiceImpl implements GroupManagementService {
|
|||||||
request.setGroupName(name);
|
request.setGroupName(name);
|
||||||
request.setOwner(owner);
|
request.setOwner(owner);
|
||||||
request.setDepth(depth);
|
request.setDepth(depth);
|
||||||
PaginationResult deviceGroupsResult = DeviceMgtAPIUtils.getGroupManagementProviderService()
|
int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId();
|
||||||
.getGroupsWithHierarchy(currentUser, request, requireGroupProps);
|
UserRealm realmService = DeviceMgtAPIUtils.getRealmService().getTenantUserRealm(tenantId);
|
||||||
|
String[] roles = realmService.getUserStoreManager().getRoleListOfUser(currentUser);
|
||||||
|
boolean hasAdminRole = Arrays.asList(roles).contains(DEFAULT_ADMIN_ROLE);
|
||||||
|
PaginationResult deviceGroupsResult;
|
||||||
|
if (hasAdminRole) {
|
||||||
|
deviceGroupsResult = DeviceMgtAPIUtils.getGroupManagementProviderService()
|
||||||
|
.getGroupsWithHierarchy(null, request, requireGroupProps);
|
||||||
|
} else{
|
||||||
|
deviceGroupsResult = DeviceMgtAPIUtils.getGroupManagementProviderService()
|
||||||
|
.getGroupsWithHierarchy(currentUser, request, requireGroupProps);
|
||||||
|
}
|
||||||
DeviceGroupList deviceGroupList = new DeviceGroupList();
|
DeviceGroupList deviceGroupList = new DeviceGroupList();
|
||||||
deviceGroupList.setList(deviceGroupsResult.getData());
|
deviceGroupList.setList(deviceGroupsResult.getData());
|
||||||
deviceGroupList.setCount(deviceGroupsResult.getRecordsTotal());
|
deviceGroupList.setCount(deviceGroupsResult.getRecordsTotal());
|
||||||
@ -119,6 +133,10 @@ public class GroupManagementServiceImpl implements GroupManagementService {
|
|||||||
String error = "Error occurred while retrieving groups with hierarchy.";
|
String error = "Error occurred while retrieving groups with hierarchy.";
|
||||||
log.error(error, e);
|
log.error(error, e);
|
||||||
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(error).build();
|
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(error).build();
|
||||||
|
} catch (UserStoreException e) {
|
||||||
|
String msg = "Error occurred while getting user realm.";
|
||||||
|
log.error(msg, e);
|
||||||
|
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -457,8 +475,8 @@ public class GroupManagementServiceImpl implements GroupManagementService {
|
|||||||
log.error(msg, e);
|
log.error(msg, e);
|
||||||
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build();
|
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build();
|
||||||
} catch (GroupAlreadyExistException e) {
|
} catch (GroupAlreadyExistException e) {
|
||||||
String msg = "Group already exists with name : " + groups.getName() + ".";
|
String msg = "Group already exists with name : " + groups.getName() + " Try with another group name.";
|
||||||
log.warn(msg);
|
log.error(msg, e);
|
||||||
return Response.status(Response.Status.CONFLICT).entity(msg).build();
|
return Response.status(Response.Status.CONFLICT).entity(msg).build();
|
||||||
} catch (RoleDoesNotExistException e) {
|
} catch (RoleDoesNotExistException e) {
|
||||||
return Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage()).build();
|
return Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage()).build();
|
||||||
|
|||||||
@ -18,6 +18,7 @@
|
|||||||
package io.entgra.device.mgt.core.device.mgt.api.jaxrs.service.impl;
|
package io.entgra.device.mgt.core.device.mgt.api.jaxrs.service.impl;
|
||||||
|
|
||||||
import io.entgra.device.mgt.core.device.mgt.common.exceptions.MetadataManagementException;
|
import io.entgra.device.mgt.core.device.mgt.common.exceptions.MetadataManagementException;
|
||||||
|
import io.entgra.device.mgt.core.device.mgt.common.group.mgt.GroupManagementException;
|
||||||
import io.entgra.device.mgt.core.device.mgt.common.metadata.mgt.Metadata;
|
import io.entgra.device.mgt.core.device.mgt.common.metadata.mgt.Metadata;
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.json.simple.JSONObject;
|
import org.json.simple.JSONObject;
|
||||||
@ -637,6 +638,7 @@ public class RoleManagementServiceImpl implements RoleManagementService {
|
|||||||
@Consumes(MediaType.WILDCARD)
|
@Consumes(MediaType.WILDCARD)
|
||||||
@Override
|
@Override
|
||||||
public Response deleteRole(@PathParam("roleName") String roleName, @QueryParam("user-store") String userStoreName) {
|
public Response deleteRole(@PathParam("roleName") String roleName, @QueryParam("user-store") String userStoreName) {
|
||||||
|
String roleToDelete = roleName;
|
||||||
if (userStoreName != null && !userStoreName.isEmpty()) {
|
if (userStoreName != null && !userStoreName.isEmpty()) {
|
||||||
roleName = userStoreName + "/" + roleName;
|
roleName = userStoreName + "/" + roleName;
|
||||||
}
|
}
|
||||||
@ -644,6 +646,7 @@ public class RoleManagementServiceImpl implements RoleManagementService {
|
|||||||
try {
|
try {
|
||||||
final UserRealm userRealm = DeviceMgtAPIUtils.getUserRealm();
|
final UserRealm userRealm = DeviceMgtAPIUtils.getUserRealm();
|
||||||
final UserStoreManager userStoreManager = userRealm.getUserStoreManager();
|
final UserStoreManager userStoreManager = userRealm.getUserStoreManager();
|
||||||
|
int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId();
|
||||||
if (!userStoreManager.isExistingRole(roleName)) {
|
if (!userStoreManager.isExistingRole(roleName)) {
|
||||||
String msg = "No role exists with the name : " + roleName ;
|
String msg = "No role exists with the name : " + roleName ;
|
||||||
return Response.status(404).entity(msg).build();
|
return Response.status(404).entity(msg).build();
|
||||||
@ -653,16 +656,18 @@ public class RoleManagementServiceImpl implements RoleManagementService {
|
|||||||
if (log.isDebugEnabled()) {
|
if (log.isDebugEnabled()) {
|
||||||
log.debug("Deleting the role in user store");
|
log.debug("Deleting the role in user store");
|
||||||
}
|
}
|
||||||
userStoreManager.deleteRole(roleName);
|
DeviceMgtAPIUtils.getGroupManagementProviderService().deleteRoleAndRoleGroupMapping(roleName, roleToDelete, tenantId, userStoreManager, authorizationManager);
|
||||||
// Delete all authorizations for the current role before deleting
|
|
||||||
authorizationManager.clearRoleAuthorization(roleName);
|
|
||||||
|
|
||||||
return Response.status(Response.Status.OK).build();
|
return Response.status(Response.Status.OK).build();
|
||||||
} catch (UserStoreException e) {
|
} catch (UserStoreException e) {
|
||||||
String msg = "Error occurred while deleting the role '" + roleName + "'";
|
String msg = "Error occurred while deleting the role '" + roleName + "'";
|
||||||
log.error(msg, e);
|
log.error(msg, e);
|
||||||
return Response.serverError().entity(
|
return Response.serverError().entity(
|
||||||
new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()).build();
|
new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()).build();
|
||||||
|
} catch (GroupManagementException e) {
|
||||||
|
String msg = "Error occurred while deleting group-role mapping records";
|
||||||
|
log.error(msg, e);
|
||||||
|
return Response.serverError().entity(
|
||||||
|
new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()).build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -31,7 +31,11 @@ import io.entgra.device.mgt.core.device.mgt.api.jaxrs.beans.DeviceGroupList;
|
|||||||
import io.entgra.device.mgt.core.device.mgt.api.jaxrs.service.api.admin.GroupManagementAdminService;
|
import io.entgra.device.mgt.core.device.mgt.api.jaxrs.service.api.admin.GroupManagementAdminService;
|
||||||
import io.entgra.device.mgt.core.device.mgt.api.jaxrs.service.impl.util.RequestValidationUtil;
|
import io.entgra.device.mgt.core.device.mgt.api.jaxrs.service.impl.util.RequestValidationUtil;
|
||||||
import io.entgra.device.mgt.core.device.mgt.api.jaxrs.util.DeviceMgtAPIUtils;
|
import io.entgra.device.mgt.core.device.mgt.api.jaxrs.util.DeviceMgtAPIUtils;
|
||||||
|
import org.wso2.carbon.context.CarbonContext;
|
||||||
import org.wso2.carbon.context.PrivilegedCarbonContext;
|
import org.wso2.carbon.context.PrivilegedCarbonContext;
|
||||||
|
import org.apache.commons.lang.StringUtils;
|
||||||
|
import org.wso2.carbon.user.api.UserRealm;
|
||||||
|
import org.wso2.carbon.user.api.UserStoreException;
|
||||||
|
|
||||||
import javax.ws.rs.DefaultValue;
|
import javax.ws.rs.DefaultValue;
|
||||||
import javax.ws.rs.GET;
|
import javax.ws.rs.GET;
|
||||||
@ -40,6 +44,7 @@ import javax.ws.rs.Path;
|
|||||||
import javax.ws.rs.QueryParam;
|
import javax.ws.rs.QueryParam;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
public class GroupManagementAdminServiceImpl implements GroupManagementAdminService {
|
public class GroupManagementAdminServiceImpl implements GroupManagementAdminService {
|
||||||
|
|
||||||
@ -94,13 +99,25 @@ public class GroupManagementAdminServiceImpl implements GroupManagementAdminServ
|
|||||||
@DefaultValue("5") @QueryParam("limit") int limit) {
|
@DefaultValue("5") @QueryParam("limit") int limit) {
|
||||||
try {
|
try {
|
||||||
RequestValidationUtil.validatePaginationParameters(offset, limit);
|
RequestValidationUtil.validatePaginationParameters(offset, limit);
|
||||||
|
String currentUser = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername();
|
||||||
GroupPaginationRequest request = new GroupPaginationRequest(offset, limit);
|
GroupPaginationRequest request = new GroupPaginationRequest(offset, limit);
|
||||||
request.setGroupName(name);
|
request.setGroupName(name);
|
||||||
request.setOwner(owner);
|
request.setOwner(owner);
|
||||||
request.setStatus(status);
|
request.setStatus(status);
|
||||||
request.setDepth(depth);
|
request.setDepth(depth);
|
||||||
PaginationResult deviceGroupsResult = DeviceMgtAPIUtils.getGroupManagementProviderService()
|
int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId();
|
||||||
.getGroupsWithHierarchy(null, request, requireGroupProps);
|
UserRealm realmService = DeviceMgtAPIUtils.getRealmService().getTenantUserRealm(tenantId);
|
||||||
|
String[] roles = realmService.getUserStoreManager().getRoleListOfUser(currentUser);
|
||||||
|
boolean isAdmin = DEFAULT_ADMIN_ROLE.equals(currentUser);
|
||||||
|
boolean hasAdminRole = Arrays.asList(roles).contains(DEFAULT_ADMIN_ROLE);
|
||||||
|
PaginationResult deviceGroupsResult;
|
||||||
|
if (StringUtils.isBlank(currentUser) || isAdmin || hasAdminRole) {
|
||||||
|
deviceGroupsResult = DeviceMgtAPIUtils.getGroupManagementProviderService()
|
||||||
|
.getGroupsWithHierarchy(null, request, requireGroupProps);
|
||||||
|
} else {
|
||||||
|
deviceGroupsResult = DeviceMgtAPIUtils.getGroupManagementProviderService()
|
||||||
|
.getGroupsWithHierarchy(currentUser, request, requireGroupProps);
|
||||||
|
}
|
||||||
DeviceGroupList deviceGroupList = new DeviceGroupList();
|
DeviceGroupList deviceGroupList = new DeviceGroupList();
|
||||||
deviceGroupList.setList(deviceGroupsResult.getData());
|
deviceGroupList.setList(deviceGroupsResult.getData());
|
||||||
deviceGroupList.setCount(deviceGroupsResult.getRecordsTotal());
|
deviceGroupList.setCount(deviceGroupsResult.getRecordsTotal());
|
||||||
@ -109,6 +126,10 @@ public class GroupManagementAdminServiceImpl implements GroupManagementAdminServ
|
|||||||
String error = "Error occurred while retrieving groups with hierarchy.";
|
String error = "Error occurred while retrieving groups with hierarchy.";
|
||||||
log.error(error, e);
|
log.error(error, e);
|
||||||
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(error).build();
|
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(error).build();
|
||||||
|
} catch (UserStoreException e) {
|
||||||
|
String msg = "Error occurred while getting user realm.";
|
||||||
|
log.error(msg, e);
|
||||||
|
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,8 +187,8 @@ public class GroupManagementAdminServiceImpl implements GroupManagementAdminServ
|
|||||||
log.error(msg, e);
|
log.error(msg, e);
|
||||||
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build();
|
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build();
|
||||||
} catch (GroupAlreadyExistException e) {
|
} catch (GroupAlreadyExistException e) {
|
||||||
String msg = "Group already exists with name : " + group.getName() + ".";
|
String msg = "Group already exists with name : " + group.getName() + " Try with another group name.";
|
||||||
log.warn(msg);
|
log.error(msg, e);
|
||||||
return Response.status(Response.Status.CONFLICT).entity(msg).build();
|
return Response.status(Response.Status.CONFLICT).entity(msg).build();
|
||||||
} catch (RoleDoesNotExistException e) {
|
} catch (RoleDoesNotExistException e) {
|
||||||
return Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage()).build();
|
return Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage()).build();
|
||||||
|
|||||||
@ -156,6 +156,15 @@ public interface GroupDAO {
|
|||||||
*/
|
*/
|
||||||
void deleteGroupsMapping(List<Integer> groupIds, int tenantId) throws GroupManagementDAOException;
|
void deleteGroupsMapping(List<Integer> groupIds, int tenantId) throws GroupManagementDAOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete mappings of Device Groups.
|
||||||
|
*
|
||||||
|
* @param role of Device Groups.
|
||||||
|
* @param tenantId of the role.
|
||||||
|
* @throws GroupManagementDAOException on error during deletion of mappings of groups
|
||||||
|
*/
|
||||||
|
void deleteGroupsMapping(String role, int tenantId) throws GroupManagementDAOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete existing Device Groups.
|
* Delete existing Device Groups.
|
||||||
*
|
*
|
||||||
|
|||||||
@ -544,6 +544,23 @@ public abstract class AbstractGroupDAOImpl implements GroupDAO {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deleteGroupsMapping(String role, int tenantId) throws GroupManagementDAOException {
|
||||||
|
|
||||||
|
try {
|
||||||
|
Connection conn = GroupManagementDAOFactory.getConnection();
|
||||||
|
String sql = "DELETE FROM DM_ROLE_GROUP_MAP WHERE ROLE = ? AND TENANT_ID = ?";
|
||||||
|
try (PreparedStatement stmt = conn.prepareStatement(sql)) {
|
||||||
|
stmt.setString(1, role);
|
||||||
|
stmt.setInt(2, tenantId);
|
||||||
|
stmt.executeUpdate();
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
String msg = "Error occurred while removing record from group-role mapping.";
|
||||||
|
log.error(msg);
|
||||||
|
throw new GroupManagementDAOException(msg, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
@Override
|
@Override
|
||||||
public void deleteGroups(List<Integer> groupIds, int tenantId) throws GroupManagementDAOException {
|
public void deleteGroups(List<Integer> groupIds, int tenantId) throws GroupManagementDAOException {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@ -480,6 +480,7 @@ public class OperationManagerImpl implements OperationManager {
|
|||||||
int failAttempts = 0;
|
int failAttempts = 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
try {
|
try {
|
||||||
|
OperationManagementDAOFactory.beginTransaction();
|
||||||
operationMappingDAO.updateOperationMapping(operation.getId(), device.getEnrolmentInfo().getId(),
|
operationMappingDAO.updateOperationMapping(operation.getId(), device.getEnrolmentInfo().getId(),
|
||||||
io.entgra.device.mgt.core.device.mgt.core.dto.operation.mgt.Operation.PushNotificationStatus.SCHEDULED);
|
io.entgra.device.mgt.core.device.mgt.core.dto.operation.mgt.Operation.PushNotificationStatus.SCHEDULED);
|
||||||
OperationManagementDAOFactory.commitTransaction();
|
OperationManagementDAOFactory.commitTransaction();
|
||||||
@ -502,6 +503,11 @@ public class OperationManagerImpl implements OperationManager {
|
|||||||
} catch (InterruptedException ignore) {
|
} catch (InterruptedException ignore) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
} catch (TransactionManagementException ex) {
|
||||||
|
log.error("Error occurred while initiating the transaction", ex);
|
||||||
|
break;
|
||||||
|
} finally {
|
||||||
|
OperationManagementDAOFactory.closeConnection();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|||||||
@ -30,6 +30,8 @@ import io.entgra.device.mgt.core.device.mgt.common.group.mgt.GroupAlreadyExistEx
|
|||||||
import io.entgra.device.mgt.core.device.mgt.common.group.mgt.GroupManagementException;
|
import io.entgra.device.mgt.core.device.mgt.common.group.mgt.GroupManagementException;
|
||||||
import io.entgra.device.mgt.core.device.mgt.common.group.mgt.GroupNotExistException;
|
import io.entgra.device.mgt.core.device.mgt.common.group.mgt.GroupNotExistException;
|
||||||
import io.entgra.device.mgt.core.device.mgt.common.group.mgt.RoleDoesNotExistException;
|
import io.entgra.device.mgt.core.device.mgt.common.group.mgt.RoleDoesNotExistException;
|
||||||
|
import org.wso2.carbon.user.api.AuthorizationManager;
|
||||||
|
import org.wso2.carbon.user.api.UserStoreManager;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -57,7 +59,7 @@ public interface GroupManagementProviderService {
|
|||||||
* @param defaultPermissions of the default role
|
* @param defaultPermissions of the default role
|
||||||
* @throws GroupManagementException
|
* @throws GroupManagementException
|
||||||
*/
|
*/
|
||||||
void createGroupWithRoles(DeviceGroupRoleWrapper groups, String defaultRole, String[] defaultPermissions) throws GroupManagementException, GroupAlreadyExistException, RoleDoesNotExistException;
|
void createGroupWithRoles(DeviceGroupRoleWrapper groups, String defaultRole, String[] defaultPermissions) throws GroupAlreadyExistException,GroupManagementException, RoleDoesNotExistException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update existing device group.
|
* Update existing device group.
|
||||||
@ -79,6 +81,18 @@ public interface GroupManagementProviderService {
|
|||||||
*/
|
*/
|
||||||
boolean deleteGroup(int groupId, boolean isDeleteChildren) throws GroupManagementException;
|
boolean deleteGroup(int groupId, boolean isDeleteChildren) throws GroupManagementException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete existing device group.
|
||||||
|
*
|
||||||
|
* @param role to be deleted with the userStore name.
|
||||||
|
* @param roleToDelete to delete the role.
|
||||||
|
* @param tenantId to belongs to roles.
|
||||||
|
* @param userStoreManager with details.
|
||||||
|
* @param authorizationManager with details.
|
||||||
|
* @throws GroupManagementException
|
||||||
|
*/
|
||||||
|
void deleteRoleAndRoleGroupMapping(String role, String roleToDelete, int tenantId, UserStoreManager userStoreManager, AuthorizationManager authorizationManager) throws GroupManagementException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the device group provided the device group id.
|
* Get the device group provided the device group id.
|
||||||
*
|
*
|
||||||
|
|||||||
@ -35,7 +35,6 @@ import io.entgra.device.mgt.core.device.mgt.core.dao.GroupManagementDAOFactory;
|
|||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang.StringUtils;
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
import org.netbeans.lib.cvsclient.commandLine.command.status;
|
|
||||||
import org.wso2.carbon.CarbonConstants;
|
import org.wso2.carbon.CarbonConstants;
|
||||||
import org.wso2.carbon.context.CarbonContext;
|
import org.wso2.carbon.context.CarbonContext;
|
||||||
import org.wso2.carbon.context.PrivilegedCarbonContext;
|
import org.wso2.carbon.context.PrivilegedCarbonContext;
|
||||||
@ -46,14 +45,13 @@ import io.entgra.device.mgt.core.device.mgt.common.exceptions.DeviceManagementEx
|
|||||||
import io.entgra.device.mgt.core.device.mgt.common.exceptions.DeviceNotFoundException;
|
import io.entgra.device.mgt.core.device.mgt.common.exceptions.DeviceNotFoundException;
|
||||||
import io.entgra.device.mgt.core.device.mgt.common.GroupPaginationRequest;
|
import io.entgra.device.mgt.core.device.mgt.common.GroupPaginationRequest;
|
||||||
import io.entgra.device.mgt.core.device.mgt.common.PaginationResult;
|
import io.entgra.device.mgt.core.device.mgt.common.PaginationResult;
|
||||||
import io.entgra.device.mgt.core.device.mgt.common.exceptions.TrackerAlreadyExistException;
|
|
||||||
import io.entgra.device.mgt.core.device.mgt.common.exceptions.TransactionManagementException;
|
import io.entgra.device.mgt.core.device.mgt.common.exceptions.TransactionManagementException;
|
||||||
import io.entgra.device.mgt.core.device.mgt.core.event.config.GroupAssignmentEventOperationExecutor;
|
import io.entgra.device.mgt.core.device.mgt.core.event.config.GroupAssignmentEventOperationExecutor;
|
||||||
import io.entgra.device.mgt.core.device.mgt.core.geo.task.GeoFenceEventOperationManager;
|
import io.entgra.device.mgt.core.device.mgt.core.geo.task.GeoFenceEventOperationManager;
|
||||||
import io.entgra.device.mgt.core.device.mgt.core.internal.DeviceManagementDataHolder;
|
import io.entgra.device.mgt.core.device.mgt.core.internal.DeviceManagementDataHolder;
|
||||||
import io.entgra.device.mgt.core.device.mgt.core.operation.mgt.OperationMgtConstants;
|
import io.entgra.device.mgt.core.device.mgt.core.operation.mgt.OperationMgtConstants;
|
||||||
import io.entgra.device.mgt.core.device.mgt.core.util.DeviceManagerUtil;
|
import io.entgra.device.mgt.core.device.mgt.core.util.DeviceManagerUtil;
|
||||||
import io.entgra.device.mgt.core.device.mgt.core.util.HttpReportingUtil;
|
import org.wso2.carbon.user.api.AuthorizationManager;
|
||||||
import org.wso2.carbon.user.api.UserRealm;
|
import org.wso2.carbon.user.api.UserRealm;
|
||||||
import org.wso2.carbon.user.api.UserStoreException;
|
import org.wso2.carbon.user.api.UserStoreException;
|
||||||
import org.wso2.carbon.user.api.UserStoreManager;
|
import org.wso2.carbon.user.api.UserStoreManager;
|
||||||
@ -148,7 +146,7 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void createGroupWithRoles(DeviceGroupRoleWrapper groups, String defaultRole, String[] defaultPermissions) throws GroupManagementException {
|
public void createGroupWithRoles(DeviceGroupRoleWrapper groups, String defaultRole, String[] defaultPermissions) throws GroupAlreadyExistException, GroupManagementException {
|
||||||
if (groups == null) {
|
if (groups == null) {
|
||||||
String msg = "Received incomplete data for createGroup";
|
String msg = "Received incomplete data for createGroup";
|
||||||
log.error(msg);
|
log.error(msg);
|
||||||
@ -181,7 +179,7 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid
|
|||||||
}
|
}
|
||||||
GroupManagementDAOFactory.commitTransaction();
|
GroupManagementDAOFactory.commitTransaction();
|
||||||
} else {
|
} else {
|
||||||
throw new GroupManagementException("Group exist with name " + groups.getName());
|
throw new GroupAlreadyExistException("Group already exists with name : " + groups.getName() + " Try with another group name.");
|
||||||
}
|
}
|
||||||
} catch (GroupManagementDAOException e) {
|
} catch (GroupManagementDAOException e) {
|
||||||
GroupManagementDAOFactory.rollbackTransaction();
|
GroupManagementDAOFactory.rollbackTransaction();
|
||||||
@ -359,6 +357,40 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void deleteRoleAndRoleGroupMapping(String roleName, String roleToDelete, int tenantId, UserStoreManager userStoreManager, AuthorizationManager authorizationManager) throws GroupManagementException {
|
||||||
|
if (log.isDebugEnabled()) {
|
||||||
|
log.debug("Delete roles");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
GroupManagementDAOFactory.beginTransaction();
|
||||||
|
groupDAO.deleteGroupsMapping(roleToDelete, tenantId);
|
||||||
|
userStoreManager.deleteRole(roleName);
|
||||||
|
// Delete all authorizations for the current role before deleting
|
||||||
|
authorizationManager.clearRoleAuthorization(roleName);
|
||||||
|
GroupManagementDAOFactory.commitTransaction();
|
||||||
|
} catch (UserStoreException e) {
|
||||||
|
GroupManagementDAOFactory.rollbackTransaction();
|
||||||
|
String msg = "Error occurred while deleting the role '" + roleName + "'";
|
||||||
|
log.error(msg, e);
|
||||||
|
throw new GroupManagementException(msg, e);
|
||||||
|
} catch (TransactionManagementException e) {
|
||||||
|
String msg = "Error occurred while initiating transaction.";
|
||||||
|
log.error(msg, e);
|
||||||
|
throw new GroupManagementException(msg, e);
|
||||||
|
} catch (GroupManagementDAOException e) {
|
||||||
|
GroupManagementDAOFactory.rollbackTransaction();
|
||||||
|
String msg = "Error occurred while deleting the role";
|
||||||
|
log.error(msg, e);
|
||||||
|
throw new GroupManagementException(msg, e);
|
||||||
|
} finally {
|
||||||
|
GroupManagementDAOFactory.closeConnection();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -74,17 +74,18 @@ public class JWTClientExtensionDataHolder {
|
|||||||
|
|
||||||
public void setRealmService(RealmService realmService) {
|
public void setRealmService(RealmService realmService) {
|
||||||
this.realmService = realmService;
|
this.realmService = realmService;
|
||||||
this.setTenantManager(realmService);
|
setTenantManager(realmService != null ?
|
||||||
|
realmService.getTenantManager() : null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setTenantManager(RealmService realmService) {
|
private void setTenantManager(TenantManager tenantManager) {
|
||||||
if (realmService == null) {
|
this.tenantManager = tenantManager;
|
||||||
throw new IllegalStateException("Realm service is not initialized properly");
|
|
||||||
}
|
|
||||||
this.tenantManager = realmService.getTenantManager();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public TenantManager getTenantManager() {
|
public TenantManager getTenantManager() {
|
||||||
|
if (tenantManager == null) {
|
||||||
|
throw new IllegalStateException("Tenant manager is not initialized properly");
|
||||||
|
}
|
||||||
return tenantManager;
|
return tenantManager;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -189,7 +189,7 @@
|
|||||||
<a href='https://entgra.io' target='_blank'>
|
<a href='https://entgra.io' target='_blank'>
|
||||||
Entgra
|
Entgra
|
||||||
</a>
|
</a>
|
||||||
IoT Server 5.2.0 | © 2023
|
UEM Server 5.3.0 | © 2023
|
||||||
, All Rights Reserved.
|
, All Rights Reserved.
|
||||||
</FooterText>
|
</FooterText>
|
||||||
<AppTitle>Entgra</AppTitle>
|
<AppTitle>Entgra</AppTitle>
|
||||||
|
|||||||
@ -227,6 +227,19 @@
|
|||||||
<Scope>perm:android:clear-application</Scope>
|
<Scope>perm:android:clear-application</Scope>
|
||||||
<Scope>perm:android:suspend-package</Scope>
|
<Scope>perm:android:suspend-package</Scope>
|
||||||
<Scope>perm:android:alternate-install</Scope>
|
<Scope>perm:android:alternate-install</Scope>
|
||||||
|
<Scope>perm:ios:lock</Scope>
|
||||||
|
<Scope>perm:ios:location</Scope>
|
||||||
|
<Scope>perm:ios:ring</Scope>
|
||||||
|
<Scope>perm:ios:clear-passcode</Scope>
|
||||||
|
<Scope>perm:ios:enterprise-wipe</Scope>
|
||||||
|
<Scope>perm:ios:notification</Scope>
|
||||||
|
<Scope>perm:ios:wipe-data</Scope>
|
||||||
|
<Scope>perm:ios:boolean-setting</Scope>
|
||||||
|
<Scope>perm:ios:wallpaper</Scope>
|
||||||
|
<Scope>perm:ios:app-attributes</Scope>
|
||||||
|
<Scope>perm:ios:app-configurations</Scope>
|
||||||
|
<Scope>perm:mac-os:restart</Scope>
|
||||||
|
<Scope>perm:mac-os:shut-down</Scope>
|
||||||
</Scopes>
|
</Scopes>
|
||||||
<SSOConfiguration>
|
<SSOConfiguration>
|
||||||
<Issuer>device-mgt</Issuer>
|
<Issuer>device-mgt</Issuer>
|
||||||
|
|||||||
@ -325,12 +325,16 @@
|
|||||||
<MetaDataConfiguration>
|
<MetaDataConfiguration>
|
||||||
<WhiteLabelConfiguration>
|
<WhiteLabelConfiguration>
|
||||||
<FooterText>
|
<FooterText>
|
||||||
<a href='https://entgra.io' target='_blank'>
|
<a href='https://entgra.io' target='_blank'>
|
||||||
Entgra
|
Entgra
|
||||||
</a>
|
</a>
|
||||||
IoT Server 5.2.0 | © 2023
|
{% if product_conf is defined %}
|
||||||
, All Rights Reserved.
|
{{product_conf.server_name}} {{product_conf.server_version}} | © {{product_conf.current_year}}
|
||||||
</FooterText>
|
{% else %}
|
||||||
|
Entgra UEM Server
|
||||||
|
{% endif %}
|
||||||
|
, All Rights Reserved.
|
||||||
|
</FooterText>
|
||||||
<AppTitle>Entgra</AppTitle>
|
<AppTitle>Entgra</AppTitle>
|
||||||
<WhiteLabelImages>
|
<WhiteLabelImages>
|
||||||
<StoragePath>repository/resources/whitelabel</StoragePath>
|
<StoragePath>repository/resources/whitelabel</StoragePath>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user