Commit 2e694e1d649d46c514d0bba86e3bc27054889d74

Authored by Andrii Shvaika
1 parent e9bf5bae

Dao layer for UsageRecords

Showing 21 changed files with 642 additions and 1 deletions
  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) {