Commit 104450c10276ba45ffd651e9a55a54288c71a107

Authored by Andrew Shvayka
1 parent c84bcd51

Refactoring of DAO layer to support rate limiting by tenant

Showing 68 changed files with 860 additions and 828 deletions

Too many changes to show.

To preserve performance only 68 of 140 files are displayed.

... ... @@ -143,6 +143,9 @@ cassandra:
143 143 concurrent_limit: "${CASSANDRA_QUERY_CONCURRENT_LIMIT:1000}"
144 144 permit_max_wait_time: "${PERMIT_MAX_WAIT_TIME:120000}"
145 145 rate_limit_print_interval_ms: "${CASSANDRA_QUERY_RATE_LIMIT_PRINT_MS:10000}"
  146 + tenant_rate_limits:
  147 + enabled: "${CASSANDRA_QUERY_TENANT_RATE_LIMITS_ENABLED:false}"
  148 + configuration: "${CASSANDRA_QUERY_TENANT_RATE_LIMITS_VALUE:1000:1,30000:60}"
146 149
147 150 # SQL configuration parameters
148 151 sql:
... ...
... ... @@ -61,6 +61,10 @@
61 61 <artifactId>logback-classic</artifactId>
62 62 </dependency>
63 63 <dependency>
  64 + <groupId>com.github.vladimir-bukhtoyarov</groupId>
  65 + <artifactId>bucket4j-core</artifactId>
  66 + </dependency>
  67 + <dependency>
64 68 <groupId>com.google.protobuf</groupId>
65 69 <artifactId>protobuf-java</artifactId>
66 70 <scope>provided</scope>
... ...
common/message/src/main/java/org/thingsboard/server/common/msg/tools/TbRateLimits.java renamed from common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/service/TbTransportRateLimits.java
... ... @@ -13,7 +13,7 @@
13 13 * See the License for the specific language governing permissions and
14 14 * limitations under the License.
15 15 */
16   -package org.thingsboard.server.common.transport.service;
  16 +package org.thingsboard.server.common.msg.tools;
