Commit 104450c10276ba45ffd651e9a55a54288c71a107
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 | } | ... | ... |