Pushed users from CE to edge

This commit is contained in:
Volodymyr Babak 2020-06-12 10:36:03 +03:00
parent ab1014bf16
commit e8afd97605
8 changed files with 133 additions and 348 deletions

View File

@ -306,88 +306,4 @@ public class UserController extends BaseController {
throw handleException(e);
}
}
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/edge/{edgeId}/user/{userId}", method = RequestMethod.POST)
@ResponseBody
public User assignUserToEdge(@PathVariable(EDGE_ID) String strEdgeId,
@PathVariable(USER_ID) String strUserId) throws ThingsboardException {
checkParameter(EDGE_ID, strEdgeId);
checkParameter(USER_ID, strUserId);
try {
EdgeId edgeId = new EdgeId(toUUID(strEdgeId));
Edge edge = checkEdgeId(edgeId, Operation.READ);
UserId userId = new UserId(toUUID(strUserId));
checkUserId(userId, Operation.ASSIGN_TO_EDGE);
User savedUser = checkNotNull(userService.assignUserToEdge(getTenantId(), userId, edgeId));
logEntityAction(userId, savedUser,
savedUser.getCustomerId(),
ActionType.ASSIGNED_TO_EDGE, null, strUserId, strEdgeId, edge.getName());
return savedUser;
} catch (Exception e) {
logEntityAction(emptyId(EntityType.USER), null,
null,
ActionType.ASSIGNED_TO_EDGE, e, strUserId, strEdgeId);
throw handleException(e);
}
}
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/edge/{edgeId}/user/{userId}", method = RequestMethod.DELETE)
@ResponseBody
public User unassignUserFromEdge(@PathVariable(EDGE_ID) String strEdgeId,
@PathVariable(USER_ID) String strUserId) throws ThingsboardException {
checkParameter(EDGE_ID, strEdgeId);
checkParameter(USER_ID, strUserId);
try {
EdgeId edgeId = new EdgeId(toUUID(strEdgeId));
Edge edge = checkEdgeId(edgeId, Operation.READ);
UserId userId = new UserId(toUUID(strUserId));
User user = checkUserId(userId, Operation.UNASSIGN_FROM_EDGE);
User savedUser = checkNotNull(userService.unassignUserFromEdge(getTenantId(), userId, edgeId));
logEntityAction(userId, savedUser,
savedUser.getCustomerId(),
ActionType.UNASSIGNED_FROM_EDGE, null, strUserId, edge.getId().toString(), edge.getName());
return savedUser;
} catch (Exception e) {
logEntityAction(emptyId(EntityType.USER), null,
null,
ActionType.UNASSIGNED_FROM_EDGE, e, strUserId);
throw handleException(e);
}
}
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/edge/{edgeId}/users", params = {"limit"}, method = RequestMethod.GET)
@ResponseBody
public TimePageData<User> getEdgeUsers(
@PathVariable(EDGE_ID) String strEdgeId,
@RequestParam int limit,
@RequestParam(required = false) Long startTime,
@RequestParam(required = false) Long endTime,
@RequestParam(required = false, defaultValue = "false") boolean ascOrder,
@RequestParam(required = false) String offset) throws ThingsboardException {
checkParameter(EDGE_ID, strEdgeId);
try {
TenantId tenantId = getCurrentUser().getTenantId();
EdgeId edgeId = new EdgeId(toUUID(strEdgeId));
checkEdgeId(edgeId, Operation.READ);
TimePageLink pageLink = createPageLink(limit, startTime, endTime, ascOrder, offset);
return checkNotNull(userService.findUsersByTenantIdAndEdgeId(tenantId, edgeId, pageLink).get());
} catch (Exception e) {
throw handleException(e);
}
}
}

View File