17 17
18 18 import io.github.bucket4j.Bandwidth;
19 19 import io.github.bucket4j.Bucket4j;
... ... @@ -25,10 +25,10 @@ import java.time.Duration;
25 25 /**
26 26 * Created by ashvayka on 22.10.18.
27 27 */
28   -class TbTransportRateLimits {
  28 +public class TbRateLimits {
29 29 private final LocalBucket bucket;
30 30
31   - public TbTransportRateLimits(String limitsConfiguration) {
  31 + public TbRateLimits(String limitsConfiguration) {
32 32 LocalBucketBuilder builder = Bucket4j.builder();
33 33 boolean initialized = false;
34 34 for (String limitSrc : limitsConfiguration.split(",")) {
... ... @@ -46,7 +46,7 @@ class TbTransportRateLimits {
46 46
47 47 }
48 48
49   - boolean tryConsume() {
  49 + public boolean tryConsume() {
50 50 return bucket.tryConsume(1);
51 51 }
52 52
... ...
... ... @@ -99,10 +99,6 @@
99 99 <groupId>com.google.protobuf</groupId>
100 100 <artifactId>protobuf-java</artifactId>
101 101 </dependency>
102   - <dependency>
103   - <groupId>com.github.vladimir-bukhtoyarov</groupId>
104   - <artifactId>bucket4j-core</artifactId>
105   - </dependency>
106 102 </dependencies>
107 103
108 104 <build>
... ...
... ... @@ -20,6 +20,7 @@ import org.springframework.beans.factory.annotation.Value;
20 20 import org.thingsboard.server.common.data.EntityType;
21 21 import org.thingsboard.server.common.data.id.DeviceId;
22 22 import org.thingsboard.server.common.data.id.TenantId;
  23 +import org.thingsboard.server.common.msg.tools.TbRateLimits;
23 24 import org.thingsboard.server.common.transport.SessionMsgListener;
24 25 import org.thingsboard.server.common.transport.TransportService;
25 26 import org.thingsboard.server.common.transport.TransportServiceCallback;
... ... @@ -58,8 +59,8 @@ public abstract class AbstractTransportService implements TransportService {
58 59 private ConcurrentMap<UUID, SessionMetaData> sessions = new ConcurrentHashMap<>();
59 60
60 61 //TODO: Implement cleanup of this maps.
61   - private ConcurrentMap<TenantId, TbTransportRateLimits> perTenantLimits = new ConcurrentHashMap<>();
62   - private ConcurrentMap<DeviceId, TbTransportRateLimits> perDeviceLimits = new ConcurrentHashMap<>();
  62 + private ConcurrentMap<TenantId, TbRateLimits> perTenantLimits = new ConcurrentHashMap<>();
  63 + private ConcurrentMap<DeviceId, TbRateLimits> perDeviceLimits = new ConcurrentHashMap<>();
63 64
64 65 @Override
65 66 public void registerAsyncSession(TransportProtos.SessionInfoProto sessionInfo, SessionMsgListener listener) {
... ... @@ -204,7 +205,7 @@ public abstract class AbstractTransportService implements TransportService {
204 205 return true;
205 206 }
206 207 TenantId tenantId = new TenantId(new UUID(sessionInfo.getTenantIdMSB(), sessionInfo.getTenantIdLSB()));
207   - TbTransportRateLimits rateLimits = perTenantLimits.computeIfAbsent(tenantId, id -> new TbTransportRateLimits(perTenantLimitsConf));
  208 + TbRateLimits rateLimits = perTenantLimits.computeIfAbsent(tenantId, id -> new TbRateLimits(perTenantLimitsConf));
208 209 if (!rateLimits.tryConsume()) {
209 210 if (callback != null) {
210 211 callback.onError(new TbRateLimitsException(EntityType.TENANT));
... ... @@ -215,7 +216,7 @@ public abstract class AbstractTransportService implements TransportService {
215 216 return false;
216 217 }
217 218 DeviceId deviceId = new DeviceId(new UUID(sessionInfo.getDeviceIdMSB(), sessionInfo.getDeviceIdLSB()));
218   - rateLimits = perDeviceLimits.computeIfAbsent(deviceId, id -> new TbTransportRateLimits(perDevicesLimitsConf));
  219 + rateLimits = perDeviceLimits.computeIfAbsent(deviceId, id -> new TbRateLimits(perDevicesLimitsConf));
219 220 if (!rateLimits.tryConsume()) {
220 221 if (callback != null) {
221 222 callback.onError(new TbRateLimitsException(EntityType.DEVICE));
... ... @@ -271,8 +272,8 @@ public abstract class AbstractTransportService implements TransportService {
271 272 public void init() {
272 273 if (rateLimitEnabled) {
273 274 //Just checking the configuration parameters
274   - new TbTransportRateLimits(perTenantLimitsConf);
275   - new TbTransportRateLimits(perDevicesLimitsConf);
  275 + new TbRateLimits(perTenantLimitsConf);
  276 + new TbRateLimits(perDevicesLimitsConf);
276 277 }
277 278 this.schedulerExecutor = Executors.newSingleThreadScheduledExecutor();
278 279 this.transportCallbackExecutor = new ThreadPoolExecutor(0, 20, 60L, TimeUnit.SECONDS, new SynchronousQueue<>());
... ...
... ... @@ -16,20 +16,21 @@
16 16 package org.thingsboard.server.dao;
17 17
18 18 import com.google.common.util.concurrent.ListenableFuture;
  19 +import org.thingsboard.server.common.data.id.TenantId;
19 20
20 21 import java.util.List;
21 22 import java.util.UUID;
22 23
23 24 public interface Dao<T> {
24 25
25   - List<T> find();
  26 + List<T> find(TenantId tenantId);
26 27
27   - T findById(UUID id);
  28 + T findById(TenantId tenantId, UUID id);
28 29
29   - ListenableFuture<T> findByIdAsync(UUID id);
  30 + ListenableFuture<T> findByIdAsync(TenantId tenantId, UUID id);
30 31
31   - T save(T t);
  32 + T save(TenantId tenantId, T t);
32 33
33   - boolean removeById(UUID id);
  34 + boolean removeById(TenantId tenantId, UUID id);
34 35
35 36 }
... ...
... ... @@ -33,9 +33,9 @@ public interface AlarmDao extends Dao<Alarm> {
33 33
34 34 ListenableFuture<Alarm> findLatestByOriginatorAndType(TenantId tenantId, EntityId originator, String type);
35 35
36   - ListenableFuture<Alarm> findAlarmByIdAsync(UUID key);
  36 + ListenableFuture<Alarm> findAlarmByIdAsync(TenantId tenantId, UUID key);
37 37
38   - Alarm save(Alarm alarm);
  38 + Alarm save(TenantId tenantId, Alarm alarm);
39 39
40   - ListenableFuture<List<AlarmInfo>> findAlarms(AlarmQuery query);
  40 + ListenableFuture<List<AlarmInfo>> findAlarms(TenantId tenantId, AlarmQuery query);
41 41 }
... ...
... ... @@ -35,17 +35,17 @@ public interface AlarmService {
35 35
36 36 Alarm createOrUpdateAlarm(Alarm alarm);
37 37
38   - ListenableFuture<Boolean> ackAlarm(AlarmId alarmId, long ackTs);
  38 + ListenableFuture<Boolean> ackAlarm(TenantId tenantId, AlarmId alarmId, long ackTs);
39 39
40   - ListenableFuture<Boolean> clearAlarm(AlarmId alarmId, JsonNode details, long ackTs);
  40 + ListenableFuture<Boolean> clearAlarm(TenantId tenantId, AlarmId alarmId, JsonNode details, long ackTs);
41 41
42   - ListenableFuture<Alarm> findAlarmByIdAsync(AlarmId alarmId);
  42 + ListenableFuture<Alarm> findAlarmByIdAsync(TenantId tenantId, AlarmId alarmId);
43 43
44   - ListenableFuture<AlarmInfo> findAlarmInfoByIdAsync(AlarmId alarmId);
  44 + ListenableFuture<AlarmInfo> findAlarmInfoByIdAsync(TenantId tenantId, AlarmId alarmId);
45 45
46   - ListenableFuture<TimePageData<AlarmInfo>> findAlarms(AlarmQuery query);
  46 + ListenableFuture<TimePageData<AlarmInfo>> findAlarms(TenantId tenantId, AlarmQuery query);
47 47
48   - AlarmSeverity findHighestAlarmSeverity(EntityId entityId, AlarmSearchStatus alarmSearchStatus,
  48 + AlarmSeverity findHighestAlarmSeverity(TenantId tenantId, EntityId entityId, AlarmSearchStatus alarmSearchStatus,
49 49 AlarmStatus alarmStatus);
50 50
51 51 ListenableFuture<Alarm> findLatestByOriginatorAndType(TenantId tenantId, EntityId originator, String type);
... ...
... ... @@ -91,7 +91,7 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ
91 91
92 92 @Override
93 93 public Alarm createOrUpdateAlarm(Alarm alarm) {
94   - alarmDataValidator.validate(alarm);
  94 + alarmDataValidator.validate(alarm, Alarm::getTenantId);
95 95 try {
96 96 if (alarm.getStartTs() == 0L) {
97 97 alarm.setStartTs(System.currentTimeMillis());
... ... @@ -120,7 +120,7 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ
120 120
121 121 private Alarm createAlarm(Alarm alarm) throws InterruptedException, ExecutionException {
122 122 log.debug("New Alarm : {}", alarm);
123   - Alarm saved = alarmDao.save(alarm);
  123 + Alarm saved = alarmDao.save(alarm.getTenantId(), alarm);
124 124 createAlarmRelations(saved);
125 125 return saved;
126 126 }
... ... @@ -129,17 +129,17 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ
129 129 if (alarm.isPropagate()) {
130 130 EntityRelationsQuery query = new EntityRelationsQuery();
131 131 query.setParameters(new RelationsSearchParameters(alarm.getOriginator(), EntitySearchDirection.TO, Integer.MAX_VALUE));
132   - List<EntityId> parentEntities = relationService.findByQuery(query).get().stream().map(r -> r.getFrom()).collect(Collectors.toList());
  132 + List<EntityId> parentEntities = relationService.findByQuery(alarm.getTenantId(), query).get().stream().map(EntityRelation::getFrom).collect(Collectors.toList());
133 133 for (EntityId parentId : parentEntities) {
134   - createAlarmRelation(parentId, alarm.getId(), alarm.getStatus(), true);
  134 + createAlarmRelation(alarm.getTenantId(), parentId, alarm.getId(), alarm.getStatus(), true);
135 135 }
136 136 }
137   - createAlarmRelation(alarm.getOriginator(), alarm.getId(), alarm.getStatus(), true);
  137 + createAlarmRelation(alarm.getTenantId(), alarm.getOriginator(), alarm.getId(), alarm.getStatus(), true);
138 138 }
139 139
140 140 private ListenableFuture<Alarm> updateAlarm(Alarm update) {
141   - alarmDataValidator.validate(update);
142   - return getAndUpdate(update.getId(), new Function<Alarm, Alarm>() {
  141 + alarmDataValidator.validate(update, Alarm::getTenantId);
  142 + return getAndUpdate(update.getTenantId(), update.getId(), new Function<Alarm, Alarm>() {
143 143 @Nullable
144 144 @Override
145 145 public Alarm apply(@Nullable Alarm alarm) {
... ... @@ -157,7 +157,7 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ
157 157 AlarmStatus newStatus = newAlarm.getStatus();
158 158 boolean oldPropagate = oldAlarm.isPropagate();
159 159 boolean newPropagate = newAlarm.isPropagate();
160   - Alarm result = alarmDao.save(merge(oldAlarm, newAlarm));
  160 + Alarm result = alarmDao.save(newAlarm.getTenantId(), merge(oldAlarm, newAlarm));
161 161 if (!oldPropagate && newPropagate) {
162 162 try {
163 163 createAlarmRelations(result);
... ... @@ -172,8 +172,8 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ
172 172 }
173 173
174 174 @Override
175   - public ListenableFuture<Boolean> ackAlarm(AlarmId alarmId, long ackTime) {
176   - return getAndUpdate(alarmId, new Function<Alarm, Boolean>() {
  175 + public ListenableFuture<Boolean> ackAlarm(TenantId tenantId, AlarmId alarmId, long ackTime) {
  176 + return getAndUpdate(tenantId, alarmId, new Function<Alarm, Boolean>() {
177 177 @Nullable
178 178 @Override
179 179 public Boolean apply(@Nullable Alarm alarm) {
... ... @@ -184,7 +184,7 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ
184 184 AlarmStatus newStatus = oldStatus.isCleared() ? AlarmStatus.CLEARED_ACK : AlarmStatus.ACTIVE_ACK;
185 185 alarm.setStatus(newStatus);
186 186 alarm.setAckTs(ackTime);
187   - alarmDao.save(alarm);
  187 + alarmDao.save(alarm.getTenantId(), alarm);
188 188 updateRelations(alarm, oldStatus, newStatus);
189 189 return true;
190 190 }
... ... @@ -193,8 +193,8 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ
193 193 }
194 194
195 195 @Override
196   - public ListenableFuture<Boolean> clearAlarm(AlarmId alarmId, JsonNode details, long clearTime) {
197   - return getAndUpdate(alarmId, new Function<Alarm, Boolean>() {
  196 + public ListenableFuture<Boolean> clearAlarm(TenantId tenantId, AlarmId alarmId, JsonNode details, long clearTime) {
  197 + return getAndUpdate(tenantId, alarmId, new Function<Alarm, Boolean>() {
198 198 @Nullable
199 199 @Override
200 200 public Boolean apply(@Nullable Alarm alarm) {
... ... @@ -208,7 +208,7 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ
208 208 if (details != null) {
209 209 alarm.setDetails(details);
210 210 }
211   - alarmDao.save(alarm);
  211 + alarmDao.save(alarm.getTenantId(), alarm);
212 212 updateRelations(alarm, oldStatus, newStatus);
213 213 return true;
214 214 }
... ... @@ -217,21 +217,21 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ
217 217 }
218 218
219 219 @Override
220   - public ListenableFuture<Alarm> findAlarmByIdAsync(AlarmId alarmId) {
  220 + public ListenableFuture<Alarm> findAlarmByIdAsync(TenantId tenantId, AlarmId alarmId) {
221 221 log.trace("Executing findAlarmById [{}]", alarmId);
222 222 validateId(alarmId, "Incorrect alarmId " + alarmId);
223   - return alarmDao.findAlarmByIdAsync(alarmId.getId());
  223 + return alarmDao.findAlarmByIdAsync(tenantId, alarmId.getId());
224 224 }
225 225
226 226 @Override
227   - public ListenableFuture<AlarmInfo> findAlarmInfoByIdAsync(AlarmId alarmId) {
  227 + public ListenableFuture<AlarmInfo> findAlarmInfoByIdAsync(TenantId tenantId, AlarmId alarmId) {
228 228 log.trace("Executing findAlarmInfoByIdAsync [{}]", alarmId);
229 229 validateId(alarmId, "Incorrect alarmId " + alarmId);
230   - return Futures.transformAsync(alarmDao.findAlarmByIdAsync(alarmId.getId()),
  230 + return Futures.transformAsync(alarmDao.findAlarmByIdAsync(tenantId, alarmId.getId()),
231 231 a -> {
232 232 AlarmInfo alarmInfo = new AlarmInfo(a);
233 233 return Futures.transform(
234   - entityService.fetchEntityNameAsync(alarmInfo.getOriginator()), originatorName -> {
  234 + entityService.fetchEntityNameAsync(tenantId, alarmInfo.getOriginator()), originatorName -> {
235 235 alarmInfo.setOriginatorName(originatorName);
236 236 return alarmInfo;
237 237 }
... ... @@ -240,14 +240,14 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ
240 240 }
241 241
242 242 @Override
243   - public ListenableFuture<TimePageData<AlarmInfo>> findAlarms(AlarmQuery query) {
244   - ListenableFuture<List<AlarmInfo>> alarms = alarmDao.findAlarms(query);
  243 + public ListenableFuture<TimePageData<AlarmInfo>> findAlarms(TenantId tenantId, AlarmQuery query) {
  244 + ListenableFuture<List<AlarmInfo>> alarms = alarmDao.findAlarms(tenantId, query);
245 245 if (query.getFetchOriginator() != null && query.getFetchOriginator().booleanValue()) {
246 246 alarms = Futures.transformAsync(alarms, input -> {
247 247 List<ListenableFuture<AlarmInfo>> alarmFutures = new ArrayList<>(input.size());
248 248 for (AlarmInfo alarmInfo : input) {
249 249 alarmFutures.add(Futures.transform(
250   - entityService.fetchEntityNameAsync(alarmInfo.getOriginator()), originatorName -> {
  250 + entityService.fetchEntityNameAsync(tenantId, alarmInfo.getOriginator()), originatorName -> {
251 251 if (originatorName == null) {
252 252 originatorName = "Deleted";
253 253 }
... ... @@ -269,7 +269,7 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ
269 269 }
270 270
271 271 @Override
272   - public AlarmSeverity findHighestAlarmSeverity(EntityId entityId, AlarmSearchStatus alarmSearchStatus,
  272 + public AlarmSeverity findHighestAlarmSeverity(TenantId tenantId, EntityId entityId, AlarmSearchStatus alarmSearchStatus,
273 273 AlarmStatus alarmStatus) {
274 274 TimePageLink nextPageLink = new TimePageLink(100);
275 275 boolean hasNext = true;
... ... @@ -279,7 +279,7 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ
279 279 query = new AlarmQuery(entityId, nextPageLink, alarmSearchStatus, alarmStatus, false);
280 280 List<AlarmInfo> alarms;
281 281 try {
282   - alarms = alarmDao.findAlarms(query).get();
  282 + alarms = alarmDao.findAlarms(tenantId, query).get();
283 283 } catch (ExecutionException | InterruptedException e) {
284 284 log.warn("Failed to find highest alarm severity. EntityId: [{}], AlarmSearchStatus: [{}], AlarmStatus: [{}]",
285 285 entityId, alarmSearchStatus, alarmStatus);
... ... @@ -312,14 +312,14 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ
312 312 }
313 313 }
314 314
315   - private void deleteRelation(EntityRelation alarmRelation) throws ExecutionException, InterruptedException {
  315 + private void deleteRelation(TenantId tenantId, EntityRelation alarmRelation) throws ExecutionException, InterruptedException {
316 316 log.debug("Deleting Alarm relation: {}", alarmRelation);
317   - relationService.deleteRelationAsync(alarmRelation).get();
  317 + relationService.deleteRelationAsync(tenantId, alarmRelation).get();
318 318 }
319 319
320   - private void createRelation(EntityRelation alarmRelation) throws ExecutionException, InterruptedException {
  320 + private void createRelation(TenantId tenantId, EntityRelation alarmRelation) throws ExecutionException, InterruptedException {
321 321 log.debug("Creating Alarm relation: {}", alarmRelation);
322   - relationService.saveRelationAsync(alarmRelation).get();
  322 + relationService.saveRelationAsync(tenantId, alarmRelation).get();
323 323 }
324 324
325 325 private Alarm merge(Alarm existing, Alarm alarm) {
... ... @@ -344,10 +344,10 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ
344 344
345 345 private void updateRelations(Alarm alarm, AlarmStatus oldStatus, AlarmStatus newStatus) {
346 346 try {
347   - List<EntityRelation> relations = relationService.findByToAsync(alarm.getId(), RelationTypeGroup.ALARM).get();
  347 + List<EntityRelation> relations = relationService.findByToAsync(alarm.getTenantId(), alarm.getId(), RelationTypeGroup.ALARM).get();
348 348 Set<EntityId> parents = relations.stream().map(EntityRelation::getFrom).collect(Collectors.toSet());
349 349 for (EntityId parentId : parents) {
350   - updateAlarmRelation(parentId, alarm.getId(), oldStatus, newStatus);
  350 + updateAlarmRelation(alarm.getTenantId(), parentId, alarm.getId(), oldStatus, newStatus);
351 351 }
352 352 } catch (ExecutionException | InterruptedException e) {
353 353 log.warn("[{}] Failed to update relations. Old status: [{}], New status: [{}]", alarm.getId(), oldStatus, newStatus);
... ... @@ -355,39 +355,39 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ
355 355 }
356 356 }
357 357
358   - private void createAlarmRelation(EntityId entityId, EntityId alarmId, AlarmStatus status, boolean createAnyRelation) {
  358 + private void createAlarmRelation(TenantId tenantId, EntityId entityId, EntityId alarmId, AlarmStatus status, boolean createAnyRelation) {
359 359 try {
360 360 if (createAnyRelation) {
361   - createRelation(new EntityRelation(entityId, alarmId, ALARM_RELATION_PREFIX + AlarmSearchStatus.ANY.name(), RelationTypeGroup.ALARM));
  361 + createRelation(tenantId, new EntityRelation(entityId, alarmId, ALARM_RELATION_PREFIX + AlarmSearchStatus.ANY.name(), RelationTypeGroup.ALARM));
362 362 }
363   - createRelation(new EntityRelation(entityId, alarmId, ALARM_RELATION_PREFIX + status.name(), RelationTypeGroup.ALARM));
364   - createRelation(new EntityRelation(entityId, alarmId, ALARM_RELATION_PREFIX + status.getClearSearchStatus().name(), RelationTypeGroup.ALARM));
365   - createRelation(new EntityRelation(entityId, alarmId, ALARM_RELATION_PREFIX + status.getAckSearchStatus().name(), RelationTypeGroup.ALARM));
  363 + createRelation(tenantId, new EntityRelation(entityId, alarmId, ALARM_RELATION_PREFIX + status.name(), RelationTypeGroup.ALARM));
  364 + createRelation(tenantId, new EntityRelation(entityId, alarmId, ALARM_RELATION_PREFIX + status.getClearSearchStatus().name(), RelationTypeGroup.ALARM));
  365 + createRelation(tenantId, new EntityRelation(entityId, alarmId, ALARM_RELATION_PREFIX + status.getAckSearchStatus().name(), RelationTypeGroup.ALARM));
366 366 } catch (ExecutionException | InterruptedException e) {
367 367 log.warn("[{}] Failed to create relation. Status: [{}]", alarmId, status);
368 368 throw new RuntimeException(e);
369 369 }
370 370 }
371 371
372   - private void deleteAlarmRelation(EntityId entityId, EntityId alarmId, AlarmStatus status) {
  372 + private void deleteAlarmRelation(TenantId tenantId, EntityId entityId, EntityId alarmId, AlarmStatus status) {
373 373 try {
374   - deleteRelation(new EntityRelation(entityId, alarmId, ALARM_RELATION_PREFIX + status.name(), RelationTypeGroup.ALARM));
375   - deleteRelation(new EntityRelation(entityId, alarmId, ALARM_RELATION_PREFIX + status.getClearSearchStatus().name(), RelationTypeGroup.ALARM));
376   - deleteRelation(new EntityRelation(entityId, alarmId, ALARM_RELATION_PREFIX + status.getAckSearchStatus().name(), RelationTypeGroup.ALARM));
  374 + deleteRelation(tenantId, new EntityRelation(entityId, alarmId, ALARM_RELATION_PREFIX + status.name(), RelationTypeGroup.ALARM));
  375 + deleteRelation(tenantId, new EntityRelation(entityId, alarmId, ALARM_RELATION_PREFIX + status.getClearSearchStatus().name(), RelationTypeGroup.ALARM));
  376 + deleteRelation(tenantId, new EntityRelation(entityId, alarmId, ALARM_RELATION_PREFIX + status.getAckSearchStatus().name(), RelationTypeGroup.ALARM));
377 377 } catch (ExecutionException | InterruptedException e) {
378 378 log.warn("[{}] Failed to delete relation. Status: [{}]", alarmId, status);
379 379 throw new RuntimeException(e);
380 380 }
381 381 }
382 382
383   - private void updateAlarmRelation(EntityId entityId, EntityId alarmId, AlarmStatus oldStatus, AlarmStatus newStatus) {
384   - deleteAlarmRelation(entityId, alarmId, oldStatus);
385   - createAlarmRelation(entityId, alarmId, newStatus, false);
  383 + private void updateAlarmRelation(TenantId tenantId, EntityId entityId, EntityId alarmId, AlarmStatus oldStatus, AlarmStatus newStatus) {
  384 + deleteAlarmRelation(tenantId, entityId, alarmId, oldStatus);
  385 + createAlarmRelation(tenantId, entityId, alarmId, newStatus, false);
386 386 }
387 387
388   - private <T> ListenableFuture<T> getAndUpdate(AlarmId alarmId, Function<Alarm, T> function) {
  388 + private <T> ListenableFuture<T> getAndUpdate(TenantId tenantId, AlarmId alarmId, Function<Alarm, T> function) {
389 389 validateId(alarmId, "Alarm id should be specified!");
390   - ListenableFuture<Alarm> entity = alarmDao.findAlarmByIdAsync(alarmId.getId());
  390 + ListenableFuture<Alarm> entity = alarmDao.findAlarmByIdAsync(tenantId, alarmId.getId());
391 391 return Futures.transform(entity, function, readResultsProcessingExecutor);
392 392 }
393 393
... ... @@ -395,7 +395,7 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ
395 395 new DataValidator<Alarm>() {
396 396
397 397 @Override
398   - protected void validateDataImpl(Alarm alarm) {
  398 + protected void validateDataImpl(TenantId tenantId, Alarm alarm) {
399 399 if (StringUtils.isEmpty(alarm.getType())) {
400 400 throw new DataValidationException("Alarm type should be specified!");
401 401 }
... ... @@ -411,7 +411,7 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ
411 411 if (alarm.getTenantId() == null) {
412 412 throw new DataValidationException("Alarm should be assigned to tenant!");
413 413 } else {
414   - Tenant tenant = tenantDao.findById(alarm.getTenantId().getId());
  414 + Tenant tenant = tenantDao.findById(alarm.getTenantId(), alarm.getTenantId().getId());
415 415 if (tenant == null) {
416 416 throw new DataValidationException("Alarm is referencing to non-existent tenant!");
417 417 }
... ...
... ... @@ -73,9 +73,9 @@ public class CassandraAlarmDao extends CassandraAbstractModelDao<AlarmEntity, Al
73 73 }
74 74
75 75 @Override
76   - public Alarm save(Alarm alarm) {
  76 + public Alarm save(TenantId tenantId, Alarm alarm) {
77 77 log.debug("Save asset [{}] ", alarm);
78   - return super.save(alarm);
  78 + return super.save(tenantId, alarm);
79 79 }
80 80
81 81 @Override
... ... @@ -88,11 +88,11 @@ public class CassandraAlarmDao extends CassandraAbstractModelDao<AlarmEntity, Al
88 88 query.and(eq(ALARM_TYPE_PROPERTY, type));
89 89 query.limit(1);
90 90 query.orderBy(QueryBuilder.asc(ModelConstants.ALARM_TYPE_PROPERTY), QueryBuilder.desc(ModelConstants.ID_PROPERTY));
91   - return findOneByStatementAsync(query);
  91 + return findOneByStatementAsync(tenantId, query);
92 92 }
93 93
94 94 @Override
95   - public ListenableFuture<List<AlarmInfo>> findAlarms(AlarmQuery query) {
  95 + public ListenableFuture<List<AlarmInfo>> findAlarms(TenantId tenantId, AlarmQuery query) {
96 96 log.trace("Try to find alarms by entity [{}], searchStatus [{}], status [{}] and pageLink [{}]", query.getAffectedEntityId(), query.getSearchStatus(), query.getStatus(), query.getPageLink());
97 97 EntityId affectedEntity = query.getAffectedEntityId();
98 98 String searchStatusName;
... ... @@ -104,12 +104,12 @@ public class CassandraAlarmDao extends CassandraAbstractModelDao<AlarmEntity, Al
104 104 searchStatusName = query.getStatus().name();
105 105 }
106 106 String relationType = BaseAlarmService.ALARM_RELATION_PREFIX + searchStatusName;
107   - ListenableFuture<List<EntityRelation>> relations = relationDao.findRelations(affectedEntity, relationType, RelationTypeGroup.ALARM, EntityType.ALARM, query.getPageLink());
  107 + ListenableFuture<List<EntityRelation>> relations = relationDao.findRelations(tenantId, affectedEntity, relationType, RelationTypeGroup.ALARM, EntityType.ALARM, query.getPageLink());
108 108 return Futures.transformAsync(relations, input -> {
109 109 List<ListenableFuture<AlarmInfo>> alarmFutures = new ArrayList<>(input.size());
110 110 for (EntityRelation relation : input) {
111 111 alarmFutures.add(Futures.transform(
112   - findAlarmByIdAsync(relation.getTo().getId()),
  112 + findAlarmByIdAsync(tenantId, relation.getTo().getId()),
113 113 AlarmInfo::new));
114 114 }
115 115 return Futures.successfulAsList(alarmFutures);
... ... @@ -117,11 +117,11 @@ public class CassandraAlarmDao extends CassandraAbstractModelDao<AlarmEntity, Al
117 117 }
118 118
119 119 @Override
120   - public ListenableFuture<Alarm> findAlarmByIdAsync(UUID key) {
  120 + public ListenableFuture<Alarm> findAlarmByIdAsync(TenantId tenantId, UUID key) {
121 121 log.debug("Get alarm by id {}", key);
122 122 Select.Where query = select().from(ALARM_BY_ID_VIEW_NAME).where(eq(ModelConstants.ID_PROPERTY, key));
123 123 query.limit(1);
124 124 log.trace("Execute query {}", query);
125   - return findOneByStatementAsync(query);
  125 + return findOneByStatementAsync(tenantId, query);
126 126 }
127 127 }
... ...
... ... @@ -18,6 +18,7 @@ package org.thingsboard.server.dao.asset;
18 18 import com.google.common.util.concurrent.ListenableFuture;
19 19 import org.thingsboard.server.common.data.EntitySubtype;
20 20 import org.thingsboard.server.common.data.asset.Asset;
  21 +import org.thingsboard.server.common.data.id.TenantId;
21 22 import org.thingsboard.server.common.data.page.TextPageLink;
22 23 import org.thingsboard.server.dao.Dao;
23 24
... ... @@ -37,7 +38,7 @@ public interface AssetDao extends Dao<Asset> {
37 38 * @param asset the asset object
38 39 * @return saved asset object
39 40 */
40   - Asset save(Asset asset);
  41 + Asset save(TenantId tenantId, Asset asset);
41 42
42 43 /**
43 44 * Find assets by tenantId and page link.
... ...
... ... @@ -30,19 +30,19 @@ import java.util.Optional;
30 30
31 31 public interface AssetService {
32 32
33   - Asset findAssetById(AssetId assetId);
  33 + Asset findAssetById(TenantId tenantId, AssetId assetId);
34 34
35   - ListenableFuture<Asset> findAssetByIdAsync(AssetId assetId);
  35 + ListenableFuture<Asset> findAssetByIdAsync(TenantId tenantId, AssetId assetId);
36 36
37 37 Asset findAssetByTenantIdAndName(TenantId tenantId, String name);
38 38
39 39 Asset saveAsset(Asset asset);
40 40
41   - Asset assignAssetToCustomer(AssetId assetId, CustomerId customerId);
  41 + Asset assignAssetToCustomer(TenantId tenantId, AssetId assetId, CustomerId customerId);
42 42
43   - Asset unassignAssetFromCustomer(AssetId assetId);
  43 + Asset unassignAssetFromCustomer(TenantId tenantId, AssetId assetId);
44 44
45   - void deleteAsset(AssetId assetId);
  45 + void deleteAsset(TenantId tenantId, AssetId assetId);
46 46
47 47 TextPageData<Asset> findAssetsByTenantId(TenantId tenantId, TextPageLink pageLink);
48 48
... ... @@ -60,7 +60,7 @@ public interface AssetService {
60 60
61 61 void unassignCustomerAssets(TenantId tenantId, CustomerId customerId);
62 62
63   - ListenableFuture<List<Asset>> findAssetsByQuery(AssetSearchQuery query);
  63 + ListenableFuture<List<Asset>> findAssetsByQuery(TenantId tenantId, AssetSearchQuery query);
64 64
65 65 ListenableFuture<List<EntitySubtype>> findAssetTypesByTenantId(TenantId tenantId);
66 66 }
... ...
... ... @@ -86,17 +86,17 @@ public class BaseAssetService extends AbstractEntityService implements AssetServ
86 86 private CacheManager cacheManager;
87 87
88 88 @Override
89   - public Asset findAssetById(AssetId assetId) {
  89 + public Asset findAssetById(TenantId tenantId, AssetId assetId) {
90 90 log.trace("Executing findAssetById [{}]", assetId);
91 91 validateId(assetId, INCORRECT_ASSET_ID + assetId);
92   - return assetDao.findById(assetId.getId());
  92 + return assetDao.findById(tenantId, assetId.getId());
93 93 }
94 94
95 95 @Override
96   - public ListenableFuture<Asset> findAssetByIdAsync(AssetId assetId) {
  96 + public ListenableFuture<Asset> findAssetByIdAsync(TenantId tenantId, AssetId assetId) {
97 97 log.trace("Executing findAssetById [{}]", assetId);
98 98 validateId(assetId, INCORRECT_ASSET_ID + assetId);
99   - return assetDao.findByIdAsync(assetId.getId());
  99 + return assetDao.findByIdAsync(tenantId, assetId.getId());
100 100 }
101 101
102 102 @Cacheable(cacheNames = ASSET_CACHE, key = "{#tenantId, #name}")
... ... @@ -112,31 +112,31 @@ public class BaseAssetService extends AbstractEntityService implements AssetServ
112 112 @Override
113 113 public Asset saveAsset(Asset asset) {
114 114 log.trace("Executing saveAsset [{}]", asset);
115   - assetValidator.validate(asset);
116   - return assetDao.save(asset);
  115 + assetValidator.validate(asset, Asset::getTenantId);
  116 + return assetDao.save(asset.getTenantId(), asset);
117 117 }
118 118
119 119 @Override
120   - public Asset assignAssetToCustomer(AssetId assetId, CustomerId customerId) {
121   - Asset asset = findAssetById(assetId);
  120 + public Asset assignAssetToCustomer(TenantId tenantId, AssetId assetId, CustomerId customerId) {
  121 + Asset asset = findAssetById(tenantId, assetId);
122 122 asset.setCustomerId(customerId);
123 123 return saveAsset(asset);
124 124 }
125 125
126 126 @Override
127   - public Asset unassignAssetFromCustomer(AssetId assetId) {
128   - Asset asset = findAssetById(assetId);
  127 + public Asset unassignAssetFromCustomer(TenantId tenantId, AssetId assetId) {
  128 + Asset asset = findAssetById(tenantId, assetId);
129 129 asset.setCustomerId(null);
130 130 return saveAsset(asset);
131 131 }
132 132
133 133 @Override
134   - public void deleteAsset(AssetId assetId) {
  134 + public void deleteAsset(TenantId tenantId, AssetId assetId) {
135 135 log.trace("Executing deleteAsset [{}]", assetId);
136 136 validateId(assetId, INCORRECT_ASSET_ID + assetId);
137   - deleteEntityRelations(assetId);
  137 + deleteEntityRelations(tenantId, assetId);
138 138
139   - Asset asset = assetDao.findById(assetId.getId());
  139 + Asset asset = assetDao.findById(tenantId, assetId.getId());
140 140 try {
141 141 List<EntityView> entityViews = entityViewService.findEntityViewsByTenantIdAndEntityIdAsync(asset.getTenantId(), assetId).get();
142 142 if (entityViews != null && !entityViews.isEmpty()) {
... ... @@ -153,7 +153,7 @@ public class BaseAssetService extends AbstractEntityService implements AssetServ
153 153 Cache cache = cacheManager.getCache(ASSET_CACHE);
154 154 cache.evict(list);
155 155
156   - assetDao.removeById(assetId.getId());
  156 + assetDao.removeById(tenantId, assetId.getId());
157 157 }
158 158
159 159 @Override
... ... @@ -187,7 +187,7 @@ public class BaseAssetService extends AbstractEntityService implements AssetServ
187 187 public void deleteAssetsByTenantId(TenantId tenantId) {
188 188 log.trace("Executing deleteAssetsByTenantId, tenantId [{}]", tenantId);
189 189 validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
190   - tenantAssetsRemover.removeEntities(tenantId);
  190 + tenantAssetsRemover.removeEntities(tenantId, tenantId);
191 191 }
192 192
193 193 @Override
... ... @@ -225,24 +225,24 @@ public class BaseAssetService extends AbstractEntityService implements AssetServ
225 225 log.trace("Executing unassignCustomerAssets, tenantId [{}], customerId [{}]", tenantId, customerId);
226 226 validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
227 227 validateId(customerId, INCORRECT_CUSTOMER_ID + customerId);
228   - new CustomerAssetsUnassigner(tenantId).removeEntities(customerId);
  228 + customerAssetsUnasigner.removeEntities(tenantId, customerId);
229 229 }
230 230
231 231 @Override
232   - public ListenableFuture<List<Asset>> findAssetsByQuery(AssetSearchQuery query) {
233   - ListenableFuture<List<EntityRelation>> relations = relationService.findByQuery(query.toEntitySearchQuery());
  232 + public ListenableFuture<List<Asset>> findAssetsByQuery(TenantId tenantId, AssetSearchQuery query) {
  233 + ListenableFuture<List<EntityRelation>> relations = relationService.findByQuery(tenantId, query.toEntitySearchQuery());
234 234 ListenableFuture<List<Asset>> assets = Futures.transformAsync(relations, r -> {
235 235 EntitySearchDirection direction = query.toEntitySearchQuery().getParameters().getDirection();
236 236 List<ListenableFuture<Asset>> futures = new ArrayList<>();
237 237 for (EntityRelation relation : r) {
238 238 EntityId entityId = direction == EntitySearchDirection.FROM ? relation.getTo() : relation.getFrom();
239 239 if (entityId.getEntityType() == EntityType.ASSET) {
240   - futures.add(findAssetByIdAsync(new AssetId(entityId.getId())));
  240 + futures.add(findAssetByIdAsync(tenantId, new AssetId(entityId.getId())));
241 241 }
242 242 }
243 243 return Futures.successfulAsList(futures);
244 244 });
245   - assets = Futures.transform(assets, (Function<List<Asset>, List<Asset>>)assetList ->
  245 + assets = Futures.transform(assets, assetList ->
246 246 assetList == null ? Collections.emptyList() : assetList.stream().filter(asset -> query.getAssetTypes().contains(asset.getType())).collect(Collectors.toList())
247 247 );
248 248 return assets;
... ... @@ -254,7 +254,7 @@ public class BaseAssetService extends AbstractEntityService implements AssetServ
254 254 validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
255 255 ListenableFuture<List<EntitySubtype>> tenantAssetTypes = assetDao.findTenantAssetTypesAsync(tenantId.getId());
256 256 return Futures.transform(tenantAssetTypes,
257   - (Function<List<EntitySubtype>, List<EntitySubtype>>) assetTypes -> {
  257 + assetTypes -> {
258 258 assetTypes.sort(Comparator.comparing(EntitySubtype::getType));
259 259 return assetTypes;
260 260 });
... ... @@ -264,7 +264,7 @@ public class BaseAssetService extends AbstractEntityService implements AssetServ
264 264 new DataValidator<Asset>() {
265 265
266 266 @Override
267   - protected void validateCreate(Asset asset) {
  267 + protected void validateCreate(TenantId tenantId, Asset asset) {
268 268 assetDao.findAssetsByTenantIdAndName(asset.getTenantId().getId(), asset.getName()).ifPresent(
269 269 d -> {
270 270 throw new DataValidationException("Asset with such name already exists!");
... ... @@ -273,7 +273,7 @@ public class BaseAssetService extends AbstractEntityService implements AssetServ
273 273 }
274 274
275 275 @Override
276   - protected void validateUpdate(Asset asset) {
  276 + protected void validateUpdate(TenantId tenantId, Asset asset) {
277 277 assetDao.findAssetsByTenantIdAndName(asset.getTenantId().getId(), asset.getName()).ifPresent(
278 278 d -> {
279 279 if (!d.getId().equals(asset.getId())) {
... ... @@ -284,7 +284,7 @@ public class BaseAssetService extends AbstractEntityService implements AssetServ
284 284 }
285 285
286 286 @Override
287   - protected void validateDataImpl(Asset asset) {
  287 + protected void validateDataImpl(TenantId tenantId, Asset asset) {
288 288 if (StringUtils.isEmpty(asset.getType())) {
289 289 throw new DataValidationException("Asset type should be specified!");
290 290 }
... ... @@ -294,7 +294,7 @@ public class BaseAssetService extends AbstractEntityService implements AssetServ
294 294 if (asset.getTenantId() == null) {
295 295 throw new DataValidationException("Asset should be assigned to tenant!");
296 296 } else {
297   - Tenant tenant = tenantDao.findById(asset.getTenantId().getId());
  297 + Tenant tenant = tenantDao.findById(tenantId, asset.getTenantId().getId());
298 298 if (tenant == null) {
299 299 throw new DataValidationException("Asset is referencing to non-existent tenant!");
300 300 }
... ... @@ -302,7 +302,7 @@ public class BaseAssetService extends AbstractEntityService implements AssetServ
302 302 if (asset.getCustomerId() == null) {
303 303 asset.setCustomerId(new CustomerId(NULL_UUID));
304 304 } else if (!asset.getCustomerId().getId().equals(NULL_UUID)) {
305   - Customer customer = customerDao.findById(asset.getCustomerId().getId());
  305 + Customer customer = customerDao.findById(tenantId, asset.getCustomerId().getId());
306 306 if (customer == null) {
307 307 throw new DataValidationException("Can't assign asset to non-existent customer!");
308 308 }
... ... @@ -314,35 +314,29 @@ public class BaseAssetService extends AbstractEntityService implements AssetServ
314 314 };
315 315
316 316 private PaginatedRemover<TenantId, Asset> tenantAssetsRemover =
317   - new PaginatedRemover<TenantId, Asset>() {
  317 + new PaginatedRemover<TenantId, Asset>() {
318 318
319   - @Override
320   - protected List<Asset> findEntities(TenantId id, TextPageLink pageLink) {
321   - return assetDao.findAssetsByTenantId(id.getId(), pageLink);
322   - }
323   -
324   - @Override
325   - protected void removeEntity(Asset entity) {
326   - deleteAsset(new AssetId(entity.getId().getId()));
327   - }
328   - };
  319 + @Override
  320 + protected List<Asset> findEntities(TenantId tenantId, TenantId id, TextPageLink pageLink) {
  321 + return assetDao.findAssetsByTenantId(id.getId(), pageLink);
  322 + }
329 323
330   - class CustomerAssetsUnassigner extends PaginatedRemover<CustomerId, Asset> {
  324 + @Override
  325 + protected void removeEntity(TenantId tenantId, Asset entity) {
  326 + deleteAsset(tenantId, new AssetId(entity.getId().getId()));
  327 + }
  328 + };
331 329
332   - private TenantId tenantId;
333   -
334   - CustomerAssetsUnassigner(TenantId tenantId) {
335   - this.tenantId = tenantId;
336   - }
  330 + private PaginatedRemover<CustomerId, Asset> customerAssetsUnasigner = new PaginatedRemover<CustomerId, Asset>() {
337 331
338 332 @Override
339   - protected List<Asset> findEntities(CustomerId id, TextPageLink pageLink) {
  333 + protected List<Asset> findEntities(TenantId tenantId, CustomerId id, TextPageLink pageLink) {
340 334 return assetDao.findAssetsByTenantIdAndCustomerId(tenantId.getId(), id.getId(), pageLink);
341 335 }
342 336
343 337 @Override
344   - protected void removeEntity(Asset entity) {
345   - unassignAssetFromCustomer(new AssetId(entity.getId().getId()));
  338 + protected void removeEntity(TenantId tenantId, Asset entity) {
  339 + unassignAssetFromCustomer(tenantId, new AssetId(entity.getId().getId()));
346 340 }
347   - }
  341 + };
348 342 }
... ...
... ... @@ -28,6 +28,7 @@ import org.springframework.stereotype.Component;
28 28 import org.thingsboard.server.common.data.EntitySubtype;
29 29 import org.thingsboard.server.common.data.EntityType;
30 30 import org.thingsboard.server.common.data.asset.Asset;
  31 +import org.thingsboard.server.common.data.id.TenantId;
31 32 import org.thingsboard.server.common.data.page.TextPageLink;
32 33 import org.thingsboard.server.dao.DaoUtil;
33 34 import org.thingsboard.server.dao.model.EntitySubtypeEntity;
... ... @@ -77,19 +78,19 @@ public class CassandraAssetDao extends CassandraAbstractSearchTextDao<AssetEntit
77 78 }
78 79
79 80 @Override
80   - public Asset save(Asset domain) {
81   - Asset savedAsset = super.save(domain);
  81 + public Asset save(TenantId tenantId, Asset domain) {
  82 + Asset savedAsset = super.save(tenantId, domain);
82 83 EntitySubtype entitySubtype = new EntitySubtype(savedAsset.getTenantId(), EntityType.ASSET, savedAsset.getType());
83 84 EntitySubtypeEntity entitySubtypeEntity = new EntitySubtypeEntity(entitySubtype);
84 85 Statement saveStatement = cluster.getMapper(EntitySubtypeEntity.class).saveQuery(entitySubtypeEntity);
85   - executeWrite(saveStatement);
  86 + executeWrite(tenantId, saveStatement);
86 87 return savedAsset;
87 88 }
88 89
89 90 @Override
90 91 public List<Asset> findAssetsByTenantId(UUID tenantId, TextPageLink pageLink) {
91 92 log.debug("Try to find assets by tenantId [{}] and pageLink [{}]", tenantId, pageLink);
92   - List<AssetEntity> assetEntities = findPageWithTextSearch(ASSET_BY_TENANT_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME,
  93 + List<AssetEntity> assetEntities = findPageWithTextSearch(new TenantId(tenantId), ASSET_BY_TENANT_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME,
93 94 Collections.singletonList(eq(ASSET_TENANT_ID_PROPERTY, tenantId)), pageLink);
94 95
95 96 log.trace("Found assets [{}] by tenantId [{}] and pageLink [{}]", assetEntities, tenantId, pageLink);
... ... @@ -99,7 +100,7 @@ public class CassandraAssetDao extends CassandraAbstractSearchTextDao<AssetEntit
99 100 @Override
100 101 public List<Asset> findAssetsByTenantIdAndType(UUID tenantId, String type, TextPageLink pageLink) {
101 102 log.debug("Try to find assets by tenantId [{}], type [{}] and pageLink [{}]", tenantId, type, pageLink);
102   - List<AssetEntity> assetEntities = findPageWithTextSearch(ASSET_BY_TENANT_BY_TYPE_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME,
  103 + List<AssetEntity> assetEntities = findPageWithTextSearch(new TenantId(tenantId), ASSET_BY_TENANT_BY_TYPE_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME,
103 104 Arrays.asList(eq(ASSET_TYPE_PROPERTY, type),
104 105 eq(ASSET_TENANT_ID_PROPERTY, tenantId)), pageLink);
105 106 log.trace("Found assets [{}] by tenantId [{}], type [{}] and pageLink [{}]", assetEntities, tenantId, type, pageLink);
... ... @@ -112,13 +113,13 @@ public class CassandraAssetDao extends CassandraAbstractSearchTextDao<AssetEntit
112 113 Select.Where query = select.where();
113 114 query.and(eq(ASSET_TENANT_ID_PROPERTY, tenantId));
114 115 query.and(in(ID_PROPERTY, assetIds));
115   - return findListByStatementAsync(query);
  116 + return findListByStatementAsync(new TenantId(tenantId), query);
116 117 }
117 118
118 119 @Override
119 120 public List<Asset> findAssetsByTenantIdAndCustomerId(UUID tenantId, UUID customerId, TextPageLink pageLink) {
120 121 log.debug("Try to find assets by tenantId [{}], customerId[{}] and pageLink [{}]", tenantId, customerId, pageLink);
121   - List<AssetEntity> assetEntities = findPageWithTextSearch(ASSET_BY_CUSTOMER_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME,
  122 + List<AssetEntity> assetEntities = findPageWithTextSearch(new TenantId(tenantId), ASSET_BY_CUSTOMER_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME,
122 123 Arrays.asList(eq(ASSET_CUSTOMER_ID_PROPERTY, customerId),
123 124 eq(ASSET_TENANT_ID_PROPERTY, tenantId)),
124 125 pageLink);
... ... @@ -130,7 +131,7 @@ public class CassandraAssetDao extends CassandraAbstractSearchTextDao<AssetEntit
130 131 @Override
131 132 public List<Asset> findAssetsByTenantIdAndCustomerIdAndType(UUID tenantId, UUID customerId, String type, TextPageLink pageLink) {
132 133 log.debug("Try to find assets by tenantId [{}], customerId [{}], type [{}] and pageLink [{}]", tenantId, customerId, type, pageLink);
133   - List<AssetEntity> assetEntities = findPageWithTextSearch(ASSET_BY_CUSTOMER_BY_TYPE_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME,
  134 + List<AssetEntity> assetEntities = findPageWithTextSearch(new TenantId(tenantId), ASSET_BY_CUSTOMER_BY_TYPE_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME,
134 135 Arrays.asList(eq(ASSET_TYPE_PROPERTY, type),
135 136 eq(ASSET_CUSTOMER_ID_PROPERTY, customerId),
136 137 eq(ASSET_TENANT_ID_PROPERTY, tenantId)),
... ... @@ -148,7 +149,7 @@ public class CassandraAssetDao extends CassandraAbstractSearchTextDao<AssetEntit
148 149 query.and(eq(ASSET_TENANT_ID_PROPERTY, tenantId));
149 150 query.and(eq(ASSET_CUSTOMER_ID_PROPERTY, customerId));
150 151 query.and(in(ID_PROPERTY, assetIds));
151   - return findListByStatementAsync(query);
  152 + return findListByStatementAsync(new TenantId(tenantId), query);
152 153 }
153 154
154 155 @Override
... ... @@ -157,7 +158,7 @@ public class CassandraAssetDao extends CassandraAbstractSearchTextDao<AssetEntit
157 158 Select.Where query = select.where();
158 159 query.and(eq(ASSET_TENANT_ID_PROPERTY, tenantId));
159 160 query.and(eq(ASSET_NAME_PROPERTY, assetName));
160   - AssetEntity assetEntity = (AssetEntity) findOneByStatement(query);
  161 + AssetEntity assetEntity = (AssetEntity) findOneByStatement(new TenantId(tenantId), query);
161 162 return Optional.ofNullable(DaoUtil.getData(assetEntity));
162 163 }
163 164
... ... @@ -168,7 +169,7 @@ public class CassandraAssetDao extends CassandraAbstractSearchTextDao<AssetEntit
168 169 query.and(eq(ENTITY_SUBTYPE_TENANT_ID_PROPERTY, tenantId));
169 170 query.and(eq(ENTITY_SUBTYPE_ENTITY_TYPE_PROPERTY, EntityType.ASSET));
170 171 query.setConsistencyLevel(cluster.getDefaultReadConsistencyLevel());
171   - ResultSetFuture resultSetFuture = executeAsyncRead(query);
  172 + ResultSetFuture resultSetFuture = executeAsyncRead(new TenantId(tenantId), query);
172 173 return Futures.transform(resultSetFuture, new Function<ResultSet, List<EntitySubtype>>() {
173 174 @Nullable
174 175 @Override
... ...
... ... @@ -17,6 +17,7 @@ package org.thingsboard.server.dao.attributes;
17 17
18 18 import com.google.common.util.concurrent.ListenableFuture;
19 19 import org.thingsboard.server.common.data.id.EntityId;
  20 +import org.thingsboard.server.common.data.id.TenantId;
20 21 import org.thingsboard.server.common.data.kv.AttributeKvEntry;
21 22
22 23 import java.util.Collection;
... ... @@ -28,13 +29,13 @@ import java.util.Optional;
28 29 */
29 30 public interface AttributesDao {
30 31
31   - ListenableFuture<Optional<AttributeKvEntry>> find(EntityId entityId, String attributeType, String attributeKey);
  32 + ListenableFuture<Optional<AttributeKvEntry>> find(TenantId tenantId, EntityId entityId, String attributeType, String attributeKey);
32 33
33   - ListenableFuture<List<AttributeKvEntry>> find(EntityId entityId, String attributeType, Collection<String> attributeKey);
  34 + ListenableFuture<List<AttributeKvEntry>> find(TenantId tenantId, EntityId entityId, String attributeType, Collection<String> attributeKey);
34 35
35   - ListenableFuture<List<AttributeKvEntry>> findAll(EntityId entityId, String attributeType);
  36 + ListenableFuture<List<AttributeKvEntry>> findAll(TenantId tenantId, EntityId entityId, String attributeType);
36 37
37   - ListenableFuture<Void> save(EntityId entityId, String attributeType, AttributeKvEntry attribute);
  38 + ListenableFuture<Void> save(TenantId tenantId, EntityId entityId, String attributeType, AttributeKvEntry attribute);
38 39
39   - ListenableFuture<List<Void>> removeAll(EntityId entityId, String attributeType, List<String> keys);
  40 + ListenableFuture<List<Void>> removeAll(TenantId tenantId, EntityId entityId, String attributeType, List<String> keys);
40 41 }
... ...
... ... @@ -17,6 +17,7 @@ package org.thingsboard.server.dao.attributes;
17 17
18 18 import com.google.common.util.concurrent.ListenableFuture;
19 19 import org.thingsboard.server.common.data.id.EntityId;
  20 +import org.thingsboard.server.common.data.id.TenantId;
20 21 import org.thingsboard.server.common.data.kv.AttributeKvEntry;
21 22
22 23 import java.util.Collection;
... ... @@ -28,13 +29,13 @@ import java.util.Optional;
28 29 */
29 30 public interface AttributesService {
30 31
31   - ListenableFuture<Optional<AttributeKvEntry>> find(EntityId entityId, String scope, String attributeKey);
  32 + ListenableFuture<Optional<AttributeKvEntry>> find(TenantId tenantId, EntityId entityId, String scope, String attributeKey);
32 33
33   - ListenableFuture<List<AttributeKvEntry>> find(EntityId entityId, String scope, Collection<String> attributeKeys);
  34 + ListenableFuture<List<AttributeKvEntry>> find(TenantId tenantId, EntityId entityId, String scope, Collection<String> attributeKeys);
34 35
35   - ListenableFuture<List<AttributeKvEntry>> findAll(EntityId entityId, String scope);
  36 + ListenableFuture<List<AttributeKvEntry>> findAll(TenantId tenantId, EntityId entityId, String scope);
36 37
37   - ListenableFuture<List<Void>> save(EntityId entityId, String scope, List<AttributeKvEntry> attributes);
  38 + ListenableFuture<List<Void>> save(TenantId tenantId, EntityId entityId, String scope, List<AttributeKvEntry> attributes);
38 39
39   - ListenableFuture<List<Void>> removeAll(EntityId entityId, String scope, List<String> attributeKeys);
  40 + ListenableFuture<List<Void>> removeAll(TenantId tenantId, EntityId entityId, String scope, List<String> attributeKeys);
40 41 }
... ...
... ... @@ -21,6 +21,7 @@ import com.google.common.util.concurrent.ListenableFuture;
21 21 import org.springframework.beans.factory.annotation.Autowired;
22 22 import org.springframework.stereotype.Service;
23 23 import org.thingsboard.server.common.data.id.EntityId;
  24 +import org.thingsboard.server.common.data.id.TenantId;
24 25 import org.thingsboard.server.common.data.kv.AttributeKvEntry;
25 26 import org.thingsboard.server.dao.exception.IncorrectParameterException;
26 27 import org.thingsboard.server.dao.service.Validator;
... ... @@ -39,40 +40,40 @@ public class BaseAttributesService implements AttributesService {
39 40 private AttributesDao attributesDao;
40 41
41 42 @Override
42   - public ListenableFuture<Optional<AttributeKvEntry>> find(EntityId entityId, String scope, String attributeKey) {
  43 + public ListenableFuture<Optional<AttributeKvEntry>> find(TenantId tenantId, EntityId entityId, String scope, String attributeKey) {
43 44 validate(entityId, scope);
44 45 Validator.validateString(attributeKey, "Incorrect attribute key " + attributeKey);
45   - return attributesDao.find(entityId, scope, attributeKey);
  46 + return attributesDao.find(tenantId, entityId, scope, attributeKey);
46 47 }
47 48
48 49 @Override
49   - public ListenableFuture<List<AttributeKvEntry>> find(EntityId entityId, String scope, Collection<String> attributeKeys) {
  50 + public ListenableFuture<List<AttributeKvEntry>> find(TenantId tenantId, EntityId entityId, String scope, Collection<String> attributeKeys) {
50 51 validate(entityId, scope);
51 52 attributeKeys.forEach(attributeKey -> Validator.validateString(attributeKey, "Incorrect attribute key " + attributeKey));
52   - return attributesDao.find(entityId, scope, attributeKeys);
  53 + return attributesDao.find(tenantId, entityId, scope, attributeKeys);
53 54 }
54 55
55 56 @Override
56   - public ListenableFuture<List<AttributeKvEntry>> findAll(EntityId entityId, String scope) {
  57 + public ListenableFuture<List<AttributeKvEntry>> findAll(TenantId tenantId, EntityId entityId, String scope) {
57 58 validate(entityId, scope);
58   - return attributesDao.findAll(entityId, scope);
  59 + return attributesDao.findAll(tenantId, entityId, scope);
59 60 }
60 61
61 62 @Override
62   - public ListenableFuture<List<Void>> save(EntityId entityId, String scope, List<AttributeKvEntry> attributes) {
  63 + public ListenableFuture<List<Void>> save(TenantId tenantId, EntityId entityId, String scope, List<AttributeKvEntry> attributes) {
63 64 validate(entityId, scope);
64 65 attributes.forEach(attribute -> validate(attribute));
65 66 List<ListenableFuture<Void>> futures = Lists.newArrayListWithExpectedSize(attributes.size());
66 67 for (AttributeKvEntry attribute : attributes) {
67   - futures.add(attributesDao.save(entityId, scope, attribute));
  68 + futures.add(attributesDao.save(tenantId, entityId, scope, attribute));
68 69 }
69 70 return Futures.allAsList(futures);
70 71 }
71 72
72 73 @Override
73   - public ListenableFuture<List<Void>> removeAll(EntityId entityId, String scope, List<String> keys) {
  74 + public ListenableFuture<List<Void>> removeAll(TenantId tenantId, EntityId entityId, String scope, List<String> keys) {
74 75 validate(entityId, scope);
75   - return attributesDao.removeAll(entityId, scope, keys);
  76 + return attributesDao.removeAll(tenantId, entityId, scope, keys);
76 77 }
77 78
78 79 private static void validate(EntityId id, String scope) {
... ...
... ... @@ -28,6 +28,7 @@ import com.google.common.util.concurrent.ListenableFuture;
28 28 import lombok.extern.slf4j.Slf4j;
29 29 import org.springframework.stereotype.Component;
30 30 import org.thingsboard.server.common.data.id.EntityId;
  31 +import org.thingsboard.server.common.data.id.TenantId;
31 32 import org.thingsboard.server.common.data.kv.AttributeKvEntry;
32 33 import org.thingsboard.server.common.data.kv.BaseAttributeKvEntry;
33 34 import org.thingsboard.server.dao.model.ModelConstants;
... ... @@ -73,22 +74,22 @@ public class CassandraBaseAttributesDao extends CassandraAbstractAsyncDao implem
73 74 }
74 75
75 76 @Override
76   - public ListenableFuture<Optional<AttributeKvEntry>> find(EntityId entityId, String attributeType, String attributeKey) {
  77 + public ListenableFuture<Optional<AttributeKvEntry>> find(TenantId tenantId, EntityId entityId, String attributeType, String attributeKey) {
77 78 Select.Where select = select().from(ATTRIBUTES_KV_CF)
78 79 .where(eq(ENTITY_TYPE_COLUMN, entityId.getEntityType()))
79 80 .and(eq(ENTITY_ID_COLUMN, entityId.getId()))
80 81 .and(eq(ATTRIBUTE_TYPE_COLUMN, attributeType))
81 82 .and(eq(ATTRIBUTE_KEY_COLUMN, attributeKey));
82 83 log.trace("Generated query [{}] for entityId {} and key {}", select, entityId, attributeKey);
83   - return Futures.transform(executeAsyncRead(select), (Function<? super ResultSet, ? extends Optional<AttributeKvEntry>>) input ->
  84 + return Futures.transform(executeAsyncRead(tenantId, select), (Function<? super ResultSet, ? extends Optional<AttributeKvEntry>>) input ->
84 85 Optional.ofNullable(convertResultToAttributesKvEntry(attributeKey, input.one()))
85 86 , readResultsProcessingExecutor);
86 87 }
87 88
88 89 @Override
89   - public ListenableFuture<List<AttributeKvEntry>> find(EntityId entityId, String attributeType, Collection<String> attributeKeys) {
  90 + public ListenableFuture<List<AttributeKvEntry>> find(TenantId tenantId, EntityId entityId, String attributeType, Collection<String> attributeKeys) {
90 91 List<ListenableFuture<Optional<AttributeKvEntry>>> entries = new ArrayList<>();
91   - attributeKeys.forEach(attributeKey -> entries.add(find(entityId, attributeType, attributeKey)));
  92 + attributeKeys.forEach(attributeKey -> entries.add(find(tenantId, entityId, attributeType, attributeKey)));
92 93 return Futures.transform(Futures.allAsList(entries), (Function<List<Optional<AttributeKvEntry>>, ? extends List<AttributeKvEntry>>) input -> {
93 94 List<AttributeKvEntry> result = new ArrayList<>();
94 95 input.stream().filter(opt -> opt.isPresent()).forEach(opt -> result.add(opt.get()));
... ... @@ -98,19 +99,19 @@ public class CassandraBaseAttributesDao extends CassandraAbstractAsyncDao implem
98 99
99 100
100 101 @Override
101   - public ListenableFuture<List<AttributeKvEntry>> findAll(EntityId entityId, String attributeType) {
  102 + public ListenableFuture<List<AttributeKvEntry>> findAll(TenantId tenantId, EntityId entityId, String attributeType) {
102 103 Select.Where select = select().from(ATTRIBUTES_KV_CF)
103 104 .where(eq(ENTITY_TYPE_COLUMN, entityId.getEntityType()))
104 105 .and(eq(ENTITY_ID_COLUMN, entityId.getId()))
105 106 .and(eq(ATTRIBUTE_TYPE_COLUMN, attributeType));
106 107 log.trace("Generated query [{}] for entityId {} and attributeType {}", select, entityId, attributeType);
107   - return Futures.transform(executeAsyncRead(select), (Function<? super ResultSet, ? extends List<AttributeKvEntry>>) input ->
  108 + return Futures.transform(executeAsyncRead(tenantId, select), (Function<? super ResultSet, ? extends List<AttributeKvEntry>>) input ->
108 109 convertResultToAttributesKvEntryList(input)
109 110 , readResultsProcessingExecutor);
110 111 }
111 112
112 113 @Override
113   - public ListenableFuture<Void> save(EntityId entityId, String attributeType, AttributeKvEntry attribute) {
  114 + public ListenableFuture<Void> save(TenantId tenantId, EntityId entityId, String attributeType, AttributeKvEntry attribute) {
114 115 BoundStatement stmt = getSaveStmt().bind();
115 116 stmt.setString(0, entityId.getEntityType().name());
116 117 stmt.setUUID(1, entityId.getId());
... ... @@ -137,26 +138,26 @@ public class CassandraBaseAttributesDao extends CassandraAbstractAsyncDao implem
137 138 stmt.setToNull(8);
138 139 }
139 140 log.trace("Generated save stmt [{}] for entityId {} and attributeType {} and attribute", stmt, entityId, attributeType, attribute);
140   - return getFuture(executeAsyncWrite(stmt), rs -> null);
  141 + return getFuture(executeAsyncWrite(tenantId, stmt), rs -> null);
141 142 }
142 143
143 144 @Override
144   - public ListenableFuture<List<Void>> removeAll(EntityId entityId, String attributeType, List<String> keys) {
  145 + public ListenableFuture<List<Void>> removeAll(TenantId tenantId, EntityId entityId, String attributeType, List<String> keys) {
145 146 List<ListenableFuture<Void>> futures = keys
146 147 .stream()
147   - .map(key -> delete(entityId, attributeType, key))
  148 + .map(key -> delete(tenantId, entityId, attributeType, key))
148 149 .collect(Collectors.toList());
149 150 return Futures.allAsList(futures);
150 151 }
151 152
152   - private ListenableFuture<Void> delete(EntityId entityId, String attributeType, String key) {
  153 + private ListenableFuture<Void> delete(TenantId tenantId, EntityId entityId, String attributeType, String key) {
153 154 Statement delete = QueryBuilder.delete().all().from(ModelConstants.ATTRIBUTES_KV_CF)
154 155 .where(eq(ENTITY_TYPE_COLUMN, entityId.getEntityType()))
155 156 .and(eq(ENTITY_ID_COLUMN, entityId.getId()))
156 157 .and(eq(ATTRIBUTE_TYPE_COLUMN, attributeType))
157 158 .and(eq(ATTRIBUTE_KEY_COLUMN, key));
158 159 log.debug("Remove request: {}", delete.toString());
159   - return getFuture(executeAsyncWrite(delete), rs -> null);
  160 + return getFuture(executeAsyncWrite(tenantId, delete), rs -> null);
160 161 }
161 162
162 163 private PreparedStatement getSaveStmt() {
... ...
... ... @@ -128,7 +128,7 @@ public class AuditLogServiceImpl implements AuditLogService {
128 128 entityName = entity.getName();
129 129 } else {
130 130 try {
131   - entityName = entityService.fetchEntityNameAsync(entityId).get();
  131 + entityName = entityService.fetchEntityNameAsync(tenantId, entityId).get();
132 132 } catch (Exception ex) {}
133 133 }
134 134 if (e != null) {
... ... @@ -315,7 +315,7 @@ public class AuditLogServiceImpl implements AuditLogService {
315 315 AuditLog auditLogEntry = createAuditLogEntry(tenantId, entityId, entityName, customerId, userId, userName,
316 316 actionType, actionData, actionStatus, actionFailureDetails);
317 317 log.trace("Executing logAction [{}]", auditLogEntry);
318   - auditLogValidator.validate(auditLogEntry);
  318 + auditLogValidator.validate(auditLogEntry, AuditLog::getTenantId);
319 319 List<ListenableFuture<Void>> futures = Lists.newArrayListWithExpectedSize(INSERTS_PER_ENTRY);
320 320 futures.add(auditLogDao.savePartitionsByTenantId(auditLogEntry));
321 321 futures.add(auditLogDao.saveByTenantId(auditLogEntry));
... ... @@ -331,7 +331,7 @@ public class AuditLogServiceImpl implements AuditLogService {
331 331 private DataValidator<AuditLog> auditLogValidator =
332 332 new DataValidator<AuditLog>() {
333 333 @Override
334   - protected void validateDataImpl(AuditLog auditLog) {
  334 + protected void validateDataImpl(TenantId tenantId, AuditLog auditLog) {
335 335 if (auditLog.getEntityId() == null) {
336 336 throw new DataValidationException("Entity Id should be specified!");
337 337 }
... ...
... ... @@ -32,6 +32,7 @@ import org.springframework.stereotype.Component;
32 32 import org.thingsboard.server.common.data.audit.AuditLog;
33 33 import org.thingsboard.server.common.data.id.CustomerId;
34 34 import org.thingsboard.server.common.data.id.EntityId;
  35 +import org.thingsboard.server.common.data.id.TenantId;
35 36 import org.thingsboard.server.common.data.id.UserId;
36 37 import org.thingsboard.server.common.data.page.TimePageLink;
37 38 import org.thingsboard.server.dao.DaoUtil;
... ... @@ -142,7 +143,7 @@ public class CassandraAuditLogDao extends CassandraAbstractSearchTimeDao<AuditLo
142 143 long partition = toPartitionTs(LocalDate.now().atStartOfDay().toInstant(ZoneOffset.UTC).toEpochMilli());
143 144 BoundStatement stmt = getSaveByTenantStmt().bind();
144 145 stmt = setSaveStmtVariables(stmt, auditLog, partition);
145   - return getFuture(executeAsyncWrite(stmt), rs -> null);
  146 + return getFuture(executeAsyncWrite(auditLog.getTenantId(), stmt), rs -> null);
146 147 }
147 148
148 149 @Override
... ... @@ -151,7 +152,7 @@ public class CassandraAuditLogDao extends CassandraAbstractSearchTimeDao<AuditLo
151 152
152 153 BoundStatement stmt = getSaveByTenantIdAndEntityIdStmt().bind();
153 154 stmt = setSaveStmtVariables(stmt, auditLog, -1);
154   - return getFuture(executeAsyncWrite(stmt), rs -> null);
  155 + return getFuture(executeAsyncWrite(auditLog.getTenantId(), stmt), rs -> null);
155 156 }
156 157
157 158 @Override
... ... @@ -160,7 +161,7 @@ public class CassandraAuditLogDao extends CassandraAbstractSearchTimeDao<AuditLo
160 161
161 162 BoundStatement stmt = getSaveByTenantIdAndCustomerIdStmt().bind();
162 163 stmt = setSaveStmtVariables(stmt, auditLog, -1);
163   - return getFuture(executeAsyncWrite(stmt), rs -> null);
  164 + return getFuture(executeAsyncWrite(auditLog.getTenantId(), stmt), rs -> null);
164 165 }
165 166
166 167 @Override
... ... @@ -169,11 +170,11 @@ public class CassandraAuditLogDao extends CassandraAbstractSearchTimeDao<AuditLo
169 170
170 171 BoundStatement stmt = getSaveByTenantIdAndUserIdStmt().bind();
171 172 stmt = setSaveStmtVariables(stmt, auditLog, -1);
172   - return getFuture(executeAsyncWrite(stmt), rs -> null);
  173 + return getFuture(executeAsyncWrite(auditLog.getTenantId(), stmt), rs -> null);
173 174 }
174 175
175 176 private BoundStatement setSaveStmtVariables(BoundStatement stmt, AuditLog auditLog, long partition) {
176   - stmt.setUUID(0, auditLog.getId().getId())
  177 + stmt.setUUID(0, auditLog.getId().getId())
177 178 .setUUID(1, auditLog.getTenantId().getId())
178 179 .setUUID(2, auditLog.getCustomerId().getId())
179 180 .setUUID(3, auditLog.getEntityId().getId())
... ... @@ -200,7 +201,7 @@ public class CassandraAuditLogDao extends CassandraAbstractSearchTimeDao<AuditLo
200 201 BoundStatement stmt = getPartitionInsertStmt().bind();
201 202 stmt = stmt.setUUID(0, auditLog.getTenantId().getId())
202 203 .setLong(1, partition);
203   - return getFuture(executeAsyncWrite(stmt), rs -> null);
  204 + return getFuture(executeAsyncWrite(auditLog.getTenantId(), stmt), rs -> null);
204 205 }
205 206
206 207 private PreparedStatement getSaveByTenantStmt() {
... ... @@ -249,7 +250,7 @@ public class CassandraAuditLogDao extends CassandraAbstractSearchTimeDao<AuditLo
249 250 columnsList.add(ModelConstants.AUDIT_LOG_PARTITION_PROPERTY);
250 251 }
251 252 StringJoiner values = new StringJoiner(",");
252   - for (int i=0;i<columnsList.size();i++) {
  253 + for (int i = 0; i < columnsList.size(); i++) {
253 254 values.add("?");
254 255 }
255 256 String statementString = INSERT_INTO + cfName + " (" + String.join(",", columnsList) + ") VALUES (" + values.toString() + ")";
... ... @@ -274,7 +275,7 @@ public class CassandraAuditLogDao extends CassandraAbstractSearchTimeDao<AuditLo
274 275 @Override
275 276 public List<AuditLog> findAuditLogsByTenantIdAndEntityId(UUID tenantId, EntityId entityId, TimePageLink pageLink) {
276 277 log.trace("Try to find audit logs by tenant [{}], entity [{}] and pageLink [{}]", tenantId, entityId, pageLink);
277   - List<AuditLogEntity> entities = findPageWithTimeSearch(AUDIT_LOG_BY_ENTITY_ID_CF,
  278 + List<AuditLogEntity> entities = findPageWithTimeSearch(new TenantId(tenantId), AUDIT_LOG_BY_ENTITY_ID_CF,
278 279 Arrays.asList(eq(ModelConstants.AUDIT_LOG_TENANT_ID_PROPERTY, tenantId),
279 280 eq(ModelConstants.AUDIT_LOG_ENTITY_TYPE_PROPERTY, entityId.getEntityType()),
280 281 eq(ModelConstants.AUDIT_LOG_ENTITY_ID_PROPERTY, entityId.getId())),
... ... @@ -286,7 +287,7 @@ public class CassandraAuditLogDao extends CassandraAbstractSearchTimeDao<AuditLo
286 287 @Override
287 288 public List<AuditLog> findAuditLogsByTenantIdAndCustomerId(UUID tenantId, CustomerId customerId, TimePageLink pageLink) {
288 289 log.trace("Try to find audit logs by tenant [{}], customer [{}] and pageLink [{}]", tenantId, customerId, pageLink);
289   - List<AuditLogEntity> entities = findPageWithTimeSearch(AUDIT_LOG_BY_CUSTOMER_ID_CF,
  290 + List<AuditLogEntity> entities = findPageWithTimeSearch(new TenantId(tenantId), AUDIT_LOG_BY_CUSTOMER_ID_CF,
290 291 Arrays.asList(eq(ModelConstants.AUDIT_LOG_TENANT_ID_PROPERTY, tenantId),
291 292 eq(ModelConstants.AUDIT_LOG_CUSTOMER_ID_PROPERTY, customerId.getId())),
292 293 pageLink);
... ... @@ -297,7 +298,7 @@ public class CassandraAuditLogDao extends CassandraAbstractSearchTimeDao<AuditLo
297 298 @Override
298 299 public List<AuditLog> findAuditLogsByTenantIdAndUserId(UUID tenantId, UserId userId, TimePageLink pageLink) {
299 300 log.trace("Try to find audit logs by tenant [{}], user [{}] and pageLink [{}]", tenantId, userId, pageLink);
300   - List<AuditLogEntity> entities = findPageWithTimeSearch(AUDIT_LOG_BY_USER_ID_CF,
  301 + List<AuditLogEntity> entities = findPageWithTimeSearch(new TenantId(tenantId), AUDIT_LOG_BY_USER_ID_CF,
301 302 Arrays.asList(eq(ModelConstants.AUDIT_LOG_TENANT_ID_PROPERTY, tenantId),
302 303 eq(ModelConstants.AUDIT_LOG_USER_ID_PROPERTY, userId.getId())),
303 304 pageLink);
... ... @@ -339,7 +340,7 @@ public class CassandraAuditLogDao extends CassandraAbstractSearchTimeDao<AuditLo
339 340 if (cursor.isFull() || !cursor.hasNextPartition()) {
340 341 return cursor.getData();
341 342 } else {
342   - cursor.addData(findPageWithTimeSearch(AUDIT_LOG_BY_TENANT_ID_CF,
  343 + cursor.addData(findPageWithTimeSearch(new TenantId(cursor.getTenantId()), AUDIT_LOG_BY_TENANT_ID_CF,
343 344 Arrays.asList(eq(ModelConstants.AUDIT_LOG_TENANT_ID_PROPERTY, cursor.getTenantId()),
344 345 eq(ModelConstants.AUDIT_LOG_PARTITION_PROPERTY, cursor.getNextPartition())),
345 346 cursor.getPageLink()));
... ... @@ -352,7 +353,7 @@ public class CassandraAuditLogDao extends CassandraAbstractSearchTimeDao<AuditLo
352 353 .where(eq(ModelConstants.AUDIT_LOG_TENANT_ID_PROPERTY, tenantId));
353 354 select.and(QueryBuilder.gte(ModelConstants.PARTITION_COLUMN, minPartition));
354 355 select.and(QueryBuilder.lte(ModelConstants.PARTITION_COLUMN, maxPartition));
355   - return executeRead(select);
  356 + return executeRead(new TenantId(tenantId), select);
356 357 }
357 358
358 359 }
... ...
... ... @@ -16,6 +16,7 @@
16 16 package org.thingsboard.server.dao.cache;
17 17
18 18 import org.springframework.cache.interceptor.KeyGenerator;
  19 +import org.thingsboard.server.common.data.id.TenantId;
19 20 import org.thingsboard.server.common.data.security.DeviceCredentials;
20 21 import org.thingsboard.server.dao.device.DeviceCredentialsService;
21 22
... ... @@ -28,9 +29,10 @@ public class PreviousDeviceCredentialsIdKeyGenerator implements KeyGenerator {
28 29 @Override
29 30 public Object generate(Object o, Method method, Object... objects) {
30 31 DeviceCredentialsService deviceCredentialsService = (DeviceCredentialsService) o;
31   - DeviceCredentials deviceCredentials = (DeviceCredentials) objects[0];
  32 + TenantId tenantId = (TenantId) objects[0];
  33 + DeviceCredentials deviceCredentials = (DeviceCredentials) objects[1];
32 34 if (deviceCredentials.getDeviceId() != null) {
33   - DeviceCredentials oldDeviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(deviceCredentials.getDeviceId());
  35 + DeviceCredentials oldDeviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(tenantId, deviceCredentials.getDeviceId());
34 36 if (oldDeviceCredentials != null) {
35 37 return oldDeviceCredentials.getCredentialsId();
36 38 }
... ...
... ... @@ -25,6 +25,8 @@ import org.apache.commons.lang3.StringUtils;
25 25 import org.springframework.beans.factory.annotation.Autowired;
26 26 import org.springframework.stereotype.Service;
27 27 import org.thingsboard.server.common.data.id.ComponentDescriptorId;
  28 +import org.thingsboard.server.common.data.id.EntityId;
  29 +import org.thingsboard.server.common.data.id.TenantId;
28 30 import org.thingsboard.server.common.data.page.TextPageData;
29 31 import org.thingsboard.server.common.data.page.TextPageLink;
30 32 import org.thingsboard.server.common.data.plugin.ComponentDescriptor;
... ... @@ -49,50 +51,50 @@ public class BaseComponentDescriptorService implements ComponentDescriptorServic
49 51 private ComponentDescriptorDao componentDescriptorDao;
50 52
51 53 @Override
52   - public ComponentDescriptor saveComponent(ComponentDescriptor component) {
53   - componentValidator.validate(component);
54   - Optional<ComponentDescriptor> result = componentDescriptorDao.saveIfNotExist(component);
  54 + public ComponentDescriptor saveComponent(TenantId tenantId, ComponentDescriptor component) {
  55 + componentValidator.validate(component, data -> new TenantId(EntityId.NULL_UUID));
  56 + Optional<ComponentDescriptor> result = componentDescriptorDao.saveIfNotExist(tenantId, component);
55 57 if (result.isPresent()) {
56 58 return result.get();
57 59 } else {
58   - return componentDescriptorDao.findByClazz(component.getClazz());
  60 + return componentDescriptorDao.findByClazz(tenantId, component.getClazz());
59 61 }
60 62 }
61 63
62 64 @Override
63   - public ComponentDescriptor findById(ComponentDescriptorId componentId) {
  65 + public ComponentDescriptor findById(TenantId tenantId, ComponentDescriptorId componentId) {
64 66 Validator.validateId(componentId, "Incorrect component id for search request.");
65   - return componentDescriptorDao.findById(componentId);
  67 + return componentDescriptorDao.findById(tenantId, componentId);
66 68 }
67 69
68 70 @Override
69   - public ComponentDescriptor findByClazz(String clazz) {
  71 + public ComponentDescriptor findByClazz(TenantId tenantId, String clazz) {
70 72 Validator.validateString(clazz, "Incorrect clazz for search request.");
71   - return componentDescriptorDao.findByClazz(clazz);
  73 + return componentDescriptorDao.findByClazz(tenantId, clazz);
72 74 }
73 75
74 76 @Override
75   - public TextPageData<ComponentDescriptor> findByTypeAndPageLink(ComponentType type, TextPageLink pageLink) {
  77 + public TextPageData<ComponentDescriptor> findByTypeAndPageLink(TenantId tenantId, ComponentType type, TextPageLink pageLink) {
76 78 Validator.validatePageLink(pageLink, "Incorrect PageLink object for search plugin components request.");
77   - List<ComponentDescriptor> components = componentDescriptorDao.findByTypeAndPageLink(type, pageLink);
  79 + List<ComponentDescriptor> components = componentDescriptorDao.findByTypeAndPageLink(tenantId, type, pageLink);
78 80 return new TextPageData<>(components, pageLink);
79 81 }
80 82
81 83 @Override
82   - public TextPageData<ComponentDescriptor> findByScopeAndTypeAndPageLink(ComponentScope scope, ComponentType type, TextPageLink pageLink) {
  84 + public TextPageData<ComponentDescriptor> findByScopeAndTypeAndPageLink(TenantId tenantId, ComponentScope scope, ComponentType type, TextPageLink pageLink) {
83 85 Validator.validatePageLink(pageLink, "Incorrect PageLink object for search plugin components request.");
84   - List<ComponentDescriptor> components = componentDescriptorDao.findByScopeAndTypeAndPageLink(scope, type, pageLink);
  86 + List<ComponentDescriptor> components = componentDescriptorDao.findByScopeAndTypeAndPageLink(tenantId, scope, type, pageLink);
85 87 return new TextPageData<>(components, pageLink);
86 88 }
87 89
88 90 @Override
89   - public void deleteByClazz(String clazz) {
  91 + public void deleteByClazz(TenantId tenantId, String clazz) {
90 92 Validator.validateString(clazz, "Incorrect clazz for delete request.");
91   - componentDescriptorDao.deleteByClazz(clazz);
  93 + componentDescriptorDao.deleteByClazz(tenantId, clazz);
92 94 }
93 95
94 96 @Override
95   - public boolean validate(ComponentDescriptor component, JsonNode configuration) {
  97 + public boolean validate(TenantId tenantId, ComponentDescriptor component, JsonNode configuration) {
96 98 JsonValidator validator = JsonSchemaFactory.byDefault().getValidator();
97 99 try {
98 100 if (!component.getConfigurationDescriptor().has("schema")) {
... ... @@ -109,7 +111,7 @@ public class BaseComponentDescriptorService implements ComponentDescriptorServic
109 111 private DataValidator<ComponentDescriptor> componentValidator =
110 112 new DataValidator<ComponentDescriptor>() {
111 113 @Override
112   - protected void validateDataImpl(ComponentDescriptor plugin) {
  114 + protected void validateDataImpl(TenantId tenantId, ComponentDescriptor plugin) {
113 115 if (plugin.getType() == null) {
114 116 throw new DataValidationException("Component type should be specified!.");
115 117 }
... ...
... ... @@ -23,6 +23,7 @@ import com.datastax.driver.core.utils.UUIDs;
23 23 import lombok.extern.slf4j.Slf4j;
24 24 import org.springframework.stereotype.Component;
25 25 import org.thingsboard.server.common.data.id.ComponentDescriptorId;
  26 +import org.thingsboard.server.common.data.id.TenantId;
26 27 import org.thingsboard.server.common.data.page.TextPageLink;
27 28 import org.thingsboard.server.common.data.plugin.ComponentDescriptor;
28 29 import org.thingsboard.server.common.data.plugin.ComponentScope;
... ... @@ -62,10 +63,10 @@ public class CassandraBaseComponentDescriptorDao extends CassandraAbstractSearch
62 63 }
63 64
64 65 @Override
65   - public Optional<ComponentDescriptor> saveIfNotExist(ComponentDescriptor component) {
  66 + public Optional<ComponentDescriptor> saveIfNotExist(TenantId tenantId, ComponentDescriptor component) {
66 67 ComponentDescriptorEntity entity = new ComponentDescriptorEntity(component);
67 68 log.debug("Save component entity [{}]", entity);
68   - Optional<ComponentDescriptor> result = saveIfNotExist(entity);
  69 + Optional<ComponentDescriptor> result = saveIfNotExist(tenantId, entity);
69 70 if (log.isTraceEnabled()) {
70 71 log.trace("Saved result: [{}] for component entity [{}]", result.isPresent(), result.orElse(null));
71 72 } else {
... ... @@ -75,9 +76,9 @@ public class CassandraBaseComponentDescriptorDao extends CassandraAbstractSearch
75 76 }
76 77
77 78 @Override
78   - public ComponentDescriptor findById(ComponentDescriptorId componentId) {
  79 + public ComponentDescriptor findById(TenantId tenantId, ComponentDescriptorId componentId) {
79 80 log.debug("Search component entity by id [{}]", componentId);
80   - ComponentDescriptor componentDescriptor = super.findById(componentId.getId());
  81 + ComponentDescriptor componentDescriptor = super.findById(tenantId, componentId.getId());
81 82 if (log.isTraceEnabled()) {
82 83 log.trace("Search result: [{}] for component entity [{}]", componentDescriptor != null, componentDescriptor);
83 84 } else {
... ... @@ -87,11 +88,11 @@ public class CassandraBaseComponentDescriptorDao extends CassandraAbstractSearch
87 88 }
88 89
89 90 @Override
90   - public ComponentDescriptor findByClazz(String clazz) {
  91 + public ComponentDescriptor findByClazz(TenantId tenantId, String clazz) {
91 92 log.debug("Search component entity by clazz [{}]", clazz);
92 93 Select.Where query = select().from(getColumnFamilyName()).where(eq(ModelConstants.COMPONENT_DESCRIPTOR_CLASS_PROPERTY, clazz));
93 94 log.trace("Execute query [{}]", query);
94   - ComponentDescriptorEntity entity = findOneByStatement(query);
  95 + ComponentDescriptorEntity entity = findOneByStatement(tenantId, query);
95 96 if (log.isTraceEnabled()) {
96 97 log.trace("Search result: [{}] for component entity [{}]", entity != null, entity);
97 98 } else {
... ... @@ -101,9 +102,9 @@ public class CassandraBaseComponentDescriptorDao extends CassandraAbstractSearch
101 102 }
102 103
103 104 @Override
104   - public List<ComponentDescriptor> findByTypeAndPageLink(ComponentType type, TextPageLink pageLink) {
  105 + public List<ComponentDescriptor> findByTypeAndPageLink(TenantId tenantId, ComponentType type, TextPageLink pageLink) {
105 106 log.debug("Try to find component by type [{}] and pageLink [{}]", type, pageLink);
106   - List<ComponentDescriptorEntity> entities = findPageWithTextSearch(ModelConstants.COMPONENT_DESCRIPTOR_BY_TYPE_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME,
  107 + List<ComponentDescriptorEntity> entities = findPageWithTextSearch(tenantId, ModelConstants.COMPONENT_DESCRIPTOR_BY_TYPE_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME,
107 108 Arrays.asList(eq(ModelConstants.COMPONENT_DESCRIPTOR_TYPE_PROPERTY, type)), pageLink);
108 109 if (log.isTraceEnabled()) {
109 110 log.trace(SEARCH_RESULT, Arrays.toString(entities.toArray()));
... ... @@ -114,9 +115,9 @@ public class CassandraBaseComponentDescriptorDao extends CassandraAbstractSearch
114 115 }
115 116
116 117 @Override
117   - public List<ComponentDescriptor> findByScopeAndTypeAndPageLink(ComponentScope scope, ComponentType type, TextPageLink pageLink) {
  118 + public List<ComponentDescriptor> findByScopeAndTypeAndPageLink(TenantId tenantId, ComponentScope scope, ComponentType type, TextPageLink pageLink) {
118 119 log.debug("Try to find component by scope [{}] and type [{}] and pageLink [{}]", scope, type, pageLink);
119   - List<ComponentDescriptorEntity> entities = findPageWithTextSearch(ModelConstants.COMPONENT_DESCRIPTOR_BY_SCOPE_TYPE_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME,
  120 + List<ComponentDescriptorEntity> entities = findPageWithTextSearch(tenantId, ModelConstants.COMPONENT_DESCRIPTOR_BY_SCOPE_TYPE_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME,
120 121 Arrays.asList(eq(ModelConstants.COMPONENT_DESCRIPTOR_TYPE_PROPERTY, type),
121 122 eq(ModelConstants.COMPONENT_DESCRIPTOR_SCOPE_PROPERTY, scope.name())), pageLink);
122 123 if (log.isTraceEnabled()) {
... ... @@ -127,34 +128,34 @@ public class CassandraBaseComponentDescriptorDao extends CassandraAbstractSearch
127 128 return DaoUtil.convertDataList(entities);
128 129 }
129 130
130   - public boolean removeById(UUID key) {
  131 + public boolean removeById(TenantId tenantId, UUID key) {
131 132 Statement delete = QueryBuilder.delete().all().from(ModelConstants.COMPONENT_DESCRIPTOR_BY_ID).where(eq(ModelConstants.ID_PROPERTY, key));
132 133 log.debug("Remove request: {}", delete.toString());
133   - return executeWrite(delete).wasApplied();
  134 + return executeWrite(tenantId, delete).wasApplied();
134 135 }
135 136
136 137 @Override
137   - public void deleteById(ComponentDescriptorId id) {
  138 + public void deleteById(TenantId tenantId, ComponentDescriptorId id) {
138 139 log.debug("Delete plugin meta-data entity by id [{}]", id);
139   - boolean result = removeById(id.getId());
  140 + boolean result = removeById(tenantId, id.getId());
140 141 log.debug("Delete result: [{}]", result);
141 142 }
142 143
143 144 @Override
144   - public void deleteByClazz(String clazz) {
  145 + public void deleteByClazz(TenantId tenantId, String clazz) {
145 146 log.debug("Delete plugin meta-data entity by id [{}]", clazz);
146 147 Statement delete = QueryBuilder.delete().all().from(getColumnFamilyName()).where(eq(ModelConstants.COMPONENT_DESCRIPTOR_CLASS_PROPERTY, clazz));
147 148 log.debug("Remove request: {}", delete.toString());
148   - ResultSet resultSet = executeWrite(delete);
  149 + ResultSet resultSet = executeWrite(tenantId, delete);
149 150 log.debug("Delete result: [{}]", resultSet.wasApplied());
150 151 }
151 152
152   - private Optional<ComponentDescriptor> saveIfNotExist(ComponentDescriptorEntity entity) {
  153 + private Optional<ComponentDescriptor> saveIfNotExist(TenantId tenantId, ComponentDescriptorEntity entity) {
153 154 if (entity.getId() == null) {
154 155 entity.setId(UUIDs.timeBased());
155 156 }
156 157
157   - ResultSet rs = executeRead(QueryBuilder.insertInto(getColumnFamilyName())
  158 + ResultSet rs = executeRead(tenantId, QueryBuilder.insertInto(getColumnFamilyName())
158 159 .value(ModelConstants.ID_PROPERTY, entity.getId())
159 160 .value(ModelConstants.COMPONENT_DESCRIPTOR_NAME_PROPERTY, entity.getName())
160 161 .value(ModelConstants.COMPONENT_DESCRIPTOR_CLASS_PROPERTY, entity.getClazz())
... ...
... ... @@ -16,6 +16,7 @@
16 16 package org.thingsboard.server.dao.component;
17 17
18 18 import org.thingsboard.server.common.data.id.ComponentDescriptorId;
  19 +import org.thingsboard.server.common.data.id.TenantId;
19 20 import org.thingsboard.server.common.data.page.TextPageLink;
20 21 import org.thingsboard.server.common.data.plugin.ComponentDescriptor;
21 22 import org.thingsboard.server.common.data.plugin.ComponentScope;
... ... @@ -30,18 +31,18 @@ import java.util.Optional;
30 31 */
31 32 public interface ComponentDescriptorDao extends Dao<ComponentDescriptor> {
32 33
33   - Optional<ComponentDescriptor> saveIfNotExist(ComponentDescriptor component);
  34 + Optional<ComponentDescriptor> saveIfNotExist(TenantId tenantId, ComponentDescriptor component);
34 35
35   - ComponentDescriptor findById(ComponentDescriptorId componentId);
  36 + ComponentDescriptor findById(TenantId tenantId, ComponentDescriptorId componentId);
36 37
37   - ComponentDescriptor findByClazz(String clazz);
  38 + ComponentDescriptor findByClazz(TenantId tenantId, String clazz);
38 39
39   - List<ComponentDescriptor> findByTypeAndPageLink(ComponentType type, TextPageLink pageLink);
  40 + List<ComponentDescriptor> findByTypeAndPageLink(TenantId tenantId, ComponentType type, TextPageLink pageLink);
40 41
41   - List<ComponentDescriptor> findByScopeAndTypeAndPageLink(ComponentScope scope, ComponentType type, TextPageLink pageLink);
  42 + List<ComponentDescriptor> findByScopeAndTypeAndPageLink(TenantId tenantId, ComponentScope scope, ComponentType type, TextPageLink pageLink);
42 43
43   - void deleteById(ComponentDescriptorId componentId);
  44 + void deleteById(TenantId tenantId, ComponentDescriptorId componentId);
44 45
45   - void deleteByClazz(String clazz);
  46 + void deleteByClazz(TenantId tenantId, String clazz);
46 47
47 48 }
... ...
... ... @@ -17,6 +17,7 @@ package org.thingsboard.server.dao.component;
17 17
18 18 import com.fasterxml.jackson.databind.JsonNode;
19 19 import org.thingsboard.server.common.data.id.ComponentDescriptorId;
  20 +import org.thingsboard.server.common.data.id.TenantId;
20 21 import org.thingsboard.server.common.data.page.TextPageData;
21 22 import org.thingsboard.server.common.data.page.TextPageLink;
22 23 import org.thingsboard.server.common.data.plugin.ComponentDescriptor;
... ... @@ -28,18 +29,18 @@ import org.thingsboard.server.common.data.plugin.ComponentType;
28 29 */
29 30 public interface ComponentDescriptorService {
30 31
31   - ComponentDescriptor saveComponent(ComponentDescriptor component);
  32 + ComponentDescriptor saveComponent(TenantId tenantId, ComponentDescriptor component);
32 33
33   - ComponentDescriptor findById(ComponentDescriptorId componentId);
  34 + ComponentDescriptor findById(TenantId tenantId, ComponentDescriptorId componentId);
34 35
35   - ComponentDescriptor findByClazz(String clazz);
  36 + ComponentDescriptor findByClazz(TenantId tenantId, String clazz);
36 37
37   - TextPageData<ComponentDescriptor> findByTypeAndPageLink(ComponentType type, TextPageLink pageLink);
  38 + TextPageData<ComponentDescriptor> findByTypeAndPageLink(TenantId tenantId, ComponentType type, TextPageLink pageLink);
38 39
39   - TextPageData<ComponentDescriptor> findByScopeAndTypeAndPageLink(ComponentScope scope, ComponentType type, TextPageLink pageLink);
  40 + TextPageData<ComponentDescriptor> findByScopeAndTypeAndPageLink(TenantId tenantId, ComponentScope scope, ComponentType type, TextPageLink pageLink);
40 41
41   - boolean validate(ComponentDescriptor component, JsonNode configuration);
  42 + boolean validate(TenantId tenantId, ComponentDescriptor component, JsonNode configuration);
42 43
43   - void deleteByClazz(String clazz);
  44 + void deleteByClazz(TenantId tenantId, String clazz);
44 45
45 46 }
... ...
... ... @@ -19,6 +19,7 @@ import com.datastax.driver.core.querybuilder.Select;
19 19 import lombok.extern.slf4j.Slf4j;
20 20 import org.springframework.stereotype.Component;
21 21 import org.thingsboard.server.common.data.Customer;
  22 +import org.thingsboard.server.common.data.id.TenantId;
22 23 import org.thingsboard.server.common.data.page.TextPageLink;
23 24 import org.thingsboard.server.dao.DaoUtil;
24 25 import org.thingsboard.server.dao.model.ModelConstants;
... ... @@ -36,6 +37,7 @@ import static com.datastax.driver.core.querybuilder.QueryBuilder.select;
36 37 import static org.thingsboard.server.dao.model.ModelConstants.CUSTOMER_BY_TENANT_AND_TITLE_VIEW_NAME;
37 38 import static org.thingsboard.server.dao.model.ModelConstants.CUSTOMER_TENANT_ID_PROPERTY;
38 39 import static org.thingsboard.server.dao.model.ModelConstants.CUSTOMER_TITLE_PROPERTY;
  40 +
39 41 @Component
40 42 @Slf4j
41 43 @NoSqlDao
... ... @@ -54,9 +56,9 @@ public class CassandraCustomerDao extends CassandraAbstractSearchTextDao<Custome
54 56 @Override
55 57 public List<Customer> findCustomersByTenantId(UUID tenantId, TextPageLink pageLink) {
56 58 log.debug("Try to find customers by tenantId [{}] and pageLink [{}]", tenantId, pageLink);
57   - List<CustomerEntity> customerEntities = findPageWithTextSearch(ModelConstants.CUSTOMER_BY_TENANT_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME,
  59 + List<CustomerEntity> customerEntities = findPageWithTextSearch(new TenantId(tenantId), ModelConstants.CUSTOMER_BY_TENANT_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME,
58 60 Arrays.asList(eq(ModelConstants.CUSTOMER_TENANT_ID_PROPERTY, tenantId)),
59   - pageLink);
  61 + pageLink);
60 62 log.trace("Found customers [{}] by tenantId [{}] and pageLink [{}]", customerEntities, tenantId, pageLink);
61 63 return DaoUtil.convertDataList(customerEntities);
62 64 }
... ... @@ -67,7 +69,7 @@ public class CassandraCustomerDao extends CassandraAbstractSearchTextDao<Custome
67 69 Select.Where query = select.where();
68 70 query.and(eq(CUSTOMER_TENANT_ID_PROPERTY, tenantId));
69 71 query.and(eq(CUSTOMER_TITLE_PROPERTY, title));
70   - CustomerEntity customerEntity = findOneByStatement(query);
  72 + CustomerEntity customerEntity = findOneByStatement(new TenantId(tenantId), query);
71 73 Customer customer = DaoUtil.getData(customerEntity);
72 74 return Optional.ofNullable(customer);
73 75 }
... ...
... ... @@ -16,6 +16,7 @@
16 16 package org.thingsboard.server.dao.customer;
17 17
18 18 import org.thingsboard.server.common.data.Customer;
  19 +import org.thingsboard.server.common.data.id.TenantId;
19 20 import org.thingsboard.server.common.data.page.TextPageLink;
20 21 import org.thingsboard.server.dao.Dao;
21 22
... ... @@ -34,7 +35,7 @@ public interface CustomerDao extends Dao<Customer> {
34 35 * @param customer the customer object
35 36 * @return saved customer object
36 37 */
37   - Customer save(Customer customer);
  38 + Customer save(TenantId tenantId, Customer customer);
38 39
39 40 /**
40 41 * Find customers by tenant id and page link.
... ...
... ... @@ -26,15 +26,15 @@ import java.util.Optional;
26 26
27 27 public interface CustomerService {
28 28
29   - Customer findCustomerById(CustomerId customerId);
  29 + Customer findCustomerById(TenantId tenantId, CustomerId customerId);
30 30
31 31 Optional<Customer> findCustomerByTenantIdAndTitle(TenantId tenantId, String title);
32 32
33   - ListenableFuture<Customer> findCustomerByIdAsync(CustomerId customerId);
  33 + ListenableFuture<Customer> findCustomerByIdAsync(TenantId tenantId, CustomerId customerId);
34 34
35 35 Customer saveCustomer(Customer customer);
36 36
37   - void deleteCustomer(CustomerId customerId);
  37 + void deleteCustomer(TenantId tenantId, CustomerId customerId);
38 38
39 39 Customer findOrCreatePublicCustomer(TenantId tenantId);
40 40
... ...
... ... @@ -77,10 +77,10 @@ public class CustomerServiceImpl extends AbstractEntityService implements Custom
77 77 private DashboardService dashboardService;
78 78
79 79 @Override
80   - public Customer findCustomerById(CustomerId customerId) {
  80 + public Customer findCustomerById(TenantId tenantId, CustomerId customerId) {
81 81 log.trace("Executing findCustomerById [{}]", customerId);
82 82 Validator.validateId(customerId, INCORRECT_CUSTOMER_ID + customerId);
83   - return customerDao.findById(customerId.getId());
  83 + return customerDao.findById(tenantId, customerId.getId());
84 84 }
85 85
86 86 @Override
... ... @@ -91,36 +91,36 @@ public class CustomerServiceImpl extends AbstractEntityService implements Custom
91 91 }
92 92
93 93 @Override
94   - public ListenableFuture<Customer> findCustomerByIdAsync(CustomerId customerId) {
  94 + public ListenableFuture<Customer> findCustomerByIdAsync(TenantId tenantId, CustomerId customerId) {
95 95 log.trace("Executing findCustomerByIdAsync [{}]", customerId);
96 96 validateId(customerId, INCORRECT_CUSTOMER_ID + customerId);
97   - return customerDao.findByIdAsync(customerId.getId());
  97 + return customerDao.findByIdAsync(tenantId, customerId.getId());
98 98 }
99 99
100 100 @Override
101 101 public Customer saveCustomer(Customer customer) {
102 102 log.trace("Executing saveCustomer [{}]", customer);
103   - customerValidator.validate(customer);
104   - Customer savedCustomer = customerDao.save(customer);
105   - dashboardService.updateCustomerDashboards(savedCustomer.getId());
  103 + customerValidator.validate(customer, Customer::getTenantId);
  104 + Customer savedCustomer = customerDao.save(customer.getTenantId(), customer);
  105 + dashboardService.updateCustomerDashboards(savedCustomer.getTenantId(), savedCustomer.getId());
106 106 return savedCustomer;
107 107 }
108 108
109 109 @Override
110   - public void deleteCustomer(CustomerId customerId) {
  110 + public void deleteCustomer(TenantId tenantId, CustomerId customerId) {
111 111 log.trace("Executing deleteCustomer [{}]", customerId);
112 112 Validator.validateId(customerId, INCORRECT_CUSTOMER_ID + customerId);
113   - Customer customer = findCustomerById(customerId);
  113 + Customer customer = findCustomerById(tenantId, customerId);
114 114 if (customer == null) {
115 115 throw new IncorrectParameterException("Unable to delete non-existent customer.");
116 116 }
117   - dashboardService.unassignCustomerDashboards(customerId);
  117 + dashboardService.unassignCustomerDashboards(tenantId, customerId);
118 118 entityViewService.unassignCustomerEntityViews(customer.getTenantId(), customerId);
119 119 assetService.unassignCustomerAssets(customer.getTenantId(), customerId);
120 120 deviceService.unassignCustomerDevices(customer.getTenantId(), customerId);
121 121 userService.deleteCustomerUsers(customer.getTenantId(), customerId);
122   - deleteEntityRelations(customerId);
123   - customerDao.removeById(customerId.getId());
  122 + deleteEntityRelations(tenantId, customerId);
  123 + customerDao.removeById(tenantId, customerId.getId());
124 124 }
125 125
126 126 @Override
... ... @@ -139,7 +139,7 @@ public class CustomerServiceImpl extends AbstractEntityService implements Custom
139 139 } catch (IOException e) {
140 140 throw new IncorrectParameterException("Unable to create public customer.", e);
141 141 }
142   - return customerDao.save(publicCustomer);
  142 + return customerDao.save(tenantId, publicCustomer);
143 143 }
144 144 }
145 145
... ... @@ -156,14 +156,14 @@ public class CustomerServiceImpl extends AbstractEntityService implements Custom
156 156 public void deleteCustomersByTenantId(TenantId tenantId) {
157 157 log.trace("Executing deleteCustomersByTenantId, tenantId [{}]", tenantId);
158 158 Validator.validateId(tenantId, "Incorrect tenantId " + tenantId);
159   - customersByTenantRemover.removeEntities(tenantId);
  159 + customersByTenantRemover.removeEntities(tenantId, tenantId);
160 160 }
161 161
162 162 private DataValidator<Customer> customerValidator =
163 163 new DataValidator<Customer>() {
164 164
165 165 @Override
166   - protected void validateCreate(Customer customer) {
  166 + protected void validateCreate(TenantId tenantId, Customer customer) {
167 167 customerDao.findCustomersByTenantIdAndTitle(customer.getTenantId().getId(), customer.getTitle()).ifPresent(
168 168 c -> {
169 169 throw new DataValidationException("Customer with such title already exists!");
... ... @@ -172,7 +172,7 @@ public class CustomerServiceImpl extends AbstractEntityService implements Custom
172 172 }
173 173
174 174 @Override
175   - protected void validateUpdate(Customer customer) {
  175 + protected void validateUpdate(TenantId tenantId, Customer customer) {
176 176 customerDao.findCustomersByTenantIdAndTitle(customer.getTenantId().getId(), customer.getTitle()).ifPresent(
177 177 c -> {
178 178 if (!c.getId().equals(customer.getId())) {
... ... @@ -183,7 +183,7 @@ public class CustomerServiceImpl extends AbstractEntityService implements Custom
183 183 }
184 184
185 185 @Override
186   - protected void validateDataImpl(Customer customer) {
  186 + protected void validateDataImpl(TenantId tenantId, Customer customer) {
187 187 if (StringUtils.isEmpty(customer.getTitle())) {
188 188 throw new DataValidationException("Customer title should be specified!");
189 189 }
... ... @@ -196,7 +196,7 @@ public class CustomerServiceImpl extends AbstractEntityService implements Custom
196 196 if (customer.getTenantId() == null) {
197 197 throw new DataValidationException("Customer should be assigned to tenant!");
198 198 } else {
199   - Tenant tenant = tenantDao.findById(customer.getTenantId().getId());
  199 + Tenant tenant = tenantDao.findById(tenantId, customer.getTenantId().getId());
200 200 if (tenant == null) {
201 201 throw new DataValidationException("Customer is referencing to non-existent tenant!");
202 202 }
... ... @@ -208,13 +208,13 @@ public class CustomerServiceImpl extends AbstractEntityService implements Custom
208 208 new PaginatedRemover<TenantId, Customer>() {
209 209
210 210 @Override
211   - protected List<Customer> findEntities(TenantId id, TextPageLink pageLink) {
  211 + protected List<Customer> findEntities(TenantId tenantId, TenantId id, TextPageLink pageLink) {
212 212 return customerDao.findCustomersByTenantId(id.getId(), pageLink);
213 213 }
214 214
215 215 @Override
216   - protected void removeEntity(Customer entity) {
217   - deleteCustomer(new CustomerId(entity.getUuidId()));
  216 + protected void removeEntity(TenantId tenantId, Customer entity) {
  217 + deleteCustomer(tenantId, new CustomerId(entity.getUuidId()));
218 218 }
219 219 };
220 220 }
... ...
... ... @@ -23,6 +23,7 @@ import org.springframework.stereotype.Component;
23 23 import org.thingsboard.server.common.data.DashboardInfo;
24 24 import org.thingsboard.server.common.data.EntityType;
25 25 import org.thingsboard.server.common.data.id.CustomerId;
  26 +import org.thingsboard.server.common.data.id.TenantId;
26 27 import org.thingsboard.server.common.data.page.TextPageLink;
27 28 import org.thingsboard.server.common.data.page.TimePageLink;
28 29 import org.thingsboard.server.common.data.relation.EntityRelation;
... ... @@ -64,7 +65,7 @@ public class CassandraDashboardInfoDao extends CassandraAbstractSearchTextDao<Da
64 65 @Override
65 66 public List<DashboardInfo> findDashboardsByTenantId(UUID tenantId, TextPageLink pageLink) {
66 67 log.debug("Try to find dashboards by tenantId [{}] and pageLink [{}]", tenantId, pageLink);
67   - List<DashboardInfoEntity> dashboardEntities = findPageWithTextSearch(DASHBOARD_BY_TENANT_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME,
  68 + List<DashboardInfoEntity> dashboardEntities = findPageWithTextSearch(new TenantId(tenantId), DASHBOARD_BY_TENANT_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME,
68 69 Collections.singletonList(eq(DASHBOARD_TENANT_ID_PROPERTY, tenantId)),
69 70 pageLink);
70 71
... ... @@ -76,12 +77,12 @@ public class CassandraDashboardInfoDao extends CassandraAbstractSearchTextDao<Da
76 77 public ListenableFuture<List<DashboardInfo>> findDashboardsByTenantIdAndCustomerId(UUID tenantId, UUID customerId, TimePageLink pageLink) {
77 78 log.debug("Try to find dashboards by tenantId [{}], customerId[{}] and pageLink [{}]", tenantId, customerId, pageLink);
78 79
79   - ListenableFuture<List<EntityRelation>> relations = relationDao.findRelations(new CustomerId(customerId), EntityRelation.CONTAINS_TYPE, RelationTypeGroup.DASHBOARD, EntityType.DASHBOARD, pageLink);
  80 + ListenableFuture<List<EntityRelation>> relations = relationDao.findRelations(new TenantId(tenantId), new CustomerId(customerId), EntityRelation.CONTAINS_TYPE, RelationTypeGroup.DASHBOARD, EntityType.DASHBOARD, pageLink);
80 81
81 82 return Futures.transformAsync(relations, input -> {
82 83 List<ListenableFuture<DashboardInfo>> dashboardFutures = new ArrayList<>(input.size());
83 84 for (EntityRelation relation : input) {
84   - dashboardFutures.add(findByIdAsync(relation.getTo().getId()));
  85 + dashboardFutures.add(findByIdAsync(new TenantId(tenantId), relation.getTo().getId()));
85 86 }
86 87 return Futures.successfulAsList(dashboardFutures);
87 88 });
... ...
... ... @@ -16,6 +16,7 @@
16 16 package org.thingsboard.server.dao.dashboard;
17 17
18 18 import org.thingsboard.server.common.data.Dashboard;
  19 +import org.thingsboard.server.common.data.id.TenantId;
19 20 import org.thingsboard.server.dao.Dao;
20 21
21 22 /**
... ... @@ -29,6 +30,6 @@ public interface DashboardDao extends Dao<Dashboard> {
29 30 * @param dashboard the dashboard object
30 31 * @return saved dashboard object
31 32 */
32   - Dashboard save(Dashboard dashboard);
  33 + Dashboard save(TenantId tenantId, Dashboard dashboard);
33 34
34 35 }
... ...
... ... @@ -28,21 +28,21 @@ import org.thingsboard.server.common.data.page.TimePageLink;
28 28
29 29 public interface DashboardService {
30 30
31   - Dashboard findDashboardById(DashboardId dashboardId);
  31 + Dashboard findDashboardById(TenantId tenantId, DashboardId dashboardId);
32 32
33   - ListenableFuture<Dashboard> findDashboardByIdAsync(DashboardId dashboardId);
  33 + ListenableFuture<Dashboard> findDashboardByIdAsync(TenantId tenantId, DashboardId dashboardId);
34 34
35   - DashboardInfo findDashboardInfoById(DashboardId dashboardId);
  35 + DashboardInfo findDashboardInfoById(TenantId tenantId, DashboardId dashboardId);
36 36
37   - ListenableFuture<DashboardInfo> findDashboardInfoByIdAsync(DashboardId dashboardId);
  37 + ListenableFuture<DashboardInfo> findDashboardInfoByIdAsync(TenantId tenantId, DashboardId dashboardId);
38 38
39 39 Dashboard saveDashboard(Dashboard dashboard);
40 40
41   - Dashboard assignDashboardToCustomer(DashboardId dashboardId, CustomerId customerId);
  41 + Dashboard assignDashboardToCustomer(TenantId tenantId, DashboardId dashboardId, CustomerId customerId);
42 42
43   - Dashboard unassignDashboardFromCustomer(DashboardId dashboardId, CustomerId customerId);
  43 + Dashboard unassignDashboardFromCustomer(TenantId tenantId, DashboardId dashboardId, CustomerId customerId);
44 44
45   - void deleteDashboard(DashboardId dashboardId);
  45 + void deleteDashboard(TenantId tenantId, DashboardId dashboardId);
46 46
47 47 TextPageData<DashboardInfo> findDashboardsByTenantId(TenantId tenantId, TextPageLink pageLink);
48 48
... ... @@ -50,8 +50,8 @@ public interface DashboardService {
50 50
51 51 ListenableFuture<TimePageData<DashboardInfo>> findDashboardsByTenantIdAndCustomerId(TenantId tenantId, CustomerId customerId, TimePageLink pageLink);
52 52
53   - void unassignCustomerDashboards(CustomerId customerId);
  53 + void unassignCustomerDashboards(TenantId tenantId, CustomerId customerId);
54 54
55   - void updateCustomerDashboards(CustomerId customerId);
  55 + void updateCustomerDashboards(TenantId tenantId, CustomerId customerId);
56 56
57 57 }
... ...
... ... @@ -69,44 +69,44 @@ public class DashboardServiceImpl extends AbstractEntityService implements Dashb
69 69 private CustomerDao customerDao;
70 70
71 71 @Override
72   - public Dashboard findDashboardById(DashboardId dashboardId) {
  72 + public Dashboard findDashboardById(TenantId tenantId, DashboardId dashboardId) {
73 73 log.trace("Executing findDashboardById [{}]", dashboardId);
74 74 Validator.validateId(dashboardId, INCORRECT_DASHBOARD_ID + dashboardId);
75   - return dashboardDao.findById(dashboardId.getId());
  75 + return dashboardDao.findById(tenantId, dashboardId.getId());
76 76 }
77 77
78 78 @Override
79   - public ListenableFuture<Dashboard> findDashboardByIdAsync(DashboardId dashboardId) {
  79 + public ListenableFuture<Dashboard> findDashboardByIdAsync(TenantId tenantId, DashboardId dashboardId) {
80 80 log.trace("Executing findDashboardByIdAsync [{}]", dashboardId);
81 81 validateId(dashboardId, INCORRECT_DASHBOARD_ID + dashboardId);
82   - return dashboardDao.findByIdAsync(dashboardId.getId());
  82 + return dashboardDao.findByIdAsync(tenantId, dashboardId.getId());
83 83 }
84 84
85 85 @Override
86   - public DashboardInfo findDashboardInfoById(DashboardId dashboardId) {
  86 + public DashboardInfo findDashboardInfoById(TenantId tenantId, DashboardId dashboardId) {
87 87 log.trace("Executing findDashboardInfoById [{}]", dashboardId);
88 88 Validator.validateId(dashboardId, INCORRECT_DASHBOARD_ID + dashboardId);
89   - return dashboardInfoDao.findById(dashboardId.getId());
  89 + return dashboardInfoDao.findById(tenantId, dashboardId.getId());
90 90 }
91 91
92 92 @Override
93   - public ListenableFuture<DashboardInfo> findDashboardInfoByIdAsync(DashboardId dashboardId) {
  93 + public ListenableFuture<DashboardInfo> findDashboardInfoByIdAsync(TenantId tenantId, DashboardId dashboardId) {
94 94 log.trace("Executing findDashboardInfoByIdAsync [{}]", dashboardId);
95 95 validateId(dashboardId, INCORRECT_DASHBOARD_ID + dashboardId);
96   - return dashboardInfoDao.findByIdAsync(dashboardId.getId());
  96 + return dashboardInfoDao.findByIdAsync(tenantId, dashboardId.getId());
97 97 }
98 98
99 99 @Override
100 100 public Dashboard saveDashboard(Dashboard dashboard) {
101 101 log.trace("Executing saveDashboard [{}]", dashboard);
102   - dashboardValidator.validate(dashboard);
103   - return dashboardDao.save(dashboard);
  102 + dashboardValidator.validate(dashboard, DashboardInfo::getTenantId);
  103 + return dashboardDao.save(dashboard.getTenantId(), dashboard);
104 104 }
105 105
106 106 @Override
107   - public Dashboard assignDashboardToCustomer(DashboardId dashboardId, CustomerId customerId) {
108   - Dashboard dashboard = findDashboardById(dashboardId);
109   - Customer customer = customerDao.findById(customerId.getId());
  107 + public Dashboard assignDashboardToCustomer(TenantId tenantId, DashboardId dashboardId, CustomerId customerId) {
  108 + Dashboard dashboard = findDashboardById(tenantId, dashboardId);
  109 + Customer customer = customerDao.findById(tenantId, customerId.getId());
110 110 if (customer == null) {
111 111 throw new DataValidationException("Can't assign dashboard to non-existent customer!");
112 112 }
... ... @@ -115,7 +115,7 @@ public class DashboardServiceImpl extends AbstractEntityService implements Dashb
115 115 }
116 116 if (dashboard.addAssignedCustomer(customer)) {
117 117 try {
118   - createRelation(new EntityRelation(customerId, dashboardId, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.DASHBOARD));
  118 + createRelation(tenantId, new EntityRelation(customerId, dashboardId, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.DASHBOARD));
119 119 } catch (ExecutionException | InterruptedException e) {
120 120 log.warn("[{}] Failed to create dashboard relation. Customer Id: [{}]", dashboardId, customerId);
121 121 throw new RuntimeException(e);
... ... @@ -127,15 +127,15 @@ public class DashboardServiceImpl extends AbstractEntityService implements Dashb
127 127 }
128 128
129 129 @Override
130   - public Dashboard unassignDashboardFromCustomer(DashboardId dashboardId, CustomerId customerId) {
131   - Dashboard dashboard = findDashboardById(dashboardId);
132   - Customer customer = customerDao.findById(customerId.getId());
  130 + public Dashboard unassignDashboardFromCustomer(TenantId tenantId, DashboardId dashboardId, CustomerId customerId) {
  131 + Dashboard dashboard = findDashboardById(tenantId, dashboardId);
  132 + Customer customer = customerDao.findById(tenantId, customerId.getId());
133 133 if (customer == null) {
134 134 throw new DataValidationException("Can't unassign dashboard from non-existent customer!");
135 135 }
136 136 if (dashboard.removeAssignedCustomer(customer)) {
137 137 try {
138   - deleteRelation(new EntityRelation(customerId, dashboardId, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.DASHBOARD));
  138 + deleteRelation(tenantId, new EntityRelation(customerId, dashboardId, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.DASHBOARD));
139 139 } catch (ExecutionException | InterruptedException e) {
140 140 log.warn("[{}] Failed to delete dashboard relation. Customer Id: [{}]", dashboardId, customerId);
141 141 throw new RuntimeException(e);
... ... @@ -146,8 +146,8 @@ public class DashboardServiceImpl extends AbstractEntityService implements Dashb
146 146 }
147 147 }
148 148
149   - private Dashboard updateAssignedCustomer(DashboardId dashboardId, Customer customer) {
150   - Dashboard dashboard = findDashboardById(dashboardId);
  149 + private Dashboard updateAssignedCustomer(TenantId tenantId, DashboardId dashboardId, Customer customer) {
  150 + Dashboard dashboard = findDashboardById(tenantId, dashboardId);
151 151 if (dashboard.updateAssignedCustomer(customer)) {
152 152 return saveDashboard(dashboard);
153 153 } else {
... ... @@ -155,22 +155,22 @@ public class DashboardServiceImpl extends AbstractEntityService implements Dashb
155 155 }
156 156 }
157 157
158   - private void deleteRelation(EntityRelation dashboardRelation) throws ExecutionException, InterruptedException {
  158 + private void deleteRelation(TenantId tenantId, EntityRelation dashboardRelation) throws ExecutionException, InterruptedException {
159 159 log.debug("Deleting Dashboard relation: {}", dashboardRelation);
160   - relationService.deleteRelationAsync(dashboardRelation).get();
  160 + relationService.deleteRelationAsync(tenantId, dashboardRelation).get();
161 161 }
162 162
163   - private void createRelation(EntityRelation dashboardRelation) throws ExecutionException, InterruptedException {
  163 + private void createRelation(TenantId tenantId, EntityRelation dashboardRelation) throws ExecutionException, InterruptedException {
164 164 log.debug("Creating Dashboard relation: {}", dashboardRelation);
165   - relationService.saveRelationAsync(dashboardRelation).get();
  165 + relationService.saveRelationAsync(tenantId, dashboardRelation).get();
166 166 }
167 167
168 168 @Override
169   - public void deleteDashboard(DashboardId dashboardId) {
  169 + public void deleteDashboard(TenantId tenantId, DashboardId dashboardId) {
170 170 log.trace("Executing deleteDashboard [{}]", dashboardId);
171 171 Validator.validateId(dashboardId, INCORRECT_DASHBOARD_ID + dashboardId);
172   - deleteEntityRelations(dashboardId);
173   - dashboardDao.removeById(dashboardId.getId());
  172 + deleteEntityRelations(tenantId, dashboardId);
  173 + dashboardDao.removeById(tenantId, dashboardId.getId());
174 174 }
175 175
176 176 @Override
... ... @@ -186,7 +186,7 @@ public class DashboardServiceImpl extends AbstractEntityService implements Dashb
186 186 public void deleteDashboardsByTenantId(TenantId tenantId) {
187 187 log.trace("Executing deleteDashboardsByTenantId, tenantId [{}]", tenantId);
188 188 Validator.validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
189   - tenantDashboardsRemover.removeEntities(tenantId);
  189 + tenantDashboardsRemover.removeEntities(tenantId, tenantId);
190 190 }
191 191
192 192 @Override
... ... @@ -207,10 +207,10 @@ public class DashboardServiceImpl extends AbstractEntityService implements Dashb
207 207 }
208 208
209 209 @Override
210   - public void unassignCustomerDashboards(CustomerId customerId) {
  210 + public void unassignCustomerDashboards(TenantId tenantId, CustomerId customerId) {
211 211 log.trace("Executing unassignCustomerDashboards, customerId [{}]", customerId);
212 212 Validator.validateId(customerId, "Incorrect customerId " + customerId);
213   - Customer customer = customerDao.findById(customerId.getId());
  213 + Customer customer = customerDao.findById(tenantId, customerId.getId());
214 214 if (customer == null) {
215 215 throw new DataValidationException("Can't unassign dashboards from non-existent customer!");
216 216 }
... ... @@ -218,10 +218,10 @@ public class DashboardServiceImpl extends AbstractEntityService implements Dashb
218 218 }
219 219
220 220 @Override
221   - public void updateCustomerDashboards(CustomerId customerId) {
  221 + public void updateCustomerDashboards(TenantId tenantId, CustomerId customerId) {
222 222 log.trace("Executing updateCustomerDashboards, customerId [{}]", customerId);
223 223 Validator.validateId(customerId, "Incorrect customerId " + customerId);
224   - Customer customer = customerDao.findById(customerId.getId());
  224 + Customer customer = customerDao.findById(tenantId, customerId.getId());
225 225 if (customer == null) {
226 226 throw new DataValidationException("Can't update dashboards for non-existent customer!");
227 227 }
... ... @@ -231,14 +231,14 @@ public class DashboardServiceImpl extends AbstractEntityService implements Dashb
231 231 private DataValidator<Dashboard> dashboardValidator =
232 232 new DataValidator<Dashboard>() {
233 233 @Override
234   - protected void validateDataImpl(Dashboard dashboard) {
  234 + protected void validateDataImpl(TenantId tenantId, Dashboard dashboard) {
235 235 if (StringUtils.isEmpty(dashboard.getTitle())) {
236 236 throw new DataValidationException("Dashboard title should be specified!");
237 237 }
238 238 if (dashboard.getTenantId() == null) {
239 239 throw new DataValidationException("Dashboard should be assigned to tenant!");
240 240 } else {
241   - Tenant tenant = tenantDao.findById(dashboard.getTenantId().getId());
  241 + Tenant tenant = tenantDao.findById(tenantId, dashboard.getTenantId().getId());
242 242 if (tenant == null) {
243 243 throw new DataValidationException("Dashboard is referencing to non-existent tenant!");
244 244 }
... ... @@ -250,13 +250,13 @@ public class DashboardServiceImpl extends AbstractEntityService implements Dashb
250 250 new PaginatedRemover<TenantId, DashboardInfo>() {
251 251
252 252 @Override
253   - protected List<DashboardInfo> findEntities(TenantId id, TextPageLink pageLink) {
  253 + protected List<DashboardInfo> findEntities(TenantId tenantId, TenantId id, TextPageLink pageLink) {
254 254 return dashboardInfoDao.findDashboardsByTenantId(id.getId(), pageLink);
255 255 }
256 256
257 257 @Override
258   - protected void removeEntity(DashboardInfo entity) {
259   - deleteDashboard(new DashboardId(entity.getUuidId()));
  258 + protected void removeEntity(TenantId tenantId, DashboardInfo entity) {
  259 + deleteDashboard(tenantId, new DashboardId(entity.getUuidId()));
260 260 }
261 261 };
262 262
... ... @@ -280,7 +280,7 @@ public class DashboardServiceImpl extends AbstractEntityService implements Dashb
280 280
281 281 @Override
282 282 protected void removeEntity(DashboardInfo entity) {
283   - unassignDashboardFromCustomer(new DashboardId(entity.getUuidId()), this.customer.getId());
  283 + unassignDashboardFromCustomer(customer.getTenantId(), new DashboardId(entity.getUuidId()), this.customer.getId());
284 284 }
285 285
286 286 }
... ... @@ -305,7 +305,7 @@ public class DashboardServiceImpl extends AbstractEntityService implements Dashb
305 305
306 306 @Override
307 307 protected void removeEntity(DashboardInfo entity) {
308   - updateAssignedCustomer(new DashboardId(entity.getUuidId()), this.customer);
  308 + updateAssignedCustomer(customer.getTenantId(), new DashboardId(entity.getUuidId()), this.customer);
309 309 }
310 310
311 311 }
... ...
... ... @@ -18,6 +18,7 @@ package org.thingsboard.server.dao.device;
18 18 import com.datastax.driver.core.querybuilder.Select.Where;
19 19 import lombok.extern.slf4j.Slf4j;
20 20 import org.springframework.stereotype.Component;
  21 +import org.thingsboard.server.common.data.id.TenantId;
21 22 import org.thingsboard.server.common.data.security.DeviceCredentials;
22 23 import org.thingsboard.server.dao.DaoUtil;
23 24 import org.thingsboard.server.dao.model.ModelConstants;
... ... @@ -46,23 +47,23 @@ public class CassandraDeviceCredentialsDao extends CassandraAbstractModelDao<Dev
46 47 }
47 48
48 49 @Override
49   - public DeviceCredentials findByDeviceId(UUID deviceId) {
  50 + public DeviceCredentials findByDeviceId(TenantId tenantId, UUID deviceId) {
50 51 log.debug("Try to find device credentials by deviceId [{}] ", deviceId);
51 52 Where query = select().from(ModelConstants.DEVICE_CREDENTIALS_BY_DEVICE_COLUMN_FAMILY_NAME)
52 53 .where(eq(ModelConstants.DEVICE_CREDENTIALS_DEVICE_ID_PROPERTY, deviceId));
53 54 log.trace("Execute query {}", query);
54   - DeviceCredentialsEntity deviceCredentialsEntity = findOneByStatement(query);
  55 + DeviceCredentialsEntity deviceCredentialsEntity = findOneByStatement(tenantId, query);
55 56 log.trace("Found device credentials [{}] by deviceId [{}]", deviceCredentialsEntity, deviceId);
56 57 return DaoUtil.getData(deviceCredentialsEntity);
57 58 }
58 59
59 60 @Override
60   - public DeviceCredentials findByCredentialsId(String credentialsId) {
  61 + public DeviceCredentials findByCredentialsId(TenantId tenantId, String credentialsId) {
61 62 log.debug("Try to find device credentials by credentialsId [{}] ", credentialsId);
62 63 Where query = select().from(ModelConstants.DEVICE_CREDENTIALS_BY_CREDENTIALS_ID_COLUMN_FAMILY_NAME)
63 64 .where(eq(ModelConstants.DEVICE_CREDENTIALS_CREDENTIALS_ID_PROPERTY, credentialsId));
64 65 log.trace("Execute query {}", query);
65   - DeviceCredentialsEntity deviceCredentialsEntity = findOneByStatement(query);
  66 + DeviceCredentialsEntity deviceCredentialsEntity = findOneByStatement(tenantId, query);
66 67 log.trace("Found device credentials [{}] by credentialsId [{}]", deviceCredentialsEntity, credentialsId);
67 68 return DaoUtil.getData(deviceCredentialsEntity);
68 69 }
... ...
... ... @@ -28,6 +28,7 @@ import org.springframework.stereotype.Component;
28 28 import org.thingsboard.server.common.data.Device;
29 29 import org.thingsboard.server.common.data.EntitySubtype;
30 30 import org.thingsboard.server.common.data.EntityType;
  31 +import org.thingsboard.server.common.data.id.TenantId;
31 32 import org.thingsboard.server.common.data.page.TextPageLink;
32 33 import org.thingsboard.server.dao.DaoUtil;
33 34 import org.thingsboard.server.dao.model.EntitySubtypeEntity;
... ... @@ -77,19 +78,19 @@ public class CassandraDeviceDao extends CassandraAbstractSearchTextDao<DeviceEnt
77 78 }
78 79
79 80 @Override
80   - public Device save(Device domain) {
81   - Device savedDevice = super.save(domain);
  81 + public Device save(TenantId tenantId, Device domain) {
  82 + Device savedDevice = super.save(tenantId, domain);
82 83 EntitySubtype entitySubtype = new EntitySubtype(savedDevice.getTenantId(), EntityType.DEVICE, savedDevice.getType());
83 84 EntitySubtypeEntity entitySubtypeEntity = new EntitySubtypeEntity(entitySubtype);
84 85 Statement saveStatement = cluster.getMapper(EntitySubtypeEntity.class).saveQuery(entitySubtypeEntity);
85   - executeWrite(saveStatement);
  86 + executeWrite(tenantId, saveStatement);
86 87 return savedDevice;
87 88 }
88 89
89 90 @Override
90 91 public List<Device> findDevicesByTenantId(UUID tenantId, TextPageLink pageLink) {
91 92 log.debug("Try to find devices by tenantId [{}] and pageLink [{}]", tenantId, pageLink);
92   - List<DeviceEntity> deviceEntities = findPageWithTextSearch(DEVICE_BY_TENANT_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME,
  93 + List<DeviceEntity> deviceEntities = findPageWithTextSearch(new TenantId(tenantId), DEVICE_BY_TENANT_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME,
93 94 Collections.singletonList(eq(DEVICE_TENANT_ID_PROPERTY, tenantId)), pageLink);
94 95
95 96 log.trace("Found devices [{}] by tenantId [{}] and pageLink [{}]", deviceEntities, tenantId, pageLink);
... ... @@ -99,7 +100,7 @@ public class CassandraDeviceDao extends CassandraAbstractSearchTextDao<DeviceEnt
99 100 @Override
100 101 public List<Device> findDevicesByTenantIdAndType(UUID tenantId, String type, TextPageLink pageLink) {
101 102 log.debug("Try to find devices by tenantId [{}], type [{}] and pageLink [{}]", tenantId, type, pageLink);
102   - List<DeviceEntity> deviceEntities = findPageWithTextSearch(DEVICE_BY_TENANT_BY_TYPE_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME,
  103 + List<DeviceEntity> deviceEntities = findPageWithTextSearch(new TenantId(tenantId), DEVICE_BY_TENANT_BY_TYPE_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME,
103 104 Arrays.asList(eq(DEVICE_TYPE_PROPERTY, type),
104 105 eq(DEVICE_TENANT_ID_PROPERTY, tenantId)), pageLink);
105 106 log.trace("Found devices [{}] by tenantId [{}], type [{}] and pageLink [{}]", deviceEntities, tenantId, type, pageLink);
... ... @@ -113,13 +114,13 @@ public class CassandraDeviceDao extends CassandraAbstractSearchTextDao<DeviceEnt
113 114 Select.Where query = select.where();
114 115 query.and(eq(DEVICE_TENANT_ID_PROPERTY, tenantId));
115 116 query.and(in(ID_PROPERTY, deviceIds));
116   - return findListByStatementAsync(query);
  117 + return findListByStatementAsync(new TenantId(tenantId), query);
117 118 }
118 119
119 120 @Override
120 121 public List<Device> findDevicesByTenantIdAndCustomerId(UUID tenantId, UUID customerId, TextPageLink pageLink) {
121 122 log.debug("Try to find devices by tenantId [{}], customerId[{}] and pageLink [{}]", tenantId, customerId, pageLink);
122   - List<DeviceEntity> deviceEntities = findPageWithTextSearch(DEVICE_BY_CUSTOMER_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME,
  123 + List<DeviceEntity> deviceEntities = findPageWithTextSearch(new TenantId(tenantId), DEVICE_BY_CUSTOMER_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME,
123 124 Arrays.asList(eq(DEVICE_CUSTOMER_ID_PROPERTY, customerId),
124 125 eq(DEVICE_TENANT_ID_PROPERTY, tenantId)),
125 126 pageLink);
... ... @@ -131,7 +132,7 @@ public class CassandraDeviceDao extends CassandraAbstractSearchTextDao<DeviceEnt
131 132 @Override
132 133 public List<Device> findDevicesByTenantIdAndCustomerIdAndType(UUID tenantId, UUID customerId, String type, TextPageLink pageLink) {
133 134 log.debug("Try to find devices by tenantId [{}], customerId [{}], type [{}] and pageLink [{}]", tenantId, customerId, type, pageLink);
134   - List<DeviceEntity> deviceEntities = findPageWithTextSearch(DEVICE_BY_CUSTOMER_BY_TYPE_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME,
  135 + List<DeviceEntity> deviceEntities = findPageWithTextSearch(new TenantId(tenantId), DEVICE_BY_CUSTOMER_BY_TYPE_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME,
135 136 Arrays.asList(eq(DEVICE_TYPE_PROPERTY, type),
136 137 eq(DEVICE_CUSTOMER_ID_PROPERTY, customerId),
137 138 eq(DEVICE_TENANT_ID_PROPERTY, tenantId)),
... ... @@ -149,7 +150,7 @@ public class CassandraDeviceDao extends CassandraAbstractSearchTextDao<DeviceEnt
149 150 query.and(eq(DEVICE_TENANT_ID_PROPERTY, tenantId));
150 151 query.and(eq(DEVICE_CUSTOMER_ID_PROPERTY, customerId));
151 152 query.and(in(ID_PROPERTY, deviceIds));
152   - return findListByStatementAsync(query);
  153 + return findListByStatementAsync(new TenantId(tenantId), query);
153 154 }
154 155
155 156 @Override
... ... @@ -158,7 +159,7 @@ public class CassandraDeviceDao extends CassandraAbstractSearchTextDao<DeviceEnt
158 159 Select.Where query = select.where();
159 160 query.and(eq(DEVICE_TENANT_ID_PROPERTY, tenantId));
160 161 query.and(eq(DEVICE_NAME_PROPERTY, deviceName));
161   - return Optional.ofNullable(DaoUtil.getData(findOneByStatement(query)));
  162 + return Optional.ofNullable(DaoUtil.getData(findOneByStatement(new TenantId(tenantId), query)));
162 163 }
163 164
164 165 @Override
... ... @@ -168,7 +169,7 @@ public class CassandraDeviceDao extends CassandraAbstractSearchTextDao<DeviceEnt
168 169 query.and(eq(ENTITY_SUBTYPE_TENANT_ID_PROPERTY, tenantId));
169 170 query.and(eq(ENTITY_SUBTYPE_ENTITY_TYPE_PROPERTY, EntityType.DEVICE));
170 171 query.setConsistencyLevel(cluster.getDefaultReadConsistencyLevel());
171   - ResultSetFuture resultSetFuture = executeAsyncRead(query);
  172 + ResultSetFuture resultSetFuture = executeAsyncRead(new TenantId(tenantId), query);
172 173 return Futures.transform(resultSetFuture, new Function<ResultSet, List<EntitySubtype>>() {
173 174 @Nullable
174 175 @Override
... ...
... ... @@ -15,6 +15,7 @@
15 15 */
16 16 package org.thingsboard.server.dao.device;
17 17
  18 +import org.thingsboard.server.common.data.id.TenantId;
18 19 import org.thingsboard.server.common.data.security.DeviceCredentials;
19 20 import org.thingsboard.server.dao.Dao;
20 21
... ... @@ -28,10 +29,11 @@ public interface DeviceCredentialsDao extends Dao<DeviceCredentials> {
28 29 /**
29 30 * Save or update device credentials object
30 31 *
  32 + * @param tenantId the device tenant id
31 33 * @param deviceCredentials the device credentials object
32 34 * @return saved device credentials object
33 35 */
34   - DeviceCredentials save(DeviceCredentials deviceCredentials);
  36 + DeviceCredentials save(TenantId tenantId, DeviceCredentials deviceCredentials);
35 37
36 38 /**
37 39 * Find device credentials by device id.
... ... @@ -39,7 +41,7 @@ public interface DeviceCredentialsDao extends Dao<DeviceCredentials> {
39 41 * @param deviceId the device id
40 42 * @return the device credentials object
41 43 */
42   - DeviceCredentials findByDeviceId(UUID deviceId);
  44 + DeviceCredentials findByDeviceId(TenantId tenantId, UUID deviceId);
43 45
44 46 /**
45 47 * Find device credentials by credentials id.
... ... @@ -47,6 +49,6 @@ public interface DeviceCredentialsDao extends Dao<DeviceCredentials> {
47 49 * @param credentialsId the credentials id
48 50 * @return the device credentials object
49 51 */
50   - DeviceCredentials findByCredentialsId(String credentialsId);
  52 + DeviceCredentials findByCredentialsId(TenantId tenantId, String credentialsId);
51 53
52 54 }
... ...
... ... @@ -16,17 +16,18 @@
16 16 package org.thingsboard.server.dao.device;
17 17
18 18 import org.thingsboard.server.common.data.id.DeviceId;
  19 +import org.thingsboard.server.common.data.id.TenantId;
19 20 import org.thingsboard.server.common.data.security.DeviceCredentials;
20 21
21 22 public interface DeviceCredentialsService {
22 23
23   - DeviceCredentials findDeviceCredentialsByDeviceId(DeviceId deviceId);
  24 + DeviceCredentials findDeviceCredentialsByDeviceId(TenantId tenantId, DeviceId deviceId);
24 25
25 26 DeviceCredentials findDeviceCredentialsByCredentialsId(String credentialsId);
26 27
27   - DeviceCredentials updateDeviceCredentials(DeviceCredentials deviceCredentials);
  28 + DeviceCredentials updateDeviceCredentials(TenantId tenantId, DeviceCredentials deviceCredentials);
28 29
29   - DeviceCredentials createDeviceCredentials(DeviceCredentials deviceCredentials);
  30 + DeviceCredentials createDeviceCredentials(TenantId tenantId, DeviceCredentials deviceCredentials);
30 31
31   - void deleteDeviceCredentials(DeviceCredentials deviceCredentials);
  32 + void deleteDeviceCredentials(TenantId tenantId, DeviceCredentials deviceCredentials);
32 33 }
... ...
... ... @@ -24,6 +24,8 @@ import org.springframework.stereotype.Service;
24 24 import org.springframework.util.StringUtils;
25 25 import org.thingsboard.server.common.data.Device;
26 26 import org.thingsboard.server.common.data.id.DeviceId;
  27 +import org.thingsboard.server.common.data.id.EntityId;
  28 +import org.thingsboard.server.common.data.id.TenantId;
27 29 import org.thingsboard.server.common.data.security.DeviceCredentials;
28 30 import org.thingsboard.server.common.data.security.DeviceCredentialsType;
29 31 import org.thingsboard.server.common.msg.EncryptionUtil;
... ... @@ -45,38 +47,38 @@ public class DeviceCredentialsServiceImpl implements DeviceCredentialsService {
45 47 private DeviceService deviceService;
46 48
47 49 @Override
48   - public DeviceCredentials findDeviceCredentialsByDeviceId(DeviceId deviceId) {
  50 + public DeviceCredentials findDeviceCredentialsByDeviceId(TenantId tenantId, DeviceId deviceId) {
49 51 log.trace("Executing findDeviceCredentialsByDeviceId [{}]", deviceId);
50 52 validateId(deviceId, "Incorrect deviceId " + deviceId);
51   - return deviceCredentialsDao.findByDeviceId(deviceId.getId());
  53 + return deviceCredentialsDao.findByDeviceId(tenantId, deviceId.getId());
52 54 }
53 55
54 56 @Override
55   - @Cacheable(cacheNames = DEVICE_CREDENTIALS_CACHE, unless="#result == null")
  57 + @Cacheable(cacheNames = DEVICE_CREDENTIALS_CACHE, unless = "#result == null")
56 58 public DeviceCredentials findDeviceCredentialsByCredentialsId(String credentialsId) {
57 59 log.trace("Executing findDeviceCredentialsByCredentialsId [{}]", credentialsId);
58 60 validateString(credentialsId, "Incorrect credentialsId " + credentialsId);
59   - return deviceCredentialsDao.findByCredentialsId(credentialsId);
  61 + return deviceCredentialsDao.findByCredentialsId(new TenantId(EntityId.NULL_UUID), credentialsId);
60 62 }
61 63
62 64 @Override
63   - @CacheEvict(cacheNames = DEVICE_CREDENTIALS_CACHE, keyGenerator="previousDeviceCredentialsId", beforeInvocation = true)
64   - public DeviceCredentials updateDeviceCredentials(DeviceCredentials deviceCredentials) {
65   - return saveOrUpdate(deviceCredentials);
  65 + @CacheEvict(cacheNames = DEVICE_CREDENTIALS_CACHE, keyGenerator = "previousDeviceCredentialsId", beforeInvocation = true)
  66 + public DeviceCredentials updateDeviceCredentials(TenantId tenantId, DeviceCredentials deviceCredentials) {
  67 + return saveOrUpdate(tenantId, deviceCredentials);
66 68 }
67 69
68 70 @Override
69   - public DeviceCredentials createDeviceCredentials(DeviceCredentials deviceCredentials) {
70   - return saveOrUpdate(deviceCredentials);
  71 + public DeviceCredentials createDeviceCredentials(TenantId tenantId, DeviceCredentials deviceCredentials) {
  72 + return saveOrUpdate(tenantId, deviceCredentials);
71 73 }
72 74
73   - private DeviceCredentials saveOrUpdate(DeviceCredentials deviceCredentials) {
  75 + private DeviceCredentials saveOrUpdate(TenantId tenantId, DeviceCredentials deviceCredentials) {
74 76 if (deviceCredentials.getCredentialsType() == DeviceCredentialsType.X509_CERTIFICATE) {
75 77 formatCertData(deviceCredentials);
76 78 }
77 79 log.trace("Executing updateDeviceCredentials [{}]", deviceCredentials);
78   - credentialsValidator.validate(deviceCredentials);
79   - return deviceCredentialsDao.save(deviceCredentials);
  80 + credentialsValidator.validate(deviceCredentials, id -> tenantId);
  81 + return deviceCredentialsDao.save(tenantId, deviceCredentials);
80 82 }
81 83
82 84 private void formatCertData(DeviceCredentials deviceCredentials) {
... ... @@ -87,37 +89,37 @@ public class DeviceCredentialsServiceImpl implements DeviceCredentialsService {
87 89 }
88 90
89 91 @Override
90   - @CacheEvict(cacheNames = DEVICE_CREDENTIALS_CACHE, key="#deviceCredentials.credentialsId")
91   - public void deleteDeviceCredentials(DeviceCredentials deviceCredentials) {
  92 + @CacheEvict(cacheNames = DEVICE_CREDENTIALS_CACHE, key = "#deviceCredentials.credentialsId")
  93 + public void deleteDeviceCredentials(TenantId tenantId, DeviceCredentials deviceCredentials) {
92 94 log.trace("Executing deleteDeviceCredentials [{}]", deviceCredentials);
93   - deviceCredentialsDao.removeById(deviceCredentials.getUuidId());
  95 + deviceCredentialsDao.removeById(tenantId, deviceCredentials.getUuidId());
94 96 }
95 97
96 98 private DataValidator<DeviceCredentials> credentialsValidator =
97 99 new DataValidator<DeviceCredentials>() {
98 100
99 101 @Override
100   - protected void validateCreate(DeviceCredentials deviceCredentials) {
101   - DeviceCredentials existingCredentialsEntity = deviceCredentialsDao.findByCredentialsId(deviceCredentials.getCredentialsId());
  102 + protected void validateCreate(TenantId tenantId, DeviceCredentials deviceCredentials) {
  103 + DeviceCredentials existingCredentialsEntity = deviceCredentialsDao.findByCredentialsId(tenantId, deviceCredentials.getCredentialsId());
102 104 if (existingCredentialsEntity != null) {
103 105 throw new DataValidationException("Create of existent device credentials!");
104 106 }
105 107 }
106 108
107 109 @Override
108   - protected void validateUpdate(DeviceCredentials deviceCredentials) {
109   - DeviceCredentials existingCredentials = deviceCredentialsDao.findById(deviceCredentials.getUuidId());
  110 + protected void validateUpdate(TenantId tenantId, DeviceCredentials deviceCredentials) {
  111 + DeviceCredentials existingCredentials = deviceCredentialsDao.findById(tenantId, deviceCredentials.getUuidId());
110 112 if (existingCredentials == null) {
111 113 throw new DataValidationException("Unable to update non-existent device credentials!");
112 114 }
113   - DeviceCredentials sameCredentialsId = deviceCredentialsDao.findByCredentialsId(deviceCredentials.getCredentialsId());
  115 + DeviceCredentials sameCredentialsId = deviceCredentialsDao.findByCredentialsId(tenantId, deviceCredentials.getCredentialsId());
114 116 if (sameCredentialsId != null && !sameCredentialsId.getUuidId().equals(deviceCredentials.getUuidId())) {
115 117 throw new DataValidationException("Specified credentials are already registered!");
116 118 }
117 119 }
118 120
119 121 @Override
120   - protected void validateDataImpl(DeviceCredentials deviceCredentials) {
  122 + protected void validateDataImpl(TenantId tenantId, DeviceCredentials deviceCredentials) {
121 123 if (deviceCredentials.getDeviceId() == null) {
122 124 throw new DataValidationException("Device credentials should be assigned to device!");
123 125 }
... ... @@ -127,7 +129,7 @@ public class DeviceCredentialsServiceImpl implements DeviceCredentialsService {
127 129 if (StringUtils.isEmpty(deviceCredentials.getCredentialsId())) {
128 130 throw new DataValidationException("Device credentials id should be specified!");
129 131 }
130   - Device device = deviceService.findDeviceById(deviceCredentials.getDeviceId());
  132 + Device device = deviceService.findDeviceById(tenantId, deviceCredentials.getDeviceId());
131 133 if (device == null) {
132 134 throw new DataValidationException("Can't assign device credentials to non-existent device!");
133 135 }
... ...
... ... @@ -18,6 +18,7 @@ package org.thingsboard.server.dao.device;
18 18 import com.google.common.util.concurrent.ListenableFuture;
19 19 import org.thingsboard.server.common.data.Device;
20 20 import org.thingsboard.server.common.data.EntitySubtype;
  21 +import org.thingsboard.server.common.data.id.TenantId;
21 22 import org.thingsboard.server.common.data.page.TextPageLink;
22 23 import org.thingsboard.server.dao.Dao;
23 24
... ... @@ -37,7 +38,7 @@ public interface DeviceDao extends Dao<Device> {
37 38 * @param device the device object
38 39 * @return saved device object
39 40 */
40   - Device save(Device device);
  41 + Device save(TenantId tenantId, Device device);
41 42
42 43 /**
43 44 * Find devices by tenantId and page link.
... ...
... ... @@ -29,19 +29,19 @@ import java.util.List;
29 29
30 30 public interface DeviceService {
31 31
32   - Device findDeviceById(DeviceId deviceId);
  32 + Device findDeviceById(TenantId tenantId, DeviceId deviceId);
33 33
34   - ListenableFuture<Device> findDeviceByIdAsync(DeviceId deviceId);
  34 + ListenableFuture<Device> findDeviceByIdAsync(TenantId tenantId, DeviceId deviceId);
35 35
36 36 Device findDeviceByTenantIdAndName(TenantId tenantId, String name);
37 37
38 38 Device saveDevice(Device device);
39 39
40   - Device assignDeviceToCustomer(DeviceId deviceId, CustomerId customerId);
  40 + Device assignDeviceToCustomer(TenantId tenantId, DeviceId deviceId, CustomerId customerId);
41 41
42   - Device unassignDeviceFromCustomer(DeviceId deviceId);
  42 + Device unassignDeviceFromCustomer(TenantId tenantId, DeviceId deviceId);
43 43
44   - void deleteDevice(DeviceId deviceId);
  44 + void deleteDevice(TenantId tenantId, DeviceId deviceId);
45 45
46 46 TextPageData<Device> findDevicesByTenantId(TenantId tenantId, TextPageLink pageLink);
47 47
... ... @@ -59,7 +59,7 @@ public interface DeviceService {
59 59
60 60 void unassignCustomerDevices(TenantId tenantId, CustomerId customerId);
61 61
62   - ListenableFuture<List<Device>> findDevicesByQuery(DeviceSearchQuery query);
  62 + ListenableFuture<List<Device>> findDevicesByQuery(TenantId tenantId, DeviceSearchQuery query);
63 63
64 64 ListenableFuture<List<EntitySubtype>> findDeviceTypesByTenantId(TenantId tenantId);
65 65
... ...
... ... @@ -96,17 +96,17 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe
96 96 private CacheManager cacheManager;
97 97
98 98 @Override
99   - public Device findDeviceById(DeviceId deviceId) {
  99 + public Device findDeviceById(TenantId tenantId, DeviceId deviceId) {
100 100 log.trace("Executing findDeviceById [{}]", deviceId);
101 101 validateId(deviceId, INCORRECT_DEVICE_ID + deviceId);
102   - return deviceDao.findById(deviceId.getId());
  102 + return deviceDao.findById(tenantId, deviceId.getId());
103 103 }
104 104
105 105 @Override
106   - public ListenableFuture<Device> findDeviceByIdAsync(DeviceId deviceId) {
  106 + public ListenableFuture<Device> findDeviceByIdAsync(TenantId tenantId, DeviceId deviceId) {
107 107 log.trace("Executing findDeviceById [{}]", deviceId);
108 108 validateId(deviceId, INCORRECT_DEVICE_ID + deviceId);
109   - return deviceDao.findByIdAsync(deviceId.getId());
  109 + return deviceDao.findByIdAsync(tenantId, deviceId.getId());
110 110 }
111 111
112 112 @Cacheable(cacheNames = DEVICE_CACHE, key = "{#tenantId, #name}")
... ... @@ -122,38 +122,38 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe
122 122 @Override
123 123 public Device saveDevice(Device device) {
124 124 log.trace("Executing saveDevice [{}]", device);
125   - deviceValidator.validate(device);
126   - Device savedDevice = deviceDao.save(device);
  125 + deviceValidator.validate(device, Device::getTenantId);
  126 + Device savedDevice = deviceDao.save(device.getTenantId(), device);
127 127 if (device.getId() == null) {
128 128 DeviceCredentials deviceCredentials = new DeviceCredentials();
129 129 deviceCredentials.setDeviceId(new DeviceId(savedDevice.getUuidId()));
130 130 deviceCredentials.setCredentialsType(DeviceCredentialsType.ACCESS_TOKEN);
131 131 deviceCredentials.setCredentialsId(RandomStringUtils.randomAlphanumeric(20));
132   - deviceCredentialsService.createDeviceCredentials(deviceCredentials);
  132 + deviceCredentialsService.createDeviceCredentials(device.getTenantId(), deviceCredentials);
133 133 }
134 134 return savedDevice;
135 135 }
136 136
137 137 @Override
138   - public Device assignDeviceToCustomer(DeviceId deviceId, CustomerId customerId) {
139   - Device device = findDeviceById(deviceId);
  138 + public Device assignDeviceToCustomer(TenantId tenantId, DeviceId deviceId, CustomerId customerId) {
  139 + Device device = findDeviceById(tenantId, deviceId);
140 140 device.setCustomerId(customerId);
141 141 return saveDevice(device);
142 142 }
143 143
144 144 @Override
145   - public Device unassignDeviceFromCustomer(DeviceId deviceId) {
146   - Device device = findDeviceById(deviceId);
  145 + public Device unassignDeviceFromCustomer(TenantId tenantId, DeviceId deviceId) {
  146 + Device device = findDeviceById(tenantId, deviceId);
147 147 device.setCustomerId(null);
148 148 return saveDevice(device);
149 149 }
150 150
151 151 @Override
152   - public void deleteDevice(DeviceId deviceId) {
  152 + public void deleteDevice(TenantId tenantId, DeviceId deviceId) {
153 153 log.trace("Executing deleteDevice [{}]", deviceId);
154 154 validateId(deviceId, INCORRECT_DEVICE_ID + deviceId);
155 155
156   - Device device = deviceDao.findById(deviceId.getId());
  156 + Device device = deviceDao.findById(tenantId, deviceId.getId());
157 157 try {
158 158 List<EntityView> entityViews = entityViewService.findEntityViewsByTenantIdAndEntityIdAsync(device.getTenantId(), deviceId).get();
159 159 if (entityViews != null && !entityViews.isEmpty()) {
... ... @@ -164,11 +164,11 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe
164 164 throw new RuntimeException("Exception while finding entity views for deviceId [" + deviceId + "]", e);
165 165 }
166 166
167   - DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(deviceId);
  167 + DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(tenantId, deviceId);
168 168 if (deviceCredentials != null) {
169   - deviceCredentialsService.deleteDeviceCredentials(deviceCredentials);
  169 + deviceCredentialsService.deleteDeviceCredentials(tenantId, deviceCredentials);
170 170 }
171   - deleteEntityRelations(deviceId);
  171 + deleteEntityRelations(tenantId, deviceId);
172 172
173 173 List<Object> list = new ArrayList<>();
174 174 list.add(device.getTenantId());
... ... @@ -176,7 +176,7 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe
176 176 Cache cache = cacheManager.getCache(DEVICE_CACHE);
177 177 cache.evict(list);
178 178
179   - deviceDao.removeById(deviceId.getId());
  179 + deviceDao.removeById(tenantId, deviceId.getId());
180 180 }
181 181
182 182 @Override
... ... @@ -211,7 +211,7 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe
211 211 public void deleteDevicesByTenantId(TenantId tenantId) {
212 212 log.trace("Executing deleteDevicesByTenantId, tenantId [{}]", tenantId);
213 213 validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
214   - tenantDevicesRemover.removeEntities(tenantId);
  214 + tenantDevicesRemover.removeEntities(tenantId, tenantId);
215 215 }
216 216
217 217 @Override
... ... @@ -250,19 +250,19 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe
250 250 log.trace("Executing unassignCustomerDevices, tenantId [{}], customerId [{}]", tenantId, customerId);
251 251 validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
252 252 validateId(customerId, INCORRECT_CUSTOMER_ID + customerId);
253   - new CustomerDevicesUnassigner(tenantId).removeEntities(customerId);
  253 + customerDeviceUnasigner.removeEntities(tenantId, customerId);
254 254 }
255 255
256 256 @Override
257   - public ListenableFuture<List<Device>> findDevicesByQuery(DeviceSearchQuery query) {
258   - ListenableFuture<List<EntityRelation>> relations = relationService.findByQuery(query.toEntitySearchQuery());
  257 + public ListenableFuture<List<Device>> findDevicesByQuery(TenantId tenantId, DeviceSearchQuery query) {
  258 + ListenableFuture<List<EntityRelation>> relations = relationService.findByQuery(tenantId, query.toEntitySearchQuery());
259 259 ListenableFuture<List<Device>> devices = Futures.transformAsync(relations, r -> {
260 260 EntitySearchDirection direction = query.toEntitySearchQuery().getParameters().getDirection();
261 261 List<ListenableFuture<Device>> futures = new ArrayList<>();
262 262 for (EntityRelation relation : r) {
263 263 EntityId entityId = direction == EntitySearchDirection.FROM ? relation.getTo() : relation.getFrom();
264 264 if (entityId.getEntityType() == EntityType.DEVICE) {
265   - futures.add(findDeviceByIdAsync(new DeviceId(entityId.getId())));
  265 + futures.add(findDeviceByIdAsync(tenantId, new DeviceId(entityId.getId())));
266 266 }
267 267 }
268 268 return Futures.successfulAsList(futures);
... ... @@ -285,7 +285,7 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe
285 285 validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
286 286 ListenableFuture<List<EntitySubtype>> tenantDeviceTypes = deviceDao.findTenantDeviceTypesAsync(tenantId.getId());
287 287 return Futures.transform(tenantDeviceTypes,
288   - (Function<List<EntitySubtype>, List<EntitySubtype>>) deviceTypes -> {
  288 + deviceTypes -> {
289 289 deviceTypes.sort(Comparator.comparing(EntitySubtype::getType));
290 290 return deviceTypes;
291 291 });
... ... @@ -295,7 +295,7 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe
295 295 new DataValidator<Device>() {
296 296
297 297 @Override
298   - protected void validateCreate(Device device) {
  298 + protected void validateCreate(TenantId tenantId, Device device) {
299 299 deviceDao.findDeviceByTenantIdAndName(device.getTenantId().getId(), device.getName()).ifPresent(
300 300 d -> {
301 301 throw new DataValidationException("Device with such name already exists!");
... ... @@ -304,7 +304,7 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe
304 304 }
305 305
306 306 @Override
307   - protected void validateUpdate(Device device) {
  307 + protected void validateUpdate(TenantId tenantId, Device device) {
308 308 deviceDao.findDeviceByTenantIdAndName(device.getTenantId().getId(), device.getName()).ifPresent(
309 309 d -> {
310 310 if (!d.getUuidId().equals(device.getUuidId())) {
... ... @@ -315,7 +315,7 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe
315 315 }
316 316
317 317 @Override
318   - protected void validateDataImpl(Device device) {
  318 + protected void validateDataImpl(TenantId tenantId, Device device) {
319 319 if (StringUtils.isEmpty(device.getType())) {
320 320 throw new DataValidationException("Device type should be specified!");
321 321 }
... ... @@ -325,7 +325,7 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe
325 325 if (device.getTenantId() == null) {
326 326 throw new DataValidationException("Device should be assigned to tenant!");
327 327 } else {
328   - Tenant tenant = tenantDao.findById(device.getTenantId().getId());
  328 + Tenant tenant = tenantDao.findById(device.getTenantId(), device.getTenantId().getId());
329 329 if (tenant == null) {
330 330 throw new DataValidationException("Device is referencing to non-existent tenant!");
331 331 }
... ... @@ -333,7 +333,7 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe
333 333 if (device.getCustomerId() == null) {
334 334 device.setCustomerId(new CustomerId(NULL_UUID));
335 335 } else if (!device.getCustomerId().getId().equals(NULL_UUID)) {
336   - Customer customer = customerDao.findById(device.getCustomerId().getId());
  336 + Customer customer = customerDao.findById(device.getTenantId(), device.getCustomerId().getId());
337 337 if (customer == null) {
338 338 throw new DataValidationException("Can't assign device to non-existent customer!");
339 339 }
... ... @@ -345,36 +345,29 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe
345 345 };
346 346
347 347 private PaginatedRemover<TenantId, Device> tenantDevicesRemover =
348   - new PaginatedRemover<TenantId, Device>() {
  348 + new PaginatedRemover<TenantId, Device>() {
349 349
350   - @Override
351   - protected List<Device> findEntities(TenantId id, TextPageLink pageLink) {
352   - return deviceDao.findDevicesByTenantId(id.getId(), pageLink);
353   - }
354   -
355   - @Override
356   - protected void removeEntity(Device entity) {
357   - deleteDevice(new DeviceId(entity.getUuidId()));
358   - }
359   - };
360   -
361   - private class CustomerDevicesUnassigner extends PaginatedRemover<CustomerId, Device> {
  350 + @Override
  351 + protected List<Device> findEntities(TenantId tenantId, TenantId id, TextPageLink pageLink) {
  352 + return deviceDao.findDevicesByTenantId(id.getId(), pageLink);
  353 + }
362 354
363   - private TenantId tenantId;
  355 + @Override
  356 + protected void removeEntity(TenantId tenantId, Device entity) {
  357 + deleteDevice(tenantId, new DeviceId(entity.getUuidId()));
  358 + }
  359 + };
364 360
365   - CustomerDevicesUnassigner(TenantId tenantId) {
366   - this.tenantId = tenantId;
367   - }
  361 + private PaginatedRemover<CustomerId, Device> customerDeviceUnasigner = new PaginatedRemover<CustomerId, Device>() {
368 362
369 363 @Override
370   - protected List<Device> findEntities(CustomerId id, TextPageLink pageLink) {
  364 + protected List<Device> findEntities(TenantId tenantId, CustomerId id, TextPageLink pageLink) {
371 365 return deviceDao.findDevicesByTenantIdAndCustomerId(tenantId.getId(), id.getId(), pageLink);
372 366 }
373 367
374 368 @Override
375   - protected void removeEntity(Device entity) {
376   - unassignDeviceFromCustomer(new DeviceId(entity.getUuidId()));
  369 + protected void removeEntity(TenantId tenantId, Device entity) {
  370 + unassignDeviceFromCustomer(tenantId, new DeviceId(entity.getUuidId()));
377 371 }
378   -
379   - }
  372 + };
380 373 }
... ...
... ... @@ -18,6 +18,7 @@ package org.thingsboard.server.dao.entity;
18 18 import lombok.extern.slf4j.Slf4j;
19 19 import org.springframework.beans.factory.annotation.Autowired;
20 20 import org.thingsboard.server.common.data.id.EntityId;
  21 +import org.thingsboard.server.common.data.id.TenantId;
21 22 import org.thingsboard.server.dao.relation.RelationService;
22 23
23 24 @Slf4j
... ... @@ -26,9 +27,9 @@ public abstract class AbstractEntityService {
26 27 @Autowired
27 28 protected RelationService relationService;
28 29
29   - protected void deleteEntityRelations(EntityId entityId) {
  30 + protected void deleteEntityRelations(TenantId tenantId, EntityId entityId) {
30 31 log.trace("Executing deleteEntityRelations [{}]", entityId);
31   - relationService.deleteEntityRelations(entityId);
  32 + relationService.deleteEntityRelations(tenantId, entityId);
32 33 }
33 34
34 35 }
... ...
... ... @@ -69,42 +69,42 @@ public class BaseEntityService extends AbstractEntityService implements EntitySe
69 69 private RuleChainService ruleChainService;
70 70
71 71 @Override
72   - public void deleteEntityRelations(EntityId entityId) {
73   - super.deleteEntityRelations(entityId);
  72 + public void deleteEntityRelations(TenantId tenantId, EntityId entityId) {
  73 + super.deleteEntityRelations(tenantId, entityId);
74 74 }
75 75
76 76 @Override
77   - public ListenableFuture<String> fetchEntityNameAsync(EntityId entityId) {
  77 + public ListenableFuture<String> fetchEntityNameAsync(TenantId tenantId, EntityId entityId) {
78 78 log.trace("Executing fetchEntityNameAsync [{}]", entityId);
79 79 ListenableFuture<String> entityName;
80 80 ListenableFuture<? extends HasName> hasName;
81 81 switch (entityId.getEntityType()) {
82 82 case ASSET:
83   - hasName = assetService.findAssetByIdAsync(new AssetId(entityId.getId()));
  83 + hasName = assetService.findAssetByIdAsync(tenantId, new AssetId(entityId.getId()));
84 84 break;
85 85 case DEVICE:
86   - hasName = deviceService.findDeviceByIdAsync(new DeviceId(entityId.getId()));
  86 + hasName = deviceService.findDeviceByIdAsync(tenantId, new DeviceId(entityId.getId()));
87 87 break;
88 88 case ENTITY_VIEW:
89   - hasName = entityViewService.findEntityViewByIdAsync(new EntityViewId(entityId.getId()));
  89 + hasName = entityViewService.findEntityViewByIdAsync(tenantId, new EntityViewId(entityId.getId()));
90 90 break;
91 91 case TENANT:
92   - hasName = tenantService.findTenantByIdAsync(new TenantId(entityId.getId()));
  92 + hasName = tenantService.findTenantByIdAsync(tenantId, new TenantId(entityId.getId()));
93 93 break;
94 94 case CUSTOMER:
95   - hasName = customerService.findCustomerByIdAsync(new CustomerId(entityId.getId()));
  95 + hasName = customerService.findCustomerByIdAsync(tenantId, new CustomerId(entityId.getId()));
96 96 break;
97 97 case USER:
98   - hasName = userService.findUserByIdAsync(new UserId(entityId.getId()));
  98 + hasName = userService.findUserByIdAsync(tenantId, new UserId(entityId.getId()));
99 99 break;
100 100 case DASHBOARD:
101   - hasName = dashboardService.findDashboardInfoByIdAsync(new DashboardId(entityId.getId()));
  101 + hasName = dashboardService.findDashboardInfoByIdAsync(tenantId, new DashboardId(entityId.getId()));
102 102 break;
103 103 case ALARM:
104   - hasName = alarmService.findAlarmByIdAsync(new AlarmId(entityId.getId()));
  104 + hasName = alarmService.findAlarmByIdAsync(tenantId, new AlarmId(entityId.getId()));
105 105 break;
106 106 case RULE_CHAIN:
107   - hasName = ruleChainService.findRuleChainByIdAsync(new RuleChainId(entityId.getId()));
  107 + hasName = ruleChainService.findRuleChainByIdAsync(tenantId, new RuleChainId(entityId.getId()));
108 108 break;
109 109 default:
110 110 throw new IllegalStateException("Not Implemented!");
... ...
... ... @@ -17,11 +17,12 @@ package org.thingsboard.server.dao.entity;
17 17
18 18 import com.google.common.util.concurrent.ListenableFuture;
19 19 import org.thingsboard.server.common.data.id.EntityId;
  20 +import org.thingsboard.server.common.data.id.TenantId;
20 21
21 22 public interface EntityService {
22 23
23   - ListenableFuture<String> fetchEntityNameAsync(EntityId entityId);
  24 + ListenableFuture<String> fetchEntityNameAsync(TenantId tenantId, EntityId entityId);
24 25
25   - void deleteEntityRelations(EntityId entityId);
  26 + void deleteEntityRelations(TenantId tenantId, EntityId entityId);
26 27
27 28 }
... ...
... ... @@ -28,6 +28,7 @@ import org.springframework.stereotype.Component;
28 28 import org.thingsboard.server.common.data.EntitySubtype;
29 29 import org.thingsboard.server.common.data.EntityType;
30 30 import org.thingsboard.server.common.data.EntityView;
  31 +import org.thingsboard.server.common.data.id.TenantId;
31 32 import org.thingsboard.server.common.data.page.TextPageLink;
32 33 import org.thingsboard.server.dao.DaoUtil;
33 34 import org.thingsboard.server.dao.model.EntitySubtypeEntity;
... ... @@ -82,12 +83,12 @@ public class CassandraEntityViewDao extends CassandraAbstractSearchTextDao<Entit
82 83 }
83 84
84 85 @Override
85   - public EntityView save(EntityView domain) {
86   - EntityView savedEntityView = super.save(domain);
  86 + public EntityView save(TenantId tenantId, EntityView domain) {
  87 + EntityView savedEntityView = super.save(domain.getTenantId(), domain);
87 88 EntitySubtype entitySubtype = new EntitySubtype(savedEntityView.getTenantId(), EntityType.ENTITY_VIEW, savedEntityView.getType());
88 89 EntitySubtypeEntity entitySubtypeEntity = new EntitySubtypeEntity(entitySubtype);
89 90 Statement saveStatement = cluster.getMapper(EntitySubtypeEntity.class).saveQuery(entitySubtypeEntity);
90   - executeWrite(saveStatement);
  91 + executeWrite(tenantId, saveStatement);
91 92 return savedEntityView;
92 93 }
93 94
... ... @@ -95,7 +96,7 @@ public class CassandraEntityViewDao extends CassandraAbstractSearchTextDao<Entit
95 96 public List<EntityView> findEntityViewsByTenantId(UUID tenantId, TextPageLink pageLink) {
96 97 log.debug("Try to find entity views by tenantId [{}] and pageLink [{}]", tenantId, pageLink);
97 98 List<EntityViewEntity> entityViewEntities =
98   - findPageWithTextSearch(ENTITY_VIEW_BY_TENANT_AND_SEARCH_TEXT_CF,
  99 + findPageWithTextSearch(new TenantId(tenantId), ENTITY_VIEW_BY_TENANT_AND_SEARCH_TEXT_CF,
99 100 Collections.singletonList(eq(TENANT_ID_PROPERTY, tenantId)), pageLink);
100 101 log.trace("Found entity views [{}] by tenantId [{}] and pageLink [{}]",
101 102 entityViewEntities, tenantId, pageLink);
... ... @@ -106,7 +107,7 @@ public class CassandraEntityViewDao extends CassandraAbstractSearchTextDao<Entit
106 107 public List<EntityView> findEntityViewsByTenantIdAndType(UUID tenantId, String type, TextPageLink pageLink) {
107 108 log.debug("Try to find entity views by tenantId [{}], type [{}] and pageLink [{}]", tenantId, type, pageLink);
108 109 List<EntityViewEntity> entityViewEntities =
109   - findPageWithTextSearch(ENTITY_VIEW_BY_TENANT_BY_TYPE_AND_SEARCH_TEXT_CF,
  110 + findPageWithTextSearch(new TenantId(tenantId), ENTITY_VIEW_BY_TENANT_BY_TYPE_AND_SEARCH_TEXT_CF,
110 111 Arrays.asList(eq(ENTITY_VIEW_TYPE_PROPERTY, type),
111 112 eq(TENANT_ID_PROPERTY, tenantId)), pageLink);
112 113 log.trace("Found entity views [{}] by tenantId [{}], type [{}] and pageLink [{}]",
... ... @@ -119,14 +120,14 @@ public class CassandraEntityViewDao extends CassandraAbstractSearchTextDao<Entit
119 120 Select.Where query = select().from(ENTITY_VIEW_BY_TENANT_AND_NAME).where();
120 121 query.and(eq(ENTITY_VIEW_TENANT_ID_PROPERTY, tenantId));
121 122 query.and(eq(ENTITY_VIEW_NAME_PROPERTY, name));
122   - return Optional.ofNullable(DaoUtil.getData(findOneByStatement(query)));
  123 + return Optional.ofNullable(DaoUtil.getData(findOneByStatement(new TenantId(tenantId), query)));
123 124 }
124 125
125 126 @Override
126 127 public List<EntityView> findEntityViewsByTenantIdAndCustomerId(UUID tenantId, UUID customerId, TextPageLink pageLink) {
127 128 log.debug("Try to find entity views by tenantId [{}], customerId[{}] and pageLink [{}]",
128 129 tenantId, customerId, pageLink);
129   - List<EntityViewEntity> entityViewEntities = findPageWithTextSearch(
  130 + List<EntityViewEntity> entityViewEntities = findPageWithTextSearch(new TenantId(tenantId),
130 131 ENTITY_VIEW_BY_TENANT_AND_CUSTOMER_CF,
131 132 Arrays.asList(eq(CUSTOMER_ID_PROPERTY, customerId), eq(TENANT_ID_PROPERTY, tenantId)),
132 133 pageLink);
... ... @@ -139,7 +140,7 @@ public class CassandraEntityViewDao extends CassandraAbstractSearchTextDao<Entit
139 140 public List<EntityView> findEntityViewsByTenantIdAndCustomerIdAndType(UUID tenantId, UUID customerId, String type, TextPageLink pageLink) {
140 141 log.debug("Try to find entity views by tenantId [{}], customerId[{}], type [{}] and pageLink [{}]",
141 142 tenantId, customerId, type, pageLink);
142   - List<EntityViewEntity> entityViewEntities = findPageWithTextSearch(
  143 + List<EntityViewEntity> entityViewEntities = findPageWithTextSearch(new TenantId(tenantId),
143 144 ENTITY_VIEW_BY_TENANT_AND_CUSTOMER_AND_TYPE_CF,
144 145 Arrays.asList(eq(DEVICE_TYPE_PROPERTY, type), eq(CUSTOMER_ID_PROPERTY, customerId), eq(TENANT_ID_PROPERTY, tenantId)),
145 146 pageLink);
... ... @@ -154,7 +155,7 @@ public class CassandraEntityViewDao extends CassandraAbstractSearchTextDao<Entit
154 155 Select.Where query = select().from(ENTITY_VIEW_BY_TENANT_AND_ENTITY_ID_CF).where();
155 156 query.and(eq(TENANT_ID_PROPERTY, tenantId));
156 157 query.and(eq(ENTITY_ID_COLUMN, entityId));
157   - return findListByStatementAsync(query);
  158 + return findListByStatementAsync(new TenantId(tenantId), query);
158 159 }
159 160
160 161 @Override
... ... @@ -164,7 +165,7 @@ public class CassandraEntityViewDao extends CassandraAbstractSearchTextDao<Entit
164 165 query.and(eq(ENTITY_SUBTYPE_TENANT_ID_PROPERTY, tenantId));
165 166 query.and(eq(ENTITY_SUBTYPE_ENTITY_TYPE_PROPERTY, EntityType.ENTITY_VIEW));
166 167 query.setConsistencyLevel(cluster.getDefaultReadConsistencyLevel());
167   - ResultSetFuture resultSetFuture = executeAsyncRead(query);
  168 + ResultSetFuture resultSetFuture = executeAsyncRead(new TenantId(tenantId), query);
168 169 return Futures.transform(resultSetFuture, new Function<ResultSet, List<EntitySubtype>>() {
169 170 @Nullable
170 171 @Override
... ...
... ... @@ -19,6 +19,7 @@ import com.google.common.util.concurrent.ListenableFuture;
19 19 import org.thingsboard.server.common.data.Device;
20 20 import org.thingsboard.server.common.data.EntitySubtype;
21 21 import org.thingsboard.server.common.data.EntityView;
  22 +import org.thingsboard.server.common.data.id.TenantId;
22 23 import org.thingsboard.server.common.data.page.TextPageLink;
23 24 import org.thingsboard.server.dao.Dao;
24 25
... ... @@ -37,7 +38,7 @@ public interface EntityViewDao extends Dao<EntityView> {
37 38 * @param entityView the entity-view object
38 39 * @return saved entity-view object
39 40 */
40   - EntityView save(EntityView entityView);
  41 + EntityView save(TenantId tenantId, EntityView entityView);
41 42
42 43 /**
43 44 * Find entity views by tenantId and page link.
... ...
... ... @@ -18,6 +18,7 @@ package org.thingsboard.server.dao.entityview;
18 18 import com.google.common.util.concurrent.ListenableFuture;
19 19 import org.thingsboard.server.common.data.EntitySubtype;
20 20 import org.thingsboard.server.common.data.EntityView;
  21 +import org.thingsboard.server.common.data.Tenant;
21 22 import org.thingsboard.server.common.data.entityview.EntityViewSearchQuery;
22 23 import org.thingsboard.server.common.data.id.CustomerId;
23 24 import org.thingsboard.server.common.data.id.EntityId;
... ... @@ -35,13 +36,13 @@ public interface EntityViewService {
35 36
36 37 EntityView saveEntityView(EntityView entityView);
37 38
38   - EntityView assignEntityViewToCustomer(EntityViewId entityViewId, CustomerId customerId);
  39 + EntityView assignEntityViewToCustomer(TenantId tenantId, EntityViewId entityViewId, CustomerId customerId);
39 40
40   - EntityView unassignEntityViewFromCustomer(EntityViewId entityViewId);
  41 + EntityView unassignEntityViewFromCustomer(TenantId tenantId, EntityViewId entityViewId);
41 42
42 43 void unassignCustomerEntityViews(TenantId tenantId, CustomerId customerId);
43 44
44   - EntityView findEntityViewById(EntityViewId entityViewId);
  45 + EntityView findEntityViewById(TenantId tenantId, EntityViewId entityViewId);
45 46
46 47 EntityView findEntityViewByTenantIdAndName(TenantId tenantId, String name);
47 48
... ... @@ -53,13 +54,13 @@ public interface EntityViewService {
53 54
54 55 TextPageData<EntityView> findEntityViewsByTenantIdAndCustomerIdAndType(TenantId tenantId, CustomerId customerId, TextPageLink pageLink, String type);
55 56
56   - ListenableFuture<List<EntityView>> findEntityViewsByQuery(EntityViewSearchQuery query);
  57 + ListenableFuture<List<EntityView>> findEntityViewsByQuery(TenantId tenantId, EntityViewSearchQuery query);
57 58
58   - ListenableFuture<EntityView> findEntityViewByIdAsync(EntityViewId entityViewId);
  59 + ListenableFuture<EntityView> findEntityViewByIdAsync(TenantId tenantId, EntityViewId entityViewId);
59 60
60 61 ListenableFuture<List<EntityView>> findEntityViewsByTenantIdAndEntityIdAsync(TenantId tenantId, EntityId entityId);
61 62
62   - void deleteEntityView(EntityViewId entityViewId);
  63 + void deleteEntityView(TenantId tenantId, EntityViewId entityViewId);
63 64
64 65 void deleteEntityViewsByTenantId(TenantId tenantId);
65 66
... ...
... ... @@ -95,23 +95,23 @@ public class EntityViewServiceImpl extends AbstractEntityService implements Enti
95 95 @Override
96 96 public EntityView saveEntityView(EntityView entityView) {
97 97 log.trace("Executing save entity view [{}]", entityView);
98   - entityViewValidator.validate(entityView);
99   - EntityView savedEntityView = entityViewDao.save(entityView);
  98 + entityViewValidator.validate(entityView, EntityView::getTenantId);
  99 + EntityView savedEntityView = entityViewDao.save(entityView.getTenantId(), entityView);
100 100 return savedEntityView;
101 101 }
102 102
103 103 @CacheEvict(cacheNames = ENTITY_VIEW_CACHE, key = "{#entityViewId}")
104 104 @Override
105   - public EntityView assignEntityViewToCustomer(EntityViewId entityViewId, CustomerId customerId) {
106   - EntityView entityView = findEntityViewById(entityViewId);
  105 + public EntityView assignEntityViewToCustomer(TenantId tenantId, EntityViewId entityViewId, CustomerId customerId) {
  106 + EntityView entityView = findEntityViewById(tenantId, entityViewId);
107 107 entityView.setCustomerId(customerId);
108 108 return saveEntityView(entityView);
109 109 }
110 110
111 111 @CacheEvict(cacheNames = ENTITY_VIEW_CACHE, key = "{#entityViewId}")
112 112 @Override
113   - public EntityView unassignEntityViewFromCustomer(EntityViewId entityViewId) {
114   - EntityView entityView = findEntityViewById(entityViewId);
  113 + public EntityView unassignEntityViewFromCustomer(TenantId tenantId, EntityViewId entityViewId) {
  114 + EntityView entityView = findEntityViewById(tenantId, entityViewId);
115 115 entityView.setCustomerId(null);
116 116 return saveEntityView(entityView);
117 117 }
... ... @@ -121,15 +121,15 @@ public class EntityViewServiceImpl extends AbstractEntityService implements Enti
121 121 log.trace("Executing unassignCustomerEntityViews, tenantId [{}], customerId [{}]", tenantId, customerId);
122 122 validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
123 123 validateId(customerId, INCORRECT_CUSTOMER_ID + customerId);
124   - new CustomerEntityViewsUnAssigner(tenantId).removeEntities(customerId);
  124 + customerEntityViewsUnAssigner.removeEntities(tenantId, customerId);
125 125 }
126 126
127 127 @Cacheable(cacheNames = ENTITY_VIEW_CACHE, key = "{#entityViewId}")
128 128 @Override
129   - public EntityView findEntityViewById(EntityViewId entityViewId) {
  129 + public EntityView findEntityViewById(TenantId tenantId, EntityViewId entityViewId) {
130 130 log.trace("Executing findEntityViewById [{}]", entityViewId);
131 131 validateId(entityViewId, INCORRECT_ENTITY_VIEW_ID + entityViewId);
132   - return entityViewDao.findById(entityViewId.getId());
  132 + return entityViewDao.findById(tenantId, entityViewId.getId());
133 133 }
134 134
135 135 @Cacheable(cacheNames = ENTITY_VIEW_CACHE, key = "{#tenantId, #name}")
... ... @@ -187,15 +187,15 @@ public class EntityViewServiceImpl extends AbstractEntityService implements Enti
187 187 }
188 188
189 189 @Override
190   - public ListenableFuture<List<EntityView>> findEntityViewsByQuery(EntityViewSearchQuery query) {
191   - ListenableFuture<List<EntityRelation>> relations = relationService.findByQuery(query.toEntitySearchQuery());
  190 + public ListenableFuture<List<EntityView>> findEntityViewsByQuery(TenantId tenantId, EntityViewSearchQuery query) {
  191 + ListenableFuture<List<EntityRelation>> relations = relationService.findByQuery(tenantId, query.toEntitySearchQuery());
192 192 ListenableFuture<List<EntityView>> entityViews = Futures.transformAsync(relations, r -> {
193 193 EntitySearchDirection direction = query.toEntitySearchQuery().getParameters().getDirection();
194 194 List<ListenableFuture<EntityView>> futures = new ArrayList<>();
195 195 for (EntityRelation relation : r) {
196 196 EntityId entityId = direction == EntitySearchDirection.FROM ? relation.getTo() : relation.getFrom();
197 197 if (entityId.getEntityType() == EntityType.ENTITY_VIEW) {
198   - futures.add(findEntityViewByIdAsync(new EntityViewId(entityId.getId())));
  198 + futures.add(findEntityViewByIdAsync(tenantId, new EntityViewId(entityId.getId())));
199 199 }
200 200 }
201 201 return Futures.successfulAsList(futures);
... ... @@ -213,10 +213,10 @@ public class EntityViewServiceImpl extends AbstractEntityService implements Enti
213 213 }
214 214
215 215 @Override
216   - public ListenableFuture<EntityView> findEntityViewByIdAsync(EntityViewId entityViewId) {
  216 + public ListenableFuture<EntityView> findEntityViewByIdAsync(TenantId tenantId, EntityViewId entityViewId) {
217 217 log.trace("Executing findEntityViewById [{}]", entityViewId);
218 218 validateId(entityViewId, INCORRECT_ENTITY_VIEW_ID + entityViewId);
219   - return entityViewDao.findByIdAsync(entityViewId.getId());
  219 + return entityViewDao.findByIdAsync(tenantId, entityViewId.getId());
220 220 }
221 221
222 222 @Override
... ... @@ -253,21 +253,21 @@ public class EntityViewServiceImpl extends AbstractEntityService implements Enti
253 253
254 254 @CacheEvict(cacheNames = ENTITY_VIEW_CACHE, key = "{#entityViewId}")
255 255 @Override
256   - public void deleteEntityView(EntityViewId entityViewId) {
  256 + public void deleteEntityView(TenantId tenantId, EntityViewId entityViewId) {
257 257 log.trace("Executing deleteEntityView [{}]", entityViewId);
258 258 validateId(entityViewId, INCORRECT_ENTITY_VIEW_ID + entityViewId);
259   - deleteEntityRelations(entityViewId);
260   - EntityView entityView = entityViewDao.findById(entityViewId.getId());
  259 + deleteEntityRelations(tenantId, entityViewId);
  260 + EntityView entityView = entityViewDao.findById(tenantId, entityViewId.getId());
261 261 cacheManager.getCache(ENTITY_VIEW_CACHE).evict(Arrays.asList(entityView.getTenantId(), entityView.getEntityId()));
262 262 cacheManager.getCache(ENTITY_VIEW_CACHE).evict(Arrays.asList(entityView.getTenantId(), entityView.getName()));
263   - entityViewDao.removeById(entityViewId.getId());
  263 + entityViewDao.removeById(tenantId, entityViewId.getId());
264 264 }
265 265
266 266 @Override
267 267 public void deleteEntityViewsByTenantId(TenantId tenantId) {
268 268 log.trace("Executing deleteEntityViewsByTenantId, tenantId [{}]", tenantId);
269 269 validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
270   - tenantEntityViewRemover.removeEntities(tenantId);
  270 + tenantEntityViewRemover.removeEntities(tenantId, tenantId);
271 271 }
272 272
273 273 @Override
... ... @@ -286,7 +286,7 @@ public class EntityViewServiceImpl extends AbstractEntityService implements Enti
286 286 new DataValidator<EntityView>() {
287 287
288 288 @Override
289   - protected void validateCreate(EntityView entityView) {
  289 + protected void validateCreate(TenantId tenantId, EntityView entityView) {
290 290 entityViewDao.findEntityViewByTenantIdAndName(entityView.getTenantId().getId(), entityView.getName())
291 291 .ifPresent(e -> {
292 292 throw new DataValidationException("Entity view with such name already exists!");
... ... @@ -294,7 +294,7 @@ public class EntityViewServiceImpl extends AbstractEntityService implements Enti
294 294 }
295 295
296 296 @Override
297   - protected void validateUpdate(EntityView entityView) {
  297 + protected void validateUpdate(TenantId tenantId, EntityView entityView) {
298 298 entityViewDao.findEntityViewByTenantIdAndName(entityView.getTenantId().getId(), entityView.getName())
299 299 .ifPresent(e -> {
300 300 if (!e.getUuidId().equals(entityView.getUuidId())) {
... ... @@ -304,7 +304,7 @@ public class EntityViewServiceImpl extends AbstractEntityService implements Enti
304 304 }
305 305
306 306 @Override
307   - protected void validateDataImpl(EntityView entityView) {
  307 + protected void validateDataImpl(TenantId tenantId, EntityView entityView) {
308 308 if (StringUtils.isEmpty(entityView.getType())) {
309 309 throw new DataValidationException("Entity View type should be specified!");
310 310 }
... ... @@ -314,7 +314,7 @@ public class EntityViewServiceImpl extends AbstractEntityService implements Enti
314 314 if (entityView.getTenantId() == null) {
315 315 throw new DataValidationException("Entity view should be assigned to tenant!");
316 316 } else {
317   - Tenant tenant = tenantDao.findById(entityView.getTenantId().getId());
  317 + Tenant tenant = tenantDao.findById(tenantId, entityView.getTenantId().getId());
318 318 if (tenant == null) {
319 319 throw new DataValidationException("Entity view is referencing to non-existent tenant!");
320 320 }
... ... @@ -322,7 +322,7 @@ public class EntityViewServiceImpl extends AbstractEntityService implements Enti
322 322 if (entityView.getCustomerId() == null) {
323 323 entityView.setCustomerId(new CustomerId(NULL_UUID));
324 324 } else if (!entityView.getCustomerId().getId().equals(NULL_UUID)) {
325   - Customer customer = customerDao.findById(entityView.getCustomerId().getId());
  325 + Customer customer = customerDao.findById(tenantId, entityView.getCustomerId().getId());
326 326 if (customer == null) {
327 327 throw new DataValidationException("Can't assign entity view to non-existent customer!");
328 328 }
... ... @@ -333,36 +333,27 @@ public class EntityViewServiceImpl extends AbstractEntityService implements Enti
333 333 }
334 334 };
335 335
336   - private PaginatedRemover<TenantId, EntityView> tenantEntityViewRemover =
337   - new PaginatedRemover<TenantId, EntityView>() {
338   -
339   - @Override
340   - protected List<EntityView> findEntities(TenantId id, TextPageLink pageLink) {
341   - return entityViewDao.findEntityViewsByTenantId(id.getId(), pageLink);
342   - }
343   -
344   - @Override
345   - protected void removeEntity(EntityView entity) {
346   - deleteEntityView(new EntityViewId(entity.getUuidId()));
347   - }
348   - };
349   -
350   - private class CustomerEntityViewsUnAssigner extends PaginatedRemover<CustomerId, EntityView> {
351   -
352   - private TenantId tenantId;
  336 + private PaginatedRemover<TenantId, EntityView> tenantEntityViewRemover = new PaginatedRemover<TenantId, EntityView>() {
  337 + @Override
  338 + protected List<EntityView> findEntities(TenantId tenantId, TenantId id, TextPageLink pageLink) {
  339 + return entityViewDao.findEntityViewsByTenantId(id.getId(), pageLink);
  340 + }
353 341
354   - CustomerEntityViewsUnAssigner(TenantId tenantId) {
355   - this.tenantId = tenantId;
  342 + @Override
  343 + protected void removeEntity(TenantId tenantId, EntityView entity) {
  344 + deleteEntityView(tenantId, new EntityViewId(entity.getUuidId()));
356 345 }
  346 + };
357 347
  348 + private PaginatedRemover<CustomerId, EntityView> customerEntityViewsUnAssigner = new PaginatedRemover<CustomerId, EntityView>() {
358 349 @Override
359   - protected List<EntityView> findEntities(CustomerId id, TextPageLink pageLink) {
  350 + protected List<EntityView> findEntities(TenantId tenantId, CustomerId id, TextPageLink pageLink) {
360 351 return entityViewDao.findEntityViewsByTenantIdAndCustomerId(tenantId.getId(), id.getId(), pageLink);
361 352 }
362 353
363 354 @Override
364   - protected void removeEntity(EntityView entity) {
365   - unassignEntityViewFromCustomer(new EntityViewId(entity.getUuidId()));
  355 + protected void removeEntity(TenantId tenantId, EntityView entity) {
  356 + unassignEntityViewFromCustomer(tenantId, new EntityViewId(entity.getUuidId()));
366 357 }
367   - }
  358 + };
368 359 }
... ...
... ... @@ -40,19 +40,19 @@ public class BaseEventService implements EventService {
40 40
41 41 @Override
42 42 public Event save(Event event) {
43   - eventValidator.validate(event);
44   - return eventDao.save(event);
  43 + eventValidator.validate(event, Event::getTenantId);
  44 + return eventDao.save(event.getTenantId(), event);
45 45 }
46 46
47 47 @Override
48 48 public ListenableFuture<Event> saveAsync(Event event) {
49   - eventValidator.validate(event);
  49 + eventValidator.validate(event, Event::getTenantId);
50 50 return eventDao.saveAsync(event);
51 51 }
52 52
53 53 @Override
54 54 public Optional<Event> saveIfNotExists(Event event) {
55   - eventValidator.validate(event);
  55 + eventValidator.validate(event, Event::getTenantId);
56 56 if (StringUtils.isEmpty(event.getUid())) {
57 57 throw new DataValidationException("Event uid should be specified!.");
58 58 }
... ... @@ -97,7 +97,7 @@ public class BaseEventService implements EventService {
97 97 private DataValidator<Event> eventValidator =
98 98 new DataValidator<Event>() {
99 99 @Override
100   - protected void validateDataImpl(Event event) {
  100 + protected void validateDataImpl(TenantId tenantId, Event event) {
101 101 if (event.getEntityId() == null) {
102 102 throw new DataValidationException("Entity id should be specified!.");
103 103 }
... ...
... ... @@ -64,7 +64,7 @@ public class CassandraBaseEventDao extends CassandraAbstractSearchTimeDao<EventE
64 64 }
65 65
66 66 @Override
67   - public Event save(Event event) {
  67 + public Event save(TenantId tenantId, Event event) {
68 68 try {
69 69 return saveAsync(event).get();
70 70 } catch (InterruptedException | ExecutionException e) {
... ... @@ -85,7 +85,7 @@ public class CassandraBaseEventDao extends CassandraAbstractSearchTimeDao<EventE
85 85 if (StringUtils.isEmpty(event.getUid())) {
86 86 event.setUid(event.getId().toString());
87 87 }
88   - ListenableFuture<Optional<Event>> optionalSave = saveAsync(new EventEntity(event), false);
  88 + ListenableFuture<Optional<Event>> optionalSave = saveAsync(event.getTenantId(), new EventEntity(event), false);
89 89 return Futures.transform(optionalSave, opt -> opt.orElse(null));
90 90 }
91 91
... ... @@ -98,7 +98,7 @@ public class CassandraBaseEventDao extends CassandraAbstractSearchTimeDao<EventE
98 98 if (event.getId() == null) {
99 99 event.setId(new EventId(UUIDs.timeBased()));
100 100 }
101   - return save(new EventEntity(event), true);
  101 + return save(event.getTenantId(), new EventEntity(event), true);
102 102 }
103 103
104 104 @Override
... ... @@ -111,7 +111,7 @@ public class CassandraBaseEventDao extends CassandraAbstractSearchTimeDao<EventE
111 111 .and(eq(ModelConstants.EVENT_TYPE_PROPERTY, eventType))
112 112 .and(eq(ModelConstants.EVENT_UID_PROPERTY, eventUid));
113 113 log.trace("Execute query [{}]", query);
114   - EventEntity entity = findOneByStatement(query);
  114 + EventEntity entity = findOneByStatement(new TenantId(tenantId), query);
115 115 if (log.isTraceEnabled()) {
116 116 log.trace("Search result: [{}] for event entity [{}]", entity != null, entity);
117 117 } else {
... ... @@ -123,7 +123,7 @@ public class CassandraBaseEventDao extends CassandraAbstractSearchTimeDao<EventE
123 123 @Override
124 124 public List<Event> findEvents(UUID tenantId, EntityId entityId, TimePageLink pageLink) {
125 125 log.trace("Try to find events by tenant [{}], entity [{}]and pageLink [{}]", tenantId, entityId, pageLink);
126   - List<EventEntity> entities = findPageWithTimeSearch(EVENT_BY_ID_VIEW_NAME,
  126 + List<EventEntity> entities = findPageWithTimeSearch(new TenantId(tenantId), EVENT_BY_ID_VIEW_NAME,
127 127 Arrays.asList(eq(ModelConstants.EVENT_TENANT_ID_PROPERTY, tenantId),
128 128 eq(ModelConstants.EVENT_ENTITY_TYPE_PROPERTY, entityId.getEntityType()),
129 129 eq(ModelConstants.EVENT_ENTITY_ID_PROPERTY, entityId.getId())),
... ... @@ -135,7 +135,7 @@ public class CassandraBaseEventDao extends CassandraAbstractSearchTimeDao<EventE
135 135 @Override
136 136 public List<Event> findEvents(UUID tenantId, EntityId entityId, String eventType, TimePageLink pageLink) {
137 137 log.trace("Try to find events by tenant [{}], entity [{}], type [{}] and pageLink [{}]", tenantId, entityId, eventType, pageLink);
138   - List<EventEntity> entities = findPageWithTimeSearch(EVENT_BY_TYPE_AND_ID_VIEW_NAME,
  138 + List<EventEntity> entities = findPageWithTimeSearch(new TenantId(tenantId), EVENT_BY_TYPE_AND_ID_VIEW_NAME,
139 139 Arrays.asList(eq(ModelConstants.EVENT_TENANT_ID_PROPERTY, tenantId),
140 140 eq(ModelConstants.EVENT_ENTITY_TYPE_PROPERTY, entityId.getEntityType()),
141 141 eq(ModelConstants.EVENT_ENTITY_ID_PROPERTY, entityId.getId()),
... ... @@ -158,19 +158,19 @@ public class CassandraBaseEventDao extends CassandraAbstractSearchTimeDao<EventE
158 158 query.and(eq(ModelConstants.EVENT_TYPE_PROPERTY, eventType));
159 159 query.limit(limit);
160 160 query.orderBy(QueryBuilder.desc(ModelConstants.EVENT_TYPE_PROPERTY), QueryBuilder.desc(ModelConstants.ID_PROPERTY));
161   - List<EventEntity> entities = findListByStatement(query);
  161 + List<EventEntity> entities = findListByStatement(new TenantId(tenantId), query);
162 162 return DaoUtil.convertDataList(entities);
163 163 }
164 164
165   - private Optional<Event> save(EventEntity entity, boolean ifNotExists) {
  165 + private Optional<Event> save(TenantId tenantId, EventEntity entity, boolean ifNotExists) {
166 166 try {
167   - return saveAsync(entity, ifNotExists).get();
  167 + return saveAsync(tenantId, entity, ifNotExists).get();
168 168 } catch (InterruptedException | ExecutionException e) {
169 169 throw new IllegalStateException("Could not save EventEntity", e);
170 170 }
171 171 }
172 172
173   - private ListenableFuture<Optional<Event>> saveAsync(EventEntity entity, boolean ifNotExists) {
  173 + private ListenableFuture<Optional<Event>> saveAsync(TenantId tenantId, EventEntity entity, boolean ifNotExists) {
174 174 if (entity.getId() == null) {
175 175 entity.setId(UUIDs.timeBased());
176 176 }
... ... @@ -185,7 +185,7 @@ public class CassandraBaseEventDao extends CassandraAbstractSearchTimeDao<EventE
185 185 if (ifNotExists) {
186 186 insert = insert.ifNotExists();
187 187 }
188   - ResultSetFuture resultSetFuture = executeAsyncWrite(insert);
  188 + ResultSetFuture resultSetFuture = executeAsyncWrite(tenantId, insert);
189 189 return Futures.transform(resultSetFuture, rs -> {
190 190 if (rs.wasApplied()) {
191 191 return Optional.of(DaoUtil.getData(entity));
... ...
... ... @@ -18,6 +18,7 @@ package org.thingsboard.server.dao.event;
18 18 import com.google.common.util.concurrent.ListenableFuture;
19 19 import org.thingsboard.server.common.data.Event;
20 20 import org.thingsboard.server.common.data.id.EntityId;
  21 +import org.thingsboard.server.common.data.id.TenantId;
21 22 import org.thingsboard.server.common.data.page.TimePageLink;
22 23 import org.thingsboard.server.dao.Dao;
23 24
... ... @@ -36,7 +37,7 @@ public interface EventDao extends Dao<Event> {
36 37 * @param event the event object
37 38 * @return saved event object
38 39 */
39   - Event save(Event event);
  40 + Event save(TenantId tenantId, Event event);
40 41
41 42 /**
42 43 * Save or update event object async
... ...
... ... @@ -27,6 +27,7 @@ import com.datastax.driver.core.TypeCodec;
27 27 import com.datastax.driver.core.exceptions.CodecNotFoundException;
28 28 import lombok.extern.slf4j.Slf4j;
29 29 import org.springframework.beans.factory.annotation.Autowired;
  30 +import org.thingsboard.server.common.data.id.TenantId;
30 31 import org.thingsboard.server.dao.cassandra.CassandraCluster;
31 32 import org.thingsboard.server.dao.model.type.AuthorityCodec;
32 33 import org.thingsboard.server.dao.model.type.ComponentLifecycleStateCodec;
... ... @@ -84,37 +85,37 @@ public abstract class CassandraAbstractDao {
84 85 }
85 86 }
86 87
87   - protected ResultSet executeRead(Statement statement) {
88   - return execute(statement, defaultReadLevel);
  88 + protected ResultSet executeRead(TenantId tenantId, Statement statement) {
  89 + return execute(tenantId, statement, defaultReadLevel);
89 90 }
90 91
91   - protected ResultSet executeWrite(Statement statement) {
92   - return execute(statement, defaultWriteLevel);
  92 + protected ResultSet executeWrite(TenantId tenantId, Statement statement) {
  93 + return execute(tenantId, statement, defaultWriteLevel);
93 94 }
94 95
95   - protected ResultSetFuture executeAsyncRead(Statement statement) {
96   - return executeAsync(statement, defaultReadLevel);
  96 + protected ResultSetFuture executeAsyncRead(TenantId tenantId, Statement statement) {
  97 + return executeAsync(tenantId, statement, defaultReadLevel);
97 98 }
98 99
99   - protected ResultSetFuture executeAsyncWrite(Statement statement) {
100   - return executeAsync(statement, defaultWriteLevel);
  100 + protected ResultSetFuture executeAsyncWrite(TenantId tenantId, Statement statement) {
  101 + return executeAsync(tenantId, statement, defaultWriteLevel);
101 102 }
102 103
103   - private ResultSet execute(Statement statement, ConsistencyLevel level) {
  104 + private ResultSet execute(TenantId tenantId, Statement statement, ConsistencyLevel level) {
104 105 if (log.isDebugEnabled()) {
105 106 log.debug("Execute cassandra statement {}", statementToString(statement));
106 107 }
107   - return executeAsync(statement, level).getUninterruptibly();
  108 + return executeAsync(tenantId, statement, level).getUninterruptibly();
108 109 }
109 110
110   - private ResultSetFuture executeAsync(Statement statement, ConsistencyLevel level) {
  111 + private ResultSetFuture executeAsync(TenantId tenantId, Statement statement, ConsistencyLevel level) {
111 112 if (log.isDebugEnabled()) {
112 113 log.debug("Execute cassandra async statement {}", statementToString(statement));
113 114 }
114 115 if (statement.getConsistencyLevel() == null) {
115 116 statement.setConsistencyLevel(level);
116 117 }
117   - return rateLimiter.submit(new CassandraStatementTask(getSession(), statement));
  118 + return rateLimiter.submit(new CassandraStatementTask(tenantId, getSession(), statement));
118 119 }
119 120
120 121 private static String statementToString(Statement statement) {
... ...
... ... @@ -27,6 +27,7 @@ import com.google.common.base.Function;
27 27 import com.google.common.util.concurrent.Futures;
28 28 import com.google.common.util.concurrent.ListenableFuture;
29 29 import lombok.extern.slf4j.Slf4j;
  30 +import org.thingsboard.server.common.data.id.TenantId;
30 31 import org.thingsboard.server.dao.Dao;
31 32 import org.thingsboard.server.dao.DaoUtil;
32 33 import org.thingsboard.server.dao.model.BaseEntity;
... ... @@ -56,11 +57,11 @@ public abstract class CassandraAbstractModelDao<E extends BaseEntity<D>, D> exte
56 57 return cluster.getMapper(getColumnFamilyClass());
57 58 }
58 59
59   - protected List<E> findListByStatement(Statement statement) {
  60 + protected List<E> findListByStatement(TenantId tenantId, Statement statement) {
60 61 List<E> list = Collections.emptyList();
61 62 if (statement != null) {
62 63 statement.setConsistencyLevel(cluster.getDefaultReadConsistencyLevel());
63   - ResultSet resultSet = executeRead(statement);
  64 + ResultSet resultSet = executeRead(tenantId, statement);
64 65 Result<E> result = getMapper().map(resultSet);
65 66 if (result != null) {
66 67 list = result.all();
... ... @@ -69,10 +70,10 @@ public abstract class CassandraAbstractModelDao<E extends BaseEntity<D>, D> exte
69 70 return list;
70 71 }
71 72
72   - protected ListenableFuture<List<D>> findListByStatementAsync(Statement statement) {
  73 + protected ListenableFuture<List<D>> findListByStatementAsync(TenantId tenantId, Statement statement) {
73 74 if (statement != null) {
74 75 statement.setConsistencyLevel(cluster.getDefaultReadConsistencyLevel());
75   - ResultSetFuture resultSetFuture = executeAsyncRead(statement);
  76 + ResultSetFuture resultSetFuture = executeAsyncRead(tenantId, statement);
76 77 return Futures.transform(resultSetFuture, new Function<ResultSet, List<D>>() {
77 78 @Nullable
78 79 @Override
... ... @@ -90,11 +91,11 @@ public abstract class CassandraAbstractModelDao<E extends BaseEntity<D>, D> exte
90 91 return Futures.immediateFuture(Collections.emptyList());
91 92 }
92 93
93   - protected E findOneByStatement(Statement statement) {
  94 + protected E findOneByStatement(TenantId tenantId, Statement statement) {
94 95 E object = null;
95 96 if (statement != null) {
96 97 statement.setConsistencyLevel(cluster.getDefaultReadConsistencyLevel());
97   - ResultSet resultSet = executeRead(statement);
  98 + ResultSet resultSet = executeRead(tenantId, statement);
98 99 Result<E> result = getMapper().map(resultSet);
99 100 if (result != null) {
100 101 object = result.one();
... ... @@ -103,10 +104,10 @@ public abstract class CassandraAbstractModelDao<E extends BaseEntity<D>, D> exte
103 104 return object;
104 105 }
105 106
106   - protected ListenableFuture<D> findOneByStatementAsync(Statement statement) {
  107 + protected ListenableFuture<D> findOneByStatementAsync(TenantId tenantId, Statement statement) {
107 108 if (statement != null) {
108 109 statement.setConsistencyLevel(cluster.getDefaultReadConsistencyLevel());
109   - ResultSetFuture resultSetFuture = executeAsyncRead(statement);
  110 + ResultSetFuture resultSetFuture = executeAsyncRead(tenantId, statement);
110 111 return Futures.transform(resultSetFuture, new Function<ResultSet, D>() {
111 112 @Nullable
112 113 @Override
... ... @@ -128,16 +129,16 @@ public abstract class CassandraAbstractModelDao<E extends BaseEntity<D>, D> exte
128 129 return getMapper().saveQuery(dto);
129 130 }
130 131
131   - protected EntityResultSet<E> saveWithResult(E entity) {
  132 + protected EntityResultSet<E> saveWithResult(TenantId tenantId, E entity) {
132 133 log.debug("Save entity {}", entity);
133 134 if (entity.getId() == null) {
134 135 entity.setId(UUIDs.timeBased());
135 136 } else if (isDeleteOnSave()) {
136   - removeById(entity.getId());
  137 + removeById(tenantId, entity.getId());
137 138 }
138 139 Statement saveStatement = getSaveQuery(entity);
139 140 saveStatement.setConsistencyLevel(cluster.getDefaultWriteConsistencyLevel());
140   - ResultSet resultSet = executeWrite(saveStatement);
  141 + ResultSet resultSet = executeWrite(tenantId, saveStatement);
141 142 return new EntityResultSet<>(resultSet, entity);
142 143 }
143 144
... ... @@ -146,7 +147,7 @@ public abstract class CassandraAbstractModelDao<E extends BaseEntity<D>, D> exte
146 147 }
147 148
148 149 @Override
149   - public D save(D domain) {
  150 + public D save(TenantId tenantId, D domain) {
150 151 E entity;
151 152 try {
152 153 entity = getColumnFamilyClass().getConstructor(domain.getClass()).newInstance(domain);
... ... @@ -156,48 +157,39 @@ public abstract class CassandraAbstractModelDao<E extends BaseEntity<D>, D> exte
156 157 }
157 158 entity = updateSearchTextIfPresent(entity);
158 159 log.debug("Saving entity {}", entity);
159   - entity = saveWithResult(entity).getEntity();
  160 + entity = saveWithResult(tenantId, entity).getEntity();
160 161 return DaoUtil.getData(entity);
161 162 }
162 163
163 164 @Override
164   - public D findById(UUID key) {
  165 + public D findById(TenantId tenantId, UUID key) {
165 166 log.debug("Get entity by key {}", key);
166 167 Select.Where query = select().from(getColumnFamilyName()).where(eq(ModelConstants.ID_PROPERTY, key));
167 168 log.trace("Execute query {}", query);
168   - E entity = findOneByStatement(query);
  169 + E entity = findOneByStatement(tenantId, query);
169 170 return DaoUtil.getData(entity);
170 171 }
171 172
172 173 @Override
173   - public ListenableFuture<D> findByIdAsync(UUID key) {
  174 + public ListenableFuture<D> findByIdAsync(TenantId tenantId, UUID key) {
174 175 log.debug("Get entity by key {}", key);
175 176 Select.Where query = select().from(getColumnFamilyName()).where(eq(ModelConstants.ID_PROPERTY, key));
176 177 log.trace("Execute query {}", query);
177   - return findOneByStatementAsync(query);
  178 + return findOneByStatementAsync(tenantId, query);
178 179 }
179 180
180 181 @Override
181   - public boolean removeById(UUID key) {
  182 + public boolean removeById(TenantId tenantId, UUID key) {
182 183 Statement delete = QueryBuilder.delete().all().from(getColumnFamilyName()).where(eq(ModelConstants.ID_PROPERTY, key));
183 184 log.debug("Remove request: {}", delete.toString());
184   - return executeWrite(delete).wasApplied();
  185 + return executeWrite(tenantId, delete).wasApplied();
185 186 }
186 187
187 188 @Override
188   - public List<D> find() {
  189 + public List<D> find(TenantId tenantId) {
189 190 log.debug("Get all entities from column family {}", getColumnFamilyName());
190   - List<E> entities = findListByStatement(QueryBuilder.select().all().from(getColumnFamilyName()).setConsistencyLevel(cluster.getDefaultReadConsistencyLevel()));
  191 + List<E> entities = findListByStatement(tenantId, QueryBuilder.select().all().from(getColumnFamilyName()).setConsistencyLevel(cluster.getDefaultReadConsistencyLevel()));
191 192 return DaoUtil.convertDataList(entities);
192 193 }
193   -
194   - protected static <T> Function<BaseEntity<T>, T> toDataFunction() {
195   - return new Function<BaseEntity<T>, T>() {
196   - @Nullable
197   - @Override
198   - public T apply(@Nullable BaseEntity<T> entity) {
199   - return entity != null ? entity.toData() : null;
200   - }
201   - };
202   - }
  194 +
203 195 }
... ...
... ... @@ -21,6 +21,7 @@ import com.datastax.driver.core.querybuilder.Select;
21 21 import com.datastax.driver.core.querybuilder.Select.Where;
22 22 import lombok.extern.slf4j.Slf4j;
23 23 import org.apache.commons.lang3.StringUtils;
  24 +import org.thingsboard.server.common.data.id.TenantId;
24 25 import org.thingsboard.server.common.data.page.TextPageLink;
25 26 import org.thingsboard.server.dao.model.ModelConstants;
26 27 import org.thingsboard.server.dao.model.SearchTextEntity;
... ... @@ -43,38 +44,38 @@ public abstract class CassandraAbstractSearchTextDao<E extends SearchTextEntity<
43 44 return entity;
44 45 }
45 46
46   - protected List<E> findPageWithTextSearch(String searchView, List<Clause> clauses, TextPageLink pageLink) {
  47 + protected List<E> findPageWithTextSearch(TenantId tenantId, String searchView, List<Clause> clauses, TextPageLink pageLink) {
47 48 Select select = select().from(searchView);
48 49 Where query = select.where();
49 50 for (Clause clause : clauses) {
50 51 query.and(clause);
51   - }
  52 + }
52 53 query.limit(pageLink.getLimit());
53 54 if (!StringUtils.isEmpty(pageLink.getTextOffset())) {
54 55 query.and(eq(ModelConstants.SEARCH_TEXT_PROPERTY, pageLink.getTextOffset()));
55 56 query.and(QueryBuilder.lt(ModelConstants.ID_PROPERTY, pageLink.getIdOffset()));
56   - List<E> result = findListByStatement(query);
  57 + List<E> result = findListByStatement(tenantId, query);
57 58 if (result.size() < pageLink.getLimit()) {
58 59 select = select().from(searchView);
59 60 query = select.where();
60 61 for (Clause clause : clauses) {
61 62 query.and(clause);
62   - }
  63 + }
63 64 query.and(QueryBuilder.gt(ModelConstants.SEARCH_TEXT_PROPERTY, pageLink.getTextOffset()));
64 65 if (!StringUtils.isEmpty(pageLink.getTextSearch())) {
65 66 query.and(QueryBuilder.lt(ModelConstants.SEARCH_TEXT_PROPERTY, pageLink.getTextSearchBound()));
66 67 }
67 68 int limit = pageLink.getLimit() - result.size();
68 69 query.limit(limit);
69   - result.addAll(findListByStatement(query));
  70 + result.addAll(findListByStatement(tenantId, query));
70 71 }
71 72 return result;
72 73 } else if (!StringUtils.isEmpty(pageLink.getTextSearch())) {
73 74 query.and(QueryBuilder.gte(ModelConstants.SEARCH_TEXT_PROPERTY, pageLink.getTextSearch()));
74 75 query.and(QueryBuilder.lt(ModelConstants.SEARCH_TEXT_PROPERTY, pageLink.getTextSearchBound()));
75   - return findListByStatement(query);
  76 + return findListByStatement(tenantId, query);
76 77 } else {
77   - return findListByStatement(query);
  78 + return findListByStatement(tenantId, query);
78 79 }
79 80 }
80 81
... ...
... ... @@ -21,6 +21,7 @@ import com.datastax.driver.core.querybuilder.QueryBuilder;
21 21 import com.datastax.driver.core.querybuilder.Select;
22 22 import com.datastax.driver.core.querybuilder.Select.Where;
23 23 import com.datastax.driver.core.utils.UUIDs;
  24 +import org.thingsboard.server.common.data.id.TenantId;
24 25 import org.thingsboard.server.common.data.page.TimePageLink;
25 26 import org.thingsboard.server.dao.model.BaseEntity;
26 27 import org.thingsboard.server.dao.model.ModelConstants;
... ... @@ -35,24 +36,24 @@ import static com.datastax.driver.core.querybuilder.QueryBuilder.select;
35 36 public abstract class CassandraAbstractSearchTimeDao<E extends BaseEntity<D>, D> extends CassandraAbstractModelDao<E, D> {
36 37
37 38
38   - protected List<E> findPageWithTimeSearch(String searchView, List<Clause> clauses, TimePageLink pageLink) {
39   - return findPageWithTimeSearch(searchView, clauses, Collections.emptyList(), pageLink);
  39 + protected List<E> findPageWithTimeSearch(TenantId tenantId, String searchView, List<Clause> clauses, TimePageLink pageLink) {
  40 + return findPageWithTimeSearch(tenantId, searchView, clauses, Collections.emptyList(), pageLink);
40 41 }
41 42
42   - protected List<E> findPageWithTimeSearch(String searchView, List<Clause> clauses, Ordering ordering, TimePageLink pageLink) {
43   - return findPageWithTimeSearch(searchView, clauses, Collections.singletonList(ordering), pageLink);
  43 + protected List<E> findPageWithTimeSearch(TenantId tenantId, String searchView, List<Clause> clauses, Ordering ordering, TimePageLink pageLink) {
  44 + return findPageWithTimeSearch(tenantId, searchView, clauses, Collections.singletonList(ordering), pageLink);
44 45 }
45 46
46   - protected List<E> findPageWithTimeSearch(String searchView, List<Clause> clauses, List<Ordering> topLevelOrderings, TimePageLink pageLink) {
47   - return findPageWithTimeSearch(searchView, clauses, topLevelOrderings, pageLink, ModelConstants.ID_PROPERTY);
  47 + protected List<E> findPageWithTimeSearch(TenantId tenantId, String searchView, List<Clause> clauses, List<Ordering> topLevelOrderings, TimePageLink pageLink) {
  48 + return findPageWithTimeSearch(tenantId, searchView, clauses, topLevelOrderings, pageLink, ModelConstants.ID_PROPERTY);
48 49 }
49 50
50   - protected List<E> findPageWithTimeSearch(String searchView, List<Clause> clauses, TimePageLink pageLink, String idColumn) {
51   - return findPageWithTimeSearch(searchView, clauses, Collections.emptyList(), pageLink, idColumn);
  51 + protected List<E> findPageWithTimeSearch(TenantId tenantId, String searchView, List<Clause> clauses, TimePageLink pageLink, String idColumn) {
  52 + return findPageWithTimeSearch(tenantId, searchView, clauses, Collections.emptyList(), pageLink, idColumn);
52 53 }
53 54
54   - protected List<E> findPageWithTimeSearch(String searchView, List<Clause> clauses, List<Ordering> topLevelOrderings, TimePageLink pageLink, String idColumn) {
55   - return findListByStatement(buildQuery(searchView, clauses, topLevelOrderings, pageLink, idColumn));
  55 + protected List<E> findPageWithTimeSearch(TenantId tenantId, String searchView, List<Clause> clauses, List<Ordering> topLevelOrderings, TimePageLink pageLink, String idColumn) {
  56 + return findListByStatement(tenantId, buildQuery(searchView, clauses, topLevelOrderings, pageLink, idColumn));
56 57 }
57 58
58 59 public static Where buildQuery(String searchView, List<Clause> clauses, TimePageLink pageLink, String idColumn) {
... ...
... ... @@ -22,11 +22,16 @@ import lombok.extern.slf4j.Slf4j;
22 22 import org.springframework.beans.factory.annotation.Value;
23 23 import org.springframework.scheduling.annotation.Scheduled;
24 24 import org.springframework.stereotype.Component;
  25 +import org.thingsboard.server.common.data.EntityType;
  26 +import org.thingsboard.server.common.data.id.TenantId;
  27 +import org.thingsboard.server.common.msg.tools.TbRateLimits;
25 28 import org.thingsboard.server.dao.util.AbstractBufferedRateExecutor;
26 29 import org.thingsboard.server.dao.util.AsyncTaskContext;
27 30 import org.thingsboard.server.dao.util.NoSqlAnyDao;
28 31
29 32 import javax.annotation.PreDestroy;
  33 +import java.util.concurrent.ConcurrentHashMap;
  34 +import java.util.concurrent.ConcurrentMap;
30 35
31 36 /**
32 37 * Created by ashvayka on 24.10.18.
... ... @@ -42,17 +47,19 @@ public class CassandraBufferedRateExecutor extends AbstractBufferedRateExecutor<
42 47 @Value("${cassandra.query.permit_max_wait_time}") long maxWaitTime,
43 48 @Value("${cassandra.query.dispatcher_threads:2}") int dispatcherThreads,
44 49 @Value("${cassandra.query.callback_threads:2}") int callbackThreads,
45   - @Value("${cassandra.query.poll_ms:50}") long pollMs) {
46   - super(queueLimit, concurrencyLimit, maxWaitTime, dispatcherThreads, callbackThreads, pollMs);
  50 + @Value("${cassandra.query.poll_ms:50}") long pollMs,
  51 + @Value("${cassandra.query.tenant_rate_limits.enabled}") boolean tenantRateLimitsEnabled,
  52 + @Value("${cassandra.query.tenant_rate_limits.configuration}") String tenantRateLimitsConfiguration) {
  53 + super(queueLimit, concurrencyLimit, maxWaitTime, dispatcherThreads, callbackThreads, pollMs, tenantRateLimitsEnabled, tenantRateLimitsConfiguration);
47 54 }
48 55
49 56 @Scheduled(fixedDelayString = "${cassandra.query.rate_limit_print_interval_ms}")
50 57 public void printStats() {
51   - log.info("Permits queueSize [{}] totalAdded [{}] totalLaunched [{}] totalReleased [{}] totalFailed [{}] totalExpired [{}] totalRejected [{}] currBuffer [{}] ",
  58 + log.info("Permits queueSize [{}] totalAdded [{}] totalLaunched [{}] totalReleased [{}] totalFailed [{}] totalExpired [{}] totalRejected [{}] totalRateLimited [{}] currBuffer [{}] ",
52 59 getQueueSize(),
53 60 totalAdded.getAndSet(0), totalLaunched.getAndSet(0), totalReleased.getAndSet(0),
54 61 totalFailed.getAndSet(0), totalExpired.getAndSet(0), totalRejected.getAndSet(0),
55   - concurrencyLevel.get());
  62 + totalRateLimited.getAndSet(0), concurrencyLevel.get());
56 63 }
57 64
58 65 @PreDestroy
... ...
... ... @@ -18,6 +18,7 @@ package org.thingsboard.server.dao.nosql;
18 18 import com.datastax.driver.core.Session;
19 19 import com.datastax.driver.core.Statement;
20 20 import lombok.Data;
  21 +import org.thingsboard.server.common.data.id.TenantId;
21 22 import org.thingsboard.server.dao.util.AsyncTask;
22 23
23 24 /**
... ... @@ -26,6 +27,7 @@ import org.thingsboard.server.dao.util.AsyncTask;
26 27 @Data
27 28 public class CassandraStatementTask implements AsyncTask {
28 29
  30 + private final TenantId tenantId;
29 31 private final Session session;
30 32 private final Statement statement;
31 33
... ...
... ... @@ -29,6 +29,7 @@ import org.springframework.stereotype.Component;
29 29 import org.thingsboard.server.common.data.EntityType;
30 30 import org.thingsboard.server.common.data.id.EntityId;
31 31 import org.thingsboard.server.common.data.id.EntityIdFactory;
  32 +import org.thingsboard.server.common.data.id.TenantId;
32 33 import org.thingsboard.server.common.data.page.TimePageLink;
33 34 import org.thingsboard.server.common.data.relation.EntityRelation;
34 35 import org.thingsboard.server.common.data.relation.RelationTypeGroup;
... ... @@ -83,45 +84,45 @@ public class BaseRelationDao extends CassandraAbstractAsyncDao implements Relati
83 84 }
84 85
85 86 @Override
86   - public ListenableFuture<List<EntityRelation>> findAllByFrom(EntityId from, RelationTypeGroup typeGroup) {
  87 + public ListenableFuture<List<EntityRelation>> findAllByFrom(TenantId tenantId, EntityId from, RelationTypeGroup typeGroup) {
87 88 BoundStatement stmt = getFindAllByFromStmt().bind()
88 89 .setUUID(0, from.getId())
89 90 .setString(1, from.getEntityType().name())
90 91 .set(2, typeGroup, relationTypeGroupCodec);
91   - return executeAsyncRead(from, stmt);
  92 + return executeAsyncRead(tenantId, from, stmt);
92 93 }
93 94
94 95 @Override
95   - public ListenableFuture<List<EntityRelation>> findAllByFromAndType(EntityId from, String relationType, RelationTypeGroup typeGroup) {
  96 + public ListenableFuture<List<EntityRelation>> findAllByFromAndType(TenantId tenantId, EntityId from, String relationType, RelationTypeGroup typeGroup) {
96 97 BoundStatement stmt = getFindAllByFromAndTypeStmt().bind()
97 98 .setUUID(0, from.getId())
98 99 .setString(1, from.getEntityType().name())
99 100 .set(2, typeGroup, relationTypeGroupCodec)
100 101 .setString(3, relationType);
101   - return executeAsyncRead(from, stmt);
  102 + return executeAsyncRead(tenantId, from, stmt);
102 103 }
103 104
104 105 @Override
105   - public ListenableFuture<List<EntityRelation>> findAllByTo(EntityId to, RelationTypeGroup typeGroup) {
  106 + public ListenableFuture<List<EntityRelation>> findAllByTo(TenantId tenantId, EntityId to, RelationTypeGroup typeGroup) {
106 107 BoundStatement stmt = getFindAllByToStmt().bind()
107 108 .setUUID(0, to.getId())
108 109 .setString(1, to.getEntityType().name())
109 110 .set(2, typeGroup, relationTypeGroupCodec);
110   - return executeAsyncRead(to, stmt);
  111 + return executeAsyncRead(tenantId, to, stmt);
111 112 }
112 113
113 114 @Override
114   - public ListenableFuture<List<EntityRelation>> findAllByToAndType(EntityId to, String relationType, RelationTypeGroup typeGroup) {
  115 + public ListenableFuture<List<EntityRelation>> findAllByToAndType(TenantId tenantId, EntityId to, String relationType, RelationTypeGroup typeGroup) {
115 116 BoundStatement stmt = getFindAllByToAndTypeStmt().bind()
116 117 .setUUID(0, to.getId())
117 118 .setString(1, to.getEntityType().name())
118 119 .set(2, typeGroup, relationTypeGroupCodec)
119 120 .setString(3, relationType);
120   - return executeAsyncRead(to, stmt);
  121 + return executeAsyncRead(tenantId, to, stmt);
121 122 }
122 123
123 124 @Override
124   - public ListenableFuture<Boolean> checkRelation(EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup) {
  125 + public ListenableFuture<Boolean> checkRelation(TenantId tenantId, EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup) {
125 126 BoundStatement stmt = getCheckRelationStmt().bind()
126 127 .setUUID(0, from.getId())
127 128 .setString(1, from.getEntityType().name())
... ... @@ -129,11 +130,11 @@ public class BaseRelationDao extends CassandraAbstractAsyncDao implements Relati
129 130 .setString(3, to.getEntityType().name())
130 131 .set(4, typeGroup, relationTypeGroupCodec)
131 132 .setString(5, relationType);
132   - return getFuture(executeAsyncRead(stmt), rs -> rs != null ? rs.one() != null : false);
  133 + return getFuture(executeAsyncRead(tenantId, stmt), rs -> rs != null ? rs.one() != null : false);
133 134 }
134 135
135 136 @Override
136   - public ListenableFuture<EntityRelation> getRelation(EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup) {
  137 + public ListenableFuture<EntityRelation> getRelation(TenantId tenantId, EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup) {
137 138 BoundStatement stmt = getCheckRelationStmt().bind()
138 139 .setUUID(0, from.getId())
139 140 .setString(1, from.getEntityType().name())
... ... @@ -141,24 +142,24 @@ public class BaseRelationDao extends CassandraAbstractAsyncDao implements Relati
141 142 .setString(3, to.getEntityType().name())
142 143 .set(4, typeGroup, relationTypeGroupCodec)
143 144 .setString(5, relationType);
144   - return getFuture(executeAsyncRead(stmt), rs -> rs != null ? getEntityRelation(rs.one()) : null);
  145 + return getFuture(executeAsyncRead(tenantId, stmt), rs -> rs != null ? getEntityRelation(rs.one()) : null);
145 146 }
146 147
147 148 @Override
148   - public boolean saveRelation(EntityRelation relation) {
149   - BoundStatement stmt = getSaveRelationStatement(relation);
150   - ResultSet rs = executeWrite(stmt);
  149 + public boolean saveRelation(TenantId tenantId, EntityRelation relation) {
  150 + BoundStatement stmt = getSaveRelationStatement(tenantId, relation);
  151 + ResultSet rs = executeWrite(tenantId, stmt);
151 152 return rs.wasApplied();
152 153 }
153 154
154 155 @Override
155   - public ListenableFuture<Boolean> saveRelationAsync(EntityRelation relation) {
156   - BoundStatement stmt = getSaveRelationStatement(relation);
157   - ResultSetFuture future = executeAsyncWrite(stmt);
  156 + public ListenableFuture<Boolean> saveRelationAsync(TenantId tenantId, EntityRelation relation) {
  157 + BoundStatement stmt = getSaveRelationStatement(tenantId, relation);
  158 + ResultSetFuture future = executeAsyncWrite(tenantId, stmt);
158 159 return getBooleanListenableFuture(future);
159 160 }
160 161
161   - private BoundStatement getSaveRelationStatement(EntityRelation relation) {
  162 + private BoundStatement getSaveRelationStatement(TenantId tenantId, EntityRelation relation) {
162 163 BoundStatement stmt = getSaveStmt().bind()
163 164 .setUUID(0, relation.getFrom().getId())
164 165 .setString(1, relation.getFrom().getEntityType().name())
... ... @@ -171,30 +172,30 @@ public class BaseRelationDao extends CassandraAbstractAsyncDao implements Relati
171 172 }
172 173
173 174 @Override
174   - public boolean deleteRelation(EntityRelation relation) {
175   - return deleteRelation(relation.getFrom(), relation.getTo(), relation.getType(), relation.getTypeGroup());
  175 + public boolean deleteRelation(TenantId tenantId, EntityRelation relation) {
  176 + return deleteRelation(tenantId, relation.getFrom(), relation.getTo(), relation.getType(), relation.getTypeGroup());
176 177 }
177 178
178 179 @Override
179   - public ListenableFuture<Boolean> deleteRelationAsync(EntityRelation relation) {
180   - return deleteRelationAsync(relation.getFrom(), relation.getTo(), relation.getType(), relation.getTypeGroup());
  180 + public ListenableFuture<Boolean> deleteRelationAsync(TenantId tenantId, EntityRelation relation) {
  181 + return deleteRelationAsync(tenantId, relation.getFrom(), relation.getTo(), relation.getType(), relation.getTypeGroup());
181 182 }
182 183
183 184 @Override
184   - public boolean deleteRelation(EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup) {
185   - BoundStatement stmt = getDeleteRelationStatement(from, to, relationType, typeGroup);
186   - ResultSet rs = executeWrite(stmt);
  185 + public boolean deleteRelation(TenantId tenantId, EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup) {
  186 + BoundStatement stmt = getDeleteRelationStatement(tenantId, from, to, relationType, typeGroup);
  187 + ResultSet rs = executeWrite(tenantId, stmt);
187 188 return rs.wasApplied();
188 189 }
189 190
190 191 @Override
191   - public ListenableFuture<Boolean> deleteRelationAsync(EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup) {
192   - BoundStatement stmt = getDeleteRelationStatement(from, to, relationType, typeGroup);
193   - ResultSetFuture future = executeAsyncWrite(stmt);
  192 + public ListenableFuture<Boolean> deleteRelationAsync(TenantId tenantId, EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup) {
  193 + BoundStatement stmt = getDeleteRelationStatement(tenantId, from, to, relationType, typeGroup);
  194 + ResultSetFuture future = executeAsyncWrite(tenantId, stmt);
194 195 return getBooleanListenableFuture(future);
195 196 }
196 197
197   - private BoundStatement getDeleteRelationStatement(EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup) {
  198 + private BoundStatement getDeleteRelationStatement(TenantId tenantId, EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup) {
198 199 BoundStatement stmt = getDeleteStmt().bind()
199 200 .setUUID(0, from.getId())
200 201 .setString(1, from.getEntityType().name())
... ... @@ -206,26 +207,26 @@ public class BaseRelationDao extends CassandraAbstractAsyncDao implements Relati
206 207 }
207 208
208 209 @Override
209   - public boolean deleteOutboundRelations(EntityId entity) {
  210 + public boolean deleteOutboundRelations(TenantId tenantId, EntityId entity) {
210 211 BoundStatement stmt = getDeleteAllByEntityStmt().bind()
211 212 .setUUID(0, entity.getId())
212 213 .setString(1, entity.getEntityType().name());
213   - ResultSet rs = executeWrite(stmt);
  214 + ResultSet rs = executeWrite(tenantId, stmt);
214 215 return rs.wasApplied();
215 216 }
216 217
217 218
218 219 @Override
219   - public ListenableFuture<Boolean> deleteOutboundRelationsAsync(EntityId entity) {
  220 + public ListenableFuture<Boolean> deleteOutboundRelationsAsync(TenantId tenantId, EntityId entity) {
220 221 BoundStatement stmt = getDeleteAllByEntityStmt().bind()
221 222 .setUUID(0, entity.getId())
222 223 .setString(1, entity.getEntityType().name());
223   - ResultSetFuture future = executeAsyncWrite(stmt);
  224 + ResultSetFuture future = executeAsyncWrite(tenantId, stmt);
224 225 return getBooleanListenableFuture(future);
225 226 }
226 227
227 228 @Override
228   - public ListenableFuture<List<EntityRelation>> findRelations(EntityId from, String relationType, RelationTypeGroup typeGroup, EntityType childType, TimePageLink pageLink) {
  229 + public ListenableFuture<List<EntityRelation>> findRelations(TenantId tenantId, EntityId from, String relationType, RelationTypeGroup typeGroup, EntityType childType, TimePageLink pageLink) {
229 230 Select.Where query = CassandraAbstractSearchTimeDao.buildQuery(ModelConstants.RELATION_BY_TYPE_AND_CHILD_TYPE_VIEW_NAME,
230 231 Arrays.asList(eq(ModelConstants.RELATION_FROM_ID_PROPERTY, from.getId()),
231 232 eq(ModelConstants.RELATION_FROM_TYPE_PROPERTY, from.getEntityType().name()),
... ... @@ -241,7 +242,7 @@ public class BaseRelationDao extends CassandraAbstractAsyncDao implements Relati
241 242 QueryBuilder.asc(ModelConstants.RELATION_TO_TYPE_PROPERTY)
242 243 ),
243 244 pageLink, ModelConstants.RELATION_TO_ID_PROPERTY);
244   - return getFuture(executeAsyncRead(query), this::getEntityRelations);
  245 + return getFuture(executeAsyncRead(tenantId, query), this::getEntityRelations);
245 246 }
246 247
247 248 private PreparedStatement getSaveStmt() {
... ... @@ -347,9 +348,9 @@ public class BaseRelationDao extends CassandraAbstractAsyncDao implements Relati
347 348 return EntityIdFactory.getByTypeAndUuid(row.getString(typeColumn), row.getUUID(uuidColumn));
348 349 }
349 350
350   - private ListenableFuture<List<EntityRelation>> executeAsyncRead(EntityId from, BoundStatement stmt) {
  351 + private ListenableFuture<List<EntityRelation>> executeAsyncRead(TenantId tenantId, EntityId from, BoundStatement stmt) {
351 352 log.debug("Generated query [{}] for entity {}", stmt, from);
352   - return getFuture(executeAsyncRead(stmt), rs -> getEntityRelations(rs));
  353 + return getFuture(executeAsyncRead(tenantId, stmt), rs -> getEntityRelations(rs));
353 354 }
354 355
355 356 private ListenableFuture<Boolean> getBooleanListenableFuture(ResultSetFuture rsFuture) {
... ...
... ... @@ -26,7 +26,9 @@ import org.springframework.cache.annotation.Cacheable;
26 26 import org.springframework.cache.annotation.Caching;
27 27 import org.springframework.stereotype.Service;
28 28 import org.springframework.util.StringUtils;
  29 +import org.thingsboard.server.common.data.Tenant;
29 30 import org.thingsboard.server.common.data.id.EntityId;
  31 +import org.thingsboard.server.common.data.id.TenantId;
30 32 import org.thingsboard.server.common.data.relation.EntityRelation;
31 33 import org.thingsboard.server.common.data.relation.EntityRelationInfo;
32 34 import org.thingsboard.server.common.data.relation.EntityRelationsQuery;
... ... @@ -66,27 +68,27 @@ public class BaseRelationService implements RelationService {
66 68 private CacheManager cacheManager;
67 69
68 70 @Override
69   - public ListenableFuture<Boolean> checkRelation(EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup) {
  71 + public ListenableFuture<Boolean> checkRelation(TenantId tenantId, EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup) {
70 72 log.trace("Executing checkRelation [{}][{}][{}][{}]", from, to, relationType, typeGroup);
71 73 validate(from, to, relationType, typeGroup);
72   - return relationDao.checkRelation(from, to, relationType, typeGroup);
  74 + return relationDao.checkRelation(tenantId, from, to, relationType, typeGroup);
73 75 }
74 76
75 77 @Cacheable(cacheNames = RELATIONS_CACHE, key = "{#from, #to, #relationType, #typeGroup}")
76 78 @Override
77   - public EntityRelation getRelation(EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup) {
  79 + public EntityRelation getRelation(TenantId tenantId, EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup) {
78 80 try {
79   - return getRelationAsync(from, to, relationType, typeGroup).get();
  81 + return getRelationAsync(tenantId, from, to, relationType, typeGroup).get();
80 82 } catch (InterruptedException | ExecutionException e) {
81 83 throw new RuntimeException(e);
82 84 }
83 85 }
84 86
85 87 @Override
86   - public ListenableFuture<EntityRelation> getRelationAsync(EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup) {
  88 + public ListenableFuture<EntityRelation> getRelationAsync(TenantId tenantId, EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup) {
87 89 log.trace("Executing EntityRelation [{}][{}][{}][{}]", from, to, relationType, typeGroup);
88 90 validate(from, to, relationType, typeGroup);
89   - return relationDao.getRelation(from, to, relationType, typeGroup);
  91 + return relationDao.getRelation(tenantId, from, to, relationType, typeGroup);
90 92 }
91 93
92 94 @Caching(evict = {
... ... @@ -97,10 +99,10 @@ public class BaseRelationService implements RelationService {
97 99 @CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.to, #relation.type, #relation.typeGroup, 'TO'}")
98 100 })
99 101 @Override
100   - public boolean saveRelation(EntityRelation relation) {
  102 + public boolean saveRelation(TenantId tenantId, EntityRelation relation) {
101 103 log.trace("Executing saveRelation [{}]", relation);
102 104 validate(relation);
103   - return relationDao.saveRelation(relation);
  105 + return relationDao.saveRelation(tenantId, relation);
104 106 }
105 107
106 108 @Caching(evict = {
... ... @@ -111,10 +113,10 @@ public class BaseRelationService implements RelationService {
111 113 @CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.to, #relation.type, #relation.typeGroup, 'TO'}")
112 114 })
113 115 @Override
114   - public ListenableFuture<Boolean> saveRelationAsync(EntityRelation relation) {
  116 + public ListenableFuture<Boolean> saveRelationAsync(TenantId tenantId, EntityRelation relation) {
115 117 log.trace("Executing saveRelationAsync [{}]", relation);
116 118 validate(relation);
117   - return relationDao.saveRelationAsync(relation);
  119 + return relationDao.saveRelationAsync(tenantId, relation);
118 120 }
119 121
120 122 @Caching(evict = {
... ... @@ -125,10 +127,10 @@ public class BaseRelationService implements RelationService {
125 127 @CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.to, #relation.type, #relation.typeGroup, 'TO'}")
126 128 })
127 129 @Override
128   - public boolean deleteRelation(EntityRelation relation) {
  130 + public boolean deleteRelation(TenantId tenantId, EntityRelation relation) {
129 131 log.trace("Executing deleteRelation [{}]", relation);
130 132 validate(relation);
131   - return relationDao.deleteRelation(relation);
  133 + return relationDao.deleteRelation(tenantId, relation);
132 134 }
133 135
134 136 @Caching(evict = {
... ... @@ -139,10 +141,10 @@ public class BaseRelationService implements RelationService {
139 141 @CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.to, #relation.type, #relation.typeGroup, 'TO'}")
140 142 })
141 143 @Override
142   - public ListenableFuture<Boolean> deleteRelationAsync(EntityRelation relation) {
  144 + public ListenableFuture<Boolean> deleteRelationAsync(TenantId tenantId, EntityRelation relation) {
143 145 log.trace("Executing deleteRelationAsync [{}]", relation);
144 146 validate(relation);
145   - return relationDao.deleteRelationAsync(relation);
  147 + return relationDao.deleteRelationAsync(tenantId, relation);
146 148 }
147 149
148 150 @Caching(evict = {
... ... @@ -153,10 +155,10 @@ public class BaseRelationService implements RelationService {
153 155 @CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#to, #relationType, #typeGroup, 'TO'}")
154 156 })
155 157 @Override
156   - public boolean deleteRelation(EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup) {
  158 + public boolean deleteRelation(TenantId tenantId, EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup) {
157 159 log.trace("Executing deleteRelation [{}][{}][{}][{}]", from, to, relationType, typeGroup);
158 160 validate(from, to, relationType, typeGroup);
159   - return relationDao.deleteRelation(from, to, relationType, typeGroup);
  161 + return relationDao.deleteRelation(tenantId, from, to, relationType, typeGroup);
160 162 }
161 163
162 164 @Caching(evict = {
... ... @@ -167,69 +169,69 @@ public class BaseRelationService implements RelationService {
167 169 @CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#to, #relationType, #typeGroup, 'TO'}")
168 170 })
169 171 @Override
170   - public ListenableFuture<Boolean> deleteRelationAsync(EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup) {
  172 + public ListenableFuture<Boolean> deleteRelationAsync(TenantId tenantId, EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup) {
171 173 log.trace("Executing deleteRelationAsync [{}][{}][{}][{}]", from, to, relationType, typeGroup);
172 174 validate(from, to, relationType, typeGroup);
173   - return relationDao.deleteRelationAsync(from, to, relationType, typeGroup);
  175 + return relationDao.deleteRelationAsync(tenantId, from, to, relationType, typeGroup);
174 176 }
175 177
176 178 @Override
177   - public void deleteEntityRelations(EntityId entityId) {
  179 + public void deleteEntityRelations(TenantId tenantId, EntityId entityId) {
178 180 try {
179   - deleteEntityRelationsAsync(entityId).get();
  181 + deleteEntityRelationsAsync(tenantId, entityId).get();
180 182 } catch (InterruptedException | ExecutionException e) {
181 183 throw new RuntimeException(e);
182 184 }
183 185 }
184 186
185 187 @Override
186   - public ListenableFuture<Void> deleteEntityRelationsAsync(EntityId entityId) {
  188 + public ListenableFuture<Void> deleteEntityRelationsAsync(TenantId tenantId, EntityId entityId) {
187 189 Cache cache = cacheManager.getCache(RELATIONS_CACHE);
188 190 log.trace("Executing deleteEntityRelationsAsync [{}]", entityId);
189 191 validate(entityId);
190 192 List<ListenableFuture<List<EntityRelation>>> inboundRelationsList = new ArrayList<>();
191 193 for (RelationTypeGroup typeGroup : RelationTypeGroup.values()) {
192   - inboundRelationsList.add(relationDao.findAllByTo(entityId, typeGroup));
  194 + inboundRelationsList.add(relationDao.findAllByTo(tenantId, entityId, typeGroup));
193 195 }
194 196
195 197 ListenableFuture<List<List<EntityRelation>>> inboundRelations = Futures.allAsList(inboundRelationsList);
196 198
197 199 List<ListenableFuture<List<EntityRelation>>> outboundRelationsList = new ArrayList<>();
198 200 for (RelationTypeGroup typeGroup : RelationTypeGroup.values()) {
199   - outboundRelationsList.add(relationDao.findAllByFrom(entityId, typeGroup));
  201 + outboundRelationsList.add(relationDao.findAllByFrom(tenantId, entityId, typeGroup));
200 202 }
201 203
202 204 ListenableFuture<List<List<EntityRelation>>> outboundRelations = Futures.allAsList(outboundRelationsList);
203 205
204 206 ListenableFuture<List<Boolean>> inboundDeletions = Futures.transformAsync(inboundRelations,
205 207 relations -> {
206   - List<ListenableFuture<Boolean>> results = deleteRelationGroupsAsync(relations, cache, true);
  208 + List<ListenableFuture<Boolean>> results = deleteRelationGroupsAsync(tenantId, relations, cache, true);
207 209 return Futures.allAsList(results);
208 210 });
209 211
210 212 ListenableFuture<List<Boolean>> outboundDeletions = Futures.transformAsync(outboundRelations,
211 213 relations -> {
212   - List<ListenableFuture<Boolean>> results = deleteRelationGroupsAsync(relations, cache, false);
  214 + List<ListenableFuture<Boolean>> results = deleteRelationGroupsAsync(tenantId, relations, cache, false);
213 215 return Futures.allAsList(results);
214 216 });
215 217
216 218 ListenableFuture<List<List<Boolean>>> deletionsFuture = Futures.allAsList(inboundDeletions, outboundDeletions);
217 219
218   - return Futures.transform(Futures.transformAsync(deletionsFuture, (deletions) -> relationDao.deleteOutboundRelationsAsync(entityId)), result -> null);
  220 + return Futures.transform(Futures.transformAsync(deletionsFuture, (deletions) -> relationDao.deleteOutboundRelationsAsync(tenantId, entityId)), result -> null);
219 221 }
220 222
221   - private List<ListenableFuture<Boolean>> deleteRelationGroupsAsync(List<List<EntityRelation>> relations, Cache cache, boolean deleteFromDb) {
  223 + private List<ListenableFuture<Boolean>> deleteRelationGroupsAsync(TenantId tenantId, List<List<EntityRelation>> relations, Cache cache, boolean deleteFromDb) {
222 224 List<ListenableFuture<Boolean>> results = new ArrayList<>();
223 225 for (List<EntityRelation> relationList : relations) {
224   - relationList.forEach(relation -> results.add(deleteAsync(cache, relation, deleteFromDb)));
  226 + relationList.forEach(relation -> results.add(deleteAsync(tenantId, cache, relation, deleteFromDb)));
225 227 }
226 228 return results;
227 229 }
228 230
229   - private ListenableFuture<Boolean> deleteAsync(Cache cache, EntityRelation relation, boolean deleteFromDb) {
  231 + private ListenableFuture<Boolean> deleteAsync(TenantId tenantId, Cache cache, EntityRelation relation, boolean deleteFromDb) {
230 232 cacheEviction(relation, cache);
231 233 if (deleteFromDb) {
232   - return relationDao.deleteRelationAsync(relation);
  234 + return relationDao.deleteRelationAsync(tenantId, relation);
233 235 } else {
234 236 return Futures.immediateFuture(false);
235 237 }
... ... @@ -272,18 +274,18 @@ public class BaseRelationService implements RelationService {
272 274
273 275 @Cacheable(cacheNames = RELATIONS_CACHE, key = "{#from, #typeGroup, 'FROM'}")
274 276 @Override
275   - public List<EntityRelation> findByFrom(EntityId from, RelationTypeGroup typeGroup) {
  277 + public List<EntityRelation> findByFrom(TenantId tenantId, EntityId from, RelationTypeGroup typeGroup) {
276 278 validate(from);
277 279 validateTypeGroup(typeGroup);
278 280 try {
279   - return relationDao.findAllByFrom(from, typeGroup).get();
  281 + return relationDao.findAllByFrom(tenantId, from, typeGroup).get();
280 282 } catch (InterruptedException | ExecutionException e) {
281 283 throw new RuntimeException(e);
282 284 }
283 285 }
284 286
285 287 @Override
286   - public ListenableFuture<List<EntityRelation>> findByFromAsync(EntityId from, RelationTypeGroup typeGroup) {
  288 + public ListenableFuture<List<EntityRelation>> findByFromAsync(TenantId tenantId, EntityId from, RelationTypeGroup typeGroup) {
287 289 log.trace("Executing findByFrom [{}][{}]", from, typeGroup);
288 290 validate(from);
289 291 validateTypeGroup(typeGroup);
... ... @@ -298,7 +300,7 @@ public class BaseRelationService implements RelationService {
298 300 if (fromCache != null) {
299 301 return Futures.immediateFuture(fromCache);
300 302 } else {
301   - ListenableFuture<List<EntityRelation>> relationsFuture = relationDao.findAllByFrom(from, typeGroup);
  303 + ListenableFuture<List<EntityRelation>> relationsFuture = relationDao.findAllByFrom(tenantId, from, typeGroup);
302 304 Futures.addCallback(relationsFuture,
303 305 new FutureCallback<List<EntityRelation>>() {
304 306 @Override
... ... @@ -313,16 +315,16 @@ public class BaseRelationService implements RelationService {
313 315 }
314 316
315 317 @Override
316   - public ListenableFuture<List<EntityRelationInfo>> findInfoByFrom(EntityId from, RelationTypeGroup typeGroup) {
  318 + public ListenableFuture<List<EntityRelationInfo>> findInfoByFrom(TenantId tenantId, EntityId from, RelationTypeGroup typeGroup) {
317 319 log.trace("Executing findInfoByFrom [{}][{}]", from, typeGroup);
318 320 validate(from);
319 321 validateTypeGroup(typeGroup);
320   - ListenableFuture<List<EntityRelation>> relations = relationDao.findAllByFrom(from, typeGroup);
  322 + ListenableFuture<List<EntityRelation>> relations = relationDao.findAllByFrom(tenantId, from, typeGroup);
321 323 return Futures.transformAsync(relations,
322 324 relations1 -> {
323 325 List<ListenableFuture<EntityRelationInfo>> futures = new ArrayList<>();
324 326 relations1.forEach(relation ->
325   - futures.add(fetchRelationInfoAsync(relation,
  327 + futures.add(fetchRelationInfoAsync(tenantId, relation,
326 328 EntityRelation::getTo,
327 329 EntityRelationInfo::setToName))
328 330 );
... ... @@ -332,37 +334,37 @@ public class BaseRelationService implements RelationService {
332 334
333 335 @Cacheable(cacheNames = RELATIONS_CACHE, key = "{#from, #relationType, #typeGroup, 'FROM'}")
334 336 @Override
335   - public List<EntityRelation> findByFromAndType(EntityId from, String relationType, RelationTypeGroup typeGroup) {
  337 + public List<EntityRelation> findByFromAndType(TenantId tenantId, EntityId from, String relationType, RelationTypeGroup typeGroup) {
336 338 try {
337   - return findByFromAndTypeAsync(from, relationType, typeGroup).get();
  339 + return findByFromAndTypeAsync(tenantId, from, relationType, typeGroup).get();
338 340 } catch (InterruptedException | ExecutionException e) {
339 341 throw new RuntimeException(e);
340 342 }
341 343 }
342 344
343 345 @Override
344   - public ListenableFuture<List<EntityRelation>> findByFromAndTypeAsync(EntityId from, String relationType, RelationTypeGroup typeGroup) {
  346 + public ListenableFuture<List<EntityRelation>> findByFromAndTypeAsync(TenantId tenantId, EntityId from, String relationType, RelationTypeGroup typeGroup) {
345 347 log.trace("Executing findByFromAndType [{}][{}][{}]", from, relationType, typeGroup);
346 348 validate(from);
347 349 validateType(relationType);
348 350 validateTypeGroup(typeGroup);
349   - return relationDao.findAllByFromAndType(from, relationType, typeGroup);
  351 + return relationDao.findAllByFromAndType(tenantId, from, relationType, typeGroup);
350 352 }
351 353
352 354 @Cacheable(cacheNames = RELATIONS_CACHE, key = "{#to, #typeGroup, 'TO'}")
353 355 @Override
354   - public List<EntityRelation> findByTo(EntityId to, RelationTypeGroup typeGroup) {
  356 + public List<EntityRelation> findByTo(TenantId tenantId, EntityId to, RelationTypeGroup typeGroup) {
355 357 validate(to);
356 358 validateTypeGroup(typeGroup);
357 359 try {
358   - return relationDao.findAllByTo(to, typeGroup).get();
  360 + return relationDao.findAllByTo(tenantId, to, typeGroup).get();
359 361 } catch (InterruptedException | ExecutionException e) {
360 362 throw new RuntimeException(e);
361 363 }
362 364 }
363 365
364 366 @Override
365   - public ListenableFuture<List<EntityRelation>> findByToAsync(EntityId to, RelationTypeGroup typeGroup) {
  367 + public ListenableFuture<List<EntityRelation>> findByToAsync(TenantId tenantId, EntityId to, RelationTypeGroup typeGroup) {
366 368 log.trace("Executing findByTo [{}][{}]", to, typeGroup);
367 369 validate(to);
368 370 validateTypeGroup(typeGroup);
... ... @@ -377,7 +379,7 @@ public class BaseRelationService implements RelationService {
377 379 if (fromCache != null) {
378 380 return Futures.immediateFuture(fromCache);
379 381 } else {
380   - ListenableFuture<List<EntityRelation>> relationsFuture = relationDao.findAllByTo(to, typeGroup);
  382 + ListenableFuture<List<EntityRelation>> relationsFuture = relationDao.findAllByTo(tenantId, to, typeGroup);
381 383 Futures.addCallback(relationsFuture,
382 384 new FutureCallback<List<EntityRelation>>() {
383 385 @Override
... ... @@ -392,16 +394,16 @@ public class BaseRelationService implements RelationService {
392 394 }
393 395
394 396 @Override
395   - public ListenableFuture<List<EntityRelationInfo>> findInfoByTo(EntityId to, RelationTypeGroup typeGroup) {
  397 + public ListenableFuture<List<EntityRelationInfo>> findInfoByTo(TenantId tenantId, EntityId to, RelationTypeGroup typeGroup) {
396 398 log.trace("Executing findInfoByTo [{}][{}]", to, typeGroup);
397 399 validate(to);
398 400 validateTypeGroup(typeGroup);
399   - ListenableFuture<List<EntityRelation>> relations = relationDao.findAllByTo(to, typeGroup);
  401 + ListenableFuture<List<EntityRelation>> relations = relationDao.findAllByTo(tenantId, to, typeGroup);
400 402 return Futures.transformAsync(relations,
401 403 relations1 -> {
402 404 List<ListenableFuture<EntityRelationInfo>> futures = new ArrayList<>();
403 405 relations1.forEach(relation ->
404   - futures.add(fetchRelationInfoAsync(relation,
  406 + futures.add(fetchRelationInfoAsync(tenantId, relation,
405 407 EntityRelation::getFrom,
406 408 EntityRelationInfo::setFromName))
407 409 );
... ... @@ -409,10 +411,10 @@ public class BaseRelationService implements RelationService {
409 411 });
410 412 }
411 413
412   - private ListenableFuture<EntityRelationInfo> fetchRelationInfoAsync(EntityRelation relation,
  414 + private ListenableFuture<EntityRelationInfo> fetchRelationInfoAsync(TenantId tenantId, EntityRelation relation,
413 415 Function<EntityRelation, EntityId> entityIdGetter,
414 416 BiConsumer<EntityRelationInfo, String> entityNameSetter) {
415   - ListenableFuture<String> entityName = entityService.fetchEntityNameAsync(entityIdGetter.apply(relation));
  417 + ListenableFuture<String> entityName = entityService.fetchEntityNameAsync(tenantId, entityIdGetter.apply(relation));
416 418 return Futures.transform(entityName, entityName1 -> {
417 419 EntityRelationInfo entityRelationInfo1 = new EntityRelationInfo(relation);
418 420 entityNameSetter.accept(entityRelationInfo1, entityName1);
... ... @@ -422,25 +424,25 @@ public class BaseRelationService implements RelationService {
422 424
423 425 @Cacheable(cacheNames = RELATIONS_CACHE, key = "{#to, #relationType, #typeGroup, 'TO'}")
424 426 @Override
425   - public List<EntityRelation> findByToAndType(EntityId to, String relationType, RelationTypeGroup typeGroup) {
  427 + public List<EntityRelation> findByToAndType(TenantId tenantId, EntityId to, String relationType, RelationTypeGroup typeGroup) {
426 428 try {
427   - return findByToAndTypeAsync(to, relationType, typeGroup).get();
  429 + return findByToAndTypeAsync(tenantId, to, relationType, typeGroup).get();
428 430 } catch (InterruptedException | ExecutionException e) {
429 431 throw new RuntimeException(e);
430 432 }
431 433 }
432 434
433 435 @Override
434   - public ListenableFuture<List<EntityRelation>> findByToAndTypeAsync(EntityId to, String relationType, RelationTypeGroup typeGroup) {
  436 + public ListenableFuture<List<EntityRelation>> findByToAndTypeAsync(TenantId tenantId, EntityId to, String relationType, RelationTypeGroup typeGroup) {
435 437 log.trace("Executing findByToAndType [{}][{}][{}]", to, relationType, typeGroup);
436 438 validate(to);
437 439 validateType(relationType);
438 440 validateTypeGroup(typeGroup);
439   - return relationDao.findAllByToAndType(to, relationType, typeGroup);
  441 + return relationDao.findAllByToAndType(tenantId, to, relationType, typeGroup);
440 442 }
441 443
442 444 @Override
443   - public ListenableFuture<List<EntityRelation>> findByQuery(EntityRelationsQuery query) {
  445 + public ListenableFuture<List<EntityRelation>> findByQuery(TenantId tenantId, EntityRelationsQuery query) {
444 446 log.trace("Executing findByQuery [{}]", query);
445 447 RelationsSearchParameters params = query.getParameters();
446 448 final List<EntityTypeFilter> filters = query.getFilters();
... ... @@ -451,7 +453,7 @@ public class BaseRelationService implements RelationService {
451 453 int maxLvl = params.getMaxLevel() > 0 ? params.getMaxLevel() : Integer.MAX_VALUE;
452 454
453 455 try {
454   - ListenableFuture<Set<EntityRelation>> relationSet = findRelationsRecursively(params.getEntityId(), params.getDirection(), params.getRelationTypeGroup(), maxLvl, new ConcurrentHashMap<>());
  456 + ListenableFuture<Set<EntityRelation>> relationSet = findRelationsRecursively(tenantId, params.getEntityId(), params.getDirection(), params.getRelationTypeGroup(), maxLvl, new ConcurrentHashMap<>());
455 457 return Futures.transform(relationSet, input -> {
456 458 List<EntityRelation> relations = new ArrayList<>();
457 459 if (filters == null || filters.isEmpty()) {
... ... @@ -472,15 +474,15 @@ public class BaseRelationService implements RelationService {
472 474 }
473 475
474 476 @Override
475   - public ListenableFuture<List<EntityRelationInfo>> findInfoByQuery(EntityRelationsQuery query) {
  477 + public ListenableFuture<List<EntityRelationInfo>> findInfoByQuery(TenantId tenantId, EntityRelationsQuery query) {
476 478 log.trace("Executing findInfoByQuery [{}]", query);
477   - ListenableFuture<List<EntityRelation>> relations = findByQuery(query);
  479 + ListenableFuture<List<EntityRelation>> relations = findByQuery(tenantId, query);
478 480 EntitySearchDirection direction = query.getParameters().getDirection();
479 481 return Futures.transformAsync(relations,
480 482 relations1 -> {
481 483 List<ListenableFuture<EntityRelationInfo>> futures = new ArrayList<>();
482 484 relations1.forEach(relation ->
483   - futures.add(fetchRelationInfoAsync(relation,
  485 + futures.add(fetchRelationInfoAsync(tenantId, relation,
484 486 relation2 -> direction == EntitySearchDirection.FROM ? relation2.getTo() : relation2.getFrom(),
485 487 (EntityRelationInfo relationInfo, String entityName) -> {
486 488 if (direction == EntitySearchDirection.FROM) {
... ... @@ -567,7 +569,7 @@ public class BaseRelationService implements RelationService {
567 569 }
568 570 }
569 571
570   - private ListenableFuture<Set<EntityRelation>> findRelationsRecursively(final EntityId rootId, final EntitySearchDirection direction,
  572 + private ListenableFuture<Set<EntityRelation>> findRelationsRecursively(final TenantId tenantId, final EntityId rootId, final EntitySearchDirection direction,
571 573 RelationTypeGroup relationTypeGroup, int lvl,
572 574 final ConcurrentHashMap<EntityId, Boolean> uniqueMap) throws Exception {
573 575 if (lvl == 0) {
... ... @@ -575,7 +577,7 @@ public class BaseRelationService implements RelationService {
575 577 }
576 578 lvl--;
577 579 //TODO: try to remove this blocking operation
578   - Set<EntityRelation> children = new HashSet<>(findRelations(rootId, direction, relationTypeGroup).get());
  580 + Set<EntityRelation> children = new HashSet<>(findRelations(tenantId, rootId, direction, relationTypeGroup).get());
579 581 Set<EntityId> childrenIds = new HashSet<>();
580 582 for (EntityRelation childRelation : children) {
581 583 log.trace("Found Relation: {}", childRelation);
... ... @@ -594,7 +596,7 @@ public class BaseRelationService implements RelationService {
594 596 }
595 597 List<ListenableFuture<Set<EntityRelation>>> futures = new ArrayList<>();
596 598 for (EntityId entityId : childrenIds) {
597   - futures.add(findRelationsRecursively(entityId, direction, relationTypeGroup, lvl, uniqueMap));
  599 + futures.add(findRelationsRecursively(tenantId, entityId, direction, relationTypeGroup, lvl, uniqueMap));
598 600 }
599 601 //TODO: try to remove this blocking operation
600 602 List<Set<EntityRelation>> relations = Futures.successfulAsList(futures).get();
... ... @@ -602,15 +604,15 @@ public class BaseRelationService implements RelationService {
602 604 return Futures.immediateFuture(children);
603 605 }
604 606
605   - private ListenableFuture<List<EntityRelation>> findRelations(final EntityId rootId, final EntitySearchDirection direction, RelationTypeGroup relationTypeGroup) {
  607 + private ListenableFuture<List<EntityRelation>> findRelations(final TenantId tenantId, final EntityId rootId, final EntitySearchDirection direction, RelationTypeGroup relationTypeGroup) {
606 608 ListenableFuture<List<EntityRelation>> relations;
607 609 if (relationTypeGroup == null) {
608 610 relationTypeGroup = RelationTypeGroup.COMMON;
609 611 }
610 612 if (direction == EntitySearchDirection.FROM) {
611   - relations = findByFromAsync(rootId, relationTypeGroup);
  613 + relations = findByFromAsync(tenantId, rootId, relationTypeGroup);
612 614 } else {
613   - relations = findByToAsync(rootId, relationTypeGroup);
  615 + relations = findByToAsync(tenantId, rootId, relationTypeGroup);
614 616 }
615 617 return relations;
616 618 }
... ...
... ... @@ -18,6 +18,7 @@ package org.thingsboard.server.dao.relation;
18 18 import com.google.common.util.concurrent.ListenableFuture;
19 19 import org.thingsboard.server.common.data.EntityType;
20 20 import org.thingsboard.server.common.data.id.EntityId;
  21 +import org.thingsboard.server.common.data.id.TenantId;
21 22 import org.thingsboard.server.common.data.page.TimePageLink;
22 23 import org.thingsboard.server.common.data.relation.EntityRelation;
23 24 import org.thingsboard.server.common.data.relation.RelationTypeGroup;
... ... @@ -29,34 +30,34 @@ import java.util.List;
29 30 */
30 31 public interface RelationDao {
31 32
32   - ListenableFuture<List<EntityRelation>> findAllByFrom(EntityId from, RelationTypeGroup typeGroup);
  33 + ListenableFuture<List<EntityRelation>> findAllByFrom(TenantId tenantId, EntityId from, RelationTypeGroup typeGroup);
33 34
34   - ListenableFuture<List<EntityRelation>> findAllByFromAndType(EntityId from, String relationType, RelationTypeGroup typeGroup);
  35 + ListenableFuture<List<EntityRelation>> findAllByFromAndType(TenantId tenantId, EntityId from, String relationType, RelationTypeGroup typeGroup);
35 36
36   - ListenableFuture<List<EntityRelation>> findAllByTo(EntityId to, RelationTypeGroup typeGroup);
  37 + ListenableFuture<List<EntityRelation>> findAllByTo(TenantId tenantId, EntityId to, RelationTypeGroup typeGroup);
37 38
38   - ListenableFuture<List<EntityRelation>> findAllByToAndType(EntityId to, String relationType, RelationTypeGroup typeGroup);
  39 + ListenableFuture<List<EntityRelation>> findAllByToAndType(TenantId tenantId, EntityId to, String relationType, RelationTypeGroup typeGroup);
39 40
40   - ListenableFuture<Boolean> checkRelation(EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup);
  41 + ListenableFuture<Boolean> checkRelation(TenantId tenantId, EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup);
41 42
42   - ListenableFuture<EntityRelation> getRelation(EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup);
  43 + ListenableFuture<EntityRelation> getRelation(TenantId tenantId, EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup);
43 44
44   - boolean saveRelation(EntityRelation relation);
  45 + boolean saveRelation(TenantId tenantId, EntityRelation relation);
45 46
46   - ListenableFuture<Boolean> saveRelationAsync(EntityRelation relation);
  47 + ListenableFuture<Boolean> saveRelationAsync(TenantId tenantId, EntityRelation relation);
47 48
48   - boolean deleteRelation(EntityRelation relation);
  49 + boolean deleteRelation(TenantId tenantId, EntityRelation relation);
49 50
50   - ListenableFuture<Boolean> deleteRelationAsync(EntityRelation relation);
  51 + ListenableFuture<Boolean> deleteRelationAsync(TenantId tenantId, EntityRelation relation);
51 52
52   - boolean deleteRelation(EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup);
  53 + boolean deleteRelation(TenantId tenantId, EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup);
53 54
54   - ListenableFuture<Boolean> deleteRelationAsync(EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup);
  55 + ListenableFuture<Boolean> deleteRelationAsync(TenantId tenantId, EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup);
55 56
56   - boolean deleteOutboundRelations(EntityId entity);
  57 + boolean deleteOutboundRelations(TenantId tenantId, EntityId entity);
57 58
58   - ListenableFuture<Boolean> deleteOutboundRelationsAsync(EntityId entity);
  59 + ListenableFuture<Boolean> deleteOutboundRelationsAsync(TenantId tenantId, EntityId entity);
59 60
60   - ListenableFuture<List<EntityRelation>> findRelations(EntityId from, String relationType, RelationTypeGroup typeGroup, EntityType toType, TimePageLink pageLink);
  61 + ListenableFuture<List<EntityRelation>> findRelations(TenantId tenantId, EntityId from, String relationType, RelationTypeGroup typeGroup, EntityType toType, TimePageLink pageLink);
61 62
62 63 }
... ...
... ... @@ -17,6 +17,7 @@ package org.thingsboard.server.dao.relation;
17 17
18 18 import com.google.common.util.concurrent.ListenableFuture;
19 19 import org.thingsboard.server.common.data.id.EntityId;
  20 +import org.thingsboard.server.common.data.id.TenantId;
20 21 import org.thingsboard.server.common.data.relation.EntityRelation;
21 22 import org.thingsboard.server.common.data.relation.EntityRelationInfo;
22 23 import org.thingsboard.server.common.data.relation.EntityRelationsQuery;
... ... @@ -30,51 +31,51 @@ import java.util.concurrent.ExecutionException;
30 31 */
31 32 public interface RelationService {
32 33
33   - ListenableFuture<Boolean> checkRelation(EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup);
  34 + ListenableFuture<Boolean> checkRelation(TenantId tenantId, EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup);
34 35
35   - EntityRelation getRelation(EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup);
  36 + EntityRelation getRelation(TenantId tenantId, EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup);
36 37
37   - ListenableFuture<EntityRelation> getRelationAsync(EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup);
  38 + ListenableFuture<EntityRelation> getRelationAsync(TenantId tenantId, EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup);
38 39
39   - boolean saveRelation(EntityRelation relation);
  40 + boolean saveRelation(TenantId tenantId, EntityRelation relation);
40 41
41   - ListenableFuture<Boolean> saveRelationAsync(EntityRelation relation);
  42 + ListenableFuture<Boolean> saveRelationAsync(TenantId tenantId, EntityRelation relation);
42 43
43   - boolean deleteRelation(EntityRelation relation);
  44 + boolean deleteRelation(TenantId tenantId, EntityRelation relation);
44 45
45   - ListenableFuture<Boolean> deleteRelationAsync(EntityRelation relation);
  46 + ListenableFuture<Boolean> deleteRelationAsync(TenantId tenantId, EntityRelation relation);
46 47
47   - boolean deleteRelation(EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup);
  48 + boolean deleteRelation(TenantId tenantId, EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup);
48 49
49   - ListenableFuture<Boolean> deleteRelationAsync(EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup);
  50 + ListenableFuture<Boolean> deleteRelationAsync(TenantId tenantId, EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup);
50 51
51   - void deleteEntityRelations(EntityId entity);
  52 + void deleteEntityRelations(TenantId tenantId, EntityId entity);
52 53
53   - ListenableFuture<Void> deleteEntityRelationsAsync(EntityId entity);
  54 + ListenableFuture<Void> deleteEntityRelationsAsync(TenantId tenantId, EntityId entity);
54 55
55   - List<EntityRelation> findByFrom(EntityId from, RelationTypeGroup typeGroup);
  56 + List<EntityRelation> findByFrom(TenantId tenantId, EntityId from, RelationTypeGroup typeGroup);
56 57
57   - ListenableFuture<List<EntityRelation>> findByFromAsync(EntityId from, RelationTypeGroup typeGroup);
  58 + ListenableFuture<List<EntityRelation>> findByFromAsync(TenantId tenantId, EntityId from, RelationTypeGroup typeGroup);
58 59
59   - ListenableFuture<List<EntityRelationInfo>> findInfoByFrom(EntityId from, RelationTypeGroup typeGroup);
  60 + ListenableFuture<List<EntityRelationInfo>> findInfoByFrom(TenantId tenantId, EntityId from, RelationTypeGroup typeGroup);
60 61
61   - List<EntityRelation> findByFromAndType(EntityId from, String relationType, RelationTypeGroup typeGroup);
  62 + List<EntityRelation> findByFromAndType(TenantId tenantId, EntityId from, String relationType, RelationTypeGroup typeGroup);
62 63
63   - ListenableFuture<List<EntityRelation>> findByFromAndTypeAsync(EntityId from, String relationType, RelationTypeGroup typeGroup);
  64 + ListenableFuture<List<EntityRelation>> findByFromAndTypeAsync(TenantId tenantId, EntityId from, String relationType, RelationTypeGroup typeGroup);
64 65
65   - List<EntityRelation> findByTo(EntityId to, RelationTypeGroup typeGroup);
  66 + List<EntityRelation> findByTo(TenantId tenantId, EntityId to, RelationTypeGroup typeGroup);
66 67
67   - ListenableFuture<List<EntityRelation>> findByToAsync(EntityId to, RelationTypeGroup typeGroup);
  68 + ListenableFuture<List<EntityRelation>> findByToAsync(TenantId tenantId, EntityId to, RelationTypeGroup typeGroup);
68 69
69   - ListenableFuture<List<EntityRelationInfo>> findInfoByTo(EntityId to, RelationTypeGroup typeGroup);
  70 + ListenableFuture<List<EntityRelationInfo>> findInfoByTo(TenantId tenantId, EntityId to, RelationTypeGroup typeGroup);
70 71
71   - List<EntityRelation> findByToAndType(EntityId to, String relationType, RelationTypeGroup typeGroup);
  72 + List<EntityRelation> findByToAndType(TenantId tenantId, EntityId to, String relationType, RelationTypeGroup typeGroup);
72 73
73   - ListenableFuture<List<EntityRelation>> findByToAndTypeAsync(EntityId to, String relationType, RelationTypeGroup typeGroup);
  74 + ListenableFuture<List<EntityRelation>> findByToAndTypeAsync(TenantId tenantId, EntityId to, String relationType, RelationTypeGroup typeGroup);
74 75
75   - ListenableFuture<List<EntityRelation>> findByQuery(EntityRelationsQuery query);
  76 + ListenableFuture<List<EntityRelation>> findByQuery(TenantId tenantId, EntityRelationsQuery query);
76 77
77   - ListenableFuture<List<EntityRelationInfo>> findInfoByQuery(EntityRelationsQuery query);
  78 + ListenableFuture<List<EntityRelationInfo>> findInfoByQuery(TenantId tenantId, EntityRelationsQuery query);
78 79
79 80 // TODO: This method may be useful for some validations in the future
80 81 // ListenableFuture<Boolean> checkRecursiveRelation(EntityId from, EntityId to);
... ...
... ... @@ -67,11 +67,11 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
67 67
68 68 @Override
69 69 public RuleChain saveRuleChain(RuleChain ruleChain) {
70   - ruleChainValidator.validate(ruleChain);
71   - RuleChain savedRuleChain = ruleChainDao.save(ruleChain);
  70 + ruleChainValidator.validate(ruleChain, RuleChain::getTenantId);
  71 + RuleChain savedRuleChain = ruleChainDao.save(ruleChain.getTenantId(), ruleChain);
72 72 if (ruleChain.isRoot() && ruleChain.getId() == null) {
73 73 try {
74   - createRelation(new EntityRelation(savedRuleChain.getTenantId(), savedRuleChain.getId(),
  74 + createRelation(ruleChain.getTenantId(), new EntityRelation(savedRuleChain.getTenantId(), savedRuleChain.getId(),
75 75 EntityRelation.CONTAINS_TYPE, RelationTypeGroup.RULE_CHAIN));
76 76 } catch (ExecutionException | InterruptedException e) {
77 77 log.warn("[{}] Failed to create tenant to root rule chain relation. from: [{}], to: [{}]",
... ... @@ -83,20 +83,20 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
83 83 }
84 84
85 85 @Override
86   - public boolean setRootRuleChain(RuleChainId ruleChainId) {
87   - RuleChain ruleChain = ruleChainDao.findById(ruleChainId.getId());
  86 + public boolean setRootRuleChain(TenantId tenantId, RuleChainId ruleChainId) {
  87 + RuleChain ruleChain = ruleChainDao.findById(tenantId, ruleChainId.getId());
88 88 if (!ruleChain.isRoot()) {
89 89 RuleChain previousRootRuleChain = getRootTenantRuleChain(ruleChain.getTenantId());
90 90 if (!previousRootRuleChain.getId().equals(ruleChain.getId())) {
91 91 try {
92   - deleteRelation(new EntityRelation(previousRootRuleChain.getTenantId(), previousRootRuleChain.getId(),
  92 + deleteRelation(tenantId, new EntityRelation(previousRootRuleChain.getTenantId(), previousRootRuleChain.getId(),
93 93 EntityRelation.CONTAINS_TYPE, RelationTypeGroup.RULE_CHAIN));
94 94 previousRootRuleChain.setRoot(false);
95   - ruleChainDao.save(previousRootRuleChain);
96   - createRelation(new EntityRelation(ruleChain.getTenantId(), ruleChain.getId(),
  95 + ruleChainDao.save(tenantId, previousRootRuleChain);
  96 + createRelation(tenantId, new EntityRelation(ruleChain.getTenantId(), ruleChain.getId(),
97 97 EntityRelation.CONTAINS_TYPE, RelationTypeGroup.RULE_CHAIN));
98 98 ruleChain.setRoot(true);
99   - ruleChainDao.save(ruleChain);
  99 + ruleChainDao.save(tenantId, ruleChain);
100 100 return true;
101 101 } catch (ExecutionException | InterruptedException e) {
102 102 log.warn("[{}] Failed to set root rule chain, ruleChainId: [{}]", ruleChainId);
... ... @@ -108,9 +108,9 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
108 108 }
109 109
110 110 @Override
111   - public RuleChainMetaData saveRuleChainMetaData(RuleChainMetaData ruleChainMetaData) {
  111 + public RuleChainMetaData saveRuleChainMetaData(TenantId tenantId, RuleChainMetaData ruleChainMetaData) {
112 112 Validator.validateId(ruleChainMetaData.getRuleChainId(), "Incorrect rule chain id.");
113   - RuleChain ruleChain = findRuleChainById(ruleChainMetaData.getRuleChainId());
  113 + RuleChain ruleChain = findRuleChainById(tenantId, ruleChainMetaData.getRuleChainId());
114 114 if (ruleChain == null) {
115 115 return null;
116 116 }
... ... @@ -130,9 +130,9 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
130 130 }
131 131 }
132 132
133   - List<RuleNode> existingRuleNodes = getRuleChainNodes(ruleChainMetaData.getRuleChainId());
  133 + List<RuleNode> existingRuleNodes = getRuleChainNodes(tenantId, ruleChainMetaData.getRuleChainId());
134 134 for (RuleNode existingNode : existingRuleNodes) {
135   - deleteEntityRelations(existingNode.getId());
  135 + deleteEntityRelations(tenantId, existingNode.getId());
136 136 Integer index = ruleNodeIndexMap.get(existingNode.getId());
137 137 if (index != null) {
138 138 toAddOrUpdate.add(ruleChainMetaData.getNodes().get(index));
... ... @@ -142,9 +142,9 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
142 142 }
143 143 for (RuleNode node : toAddOrUpdate) {
144 144 node.setRuleChainId(ruleChain.getId());
145   - RuleNode savedNode = ruleNodeDao.save(node);
  145 + RuleNode savedNode = ruleNodeDao.save(tenantId, node);
146 146 try {
147   - createRelation(new EntityRelation(ruleChainMetaData.getRuleChainId(), savedNode.getId(),
  147 + createRelation(tenantId, new EntityRelation(ruleChainMetaData.getRuleChainId(), savedNode.getId(),
148 148 EntityRelation.CONTAINS_TYPE, RelationTypeGroup.RULE_CHAIN));
149 149 } catch (ExecutionException | InterruptedException e) {
150 150 log.warn("[{}] Failed to create rule chain to rule node relation. from: [{}], to: [{}]",
... ... @@ -156,7 +156,7 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
156 156 ruleNodeIndexMap.put(savedNode.getId(), index);
157 157 }
158 158 for (RuleNode node : toDelete) {
159   - deleteRuleNode(node.getId());
  159 + deleteRuleNode(tenantId, node.getId());
160 160 }
161 161 RuleNodeId firstRuleNodeId = null;
162 162 if (ruleChainMetaData.getFirstNodeIndex() != null) {
... ... @@ -165,7 +165,7 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
165 165 if ((ruleChain.getFirstRuleNodeId() != null && !ruleChain.getFirstRuleNodeId().equals(firstRuleNodeId))
166 166 || (ruleChain.getFirstRuleNodeId() == null && firstRuleNodeId != null)) {
167 167 ruleChain.setFirstRuleNodeId(firstRuleNodeId);
168   - ruleChainDao.save(ruleChain);
  168 + ruleChainDao.save(tenantId, ruleChain);
169 169 }
170 170 if (ruleChainMetaData.getConnections() != null) {
171 171 for (NodeConnectionInfo nodeConnection : ruleChainMetaData.getConnections()) {
... ... @@ -173,7 +173,7 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
173 173 EntityId to = nodes.get(nodeConnection.getToIndex()).getId();
174 174 String type = nodeConnection.getType();
175 175 try {
176   - createRelation(new EntityRelation(from, to, type, RelationTypeGroup.RULE_NODE));
  176 + createRelation(tenantId, new EntityRelation(from, to, type, RelationTypeGroup.RULE_NODE));
177 177 } catch (ExecutionException | InterruptedException e) {
178 178 log.warn("[{}] Failed to create rule node relation. from: [{}], to: [{}]", from, to);
179 179 throw new RuntimeException(e);
... ... @@ -186,7 +186,7 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
186 186 EntityId to = nodeToRuleChainConnection.getTargetRuleChainId();
187 187 String type = nodeToRuleChainConnection.getType();
188 188 try {
189   - createRelation(new EntityRelation(from, to, type, RelationTypeGroup.RULE_NODE, nodeToRuleChainConnection.getAdditionalInfo()));
  189 + createRelation(tenantId, new EntityRelation(from, to, type, RelationTypeGroup.RULE_NODE, nodeToRuleChainConnection.getAdditionalInfo()));
190 190 } catch (ExecutionException | InterruptedException e) {
191 191 log.warn("[{}] Failed to create rule node to rule chain relation. from: [{}], to: [{}]", from, to);
192 192 throw new RuntimeException(e);
... ... @@ -194,19 +194,19 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
194 194 }
195 195 }
196 196
197   - return loadRuleChainMetaData(ruleChainMetaData.getRuleChainId());
  197 + return loadRuleChainMetaData(tenantId, ruleChainMetaData.getRuleChainId());
198 198 }
199 199
200 200 @Override
201   - public RuleChainMetaData loadRuleChainMetaData(RuleChainId ruleChainId) {
  201 + public RuleChainMetaData loadRuleChainMetaData(TenantId tenantId, RuleChainId ruleChainId) {
202 202 Validator.validateId(ruleChainId, "Incorrect rule chain id.");
203   - RuleChain ruleChain = findRuleChainById(ruleChainId);
  203 + RuleChain ruleChain = findRuleChainById(tenantId, ruleChainId);
204 204 if (ruleChain == null) {
205 205 return null;
206 206 }
207 207 RuleChainMetaData ruleChainMetaData = new RuleChainMetaData();
208 208 ruleChainMetaData.setRuleChainId(ruleChainId);
209   - List<RuleNode> ruleNodes = getRuleChainNodes(ruleChainId);
  209 + List<RuleNode> ruleNodes = getRuleChainNodes(tenantId, ruleChainId);
210 210 Map<RuleNodeId, Integer> ruleNodeIndexMap = new HashMap<>();
211 211 for (RuleNode node : ruleNodes) {
212 212 ruleNodeIndexMap.put(node.getId(), ruleNodes.indexOf(node));
... ... @@ -217,7 +217,7 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
217 217 }
218 218 for (RuleNode node : ruleNodes) {
219 219 int fromIndex = ruleNodeIndexMap.get(node.getId());
220   - List<EntityRelation> nodeRelations = getRuleNodeRelations(node.getId());
  220 + List<EntityRelation> nodeRelations = getRuleNodeRelations(tenantId, node.getId());
221 221 for (EntityRelation nodeRelation : nodeRelations) {
222 222 String type = nodeRelation.getType();
223 223 if (nodeRelation.getTo().getEntityType() == EntityType.RULE_NODE) {
... ... @@ -234,54 +234,54 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
234 234 }
235 235
236 236 @Override
237   - public RuleChain findRuleChainById(RuleChainId ruleChainId) {
  237 + public RuleChain findRuleChainById(TenantId tenantId, RuleChainId ruleChainId) {
238 238 Validator.validateId(ruleChainId, "Incorrect rule chain id for search request.");
239   - return ruleChainDao.findById(ruleChainId.getId());
  239 + return ruleChainDao.findById(tenantId, ruleChainId.getId());
240 240 }
241 241
242 242 @Override
243   - public RuleNode findRuleNodeById(RuleNodeId ruleNodeId) {
  243 + public RuleNode findRuleNodeById(TenantId tenantId, RuleNodeId ruleNodeId) {
244 244 Validator.validateId(ruleNodeId, "Incorrect rule node id for search request.");
245   - return ruleNodeDao.findById(ruleNodeId.getId());
  245 + return ruleNodeDao.findById(tenantId, ruleNodeId.getId());
246 246 }
247 247
248 248 @Override
249   - public ListenableFuture<RuleChain> findRuleChainByIdAsync(RuleChainId ruleChainId) {
  249 + public ListenableFuture<RuleChain> findRuleChainByIdAsync(TenantId tenantId, RuleChainId ruleChainId) {
250 250 Validator.validateId(ruleChainId, "Incorrect rule chain id for search request.");
251   - return ruleChainDao.findByIdAsync(ruleChainId.getId());
  251 + return ruleChainDao.findByIdAsync(tenantId, ruleChainId.getId());
252 252 }
253 253
254 254 @Override
255   - public ListenableFuture<RuleNode> findRuleNodeByIdAsync(RuleNodeId ruleNodeId) {
  255 + public ListenableFuture<RuleNode> findRuleNodeByIdAsync(TenantId tenantId, RuleNodeId ruleNodeId) {
256 256 Validator.validateId(ruleNodeId, "Incorrect rule node id for search request.");
257   - return ruleNodeDao.findByIdAsync(ruleNodeId.getId());
  257 + return ruleNodeDao.findByIdAsync(tenantId, ruleNodeId.getId());
258 258 }
259 259
260 260 @Override
261 261 public RuleChain getRootTenantRuleChain(TenantId tenantId) {
262 262 Validator.validateId(tenantId, "Incorrect tenant id for search request.");
263   - List<EntityRelation> relations = relationService.findByFrom(tenantId, RelationTypeGroup.RULE_CHAIN);
  263 + List<EntityRelation> relations = relationService.findByFrom(tenantId, tenantId, RelationTypeGroup.RULE_CHAIN);
264 264 if (relations != null && !relations.isEmpty()) {
265 265 EntityRelation relation = relations.get(0);
266 266 RuleChainId ruleChainId = new RuleChainId(relation.getTo().getId());
267   - return findRuleChainById(ruleChainId);
  267 + return findRuleChainById(tenantId, ruleChainId);
268 268 } else {
269 269 return null;
270 270 }
271 271 }
272 272
273 273 @Override
274   - public List<RuleNode> getRuleChainNodes(RuleChainId ruleChainId) {
  274 + public List<RuleNode> getRuleChainNodes(TenantId tenantId, RuleChainId ruleChainId) {
275 275 Validator.validateId(ruleChainId, "Incorrect rule chain id for search request.");
276   - List<EntityRelation> relations = getRuleChainToNodeRelations(ruleChainId);
277   - List<RuleNode> ruleNodes = relations.stream().map(relation -> ruleNodeDao.findById(relation.getTo().getId())).collect(Collectors.toList());
  276 + List<EntityRelation> relations = getRuleChainToNodeRelations(tenantId, ruleChainId);
  277 + List<RuleNode> ruleNodes = relations.stream().map(relation -> ruleNodeDao.findById(tenantId, relation.getTo().getId())).collect(Collectors.toList());
278 278 return ruleNodes;
279 279 }
280 280
281 281 @Override
282   - public List<EntityRelation> getRuleNodeRelations(RuleNodeId ruleNodeId) {
  282 + public List<EntityRelation> getRuleNodeRelations(TenantId tenantId, RuleNodeId ruleNodeId) {
283 283 Validator.validateId(ruleNodeId, "Incorrect rule node id for search request.");
284   - return relationService.findByFrom(ruleNodeId, RelationTypeGroup.RULE_NODE);
  284 + return relationService.findByFrom(tenantId, ruleNodeId, RelationTypeGroup.RULE_NODE);
285 285 }
286 286
287 287 @Override
... ... @@ -293,60 +293,60 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
293 293 }
294 294
295 295 @Override
296   - public void deleteRuleChainById(RuleChainId ruleChainId) {
  296 + public void deleteRuleChainById(TenantId tenantId, RuleChainId ruleChainId) {
297 297 Validator.validateId(ruleChainId, "Incorrect rule chain id for delete request.");
298   - RuleChain ruleChain = ruleChainDao.findById(ruleChainId.getId());
  298 + RuleChain ruleChain = ruleChainDao.findById(tenantId, ruleChainId.getId());
299 299 if (ruleChain != null && ruleChain.isRoot()) {
300 300 throw new DataValidationException("Deletion of Root Tenant Rule Chain is prohibited!");
301 301 }
302   - checkRuleNodesAndDelete(ruleChainId);
  302 + checkRuleNodesAndDelete(tenantId, ruleChainId);
303 303 }
304 304
305 305 @Override
306 306 public void deleteRuleChainsByTenantId(TenantId tenantId) {
307 307 Validator.validateId(tenantId, "Incorrect tenant id for delete rule chains request.");
308   - tenantRuleChainsRemover.removeEntities(tenantId);
  308 + tenantRuleChainsRemover.removeEntities(tenantId, tenantId);
309 309 }
310 310
311   - private void checkRuleNodesAndDelete(RuleChainId ruleChainId) {
312   - List<EntityRelation> nodeRelations = getRuleChainToNodeRelations(ruleChainId);
  311 + private void checkRuleNodesAndDelete(TenantId tenantId, RuleChainId ruleChainId) {
  312 + List<EntityRelation> nodeRelations = getRuleChainToNodeRelations(tenantId, ruleChainId);
313 313 for (EntityRelation relation : nodeRelations) {
314   - deleteRuleNode(relation.getTo());
  314 + deleteRuleNode(tenantId, relation.getTo());
315 315 }
316   - deleteEntityRelations(ruleChainId);
317   - ruleChainDao.removeById(ruleChainId.getId());
  316 + deleteEntityRelations(tenantId, ruleChainId);
  317 + ruleChainDao.removeById(tenantId, ruleChainId.getId());
318 318 }
319 319
320   - private List<EntityRelation> getRuleChainToNodeRelations(RuleChainId ruleChainId) {
321   - return relationService.findByFrom(ruleChainId, RelationTypeGroup.RULE_CHAIN);
  320 + private List<EntityRelation> getRuleChainToNodeRelations(TenantId tenantId, RuleChainId ruleChainId) {
  321 + return relationService.findByFrom(tenantId, ruleChainId, RelationTypeGroup.RULE_CHAIN);
322 322 }
323 323
324   - private void deleteRuleNode(EntityId entityId) {
325   - deleteEntityRelations(entityId);
326   - ruleNodeDao.removeById(entityId.getId());
  324 + private void deleteRuleNode(TenantId tenantId, EntityId entityId) {
  325 + deleteEntityRelations(tenantId, entityId);
  326 + ruleNodeDao.removeById(tenantId, entityId.getId());
327 327 }
328 328
329   - private void createRelation(EntityRelation relation) throws ExecutionException, InterruptedException {
  329 + private void createRelation(TenantId tenantId, EntityRelation relation) throws ExecutionException, InterruptedException {
330 330 log.debug("Creating relation: {}", relation);
331   - relationService.saveRelation(relation);
  331 + relationService.saveRelation(tenantId, relation);
332 332 }
333 333
334   - private void deleteRelation(EntityRelation relation) throws ExecutionException, InterruptedException {
  334 + private void deleteRelation(TenantId tenantId, EntityRelation relation) throws ExecutionException, InterruptedException {
335 335 log.debug("Deleting relation: {}", relation);
336   - relationService.deleteRelation(relation);
  336 + relationService.deleteRelation(tenantId, relation);
337 337 }
338 338
339 339 private DataValidator<RuleChain> ruleChainValidator =
340 340 new DataValidator<RuleChain>() {
341 341 @Override
342   - protected void validateDataImpl(RuleChain ruleChain) {
  342 + protected void validateDataImpl(TenantId tenantId, RuleChain ruleChain) {
343 343 if (StringUtils.isEmpty(ruleChain.getName())) {
344 344 throw new DataValidationException("Rule chain name should be specified!.");
345 345 }
346 346 if (ruleChain.getTenantId() == null || ruleChain.getTenantId().isNullUid()) {
347 347 throw new DataValidationException("Rule chain should be assigned to tenant!");
348 348 }
349   - Tenant tenant = tenantDao.findById(ruleChain.getTenantId().getId());
  349 + Tenant tenant = tenantDao.findById(tenantId, ruleChain.getTenantId().getId());
350 350 if (tenant == null) {
351 351 throw new DataValidationException("Rule chain is referencing to non-existent tenant!");
352 352 }
... ... @@ -363,13 +363,13 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
363 363 new PaginatedRemover<TenantId, RuleChain>() {
364 364
365 365 @Override
366   - protected List<RuleChain> findEntities(TenantId id, TextPageLink pageLink) {
  366 + protected List<RuleChain> findEntities(TenantId tenantId, TenantId id, TextPageLink pageLink) {
367 367 return ruleChainDao.findRuleChainsByTenantId(id.getId(), pageLink);
368 368 }
369 369
370 370 @Override
371   - protected void removeEntity(RuleChain entity) {
372   - checkRuleNodesAndDelete(entity.getId());
  371 + protected void removeEntity(TenantId tenantId, RuleChain entity) {
  372 + checkRuleNodesAndDelete(tenantId, entity.getId());
373 373 }
374 374 };
375 375 }
... ...
... ... @@ -17,6 +17,7 @@ package org.thingsboard.server.dao.rule;
17 17
18 18 import lombok.extern.slf4j.Slf4j;
19 19 import org.springframework.stereotype.Component;
  20 +import org.thingsboard.server.common.data.id.TenantId;
20 21 import org.thingsboard.server.common.data.page.TextPageLink;
21 22 import org.thingsboard.server.common.data.rule.RuleChain;
22 23 import org.thingsboard.server.dao.DaoUtil;
... ... @@ -51,7 +52,7 @@ public class CassandraRuleChainDao extends CassandraAbstractSearchTextDao<RuleCh
51 52 @Override
52 53 public List<RuleChain> findRuleChainsByTenantId(UUID tenantId, TextPageLink pageLink) {
53 54 log.debug("Try to find rule chains by tenantId [{}] and pageLink [{}]", tenantId, pageLink);
54   - List<RuleChainEntity> ruleChainEntities = findPageWithTextSearch(RULE_CHAIN_BY_TENANT_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME,
  55 + List<RuleChainEntity> ruleChainEntities = findPageWithTextSearch(new TenantId(tenantId), RULE_CHAIN_BY_TENANT_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME,
55 56 Collections.singletonList(eq(RULE_CHAIN_TENANT_ID_PROPERTY, tenantId)),
56 57 pageLink);
57 58
... ...
... ... @@ -36,29 +36,29 @@ public interface RuleChainService {
36 36
37 37 RuleChain saveRuleChain(RuleChain ruleChain);
38 38
39   - boolean setRootRuleChain(RuleChainId ruleChainId);
  39 + boolean setRootRuleChain(TenantId tenantId, RuleChainId ruleChainId);
40 40
41   - RuleChainMetaData saveRuleChainMetaData(RuleChainMetaData ruleChainMetaData);
  41 + RuleChainMetaData saveRuleChainMetaData(TenantId tenantId, RuleChainMetaData ruleChainMetaData);
42 42
43   - RuleChainMetaData loadRuleChainMetaData(RuleChainId ruleChainId);
  43 + RuleChainMetaData loadRuleChainMetaData(TenantId tenantId, RuleChainId ruleChainId);
44 44
45   - RuleChain findRuleChainById(RuleChainId ruleChainId);
  45 + RuleChain findRuleChainById(TenantId tenantId, RuleChainId ruleChainId);
46 46
47   - RuleNode findRuleNodeById(RuleNodeId ruleNodeId);
  47 + RuleNode findRuleNodeById(TenantId tenantId, RuleNodeId ruleNodeId);
48 48
49   - ListenableFuture<RuleChain> findRuleChainByIdAsync(RuleChainId ruleChainId);
  49 + ListenableFuture<RuleChain> findRuleChainByIdAsync(TenantId tenantId, RuleChainId ruleChainId);
50 50
51   - ListenableFuture<RuleNode> findRuleNodeByIdAsync(RuleNodeId ruleNodeId);
  51 + ListenableFuture<RuleNode> findRuleNodeByIdAsync(TenantId tenantId, RuleNodeId ruleNodeId);
52 52
53 53 RuleChain getRootTenantRuleChain(TenantId tenantId);
54 54
55   - List<RuleNode> getRuleChainNodes(RuleChainId ruleChainId);
  55 + List<RuleNode> getRuleChainNodes(TenantId tenantId, RuleChainId ruleChainId);
56 56
57   - List<EntityRelation> getRuleNodeRelations(RuleNodeId ruleNodeId);
  57 + List<EntityRelation> getRuleNodeRelations(TenantId tenantId, RuleNodeId ruleNodeId);
58 58
59 59 TextPageData<RuleChain> findTenantRuleChains(TenantId tenantId, TextPageLink pageLink);
60 60
61   - void deleteRuleChainById(RuleChainId ruleChainId);
  61 + void deleteRuleChainById(TenantId tenantId, RuleChainId ruleChainId);
62 62
63 63 void deleteRuleChainsByTenantId(TenantId tenantId);
64 64
... ...
... ... @@ -19,70 +19,73 @@ import com.fasterxml.jackson.databind.JsonNode;
19 19 import lombok.extern.slf4j.Slf4j;
20 20 import org.apache.commons.validator.routines.EmailValidator;
21 21 import org.thingsboard.server.common.data.BaseData;
  22 +import org.thingsboard.server.common.data.id.TenantId;
22 23 import org.thingsboard.server.dao.exception.DataValidationException;
23 24
24 25 import java.util.HashSet;
25 26 import java.util.Iterator;
26 27 import java.util.Set;
  28 +import java.util.function.Function;
27 29
28 30 @Slf4j
29 31 public abstract class DataValidator<D extends BaseData<?>> {
30 32
31 33 private static EmailValidator emailValidator = EmailValidator.getInstance();
32   -
33   - public void validate(D data) {
  34 +
  35 + public void validate(D data, Function<D, TenantId> tenantIdFunction) {
34 36 try {
35 37 if (data == null) {
36 38 throw new DataValidationException("Data object can't be null!");
37 39 }
38   - validateDataImpl(data);
  40 + TenantId tenantId = tenantIdFunction.apply(data);
  41 + validateDataImpl(tenantId, data);
39 42 if (data.getId() == null) {
40   - validateCreate(data);
  43 + validateCreate(tenantId, data);
41 44 } else {
42   - validateUpdate(data);
  45 + validateUpdate(tenantId, data);
43 46 }
44 47 } catch (DataValidationException e) {
45 48 log.error("Data object is invalid: [{}]", e.getMessage());
46 49 throw e;
47 50 }
48 51 }
49   -
50   - protected void validateDataImpl(D data) {
  52 +
  53 + protected void validateDataImpl(TenantId tenantId, D data) {
51 54 }
52   -
53   - protected void validateCreate(D data) {
  55 +
  56 + protected void validateCreate(TenantId tenantId, D data) {
54 57 }
55 58
56   - protected void validateUpdate(D data) {
  59 + protected void validateUpdate(TenantId tenantId, D data) {
57 60 }
58   -
  61 +
59 62 protected boolean isSameData(D existentData, D actualData) {
60 63 return actualData.getId() != null && existentData.getId().equals(actualData.getId());
61 64 }
62   -
  65 +
63 66 protected static void validateEmail(String email) {
64 67 if (!emailValidator.isValid(email)) {
65 68 throw new DataValidationException("Invalid email address format '" + email + "'!");
66 69 }
67 70 }
68   -
  71 +
69 72 protected static void validateJsonStructure(JsonNode expectedNode, JsonNode actualNode) {
70   - Set<String> expectedFields = new HashSet<>();
  73 + Set<String> expectedFields = new HashSet<>();
71 74 Iterator<String> fieldsIterator = expectedNode.fieldNames();
72 75 while (fieldsIterator.hasNext()) {
73 76 expectedFields.add(fieldsIterator.next());
74 77 }
75   -
76   - Set<String> actualFields = new HashSet<>();
  78 +
  79 + Set<String> actualFields = new HashSet<>();
77 80 fieldsIterator = actualNode.fieldNames();
78 81 while (fieldsIterator.hasNext()) {
79 82 actualFields.add(fieldsIterator.next());
80 83 }
81   -
  84 +
82 85 if (!expectedFields.containsAll(actualFields) || !actualFields.containsAll(expectedFields)) {
83 86 throw new DataValidationException("Provided json structure is different from stored one '" + actualNode + "'!");
84 87 }
85   -
  88 +
86 89 for (String field : actualFields) {
87 90 if (!actualNode.get(field).isTextual()) {
88 91 throw new DataValidationException("Provided json structure can't contain non-text values '" + actualNode + "'!");
... ...
... ... @@ -16,6 +16,7 @@
16 16 package org.thingsboard.server.dao.service;
17 17
18 18 import org.thingsboard.server.common.data.id.IdBased;
  19 +import org.thingsboard.server.common.data.id.TenantId;
19 20 import org.thingsboard.server.common.data.page.TextPageLink;
20 21
21 22 import java.util.List;
... ... @@ -25,13 +26,13 @@ public abstract class PaginatedRemover<I, D extends IdBased<?>> {
25 26
26 27 private static final int DEFAULT_LIMIT = 100;
27 28
28   - public void removeEntities(I id) {
  29 + public void removeEntities(TenantId tenantId, I id) {
29 30 TextPageLink pageLink = new TextPageLink(DEFAULT_LIMIT);
30 31 boolean hasNext = true;
31 32 while (hasNext) {
32   - List<D> entities = findEntities(id, pageLink);
  33 + List<D> entities = findEntities(tenantId, id, pageLink);
33 34 for (D entity : entities) {
34   - removeEntity(entity);
  35 + removeEntity(tenantId, entity);
35 36 }
36 37 hasNext = entities.size() == pageLink.getLimit();
37 38 if (hasNext) {
... ... @@ -42,8 +43,8 @@ public abstract class PaginatedRemover<I, D extends IdBased<?>> {
42 43 }
43 44 }
44 45
45   - protected abstract List<D> findEntities(I id, TextPageLink pageLink);
  46 + protected abstract List<D> findEntities(TenantId tenantId,I id, TextPageLink pageLink);
46 47
47   - protected abstract void removeEntity(D entity);
  48 + protected abstract void removeEntity(TenantId tenantId, D entity);
48 49
49 50 }
... ...
... ... @@ -16,6 +16,7 @@
16 16 package org.thingsboard.server.dao.settings;
17 17
18 18 import org.thingsboard.server.common.data.AdminSettings;
  19 +import org.thingsboard.server.common.data.id.TenantId;
19 20 import org.thingsboard.server.dao.Dao;
20 21
21 22 public interface AdminSettingsDao extends Dao<AdminSettings> {
... ... @@ -26,7 +27,7 @@ public interface AdminSettingsDao extends Dao<AdminSettings> {
26 27 * @param adminSettings the admin settings object
27 28 * @return saved admin settings object
28 29 */
29   - AdminSettings save(AdminSettings adminSettings);
  30 + AdminSettings save(TenantId tenantId, AdminSettings adminSettings);
30 31
31 32 /**
32 33 * Find admin settings by key.
... ... @@ -34,6 +35,6 @@ public interface AdminSettingsDao extends Dao<AdminSettings> {
34 35 * @param key the key
35 36 * @return the admin settings object
36 37 */
37   - AdminSettings findByKey(String key);
  38 + AdminSettings findByKey(TenantId tenantId, String key);
38 39
39 40 }
... ...
... ... @@ -17,13 +17,14 @@ package org.thingsboard.server.dao.settings;
17 17
18 18 import org.thingsboard.server.common.data.AdminSettings;
19 19 import org.thingsboard.server.common.data.id.AdminSettingsId;
  20 +import org.thingsboard.server.common.data.id.TenantId;
20 21
21 22 public interface AdminSettingsService {
22 23
23   - AdminSettings findAdminSettingsById(AdminSettingsId adminSettingsId);
  24 + AdminSettings findAdminSettingsById(TenantId tenantId, AdminSettingsId adminSettingsId);
24 25
25   - AdminSettings findAdminSettingsByKey(String key);
  26 + AdminSettings findAdminSettingsByKey(TenantId tenantId, String key);
26 27
27   - AdminSettings saveAdminSettings(AdminSettings adminSettings);
  28 + AdminSettings saveAdminSettings(TenantId tenantId, AdminSettings adminSettings);
28 29
29 30 }
... ...