Improve Access control interfaces.

This commit is contained in:
Igor Kulikov 2018-12-08 11:48:29 +02:00
parent f6b70211da
commit a043decbf2
11 changed files with 59 additions and 87 deletions

View File

@ -51,7 +51,7 @@ public class AdminController extends BaseController {
@ResponseBody @ResponseBody
public AdminSettings getAdminSettings(@PathVariable("key") String key) throws ThingsboardException { public AdminSettings getAdminSettings(@PathVariable("key") String key) throws ThingsboardException {
try { try {
accessControlService.checkPermission(getCurrentUser(), TenantId.SYS_TENANT_ID, Resource.ADMIN_SETTINGS, Operation.READ); accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.READ);
return checkNotNull(adminSettingsService.findAdminSettingsByKey(TenantId.SYS_TENANT_ID, key)); return checkNotNull(adminSettingsService.findAdminSettingsByKey(TenantId.SYS_TENANT_ID, key));
} catch (Exception e) { } catch (Exception e) {
throw handleException(e); throw handleException(e);
@ -63,7 +63,7 @@ public class AdminController extends BaseController {
@ResponseBody @ResponseBody
public AdminSettings saveAdminSettings(@RequestBody AdminSettings adminSettings) throws ThingsboardException { public AdminSettings saveAdminSettings(@RequestBody AdminSettings adminSettings) throws ThingsboardException {
try { try {
accessControlService.checkPermission(getCurrentUser(), TenantId.SYS_TENANT_ID, Resource.ADMIN_SETTINGS, Operation.WRITE); accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.WRITE);
adminSettings = checkNotNull(adminSettingsService.saveAdminSettings(TenantId.SYS_TENANT_ID, adminSettings)); adminSettings = checkNotNull(adminSettingsService.saveAdminSettings(TenantId.SYS_TENANT_ID, adminSettings));
if (adminSettings.getKey().equals("mail")) { if (adminSettings.getKey().equals("mail")) {
mailService.updateMailConfiguration(); mailService.updateMailConfiguration();
@ -78,7 +78,7 @@ public class AdminController extends BaseController {
@RequestMapping(value = "/settings/testMail", method = RequestMethod.POST) @RequestMapping(value = "/settings/testMail", method = RequestMethod.POST)
public void sendTestMail(@RequestBody AdminSettings adminSettings) throws ThingsboardException { public void sendTestMail(@RequestBody AdminSettings adminSettings) throws ThingsboardException {
try { try {
accessControlService.checkPermission(getCurrentUser(), TenantId.SYS_TENANT_ID, Resource.ADMIN_SETTINGS, Operation.READ); accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.READ);
adminSettings = checkNotNull(adminSettings); adminSettings = checkNotNull(adminSettings);
if (adminSettings.getKey().equals("mail")) { if (adminSettings.getKey().equals("mail")) {
String email = getCurrentUser().getEmail(); String email = getCurrentUser().getEmail();

View File

@ -259,9 +259,16 @@ public abstract class BaseController {
} }
} }
void checkTenantId(TenantId tenantId, Operation operation) throws ThingsboardException { Tenant checkTenantId(TenantId tenantId, Operation operation) throws ThingsboardException {
validateId(tenantId, INCORRECT_TENANT_ID + tenantId); try {
accessControlService.checkPermission(getCurrentUser(), tenantId, Resource.TENANT, operation, tenantId); validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
Tenant tenant = tenantService.findTenantById(tenantId);
checkNotNull(tenant);
accessControlService.checkPermission(getCurrentUser(), Resource.TENANT, operation, tenantId, tenant);
return tenant;
} catch (Exception e) {
throw handleException(e, false);
}
} }
protected TenantId getTenantId() throws ThingsboardException { protected TenantId getTenantId() throws ThingsboardException {
@ -270,16 +277,11 @@ public abstract class BaseController {
Customer checkCustomerId(CustomerId customerId, Operation operation) throws ThingsboardException { Customer checkCustomerId(CustomerId customerId, Operation operation) throws ThingsboardException {
try { try {
accessControlService.checkPermission(getCurrentUser(), getCurrentUser().getTenantId(), Resource.CUSTOMER, operation, customerId); validateId(customerId, "Incorrect customerId " + customerId);
Customer customer = customerService.findCustomerById(getTenantId(), customerId);
if (customerId != null && !customerId.isNullUid()) { checkNotNull(customer);
Customer customer = customerService.findCustomerById(getTenantId(), customerId); accessControlService.checkPermission(getCurrentUser(), Resource.CUSTOMER, operation, customerId, customer);
checkNotNull(customer); return customer;
accessControlService.checkPermission(getCurrentUser(), Resource.CUSTOMER, operation, customerId, customer);
return customer;
} else {
return null;
}
} catch (Exception e) { } catch (Exception e) {
throw handleException(e, false); throw handleException(e, false);
} }

View File

@ -72,8 +72,8 @@ public class TenantController extends BaseController {
Operation operation = newTenant ? Operation.CREATE : Operation.WRITE; Operation operation = newTenant ? Operation.CREATE : Operation.WRITE;
accessControlService.checkPermission(getCurrentUser(), tenant.getId(), Resource.TENANT, operation, accessControlService.checkPermission(getCurrentUser(), Resource.TENANT, operation,
tenant.getId()); tenant.getId(), tenant);
tenant = checkNotNull(tenantService.saveTenant(tenant)); tenant = checkNotNull(tenantService.saveTenant(tenant));
if (newTenant) { if (newTenant) {

View File

@ -275,7 +275,7 @@ public class AccessValidator {
return ValidationResult.entityNotFound("Customer with requested id wasn't found!"); return ValidationResult.entityNotFound("Customer with requested id wasn't found!");
} else { } else {
try { try {
accessControlService.checkPermission(currentUser, customer.getTenantId(), Resource.CUSTOMER, operation, entityId); accessControlService.checkPermission(currentUser, Resource.CUSTOMER, operation, entityId, customer);
} catch (ThingsboardException e) { } catch (ThingsboardException e) {
return ValidationResult.accessDenied(e.getMessage()); return ValidationResult.accessDenied(e.getMessage());
} }
@ -297,7 +297,7 @@ public class AccessValidator {
return ValidationResult.entityNotFound("Tenant with requested id wasn't found!"); return ValidationResult.entityNotFound("Tenant with requested id wasn't found!");
} }
try { try {
accessControlService.checkPermission(currentUser, new TenantId(entityId.getId()), Resource.TENANT, operation, entityId); accessControlService.checkPermission(currentUser, Resource.TENANT, operation, entityId, tenant);
} catch (ThingsboardException e) { } catch (ThingsboardException e) {
return ValidationResult.accessDenied(e.getMessage()); return ValidationResult.accessDenied(e.getMessage());
} }

View File

@ -24,10 +24,8 @@ import org.thingsboard.server.service.security.model.SecurityUser;
public interface AccessControlService { public interface AccessControlService {
void checkPermission(SecurityUser user, TenantId tenantId, Resource resource, Operation operation) throws ThingsboardException; void checkPermission(SecurityUser user, Resource resource, Operation operation) throws ThingsboardException;
void checkPermission(SecurityUser user, TenantId tenantId, Resource resource, Operation operation, EntityId entityId) throws ThingsboardException; <I extends EntityId, T extends HasTenantId> void checkPermission(SecurityUser user, Resource resource, Operation operation, I entityId, T entity) throws ThingsboardException;
<T extends HasTenantId, I extends EntityId> void checkPermission(SecurityUser user, Resource resource, Operation operation, I entityId, T entity) throws ThingsboardException;
} }

View File

@ -42,7 +42,7 @@ public class CustomerUserPremissions extends AbstractPermissions {
put(Resource.WIDGET_TYPE, widgetsPermissionChecker); put(Resource.WIDGET_TYPE, widgetsPermissionChecker);
} }
public static final PermissionChecker customerEntityPermissionChecker = private static final PermissionChecker customerEntityPermissionChecker =
new PermissionChecker.GenericPermissionChecker(Operation.READ, Operation.READ_ATTRIBUTES, Operation.READ_TELEMETRY) { new PermissionChecker.GenericPermissionChecker(Operation.READ, Operation.READ_ATTRIBUTES, Operation.READ_TELEMETRY) {
@Override @Override
@ -68,8 +68,8 @@ public class CustomerUserPremissions extends AbstractPermissions {
new PermissionChecker.GenericPermissionChecker(Operation.READ, Operation.READ_ATTRIBUTES, Operation.READ_TELEMETRY) { new PermissionChecker.GenericPermissionChecker(Operation.READ, Operation.READ_ATTRIBUTES, Operation.READ_TELEMETRY) {
@Override @Override
public boolean hasPermission(SecurityUser user, TenantId tenantId, Operation operation, EntityId entityId) { public boolean hasPermission(SecurityUser user, Operation operation, EntityId entityId, HasTenantId entity) {
if (!super.hasPermission(user, tenantId, operation, entityId)) { if (!super.hasPermission(user, operation, entityId, entity)) {
return false; return false;
} }
if (!user.getCustomerId().equals(entityId)) { if (!user.getCustomerId().equals(entityId)) {
@ -81,7 +81,7 @@ public class CustomerUserPremissions extends AbstractPermissions {
}; };
private static final PermissionChecker customerDashboardPermissionChecker = private static final PermissionChecker customerDashboardPermissionChecker =
new PermissionChecker.GenericPermissionChecker<DashboardInfo, DashboardId>(Operation.READ, Operation.READ_ATTRIBUTES, Operation.READ_TELEMETRY) { new PermissionChecker.GenericPermissionChecker<DashboardId, DashboardInfo>(Operation.READ, Operation.READ_ATTRIBUTES, Operation.READ_TELEMETRY) {
@Override @Override
public boolean hasPermission(SecurityUser user, Operation operation, DashboardId dashboardId, DashboardInfo dashboard) { public boolean hasPermission(SecurityUser user, Operation operation, DashboardId dashboardId, DashboardInfo dashboard) {
@ -100,7 +100,7 @@ public class CustomerUserPremissions extends AbstractPermissions {
}; };
private static final PermissionChecker userPermissionChecker = new PermissionChecker<User, UserId>() { private static final PermissionChecker userPermissionChecker = new PermissionChecker<UserId, User>() {
@Override @Override
public boolean hasPermission(SecurityUser user, Operation operation, UserId userId, User userEntity) { public boolean hasPermission(SecurityUser user, Operation operation, UserId userId, User userEntity) {
@ -122,9 +122,12 @@ public class CustomerUserPremissions extends AbstractPermissions {
if (!super.hasPermission(user, operation, entityId, entity)) { if (!super.hasPermission(user, operation, entityId, entity)) {
return false; return false;
} }
if (entity.getTenantId() == null || entity.getTenantId().isNullUid() || user.getTenantId().equals(entity.getTenantId())) { if (entity.getTenantId() == null || entity.getTenantId().isNullUid()) {
return true; return true;
} }
if (!user.getTenantId().equals(entity.getTenantId())) {
return false;
}
return true; return true;
} }

View File

@ -56,23 +56,15 @@ public class DefaultAccessControlService implements AccessControlService {
} }
@Override @Override
public void checkPermission(SecurityUser user, TenantId tenantId, Resource resource, Operation operation) throws ThingsboardException { public void checkPermission(SecurityUser user, Resource resource, Operation operation) throws ThingsboardException {
PermissionChecker permissionChecker = getPermissionChecker(user.getAuthority(), resource); PermissionChecker permissionChecker = getPermissionChecker(user.getAuthority(), resource);
if (!permissionChecker.hasPermission(user, tenantId, operation)) { if (!permissionChecker.hasPermission(user, operation)) {
permissionDenied(); permissionDenied();
} }
} }
@Override @Override
public void checkPermission(SecurityUser user, TenantId tenantId, Resource resource, Operation operation, EntityId entityId) throws ThingsboardException { public <I extends EntityId, T extends HasTenantId> void checkPermission(SecurityUser user, Resource resource,
PermissionChecker permissionChecker = getPermissionChecker(user.getAuthority(), resource);
if (!permissionChecker.hasPermission(user, tenantId, operation, entityId)) {
permissionDenied();
}
}
@Override
public <T extends HasTenantId, I extends EntityId> void checkPermission(SecurityUser user, Resource resource,
Operation operation, I entityId, T entity) throws ThingsboardException { Operation operation, I entityId, T entity) throws ThingsboardException {
PermissionChecker permissionChecker = getPermissionChecker(user.getAuthority(), resource); PermissionChecker permissionChecker = getPermissionChecker(user.getAuthority(), resource);
if (!permissionChecker.hasPermission(user, operation, entityId, entity)) { if (!permissionChecker.hasPermission(user, operation, entityId, entity)) {

View File

@ -25,13 +25,9 @@ import java.util.Arrays;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
public interface PermissionChecker<T extends HasTenantId, I extends EntityId> { public interface PermissionChecker<I extends EntityId, T extends HasTenantId> {
default boolean hasPermission(SecurityUser user, TenantId tenantId, Operation operation) { default boolean hasPermission(SecurityUser user, Operation operation) {
return false;
}
default boolean hasPermission(SecurityUser user, TenantId tenantId, Operation operation, EntityId entityId) {
return false; return false;
} }
@ -39,7 +35,7 @@ public interface PermissionChecker<T extends HasTenantId, I extends EntityId> {
return false; return false;
} }
public class GenericPermissionChecker<T extends HasTenantId, I extends EntityId> implements PermissionChecker<T, I> { public class GenericPermissionChecker<I extends EntityId, T extends HasTenantId> implements PermissionChecker<I,T> {
private final Set<Operation> allowedOperations; private final Set<Operation> allowedOperations;
@ -48,12 +44,7 @@ public interface PermissionChecker<T extends HasTenantId, I extends EntityId> {
} }
@Override @Override
public boolean hasPermission(SecurityUser user, TenantId tenantId, Operation operation) { public boolean hasPermission(SecurityUser user, Operation operation) {
return allowedOperations.contains(Operation.ALL) || allowedOperations.contains(operation);
}
@Override
public boolean hasPermission(SecurityUser user, TenantId tenantId, Operation operation, EntityId entityId) {
return allowedOperations.contains(Operation.ALL) || allowedOperations.contains(operation); return allowedOperations.contains(Operation.ALL) || allowedOperations.contains(operation);
} }
@ -65,15 +56,10 @@ public interface PermissionChecker<T extends HasTenantId, I extends EntityId> {
public static PermissionChecker denyAllPermissionChecker = new PermissionChecker() {}; public static PermissionChecker denyAllPermissionChecker = new PermissionChecker() {};
public static PermissionChecker allowAllPermissionChecker = new PermissionChecker<HasTenantId, EntityId>() { public static PermissionChecker allowAllPermissionChecker = new PermissionChecker<EntityId, HasTenantId>() {
@Override @Override
public boolean hasPermission(SecurityUser user, TenantId tenantId, Operation operation) { public boolean hasPermission(SecurityUser user, Operation operation) {
return true;
}
@Override
public boolean hasPermission(SecurityUser user, TenantId tenantId, Operation operation, EntityId entityId) {
return true; return true;
} }

View File

@ -41,15 +41,7 @@ public class SysAdminPermissions extends AbstractPermissions {
put(Resource.WIDGET_TYPE, systemEntityPermissionChecker); put(Resource.WIDGET_TYPE, systemEntityPermissionChecker);
} }
private static final PermissionChecker systemEntityPermissionChecker = new PermissionChecker<HasTenantId, EntityId>() { private static final PermissionChecker systemEntityPermissionChecker = new PermissionChecker() {
@Override
public boolean hasPermission(SecurityUser user, TenantId tenantId, Operation operation, EntityId entityId) {
if (tenantId != null && !tenantId.isNullUid()) {
return false;
}
return true;
}
@Override @Override
public boolean hasPermission(SecurityUser user, Operation operation, EntityId entityId, HasTenantId entity) { public boolean hasPermission(SecurityUser user, Operation operation, EntityId entityId, HasTenantId entity) {
@ -61,7 +53,7 @@ public class SysAdminPermissions extends AbstractPermissions {
} }
}; };
private static final PermissionChecker userPermissionChecker = new PermissionChecker<User, UserId>() { private static final PermissionChecker userPermissionChecker = new PermissionChecker<UserId, User>() {
@Override @Override
public boolean hasPermission(SecurityUser user, Operation operation, UserId userId, User userEntity) { public boolean hasPermission(SecurityUser user, Operation operation, UserId userId, User userEntity) {

View File

@ -44,15 +44,7 @@ public class TenantAdminPermissions extends AbstractPermissions {
put(Resource.WIDGET_TYPE, widgetsPermissionChecker); put(Resource.WIDGET_TYPE, widgetsPermissionChecker);
} }
public static final PermissionChecker tenantEntityPermissionChecker = new PermissionChecker<HasTenantId, EntityId>() { public static final PermissionChecker tenantEntityPermissionChecker = new PermissionChecker() {
@Override
public boolean hasPermission(SecurityUser user, TenantId tenantId, Operation operation, EntityId entityId) {
if (!user.getTenantId().equals(tenantId)) {
return false;
}
return true;
}
@Override @Override
public boolean hasPermission(SecurityUser user, Operation operation, EntityId entityId, HasTenantId entity) { public boolean hasPermission(SecurityUser user, Operation operation, EntityId entityId, HasTenantId entity) {
@ -64,12 +56,12 @@ public class TenantAdminPermissions extends AbstractPermissions {
} }
}; };
public static final PermissionChecker tenantPermissionChecker = private static final PermissionChecker tenantPermissionChecker =
new PermissionChecker.GenericPermissionChecker(Operation.READ) { new PermissionChecker.GenericPermissionChecker(Operation.READ, Operation.READ_ATTRIBUTES, Operation.READ_TELEMETRY) {
@Override @Override
public boolean hasPermission(SecurityUser user, TenantId tenantId, Operation operation, EntityId entityId) { public boolean hasPermission(SecurityUser user, Operation operation, EntityId entityId, HasTenantId entity) {
if (!super.hasPermission(user, tenantId, operation, entityId)) { if (!super.hasPermission(user, operation, entityId, entity)) {
return false; return false;
} }
if (!user.getTenantId().equals(entityId)) { if (!user.getTenantId().equals(entityId)) {
@ -80,7 +72,7 @@ public class TenantAdminPermissions extends AbstractPermissions {
}; };
private static final PermissionChecker userPermissionChecker = new PermissionChecker<User, UserId>() { private static final PermissionChecker userPermissionChecker = new PermissionChecker<UserId, User>() {
@Override @Override
public boolean hasPermission(SecurityUser user, Operation operation, UserId userId, User userEntity) { public boolean hasPermission(SecurityUser user, Operation operation, UserId userId, User userEntity) {
@ -95,7 +87,7 @@ public class TenantAdminPermissions extends AbstractPermissions {
}; };
private static final PermissionChecker widgetsPermissionChecker = new PermissionChecker<HasTenantId, EntityId>() { private static final PermissionChecker widgetsPermissionChecker = new PermissionChecker() {
@Override @Override
public boolean hasPermission(SecurityUser user, Operation operation, EntityId entityId, HasTenantId entity) { public boolean hasPermission(SecurityUser user, Operation operation, EntityId entityId, HasTenantId entity) {

View File

@ -15,6 +15,7 @@
*/ */
package org.thingsboard.server.common.data; package org.thingsboard.server.common.data;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
@ -22,7 +23,7 @@ import org.thingsboard.server.common.data.id.TenantId;
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.JsonNode;
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
public class Tenant extends ContactBased<TenantId> implements HasName { public class Tenant extends ContactBased<TenantId> implements HasName, HasTenantId {
private static final long serialVersionUID = 8057243243859922101L; private static final long serialVersionUID = 8057243243859922101L;
@ -51,6 +52,12 @@ public class Tenant extends ContactBased<TenantId> implements HasName {
this.title = title; this.title = title;
} }
@Override
@JsonIgnore
public TenantId getTenantId() {
return getId();
}
@Override @Override
@JsonProperty(access = JsonProperty.Access.READ_ONLY) @JsonProperty(access = JsonProperty.Access.READ_ONLY)
public String getName() { public String getName() {