@ -17,6 +17,7 @@ package org.thingsboard.server.service.edge.rpc.init;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.MoreExecutors;
import io.grpc.stub.StreamObserver;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
@ -30,6 +31,8 @@ import org.thingsboard.server.common.data.asset.Asset;
import org.thingsboard.server.common.data.edge.Edge;
import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.RuleChainId;
import org.thingsboard.server.common.data.page.TextPageData;
import org.thingsboard.server.common.data.page.TextPageLink;
import org.thingsboard.server.common.data.page.TimePageData;
import org.thingsboard.server.common.data.page.TimePageLink;
import org.thingsboard.server.common.data.relation.EntityRelation;
@ -121,53 +124,57 @@ public class DefaultSyncEdgeService implements SyncEdgeService {
@Override
public void sync(EdgeContextComponent ctx, Edge edge, StreamObserver<ResponseMsg> outputStream) {
Set<EntityId> pushedEntityIds = new HashSet<>();
syncRuleChains(edge, pushedEntityIds, outputStream);
syncDevices(edge, pushedEntityIds, outputStream);
syncAssets(edge, pushedEntityIds, outputStream);
syncEntityViews(edge, pushedEntityIds, outputStream);
syncDashboards(edge, pushedEntityIds, outputStream);
syncUsers(ctx, edge, pushedEntityIds, outputStream);
syncRelations(ctx, edge, pushedEntityIds, outputStream);
List<ListenableFuture<Void>> futures = new ArrayList<>();
futures.add(syncRuleChains(ctx, edge, pushedEntityIds, outputStream));
futures.add(syncDevices(ctx, edge, pushedEntityIds, outputStream));
futures.add(syncAssets(ctx, edge, pushedEntityIds, outputStream));
futures.add(syncEntityViews(ctx, edge, pushedEntityIds, outputStream));
futures.add(syncDashboards(ctx, edge, pushedEntityIds, outputStream));
ListenableFuture<List<Void>> joinFuture = Futures.allAsList(futures);
Futures.transform(joinFuture, result -> {
syncRelations(ctx, edge, pushedEntityIds, outputStream);
return null;
}, MoreExecutors.directExecutor());
}
private void syncRuleChains(Edge edge, Set<EntityId> pushedEntityIds, StreamObserver<ResponseMsg> outputStream) {
private ListenableFuture<Void> syncRuleChains(EdgeContextComponent ctx, Edge edge, Set<EntityId> pushedEntityIds, StreamObserver<ResponseMsg> outputStream) {
try {
TimePageLink pageLink = new TimePageLink(100);
TimePageData<RuleChain> pageData;
do {
pageData = ruleChainService.findRuleChainsByTenantIdAndEdgeId(edge.getTenantId(), edge.getId(), pageLink).get();
if (!pageData.getData().isEmpty()) {
log.trace("[{}] [{}] rule chains(s) are going to be pushed to edge.", edge.getId(), pageData.getData().size());
for (RuleChain ruleChain : pageData.getData()) {
RuleChainUpdateMsg ruleChainUpdateMsg =
ruleChainUpdateMsgConstructor.constructRuleChainUpdatedMsg(
edge.getRootRuleChainId(),
UpdateMsgType.ENTITY_UPDATED_RPC_MESSAGE,
ruleChain);
EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder()
.setRuleChainUpdateMsg(ruleChainUpdateMsg)
.build();
outputStream.onNext(ResponseMsg.newBuilder()
.setEntityUpdateMsg(entityUpdateMsg)
.build());
pushedEntityIds.add(ruleChain.getId());
ListenableFuture<TimePageData<RuleChain>> future = ruleChainService.findRuleChainsByTenantIdAndEdgeId(edge.getTenantId(), edge.getId(), new TimePageLink(Integer.MAX_VALUE));
return Futures.transform(future, pageData -> {
try {
if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) {
log.trace("[{}] [{}] rule chains(s) are going to be pushed to edge.", edge.getId(), pageData.getData().size());
for (RuleChain ruleChain : pageData.getData()) {
RuleChainUpdateMsg ruleChainUpdateMsg =
ruleChainUpdateMsgConstructor.constructRuleChainUpdatedMsg(
edge.getRootRuleChainId(),
UpdateMsgType.ENTITY_UPDATED_RPC_MESSAGE,
ruleChain);
EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder()
.setRuleChainUpdateMsg(ruleChainUpdateMsg)
.build();
outputStream.onNext(ResponseMsg.newBuilder()
.setEntityUpdateMsg(entityUpdateMsg)
.build());
pushedEntityIds.add(ruleChain.getId());
}
}
} catch (Exception e) {
log.error("Exception during loading edge rule chain(s) on sync!", e);
}
if (pageData.hasNext()) {
pageLink = pageData.getNextPageLink();
}
} while (pageData.hasNext());
return null;
}, ctx.getDbCallbackExecutor());
} catch (Exception e) {
log.error("Exception during loading edge rule chain(s) on sync!", e);
return Futures.immediateFuture(null);
}
}
private void syncDevices(Edge edge, Set<EntityId> pushedEntityIds, StreamObserver<ResponseMsg> outputStream) {
private ListenableFuture<Void> syncDevices(EdgeContextComponent ctx, Edge edge, Set<EntityId> pushedEntityIds, StreamObserver<ResponseMsg> outputStream) {
try {
TimePageLink pageLink = new TimePageLink(100);
TimePageData<Device> pageData;
do {
pageData = deviceService.findDevicesByTenantIdAndEdgeId(edge.getTenantId(), edge.getId(), pageLink).get();
ListenableFuture<TimePageData<Device>> future = deviceService.findDevicesByTenantIdAndEdgeId(edge.getTenantId(), edge.getId(), new TimePageLink(Integer.MAX_VALUE));
return Futures.transform(future, pageData -> {
if (!pageData.getData().isEmpty()) {
log.trace("[{}] [{}] device(s) are going to be pushed to edge.", edge.getId(), pageData.getData().size());
for (Device device : pageData.getData()) {
@ -184,22 +191,19 @@ public class DefaultSyncEdgeService implements SyncEdgeService {
pushedEntityIds.add(device.getId());
}
}
if (pageData.hasNext()) {
pageLink = pageData.getNextPageLink();
}
} while (pageData.hasNext());
return null;
}, ctx.getDbCallbackExecutor());
} catch (Exception e) {
log.error("Exception during loading edge device(s) on sync!", e);
return Futures.immediateFuture(null);
}
}
private void syncAssets(Edge edge, Set<EntityId> pushedEntityIds, StreamObserver<ResponseMsg> outputStream) {
private ListenableFuture<Void> syncAssets(EdgeContextComponent ctx, Edge edge, Set<EntityId> pushedEntityIds, StreamObserver<ResponseMsg> outputStream) {
try {
TimePageLink pageLink = new TimePageLink(100);
TimePageData<Asset> pageData;
do {
pageData = assetService.findAssetsByTenantIdAndEdgeId(edge.getTenantId(), edge.getId(), pageLink).get();
if (!pageData.getData().isEmpty()) {
ListenableFuture<TimePageData<Asset>> future = assetService.findAssetsByTenantIdAndEdgeId(edge.getTenantId(), edge.getId(), new TimePageLink(Integer.MAX_VALUE));
return Futures.transform(future, pageData -> {
if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) {
log.trace("[{}] [{}] asset(s) are going to be pushed to edge.", edge.getId(), pageData.getData().size());
for (Asset asset : pageData.getData()) {
AssetUpdateMsg assetUpdateMsg =
@ -215,110 +219,112 @@ public class DefaultSyncEdgeService implements SyncEdgeService {
pushedEntityIds.add(asset.getId());
}
}
if (pageData.hasNext()) {
pageLink = pageData.getNextPageLink();
}
} while (pageData.hasNext());
return null;
}, ctx.getDbCallbackExecutor());
} catch (Exception e) {
log.error("Exception during loading edge asset(s) on sync!", e);
return Futures.immediateFuture(null);
}
}
private void syncEntityViews(Edge edge, Set<EntityId> pushedEntityIds, StreamObserver<ResponseMsg> outputStream) {
private ListenableFuture<Void> syncEntityViews(EdgeContextComponent ctx, Edge edge, Set<EntityId> pushedEntityIds, StreamObserver<ResponseMsg> outputStream) {
try {
TimePageLink pageLink = new TimePageLink(100);
TimePageData<EntityView> pageData;
do {
pageData = entityViewService.findEntityViewsByTenantIdAndEdgeId(edge.getTenantId(), edge.getId(), pageLink).get();
if (!pageData.getData().isEmpty()) {
log.trace("[{}] [{}] entity view(s) are going to be pushed to edge.", edge.getId(), pageData.getData().size());
for (EntityView entityView : pageData.getData()) {
EntityViewUpdateMsg entityViewUpdateMsg =
entityViewUpdateMsgConstructor.constructEntityViewUpdatedMsg(
UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE,
entityView);
EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder()
.setEntityViewUpdateMsg(entityViewUpdateMsg)
.build();
outputStream.onNext(ResponseMsg.newBuilder()
.setEntityUpdateMsg(entityUpdateMsg)
.build());
pushedEntityIds.add(entityView.getId());
ListenableFuture<TimePageData<EntityView>> future = entityViewService.findEntityViewsByTenantIdAndEdgeId(edge.getTenantId(), edge.getId(), new TimePageLink(Integer.MAX_VALUE));
return Futures.transform(future, pageData -> {
try {
if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) {
log.trace("[{}] [{}] entity view(s) are going to be pushed to edge.", edge.getId(), pageData.getData().size());
for (EntityView entityView : pageData.getData()) {
EntityViewUpdateMsg entityViewUpdateMsg =
entityViewUpdateMsgConstructor.constructEntityViewUpdatedMsg(
UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE,
entityView);
EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder()
.setEntityViewUpdateMsg(entityViewUpdateMsg)
.build();
outputStream.onNext(ResponseMsg.newBuilder()
.setEntityUpdateMsg(entityUpdateMsg)
.build());
pushedEntityIds.add(entityView.getId());
}
}
} catch (Exception e) {
log.error("Exception during loading edge entity view(s) on sync!", e);
}
if (pageData.hasNext()) {
pageLink = pageData.getNextPageLink();
}
} while (pageData.hasNext());
return null;
}, ctx.getDbCallbackExecutor());
} catch (Exception e) {
log.error("Exception during loading edge entity view(s) on sync!", e);
return Futures.immediateFuture(null);
}
}
private void syncDashboards(Edge edge, Set<EntityId> pushedEntityIds, StreamObserver<ResponseMsg> outputStream) {
private ListenableFuture<Void> syncDashboards(EdgeContextComponent ctx, Edge edge, Set<EntityId> pushedEntityIds, StreamObserver<ResponseMsg> outputStream) {
try {
TimePageLink pageLink = new TimePageLink(100);
TimePageData<DashboardInfo> pageData;
do {
pageData = dashboardService.findDashboardsByTenantIdAndEdgeId(edge.getTenantId(), edge.getId(), pageLink).get();
if (!pageData.getData().isEmpty()) {
log.trace("[{}] [{}] dashboard(s) are going to be pushed to edge.", edge.getId(), pageData.getData().size());
for (DashboardInfo dashboardInfo : pageData.getData()) {
Dashboard dashboard = dashboardService.findDashboardById(edge.getTenantId(), dashboardInfo.getId());
DashboardUpdateMsg dashboardUpdateMsg =
dashboardUpdateMsgConstructor.constructDashboardUpdatedMsg(
UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE,
dashboard);
EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder()
.setDashboardUpdateMsg(dashboardUpdateMsg)
.build();
outputStream.onNext(ResponseMsg.newBuilder()
.setEntityUpdateMsg(entityUpdateMsg)
.build());
pushedEntityIds.add(dashboard.getId());
ListenableFuture<TimePageData<DashboardInfo>> future = dashboardService.findDashboardsByTenantIdAndEdgeId(edge.getTenantId(), edge.getId(), new TimePageLink(Integer.MAX_VALUE));
return Futures.transform(future, pageData -> {
try {
if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) {
log.trace("[{}] [{}] dashboard(s) are going to be pushed to edge.", edge.getId(), pageData.getData().size());
for (DashboardInfo dashboardInfo : pageData.getData()) {
Dashboard dashboard = dashboardService.findDashboardById(edge.getTenantId(), dashboardInfo.getId());
DashboardUpdateMsg dashboardUpdateMsg =
dashboardUpdateMsgConstructor.constructDashboardUpdatedMsg(
UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE,
dashboard);
EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder()
.setDashboardUpdateMsg(dashboardUpdateMsg)
.build();
outputStream.onNext(ResponseMsg.newBuilder()
.setEntityUpdateMsg(entityUpdateMsg)
.build());
pushedEntityIds.add(dashboard.getId());
}
}
} catch (Exception e) {
log.error("Exception during loading edge dashboard(s) on sync!", e);
}
if (pageData.hasNext()) {
pageLink = pageData.getNextPageLink();
}
} while (pageData.hasNext());
return null;
}, ctx.getDbCallbackExecutor());
} catch (Exception e) {
log.error("Exception during loading edge dashboard(s) on sync!", e);
return Futures.immediateFuture(null);
}
}
private void syncUsers(EdgeContextComponent ctx, Edge edge, Set<EntityId> pushedEntityIds, StreamObserver<ResponseMsg> outputStream) {
try {
TimePageLink pageLink = new TimePageLink(100);
TimePageData<User> pageData;
do {
pageData = userService.findUsersByTenantIdAndEdgeId(edge.getTenantId(), edge.getId(), pageLink).get();
if (!pageData.getData().isEmpty()) {
log.trace("[{}] [{}] user(s) are going to be pushed to edge.", edge.getId(), pageData.getData().size());
for (User user : pageData.getData()) {
UserUpdateMsg userUpdateMsg =
userUpdateMsgConstructor.constructUserUpdatedMsg(
UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE,
user);
EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder()
.setUserUpdateMsg(userUpdateMsg)
.build();
outputStream.onNext(ResponseMsg.newBuilder()
.setEntityUpdateMsg(entityUpdateMsg)
.build());
pushedEntityIds.add(user.getId());
}
}
if (pageData.hasNext()) {
pageLink = pageData.getNextPageLink();
}
} while (pageData.hasNext());
TextPageData<User> pageData = userService.findTenantAdmins(edge.getTenantId(), new TextPageLink(Integer.MAX_VALUE));
pushUsersToEdge(pageData, edge, pushedEntityIds, outputStream);
if (edge.getCustomerId() != null && !EntityId.NULL_UUID.equals(edge.getCustomerId().getId())) {
pageData = userService.findCustomerUsers(edge.getTenantId(), edge.getCustomerId(), new TextPageLink(Integer.MAX_VALUE));
pushUsersToEdge(pageData, edge, pushedEntityIds, outputStream);
}
} catch (Exception e) {
log.error("Exception during loading edge user(s) on sync!", e);
}
}
private void syncRelations(EdgeContextComponent ctx, Edge edge, Set<EntityId> pushedEntityIds, StreamObserver<ResponseMsg> outputStream) {
private void pushUsersToEdge(TextPageData<User> pageData, Edge edge, Set<EntityId> pushedEntityIds, StreamObserver<ResponseMsg> outputStream) {
if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) {
log.trace("[{}] [{}] user(s) are going to be pushed to edge.", edge.getId(), pageData.getData().size());
for (User user : pageData.getData()) {
UserUpdateMsg userUpdateMsg =
userUpdateMsgConstructor.constructUserUpdatedMsg(
UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE,
user);
EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder()
.setUserUpdateMsg(userUpdateMsg)
.build();
outputStream.onNext(ResponseMsg.newBuilder()
.setEntityUpdateMsg(entityUpdateMsg)
.build());
pushedEntityIds.add(user.getId());
}
}
}
private ListenableFuture<Void> syncRelations(EdgeContextComponent ctx, Edge edge, Set<EntityId> pushedEntityIds, StreamObserver<ResponseMsg> outputStream) {
if (!pushedEntityIds.isEmpty()) {
List<ListenableFuture<List<EntityRelation>>> futures = new ArrayList<>();
for (EntityId entityId : pushedEntityIds) {
@ -326,7 +332,7 @@ public class DefaultSyncEdgeService implements SyncEdgeService {
futures.add(syncRelations(edge, entityId, EntitySearchDirection.TO));
}
ListenableFuture<List<List<EntityRelation>>> relationsListFuture = Futures.allAsList(futures);
Futures.transform(relationsListFuture, relationsList -> {
return Futures.transform(relationsListFuture, relationsList -> {
try {
Set<EntityRelation> uniqueEntityRelations = new HashSet<>();
if (!relationsList.isEmpty()) {
@ -360,6 +366,8 @@ public class DefaultSyncEdgeService implements SyncEdgeService {
}
return null;
}, ctx.getDbCallbackExecutor());
} else {
return Futures.immediateFuture(null);
}
}
@ -369,7 +377,6 @@ public class DefaultSyncEdgeService implements SyncEdgeService {
return relationService.findByQuery(edge.getTenantId(), query);
}
@Override
public void syncRuleChainMetadata(Edge edge, RuleChainMetadataRequestMsg ruleChainMetadataRequestMsg, StreamObserver<ResponseMsg> outputStream) {
if (ruleChainMetadataRequestMsg.getRuleChainIdMSB() != 0 && ruleChainMetadataRequestMsg.getRuleChainIdLSB() != 0) {

View File

@ -18,14 +18,11 @@ package org.thingsboard.server.dao.user;
import com.google.common.util.concurrent.ListenableFuture;
import org.thingsboard.server.common.data.User;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.EdgeId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.id.UserCredentialsId;
import org.thingsboard.server.common.data.id.UserId;
import org.thingsboard.server.common.data.page.TextPageData;
import org.thingsboard.server.common.data.page.TextPageLink;
import org.thingsboard.server.common.data.page.TimePageData;
import org.thingsboard.server.common.data.page.TimePageLink;
import org.thingsboard.server.common.data.security.UserCredentials;
public interface UserService {
@ -69,10 +66,4 @@ public interface UserService {
void onUserLoginSuccessful(TenantId tenantId, UserId userId);
int onUserLoginIncorrectCredentials(TenantId tenantId, UserId userId);
User assignUserToEdge(TenantId tenantId, UserId userId, EdgeId edgeId);
User unassignUserFromEdge(TenantId tenantId, UserId userId, EdgeId edgeId);
ListenableFuture<TimePageData<User>> findUsersByTenantIdAndEdgeId(TenantId tenantId, EdgeId edgeId, TimePageLink pageLink);
}

View File

@ -5,7 +5,7 @@
* 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
* 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,

View File

@ -15,31 +15,21 @@
*/
package org.thingsboard.server.dao.sql.user;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.MoreExecutors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Component;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.User;
import org.thingsboard.server.common.data.id.EdgeId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.TextPageLink;
import org.thingsboard.server.common.data.page.TimePageLink;
import org.thingsboard.server.common.data.relation.EntityRelation;
import org.thingsboard.server.common.data.relation.RelationTypeGroup;
import org.thingsboard.server.common.data.security.Authority;
import org.thingsboard.server.dao.DaoUtil;
import org.thingsboard.server.dao.model.sql.UserEntity;
import org.thingsboard.server.dao.relation.RelationDao;
import org.thingsboard.server.dao.sql.JpaAbstractSearchTextDao;
import org.thingsboard.server.dao.user.UserDao;
import org.thingsboard.server.dao.util.SqlDao;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
@ -58,9 +48,6 @@ public class JpaUserDao extends JpaAbstractSearchTextDao<UserEntity, User> imple
@Autowired
private UserRepository userRepository;
@Autowired
private RelationDao relationDao;
@Override
protected Class<UserEntity> getEntityClass() {
return UserEntity.class;
@ -102,17 +89,4 @@ public class JpaUserDao extends JpaAbstractSearchTextDao<UserEntity, User> imple
PageRequest.of(0, pageLink.getLimit())));
}
@Override
public ListenableFuture<List<User>> findUsersByTenantIdAndEdgeId(UUID tenantId, UUID edgeId, TimePageLink pageLink) {
log.debug("Try to find users by tenantId [{}], edgeId [{}] and pageLink [{}]", tenantId, edgeId, pageLink);
ListenableFuture<List<EntityRelation>> relations = relationDao.findRelations(new TenantId(tenantId), new EdgeId(edgeId), EntityRelation.CONTAINS_TYPE, RelationTypeGroup.EDGE, EntityType.USER, pageLink);
return Futures.transformAsync(relations, input -> {
List<ListenableFuture<User>> userFutures = new ArrayList<>(input.size());
for (EntityRelation relation : input) {
userFutures.add(findByIdAsync(new TenantId(tenantId), relation.getTo().getId()));
}
return Futures.successfulAsList(userFutures);
}, MoreExecutors.directExecutor());
}
}

View File

@ -16,30 +16,18 @@
package org.thingsboard.server.dao.user;
import com.datastax.driver.core.querybuilder.Select.Where;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.MoreExecutors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.User;
import org.thingsboard.server.common.data.asset.Asset;
import org.thingsboard.server.common.data.id.EdgeId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.TextPageLink;
import org.thingsboard.server.common.data.page.TimePageLink;
import org.thingsboard.server.common.data.relation.EntityRelation;
import org.thingsboard.server.common.data.relation.RelationTypeGroup;
import org.thingsboard.server.common.data.security.Authority;
import org.thingsboard.server.dao.DaoUtil;
import org.thingsboard.server.dao.model.ModelConstants;
import org.thingsboard.server.dao.model.nosql.UserEntity;
import org.thingsboard.server.dao.nosql.CassandraAbstractSearchTextDao;
import org.thingsboard.server.dao.relation.RelationDao;
import org.thingsboard.server.dao.util.NoSqlDao;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
@ -52,9 +40,6 @@ import static com.datastax.driver.core.querybuilder.QueryBuilder.select;
@NoSqlDao
public class CassandraUserDao extends CassandraAbstractSearchTextDao<UserEntity, User> implements UserDao {
@Autowired
private RelationDao relationDao;
@Override
protected Class<UserEntity> getColumnFamilyClass() {
return UserEntity.class;
@ -100,17 +85,4 @@ public class CassandraUserDao extends CassandraAbstractSearchTextDao<UserEntity,
log.trace("Found customer users [{}] by tenantId [{}], customerId [{}] and pageLink [{}]", userEntities, tenantId, customerId, pageLink);
return DaoUtil.convertDataList(userEntities);
}
@Override
public ListenableFuture<List<User>> findUsersByTenantIdAndEdgeId(UUID tenantId, UUID edgeId, TimePageLink pageLink) {
log.debug("Try to find users by tenantId [{}], edgeId [{}] and pageLink [{}]", tenantId, edgeId, pageLink);
ListenableFuture<List<EntityRelation>> relations = relationDao.findRelations(new TenantId(tenantId), new EdgeId(edgeId), EntityRelation.CONTAINS_TYPE, RelationTypeGroup.EDGE, EntityType.USER, pageLink);
return Futures.transformAsync(relations, input -> {
List<ListenableFuture<User>> userFutures = new ArrayList<>(input.size());
for (EntityRelation relation : input) {
userFutures.add(findByIdAsync(new TenantId(tenantId), relation.getTo().getId()));
}
return Futures.successfulAsList(userFutures);
}, MoreExecutors.directExecutor());
}
}

View File

@ -15,11 +15,9 @@
*/
package org.thingsboard.server.dao.user;
import com.google.common.util.concurrent.ListenableFuture;
import org.thingsboard.server.common.data.User;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.TextPageLink;
import org.thingsboard.server.common.data.page.TimePageLink;
import org.thingsboard.server.dao.Dao;
import java.util.List;
@ -42,7 +40,7 @@ public interface UserDao extends Dao<User> {
* @return the user entity
*/
User findByEmail(TenantId tenantId, String email);
/**
* Find tenant admin users by tenantId and page link.
*
@ -51,7 +49,7 @@ public interface UserDao extends Dao<User> {
* @return the list of user entities
*/
List<User> findTenantAdmins(UUID tenantId, TextPageLink pageLink);
/**
* Find customer users by tenantId, customerId and page link.
*
@ -61,15 +59,4 @@ public interface UserDao extends Dao<User> {
* @return the list of user entities
*/
List<User> findCustomerUsers(UUID tenantId, UUID customerId, TextPageLink pageLink);
/**
* Find users by tenantId, edgeId and page link.
*
* @param tenantId the tenantId
* @param edgeId the edgeId
* @param pageLink the page link
* @return the list of user objects
*/
ListenableFuture<List<User>> findUsersByTenantIdAndEdgeId(UUID tenantId, UUID edgeId, TimePageLink pageLink);
}

View File

@ -18,10 +18,7 @@ package org.thingsboard.server.dao.user;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.base.Function;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.MoreExecutors;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
@ -31,18 +28,12 @@ import org.springframework.stereotype.Service;
import org.thingsboard.server.common.data.Customer;
import org.thingsboard.server.common.data.Tenant;
import org.thingsboard.server.common.data.User;
import org.thingsboard.server.common.data.edge.Edge;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.EdgeId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.id.UserCredentialsId;
import org.thingsboard.server.common.data.id.UserId;
import org.thingsboard.server.common.data.page.TextPageData;
import org.thingsboard.server.common.data.page.TextPageLink;
import org.thingsboard.server.common.data.page.TimePageData;
import org.thingsboard.server.common.data.page.TimePageLink;
import org.thingsboard.server.common.data.relation.EntityRelation;
import org.thingsboard.server.common.data.relation.RelationTypeGroup;
import org.thingsboard.server.common.data.security.Authority;
import org.thingsboard.server.common.data.security.UserCredentials;
import org.thingsboard.server.dao.customer.CustomerDao;
@ -55,11 +46,9 @@ import org.thingsboard.server.dao.service.DataValidator;
import org.thingsboard.server.dao.service.PaginatedRemover;
import org.thingsboard.server.dao.tenant.TenantDao;
import javax.annotation.Nullable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import static org.thingsboard.server.dao.service.Validator.validateId;
import static org.thingsboard.server.dao.service.Validator.validatePageLink;
@ -327,57 +316,6 @@ public class UserServiceImpl extends AbstractEntityService implements UserServic
return failedLoginAttempts;
}
@Override
public User assignUserToEdge(TenantId tenantId, UserId userId, EdgeId edgeId) {
User user = findUserById(tenantId, userId);
Edge edge = edgeService.findEdgeById(tenantId, edgeId);
if (edge == null) {
throw new DataValidationException("Can't assign user to non-existent edge!");
}
if (!edge.getTenantId().getId().equals(user.getTenantId().getId())) {
throw new DataValidationException("Can't assign user to edge from different tenant!");
}
try {
createRelation(tenantId, new EntityRelation(edgeId, userId, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.EDGE));
} catch (ExecutionException | InterruptedException e) {
log.warn("[{}] Failed to create user relation. Edge Id: [{}]", userId, edgeId);
throw new RuntimeException(e);
}
return user;
}
@Override
public User unassignUserFromEdge(TenantId tenantId, UserId userId, EdgeId edgeId) {
User user = findUserById(tenantId, userId);
Edge edge = edgeService.findEdgeById(tenantId, edgeId);
if (edge == null) {
throw new DataValidationException("Can't unassign user from non-existent edge!");
}
try {
deleteRelation(tenantId, new EntityRelation(edgeId, userId, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.EDGE));
} catch (ExecutionException | InterruptedException e) {
log.warn("[{}] Failed to delete user relation. Edge Id: [{}]", userId, edgeId);
throw new RuntimeException(e);
}
return user;
}
@Override
public ListenableFuture<TimePageData<User>> findUsersByTenantIdAndEdgeId(TenantId tenantId, EdgeId edgeId, TimePageLink pageLink) {
log.trace("Executing findUsersByTenantIdAndEdgeId, tenantId [{}], edgeId [{}], pageLink [{}]", tenantId, edgeId, pageLink);
validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
validateId(edgeId, INCORRECT_EDGE_ID + edgeId);
validatePageLink(pageLink, INCORRECT_PAGE_LINK + pageLink);
ListenableFuture<List<User>> users = userDao.findUsersByTenantIdAndEdgeId(tenantId.getId(), edgeId.getId(), pageLink);
return Futures.transform(users, new Function<List<User>, TimePageData<User>>() {
@Nullable
@Override
public TimePageData<User> apply(@Nullable List<User> users) {
return new TimePageData<>(users, pageLink);
}
}, MoreExecutors.directExecutor());
}
private int increaseFailedLoginAttempts(User user) {
JsonNode additionalInfo = user.getAdditionalInfo();
if (!(additionalInfo instanceof ObjectNode)) {