Merge branch 'master' of github.com:thingsboard/thingsboard
This commit is contained in:
commit
10e6b9a458
@ -145,10 +145,6 @@
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-websocket</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-oauth2</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-oauth2-client</artifactId>
|
||||
|
||||
@ -24,6 +24,10 @@ public class DefaultTenantProfileConfiguration implements TenantProfileConfigura
|
||||
|
||||
private long maxDevices;
|
||||
private long maxAssets;
|
||||
private long maxCustomers;
|
||||
private long maxUsers;
|
||||
private long maxDashboards;
|
||||
private long maxRuleChains;
|
||||
|
||||
private String transportTenantMsgRateLimit;
|
||||
private String transportTenantTelemetryMsgRateLimit;
|
||||
|
||||
@ -0,0 +1,23 @@
|
||||
/**
|
||||
* Copyright © 2016-2020 The Thingsboard Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.thingsboard.server.dao;
|
||||
|
||||
import org.thingsboard.server.common.data.id.TenantId;
|
||||
|
||||
public interface TenantEntityDao {
|
||||
|
||||
Long countByTenantId(TenantId tenantId);
|
||||
}
|
||||
@ -23,6 +23,7 @@ import org.thingsboard.server.common.data.id.TenantId;
|
||||
import org.thingsboard.server.common.data.page.PageData;
|
||||
import org.thingsboard.server.common.data.page.PageLink;
|
||||
import org.thingsboard.server.dao.Dao;
|
||||
import org.thingsboard.server.dao.TenantEntityDao;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
@ -32,7 +33,7 @@ import java.util.UUID;
|
||||
* The Interface AssetDao.
|
||||
*
|
||||
*/
|
||||
public interface AssetDao extends Dao<Asset> {
|
||||
public interface AssetDao extends Dao<Asset>, TenantEntityDao {
|
||||
|
||||
/**
|
||||
* Find asset info by id.
|
||||
@ -166,6 +167,4 @@ public interface AssetDao extends Dao<Asset> {
|
||||
*/
|
||||
ListenableFuture<List<EntitySubtype>> findTenantAssetTypesAsync(UUID tenantId);
|
||||
|
||||
Long countAssetsByTenantId(TenantId tenantId);
|
||||
|
||||
}
|
||||
|
||||
@ -330,12 +330,7 @@ public class BaseAssetService extends AbstractEntityService implements AssetServ
|
||||
DefaultTenantProfileConfiguration profileConfiguration =
|
||||
(DefaultTenantProfileConfiguration)tenantProfileCache.get(tenantId).getProfileData().getConfiguration();
|
||||
long maxAssets = profileConfiguration.getMaxAssets();
|
||||
if (maxAssets > 0) {
|
||||
long currentAssetsCount = assetDao.countAssetsByTenantId(tenantId);
|
||||
if (maxAssets >= currentAssetsCount) {
|
||||
throw new DataValidationException("Can't create assets more then " + maxAssets);
|
||||
}
|
||||
}
|
||||
validateNumberOfEntitiesPerTenant(tenantId, assetDao, maxAssets, EntityType.ASSET);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -20,6 +20,7 @@ import org.thingsboard.server.common.data.id.TenantId;
|
||||
import org.thingsboard.server.common.data.page.PageData;
|
||||
import org.thingsboard.server.common.data.page.PageLink;
|
||||
import org.thingsboard.server.dao.Dao;
|
||||
import org.thingsboard.server.dao.TenantEntityDao;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
@ -27,7 +28,7 @@ import java.util.UUID;
|
||||
/**
|
||||
* The Interface CustomerDao.
|
||||
*/
|
||||
public interface CustomerDao extends Dao<Customer> {
|
||||
public interface CustomerDao extends Dao<Customer>, TenantEntityDao {
|
||||
|
||||
/**
|
||||
* Save or update customer object
|
||||
|
||||
@ -21,13 +21,16 @@ import com.google.common.util.concurrent.ListenableFuture;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.thingsboard.server.common.data.Customer;
|
||||
import org.thingsboard.server.common.data.EntityType;
|
||||
import org.thingsboard.server.common.data.Tenant;
|
||||
import org.thingsboard.server.common.data.id.CustomerId;
|
||||
import org.thingsboard.server.common.data.id.TenantId;
|
||||
import org.thingsboard.server.common.data.page.PageData;
|
||||
import org.thingsboard.server.common.data.page.PageLink;
|
||||
import org.thingsboard.server.common.data.tenant.profile.DefaultTenantProfileConfiguration;
|
||||
import org.thingsboard.server.dao.asset.AssetService;
|
||||
import org.thingsboard.server.dao.dashboard.DashboardService;
|
||||
import org.thingsboard.server.dao.device.DeviceService;
|
||||
@ -38,6 +41,7 @@ import org.thingsboard.server.dao.exception.IncorrectParameterException;
|
||||
import org.thingsboard.server.dao.service.DataValidator;
|
||||
import org.thingsboard.server.dao.service.PaginatedRemover;
|
||||
import org.thingsboard.server.dao.service.Validator;
|
||||
import org.thingsboard.server.dao.tenant.TbTenantProfileCache;
|
||||
import org.thingsboard.server.dao.tenant.TenantDao;
|
||||
import org.thingsboard.server.dao.user.UserService;
|
||||
|
||||
@ -75,6 +79,10 @@ public class CustomerServiceImpl extends AbstractEntityService implements Custom
|
||||
@Autowired
|
||||
private DashboardService dashboardService;
|
||||
|
||||
@Autowired
|
||||
@Lazy
|
||||
private TbTenantProfileCache tenantProfileCache;
|
||||
|
||||
@Override
|
||||
public Customer findCustomerById(TenantId tenantId, CustomerId customerId) {
|
||||
log.trace("Executing findCustomerById [{}]", customerId);
|
||||
@ -162,6 +170,11 @@ public class CustomerServiceImpl extends AbstractEntityService implements Custom
|
||||
|
||||
@Override
|
||||
protected void validateCreate(TenantId tenantId, Customer customer) {
|
||||
DefaultTenantProfileConfiguration profileConfiguration =
|
||||
(DefaultTenantProfileConfiguration)tenantProfileCache.get(tenantId).getProfileData().getConfiguration();
|
||||
long maxCustomers = profileConfiguration.getMaxCustomers();
|
||||
|
||||
validateNumberOfEntitiesPerTenant(tenantId, customerDao, maxCustomers, EntityType.CUSTOMER);
|
||||
customerDao.findCustomersByTenantIdAndTitle(customer.getTenantId().getId(), customer.getTitle()).ifPresent(
|
||||
c -> {
|
||||
throw new DataValidationException("Customer with such title already exists!");
|
||||
|
||||
@ -18,11 +18,12 @@ package org.thingsboard.server.dao.dashboard;
|
||||
import org.thingsboard.server.common.data.Dashboard;
|
||||
import org.thingsboard.server.common.data.id.TenantId;
|
||||
import org.thingsboard.server.dao.Dao;
|
||||
import org.thingsboard.server.dao.TenantEntityDao;
|
||||
|
||||
/**
|
||||
* The Interface DashboardDao.
|
||||
*/
|
||||
public interface DashboardDao extends Dao<Dashboard> {
|
||||
public interface DashboardDao extends Dao<Dashboard>, TenantEntityDao {
|
||||
|
||||
/**
|
||||
* Save or update dashboard object
|
||||
@ -31,5 +32,4 @@ public interface DashboardDao extends Dao<Dashboard> {
|
||||
* @return saved dashboard object
|
||||
*/
|
||||
Dashboard save(TenantId tenantId, Dashboard dashboard);
|
||||
|
||||
}
|
||||
|
||||
@ -19,10 +19,12 @@ import com.google.common.util.concurrent.ListenableFuture;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.thingsboard.server.common.data.Customer;
|
||||
import org.thingsboard.server.common.data.Dashboard;
|
||||
import org.thingsboard.server.common.data.DashboardInfo;
|
||||
import org.thingsboard.server.common.data.EntityType;
|
||||
import org.thingsboard.server.common.data.Tenant;
|
||||
import org.thingsboard.server.common.data.id.CustomerId;
|
||||
import org.thingsboard.server.common.data.id.DashboardId;
|
||||
@ -31,12 +33,14 @@ import org.thingsboard.server.common.data.page.PageData;
|
||||
import org.thingsboard.server.common.data.page.PageLink;
|
||||
import org.thingsboard.server.common.data.relation.EntityRelation;
|
||||
import org.thingsboard.server.common.data.relation.RelationTypeGroup;
|
||||
import org.thingsboard.server.common.data.tenant.profile.DefaultTenantProfileConfiguration;
|
||||
import org.thingsboard.server.dao.customer.CustomerDao;
|
||||
import org.thingsboard.server.dao.entity.AbstractEntityService;
|
||||
import org.thingsboard.server.dao.exception.DataValidationException;
|
||||
import org.thingsboard.server.dao.service.DataValidator;
|
||||
import org.thingsboard.server.dao.service.PaginatedRemover;
|
||||
import org.thingsboard.server.dao.service.Validator;
|
||||
import org.thingsboard.server.dao.tenant.TbTenantProfileCache;
|
||||
import org.thingsboard.server.dao.tenant.TenantDao;
|
||||
|
||||
import java.util.concurrent.ExecutionException;
|
||||
@ -61,6 +65,10 @@ public class DashboardServiceImpl extends AbstractEntityService implements Dashb
|
||||
@Autowired
|
||||
private CustomerDao customerDao;
|
||||
|
||||
@Autowired
|
||||
@Lazy
|
||||
private TbTenantProfileCache tenantProfileCache;
|
||||
|
||||
@Override
|
||||
public Dashboard findDashboardById(TenantId tenantId, DashboardId dashboardId) {
|
||||
log.trace("Executing findDashboardById [{}]", dashboardId);
|
||||
@ -214,6 +222,14 @@ public class DashboardServiceImpl extends AbstractEntityService implements Dashb
|
||||
|
||||
private DataValidator<Dashboard> dashboardValidator =
|
||||
new DataValidator<Dashboard>() {
|
||||
@Override
|
||||
protected void validateCreate(TenantId tenantId, Dashboard data) {
|
||||
DefaultTenantProfileConfiguration profileConfiguration =
|
||||
(DefaultTenantProfileConfiguration)tenantProfileCache.get(tenantId).getProfileData().getConfiguration();
|
||||
long maxDashboards = profileConfiguration.getMaxDashboards();
|
||||
validateNumberOfEntitiesPerTenant(tenantId, dashboardDao, maxDashboards, EntityType.DASHBOARD);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void validateDataImpl(TenantId tenantId, Dashboard dashboard) {
|
||||
if (StringUtils.isEmpty(dashboard.getTitle())) {
|
||||
|
||||
@ -23,6 +23,7 @@ import org.thingsboard.server.common.data.id.TenantId;
|
||||
import org.thingsboard.server.common.data.page.PageData;
|
||||
import org.thingsboard.server.common.data.page.PageLink;
|
||||
import org.thingsboard.server.dao.Dao;
|
||||
import org.thingsboard.server.dao.TenantEntityDao;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
@ -32,7 +33,7 @@ import java.util.UUID;
|
||||
* The Interface DeviceDao.
|
||||
*
|
||||
*/
|
||||
public interface DeviceDao extends Dao<Device> {
|
||||
public interface DeviceDao extends Dao<Device>, TenantEntityDao {
|
||||
|
||||
/**
|
||||
* Find device info by id.
|
||||
@ -203,8 +204,6 @@ public interface DeviceDao extends Dao<Device> {
|
||||
*/
|
||||
ListenableFuture<Device> findDeviceByTenantIdAndIdAsync(TenantId tenantId, UUID id);
|
||||
|
||||
Long countDevicesByTenantId(TenantId tenantId);
|
||||
|
||||
Long countDevicesByDeviceProfileId(TenantId tenantId, UUID deviceProfileId);
|
||||
|
||||
/**
|
||||
|
||||
@ -530,12 +530,7 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe
|
||||
DefaultTenantProfileConfiguration profileConfiguration =
|
||||
(DefaultTenantProfileConfiguration)tenantProfileCache.get(tenantId).getProfileData().getConfiguration();
|
||||
long maxDevices = profileConfiguration.getMaxDevices();
|
||||
if (maxDevices > 0) {
|
||||
long currentDevicesCount = deviceDao.countDevicesByTenantId(tenantId);
|
||||
if (maxDevices >= currentDevicesCount) {
|
||||
throw new DataValidationException("Can't create devices more then " + maxDevices);
|
||||
}
|
||||
}
|
||||
validateNumberOfEntitiesPerTenant(tenantId, deviceDao, maxDevices, EntityType.DEVICE);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -37,12 +37,11 @@ public abstract class AbstractEntityService {
|
||||
|
||||
protected Optional<ConstraintViolationException> extractConstraintViolationException(Exception t) {
|
||||
if (t instanceof ConstraintViolationException) {
|
||||
return Optional.of ((ConstraintViolationException) t);
|
||||
return Optional.of((ConstraintViolationException) t);
|
||||
} else if (t.getCause() instanceof ConstraintViolationException) {
|
||||
return Optional.of ((ConstraintViolationException) (t.getCause()));
|
||||
return Optional.of((ConstraintViolationException) (t.getCause()));
|
||||
} else {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -24,6 +24,7 @@ import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.hibernate.exception.ConstraintViolationException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.thingsboard.server.common.data.BaseData;
|
||||
import org.thingsboard.server.common.data.EntityType;
|
||||
@ -44,11 +45,13 @@ import org.thingsboard.server.common.data.rule.RuleChainData;
|
||||
import org.thingsboard.server.common.data.rule.RuleChainImportResult;
|
||||
import org.thingsboard.server.common.data.rule.RuleChainMetaData;
|
||||
import org.thingsboard.server.common.data.rule.RuleNode;
|
||||
import org.thingsboard.server.common.data.tenant.profile.DefaultTenantProfileConfiguration;
|
||||
import org.thingsboard.server.dao.entity.AbstractEntityService;
|
||||
import org.thingsboard.server.dao.exception.DataValidationException;
|
||||
import org.thingsboard.server.dao.service.DataValidator;
|
||||
import org.thingsboard.server.dao.service.PaginatedRemover;
|
||||
import org.thingsboard.server.dao.service.Validator;
|
||||
import org.thingsboard.server.dao.tenant.TbTenantProfileCache;
|
||||
import org.thingsboard.server.dao.tenant.TenantDao;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@ -81,6 +84,10 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
|
||||
@Autowired
|
||||
private TenantDao tenantDao;
|
||||
|
||||
@Autowired
|
||||
@Lazy
|
||||
private TbTenantProfileCache tenantProfileCache;
|
||||
|
||||
@Override
|
||||
public RuleChain saveRuleChain(RuleChain ruleChain) {
|
||||
ruleChainValidator.validate(ruleChain, RuleChain::getTenantId);
|
||||
@ -580,6 +587,14 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
|
||||
|
||||
private DataValidator<RuleChain> ruleChainValidator =
|
||||
new DataValidator<RuleChain>() {
|
||||
@Override
|
||||
protected void validateCreate(TenantId tenantId, RuleChain data) {
|
||||
DefaultTenantProfileConfiguration profileConfiguration =
|
||||
(DefaultTenantProfileConfiguration)tenantProfileCache.get(tenantId).getProfileData().getConfiguration();
|
||||
long maxRuleChains = profileConfiguration.getMaxRuleChains();
|
||||
validateNumberOfEntitiesPerTenant(tenantId, ruleChainDao, maxRuleChains, EntityType.RULE_CHAIN);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void validateDataImpl(TenantId tenantId, RuleChain ruleChain) {
|
||||
if (StringUtils.isEmpty(ruleChain.getName())) {
|
||||
|
||||
@ -19,13 +19,14 @@ import org.thingsboard.server.common.data.page.PageData;
|
||||
import org.thingsboard.server.common.data.page.PageLink;
|
||||
import org.thingsboard.server.common.data.rule.RuleChain;
|
||||
import org.thingsboard.server.dao.Dao;
|
||||
import org.thingsboard.server.dao.TenantEntityDao;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Created by igor on 3/12/18.
|
||||
*/
|
||||
public interface RuleChainDao extends Dao<RuleChain> {
|
||||
public interface RuleChainDao extends Dao<RuleChain>, TenantEntityDao {
|
||||
|
||||
/**
|
||||
* Find rule chains by tenantId and page link.
|
||||
@ -35,5 +36,4 @@ public interface RuleChainDao extends Dao<RuleChain> {
|
||||
* @return the list of rule chain objects
|
||||
*/
|
||||
PageData<RuleChain> findRuleChainsByTenantId(UUID tenantId, PageLink pageLink);
|
||||
|
||||
}
|
||||
|
||||
@ -18,7 +18,9 @@ package org.thingsboard.server.dao.service;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.thingsboard.server.common.data.BaseData;
|
||||
import org.thingsboard.server.common.data.EntityType;
|
||||
import org.thingsboard.server.common.data.id.TenantId;
|
||||
import org.thingsboard.server.dao.TenantEntityDao;
|
||||
import org.thingsboard.server.dao.exception.DataValidationException;
|
||||
|
||||
import java.util.HashSet;
|
||||
@ -79,6 +81,19 @@ public abstract class DataValidator<D extends BaseData<?>> {
|
||||
return emailMatcher.matches();
|
||||
}
|
||||
|
||||
protected void validateNumberOfEntitiesPerTenant(TenantId tenantId,
|
||||
TenantEntityDao tenantEntityDao,
|
||||
long maxEntities,
|
||||
EntityType entityType) {
|
||||
if (maxEntities > 0) {
|
||||
long currentEntitiesCount = tenantEntityDao.countByTenantId(tenantId);
|
||||
if (currentEntitiesCount >= maxEntities) {
|
||||
throw new DataValidationException(String.format("Can't create more then %d %ss!",
|
||||
maxEntities, entityType.name().toLowerCase().replaceAll("_", " ")));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected static void validateJsonStructure(JsonNode expectedNode, JsonNode actualNode) {
|
||||
Set<String> expectedFields = new HashSet<>();
|
||||
Iterator<String> fieldsIterator = expectedNode.fieldNames();
|
||||
|
||||
@ -178,8 +178,7 @@ public class JpaAssetDao extends JpaAbstractSearchTextDao<AssetEntity, Asset> im
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long countAssetsByTenantId(TenantId tenantId) {
|
||||
public Long countByTenantId(TenantId tenantId) {
|
||||
return assetRepository.countByTenantId(tenantId.getId());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -37,4 +37,5 @@ public interface CustomerRepository extends PagingAndSortingRepository<CustomerE
|
||||
|
||||
CustomerEntity findByTenantIdAndTitle(UUID tenantId, String title);
|
||||
|
||||
Long countByTenantId(UUID tenantId);
|
||||
}
|
||||
|
||||
@ -19,6 +19,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.thingsboard.server.common.data.Customer;
|
||||
import org.thingsboard.server.common.data.id.TenantId;
|
||||
import org.thingsboard.server.common.data.page.PageData;
|
||||
import org.thingsboard.server.common.data.page.PageLink;
|
||||
import org.thingsboard.server.dao.DaoUtil;
|
||||
@ -62,4 +63,9 @@ public class JpaCustomerDao extends JpaAbstractSearchTextDao<CustomerEntity, Cus
|
||||
Customer customer = DaoUtil.getData(customerRepository.findByTenantIdAndTitle(tenantId, title));
|
||||
return Optional.ofNullable(customer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long countByTenantId(TenantId tenantId) {
|
||||
return customerRepository.countByTenantId(tenantId.getId());
|
||||
}
|
||||
}
|
||||
|
||||
@ -24,4 +24,6 @@ import java.util.UUID;
|
||||
* Created by Valerii Sosliuk on 5/6/2017.
|
||||
*/
|
||||
public interface DashboardRepository extends CrudRepository<DashboardEntity, UUID> {
|
||||
|
||||
Long countByTenantId(UUID tenantId);
|
||||
}
|
||||
|
||||
@ -19,6 +19,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.thingsboard.server.common.data.Dashboard;
|
||||
import org.thingsboard.server.common.data.id.TenantId;
|
||||
import org.thingsboard.server.dao.dashboard.DashboardDao;
|
||||
import org.thingsboard.server.dao.model.sql.DashboardEntity;
|
||||
import org.thingsboard.server.dao.sql.JpaAbstractSearchTextDao;
|
||||
@ -43,4 +44,9 @@ public class JpaDashboardDao extends JpaAbstractSearchTextDao<DashboardEntity, D
|
||||
protected CrudRepository<DashboardEntity, UUID> getCrudRepository() {
|
||||
return dashboardRepository;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long countByTenantId(TenantId tenantId) {
|
||||
return dashboardRepository.countByTenantId(tenantId.getId());
|
||||
}
|
||||
}
|
||||
|
||||
@ -50,9 +50,9 @@ public interface DeviceRepository extends PagingAndSortingRepository<DeviceEntit
|
||||
"AND d.deviceProfileId = :profileId " +
|
||||
"AND LOWER(d.searchText) LIKE LOWER(CONCAT(:searchText, '%'))")
|
||||
Page<DeviceEntity> findByTenantIdAndProfileId(@Param("tenantId") UUID tenantId,
|
||||
@Param("profileId") UUID profileId,
|
||||
@Param("searchText") String searchText,
|
||||
Pageable pageable);
|
||||
@Param("profileId") UUID profileId,
|
||||
@Param("searchText") String searchText,
|
||||
Pageable pageable);
|
||||
|
||||
@Query("SELECT new org.thingsboard.server.dao.model.sql.DeviceInfoEntity(d, c.title, c.additionalInfo, p.name) " +
|
||||
"FROM DeviceEntity d " +
|
||||
@ -62,9 +62,9 @@ public interface DeviceRepository extends PagingAndSortingRepository<DeviceEntit
|
||||
"AND d.customerId = :customerId " +
|
||||
"AND LOWER(d.searchText) LIKE LOWER(CONCAT(:searchText, '%'))")
|
||||
Page<DeviceInfoEntity> findDeviceInfosByTenantIdAndCustomerId(@Param("tenantId") UUID tenantId,
|
||||
@Param("customerId") UUID customerId,
|
||||
@Param("searchText") String searchText,
|
||||
Pageable pageable);
|
||||
@Param("customerId") UUID customerId,
|
||||
@Param("searchText") String searchText,
|
||||
Pageable pageable);
|
||||
|
||||
@Query("SELECT d FROM DeviceEntity d WHERE d.tenantId = :tenantId")
|
||||
Page<DeviceEntity> findByTenantId(@Param("tenantId") UUID tenantId,
|
||||
@ -102,9 +102,9 @@ public interface DeviceRepository extends PagingAndSortingRepository<DeviceEntit
|
||||
"AND d.type = :type " +
|
||||
"AND LOWER(d.searchText) LIKE LOWER(CONCAT(:textSearch, '%'))")
|
||||
Page<DeviceInfoEntity> findDeviceInfosByTenantIdAndType(@Param("tenantId") UUID tenantId,
|
||||
@Param("type") String type,
|
||||
@Param("textSearch") String textSearch,
|
||||
Pageable pageable);
|
||||
@Param("type") String type,
|
||||
@Param("textSearch") String textSearch,
|
||||
Pageable pageable);
|
||||
|
||||
@Query("SELECT new org.thingsboard.server.dao.model.sql.DeviceInfoEntity(d, c.title, c.additionalInfo, p.name) " +
|
||||
"FROM DeviceEntity d " +
|
||||
@ -137,10 +137,10 @@ public interface DeviceRepository extends PagingAndSortingRepository<DeviceEntit
|
||||
"AND d.type = :type " +
|
||||
"AND LOWER(d.searchText) LIKE LOWER(CONCAT(:textSearch, '%'))")
|
||||
Page<DeviceInfoEntity> findDeviceInfosByTenantIdAndCustomerIdAndType(@Param("tenantId") UUID tenantId,
|
||||
@Param("customerId") UUID customerId,
|
||||
@Param("type") String type,
|
||||
@Param("textSearch") String textSearch,
|
||||
Pageable pageable);
|
||||
@Param("customerId") UUID customerId,
|
||||
@Param("type") String type,
|
||||
@Param("textSearch") String textSearch,
|
||||
Pageable pageable);
|
||||
|
||||
@Query("SELECT new org.thingsboard.server.dao.model.sql.DeviceInfoEntity(d, c.title, c.additionalInfo, p.name) " +
|
||||
"FROM DeviceEntity d " +
|
||||
|
||||
@ -220,7 +220,7 @@ public class JpaDeviceDao extends JpaAbstractSearchTextDao<DeviceEntity, Device>
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long countDevicesByTenantId(TenantId tenantId) {
|
||||
public Long countByTenantId(TenantId tenantId) {
|
||||
return deviceRepository.countByTenantId(tenantId.getId());
|
||||
}
|
||||
|
||||
|
||||
@ -19,6 +19,7 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.thingsboard.server.common.data.id.TenantId;
|
||||
import org.thingsboard.server.common.data.page.PageData;
|
||||
import org.thingsboard.server.common.data.page.PageLink;
|
||||
import org.thingsboard.server.common.data.rule.RuleChain;
|
||||
@ -56,4 +57,8 @@ public class JpaRuleChainDao extends JpaAbstractSearchTextDao<RuleChainEntity, R
|
||||
DaoUtil.toPageable(pageLink)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long countByTenantId(TenantId tenantId) {
|
||||
return ruleChainRepository.countByTenantId(tenantId.getId());
|
||||
}
|
||||
}
|
||||
|
||||
@ -32,4 +32,5 @@ public interface RuleChainRepository extends PagingAndSortingRepository<RuleChai
|
||||
@Param("searchText") String searchText,
|
||||
Pageable pageable);
|
||||
|
||||
Long countByTenantId(UUID tenantId);
|
||||
}
|
||||
|
||||
@ -91,4 +91,9 @@ public class JpaUserDao extends JpaAbstractSearchTextDao<UserEntity, User> imple
|
||||
DaoUtil.toPageable(pageLink)));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long countByTenantId(TenantId tenantId) {
|
||||
return userRepository.countByTenantId(tenantId.getId());
|
||||
}
|
||||
}
|
||||
|
||||
@ -47,4 +47,5 @@ public interface UserRepository extends PagingAndSortingRepository<UserEntity, U
|
||||
@Param("searchText") String searchText,
|
||||
Pageable pageable);
|
||||
|
||||
Long countByTenantId(UUID tenantId);
|
||||
}
|
||||
|
||||
@ -20,10 +20,11 @@ import org.thingsboard.server.common.data.id.TenantId;
|
||||
import org.thingsboard.server.common.data.page.PageData;
|
||||
import org.thingsboard.server.common.data.page.PageLink;
|
||||
import org.thingsboard.server.dao.Dao;
|
||||
import org.thingsboard.server.dao.TenantEntityDao;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public interface UserDao extends Dao<User> {
|
||||
public interface UserDao extends Dao<User>, TenantEntityDao {
|
||||
|
||||
/**
|
||||
* Save or update user object
|
||||
@ -68,5 +69,4 @@ public interface UserDao extends Dao<User> {
|
||||
* @return the list of user entities
|
||||
*/
|
||||
PageData<User> findCustomerUsers(UUID tenantId, UUID customerId, PageLink pageLink);
|
||||
|
||||
}
|
||||
|
||||
@ -24,8 +24,10 @@ import org.apache.commons.lang3.RandomStringUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.thingsboard.server.common.data.Customer;
|
||||
import org.thingsboard.server.common.data.EntityType;
|
||||
import org.thingsboard.server.common.data.Tenant;
|
||||
import org.thingsboard.server.common.data.User;
|
||||
import org.thingsboard.server.common.data.id.CustomerId;
|
||||
@ -36,6 +38,7 @@ import org.thingsboard.server.common.data.page.PageData;
|
||||
import org.thingsboard.server.common.data.page.PageLink;
|
||||
import org.thingsboard.server.common.data.security.Authority;
|
||||
import org.thingsboard.server.common.data.security.UserCredentials;
|
||||
import org.thingsboard.server.common.data.tenant.profile.DefaultTenantProfileConfiguration;
|
||||
import org.thingsboard.server.dao.customer.CustomerDao;
|
||||
import org.thingsboard.server.dao.entity.AbstractEntityService;
|
||||
import org.thingsboard.server.dao.exception.DataValidationException;
|
||||
@ -43,6 +46,7 @@ import org.thingsboard.server.dao.exception.IncorrectParameterException;
|
||||
import org.thingsboard.server.dao.model.ModelConstants;
|
||||
import org.thingsboard.server.dao.service.DataValidator;
|
||||
import org.thingsboard.server.dao.service.PaginatedRemover;
|
||||
import org.thingsboard.server.dao.tenant.TbTenantProfileCache;
|
||||
import org.thingsboard.server.dao.tenant.TenantDao;
|
||||
|
||||
import java.util.HashMap;
|
||||
@ -84,6 +88,10 @@ public class UserServiceImpl extends AbstractEntityService implements UserServic
|
||||
@Autowired
|
||||
private CustomerDao customerDao;
|
||||
|
||||
@Autowired
|
||||
@Lazy
|
||||
private TbTenantProfileCache tenantProfileCache;
|
||||
|
||||
@Override
|
||||
public User findUserByEmail(TenantId tenantId, String email) {
|
||||
log.trace("Executing findUserByEmail [{}]", email);
|
||||
@ -364,6 +372,16 @@ public class UserServiceImpl extends AbstractEntityService implements UserServic
|
||||
|
||||
private DataValidator<User> userValidator =
|
||||
new DataValidator<User>() {
|
||||
@Override
|
||||
protected void validateCreate(TenantId tenantId, User user) {
|
||||
if (!user.getTenantId().getId().equals(ModelConstants.NULL_UUID)) {
|
||||
DefaultTenantProfileConfiguration profileConfiguration =
|
||||
(DefaultTenantProfileConfiguration) tenantProfileCache.get(tenantId).getProfileData().getConfiguration();
|
||||
long maxUsers = profileConfiguration.getMaxUsers();
|
||||
validateNumberOfEntitiesPerTenant(tenantId, userDao, maxUsers, EntityType.USER);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void validateDataImpl(TenantId requestTenantId, User user) {
|
||||
if (StringUtils.isEmpty(user.getEmail())) {
|
||||
|
||||
32
pom.xml
32
pom.xml
@ -36,12 +36,11 @@
|
||||
<pkg.implementationTitle>${project.name}</pkg.implementationTitle>
|
||||
<pkg.unixLogFolder>/var/log/${pkg.name}</pkg.unixLogFolder>
|
||||
<pkg.installFolder>/usr/share/${pkg.name}</pkg.installFolder>
|
||||
<spring-boot.version>2.2.6.RELEASE</spring-boot.version>
|
||||
<spring-oauth2.version>2.1.2.RELEASE</spring-oauth2.version>
|
||||
<spring.version>5.2.6.RELEASE</spring.version>
|
||||
<spring-security.version>5.2.3.RELEASE</spring-security.version>
|
||||
<spring-data-redis.version>2.2.4.RELEASE</spring-data-redis.version>
|
||||
<jedis.version>3.1.0</jedis.version>
|
||||
<spring-boot.version>2.3.5.RELEASE</spring-boot.version>
|
||||
<spring.version>5.2.10.RELEASE</spring.version>
|
||||
<spring-security.version>5.4.1</spring-security.version>
|
||||
<spring-data-redis.version>2.4.1</spring-data-redis.version>
|
||||
<jedis.version>3.3.0</jedis.version>
|
||||
<jjwt.version>0.7.0</jjwt.version>
|
||||
<json-path.version>2.2.0</json-path.version>
|
||||
<junit.version>4.12</junit.version>
|
||||
@ -52,15 +51,16 @@
|
||||
<cassandra.version>4.6.0</cassandra.version>
|
||||
<metrics.version>4.0.5</metrics.version>
|
||||
<cassandra-unit.version>4.3.1.0</cassandra-unit.version>
|
||||
<cassandra-all.version>3.11.9</cassandra-all.version>
|
||||
<takari-cpsuite.version>1.2.7</takari-cpsuite.version>
|
||||
<guava.version>28.2-jre</guava.version>
|
||||
<caffeine.version>2.6.1</caffeine.version>
|
||||
<commons-lang3.version>3.4</commons-lang3.version>
|
||||
<commons-io.version>2.5</commons-io.version>
|
||||
<commons-csv.version>1.4</commons-csv.version>
|
||||
<jackson.version>2.10.2</jackson.version>
|
||||
<jackson-annotations.version>2.10.2</jackson-annotations.version>
|
||||
<jackson-core.version>2.10.2</jackson-core.version>
|
||||
<jackson.version>2.11.3</jackson.version>
|
||||
<jackson-annotations.version>2.11.3</jackson-annotations.version>
|
||||
<jackson-core.version>2.11.3</jackson-core.version>
|
||||
<json-schema-validator.version>2.2.6</json-schema-validator.version>
|
||||
<californium.version>1.0.2</californium.version>
|
||||
<gson.version>2.6.2</gson.version>
|
||||
@ -72,7 +72,7 @@
|
||||
<grpc.version>1.22.1</grpc.version>
|
||||
<lombok.version>1.16.18</lombok.version>
|
||||
<paho.client.version>1.2.4</paho.client.version>
|
||||
<netty.version>4.1.49.Final</netty.version>
|
||||
<netty.version>4.1.53.Final</netty.version>
|
||||
<os-maven-plugin.version>1.5.0</os-maven-plugin.version>
|
||||
<rabbitmq.version>4.8.0</rabbitmq.version>
|
||||
<surfire.version>2.19.1</surfire.version>
|
||||
@ -96,7 +96,7 @@
|
||||
<bucket4j.version>4.1.1</bucket4j.version>
|
||||
<fst.version>2.57</fst.version>
|
||||
<antlr.version>2.7.7</antlr.version>
|
||||
<snakeyaml.version>1.25</snakeyaml.version>
|
||||
<snakeyaml.version>1.27</snakeyaml.version>
|
||||
<amazonaws.sqs.version>1.11.747</amazonaws.sqs.version>
|
||||
<pubsub.client.version>1.105.0</pubsub.client.version>
|
||||
<azure-servicebus.version>3.2.0</azure-servicebus.version>
|
||||
@ -872,11 +872,6 @@
|
||||
<artifactId>spring-boot-starter-security</artifactId>
|
||||
<version>${spring-boot.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-oauth2</artifactId>
|
||||
<version>${spring-oauth2.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-oauth2-client</artifactId>
|
||||
@ -1200,6 +1195,11 @@
|
||||
<version>${cassandra-unit.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.cassandra</groupId>
|
||||
<artifactId>cassandra-all</artifactId>
|
||||
<version>${cassandra-all.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
|
||||
@ -120,6 +120,11 @@
|
||||
<groupId>org.locationtech.jts</groupId>
|
||||
<artifactId>jts-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.sun.mail</groupId>
|
||||
<artifactId>javax.mail</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
|
||||
@ -54,7 +54,6 @@
|
||||
<dependency>
|
||||
<groupId>org.apache.cassandra</groupId>
|
||||
<artifactId>cassandra-all</artifactId>
|
||||
<version>3.11.6</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.datastax.oss</groupId>
|
||||
|
||||
@ -40,6 +40,54 @@
|
||||
{{ 'tenant-profile.maximum-assets-range' | translate}}
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
<mat-form-field class="mat-block">
|
||||
<mat-label translate>tenant-profile.maximum-customers</mat-label>
|
||||
<input matInput required min="0" step="1"
|
||||
formControlName="maxCustomers"
|
||||
type="number">
|
||||
<mat-error *ngIf="defaultTenantProfileConfigurationFormGroup.get('maxCustomers').hasError('required')">
|
||||
{{ 'tenant-profile.maximum-customers-required' | translate}}
|
||||
</mat-error>
|
||||
<mat-error *ngIf="defaultTenantProfileConfigurationFormGroup.get('maxCustomers').hasError('min')">
|
||||
{{ 'tenant-profile.maximum-customers-range' | translate}}
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
<mat-form-field class="mat-block">
|
||||
<mat-label translate>tenant-profile.maximum-users</mat-label>
|
||||
<input matInput required min="0" step="1"
|
||||
formControlName="maxUsers"
|
||||
type="number">
|
||||
<mat-error *ngIf="defaultTenantProfileConfigurationFormGroup.get('maxUsers').hasError('required')">
|
||||
{{ 'tenant-profile.maximum-users-required' | translate}}
|
||||
</mat-error>
|
||||
<mat-error *ngIf="defaultTenantProfileConfigurationFormGroup.get('maxUsers').hasError('min')">
|
||||
{{ 'tenant-profile.maximum-users-range' | translate}}
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
<mat-form-field class="mat-block">
|
||||
<mat-label translate>tenant-profile.maximum-dashboards</mat-label>
|
||||
<input matInput required min="0" step="1"
|
||||
formControlName="maxDashboards"
|
||||
type="number">
|
||||
<mat-error *ngIf="defaultTenantProfileConfigurationFormGroup.get('maxDashboards').hasError('required')">
|
||||
{{ 'tenant-profile.maximum-dashboards-required' | translate}}
|
||||
</mat-error>
|
||||
<mat-error *ngIf="defaultTenantProfileConfigurationFormGroup.get('maxDashboards').hasError('min')">
|
||||
{{ 'tenant-profile.maximum-dashboards-range' | translate}}
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
<mat-form-field class="mat-block">
|
||||
<mat-label translate>tenant-profile.maximum-rule-chains</mat-label>
|
||||
<input matInput required min="0" step="1"
|
||||
formControlName="maxRuleChains"
|
||||
type="number">
|
||||
<mat-error *ngIf="defaultTenantProfileConfigurationFormGroup.get('maxRuleChains').hasError('required')">
|
||||
{{ 'tenant-profile.maximum-rule-chains-required' | translate}}
|
||||
</mat-error>
|
||||
<mat-error *ngIf="defaultTenantProfileConfigurationFormGroup.get('maxRuleChains').hasError('min')">
|
||||
{{ 'tenant-profile.maximum-rule-chains-range' | translate}}
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
<mat-form-field class="mat-block">
|
||||
<mat-label translate>tenant-profile.max-transport-messages</mat-label>
|
||||
<input matInput required min="0" step="1"
|
||||
|
||||
@ -55,6 +55,10 @@ export class DefaultTenantProfileConfigurationComponent implements ControlValueA
|
||||
this.defaultTenantProfileConfigurationFormGroup = this.fb.group({
|
||||
maxDevices: [null, [Validators.required, Validators.min(0)]],
|
||||
maxAssets: [null, [Validators.required, Validators.min(0)]],
|
||||
maxCustomers: [null, [Validators.required, Validators.min(0)]],
|
||||
maxUsers: [null, [Validators.required, Validators.min(0)]],
|
||||
maxDashboards: [null, [Validators.required, Validators.min(0)]],
|
||||
maxRuleChains: [null, [Validators.required, Validators.min(0)]],
|
||||
transportTenantMsgRateLimit: [null, []],
|
||||
transportTenantTelemetryMsgRateLimit: [null, []],
|
||||
transportTenantTelemetryDataPointsRateLimit: [null, []],
|
||||
|
||||
@ -487,7 +487,8 @@ export default abstract class LeafletMap {
|
||||
}
|
||||
|
||||
const mapBounds = this.map.getBounds();
|
||||
if (bounds.isValid() && (!this.bounds || !this.bounds.isValid() || !this.bounds.equals(bounds) && !mapBounds.contains(bounds))) {
|
||||
if (bounds.isValid() && (!this.bounds || !this.bounds.isValid() || !this.bounds.equals(bounds)
|
||||
&& this.options.fitMapBounds ? !mapBounds.contains(bounds) : false)) {
|
||||
this.bounds = bounds;
|
||||
this.fitBounds(bounds);
|
||||
}
|
||||
|
||||
@ -20,6 +20,7 @@ import { EntityType } from '@shared/models/entity-type.models';
|
||||
import tinycolor from 'tinycolor2';
|
||||
|
||||
export const DEFAULT_MAP_PAGE_SIZE = 16384;
|
||||
export const DEFAULT_ZOOM_LEVEL = 8;
|
||||
|
||||
export type GenericFunction = (data: FormattedData, dsData: FormattedData[], dsIndex: number) => string;
|
||||
export type MarkerImageFunction = (data: FormattedData, dsData: FormattedData[], dsIndex: number) => string;
|
||||
@ -229,7 +230,6 @@ export const defaultSettings: any = {
|
||||
strokeWeight: 2,
|
||||
strokeOpacity: 1.0,
|
||||
initCallback: () => { },
|
||||
defaultZoomLevel: 8,
|
||||
disableScrollZooming: false,
|
||||
minZoomLevel: 16,
|
||||
credentials: '',
|
||||
|
||||
@ -17,7 +17,7 @@
|
||||
|
||||
import L from 'leaflet';
|
||||
import LeafletMap from '../leaflet-map';
|
||||
import { UnitedMapSettings } from '../map-models';
|
||||
import { DEFAULT_ZOOM_LEVEL, UnitedMapSettings } from '../map-models';
|
||||
import 'leaflet.gridlayer.googlemutant';
|
||||
import { ResourcesService } from '@core/services/resources.service';
|
||||
import { WidgetContext } from '@home/models/widget-component.models';
|
||||
@ -39,7 +39,7 @@ export class GoogleMap extends LeafletMap {
|
||||
const map = L.map($container, {
|
||||
attributionControl: false,
|
||||
editable: !!options.editablePolygon
|
||||
}).setView(options?.defaultCenterPosition, options?.defaultZoomLevel);
|
||||
}).setView(options?.defaultCenterPosition, options?.defaultZoomLevel || DEFAULT_ZOOM_LEVEL);
|
||||
(L.gridLayer as any).googleMutant({
|
||||
type: options?.gmDefaultMapType || 'roadmap'
|
||||
}).addTo(map);
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
|
||||
import L from 'leaflet';
|
||||
import LeafletMap from '../leaflet-map';
|
||||
import { UnitedMapSettings } from '../map-models';
|
||||
import { DEFAULT_ZOOM_LEVEL, UnitedMapSettings } from '../map-models';
|
||||
import { WidgetContext } from '@home/models/widget-component.models';
|
||||
|
||||
export class HEREMap extends LeafletMap {
|
||||
@ -24,7 +24,7 @@ export class HEREMap extends LeafletMap {
|
||||
super(ctx, $container, options);
|
||||
const map = L.map($container, {
|
||||
editable: !!options.editablePolygon
|
||||
}).setView(options?.defaultCenterPosition, options?.defaultZoomLevel);
|
||||
}).setView(options?.defaultCenterPosition, options?.defaultZoomLevel || DEFAULT_ZOOM_LEVEL);
|
||||
const tileLayer = (L.tileLayer as any).provider(options.mapProviderHere || 'HERE.normalDay', options.credentials);
|
||||
tileLayer.addTo(map);
|
||||
super.initSettings(options);
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
|
||||
import L from 'leaflet';
|
||||
import LeafletMap from '../leaflet-map';
|
||||
import { UnitedMapSettings } from '../map-models';
|
||||
import { DEFAULT_ZOOM_LEVEL, UnitedMapSettings } from '../map-models';
|
||||
import { WidgetContext } from '@home/models/widget-component.models';
|
||||
|
||||
export class OpenStreetMap extends LeafletMap {
|
||||
@ -24,7 +24,7 @@ export class OpenStreetMap extends LeafletMap {
|
||||
super(ctx, $container, options);
|
||||
const map = L.map($container, {
|
||||
editable: !!options.editablePolygon
|
||||
}).setView(options?.defaultCenterPosition, options?.defaultZoomLevel);
|
||||
}).setView(options?.defaultCenterPosition, options?.defaultZoomLevel || DEFAULT_ZOOM_LEVEL);
|
||||
let tileLayer;
|
||||
if (options.useCustomProvider) {
|
||||
tileLayer = L.tileLayer(options.customProviderTileUrl);
|
||||
|
||||
@ -17,7 +17,7 @@
|
||||
|
||||
import L from 'leaflet';
|
||||
import LeafletMap from '../leaflet-map';
|
||||
import { UnitedMapSettings } from '../map-models';
|
||||
import { DEFAULT_ZOOM_LEVEL, UnitedMapSettings } from '../map-models';
|
||||
import { WidgetContext } from '@home/models/widget-component.models';
|
||||
|
||||
export class TencentMap extends LeafletMap {
|
||||
@ -26,7 +26,7 @@ export class TencentMap extends LeafletMap {
|
||||
const txUrl = 'http://rt{s}.map.gtimg.com/realtimerender?z={z}&x={x}&y={y}&type=vector&style=0';
|
||||
const map = L.map($container, {
|
||||
editable: !!options.editablePolygon
|
||||
}).setView(options?.defaultCenterPosition, options?.defaultZoomLevel);
|
||||
}).setView(options?.defaultCenterPosition, options?.defaultZoomLevel || DEFAULT_ZOOM_LEVEL);
|
||||
const txLayer = L.tileLayer(txUrl, {
|
||||
subdomains: '0123',
|
||||
tms: true,
|
||||
|
||||
@ -56,6 +56,12 @@ export const customerHref = '<a href="https://github.com/thingsboard/thingsboard
|
||||
|
||||
export const attributeDataHref = '<a href="https://github.com/thingsboard/thingsboard/blob/13e6b10b7ab830e64d31b99614a9d95a1a25928a/ui-ngx/src/app/shared/models/telemetry/telemetry.models.ts#L76">Attribute Data</a>';
|
||||
|
||||
export const timeseriesDataHref = '<a href="https://github.com/thingsboard/thingsboard/blob/627c0577b08452308f925cecb3860e35292c649e/ui-ngx/src/app/shared/models/telemetry/telemetry.models.ts#L91">Timeseries Data</a>';
|
||||
|
||||
export const aggregationTypeHref = '<a href="https://github.com/thingsboard/thingsboard/blob/a8ea887eacf7729e603ace13ce2d7d89dae82931/ui-ngx/src/app/shared/models/time/time.models.ts#L54">Aggregation Type</a>';
|
||||
|
||||
export const dataSortOrderHref = '<a href="https://github.com/thingsboard/thingsboard/blob/627c0577b08452308f925cecb3860e35292c649e/ui-ngx/src/app/shared/models/telemetry/telemetry.models.ts#L95">Data Sort Order</a>';
|
||||
|
||||
export const userHref = '<a href="https://github.com/thingsboard/thingsboard/blob/13e6b10b7ab830e64d31b99614a9d95a1a25928a/ui-ngx/src/app/shared/models/user.model.ts#L23">User</a>';
|
||||
|
||||
export const entityDataHref = '<a href="https://github.com/thingsboard/thingsboard/blob/master/ui-ngx/src/app/shared/models/query/query.models.ts#L567">Entity data</a>';
|
||||
@ -1080,6 +1086,23 @@ export const serviceCompletions: TbEditorCompletions = {
|
||||
],
|
||||
return: observableReturnTypeVariable('any')
|
||||
},
|
||||
getEntityTimeseries: {
|
||||
description: 'Get entity timeseries',
|
||||
meta: 'function',
|
||||
args: [
|
||||
{name: 'entityId', type: entityIdHref, description: 'Id of the entity'},
|
||||
{name: 'keys', type: `Array<string>`, description: 'Array of the keys'},
|
||||
{name: 'startTs', type: 'number', description: 'Start time in milliseconds'},
|
||||
{name: 'endTs', type: 'number', description: 'End time in milliseconds'},
|
||||
{name: 'limit', type: 'number', description: 'Limit of values to receive for each key'},
|
||||
{name: 'agg', type: aggregationTypeHref, description: 'Aggregation type'},
|
||||
{name: 'interval', type: 'number', description: 'Aggregation interval'},
|
||||
{name: 'orderBy', type: dataSortOrderHref, description: 'Data order by time'},
|
||||
{name: 'useStrictDataTypes', type: 'boolean', description: 'If "false" all values will be returned as strings'},
|
||||
requestConfigArg
|
||||
],
|
||||
return: observableReturnTypeVariable(timeseriesDataHref)
|
||||
},
|
||||
}
|
||||
},
|
||||
entityService: {
|
||||
|
||||
@ -26,6 +26,10 @@ export enum TenantProfileType {
|
||||
export interface DefaultTenantProfileConfiguration {
|
||||
maxDevices: number;
|
||||
maxAssets: number;
|
||||
maxCustomers: number;
|
||||
maxUsers: number;
|
||||
maxDashboards: number;
|
||||
maxRuleChains: number;
|
||||
|
||||
transportTenantMsgRateLimit?: string;
|
||||
transportTenantTelemetryMsgRateLimit?: string;
|
||||
@ -56,6 +60,10 @@ export function createTenantProfileConfiguration(type: TenantProfileType): Tenan
|
||||
const defaultConfiguration: DefaultTenantProfileConfiguration = {
|
||||
maxDevices: 0,
|
||||
maxAssets: 0,
|
||||
maxCustomers: 0,
|
||||
maxUsers: 0,
|
||||
maxDashboards: 0,
|
||||
maxRuleChains: 0,
|
||||
maxTransportMessages: 0,
|
||||
maxTransportDataPoints: 0,
|
||||
maxREExecutions: 0,
|
||||
|
||||
@ -1946,6 +1946,18 @@
|
||||
"maximum-assets": "Maximum number of assets (0 - unlimited)",
|
||||
"maximum-assets-required": "Maximum number of assets is required.",
|
||||
"maximum-assets-range": "Maximum number of assets can't be negative",
|
||||
"maximum-customers": "Maximum number of customers (0 - unlimited)",
|
||||
"maximum-customers-required": "Maximum number of customers is required.",
|
||||
"maximum-customers-range": "Maximum number of customers can't be negative",
|
||||
"maximum-users": "Maximum number of users (0 - unlimited)",
|
||||
"maximum-users-required": "Maximum number of users is required.",
|
||||
"maximum-users-range": "Maximum number of users can't be negative",
|
||||
"maximum-dashboards": "Maximum number of dashboards (0 - unlimited)",
|
||||
"maximum-dashboards-required": "Maximum number of dashboards is required.",
|
||||
"maximum-dashboards-range": "Maximum number of dashboards can't be negative",
|
||||
"maximum-rule-chains": "Maximum number of rule chains (0 - unlimited)",
|
||||
"maximum-rule-chains-required": "Maximum number of rule chains is required.",
|
||||
"maximum-rule-chains-range": "Maximum number of rule chains can't be negative",
|
||||
"transport-tenant-msg-rate-limit": "Transport tenant messages rate limit.",
|
||||
"transport-tenant-telemetry-msg-rate-limit": "Transport tenant telemetry messages rate limit.",
|
||||
"transport-tenant-telemetry-data-points-rate-limit": "Transport tenant telemetry data points rate limit.",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user