Showing
21 changed files
with
642 additions
and
1 deletions
common/dao-api/src/main/java/org/thingsboard/server/dao/usagerecord/UsageRecordService.java
0 → 100644
1 | +/** | ||
2 | + * Copyright © 2016-2020 The Thingsboard Authors | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.thingsboard.server.dao.usagerecord; | ||
17 | + | ||
18 | +import org.thingsboard.server.common.data.UsageRecord; | ||
19 | +import org.thingsboard.server.common.data.id.TenantId; | ||
20 | + | ||
21 | +public interface UsageRecordService { | ||
22 | + | ||
23 | + UsageRecord findTenantUsageRecord(TenantId tenantId); | ||
24 | + | ||
25 | + void deleteUsageRecordsByTenantId(TenantId tenantId); | ||
26 | + | ||
27 | + void createDefaultUsageRecord(TenantId id); | ||
28 | +} |
@@ -19,5 +19,5 @@ package org.thingsboard.server.common.data; | @@ -19,5 +19,5 @@ package org.thingsboard.server.common.data; | ||
19 | * @author Andrew Shvayka | 19 | * @author Andrew Shvayka |
20 | */ | 20 | */ |
21 | public enum EntityType { | 21 | public enum EntityType { |
22 | - TENANT, CUSTOMER, USER, DASHBOARD, ASSET, DEVICE, ALARM, RULE_CHAIN, RULE_NODE, ENTITY_VIEW, WIDGETS_BUNDLE, WIDGET_TYPE, TENANT_PROFILE, DEVICE_PROFILE | 22 | + TENANT, CUSTOMER, USER, DASHBOARD, ASSET, DEVICE, ALARM, RULE_CHAIN, RULE_NODE, ENTITY_VIEW, WIDGETS_BUNDLE, WIDGET_TYPE, TENANT_PROFILE, DEVICE_PROFILE, USAGE_RECORD; |
23 | } | 23 | } |
1 | +/** | ||
2 | + * Copyright © 2016-2020 The Thingsboard Authors | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.thingsboard.server.common.data; | ||
17 | + | ||
18 | +import lombok.EqualsAndHashCode; | ||
19 | +import lombok.ToString; | ||
20 | +import org.thingsboard.server.common.data.id.EntityId; | ||
21 | +import org.thingsboard.server.common.data.id.TenantId; | ||
22 | +import org.thingsboard.server.common.data.id.UsageRecordId; | ||
23 | +import org.thingsboard.server.common.data.id.UserId; | ||
24 | + | ||
25 | +@ToString | ||
26 | +@EqualsAndHashCode(callSuper = true) | ||
27 | +public class UsageRecord extends BaseData<UsageRecordId> implements HasTenantId { | ||
28 | + | ||
29 | + private static final long serialVersionUID = 8250339805336035966L; | ||
30 | + | ||
31 | + private TenantId tenantId; | ||
32 | + private EntityId entityId; | ||
33 | + | ||
34 | + public UsageRecord() { | ||
35 | + super(); | ||
36 | + } | ||
37 | + | ||
38 | + public UsageRecord(UsageRecordId id) { | ||
39 | + super(id); | ||
40 | + } | ||
41 | + | ||
42 | + public UsageRecord(UsageRecord ur) { | ||
43 | + super(ur); | ||
44 | + this.tenantId = ur.getTenantId(); | ||
45 | + this.entityId = ur.getEntityId(); | ||
46 | + } | ||
47 | + | ||
48 | + @Override | ||
49 | + public TenantId getTenantId() { | ||
50 | + return tenantId; | ||
51 | + } | ||
52 | + | ||
53 | + public void setTenantId(TenantId tenantId) { | ||
54 | + this.tenantId = tenantId; | ||
55 | + } | ||
56 | + | ||
57 | + public EntityId getEntityId() { | ||
58 | + return entityId; | ||
59 | + } | ||
60 | + | ||
61 | + public void setEntityId(EntityId entityId) { | ||
62 | + this.entityId = entityId; | ||
63 | + } | ||
64 | + | ||
65 | +} |
1 | +/** | ||
2 | + * Copyright © 2016-2020 The Thingsboard Authors | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.thingsboard.server.common.data; | ||
17 | + | ||
18 | +public enum UsageRecordKey { | ||
19 | + | ||
20 | + MSG_COUNT, | ||
21 | + MSG_BYTES_COUNT, | ||
22 | + DP_TRANSPORT_COUNT, | ||
23 | + DP_STORAGE_COUNT, | ||
24 | + RE_EXEC_COUNT, | ||
25 | + JS_EXEC_COUNT | ||
26 | + | ||
27 | +} |
1 | +/** | ||
2 | + * Copyright © 2016-2020 The Thingsboard Authors | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.thingsboard.server.common.data.id; | ||
17 | + | ||
18 | +import com.fasterxml.jackson.annotation.JsonCreator; | ||
19 | +import com.fasterxml.jackson.annotation.JsonIgnore; | ||
20 | +import com.fasterxml.jackson.annotation.JsonProperty; | ||
21 | +import org.thingsboard.server.common.data.EntityType; | ||
22 | + | ||
23 | +import java.util.UUID; | ||
24 | + | ||
25 | +public class UsageRecordId extends UUIDBased implements EntityId { | ||
26 | + | ||
27 | + @JsonCreator | ||
28 | + public UsageRecordId(@JsonProperty("id") UUID id) { | ||
29 | + super(id); | ||
30 | + } | ||
31 | + | ||
32 | + public static UsageRecordId fromString(String userId) { | ||
33 | + return new UsageRecordId(UUID.fromString(userId)); | ||
34 | + } | ||
35 | + | ||
36 | + @JsonIgnore | ||
37 | + @Override | ||
38 | + public EntityType getEntityType() { | ||
39 | + return EntityType.USAGE_RECORD; | ||
40 | + } | ||
41 | + | ||
42 | +} |
@@ -439,6 +439,14 @@ public class ModelConstants { | @@ -439,6 +439,14 @@ public class ModelConstants { | ||
439 | public static final String OAUTH2_TEMPLATE_HELP_LINK_PROPERTY = "help_link"; | 439 | public static final String OAUTH2_TEMPLATE_HELP_LINK_PROPERTY = "help_link"; |
440 | 440 | ||
441 | /** | 441 | /** |
442 | + * Usage Record constants. | ||
443 | + */ | ||
444 | + public static final String UR_TABLE_NAME = "usage_record"; | ||
445 | + public static final String UR_TENANT_ID_COLUMN = TENANT_ID_PROPERTY; | ||
446 | + public static final String UR_ENTITY_TYPE_COLUMN = ENTITY_TYPE_COLUMN; | ||
447 | + public static final String UR_ENTITY_ID_COLUMN = ENTITY_ID_COLUMN; | ||
448 | + | ||
449 | + /** | ||
442 | * Cassandra attributes and timeseries constants. | 450 | * Cassandra attributes and timeseries constants. |
443 | */ | 451 | */ |
444 | public static final String ATTRIBUTES_KV_CF = "attributes_kv_cf"; | 452 | public static final String ATTRIBUTES_KV_CF = "attributes_kv_cf"; |
1 | +/** | ||
2 | + * Copyright © 2016-2020 The Thingsboard Authors | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.thingsboard.server.dao.model.sql; | ||
17 | + | ||
18 | +import com.fasterxml.jackson.databind.JsonNode; | ||
19 | +import lombok.Data; | ||
20 | +import lombok.EqualsAndHashCode; | ||
21 | +import org.hibernate.annotations.Type; | ||
22 | +import org.hibernate.annotations.TypeDef; | ||
23 | +import org.thingsboard.server.common.data.UsageRecord; | ||
24 | +import org.thingsboard.server.common.data.User; | ||
25 | +import org.thingsboard.server.common.data.id.CustomerId; | ||
26 | +import org.thingsboard.server.common.data.id.EntityIdFactory; | ||
27 | +import org.thingsboard.server.common.data.id.TenantId; | ||
28 | +import org.thingsboard.server.common.data.id.UsageRecordId; | ||
29 | +import org.thingsboard.server.common.data.id.UserId; | ||
30 | +import org.thingsboard.server.common.data.security.Authority; | ||
31 | +import org.thingsboard.server.dao.model.BaseEntity; | ||
32 | +import org.thingsboard.server.dao.model.BaseSqlEntity; | ||
33 | +import org.thingsboard.server.dao.model.ModelConstants; | ||
34 | +import org.thingsboard.server.dao.model.SearchTextEntity; | ||
35 | +import org.thingsboard.server.dao.util.mapping.JsonStringType; | ||
36 | + | ||
37 | +import javax.persistence.Column; | ||
38 | +import javax.persistence.Entity; | ||
39 | +import javax.persistence.EnumType; | ||
40 | +import javax.persistence.Enumerated; | ||
41 | +import javax.persistence.Table; | ||
42 | +import java.util.UUID; | ||
43 | + | ||
44 | +/** | ||
45 | + * Created by Valerii Sosliuk on 4/21/2017. | ||
46 | + */ | ||
47 | +@Data | ||
48 | +@EqualsAndHashCode(callSuper = true) | ||
49 | +@Entity | ||
50 | +@TypeDef(name = "json", typeClass = JsonStringType.class) | ||
51 | +@Table(name = ModelConstants.UR_TABLE_NAME) | ||
52 | +public class UsageRecordEntity extends BaseSqlEntity<UsageRecord> implements BaseEntity<UsageRecord> { | ||
53 | + | ||
54 | + @Column(name = ModelConstants.UR_TENANT_ID_COLUMN) | ||
55 | + private UUID tenantId; | ||
56 | + | ||
57 | + @Column(name = ModelConstants.UR_ENTITY_TYPE_COLUMN) | ||
58 | + private String entityType; | ||
59 | + | ||
60 | + @Column(name = ModelConstants.UR_ENTITY_ID_COLUMN) | ||
61 | + private UUID entityId; | ||
62 | + | ||
63 | + public UsageRecordEntity() { | ||
64 | + } | ||
65 | + | ||
66 | + public UsageRecordEntity(UsageRecord ur) { | ||
67 | + if (ur.getId() != null) { | ||
68 | + this.setUuid(ur.getId().getId()); | ||
69 | + } | ||
70 | + this.setCreatedTime(ur.getCreatedTime()); | ||
71 | + if (ur.getTenantId() != null) { | ||
72 | + this.tenantId = ur.getTenantId().getId(); | ||
73 | + } | ||
74 | + if (ur.getEntityId() != null) { | ||
75 | + this.entityType = ur.getEntityId().getEntityType().name(); | ||
76 | + this.entityId = ur.getEntityId().getId(); | ||
77 | + } | ||
78 | + } | ||
79 | + | ||
80 | + @Override | ||
81 | + public UsageRecord toData() { | ||
82 | + UsageRecord ur = new UsageRecord(new UsageRecordId(this.getUuid())); | ||
83 | + ur.setCreatedTime(createdTime); | ||
84 | + if (tenantId != null) { | ||
85 | + ur.setTenantId(new TenantId(tenantId)); | ||
86 | + } | ||
87 | + if (entityId != null) { | ||
88 | + ur.setEntityId(EntityIdFactory.getByTypeAndUuid(entityType, entityId)); | ||
89 | + } | ||
90 | + return ur; | ||
91 | + } | ||
92 | + | ||
93 | +} |
1 | +/** | ||
2 | + * Copyright © 2016-2020 The Thingsboard Authors | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.thingsboard.server.dao.sql.usagerecord; | ||
17 | + | ||
18 | +import org.springframework.data.repository.CrudRepository; | ||
19 | +import org.springframework.stereotype.Component; | ||
20 | +import org.thingsboard.server.common.data.UsageRecord; | ||
21 | +import org.thingsboard.server.common.data.id.TenantId; | ||
22 | +import org.thingsboard.server.dao.DaoUtil; | ||
23 | +import org.thingsboard.server.dao.model.sql.UsageRecordEntity; | ||
24 | +import org.thingsboard.server.dao.sql.JpaAbstractDao; | ||
25 | +import org.thingsboard.server.dao.usagerecord.UsageRecordDao; | ||
26 | + | ||
27 | +import java.util.UUID; | ||
28 | + | ||
29 | +/** | ||
30 | + * @author Andrii Shvaika | ||
31 | + */ | ||
32 | +@Component | ||
33 | +public class JpaUsageRecordDao extends JpaAbstractDao<UsageRecordEntity, UsageRecord> implements UsageRecordDao { | ||
34 | + | ||
35 | + private final UsageRecordRepository usageRecordRepository; | ||
36 | + | ||
37 | + public JpaUsageRecordDao(UsageRecordRepository usageRecordRepository) { | ||
38 | + this.usageRecordRepository = usageRecordRepository; | ||
39 | + } | ||
40 | + | ||
41 | + @Override | ||
42 | + protected Class<UsageRecordEntity> getEntityClass() { | ||
43 | + return UsageRecordEntity.class; | ||
44 | + } | ||
45 | + | ||
46 | + @Override | ||
47 | + protected CrudRepository<UsageRecordEntity, UUID> getCrudRepository() { | ||
48 | + return usageRecordRepository; | ||
49 | + } | ||
50 | + | ||
51 | + @Override | ||
52 | + public UsageRecord findTenantUsageRecord(UUID tenantId) { | ||
53 | + return DaoUtil.getData(usageRecordRepository.findByTenantId(tenantId)); | ||
54 | + } | ||
55 | + | ||
56 | + @Override | ||
57 | + public void deleteUsageRecordsByTenantId(TenantId tenantId) { | ||
58 | + usageRecordRepository.deleteUsageRecordsByTenantId(tenantId.getId()); | ||
59 | + } | ||
60 | +} |
1 | +/** | ||
2 | + * Copyright © 2016-2020 The Thingsboard Authors | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.thingsboard.server.dao.sql.usagerecord; | ||
17 | + | ||
18 | +import org.springframework.data.jpa.repository.Modifying; | ||
19 | +import org.springframework.data.jpa.repository.Query; | ||
20 | +import org.springframework.data.repository.CrudRepository; | ||
21 | +import org.springframework.data.repository.query.Param; | ||
22 | +import org.springframework.transaction.annotation.Transactional; | ||
23 | +import org.thingsboard.server.common.data.UsageRecord; | ||
24 | +import org.thingsboard.server.common.data.id.TenantId; | ||
25 | +import org.thingsboard.server.dao.model.sql.UsageRecordEntity; | ||
26 | +import org.thingsboard.server.dao.model.sql.UserEntity; | ||
27 | + | ||
28 | +import java.util.UUID; | ||
29 | + | ||
30 | +/** | ||
31 | + * @author Valerii Sosliuk | ||
32 | + */ | ||
33 | +public interface UsageRecordRepository extends CrudRepository<UsageRecordEntity, UUID> { | ||
34 | + | ||
35 | + @Query("SELECT ur FROM UsageRecordEntity ur WHERE ur.tenantId = :tenantId " + | ||
36 | + "AND ur.entityId = :tenantId AND ur.entityType = 'TENANT' ") | ||
37 | + UsageRecordEntity findByTenantId(@Param("tenantId") UUID tenantId); | ||
38 | + | ||
39 | + @Transactional | ||
40 | + @Modifying | ||
41 | + @Query("DELETE FROM UsageRecordEntity ur WHERE ur.tenantId = :tenantId") | ||
42 | + void deleteUsageRecordsByTenantId(@Param("tenantId") UUID tenantId); | ||
43 | +} |
@@ -39,6 +39,7 @@ import org.thingsboard.server.dao.rule.RuleChainService; | @@ -39,6 +39,7 @@ import org.thingsboard.server.dao.rule.RuleChainService; | ||
39 | import org.thingsboard.server.dao.service.DataValidator; | 39 | import org.thingsboard.server.dao.service.DataValidator; |
40 | import org.thingsboard.server.dao.service.PaginatedRemover; | 40 | import org.thingsboard.server.dao.service.PaginatedRemover; |
41 | import org.thingsboard.server.dao.service.Validator; | 41 | import org.thingsboard.server.dao.service.Validator; |
42 | +import org.thingsboard.server.dao.usagerecord.UsageRecordService; | ||
42 | import org.thingsboard.server.dao.user.UserService; | 43 | import org.thingsboard.server.dao.user.UserService; |
43 | import org.thingsboard.server.dao.widget.WidgetsBundleService; | 44 | import org.thingsboard.server.dao.widget.WidgetsBundleService; |
44 | 45 | ||
@@ -73,6 +74,9 @@ public class TenantServiceImpl extends AbstractEntityService implements TenantSe | @@ -73,6 +74,9 @@ public class TenantServiceImpl extends AbstractEntityService implements TenantSe | ||
73 | private DeviceProfileService deviceProfileService; | 74 | private DeviceProfileService deviceProfileService; |
74 | 75 | ||
75 | @Autowired | 76 | @Autowired |
77 | + private UsageRecordService usageRecordService; | ||
78 | + | ||
79 | + @Autowired | ||
76 | private EntityViewService entityViewService; | 80 | private EntityViewService entityViewService; |
77 | 81 | ||
78 | @Autowired | 82 | @Autowired |
@@ -117,6 +121,7 @@ public class TenantServiceImpl extends AbstractEntityService implements TenantSe | @@ -117,6 +121,7 @@ public class TenantServiceImpl extends AbstractEntityService implements TenantSe | ||
117 | Tenant savedTenant = tenantDao.save(tenant.getId(), tenant); | 121 | Tenant savedTenant = tenantDao.save(tenant.getId(), tenant); |
118 | if (tenant.getId() == null) { | 122 | if (tenant.getId() == null) { |
119 | deviceProfileService.createDefaultDeviceProfile(savedTenant.getId()); | 123 | deviceProfileService.createDefaultDeviceProfile(savedTenant.getId()); |
124 | + usageRecordService.createDefaultUsageRecord(savedTenant.getId()); | ||
120 | } | 125 | } |
121 | return savedTenant; | 126 | return savedTenant; |
122 | } | 127 | } |
@@ -134,6 +139,7 @@ public class TenantServiceImpl extends AbstractEntityService implements TenantSe | @@ -134,6 +139,7 @@ public class TenantServiceImpl extends AbstractEntityService implements TenantSe | ||
134 | deviceProfileService.deleteDeviceProfilesByTenantId(tenantId); | 139 | deviceProfileService.deleteDeviceProfilesByTenantId(tenantId); |
135 | userService.deleteTenantAdmins(tenantId); | 140 | userService.deleteTenantAdmins(tenantId); |
136 | ruleChainService.deleteRuleChainsByTenantId(tenantId); | 141 | ruleChainService.deleteRuleChainsByTenantId(tenantId); |
142 | + usageRecordService.deleteUsageRecordsByTenantId(tenantId); | ||
137 | tenantDao.removeById(tenantId, tenantId.getId()); | 143 | tenantDao.removeById(tenantId, tenantId.getId()); |
138 | deleteEntityRelations(tenantId, tenantId); | 144 | deleteEntityRelations(tenantId, tenantId); |
139 | } | 145 | } |
1 | +/** | ||
2 | + * Copyright © 2016-2020 The Thingsboard Authors | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.thingsboard.server.dao.usagerecord; | ||
17 | + | ||
18 | +import org.thingsboard.server.common.data.UsageRecord; | ||
19 | +import org.thingsboard.server.common.data.User; | ||
20 | +import org.thingsboard.server.common.data.id.TenantId; | ||
21 | +import org.thingsboard.server.common.data.page.PageData; | ||
22 | +import org.thingsboard.server.common.data.page.PageLink; | ||
23 | +import org.thingsboard.server.dao.Dao; | ||
24 | + | ||
25 | +import java.util.UUID; | ||
26 | + | ||
27 | +public interface UsageRecordDao extends Dao<UsageRecord> { | ||
28 | + | ||
29 | + /** | ||
30 | + * Save or update usage record object | ||
31 | + * | ||
32 | + * @param usageRecord the usage record | ||
33 | + * @return saved usage record entity | ||
34 | + */ | ||
35 | + UsageRecord save(TenantId tenantId, UsageRecord usageRecord); | ||
36 | + | ||
37 | + /** | ||
38 | + * Find usage record by tenantId. | ||
39 | + * | ||
40 | + * @param tenantId the tenantId | ||
41 | + * @return the corresponding usage record | ||
42 | + */ | ||
43 | + UsageRecord findTenantUsageRecord(UUID tenantId); | ||
44 | + | ||
45 | + /** | ||
46 | + * Delete usage record by tenantId. | ||
47 | + * | ||
48 | + * @param tenantId the tenantId | ||
49 | + */ | ||
50 | + void deleteUsageRecordsByTenantId(TenantId tenantId); | ||
51 | +} |
1 | +/** | ||
2 | + * Copyright © 2016-2020 The Thingsboard Authors | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.thingsboard.server.dao.usagerecord; | ||
17 | + | ||
18 | +import com.fasterxml.jackson.databind.JsonNode; | ||
19 | +import com.fasterxml.jackson.databind.node.ObjectNode; | ||
20 | +import com.google.common.util.concurrent.ListenableFuture; | ||
21 | +import lombok.extern.slf4j.Slf4j; | ||
22 | +import org.apache.commons.lang3.RandomStringUtils; | ||
23 | +import org.springframework.beans.factory.annotation.Autowired; | ||
24 | +import org.springframework.stereotype.Service; | ||
25 | +import org.springframework.util.StringUtils; | ||
26 | +import org.thingsboard.server.common.data.Customer; | ||
27 | +import org.thingsboard.server.common.data.EntityType; | ||
28 | +import org.thingsboard.server.common.data.Tenant; | ||
29 | +import org.thingsboard.server.common.data.UsageRecord; | ||
30 | +import org.thingsboard.server.common.data.User; | ||
31 | +import org.thingsboard.server.common.data.id.CustomerId; | ||
32 | +import org.thingsboard.server.common.data.id.TenantId; | ||
33 | +import org.thingsboard.server.common.data.id.UserCredentialsId; | ||
34 | +import org.thingsboard.server.common.data.id.UserId; | ||
35 | +import org.thingsboard.server.common.data.page.PageData; | ||
36 | +import org.thingsboard.server.common.data.page.PageLink; | ||
37 | +import org.thingsboard.server.common.data.security.UserCredentials; | ||
38 | +import org.thingsboard.server.dao.entity.AbstractEntityService; | ||
39 | +import org.thingsboard.server.dao.exception.DataValidationException; | ||
40 | +import org.thingsboard.server.dao.exception.IncorrectParameterException; | ||
41 | +import org.thingsboard.server.dao.model.ModelConstants; | ||
42 | +import org.thingsboard.server.dao.service.DataValidator; | ||
43 | +import org.thingsboard.server.dao.tenant.TenantDao; | ||
44 | + | ||
45 | +import java.util.HashMap; | ||
46 | +import java.util.Map; | ||
47 | + | ||
48 | +import static org.thingsboard.server.dao.service.Validator.validateId; | ||
49 | +import static org.thingsboard.server.dao.service.Validator.validatePageLink; | ||
50 | +import static org.thingsboard.server.dao.service.Validator.validateString; | ||
51 | + | ||
52 | +@Service | ||
53 | +@Slf4j | ||
54 | +public class UsageRecordServiceImpl extends AbstractEntityService implements UsageRecordService { | ||
55 | + public static final String INCORRECT_TENANT_ID = "Incorrect tenantId "; | ||
56 | + | ||
57 | + private final UsageRecordDao usageRecordDao; | ||
58 | + private final TenantDao tenantDao; | ||
59 | + | ||
60 | + public UsageRecordServiceImpl(TenantDao tenantDao, UsageRecordDao usageRecordDao) { | ||
61 | + this.tenantDao = tenantDao; | ||
62 | + this.usageRecordDao = usageRecordDao; | ||
63 | + } | ||
64 | + | ||
65 | + @Override | ||
66 | + public void deleteUsageRecordsByTenantId(TenantId tenantId) { | ||
67 | + log.trace("Executing deleteUsageRecordsByTenantId [{}]", tenantId); | ||
68 | + validateId(tenantId, INCORRECT_TENANT_ID + tenantId); | ||
69 | + usageRecordDao.deleteUsageRecordsByTenantId(tenantId); | ||
70 | + } | ||
71 | + | ||
72 | + @Override | ||
73 | + public void createDefaultUsageRecord(TenantId tenantId) { | ||
74 | + log.trace("Executing createDefaultUsageRecord [{}]", tenantId); | ||
75 | + validateId(tenantId, INCORRECT_TENANT_ID + tenantId); | ||
76 | + UsageRecord usageRecord = new UsageRecord(); | ||
77 | + usageRecord.setTenantId(tenantId); | ||
78 | + usageRecord.setEntityId(tenantId); | ||
79 | + usageRecordValidator.validate(usageRecord, UsageRecord::getTenantId); | ||
80 | + usageRecordDao.save(usageRecord.getTenantId(), usageRecord); | ||
81 | + } | ||
82 | + | ||
83 | + @Override | ||
84 | + public UsageRecord findTenantUsageRecord(TenantId tenantId) { | ||
85 | + log.trace("Executing findTenantUsageRecord, tenantId [{}]", tenantId); | ||
86 | + validateId(tenantId, INCORRECT_TENANT_ID + tenantId); | ||
87 | + return usageRecordDao.findTenantUsageRecord(tenantId.getId()); | ||
88 | + } | ||
89 | + | ||
90 | + private DataValidator<UsageRecord> usageRecordValidator = | ||
91 | + new DataValidator<UsageRecord>() { | ||
92 | + @Override | ||
93 | + protected void validateDataImpl(TenantId requestTenantId, UsageRecord usageRecord) { | ||
94 | + if (usageRecord.getTenantId() == null) { | ||
95 | + throw new DataValidationException("UsageRecord should be assigned to tenant!"); | ||
96 | + } else { | ||
97 | + Tenant tenant = tenantDao.findById(requestTenantId, usageRecord.getTenantId().getId()); | ||
98 | + if (tenant == null) { | ||
99 | + throw new DataValidationException("Asset is referencing to non-existent tenant!"); | ||
100 | + } | ||
101 | + } | ||
102 | + if (usageRecord.getEntityId() == null) { | ||
103 | + throw new DataValidationException("UsageRecord should be assigned to entity!"); | ||
104 | + } else if (!EntityType.TENANT.equals(usageRecord.getEntityId().getEntityType())) { | ||
105 | + throw new DataValidationException("Only Tenant Usage Records are supported!"); | ||
106 | + } else if (!usageRecord.getTenantId().getId().equals(usageRecord.getEntityId().getId())) { | ||
107 | + throw new DataValidationException("Can't assign one Usage Record to multiple tenants!"); | ||
108 | + } | ||
109 | + } | ||
110 | + }; | ||
111 | + | ||
112 | +} |
@@ -404,3 +404,12 @@ CREATE TABLE IF NOT EXISTS oauth2_client_registration_template ( | @@ -404,3 +404,12 @@ CREATE TABLE IF NOT EXISTS oauth2_client_registration_template ( | ||
404 | help_link varchar(255), | 404 | help_link varchar(255), |
405 | CONSTRAINT oauth2_template_provider_id_unq_key UNIQUE (provider_id) | 405 | CONSTRAINT oauth2_template_provider_id_unq_key UNIQUE (provider_id) |
406 | ); | 406 | ); |
407 | + | ||
408 | +CREATE TABLE IF NOT EXISTS usage_record ( | ||
409 | + id uuid NOT NULL CONSTRAINT usage_record_pkey PRIMARY KEY, | ||
410 | + created_time bigint NOT NULL, | ||
411 | + tenant_id uuid, | ||
412 | + entity_type varchar(32), | ||
413 | + entity_id uuid, | ||
414 | + CONSTRAINT usage_record_unq_key UNIQUE (tenant_id, entity_id) | ||
415 | +); |
@@ -431,6 +431,15 @@ CREATE TABLE IF NOT EXISTS oauth2_client_registration_template ( | @@ -431,6 +431,15 @@ CREATE TABLE IF NOT EXISTS oauth2_client_registration_template ( | ||
431 | CONSTRAINT oauth2_template_provider_id_unq_key UNIQUE (provider_id) | 431 | CONSTRAINT oauth2_template_provider_id_unq_key UNIQUE (provider_id) |
432 | ); | 432 | ); |
433 | 433 | ||
434 | +CREATE TABLE IF NOT EXISTS usage_record ( | ||
435 | + id uuid NOT NULL CONSTRAINT usage_record_pkey PRIMARY KEY, | ||
436 | + created_time bigint NOT NULL, | ||
437 | + tenant_id uuid, | ||
438 | + entity_type varchar(32), | ||
439 | + entity_id uuid, | ||
440 | + CONSTRAINT usage_record_unq_key UNIQUE (tenant_id, entity_id) | ||
441 | +); | ||
442 | + | ||
434 | CREATE OR REPLACE PROCEDURE cleanup_events_by_ttl(IN ttl bigint, IN debug_ttl bigint, INOUT deleted bigint) | 443 | CREATE OR REPLACE PROCEDURE cleanup_events_by_ttl(IN ttl bigint, IN debug_ttl bigint, INOUT deleted bigint) |
435 | LANGUAGE plpgsql AS | 444 | LANGUAGE plpgsql AS |
436 | $$ | 445 | $$ |
@@ -61,6 +61,7 @@ import org.thingsboard.server.dao.settings.AdminSettingsService; | @@ -61,6 +61,7 @@ import org.thingsboard.server.dao.settings.AdminSettingsService; | ||
61 | import org.thingsboard.server.dao.tenant.TenantProfileService; | 61 | import org.thingsboard.server.dao.tenant.TenantProfileService; |
62 | import org.thingsboard.server.dao.tenant.TenantService; | 62 | import org.thingsboard.server.dao.tenant.TenantService; |
63 | import org.thingsboard.server.dao.timeseries.TimeseriesService; | 63 | import org.thingsboard.server.dao.timeseries.TimeseriesService; |
64 | +import org.thingsboard.server.dao.usagerecord.UsageRecordService; | ||
64 | import org.thingsboard.server.dao.user.UserService; | 65 | import org.thingsboard.server.dao.user.UserService; |
65 | import org.thingsboard.server.dao.widget.WidgetTypeService; | 66 | import org.thingsboard.server.dao.widget.WidgetTypeService; |
66 | import org.thingsboard.server.dao.widget.WidgetsBundleService; | 67 | import org.thingsboard.server.dao.widget.WidgetsBundleService; |
@@ -86,6 +87,9 @@ public abstract class AbstractServiceTest { | @@ -86,6 +87,9 @@ public abstract class AbstractServiceTest { | ||
86 | protected UserService userService; | 87 | protected UserService userService; |
87 | 88 | ||
88 | @Autowired | 89 | @Autowired |
90 | + protected UsageRecordService usageRecordService; | ||
91 | + | ||
92 | + @Autowired | ||
89 | protected AdminSettingsService adminSettingsService; | 93 | protected AdminSettingsService adminSettingsService; |
90 | 94 | ||
91 | @Autowired | 95 | @Autowired |
1 | +/** | ||
2 | + * Copyright © 2016-2020 The Thingsboard Authors | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.thingsboard.server.dao.service; | ||
17 | + | ||
18 | +import org.junit.After; | ||
19 | +import org.junit.Assert; | ||
20 | +import org.junit.Before; | ||
21 | +import org.junit.Test; | ||
22 | +import org.thingsboard.server.common.data.Customer; | ||
23 | +import org.thingsboard.server.common.data.Tenant; | ||
24 | +import org.thingsboard.server.common.data.UsageRecord; | ||
25 | +import org.thingsboard.server.common.data.User; | ||
26 | +import org.thingsboard.server.common.data.id.CustomerId; | ||
27 | +import org.thingsboard.server.common.data.id.TenantId; | ||
28 | +import org.thingsboard.server.dao.service.AbstractServiceTest; | ||
29 | +import org.thingsboard.server.dao.service.DaoSqlTest; | ||
30 | + | ||
31 | + | ||
32 | +public abstract class BaseUsageRecordServiceTest extends AbstractServiceTest { | ||
33 | + | ||
34 | + private TenantId tenantId; | ||
35 | + | ||
36 | + @Before | ||
37 | + public void before() { | ||
38 | + Tenant tenant = new Tenant(); | ||
39 | + tenant.setTitle("My tenant"); | ||
40 | + Tenant savedTenant = tenantService.saveTenant(tenant); | ||
41 | + Assert.assertNotNull(savedTenant); | ||
42 | + tenantId = savedTenant.getId(); | ||
43 | + } | ||
44 | + | ||
45 | + @After | ||
46 | + public void after() { | ||
47 | + tenantService.deleteTenant(tenantId); | ||
48 | + } | ||
49 | + | ||
50 | + @Test | ||
51 | + public void testFindUsageRecordByTenantId() { | ||
52 | + UsageRecord usageRecord = usageRecordService.findTenantUsageRecord(tenantId); | ||
53 | + Assert.assertNotNull(usageRecord); | ||
54 | + } | ||
55 | + | ||
56 | +} |
1 | +/** | ||
2 | + * Copyright © 2016-2020 The Thingsboard Authors | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.thingsboard.server.dao.service.sql; | ||
17 | + | ||
18 | +import org.thingsboard.server.dao.service.BaseUsageRecordServiceTest; | ||
19 | +import org.thingsboard.server.dao.service.BaseUserServiceTest; | ||
20 | +import org.thingsboard.server.dao.service.DaoSqlTest; | ||
21 | + | ||
22 | +@DaoSqlTest | ||
23 | +public class UsageRecordServiceSqlTest extends BaseUsageRecordServiceTest { | ||
24 | +} |
@@ -27,4 +27,5 @@ DROP TABLE IF EXISTS rule_chain; | @@ -27,4 +27,5 @@ DROP TABLE IF EXISTS rule_chain; | ||
27 | DROP TABLE IF EXISTS oauth2_client_registration; | 27 | DROP TABLE IF EXISTS oauth2_client_registration; |
28 | DROP TABLE IF EXISTS oauth2_client_registration_info; | 28 | DROP TABLE IF EXISTS oauth2_client_registration_info; |
29 | DROP TABLE IF EXISTS oauth2_client_registration_template; | 29 | DROP TABLE IF EXISTS oauth2_client_registration_template; |
30 | +DROP TABLE IF EXISTS usage_record; | ||
30 | DROP FUNCTION IF EXISTS to_uuid; | 31 | DROP FUNCTION IF EXISTS to_uuid; |
@@ -28,3 +28,4 @@ DROP TABLE IF EXISTS tb_schema_settings; | @@ -28,3 +28,4 @@ DROP TABLE IF EXISTS tb_schema_settings; | ||
28 | DROP TABLE IF EXISTS oauth2_client_registration; | 28 | DROP TABLE IF EXISTS oauth2_client_registration; |
29 | DROP TABLE IF EXISTS oauth2_client_registration_info; | 29 | DROP TABLE IF EXISTS oauth2_client_registration_info; |
30 | DROP TABLE IF EXISTS oauth2_client_registration_template; | 30 | DROP TABLE IF EXISTS oauth2_client_registration_template; |
31 | +DROP TABLE IF EXISTS usage_record; |
@@ -28,3 +28,4 @@ DROP TABLE IF EXISTS tb_schema_settings; | @@ -28,3 +28,4 @@ DROP TABLE IF EXISTS tb_schema_settings; | ||
28 | DROP TABLE IF EXISTS oauth2_client_registration; | 28 | DROP TABLE IF EXISTS oauth2_client_registration; |
29 | DROP TABLE IF EXISTS oauth2_client_registration_info; | 29 | DROP TABLE IF EXISTS oauth2_client_registration_info; |
30 | DROP TABLE IF EXISTS oauth2_client_registration_template; | 30 | DROP TABLE IF EXISTS oauth2_client_registration_template; |
31 | +DROP TABLE IF EXISTS usage_record; |
@@ -340,6 +340,7 @@ final class MqttClientImpl implements MqttClient { | @@ -340,6 +340,7 @@ final class MqttClientImpl implements MqttClient { | ||
340 | MqttPublishVariableHeader variableHeader = new MqttPublishVariableHeader(topic, getNewMessageId().messageId()); | 340 | MqttPublishVariableHeader variableHeader = new MqttPublishVariableHeader(topic, getNewMessageId().messageId()); |
341 | MqttPublishMessage message = new MqttPublishMessage(fixedHeader, variableHeader, payload); | 341 | MqttPublishMessage message = new MqttPublishMessage(fixedHeader, variableHeader, payload); |
342 | MqttPendingPublish pendingPublish = new MqttPendingPublish(variableHeader.packetId(), future, payload.retain(), message, qos); | 342 | MqttPendingPublish pendingPublish = new MqttPendingPublish(variableHeader.packetId(), future, payload.retain(), message, qos); |
343 | + | ||
343 | ChannelFuture channelFuture = this.sendAndFlushPacket(message); | 344 | ChannelFuture channelFuture = this.sendAndFlushPacket(message); |
344 | 345 | ||
345 | if (channelFuture != null) { | 346 | if (channelFuture != null) { |