From c4bec5d9932ff9969f84e7260d36dc0869b4865f Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Tue, 4 Dec 2018 20:57:26 +0200 Subject: [PATCH] Access Control - initial refactoring. --- .../server/controller/AdminController.java | 5 + .../server/controller/AlarmController.java | 12 +- .../server/controller/AssetController.java | 36 ++--- .../server/controller/BaseController.java | 79 ++++++----- .../server/controller/CustomerController.java | 14 +- .../controller/DashboardController.java | 34 +++-- .../server/controller/DeviceController.java | 38 +++--- .../controller/EntityViewController.java | 25 ++-- .../server/controller/EventController.java | 25 ++-- .../service/security/AccessValidator.java | 127 +++++++++--------- .../permission/AccessControlService.java | 2 +- .../permission/CustomerUserPremissions.java | 86 ++++++++++++ .../DefaultAccessControlService.java | 95 +++++++++++++ .../security/permission/Operation.java | 2 +- .../permission/PermissionChecker.java | 72 ++++++++++ .../service/security/permission/Resource.java | 10 +- .../permission/SysAdminPermissions.java | 39 ++++++ .../permission/TenantAdminPermissions.java | 59 ++++++++ .../server/common/data/DashboardInfo.java | 2 +- 19 files changed, 586 insertions(+), 176 deletions(-) create mode 100644 application/src/main/java/org/thingsboard/server/service/security/permission/CustomerUserPremissions.java create mode 100644 application/src/main/java/org/thingsboard/server/service/security/permission/DefaultAccessControlService.java create mode 100644 application/src/main/java/org/thingsboard/server/service/security/permission/PermissionChecker.java create mode 100644 application/src/main/java/org/thingsboard/server/service/security/permission/SysAdminPermissions.java create mode 100644 application/src/main/java/org/thingsboard/server/service/security/permission/TenantAdminPermissions.java diff --git a/application/src/main/java/org/thingsboard/server/controller/AdminController.java b/application/src/main/java/org/thingsboard/server/controller/AdminController.java index 8c59c86d6f..b7b6f0c5bf 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AdminController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AdminController.java @@ -28,6 +28,8 @@ import org.thingsboard.server.common.data.AdminSettings; import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.dao.settings.AdminSettingsService; +import org.thingsboard.server.service.security.permission.Operation; +import org.thingsboard.server.service.security.permission.Resource; import org.thingsboard.server.service.update.UpdateService; import org.thingsboard.server.service.update.model.UpdateMessage; @@ -49,6 +51,7 @@ public class AdminController extends BaseController { @ResponseBody public AdminSettings getAdminSettings(@PathVariable("key") String key) throws ThingsboardException { try { + accessControlService.checkPermission(getCurrentUser(), TenantId.SYS_TENANT_ID, Resource.ADMIN_SETTINGS, Operation.READ); return checkNotNull(adminSettingsService.findAdminSettingsByKey(TenantId.SYS_TENANT_ID, key)); } catch (Exception e) { throw handleException(e); @@ -60,6 +63,7 @@ public class AdminController extends BaseController { @ResponseBody public AdminSettings saveAdminSettings(@RequestBody AdminSettings adminSettings) throws ThingsboardException { try { + accessControlService.checkPermission(getCurrentUser(), TenantId.SYS_TENANT_ID, Resource.ADMIN_SETTINGS, Operation.WRITE); adminSettings = checkNotNull(adminSettingsService.saveAdminSettings(TenantId.SYS_TENANT_ID, adminSettings)); if (adminSettings.getKey().equals("mail")) { mailService.updateMailConfiguration(); @@ -74,6 +78,7 @@ public class AdminController extends BaseController { @RequestMapping(value = "/settings/testMail", method = RequestMethod.POST) public void sendTestMail(@RequestBody AdminSettings adminSettings) throws ThingsboardException { try { + accessControlService.checkPermission(getCurrentUser(), TenantId.SYS_TENANT_ID, Resource.ADMIN_SETTINGS, Operation.READ); adminSettings = checkNotNull(adminSettings); if (adminSettings.getKey().equals("mail")) { String email = getCurrentUser().getEmail(); diff --git a/application/src/main/java/org/thingsboard/server/controller/AlarmController.java b/application/src/main/java/org/thingsboard/server/controller/AlarmController.java index 6261e746aa..16ba5a5c3f 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AlarmController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AlarmController.java @@ -41,6 +41,8 @@ import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.EntityIdFactory; import org.thingsboard.server.common.data.page.TimePageData; import org.thingsboard.server.common.data.page.TimePageLink; +import org.thingsboard.server.service.security.permission.Operation; +import org.thingsboard.server.service.security.permission.Resource; @RestController @RequestMapping("/api") @@ -55,7 +57,7 @@ public class AlarmController extends BaseController { checkParameter(ALARM_ID, strAlarmId); try { AlarmId alarmId = new AlarmId(toUUID(strAlarmId)); - return checkAlarmId(alarmId); + return checkAlarmId(alarmId, Operation.READ); } catch (Exception e) { throw handleException(e); } @@ -68,7 +70,7 @@ public class AlarmController extends BaseController { checkParameter(ALARM_ID, strAlarmId); try { AlarmId alarmId = new AlarmId(toUUID(strAlarmId)); - return checkAlarmInfoId(alarmId); + return checkAlarmInfoId(alarmId, Operation.READ); } catch (Exception e) { throw handleException(e); } @@ -80,6 +82,8 @@ public class AlarmController extends BaseController { public Alarm saveAlarm(@RequestBody Alarm alarm) throws ThingsboardException { try { alarm.setTenantId(getCurrentUser().getTenantId()); + Operation operation = alarm.getId() == null ? Operation.CREATE : Operation.WRITE; + accessControlService.checkPermission(getCurrentUser(), Resource.ALARM, operation, alarm.getId(), alarm); Alarm savedAlarm = checkNotNull(alarmService.createOrUpdateAlarm(alarm)); logEntityAction(savedAlarm.getId(), savedAlarm, getCurrentUser().getCustomerId(), @@ -99,7 +103,7 @@ public class AlarmController extends BaseController { checkParameter(ALARM_ID, strAlarmId); try { AlarmId alarmId = new AlarmId(toUUID(strAlarmId)); - Alarm alarm = checkAlarmId(alarmId); + Alarm alarm = checkAlarmId(alarmId, Operation.WRITE); alarmService.ackAlarm(getCurrentUser().getTenantId(), alarmId, System.currentTimeMillis()).get(); logEntityAction(alarmId, alarm, getCurrentUser().getCustomerId(), ActionType.ALARM_ACK, null); } catch (Exception e) { @@ -114,7 +118,7 @@ public class AlarmController extends BaseController { checkParameter(ALARM_ID, strAlarmId); try { AlarmId alarmId = new AlarmId(toUUID(strAlarmId)); - Alarm alarm = checkAlarmId(alarmId); + Alarm alarm = checkAlarmId(alarmId, Operation.WRITE); alarmService.clearAlarm(getCurrentUser().getTenantId(), alarmId, null, System.currentTimeMillis()).get(); logEntityAction(alarmId, alarm, getCurrentUser().getCustomerId(), ActionType.ALARM_CLEAR, null); } catch (Exception e) { diff --git a/application/src/main/java/org/thingsboard/server/controller/AssetController.java b/application/src/main/java/org/thingsboard/server/controller/AssetController.java index 0df7e6b92c..55e087b0b2 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AssetController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AssetController.java @@ -43,6 +43,8 @@ import org.thingsboard.server.common.data.security.Authority; import org.thingsboard.server.dao.exception.IncorrectParameterException; import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.service.security.model.SecurityUser; +import org.thingsboard.server.service.security.permission.Operation; +import org.thingsboard.server.service.security.permission.Resource; import java.util.ArrayList; import java.util.List; @@ -61,7 +63,7 @@ public class AssetController extends BaseController { checkParameter(ASSET_ID, strAssetId); try { AssetId assetId = new AssetId(toUUID(strAssetId)); - return checkAssetId(assetId); + return checkAssetId(assetId, Operation.READ); } catch (Exception e) { throw handleException(e); } @@ -73,15 +75,12 @@ public class AssetController extends BaseController { public Asset saveAsset(@RequestBody Asset asset) throws ThingsboardException { try { asset.setTenantId(getCurrentUser().getTenantId()); - if (getCurrentUser().getAuthority() == Authority.CUSTOMER_USER) { - if (asset.getId() == null || asset.getId().isNullUid() || - asset.getCustomerId() == null || asset.getCustomerId().isNullUid()) { - throw new ThingsboardException("You don't have permission to perform this operation!", - ThingsboardErrorCode.PERMISSION_DENIED); - } else { - checkCustomerId(asset.getCustomerId()); - } - } + + Operation operation = asset.getId() == null ? Operation.CREATE : Operation.WRITE; + + accessControlService.checkPermission(getCurrentUser(), Resource.ASSET, operation, + asset.getId(), asset); + Asset savedAsset = checkNotNull(assetService.saveAsset(asset)); logEntityAction(savedAsset.getId(), savedAsset, @@ -103,7 +102,7 @@ public class AssetController extends BaseController { checkParameter(ASSET_ID, strAssetId); try { AssetId assetId = new AssetId(toUUID(strAssetId)); - Asset asset = checkAssetId(assetId); + Asset asset = checkAssetId(assetId, Operation.DELETE); assetService.deleteAsset(getTenantId(), assetId); logEntityAction(assetId, asset, @@ -128,10 +127,10 @@ public class AssetController extends BaseController { checkParameter(ASSET_ID, strAssetId); try { CustomerId customerId = new CustomerId(toUUID(strCustomerId)); - Customer customer = checkCustomerId(customerId); + Customer customer = checkCustomerId(customerId, Operation.READ); AssetId assetId = new AssetId(toUUID(strAssetId)); - checkAssetId(assetId); + checkAssetId(assetId, Operation.ASSIGN_TO_CUSTOMER); Asset savedAsset = checkNotNull(assetService.assignAssetToCustomer(getTenantId(), assetId, customerId)); @@ -157,12 +156,12 @@ public class AssetController extends BaseController { checkParameter(ASSET_ID, strAssetId); try { AssetId assetId = new AssetId(toUUID(strAssetId)); - Asset asset = checkAssetId(assetId); + Asset asset = checkAssetId(assetId, Operation.UNASSIGN_FROM_CUSTOMER); if (asset.getCustomerId() == null || asset.getCustomerId().getId().equals(ModelConstants.NULL_UUID)) { throw new IncorrectParameterException("Asset isn't assigned to any customer!"); } - Customer customer = checkCustomerId(asset.getCustomerId()); + Customer customer = checkCustomerId(asset.getCustomerId(), Operation.READ); Asset savedAsset = checkNotNull(assetService.unassignAssetFromCustomer(getTenantId(), assetId)); @@ -188,7 +187,7 @@ public class AssetController extends BaseController { checkParameter(ASSET_ID, strAssetId); try { AssetId assetId = new AssetId(toUUID(strAssetId)); - Asset asset = checkAssetId(assetId); + Asset asset = checkAssetId(assetId, Operation.ASSIGN_TO_CUSTOMER); Customer publicCustomer = customerService.findOrCreatePublicCustomer(asset.getTenantId()); Asset savedAsset = checkNotNull(assetService.assignAssetToCustomer(getTenantId(), assetId, publicCustomer.getId())); @@ -256,7 +255,7 @@ public class AssetController extends BaseController { try { TenantId tenantId = getCurrentUser().getTenantId(); CustomerId customerId = new CustomerId(toUUID(strCustomerId)); - checkCustomerId(customerId); + checkCustomerId(customerId, Operation.READ); TextPageLink pageLink = createPageLink(limit, textSearch, idOffset, textOffset); if (type != null && type.trim().length()>0) { return checkNotNull(assetService.findAssetsByTenantIdAndCustomerIdAndType(tenantId, customerId, type, pageLink)); @@ -306,7 +305,8 @@ public class AssetController extends BaseController { List assets = checkNotNull(assetService.findAssetsByQuery(getTenantId(), query).get()); assets = assets.stream().filter(asset -> { try { - checkAsset(asset); + //checkAsset(asset); + accessControlService.checkPermission(getCurrentUser(), Resource.ASSET, Operation.READ, asset.getId(), asset); return true; } catch (ThingsboardException e) { return false; diff --git a/application/src/main/java/org/thingsboard/server/controller/BaseController.java b/application/src/main/java/org/thingsboard/server/controller/BaseController.java index f947e6dde1..1888cfffe4 100644 --- a/application/src/main/java/org/thingsboard/server/controller/BaseController.java +++ b/application/src/main/java/org/thingsboard/server/controller/BaseController.java @@ -272,18 +272,22 @@ public abstract class BaseController { return getCurrentUser().getTenantId(); } - Customer checkCustomerId(CustomerId customerId) throws ThingsboardException { + Customer checkCustomerId(CustomerId customerId, Operation operation) throws ThingsboardException { try { - SecurityUser authUser = getCurrentUser(); + /*SecurityUser authUser = getCurrentUser(); if (authUser.getAuthority() == Authority.SYS_ADMIN || (authUser.getAuthority() != Authority.TENANT_ADMIN && (authUser.getCustomerId() == null || !authUser.getCustomerId().equals(customerId)))) { throw new ThingsboardException(YOU_DON_T_HAVE_PERMISSION_TO_PERFORM_THIS_OPERATION, ThingsboardErrorCode.PERMISSION_DENIED); - } + }*/ + accessControlService.checkPermission(getCurrentUser(), getCurrentUser().getTenantId(), Resource.CUSTOMER, operation, customerId); + if (customerId != null && !customerId.isNullUid()) { - Customer customer = customerService.findCustomerById(authUser.getTenantId(), customerId); - checkCustomer(customer); + Customer customer = customerService.findCustomerById(getTenantId(), customerId); + checkNotNull(customer); + //checkCustomer(customer); + accessControlService.checkPermission(getCurrentUser(), Resource.CUSTOMER, operation, customerId, customer); return customer; } else { return null; @@ -293,10 +297,10 @@ public abstract class BaseController { } } - private void checkCustomer(Customer customer) throws ThingsboardException { + /*private void checkCustomer(Customer customer) throws ThingsboardException { checkNotNull(customer); checkTenantId(customer.getTenantId()); - } + }*/ User checkUserId(UserId userId) throws ThingsboardException { try { @@ -355,84 +359,93 @@ public abstract class BaseController { } } - Device checkDeviceId(DeviceId deviceId) throws ThingsboardException { + Device checkDeviceId(DeviceId deviceId, Operation operation) throws ThingsboardException { try { validateId(deviceId, "Incorrect deviceId " + deviceId); Device device = deviceService.findDeviceById(getCurrentUser().getTenantId(), deviceId); + checkNotNull(device); // checkDevice(device); - accessControlService.checkPermission(getCurrentUser(), Resource.DEVICE, Operation.READ, deviceId, device); + accessControlService.checkPermission(getCurrentUser(), Resource.DEVICE, operation, deviceId, device); return device; } catch (Exception e) { throw handleException(e, false); } } - protected void checkDevice(Device device) throws ThingsboardException { + /*protected void checkDevice(Device device) throws ThingsboardException { checkNotNull(device); checkTenantId(device.getTenantId()); checkCustomerId(device.getCustomerId()); - } + }*/ - protected EntityView checkEntityViewId(EntityViewId entityViewId) throws ThingsboardException { + protected EntityView checkEntityViewId(EntityViewId entityViewId, Operation operation) throws ThingsboardException { try { validateId(entityViewId, "Incorrect entityViewId " + entityViewId); EntityView entityView = entityViewService.findEntityViewById(getCurrentUser().getTenantId(), entityViewId); - checkEntityView(entityView); + checkNotNull(entityView); + //checkEntityView(entityView); + accessControlService.checkPermission(getCurrentUser(), Resource.ENTITY_VIEW, operation, entityViewId, entityView); return entityView; } catch (Exception e) { throw handleException(e, false); } } - protected void checkEntityView(EntityView entityView) throws ThingsboardException { +/* protected void checkEntityView(EntityView entityView) throws ThingsboardException { checkNotNull(entityView); checkTenantId(entityView.getTenantId()); checkCustomerId(entityView.getCustomerId()); - } + }*/ - Asset checkAssetId(AssetId assetId) throws ThingsboardException { + Asset checkAssetId(AssetId assetId, Operation operation) throws ThingsboardException { try { validateId(assetId, "Incorrect assetId " + assetId); Asset asset = assetService.findAssetById(getCurrentUser().getTenantId(), assetId); - checkAsset(asset); + checkNotNull(asset); + accessControlService.checkPermission(getCurrentUser(), Resource.ASSET, operation, assetId, asset); + //checkAsset(asset); return asset; } catch (Exception e) { throw handleException(e, false); } } - protected void checkAsset(Asset asset) throws ThingsboardException { + /*protected void checkAsset(Asset asset) throws ThingsboardException { checkNotNull(asset); checkTenantId(asset.getTenantId()); checkCustomerId(asset.getCustomerId()); - } + }*/ - Alarm checkAlarmId(AlarmId alarmId) throws ThingsboardException { + Alarm checkAlarmId(AlarmId alarmId, Operation operation) throws ThingsboardException { try { validateId(alarmId, "Incorrect alarmId " + alarmId); Alarm alarm = alarmService.findAlarmByIdAsync(getCurrentUser().getTenantId(), alarmId).get(); - checkAlarm(alarm); + checkNotNull(alarm); + accessControlService.checkPermission(getCurrentUser(), Resource.ALARM, operation, alarmId, alarm); + //checkAlarm(alarm); return alarm; } catch (Exception e) { throw handleException(e, false); } } - AlarmInfo checkAlarmInfoId(AlarmId alarmId) throws ThingsboardException { + AlarmInfo checkAlarmInfoId(AlarmId alarmId, Operation operation) throws ThingsboardException { try { validateId(alarmId, "Incorrect alarmId " + alarmId); AlarmInfo alarmInfo = alarmService.findAlarmInfoByIdAsync(getCurrentUser().getTenantId(), alarmId).get(); - checkAlarm(alarmInfo); + checkNotNull(alarmInfo); + accessControlService.checkPermission(getCurrentUser(), Resource.ALARM, operation, alarmId, alarmInfo); + //checkAlarm(alarmInfo); return alarmInfo; } catch (Exception e) { throw handleException(e, false); } } - protected void checkAlarm(Alarm alarm) throws ThingsboardException { + /* protected void checkAlarm(Alarm alarm) throws ThingsboardException { checkNotNull(alarm); checkTenantId(alarm.getTenantId()); - } + }*/ WidgetsBundle checkWidgetsBundleId(WidgetsBundleId widgetsBundleId, boolean modify) throws ThingsboardException { try { @@ -476,29 +489,33 @@ public abstract class BaseController { } } - Dashboard checkDashboardId(DashboardId dashboardId) throws ThingsboardException { + Dashboard checkDashboardId(DashboardId dashboardId, Operation operation) throws ThingsboardException { try { validateId(dashboardId, "Incorrect dashboardId " + dashboardId); Dashboard dashboard = dashboardService.findDashboardById(getCurrentUser().getTenantId(), dashboardId); - checkDashboard(dashboard); + checkNotNull(dashboard); + accessControlService.checkPermission(getCurrentUser(), Resource.DASHBOARD, operation, dashboardId, dashboard); + //checkDashboard(dashboard); return dashboard; } catch (Exception e) { throw handleException(e, false); } } - DashboardInfo checkDashboardInfoId(DashboardId dashboardId) throws ThingsboardException { + DashboardInfo checkDashboardInfoId(DashboardId dashboardId, Operation operation) throws ThingsboardException { try { validateId(dashboardId, "Incorrect dashboardId " + dashboardId); DashboardInfo dashboardInfo = dashboardService.findDashboardInfoById(getCurrentUser().getTenantId(), dashboardId); - checkDashboard(dashboardInfo); + checkNotNull(dashboardInfo); + accessControlService.checkPermission(getCurrentUser(), Resource.DASHBOARD, operation, dashboardId, dashboardInfo); + //checkDashboard(dashboardInfo); return dashboardInfo; } catch (Exception e) { throw handleException(e, false); } } - private void checkDashboard(DashboardInfo dashboard) throws ThingsboardException { + /*private void checkDashboard(DashboardInfo dashboard) throws ThingsboardException { checkNotNull(dashboard); checkTenantId(dashboard.getTenantId()); SecurityUser authUser = getCurrentUser(); @@ -508,7 +525,7 @@ public abstract class BaseController { ThingsboardErrorCode.PERMISSION_DENIED); } } - } + }*/ ComponentDescriptor checkComponentDescriptorByClazz(String clazz) throws ThingsboardException { try { diff --git a/application/src/main/java/org/thingsboard/server/controller/CustomerController.java b/application/src/main/java/org/thingsboard/server/controller/CustomerController.java index d42801dccd..dfb5d74ecc 100644 --- a/application/src/main/java/org/thingsboard/server/controller/CustomerController.java +++ b/application/src/main/java/org/thingsboard/server/controller/CustomerController.java @@ -36,6 +36,8 @@ import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.TextPageData; import org.thingsboard.server.common.data.page.TextPageLink; +import org.thingsboard.server.service.security.permission.Operation; +import org.thingsboard.server.service.security.permission.Resource; @RestController @RequestMapping("/api") @@ -51,7 +53,7 @@ public class CustomerController extends BaseController { checkParameter(CUSTOMER_ID, strCustomerId); try { CustomerId customerId = new CustomerId(toUUID(strCustomerId)); - return checkCustomerId(customerId); + return checkCustomerId(customerId, Operation.READ); } catch (Exception e) { throw handleException(e); } @@ -64,7 +66,7 @@ public class CustomerController extends BaseController { checkParameter(CUSTOMER_ID, strCustomerId); try { CustomerId customerId = new CustomerId(toUUID(strCustomerId)); - Customer customer = checkCustomerId(customerId); + Customer customer = checkCustomerId(customerId, Operation.READ); ObjectMapper objectMapper = new ObjectMapper(); ObjectNode infoObject = objectMapper.createObjectNode(); infoObject.put("title", customer.getTitle()); @@ -82,7 +84,7 @@ public class CustomerController extends BaseController { checkParameter(CUSTOMER_ID, strCustomerId); try { CustomerId customerId = new CustomerId(toUUID(strCustomerId)); - Customer customer = checkCustomerId(customerId); + Customer customer = checkCustomerId(customerId, Operation.READ); return customer.getTitle(); } catch (Exception e) { throw handleException(e); @@ -95,6 +97,10 @@ public class CustomerController extends BaseController { public Customer saveCustomer(@RequestBody Customer customer) throws ThingsboardException { try { customer.setTenantId(getCurrentUser().getTenantId()); + + Operation operation = customer.getId() == null ? Operation.CREATE : Operation.WRITE; + accessControlService.checkPermission(getCurrentUser(), Resource.CUSTOMER, operation, customer.getId(), customer); + Customer savedCustomer = checkNotNull(customerService.saveCustomer(customer)); logEntityAction(savedCustomer.getId(), savedCustomer, @@ -118,7 +124,7 @@ public class CustomerController extends BaseController { checkParameter(CUSTOMER_ID, strCustomerId); try { CustomerId customerId = new CustomerId(toUUID(strCustomerId)); - Customer customer = checkCustomerId(customerId); + Customer customer = checkCustomerId(customerId, Operation.DELETE); customerService.deleteCustomer(getTenantId(), customerId); logEntityAction(customerId, customer, diff --git a/application/src/main/java/org/thingsboard/server/controller/DashboardController.java b/application/src/main/java/org/thingsboard/server/controller/DashboardController.java index 9f32a8b7f0..033c2a2534 100644 --- a/application/src/main/java/org/thingsboard/server/controller/DashboardController.java +++ b/application/src/main/java/org/thingsboard/server/controller/DashboardController.java @@ -41,6 +41,8 @@ import org.thingsboard.server.common.data.page.TextPageData; import org.thingsboard.server.common.data.page.TextPageLink; import org.thingsboard.server.common.data.page.TimePageData; import org.thingsboard.server.common.data.page.TimePageLink; +import org.thingsboard.server.service.security.permission.Operation; +import org.thingsboard.server.service.security.permission.Resource; import java.util.HashSet; import java.util.Set; @@ -76,7 +78,7 @@ public class DashboardController extends BaseController { checkParameter(DASHBOARD_ID, strDashboardId); try { DashboardId dashboardId = new DashboardId(toUUID(strDashboardId)); - return checkDashboardInfoId(dashboardId); + return checkDashboardInfoId(dashboardId, Operation.READ); } catch (Exception e) { throw handleException(e); } @@ -89,7 +91,7 @@ public class DashboardController extends BaseController { checkParameter(DASHBOARD_ID, strDashboardId); try { DashboardId dashboardId = new DashboardId(toUUID(strDashboardId)); - return checkDashboardId(dashboardId); + return checkDashboardId(dashboardId, Operation.READ); } catch (Exception e) { throw handleException(e); } @@ -101,6 +103,12 @@ public class DashboardController extends BaseController { public Dashboard saveDashboard(@RequestBody Dashboard dashboard) throws ThingsboardException { try { dashboard.setTenantId(getCurrentUser().getTenantId()); + + Operation operation = dashboard.getId() == null ? Operation.CREATE : Operation.WRITE; + + accessControlService.checkPermission(getCurrentUser(), Resource.DASHBOARD, operation, + dashboard.getId(), dashboard); + Dashboard savedDashboard = checkNotNull(dashboardService.saveDashboard(dashboard)); logEntityAction(savedDashboard.getId(), savedDashboard, @@ -123,7 +131,7 @@ public class DashboardController extends BaseController { checkParameter(DASHBOARD_ID, strDashboardId); try { DashboardId dashboardId = new DashboardId(toUUID(strDashboardId)); - Dashboard dashboard = checkDashboardId(dashboardId); + Dashboard dashboard = checkDashboardId(dashboardId, Operation.DELETE); dashboardService.deleteDashboard(getCurrentUser().getTenantId(), dashboardId); logEntityAction(dashboardId, dashboard, @@ -150,10 +158,10 @@ public class DashboardController extends BaseController { checkParameter(DASHBOARD_ID, strDashboardId); try { CustomerId customerId = new CustomerId(toUUID(strCustomerId)); - Customer customer = checkCustomerId(customerId); + Customer customer = checkCustomerId(customerId, Operation.READ); DashboardId dashboardId = new DashboardId(toUUID(strDashboardId)); - checkDashboardId(dashboardId); + checkDashboardId(dashboardId, Operation.ASSIGN_TO_CUSTOMER); Dashboard savedDashboard = checkNotNull(dashboardService.assignDashboardToCustomer(getCurrentUser().getTenantId(), dashboardId, customerId)); @@ -182,9 +190,9 @@ public class DashboardController extends BaseController { checkParameter(DASHBOARD_ID, strDashboardId); try { CustomerId customerId = new CustomerId(toUUID(strCustomerId)); - Customer customer = checkCustomerId(customerId); + Customer customer = checkCustomerId(customerId, Operation.READ); DashboardId dashboardId = new DashboardId(toUUID(strDashboardId)); - Dashboard dashboard = checkDashboardId(dashboardId); + Dashboard dashboard = checkDashboardId(dashboardId, Operation.UNASSIGN_FROM_CUSTOMER); Dashboard savedDashboard = checkNotNull(dashboardService.unassignDashboardFromCustomer(getCurrentUser().getTenantId(), dashboardId, customerId)); @@ -211,7 +219,7 @@ public class DashboardController extends BaseController { checkParameter(DASHBOARD_ID, strDashboardId); try { DashboardId dashboardId = new DashboardId(toUUID(strDashboardId)); - Dashboard dashboard = checkDashboardId(dashboardId); + Dashboard dashboard = checkDashboardId(dashboardId, Operation.ASSIGN_TO_CUSTOMER); Set customerIds = new HashSet<>(); if (strCustomerIds != null) { @@ -276,7 +284,7 @@ public class DashboardController extends BaseController { checkParameter(DASHBOARD_ID, strDashboardId); try { DashboardId dashboardId = new DashboardId(toUUID(strDashboardId)); - Dashboard dashboard = checkDashboardId(dashboardId); + Dashboard dashboard = checkDashboardId(dashboardId, Operation.ASSIGN_TO_CUSTOMER); Set customerIds = new HashSet<>(); if (strCustomerIds != null) { @@ -319,7 +327,7 @@ public class DashboardController extends BaseController { checkParameter(DASHBOARD_ID, strDashboardId); try { DashboardId dashboardId = new DashboardId(toUUID(strDashboardId)); - Dashboard dashboard = checkDashboardId(dashboardId); + Dashboard dashboard = checkDashboardId(dashboardId, Operation.UNASSIGN_FROM_CUSTOMER); Set customerIds = new HashSet<>(); if (strCustomerIds != null) { @@ -362,7 +370,7 @@ public class DashboardController extends BaseController { checkParameter(DASHBOARD_ID, strDashboardId); try { DashboardId dashboardId = new DashboardId(toUUID(strDashboardId)); - Dashboard dashboard = checkDashboardId(dashboardId); + Dashboard dashboard = checkDashboardId(dashboardId, Operation.ASSIGN_TO_CUSTOMER); Customer publicCustomer = customerService.findOrCreatePublicCustomer(dashboard.getTenantId()); Dashboard savedDashboard = checkNotNull(dashboardService.assignDashboardToCustomer(getCurrentUser().getTenantId(), dashboardId, publicCustomer.getId())); @@ -388,7 +396,7 @@ public class DashboardController extends BaseController { checkParameter(DASHBOARD_ID, strDashboardId); try { DashboardId dashboardId = new DashboardId(toUUID(strDashboardId)); - Dashboard dashboard = checkDashboardId(dashboardId); + Dashboard dashboard = checkDashboardId(dashboardId, Operation.UNASSIGN_FROM_CUSTOMER); Customer publicCustomer = customerService.findOrCreatePublicCustomer(dashboard.getTenantId()); Dashboard savedDashboard = checkNotNull(dashboardService.unassignDashboardFromCustomer(getCurrentUser().getTenantId(), dashboardId, publicCustomer.getId())); @@ -458,7 +466,7 @@ public class DashboardController extends BaseController { try { TenantId tenantId = getCurrentUser().getTenantId(); CustomerId customerId = new CustomerId(toUUID(strCustomerId)); - checkCustomerId(customerId); + checkCustomerId(customerId, Operation.READ); TimePageLink pageLink = createPageLink(limit, startTime, endTime, ascOrder, offset); return checkNotNull(dashboardService.findDashboardsByTenantIdAndCustomerId(tenantId, customerId, pageLink).get()); } catch (Exception e) { diff --git a/application/src/main/java/org/thingsboard/server/controller/DeviceController.java b/application/src/main/java/org/thingsboard/server/controller/DeviceController.java index 66fc180735..14c66afcff 100644 --- a/application/src/main/java/org/thingsboard/server/controller/DeviceController.java +++ b/application/src/main/java/org/thingsboard/server/controller/DeviceController.java @@ -64,7 +64,7 @@ public class DeviceController extends BaseController { checkParameter(DEVICE_ID, strDeviceId); try { DeviceId deviceId = new DeviceId(toUUID(strDeviceId)); - return checkDeviceId(deviceId); + return checkDeviceId(deviceId, Operation.READ); } catch (Exception e) { throw handleException(e); } @@ -76,15 +76,12 @@ public class DeviceController extends BaseController { public Device saveDevice(@RequestBody Device device) throws ThingsboardException { try { device.setTenantId(getCurrentUser().getTenantId()); - if (getCurrentUser().getAuthority() == Authority.CUSTOMER_USER) { - if (device.getId() == null || device.getId().isNullUid() || - device.getCustomerId() == null || device.getCustomerId().isNullUid()) { - throw new ThingsboardException("You don't have permission to perform this operation!", - ThingsboardErrorCode.PERMISSION_DENIED); - } else { - checkCustomerId(device.getCustomerId()); - } - } + + Operation operation = device.getId() == null ? Operation.CREATE : Operation.WRITE; + + accessControlService.checkPermission(getCurrentUser(), Resource.DEVICE, operation, + device.getId(), device); + Device savedDevice = checkNotNull(deviceService.saveDevice(device)); actorService @@ -118,7 +115,7 @@ public class DeviceController extends BaseController { checkParameter(DEVICE_ID, strDeviceId); try { DeviceId deviceId = new DeviceId(toUUID(strDeviceId)); - Device device = checkDeviceId(deviceId); + Device device = checkDeviceId(deviceId, Operation.DELETE); deviceService.deleteDevice(getCurrentUser().getTenantId(), deviceId); logEntityAction(deviceId, device, @@ -144,10 +141,10 @@ public class DeviceController extends BaseController { checkParameter(DEVICE_ID, strDeviceId); try { CustomerId customerId = new CustomerId(toUUID(strCustomerId)); - Customer customer = checkCustomerId(customerId); + Customer customer = checkCustomerId(customerId, Operation.READ); DeviceId deviceId = new DeviceId(toUUID(strDeviceId)); - checkDeviceId(deviceId); + checkDeviceId(deviceId, Operation.ASSIGN_TO_CUSTOMER); Device savedDevice = checkNotNull(deviceService.assignDeviceToCustomer(getCurrentUser().getTenantId(), deviceId, customerId)); @@ -171,11 +168,11 @@ public class DeviceController extends BaseController { checkParameter(DEVICE_ID, strDeviceId); try { DeviceId deviceId = new DeviceId(toUUID(strDeviceId)); - Device device = checkDeviceId(deviceId); + Device device = checkDeviceId(deviceId, Operation.UNASSIGN_FROM_CUSTOMER); if (device.getCustomerId() == null || device.getCustomerId().getId().equals(ModelConstants.NULL_UUID)) { throw new IncorrectParameterException("Device isn't assigned to any customer!"); } - Customer customer = checkCustomerId(device.getCustomerId()); + Customer customer = checkCustomerId(device.getCustomerId(), Operation.READ); Device savedDevice = checkNotNull(deviceService.unassignDeviceFromCustomer(getCurrentUser().getTenantId(), deviceId)); @@ -199,7 +196,7 @@ public class DeviceController extends BaseController { checkParameter(DEVICE_ID, strDeviceId); try { DeviceId deviceId = new DeviceId(toUUID(strDeviceId)); - Device device = checkDeviceId(deviceId); + Device device = checkDeviceId(deviceId, Operation.ASSIGN_TO_CUSTOMER); Customer publicCustomer = customerService.findOrCreatePublicCustomer(device.getTenantId()); Device savedDevice = checkNotNull(deviceService.assignDeviceToCustomer(getCurrentUser().getTenantId(), deviceId, publicCustomer.getId())); @@ -223,7 +220,7 @@ public class DeviceController extends BaseController { checkParameter(DEVICE_ID, strDeviceId); try { DeviceId deviceId = new DeviceId(toUUID(strDeviceId)); - Device device = checkDeviceId(deviceId); + Device device = checkDeviceId(deviceId, Operation.READ); DeviceCredentials deviceCredentials = checkNotNull(deviceCredentialsService.findDeviceCredentialsByDeviceId(getCurrentUser().getTenantId(), deviceId)); logEntityAction(deviceId, device, device.getCustomerId(), @@ -243,7 +240,7 @@ public class DeviceController extends BaseController { public DeviceCredentials saveDeviceCredentials(@RequestBody DeviceCredentials deviceCredentials) throws ThingsboardException { checkNotNull(deviceCredentials); try { - Device device = checkDeviceId(deviceCredentials.getDeviceId()); + Device device = checkDeviceId(deviceCredentials.getDeviceId(), Operation.WRITE); DeviceCredentials result = checkNotNull(deviceCredentialsService.updateDeviceCredentials(getCurrentUser().getTenantId(), deviceCredentials)); actorService.onCredentialsUpdate(getCurrentUser().getTenantId(), deviceCredentials.getDeviceId()); logEntityAction(device.getId(), device, @@ -307,7 +304,7 @@ public class DeviceController extends BaseController { try { TenantId tenantId = getCurrentUser().getTenantId(); CustomerId customerId = new CustomerId(toUUID(strCustomerId)); - checkCustomerId(customerId); + checkCustomerId(customerId, Operation.READ); TextPageLink pageLink = createPageLink(limit, textSearch, idOffset, textOffset); if (type != null && type.trim().length() > 0) { return checkNotNull(deviceService.findDevicesByTenantIdAndCustomerIdAndType(tenantId, customerId, type, pageLink)); @@ -357,7 +354,8 @@ public class DeviceController extends BaseController { List devices = checkNotNull(deviceService.findDevicesByQuery(getCurrentUser().getTenantId(), query).get()); devices = devices.stream().filter(device -> { try { - checkDevice(device); + //checkDevice(device); + accessControlService.checkPermission(getCurrentUser(), Resource.DEVICE, Operation.READ, device.getId(), device); return true; } catch (ThingsboardException e) { return false; diff --git a/application/src/main/java/org/thingsboard/server/controller/EntityViewController.java b/application/src/main/java/org/thingsboard/server/controller/EntityViewController.java index eef742e473..0ac0e85f75 100644 --- a/application/src/main/java/org/thingsboard/server/controller/EntityViewController.java +++ b/application/src/main/java/org/thingsboard/server/controller/EntityViewController.java @@ -48,6 +48,8 @@ import org.thingsboard.server.common.data.page.TextPageLink; import org.thingsboard.server.dao.exception.IncorrectParameterException; import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.service.security.model.SecurityUser; +import org.thingsboard.server.service.security.permission.Operation; +import org.thingsboard.server.service.security.permission.Resource; import javax.annotation.Nullable; import java.util.ArrayList; @@ -74,7 +76,7 @@ public class EntityViewController extends BaseController { public EntityView getEntityViewById(@PathVariable(ENTITY_VIEW_ID) String strEntityViewId) throws ThingsboardException { checkParameter(ENTITY_VIEW_ID, strEntityViewId); try { - return checkEntityViewId(new EntityViewId(toUUID(strEntityViewId))); + return checkEntityViewId(new EntityViewId(toUUID(strEntityViewId)), Operation.READ); } catch (Exception e) { throw handleException(e); } @@ -86,6 +88,12 @@ public class EntityViewController extends BaseController { public EntityView saveEntityView(@RequestBody EntityView entityView) throws ThingsboardException { try { entityView.setTenantId(getCurrentUser().getTenantId()); + + Operation operation = entityView.getId() == null ? Operation.CREATE : Operation.WRITE; + + accessControlService.checkPermission(getCurrentUser(), Resource.ENTITY_VIEW, operation, + entityView.getId(), entityView); + EntityView savedEntityView = checkNotNull(entityViewService.saveEntityView(entityView)); List>> futures = new ArrayList<>(); if (savedEntityView.getKeys() != null && savedEntityView.getKeys().getAttributes() != null) { @@ -168,7 +176,7 @@ public class EntityViewController extends BaseController { checkParameter(ENTITY_VIEW_ID, strEntityViewId); try { EntityViewId entityViewId = new EntityViewId(toUUID(strEntityViewId)); - EntityView entityView = checkEntityViewId(entityViewId); + EntityView entityView = checkEntityViewId(entityViewId, Operation.DELETE); entityViewService.deleteEntityView(getTenantId(), entityViewId); logEntityAction(entityViewId, entityView, entityView.getCustomerId(), ActionType.DELETED, null, strEntityViewId); @@ -203,10 +211,10 @@ public class EntityViewController extends BaseController { checkParameter(ENTITY_VIEW_ID, strEntityViewId); try { CustomerId customerId = new CustomerId(toUUID(strCustomerId)); - Customer customer = checkCustomerId(customerId); + Customer customer = checkCustomerId(customerId, Operation.READ); EntityViewId entityViewId = new EntityViewId(toUUID(strEntityViewId)); - checkEntityViewId(entityViewId); + checkEntityViewId(entityViewId, Operation.ASSIGN_TO_CUSTOMER); EntityView savedEntityView = checkNotNull(entityViewService.assignEntityViewToCustomer(getTenantId(), entityViewId, customerId)); logEntityAction(entityViewId, savedEntityView, @@ -228,11 +236,11 @@ public class EntityViewController extends BaseController { checkParameter(ENTITY_VIEW_ID, strEntityViewId); try { EntityViewId entityViewId = new EntityViewId(toUUID(strEntityViewId)); - EntityView entityView = checkEntityViewId(entityViewId); + EntityView entityView = checkEntityViewId(entityViewId, Operation.UNASSIGN_FROM_CUSTOMER); if (entityView.getCustomerId() == null || entityView.getCustomerId().getId().equals(ModelConstants.NULL_UUID)) { throw new IncorrectParameterException("Entity View isn't assigned to any customer!"); } - Customer customer = checkCustomerId(entityView.getCustomerId()); + Customer customer = checkCustomerId(entityView.getCustomerId(), Operation.READ); EntityView savedEntityView = checkNotNull(entityViewService.unassignEntityViewFromCustomer(getTenantId(), entityViewId)); logEntityAction(entityViewId, entityView, entityView.getCustomerId(), @@ -261,7 +269,7 @@ public class EntityViewController extends BaseController { try { TenantId tenantId = getCurrentUser().getTenantId(); CustomerId customerId = new CustomerId(toUUID(strCustomerId)); - checkCustomerId(customerId); + checkCustomerId(customerId, Operation.READ); TextPageLink pageLink = createPageLink(limit, textSearch, idOffset, textOffset); if (type != null && type.trim().length() > 0) { return checkNotNull(entityViewService.findEntityViewsByTenantIdAndCustomerIdAndType(tenantId, customerId, pageLink, type)); @@ -308,7 +316,8 @@ public class EntityViewController extends BaseController { List entityViews = checkNotNull(entityViewService.findEntityViewsByQuery(getTenantId(), query).get()); entityViews = entityViews.stream().filter(entityView -> { try { - checkEntityView(entityView); + //checkEntityView(entityView); + accessControlService.checkPermission(getCurrentUser(), Resource.ENTITY_VIEW, Operation.READ, entityView.getId(), entityView); return true; } catch (ThingsboardException e) { return false; diff --git a/application/src/main/java/org/thingsboard/server/controller/EventController.java b/application/src/main/java/org/thingsboard/server/controller/EventController.java index 7c8b2ae45e..66b01d31d4 100644 --- a/application/src/main/java/org/thingsboard/server/controller/EventController.java +++ b/application/src/main/java/org/thingsboard/server/controller/EventController.java @@ -26,12 +26,15 @@ import org.springframework.web.bind.annotation.RestController; import org.thingsboard.server.common.data.Event; import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; import org.thingsboard.server.common.data.exception.ThingsboardException; +import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.EntityIdFactory; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.TimePageData; import org.thingsboard.server.common.data.page.TimePageLink; import org.thingsboard.server.dao.event.EventService; import org.thingsboard.server.dao.model.ModelConstants; +import org.thingsboard.server.service.security.permission.Operation; +import org.thingsboard.server.service.security.permission.Resource; @RestController @RequestMapping("/api") @@ -58,13 +61,12 @@ public class EventController extends BaseController { checkParameter("EntityType", strEntityType); try { TenantId tenantId = new TenantId(toUUID(strTenantId)); - if (!tenantId.getId().equals(ModelConstants.NULL_UUID) && - !tenantId.equals(getCurrentUser().getTenantId())) { - throw new ThingsboardException("You don't have permission to perform this operation!", - ThingsboardErrorCode.PERMISSION_DENIED); - } + + EntityId entityId = EntityIdFactory.getByTypeAndId(strEntityType, strEntityId); + checkEntityId(entityId); + TimePageLink pageLink = createPageLink(limit, startTime, endTime, ascOrder, offset); - return checkNotNull(eventService.findEvents(tenantId, EntityIdFactory.getByTypeAndId(strEntityType, strEntityId), eventType, pageLink)); + return checkNotNull(eventService.findEvents(tenantId, entityId, eventType, pageLink)); } catch (Exception e) { throw handleException(e); } @@ -87,13 +89,12 @@ public class EventController extends BaseController { checkParameter("EntityType", strEntityType); try { TenantId tenantId = new TenantId(toUUID(strTenantId)); - if (!tenantId.getId().equals(ModelConstants.NULL_UUID) && - !tenantId.equals(getCurrentUser().getTenantId())) { - throw new ThingsboardException("You don't have permission to perform this operation!", - ThingsboardErrorCode.PERMISSION_DENIED); - } + + EntityId entityId = EntityIdFactory.getByTypeAndId(strEntityType, strEntityId); + checkEntityId(entityId); + TimePageLink pageLink = createPageLink(limit, startTime, endTime, ascOrder, offset); - return checkNotNull(eventService.findEvents(tenantId, EntityIdFactory.getByTypeAndId(strEntityType, strEntityId), pageLink)); + return checkNotNull(eventService.findEvents(tenantId, entityId, pageLink)); } catch (Exception e) { throw handleException(e); } diff --git a/application/src/main/java/org/thingsboard/server/service/security/AccessValidator.java b/application/src/main/java/org/thingsboard/server/service/security/AccessValidator.java index b482982b13..11c59df0db 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/AccessValidator.java +++ b/application/src/main/java/org/thingsboard/server/service/security/AccessValidator.java @@ -51,6 +51,9 @@ import org.thingsboard.server.dao.rule.RuleChainService; import org.thingsboard.server.dao.tenant.TenantService; import org.thingsboard.server.dao.user.UserService; import org.thingsboard.server.service.security.model.SecurityUser; +import org.thingsboard.server.service.security.permission.AccessControlService; +import org.thingsboard.server.service.security.permission.Operation; +import org.thingsboard.server.service.security.permission.Resource; import org.thingsboard.server.service.telemetry.exception.ToErrorResponseEntity; import javax.annotation.Nullable; @@ -95,6 +98,9 @@ public class AccessValidator { @Autowired protected EntityViewService entityViewService; + @Autowired + protected AccessControlService accessControlService; + private ExecutorService executor; @PostConstruct @@ -109,30 +115,30 @@ public class AccessValidator { } } - public DeferredResult validateEntityAndCallback(SecurityUser currentUser, String entityType, String entityIdStr, + public DeferredResult validateEntityAndCallback(SecurityUser currentUser, Operation operation, String entityType, String entityIdStr, ThreeConsumer, TenantId, EntityId> onSuccess) throws ThingsboardException { - return validateEntityAndCallback(currentUser, entityType, entityIdStr, onSuccess, (result, t) -> handleError(t, result, HttpStatus.INTERNAL_SERVER_ERROR)); + return validateEntityAndCallback(currentUser, operation, entityType, entityIdStr, onSuccess, (result, t) -> handleError(t, result, HttpStatus.INTERNAL_SERVER_ERROR)); } - public DeferredResult validateEntityAndCallback(SecurityUser currentUser, String entityType, String entityIdStr, + public DeferredResult validateEntityAndCallback(SecurityUser currentUser, Operation operation, String entityType, String entityIdStr, ThreeConsumer, TenantId, EntityId> onSuccess, BiConsumer, Throwable> onFailure) throws ThingsboardException { - return validateEntityAndCallback(currentUser, EntityIdFactory.getByTypeAndId(entityType, entityIdStr), + return validateEntityAndCallback(currentUser, operation, EntityIdFactory.getByTypeAndId(entityType, entityIdStr), onSuccess, onFailure); } - public DeferredResult validateEntityAndCallback(SecurityUser currentUser, EntityId entityId, + public DeferredResult validateEntityAndCallback(SecurityUser currentUser, Operation operation, EntityId entityId, ThreeConsumer, TenantId, EntityId> onSuccess) throws ThingsboardException { - return validateEntityAndCallback(currentUser, entityId, onSuccess, (result, t) -> handleError(t, result, HttpStatus.INTERNAL_SERVER_ERROR)); + return validateEntityAndCallback(currentUser, operation, entityId, onSuccess, (result, t) -> handleError(t, result, HttpStatus.INTERNAL_SERVER_ERROR)); } - public DeferredResult validateEntityAndCallback(SecurityUser currentUser, EntityId entityId, + public DeferredResult validateEntityAndCallback(SecurityUser currentUser, Operation operation, EntityId entityId, ThreeConsumer, TenantId, EntityId> onSuccess, BiConsumer, Throwable> onFailure) throws ThingsboardException { final DeferredResult response = new DeferredResult<>(); - validate(currentUser, entityId, new HttpValidationCallback(response, + validate(currentUser, operation, entityId, new HttpValidationCallback(response, new FutureCallback>() { @Override public void onSuccess(@Nullable DeferredResult result) { @@ -148,25 +154,25 @@ public class AccessValidator { return response; } - public void validate(SecurityUser currentUser, EntityId entityId, FutureCallback callback) { + public void validate(SecurityUser currentUser, Operation operation, EntityId entityId, FutureCallback callback) { switch (entityId.getEntityType()) { case DEVICE: - validateDevice(currentUser, entityId, callback); + validateDevice(currentUser, operation, entityId, callback); return; case ASSET: - validateAsset(currentUser, entityId, callback); + validateAsset(currentUser, operation, entityId, callback); return; case RULE_CHAIN: - validateRuleChain(currentUser, entityId, callback); + validateRuleChain(currentUser, operation, entityId, callback); return; case CUSTOMER: - validateCustomer(currentUser, entityId, callback); + validateCustomer(currentUser, operation, entityId, callback); return; case TENANT: - validateTenant(currentUser, entityId, callback); + validateTenant(currentUser, operation, entityId, callback); return; case ENTITY_VIEW: - validateEntityView(currentUser, entityId, callback); + validateEntityView(currentUser, operation, entityId, callback); return; default: //TODO: add support of other entities @@ -174,7 +180,7 @@ public class AccessValidator { } } - private void validateDevice(final SecurityUser currentUser, EntityId entityId, FutureCallback callback) { + private void validateDevice(final SecurityUser currentUser, Operation operation, EntityId entityId, FutureCallback callback) { if (currentUser.isSystemAdmin()) { callback.onSuccess(ValidationResult.accessDenied(SYSTEM_ADMINISTRATOR_IS_NOT_ALLOWED_TO_PERFORM_THIS_OPERATION)); } else { @@ -183,19 +189,18 @@ public class AccessValidator { if (device == null) { return ValidationResult.entityNotFound(DEVICE_WITH_REQUESTED_ID_NOT_FOUND); } else { - if (!device.getTenantId().equals(currentUser.getTenantId())) { - return ValidationResult.accessDenied("Device doesn't belong to the current Tenant!"); - } else if (currentUser.isCustomerUser() && !device.getCustomerId().equals(currentUser.getCustomerId())) { - return ValidationResult.accessDenied("Device doesn't belong to the current Customer!"); - } else { - return ValidationResult.ok(device); + try { + accessControlService.checkPermission(currentUser, Resource.DEVICE, operation, entityId, device); + } catch (ThingsboardException e) { + return ValidationResult.accessDenied(e.getMessage()); } + return ValidationResult.ok(device); } }), executor); } } - private void validateAsset(final SecurityUser currentUser, EntityId entityId, FutureCallback callback) { + private void validateAsset(final SecurityUser currentUser, Operation operation, EntityId entityId, FutureCallback callback) { if (currentUser.isSystemAdmin()) { callback.onSuccess(ValidationResult.accessDenied(SYSTEM_ADMINISTRATOR_IS_NOT_ALLOWED_TO_PERFORM_THIS_OPERATION)); } else { @@ -204,19 +209,18 @@ public class AccessValidator { if (asset == null) { return ValidationResult.entityNotFound("Asset with requested id wasn't found!"); } else { - if (!asset.getTenantId().equals(currentUser.getTenantId())) { - return ValidationResult.accessDenied("Asset doesn't belong to the current Tenant!"); - } else if (currentUser.isCustomerUser() && !asset.getCustomerId().equals(currentUser.getCustomerId())) { - return ValidationResult.accessDenied("Asset doesn't belong to the current Customer!"); - } else { - return ValidationResult.ok(asset); + try { + accessControlService.checkPermission(currentUser, Resource.ASSET, operation, entityId, asset); + } catch (ThingsboardException e) { + return ValidationResult.accessDenied(e.getMessage()); } + return ValidationResult.ok(asset); } }), executor); } } - private void validateRuleChain(final SecurityUser currentUser, EntityId entityId, FutureCallback callback) { + private void validateRuleChain(final SecurityUser currentUser, Operation operation, EntityId entityId, FutureCallback callback) { if (currentUser.isCustomerUser()) { callback.onSuccess(ValidationResult.accessDenied(CUSTOMER_USER_IS_NOT_ALLOWED_TO_PERFORM_THIS_OPERATION)); } else { @@ -225,19 +229,18 @@ public class AccessValidator { if (ruleChain == null) { return ValidationResult.entityNotFound("Rule chain with requested id wasn't found!"); } else { - if (currentUser.isTenantAdmin() && !ruleChain.getTenantId().equals(currentUser.getTenantId())) { - return ValidationResult.accessDenied("Rule chain doesn't belong to the current Tenant!"); - } else if (currentUser.isSystemAdmin() && !ruleChain.getTenantId().isNullUid()) { - return ValidationResult.accessDenied("Rule chain is not in system scope!"); - } else { - return ValidationResult.ok(ruleChain); + try { + accessControlService.checkPermission(currentUser, Resource.RULE_CHAIN, operation, entityId, ruleChain); + } catch (ThingsboardException e) { + return ValidationResult.accessDenied(e.getMessage()); } + return ValidationResult.ok(ruleChain); } }), executor); } } - private void validateRule(final SecurityUser currentUser, EntityId entityId, FutureCallback callback) { + private void validateRule(final SecurityUser currentUser, Operation operation, EntityId entityId, FutureCallback callback) { if (currentUser.isCustomerUser()) { callback.onSuccess(ValidationResult.accessDenied(CUSTOMER_USER_IS_NOT_ALLOWED_TO_PERFORM_THIS_OPERATION)); } else { @@ -251,19 +254,18 @@ public class AccessValidator { } else { //TODO: make async RuleChain ruleChain = ruleChainService.findRuleChainById(currentUser.getTenantId(), ruleNode.getRuleChainId()); - if (currentUser.isTenantAdmin() && !ruleChain.getTenantId().equals(currentUser.getTenantId())) { - return ValidationResult.accessDenied("Rule chain doesn't belong to the current Tenant!"); - } else if (currentUser.isSystemAdmin() && !ruleChain.getTenantId().isNullUid()) { - return ValidationResult.accessDenied("Rule chain is not in system scope!"); - } else { - return ValidationResult.ok(ruleNode); + try { + accessControlService.checkPermission(currentUser, Resource.RULE_CHAIN, operation, ruleNode.getRuleChainId(), ruleChain); + } catch (ThingsboardException e) { + return ValidationResult.accessDenied(e.getMessage()); } + return ValidationResult.ok(ruleNode); } }), executor); } } - private void validateCustomer(final SecurityUser currentUser, EntityId entityId, FutureCallback callback) { + private void validateCustomer(final SecurityUser currentUser, Operation operation, EntityId entityId, FutureCallback callback) { if (currentUser.isSystemAdmin()) { callback.onSuccess(ValidationResult.accessDenied(SYSTEM_ADMINISTRATOR_IS_NOT_ALLOWED_TO_PERFORM_THIS_OPERATION)); } else { @@ -272,19 +274,18 @@ public class AccessValidator { if (customer == null) { return ValidationResult.entityNotFound("Customer with requested id wasn't found!"); } else { - if (!customer.getTenantId().equals(currentUser.getTenantId())) { - return ValidationResult.accessDenied("Customer doesn't belong to the current Tenant!"); - } else if (currentUser.isCustomerUser() && !customer.getId().equals(currentUser.getCustomerId())) { - return ValidationResult.accessDenied("Customer doesn't relate to the currently authorized customer user!"); - } else { - return ValidationResult.ok(customer); + try { + accessControlService.checkPermission(currentUser, customer.getTenantId(), Resource.CUSTOMER, operation, entityId); + } catch (ThingsboardException e) { + return ValidationResult.accessDenied(e.getMessage()); } + return ValidationResult.ok(customer); } }), executor); } } - private void validateTenant(final SecurityUser currentUser, EntityId entityId, FutureCallback callback) { + private void validateTenant(final SecurityUser currentUser, Operation operation, EntityId entityId, FutureCallback callback) { if (currentUser.isCustomerUser()) { callback.onSuccess(ValidationResult.accessDenied(CUSTOMER_USER_IS_NOT_ALLOWED_TO_PERFORM_THIS_OPERATION)); } else if (currentUser.isSystemAdmin()) { @@ -294,16 +295,19 @@ public class AccessValidator { Futures.addCallback(tenantFuture, getCallback(callback, tenant -> { if (tenant == null) { return ValidationResult.entityNotFound("Tenant with requested id wasn't found!"); - } else if (!tenant.getId().equals(currentUser.getTenantId())) { - return ValidationResult.accessDenied("Tenant doesn't relate to the currently authorized user!"); - } else { - return ValidationResult.ok(tenant); } + try { + accessControlService.checkPermission(currentUser, new TenantId(entityId.getId()), Resource.TENANT, operation, entityId); + } catch (ThingsboardException e) { + return ValidationResult.accessDenied(e.getMessage()); + } + return ValidationResult.ok(tenant); + }), executor); } } - private void validateEntityView(final SecurityUser currentUser, EntityId entityId, FutureCallback callback) { + private void validateEntityView(final SecurityUser currentUser, Operation operation, EntityId entityId, FutureCallback callback) { if (currentUser.isSystemAdmin()) { callback.onSuccess(ValidationResult.accessDenied(SYSTEM_ADMINISTRATOR_IS_NOT_ALLOWED_TO_PERFORM_THIS_OPERATION)); } else { @@ -312,13 +316,12 @@ public class AccessValidator { if (entityView == null) { return ValidationResult.entityNotFound(ENTITY_VIEW_WITH_REQUESTED_ID_NOT_FOUND); } else { - if (!entityView.getTenantId().equals(currentUser.getTenantId())) { - return ValidationResult.accessDenied("Entity-view doesn't belong to the current Tenant!"); - } else if (currentUser.isCustomerUser() && !entityView.getCustomerId().equals(currentUser.getCustomerId())) { - return ValidationResult.accessDenied("Entity-view doesn't belong to the current Customer!"); - } else { - return ValidationResult.ok(entityView); + try { + accessControlService.checkPermission(currentUser, Resource.ENTITY_VIEW, operation, entityId, entityView); + } catch (ThingsboardException e) { + return ValidationResult.accessDenied(e.getMessage()); } + return ValidationResult.ok(entityView); } }), executor); } diff --git a/application/src/main/java/org/thingsboard/server/service/security/permission/AccessControlService.java b/application/src/main/java/org/thingsboard/server/service/security/permission/AccessControlService.java index 03d4222cfd..ccb62ec99b 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/permission/AccessControlService.java +++ b/application/src/main/java/org/thingsboard/server/service/security/permission/AccessControlService.java @@ -28,6 +28,6 @@ public interface AccessControlService { void checkPermission(SecurityUser user, TenantId tenantId, Resource resource, Operation operation, EntityId entityId) throws ThingsboardException; - void checkPermission(SecurityUser user, Resource resource, Operation operation, I entityId, T entity) throws ThingsboardException; + void checkPermission(SecurityUser user, Resource resource, Operation operation, I entityId, T entity) throws ThingsboardException; } diff --git a/application/src/main/java/org/thingsboard/server/service/security/permission/CustomerUserPremissions.java b/application/src/main/java/org/thingsboard/server/service/security/permission/CustomerUserPremissions.java new file mode 100644 index 0000000000..4c67aa3df0 --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/service/security/permission/CustomerUserPremissions.java @@ -0,0 +1,86 @@ +package org.thingsboard.server.service.security.permission; + +import org.thingsboard.server.common.data.Dashboard; +import org.thingsboard.server.common.data.DashboardInfo; +import org.thingsboard.server.common.data.HasCustomerId; +import org.thingsboard.server.common.data.HasTenantId; +import org.thingsboard.server.common.data.id.DashboardId; +import org.thingsboard.server.common.data.id.EntityId; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.service.security.model.SecurityUser; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Set; + +public class CustomerUserPremissions extends HashMap { + + public CustomerUserPremissions() { + super(); + put(Resource.ALARM, TenantAdminPermissions.tenantEntityPermissionChecker); + put(Resource.ASSET, customerEntityPermissionChecker); + put(Resource.DEVICE, customerEntityPermissionChecker); + put(Resource.CUSTOMER, customerPermissionChecker); + put(Resource.DASHBOARD, customerDashboardPermissionChecker); + put(Resource.ENTITY_VIEW, customerEntityPermissionChecker); + put(Resource.TENANT, TenantAdminPermissions.tenantPermissionChecker); + } + + public static final PermissionChecker customerEntityPermissionChecker = new PermissionChecker.GenericPermissionChecker(Operation.READ) { + + @Override + public boolean hasPermission(SecurityUser user, Operation operation, EntityId entityId, HasTenantId entity) { + + if (!super.hasPermission(user, operation, entityId, entity)) { + return false; + } + if (!user.getTenantId().equals(entity.getTenantId())) { + return false; + } + if (!(entity instanceof HasCustomerId)) { + return false; + } + if (!user.getCustomerId().equals(((HasCustomerId)entity).getCustomerId())) { + return false; + } + return true; + } + }; + + private static final PermissionChecker customerPermissionChecker = + new PermissionChecker.GenericPermissionChecker(Operation.READ) { + + @Override + public boolean hasPermission(SecurityUser user, TenantId tenantId, Operation operation, EntityId entityId) { + if (!super.hasPermission(user, tenantId, operation, entityId)) { + return false; + } + if (!user.getCustomerId().equals(entityId)) { + return false; + } + return true; + } + + }; + + private static final PermissionChecker customerDashboardPermissionChecker = + new PermissionChecker.GenericPermissionChecker(Operation.READ) { + + @Override + public boolean hasPermission(SecurityUser user, Operation operation, DashboardId dashboardId, DashboardInfo dashboard) { + + if (!super.hasPermission(user, operation, dashboardId, dashboard)) { + return false; + } + if (!user.getTenantId().equals(dashboard.getTenantId())) { + return false; + } + if (!dashboard.isAssignedToCustomer(user.getCustomerId())) { + return false; + } + return true; + } + + }; +} diff --git a/application/src/main/java/org/thingsboard/server/service/security/permission/DefaultAccessControlService.java b/application/src/main/java/org/thingsboard/server/service/security/permission/DefaultAccessControlService.java new file mode 100644 index 0000000000..76018914db --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/service/security/permission/DefaultAccessControlService.java @@ -0,0 +1,95 @@ +/** + * Copyright © 2016-2018 The Thingsboard Authors + * + * Licensed 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 org.thingsboard.server.service.security.permission; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.thingsboard.server.common.data.Customer; +import org.thingsboard.server.common.data.EntityType; +import org.thingsboard.server.common.data.HasCustomerId; +import org.thingsboard.server.common.data.HasTenantId; +import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; +import org.thingsboard.server.common.data.exception.ThingsboardException; +import org.thingsboard.server.common.data.id.CustomerId; +import org.thingsboard.server.common.data.id.EntityId; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.security.Authority; +import org.thingsboard.server.dao.customer.CustomerService; +import org.thingsboard.server.service.security.model.SecurityUser; + +import java.util.*; + +import static org.thingsboard.server.dao.service.Validator.validateId; + +@Service +@Slf4j +public class DefaultAccessControlService implements AccessControlService { + + private static final String INCORRECT_TENANT_ID = "Incorrect tenantId "; + private static final String YOU_DON_T_HAVE_PERMISSION_TO_PERFORM_THIS_OPERATION = "You don't have permission to perform this operation!"; + + private final Map> authorityPermissions = new HashMap<>(); + { + authorityPermissions.put(Authority.SYS_ADMIN, new SysAdminPermissions()); + authorityPermissions.put(Authority.TENANT_ADMIN, new TenantAdminPermissions()); + authorityPermissions.put(Authority.CUSTOMER_USER, new CustomerUserPremissions()); + } + + @Override + public void checkPermission(SecurityUser user, TenantId tenantId, Resource resource, Operation operation) throws ThingsboardException { + PermissionChecker permissionChecker = getPermissionChecker(user.getAuthority(), resource); + if (!permissionChecker.hasPermission(user, tenantId, operation)) { + permissionDenied(); + } + } + + @Override + public void checkPermission(SecurityUser user, TenantId tenantId, Resource resource, Operation operation, EntityId entityId) throws ThingsboardException { + PermissionChecker permissionChecker = getPermissionChecker(user.getAuthority(), resource); + if (!permissionChecker.hasPermission(user, tenantId, operation, entityId)) { + permissionDenied(); + } + } + + @Override + public void checkPermission(SecurityUser user, Resource resource, + Operation operation, I entityId, T entity) throws ThingsboardException { + PermissionChecker permissionChecker = getPermissionChecker(user.getAuthority(), resource); + if (!permissionChecker.hasPermission(user, operation, entityId, entity)) { + permissionDenied(); + } + } + + private PermissionChecker getPermissionChecker(Authority authority, Resource resource) throws ThingsboardException { + Map permissions = authorityPermissions.get(authority); + if (permissions == null) { + permissionDenied(); + } + PermissionChecker permissionChecker = permissions.get(resource); + if (permissionChecker == null) { + permissionDenied(); + } + return permissionChecker; + } + + private void permissionDenied() throws ThingsboardException { + throw new ThingsboardException(YOU_DON_T_HAVE_PERMISSION_TO_PERFORM_THIS_OPERATION, + ThingsboardErrorCode.PERMISSION_DENIED); + } + +} diff --git a/application/src/main/java/org/thingsboard/server/service/security/permission/Operation.java b/application/src/main/java/org/thingsboard/server/service/security/permission/Operation.java index 3c48c664a2..d5254e737e 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/permission/Operation.java +++ b/application/src/main/java/org/thingsboard/server/service/security/permission/Operation.java @@ -17,6 +17,6 @@ package org.thingsboard.server.service.security.permission; public enum Operation { - ALL, CREATE, READ, WRITE, DELETE + ALL, CREATE, READ, WRITE, DELETE, ASSIGN_TO_CUSTOMER, UNASSIGN_FROM_CUSTOMER } diff --git a/application/src/main/java/org/thingsboard/server/service/security/permission/PermissionChecker.java b/application/src/main/java/org/thingsboard/server/service/security/permission/PermissionChecker.java new file mode 100644 index 0000000000..921b7d96c4 --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/service/security/permission/PermissionChecker.java @@ -0,0 +1,72 @@ +package org.thingsboard.server.service.security.permission; + +import org.thingsboard.server.common.data.HasCustomerId; +import org.thingsboard.server.common.data.HasTenantId; +import org.thingsboard.server.common.data.id.EntityId; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.service.security.model.SecurityUser; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +public interface PermissionChecker { + + default boolean hasPermission(SecurityUser user, TenantId tenantId, Operation operation) { + return false; + } + + default boolean hasPermission(SecurityUser user, TenantId tenantId, Operation operation, EntityId entityId) { + return false; + } + + default boolean hasPermission(SecurityUser user, Operation operation, I entityId, T entity) { + return false; + } + + public class GenericPermissionChecker implements PermissionChecker { + + private final Set allowedOperations; + + public GenericPermissionChecker(Operation... operations) { + allowedOperations = new HashSet(Arrays.asList(operations)); + } + + @Override + public boolean hasPermission(SecurityUser user, TenantId tenantId, 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); + } + + @Override + public boolean hasPermission(SecurityUser user, Operation operation, I entityId, T entity) { + return allowedOperations.contains(Operation.ALL) || allowedOperations.contains(operation); + } + } + + public static PermissionChecker denyAllPermissionChecker = new PermissionChecker() {}; + + public static PermissionChecker allowAllPermissionChecker = new PermissionChecker() { + + @Override + public boolean hasPermission(SecurityUser user, TenantId tenantId, Operation operation) { + return true; + } + + @Override + public boolean hasPermission(SecurityUser user, TenantId tenantId, Operation operation, EntityId entityId) { + return true; + } + + @Override + public boolean hasPermission(SecurityUser user, Operation operation, EntityId entityId, HasTenantId entity) { + return true; + } + }; + + +} diff --git a/application/src/main/java/org/thingsboard/server/service/security/permission/Resource.java b/application/src/main/java/org/thingsboard/server/service/security/permission/Resource.java index 391cfd5ac8..8cf4dc2613 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/permission/Resource.java +++ b/application/src/main/java/org/thingsboard/server/service/security/permission/Resource.java @@ -20,7 +20,15 @@ import org.thingsboard.server.common.data.EntityType; import java.util.Optional; public enum Resource { - DEVICE(EntityType.DEVICE); + ADMIN_SETTINGS(), + ALARM(EntityType.ALARM), + DEVICE(EntityType.DEVICE), + ASSET(EntityType.ASSET), + CUSTOMER(EntityType.CUSTOMER), + DASHBOARD(EntityType.DASHBOARD), + ENTITY_VIEW(EntityType.ENTITY_VIEW), + TENANT(EntityType.TENANT), + RULE_CHAIN(EntityType.RULE_CHAIN); private final EntityType entityType; diff --git a/application/src/main/java/org/thingsboard/server/service/security/permission/SysAdminPermissions.java b/application/src/main/java/org/thingsboard/server/service/security/permission/SysAdminPermissions.java new file mode 100644 index 0000000000..251cb9b2f0 --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/service/security/permission/SysAdminPermissions.java @@ -0,0 +1,39 @@ +package org.thingsboard.server.service.security.permission; + +import org.thingsboard.server.common.data.HasTenantId; +import org.thingsboard.server.common.data.id.EntityId; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.service.security.model.SecurityUser; + +import java.util.HashMap; + +public class SysAdminPermissions extends HashMap { + + public SysAdminPermissions() { + super(); + put(Resource.ADMIN_SETTINGS, PermissionChecker.allowAllPermissionChecker); + put(Resource.DASHBOARD, new PermissionChecker.GenericPermissionChecker(Operation.READ)); + put(Resource.TENANT, PermissionChecker.allowAllPermissionChecker); + put(Resource.RULE_CHAIN, systemEntityPermissionChecker); + } + + 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 + public boolean hasPermission(SecurityUser user, Operation operation, EntityId entityId, HasTenantId entity) { + + if (entity.getTenantId() != null && !entity.getTenantId().isNullUid()) { + return false; + } + return true; + } + }; +} diff --git a/application/src/main/java/org/thingsboard/server/service/security/permission/TenantAdminPermissions.java b/application/src/main/java/org/thingsboard/server/service/security/permission/TenantAdminPermissions.java new file mode 100644 index 0000000000..c8e208f354 --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/service/security/permission/TenantAdminPermissions.java @@ -0,0 +1,59 @@ +package org.thingsboard.server.service.security.permission; + +import org.thingsboard.server.common.data.HasTenantId; +import org.thingsboard.server.common.data.id.EntityId; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.service.security.model.SecurityUser; + +import java.util.HashMap; + +public class TenantAdminPermissions extends HashMap { + + public TenantAdminPermissions() { + super(); + put(Resource.ALARM, tenantEntityPermissionChecker); + put(Resource.ASSET, tenantEntityPermissionChecker); + put(Resource.DEVICE, tenantEntityPermissionChecker); + put(Resource.CUSTOMER, tenantEntityPermissionChecker); + put(Resource.DASHBOARD, tenantEntityPermissionChecker); + put(Resource.ENTITY_VIEW, tenantEntityPermissionChecker); + put(Resource.TENANT, tenantPermissionChecker); + put(Resource.RULE_CHAIN, tenantEntityPermissionChecker); + } + + 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 + public boolean hasPermission(SecurityUser user, Operation operation, EntityId entityId, HasTenantId entity) { + + if (!user.getTenantId().equals(entity.getTenantId())) { + return false; + } + return true; + } + }; + + public static final PermissionChecker tenantPermissionChecker = + new PermissionChecker.GenericPermissionChecker(Operation.READ) { + + @Override + public boolean hasPermission(SecurityUser user, TenantId tenantId, Operation operation, EntityId entityId) { + if (!super.hasPermission(user, tenantId, operation, entityId)) { + return false; + } + if (!user.getTenantId().equals(entityId)) { + return false; + } + return true; + } + + }; +} diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/DashboardInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/DashboardInfo.java index 7b74e6283f..e5688a6b4a 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/DashboardInfo.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/DashboardInfo.java @@ -22,7 +22,7 @@ import org.thingsboard.server.common.data.id.TenantId; import java.util.*; -public class DashboardInfo extends SearchTextBased implements HasName { +public class DashboardInfo extends SearchTextBased implements HasName, HasTenantId { private TenantId tenantId; private String title;