Merge pull request #10239 from AndriiLandiak/feature/edge-oauth-support
Edge - OAuth2 support
This commit is contained in:
commit
cb9236ff78
@ -14,7 +14,6 @@
|
||||
-- limitations under the License.
|
||||
--
|
||||
|
||||
|
||||
-- create new attribute_kv table schema
|
||||
DO
|
||||
$$
|
||||
@ -105,4 +104,11 @@ EXCEPTION
|
||||
ROLLBACK;
|
||||
RAISE EXCEPTION 'Error during COPY: %', SQLERRM;
|
||||
END
|
||||
$$;
|
||||
$$;
|
||||
|
||||
-- OAUTH2 PARAMS ALTER TABLE START
|
||||
|
||||
ALTER TABLE oauth2_params
|
||||
ADD COLUMN IF NOT EXISTS edge_enabled boolean DEFAULT false;
|
||||
|
||||
-- OAUTH2 PARAMS ALTER TABLE END
|
||||
|
||||
@ -42,6 +42,7 @@ import org.thingsboard.server.service.edge.rpc.processor.device.DeviceEdgeProces
|
||||
import org.thingsboard.server.service.edge.rpc.processor.device.profile.DeviceProfileEdgeProcessor;
|
||||
import org.thingsboard.server.service.edge.rpc.processor.edge.EdgeProcessor;
|
||||
import org.thingsboard.server.service.edge.rpc.processor.entityview.EntityViewEdgeProcessor;
|
||||
import org.thingsboard.server.service.edge.rpc.processor.oauth2.OAuth2EdgeProcessor;
|
||||
import org.thingsboard.server.service.edge.rpc.processor.ota.OtaPackageEdgeProcessor;
|
||||
import org.thingsboard.server.service.edge.rpc.processor.queue.QueueEdgeProcessor;
|
||||
import org.thingsboard.server.service.edge.rpc.processor.relation.RelationEdgeProcessor;
|
||||
@ -126,6 +127,9 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService {
|
||||
@Autowired
|
||||
private ResourceEdgeProcessor resourceEdgeProcessor;
|
||||
|
||||
@Autowired
|
||||
private OAuth2EdgeProcessor oAuth2EdgeProcessor;
|
||||
|
||||
@Autowired
|
||||
protected ApplicationEventPublisher eventPublisher;
|
||||
|
||||
@ -231,6 +235,9 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService {
|
||||
case TB_RESOURCE:
|
||||
resourceEdgeProcessor.processEntityNotification(tenantId, edgeNotificationMsg);
|
||||
break;
|
||||
case OAUTH2:
|
||||
oAuth2EdgeProcessor.processOAuth2Notification(tenantId, edgeNotificationMsg);
|
||||
break;
|
||||
default:
|
||||
log.warn("[{}] Edge event type [{}] is not designed to be pushed to edge", tenantId, type);
|
||||
}
|
||||
|
||||
@ -32,6 +32,7 @@ import org.thingsboard.server.dao.device.DeviceService;
|
||||
import org.thingsboard.server.dao.edge.EdgeEventService;
|
||||
import org.thingsboard.server.dao.edge.EdgeService;
|
||||
import org.thingsboard.server.dao.entityview.EntityViewService;
|
||||
import org.thingsboard.server.dao.oauth2.OAuth2Service;
|
||||
import org.thingsboard.server.dao.ota.OtaPackageService;
|
||||
import org.thingsboard.server.dao.queue.QueueService;
|
||||
import org.thingsboard.server.dao.resource.ResourceService;
|
||||
@ -61,6 +62,7 @@ import org.thingsboard.server.service.edge.rpc.processor.device.profile.DevicePr
|
||||
import org.thingsboard.server.service.edge.rpc.processor.edge.EdgeProcessor;
|
||||
import org.thingsboard.server.service.edge.rpc.processor.entityview.EntityViewEdgeProcessor;
|
||||
import org.thingsboard.server.service.edge.rpc.processor.entityview.EntityViewProcessorFactory;
|
||||
import org.thingsboard.server.service.edge.rpc.processor.oauth2.OAuth2EdgeProcessor;
|
||||
import org.thingsboard.server.service.edge.rpc.processor.ota.OtaPackageEdgeProcessor;
|
||||
import org.thingsboard.server.service.edge.rpc.processor.queue.QueueEdgeProcessor;
|
||||
import org.thingsboard.server.service.edge.rpc.processor.relation.RelationEdgeProcessor;
|
||||
@ -151,6 +153,9 @@ public class EdgeContextComponent {
|
||||
@Autowired
|
||||
private ResourceService resourceService;
|
||||
|
||||
@Autowired
|
||||
private OAuth2Service oAuth2Service;
|
||||
|
||||
@Autowired
|
||||
private RateLimitService rateLimitService;
|
||||
|
||||
@ -220,6 +225,9 @@ public class EdgeContextComponent {
|
||||
@Autowired
|
||||
private ResourceEdgeProcessor resourceEdgeProcessor;
|
||||
|
||||
@Autowired
|
||||
private OAuth2EdgeProcessor oAuth2EdgeProcessor;
|
||||
|
||||
@Autowired
|
||||
private EdgeMsgConstructor edgeMsgConstructor;
|
||||
|
||||
|
||||
@ -33,6 +33,7 @@ import org.thingsboard.server.common.data.alarm.AlarmComment;
|
||||
import org.thingsboard.server.common.data.audit.ActionType;
|
||||
import org.thingsboard.server.common.data.edge.EdgeEventActionType;
|
||||
import org.thingsboard.server.common.data.edge.EdgeEventType;
|
||||
import org.thingsboard.server.common.data.oauth2.OAuth2Info;
|
||||
import org.thingsboard.server.common.data.relation.EntityRelation;
|
||||
import org.thingsboard.server.common.data.relation.RelationTypeGroup;
|
||||
import org.thingsboard.server.common.data.rule.RuleChain;
|
||||
@ -159,43 +160,41 @@ public class EdgeEventSourcingListener {
|
||||
private boolean isValidSaveEntityEventForEdgeProcessing(SaveEntityEvent<?> event) {
|
||||
Object entity = event.getEntity();
|
||||
Object oldEntity = event.getOldEntity();
|
||||
switch (event.getEntityId().getEntityType()) {
|
||||
case RULE_CHAIN:
|
||||
if (entity instanceof RuleChain) {
|
||||
RuleChain ruleChain = (RuleChain) entity;
|
||||
return RuleChainType.EDGE.equals(ruleChain.getType());
|
||||
}
|
||||
break;
|
||||
case USER:
|
||||
if (entity instanceof User) {
|
||||
User user = (User) entity;
|
||||
if (Authority.SYS_ADMIN.equals(user.getAuthority())) {
|
||||
if (event.getEntityId() != null) {
|
||||
switch (event.getEntityId().getEntityType()) {
|
||||
case RULE_CHAIN:
|
||||
if (entity instanceof RuleChain ruleChain) {
|
||||
return RuleChainType.EDGE.equals(ruleChain.getType());
|
||||
}
|
||||
break;
|
||||
case USER:
|
||||
if (entity instanceof User user) {
|
||||
if (Authority.SYS_ADMIN.equals(user.getAuthority())) {
|
||||
return false;
|
||||
}
|
||||
if (oldEntity != null) {
|
||||
User oldUser = (User) oldEntity;
|
||||
cleanUpUserAdditionalInfo(oldUser);
|
||||
cleanUpUserAdditionalInfo(user);
|
||||
return !user.equals(oldUser);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case OTA_PACKAGE:
|
||||
if (entity instanceof OtaPackageInfo otaPackageInfo) {
|
||||
return otaPackageInfo.hasUrl() || otaPackageInfo.isHasData();
|
||||
}
|
||||
break;
|
||||
case ALARM:
|
||||
if (entity instanceof AlarmApiCallResult || entity instanceof Alarm) {
|
||||
return false;
|
||||
}
|
||||
if (oldEntity != null) {
|
||||
User oldUser = (User) oldEntity;
|
||||
cleanUpUserAdditionalInfo(oldUser);
|
||||
cleanUpUserAdditionalInfo(user);
|
||||
return !user.equals(oldUser);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case OTA_PACKAGE:
|
||||
if (entity instanceof OtaPackageInfo) {
|
||||
OtaPackageInfo otaPackageInfo = (OtaPackageInfo) entity;
|
||||
return otaPackageInfo.hasUrl() || otaPackageInfo.isHasData();
|
||||
}
|
||||
break;
|
||||
case ALARM:
|
||||
if (entity instanceof AlarmApiCallResult || entity instanceof Alarm) {
|
||||
break;
|
||||
case TENANT:
|
||||
return !event.getCreated();
|
||||
case API_USAGE_STATE, EDGE:
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case TENANT:
|
||||
return !event.getCreated();
|
||||
case API_USAGE_STATE:
|
||||
case EDGE:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Default: If the entity doesn't match any of the conditions, consider it as valid.
|
||||
return true;
|
||||
@ -206,8 +205,7 @@ public class EdgeEventSourcingListener {
|
||||
if (user.getAdditionalInfo() instanceof NullNode) {
|
||||
user.setAdditionalInfo(null);
|
||||
}
|
||||
if (user.getAdditionalInfo() instanceof ObjectNode) {
|
||||
ObjectNode additionalInfo = ((ObjectNode) user.getAdditionalInfo());
|
||||
if (user.getAdditionalInfo() instanceof ObjectNode additionalInfo) {
|
||||
additionalInfo.remove(UserServiceImpl.FAILED_LOGIN_ATTEMPTS);
|
||||
additionalInfo.remove(UserServiceImpl.LAST_LOGIN_TS);
|
||||
if (additionalInfo.isEmpty()) {
|
||||
@ -221,6 +219,8 @@ public class EdgeEventSourcingListener {
|
||||
private EdgeEventType getEdgeEventTypeForEntityEvent(Object entity) {
|
||||
if (entity instanceof AlarmComment) {
|
||||
return EdgeEventType.ALARM_COMMENT;
|
||||
} else if (entity instanceof OAuth2Info) {
|
||||
return EdgeEventType.OAUTH2;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@ -228,6 +228,8 @@ public class EdgeEventSourcingListener {
|
||||
private String getBodyMsgForEntityEvent(Object entity) {
|
||||
if (entity instanceof AlarmComment) {
|
||||
return JacksonUtil.toString(entity);
|
||||
} else if (entity instanceof OAuth2Info) {
|
||||
return JacksonUtil.toString(entity);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@ -238,4 +240,5 @@ public class EdgeEventSourcingListener {
|
||||
}
|
||||
return isCreated ? EdgeEventActionType.ADDED : EdgeEventActionType.UPDATED;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -705,6 +705,8 @@ public final class EdgeGrpcSession implements Closeable {
|
||||
return ctx.getTenantEdgeProcessor().convertTenantEventToDownlink(edgeEvent, this.edgeVersion);
|
||||
case TENANT_PROFILE:
|
||||
return ctx.getTenantProfileEdgeProcessor().convertTenantProfileEventToDownlink(edgeEvent, this.edgeVersion);
|
||||
case OAUTH2:
|
||||
return ctx.getOAuth2EdgeProcessor().convertOAuth2EventToDownlink(edgeEvent);
|
||||
default:
|
||||
log.warn("[{}] Unsupported edge event type [{}]", this.tenantId, edgeEvent);
|
||||
return null;
|
||||
|
||||
@ -30,6 +30,7 @@ import org.thingsboard.server.service.edge.rpc.fetch.DeviceProfilesEdgeEventFetc
|
||||
import org.thingsboard.server.service.edge.rpc.fetch.DevicesEdgeEventFetcher;
|
||||
import org.thingsboard.server.service.edge.rpc.fetch.EdgeEventFetcher;
|
||||
import org.thingsboard.server.service.edge.rpc.fetch.EntityViewsEdgeEventFetcher;
|
||||
import org.thingsboard.server.service.edge.rpc.fetch.OAuth2EdgeEventFetcher;
|
||||
import org.thingsboard.server.service.edge.rpc.fetch.OtaPackagesEdgeEventFetcher;
|
||||
import org.thingsboard.server.service.edge.rpc.fetch.QueuesEdgeEventFetcher;
|
||||
import org.thingsboard.server.service.edge.rpc.fetch.RuleChainsEdgeEventFetcher;
|
||||
@ -79,6 +80,7 @@ public class EdgeSyncCursor {
|
||||
fetchers.add(new TenantWidgetsBundlesEdgeEventFetcher(ctx.getWidgetsBundleService()));
|
||||
fetchers.add(new OtaPackagesEdgeEventFetcher(ctx.getOtaPackageService()));
|
||||
fetchers.add(new TenantResourcesEdgeEventFetcher(ctx.getResourceService()));
|
||||
fetchers.add(new OAuth2EdgeEventFetcher(ctx.getOAuth2Service()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,32 @@
|
||||
/**
|
||||
* Copyright © 2016-2024 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.service.edge.rpc.constructor.oauth2;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.thingsboard.common.util.JacksonUtil;
|
||||
import org.thingsboard.server.common.data.oauth2.OAuth2Info;
|
||||
import org.thingsboard.server.gen.edge.v1.OAuth2UpdateMsg;
|
||||
import org.thingsboard.server.queue.util.TbCoreComponent;
|
||||
|
||||
@Component
|
||||
@TbCoreComponent
|
||||
public class OAuth2MsgConstructor {
|
||||
|
||||
public OAuth2UpdateMsg constructOAuth2UpdateMsg(OAuth2Info oAuth2Info) {
|
||||
return OAuth2UpdateMsg.newBuilder().setEntity(JacksonUtil.toString(oAuth2Info)).build();
|
||||
}
|
||||
|
||||
}
|
||||
@ -46,7 +46,7 @@ public class CustomerEdgeEventFetcher implements EdgeEventFetcher {
|
||||
List<EdgeEvent> result = new ArrayList<>();
|
||||
result.add(EdgeUtils.constructEdgeEvent(edge.getTenantId(), edge.getId(),
|
||||
EdgeEventType.CUSTOMER, EdgeEventActionType.ADDED, customerId, null));
|
||||
// @voba - returns PageData object to be in sync with other fetchers
|
||||
// returns PageData object to be in sync with other fetchers
|
||||
return new PageData<>(result, 1, result.size(), false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,56 @@
|
||||
/**
|
||||
* Copyright © 2016-2024 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.service.edge.rpc.fetch;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.thingsboard.common.util.JacksonUtil;
|
||||
import org.thingsboard.server.common.data.EdgeUtils;
|
||||
import org.thingsboard.server.common.data.edge.Edge;
|
||||
import org.thingsboard.server.common.data.edge.EdgeEvent;
|
||||
import org.thingsboard.server.common.data.edge.EdgeEventActionType;
|
||||
import org.thingsboard.server.common.data.edge.EdgeEventType;
|
||||
import org.thingsboard.server.common.data.id.TenantId;
|
||||
import org.thingsboard.server.common.data.oauth2.OAuth2Info;
|
||||
import org.thingsboard.server.common.data.page.PageData;
|
||||
import org.thingsboard.server.common.data.page.PageLink;
|
||||
import org.thingsboard.server.dao.oauth2.OAuth2Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@AllArgsConstructor
|
||||
@Slf4j
|
||||
public class OAuth2EdgeEventFetcher implements EdgeEventFetcher {
|
||||
|
||||
private final OAuth2Service oAuth2Service;
|
||||
|
||||
@Override
|
||||
public PageLink getPageLink(int pageSize) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageData<EdgeEvent> fetchEdgeEvents(TenantId tenantId, Edge edge, PageLink pageLink) {
|
||||
List<EdgeEvent> result = new ArrayList<>();
|
||||
OAuth2Info oAuth2Info = oAuth2Service.findOAuth2Info();
|
||||
result.add(EdgeUtils.constructEdgeEvent(tenantId, edge.getId(), EdgeEventType.OAUTH2,
|
||||
EdgeEventActionType.ADDED, null, JacksonUtil.valueToTree(oAuth2Info)));
|
||||
// returns PageData object to be in sync with other fetchers
|
||||
return new PageData<>(result, 1, result.size(), false);
|
||||
}
|
||||
|
||||
}
|
||||
@ -51,9 +51,8 @@ import org.thingsboard.server.common.data.id.TenantId;
|
||||
import org.thingsboard.server.common.data.id.UserId;
|
||||
import org.thingsboard.server.common.data.kv.AttributeKvEntry;
|
||||
import org.thingsboard.server.common.data.msg.TbMsgType;
|
||||
import org.thingsboard.server.common.data.page.PageData;
|
||||
import org.thingsboard.server.common.data.page.PageDataIterable;
|
||||
import org.thingsboard.server.common.data.page.PageDataIterableByTenantIdEntityId;
|
||||
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.rule.RuleChain;
|
||||
@ -75,6 +74,7 @@ import org.thingsboard.server.dao.edge.EdgeEventService;
|
||||
import org.thingsboard.server.dao.edge.EdgeService;
|
||||
import org.thingsboard.server.dao.edge.EdgeSynchronizationManager;
|
||||
import org.thingsboard.server.dao.entityview.EntityViewService;
|
||||
import org.thingsboard.server.dao.oauth2.OAuth2Service;
|
||||
import org.thingsboard.server.dao.ota.OtaPackageService;
|
||||
import org.thingsboard.server.dao.queue.QueueService;
|
||||
import org.thingsboard.server.dao.relation.RelationService;
|
||||
@ -101,6 +101,7 @@ import org.thingsboard.server.service.edge.rpc.constructor.dashboard.DashboardMs
|
||||
import org.thingsboard.server.service.edge.rpc.constructor.device.DeviceMsgConstructorFactory;
|
||||
import org.thingsboard.server.service.edge.rpc.constructor.edge.EdgeMsgConstructor;
|
||||
import org.thingsboard.server.service.edge.rpc.constructor.entityview.EntityViewMsgConstructorFactory;
|
||||
import org.thingsboard.server.service.edge.rpc.constructor.oauth2.OAuth2MsgConstructor;
|
||||
import org.thingsboard.server.service.edge.rpc.constructor.ota.OtaPackageMsgConstructorFactory;
|
||||
import org.thingsboard.server.service.edge.rpc.constructor.queue.QueueMsgConstructorFactory;
|
||||
import org.thingsboard.server.service.edge.rpc.constructor.relation.RelationMsgConstructorFactory;
|
||||
@ -226,6 +227,9 @@ public abstract class BaseEdgeProcessor {
|
||||
@Autowired
|
||||
protected ResourceService resourceService;
|
||||
|
||||
@Autowired
|
||||
protected OAuth2Service oAuth2Service;
|
||||
|
||||
@Autowired
|
||||
@Lazy
|
||||
protected TbQueueProducerProvider producerProvider;
|
||||
@ -257,6 +261,9 @@ public abstract class BaseEdgeProcessor {
|
||||
@Autowired
|
||||
protected EntityDataMsgConstructor entityDataMsgConstructor;
|
||||
|
||||
@Autowired
|
||||
protected OAuth2MsgConstructor oAuth2MsgConstructor;
|
||||
|
||||
@Autowired
|
||||
protected RuleChainMsgConstructorFactory ruleChainMsgConstructorFactory;
|
||||
|
||||
@ -392,18 +399,13 @@ public abstract class BaseEdgeProcessor {
|
||||
|
||||
protected ListenableFuture<Void> processActionForAllEdges(TenantId tenantId, EdgeEventType type,
|
||||
EdgeEventActionType actionType, EntityId entityId,
|
||||
EdgeId sourceEdgeId) {
|
||||
JsonNode body, EdgeId sourceEdgeId) {
|
||||
List<ListenableFuture<Void>> futures = new ArrayList<>();
|
||||
if (TenantId.SYS_TENANT_ID.equals(tenantId)) {
|
||||
PageLink pageLink = new PageLink(DEFAULT_PAGE_SIZE);
|
||||
PageData<TenantId> tenantsIds;
|
||||
do {
|
||||
tenantsIds = tenantService.findTenantsIds(pageLink);
|
||||
for (TenantId tenantId1 : tenantsIds.getData()) {
|
||||
futures.addAll(processActionForAllEdgesByTenantId(tenantId1, type, actionType, entityId, null, sourceEdgeId));
|
||||
}
|
||||
pageLink = pageLink.nextPageLink();
|
||||
} while (tenantsIds.hasNext());
|
||||
PageDataIterable<TenantId> tenantIds = new PageDataIterable<>(link -> tenantService.findTenantsIds(link), 1024);
|
||||
for (TenantId tenantId1 : tenantIds) {
|
||||
futures.addAll(processActionForAllEdgesByTenantId(tenantId1, type, actionType, entityId, body, sourceEdgeId));
|
||||
}
|
||||
} else {
|
||||
futures = processActionForAllEdgesByTenantId(tenantId, type, actionType, entityId, null, sourceEdgeId);
|
||||
}
|
||||
@ -416,22 +418,13 @@ public abstract class BaseEdgeProcessor {
|
||||
EntityId entityId,
|
||||
JsonNode body,
|
||||
EdgeId sourceEdgeId) {
|
||||
PageLink pageLink = new PageLink(DEFAULT_PAGE_SIZE);
|
||||
PageData<Edge> pageData;
|
||||
List<ListenableFuture<Void>> futures = new ArrayList<>();
|
||||
do {
|
||||
pageData = edgeService.findEdgesByTenantId(tenantId, pageLink);
|
||||
if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) {
|
||||
for (Edge edge : pageData.getData()) {
|
||||
if (!edge.getId().equals(sourceEdgeId)) {
|
||||
futures.add(saveEdgeEvent(tenantId, edge.getId(), type, actionType, entityId, body));
|
||||
}
|
||||
}
|
||||
if (pageData.hasNext()) {
|
||||
pageLink = pageLink.nextPageLink();
|
||||
}
|
||||
PageDataIterable<Edge> edges = new PageDataIterable<>(link -> edgeService.findEdgesByTenantId(tenantId, link), 1024);
|
||||
for (Edge edge : edges) {
|
||||
if (!edge.getId().equals(sourceEdgeId)) {
|
||||
futures.add(saveEdgeEvent(tenantId, edge.getId(), type, actionType, entityId, body));
|
||||
}
|
||||
} while (pageData != null && pageData.hasNext());
|
||||
}
|
||||
return futures;
|
||||
}
|
||||
|
||||
@ -539,35 +532,24 @@ public abstract class BaseEdgeProcessor {
|
||||
}
|
||||
|
||||
private ListenableFuture<Void> updateDependentRuleChains(TenantId tenantId, RuleChainId processingRuleChainId, EdgeId edgeId) {
|
||||
PageLink pageLink = new PageLink(DEFAULT_PAGE_SIZE);
|
||||
PageData<RuleChain> pageData;
|
||||
List<ListenableFuture<Void>> futures = new ArrayList<>();
|
||||
do {
|
||||
pageData = ruleChainService.findRuleChainsByTenantIdAndEdgeId(tenantId, edgeId, pageLink);
|
||||
if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) {
|
||||
for (RuleChain ruleChain : pageData.getData()) {
|
||||
if (!ruleChain.getId().equals(processingRuleChainId)) {
|
||||
List<RuleChainConnectionInfo> connectionInfos =
|
||||
ruleChainService.loadRuleChainMetaData(ruleChain.getTenantId(), ruleChain.getId()).getRuleChainConnections();
|
||||
if (connectionInfos != null && !connectionInfos.isEmpty()) {
|
||||
for (RuleChainConnectionInfo connectionInfo : connectionInfos) {
|
||||
if (connectionInfo.getTargetRuleChainId().equals(processingRuleChainId)) {
|
||||
futures.add(saveEdgeEvent(tenantId,
|
||||
edgeId,
|
||||
EdgeEventType.RULE_CHAIN_METADATA,
|
||||
EdgeEventActionType.UPDATED,
|
||||
ruleChain.getId(),
|
||||
null));
|
||||
}
|
||||
}
|
||||
}
|
||||
PageDataIterable<RuleChain> ruleChains = new PageDataIterable<>(link -> ruleChainService.findRuleChainsByTenantIdAndEdgeId(tenantId, edgeId, link), 1024);
|
||||
for (RuleChain ruleChain : ruleChains) {
|
||||
List<RuleChainConnectionInfo> connectionInfos =
|
||||
ruleChainService.loadRuleChainMetaData(ruleChain.getTenantId(), ruleChain.getId()).getRuleChainConnections();
|
||||
if (connectionInfos != null && !connectionInfos.isEmpty()) {
|
||||
for (RuleChainConnectionInfo connectionInfo : connectionInfos) {
|
||||
if (connectionInfo.getTargetRuleChainId().equals(processingRuleChainId)) {
|
||||
futures.add(saveEdgeEvent(tenantId,
|
||||
edgeId,
|
||||
EdgeEventType.RULE_CHAIN_METADATA,
|
||||
EdgeEventActionType.UPDATED,
|
||||
ruleChain.getId(),
|
||||
null));
|
||||
}
|
||||
}
|
||||
if (pageData.hasNext()) {
|
||||
pageLink = pageLink.nextPageLink();
|
||||
}
|
||||
}
|
||||
} while (pageData != null && pageData.hasNext());
|
||||
}
|
||||
return Futures.transform(Futures.allAsList(futures), voids -> null, dbCallbackExecutorService);
|
||||
}
|
||||
|
||||
@ -577,7 +559,7 @@ public abstract class BaseEdgeProcessor {
|
||||
case UPDATED:
|
||||
case DELETED:
|
||||
case CREDENTIALS_UPDATED: // used by USER entity
|
||||
return processActionForAllEdges(tenantId, type, actionType, entityId, sourceEdgeId);
|
||||
return processActionForAllEdges(tenantId, type, actionType, entityId, null, sourceEdgeId);
|
||||
default:
|
||||
return Futures.immediateFuture(null);
|
||||
}
|
||||
|
||||
@ -29,8 +29,7 @@ import org.thingsboard.server.common.data.id.CustomerId;
|
||||
import org.thingsboard.server.common.data.id.EdgeId;
|
||||
import org.thingsboard.server.common.data.id.EntityIdFactory;
|
||||
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.page.PageDataIterable;
|
||||
import org.thingsboard.server.gen.edge.v1.CustomerUpdateMsg;
|
||||
import org.thingsboard.server.gen.edge.v1.DownlinkMsg;
|
||||
import org.thingsboard.server.gen.edge.v1.EdgeVersion;
|
||||
@ -85,20 +84,11 @@ public class CustomerEdgeProcessor extends BaseEdgeProcessor {
|
||||
CustomerId customerId = new CustomerId(EntityIdFactory.getByEdgeEventTypeAndUuid(type, uuid).getId());
|
||||
switch (actionType) {
|
||||
case UPDATED:
|
||||
PageLink pageLink = new PageLink(DEFAULT_PAGE_SIZE);
|
||||
PageData<Edge> pageData;
|
||||
List<ListenableFuture<Void>> futures = new ArrayList<>();
|
||||
do {
|
||||
pageData = edgeService.findEdgesByTenantIdAndCustomerId(tenantId, customerId, pageLink);
|
||||
if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) {
|
||||
for (Edge edge : pageData.getData()) {
|
||||
futures.add(saveEdgeEvent(tenantId, edge.getId(), type, actionType, customerId, null));
|
||||
}
|
||||
if (pageData.hasNext()) {
|
||||
pageLink = pageLink.nextPageLink();
|
||||
}
|
||||
}
|
||||
} while (pageData != null && pageData.hasNext());
|
||||
PageDataIterable<Edge> edges = new PageDataIterable<>(link -> edgeService.findEdgesByTenantIdAndCustomerId(tenantId, customerId, link), 1024);
|
||||
for (Edge edge : edges) {
|
||||
futures.add(saveEdgeEvent(tenantId, edge.getId(), type, actionType, customerId, null));
|
||||
}
|
||||
return Futures.transform(Futures.allAsList(futures), voids -> null, dbCallbackExecutorService);
|
||||
case DELETED:
|
||||
EdgeId edgeId = new EdgeId(new UUID(edgeNotificationMsg.getEdgeIdMSB(), edgeNotificationMsg.getEdgeIdLSB()));
|
||||
|
||||
@ -0,0 +1,63 @@
|
||||
/**
|
||||
* Copyright © 2016-2024 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.service.edge.rpc.processor.oauth2;
|
||||
|
||||
import com.google.common.util.concurrent.Futures;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.thingsboard.common.util.JacksonUtil;
|
||||
import org.thingsboard.server.common.data.EdgeUtils;
|
||||
import org.thingsboard.server.common.data.edge.EdgeEvent;
|
||||
import org.thingsboard.server.common.data.edge.EdgeEventActionType;
|
||||
import org.thingsboard.server.common.data.edge.EdgeEventType;
|
||||
import org.thingsboard.server.common.data.id.TenantId;
|
||||
import org.thingsboard.server.common.data.oauth2.OAuth2Info;
|
||||
import org.thingsboard.server.gen.edge.v1.DownlinkMsg;
|
||||
import org.thingsboard.server.gen.edge.v1.OAuth2UpdateMsg;
|
||||
import org.thingsboard.server.gen.transport.TransportProtos;
|
||||
import org.thingsboard.server.queue.util.TbCoreComponent;
|
||||
import org.thingsboard.server.service.edge.rpc.processor.BaseEdgeProcessor;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
@TbCoreComponent
|
||||
public class OAuth2EdgeProcessor extends BaseEdgeProcessor {
|
||||
|
||||
public DownlinkMsg convertOAuth2EventToDownlink(EdgeEvent edgeEvent) {
|
||||
DownlinkMsg downlinkMsg = null;
|
||||
OAuth2Info oAuth2Info = JacksonUtil.convertValue(edgeEvent.getBody(), OAuth2Info.class);
|
||||
if (oAuth2Info != null) {
|
||||
OAuth2UpdateMsg oAuth2UpdateMsg = oAuth2MsgConstructor.constructOAuth2UpdateMsg(oAuth2Info);
|
||||
downlinkMsg = DownlinkMsg.newBuilder()
|
||||
.setDownlinkMsgId(EdgeUtils.nextPositiveInt())
|
||||
.addOAuth2UpdateMsg(oAuth2UpdateMsg)
|
||||
.build();
|
||||
}
|
||||
return downlinkMsg;
|
||||
}
|
||||
|
||||
public ListenableFuture<Void> processOAuth2Notification(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) {
|
||||
OAuth2Info oAuth2Info = JacksonUtil.fromString(edgeNotificationMsg.getBody(), OAuth2Info.class);
|
||||
if (oAuth2Info == null) {
|
||||
return Futures.immediateFuture(null);
|
||||
}
|
||||
EdgeEventType type = EdgeEventType.valueOf(edgeNotificationMsg.getType());
|
||||
EdgeEventActionType actionType = EdgeEventActionType.valueOf(edgeNotificationMsg.getAction());
|
||||
return processActionForAllEdges(tenantId, type, actionType, null, JacksonUtil.toJsonNode(edgeNotificationMsg.getBody()), null);
|
||||
}
|
||||
|
||||
}
|
||||
@ -76,6 +76,7 @@ import org.thingsboard.server.gen.edge.v1.CustomerUpdateMsg;
|
||||
import org.thingsboard.server.gen.edge.v1.DeviceProfileUpdateMsg;
|
||||
import org.thingsboard.server.gen.edge.v1.DeviceUpdateMsg;
|
||||
import org.thingsboard.server.gen.edge.v1.EdgeVersion;
|
||||
import org.thingsboard.server.gen.edge.v1.OAuth2UpdateMsg;
|
||||
import org.thingsboard.server.gen.edge.v1.QueueUpdateMsg;
|
||||
import org.thingsboard.server.gen.edge.v1.RuleChainUpdateMsg;
|
||||
import org.thingsboard.server.gen.edge.v1.SyncCompletedMsg;
|
||||
@ -631,7 +632,7 @@ public class EdgeControllerTest extends AbstractControllerTest {
|
||||
|
||||
List<Edge> loadedEdges = new ArrayList<>();
|
||||
PageLink pageLink = new PageLink(23);
|
||||
PageData<Edge> pageData = null;
|
||||
PageData<Edge> pageData;
|
||||
do {
|
||||
pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/edges?",
|
||||
new TypeReference<>() {
|
||||
@ -885,6 +886,7 @@ public class EdgeControllerTest extends AbstractControllerTest {
|
||||
|
||||
EdgeImitator edgeImitator = new EdgeImitator(EDGE_HOST, EDGE_PORT, edge.getRoutingKey(), edge.getSecret());
|
||||
edgeImitator.ignoreType(UserCredentialsUpdateMsg.class);
|
||||
edgeImitator.ignoreType(OAuth2UpdateMsg.class);
|
||||
|
||||
edgeImitator.expectMessageAmount(24);
|
||||
edgeImitator.connect();
|
||||
@ -973,8 +975,7 @@ public class EdgeControllerTest extends AbstractControllerTest {
|
||||
|
||||
private boolean popQueueMsg(List<AbstractMessage> messages, UpdateMsgType msgType, String name) {
|
||||
for (AbstractMessage message : messages) {
|
||||
if (message instanceof QueueUpdateMsg) {
|
||||
QueueUpdateMsg queueUpdateMsg = (QueueUpdateMsg) message;
|
||||
if (message instanceof QueueUpdateMsg queueUpdateMsg) {
|
||||
Queue queue = JacksonUtil.fromString(queueUpdateMsg.getEntity(), Queue.class, true);
|
||||
Assert.assertNotNull(queue);
|
||||
if (msgType.equals(queueUpdateMsg.getMsgType()) && name.equals(queue.getName())) {
|
||||
@ -988,8 +989,7 @@ public class EdgeControllerTest extends AbstractControllerTest {
|
||||
|
||||
private boolean popRuleChainMsg(List<AbstractMessage> messages, UpdateMsgType msgType, String name) {
|
||||
for (AbstractMessage message : messages) {
|
||||
if (message instanceof RuleChainUpdateMsg) {
|
||||
RuleChainUpdateMsg ruleChainUpdateMsg = (RuleChainUpdateMsg) message;
|
||||
if (message instanceof RuleChainUpdateMsg ruleChainUpdateMsg) {
|
||||
RuleChain ruleChain = JacksonUtil.fromString(ruleChainUpdateMsg.getEntity(), RuleChain.class, true);
|
||||
Assert.assertNotNull(ruleChain);
|
||||
if (msgType.equals(ruleChainUpdateMsg.getMsgType())
|
||||
@ -1005,8 +1005,7 @@ public class EdgeControllerTest extends AbstractControllerTest {
|
||||
|
||||
private boolean popAdminSettingsMsg(List<AbstractMessage> messages, String key) {
|
||||
for (AbstractMessage message : messages) {
|
||||
if (message instanceof AdminSettingsUpdateMsg) {
|
||||
AdminSettingsUpdateMsg adminSettingsUpdateMsg = (AdminSettingsUpdateMsg) message;
|
||||
if (message instanceof AdminSettingsUpdateMsg adminSettingsUpdateMsg) {
|
||||
AdminSettings adminSettings = JacksonUtil.fromString(adminSettingsUpdateMsg.getEntity(), AdminSettings.class, true);
|
||||
Assert.assertNotNull(adminSettings);
|
||||
if (key.equals(adminSettings.getKey())) {
|
||||
@ -1020,8 +1019,7 @@ public class EdgeControllerTest extends AbstractControllerTest {
|
||||
|
||||
private boolean popDeviceProfileMsg(List<AbstractMessage> messages, UpdateMsgType msgType, String name) {
|
||||
for (AbstractMessage message : messages) {
|
||||
if (message instanceof DeviceProfileUpdateMsg) {
|
||||
DeviceProfileUpdateMsg deviceProfileUpdateMsg = (DeviceProfileUpdateMsg) message;
|
||||
if (message instanceof DeviceProfileUpdateMsg deviceProfileUpdateMsg) {
|
||||
DeviceProfile deviceProfile = JacksonUtil.fromString(deviceProfileUpdateMsg.getEntity(), DeviceProfile.class, true);
|
||||
Assert.assertNotNull(deviceProfile);
|
||||
if (msgType.equals(deviceProfileUpdateMsg.getMsgType())
|
||||
@ -1036,8 +1034,7 @@ public class EdgeControllerTest extends AbstractControllerTest {
|
||||
|
||||
private boolean popDeviceMsg(List<AbstractMessage> messages, UpdateMsgType msgType, String name) {
|
||||
for (AbstractMessage message : messages) {
|
||||
if (message instanceof DeviceUpdateMsg) {
|
||||
DeviceUpdateMsg deviceUpdateMsg = (DeviceUpdateMsg) message;
|
||||
if (message instanceof DeviceUpdateMsg deviceUpdateMsg) {
|
||||
Device device = JacksonUtil.fromString(deviceUpdateMsg.getEntity(), Device.class, true);
|
||||
Assert.assertNotNull(device);
|
||||
if (msgType.equals(deviceUpdateMsg.getMsgType())
|
||||
@ -1052,8 +1049,7 @@ public class EdgeControllerTest extends AbstractControllerTest {
|
||||
|
||||
private boolean popAssetProfileMsg(List<AbstractMessage> messages, UpdateMsgType msgType, String name) {
|
||||
for (AbstractMessage message : messages) {
|
||||
if (message instanceof AssetProfileUpdateMsg) {
|
||||
AssetProfileUpdateMsg assetProfileUpdateMsg = (AssetProfileUpdateMsg) message;
|
||||
if (message instanceof AssetProfileUpdateMsg assetProfileUpdateMsg) {
|
||||
AssetProfile assetProfile = JacksonUtil.fromString(assetProfileUpdateMsg.getEntity(), AssetProfile.class, true);
|
||||
Assert.assertNotNull(assetProfile);
|
||||
if (msgType.equals(assetProfileUpdateMsg.getMsgType())
|
||||
@ -1068,8 +1064,7 @@ public class EdgeControllerTest extends AbstractControllerTest {
|
||||
|
||||
private boolean popAssetMsg(List<AbstractMessage> messages, UpdateMsgType msgType, String name) {
|
||||
for (AbstractMessage message : messages) {
|
||||
if (message instanceof AssetUpdateMsg) {
|
||||
AssetUpdateMsg assetUpdateMsg = (AssetUpdateMsg) message;
|
||||
if (message instanceof AssetUpdateMsg assetUpdateMsg) {
|
||||
Asset asset = JacksonUtil.fromString(assetUpdateMsg.getEntity(), Asset.class, true);
|
||||
Assert.assertNotNull(asset);
|
||||
if (msgType.equals(assetUpdateMsg.getMsgType())
|
||||
@ -1084,8 +1079,7 @@ public class EdgeControllerTest extends AbstractControllerTest {
|
||||
|
||||
private boolean popUserMsg(List<AbstractMessage> messages, UpdateMsgType msgType, String email, Authority authority) {
|
||||
for (AbstractMessage message : messages) {
|
||||
if (message instanceof UserUpdateMsg) {
|
||||
UserUpdateMsg userUpdateMsg = (UserUpdateMsg) message;
|
||||
if (message instanceof UserUpdateMsg userUpdateMsg) {
|
||||
User user = JacksonUtil.fromString(userUpdateMsg.getEntity(), User.class, true);
|
||||
Assert.assertNotNull(user);
|
||||
if (msgType.equals(userUpdateMsg.getMsgType())
|
||||
@ -1101,8 +1095,7 @@ public class EdgeControllerTest extends AbstractControllerTest {
|
||||
|
||||
private boolean popCustomerMsg(List<AbstractMessage> messages, UpdateMsgType msgType, String title) {
|
||||
for (AbstractMessage message : messages) {
|
||||
if (message instanceof CustomerUpdateMsg) {
|
||||
CustomerUpdateMsg customerUpdateMsg = (CustomerUpdateMsg) message;
|
||||
if (message instanceof CustomerUpdateMsg customerUpdateMsg) {
|
||||
Customer customer = JacksonUtil.fromString(customerUpdateMsg.getEntity(), Customer.class, true);
|
||||
Assert.assertNotNull(customer);
|
||||
if (msgType.equals(customerUpdateMsg.getMsgType())
|
||||
@ -1117,8 +1110,7 @@ public class EdgeControllerTest extends AbstractControllerTest {
|
||||
|
||||
private boolean popTenantMsg(List<AbstractMessage> messages, TenantId tenantId1) {
|
||||
for (AbstractMessage message : messages) {
|
||||
if (message instanceof TenantUpdateMsg) {
|
||||
TenantUpdateMsg tenantUpdateMsg = (TenantUpdateMsg) message;
|
||||
if (message instanceof TenantUpdateMsg tenantUpdateMsg) {
|
||||
Tenant tenant = JacksonUtil.fromString(tenantUpdateMsg.getEntity(), Tenant.class, true);
|
||||
Assert.assertNotNull(tenant);
|
||||
if (UpdateMsgType.ENTITY_UPDATED_RPC_MESSAGE.equals(tenantUpdateMsg.getMsgType())
|
||||
@ -1133,8 +1125,7 @@ public class EdgeControllerTest extends AbstractControllerTest {
|
||||
|
||||
private boolean popTenantProfileMsg(List<AbstractMessage> messages, TenantProfileId tenantProfileId) {
|
||||
for (AbstractMessage message : messages) {
|
||||
if (message instanceof TenantProfileUpdateMsg) {
|
||||
TenantProfileUpdateMsg tenantProfileUpdateMsg = (TenantProfileUpdateMsg) message;
|
||||
if (message instanceof TenantProfileUpdateMsg tenantProfileUpdateMsg) {
|
||||
TenantProfile tenantProfile = JacksonUtil.fromString(tenantProfileUpdateMsg.getEntity(), TenantProfile.class, true);
|
||||
Assert.assertNotNull(tenantProfile);
|
||||
if (UpdateMsgType.ENTITY_UPDATED_RPC_MESSAGE.equals(tenantProfileUpdateMsg.getMsgType())
|
||||
@ -1236,4 +1227,5 @@ public class EdgeControllerTest extends AbstractControllerTest {
|
||||
edgeUpgradeInstructionsService.setAppVersion("3.6.2.6");
|
||||
Assert.assertTrue(edgeUpgradeInstructionsService.isUpgradeAvailable(savedEdge.getTenantId(), savedEdge.getId()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -494,7 +494,7 @@ public class HomePageApiTest extends AbstractControllerTest {
|
||||
}
|
||||
|
||||
private OAuth2Info createDefaultOAuth2Info() {
|
||||
return new OAuth2Info(true, Lists.newArrayList(
|
||||
return new OAuth2Info(true, false, Lists.newArrayList(
|
||||
OAuth2ParamsInfo.builder()
|
||||
.domainInfos(Lists.newArrayList(
|
||||
OAuth2DomainInfo.builder().name("domain").scheme(SchemeType.MIXED).build()
|
||||
|
||||
@ -63,6 +63,7 @@ import org.thingsboard.server.common.data.id.DeviceProfileId;
|
||||
import org.thingsboard.server.common.data.id.EdgeId;
|
||||
import org.thingsboard.server.common.data.id.RuleChainId;
|
||||
import org.thingsboard.server.common.data.id.TenantId;
|
||||
import org.thingsboard.server.common.data.oauth2.OAuth2Info;
|
||||
import org.thingsboard.server.common.data.ota.ChecksumAlgorithm;
|
||||
import org.thingsboard.server.common.data.ota.OtaPackageType;
|
||||
import org.thingsboard.server.common.data.page.PageData;
|
||||
@ -85,6 +86,7 @@ import org.thingsboard.server.gen.edge.v1.CustomerUpdateMsg;
|
||||
import org.thingsboard.server.gen.edge.v1.DeviceProfileUpdateMsg;
|
||||
import org.thingsboard.server.gen.edge.v1.DeviceUpdateMsg;
|
||||
import org.thingsboard.server.gen.edge.v1.EdgeConfiguration;
|
||||
import org.thingsboard.server.gen.edge.v1.OAuth2UpdateMsg;
|
||||
import org.thingsboard.server.gen.edge.v1.QueueUpdateMsg;
|
||||
import org.thingsboard.server.gen.edge.v1.RuleChainMetadataRequestMsg;
|
||||
import org.thingsboard.server.gen.edge.v1.RuleChainMetadataUpdateMsg;
|
||||
@ -140,6 +142,7 @@ abstract public class AbstractEdgeTest extends AbstractControllerTest {
|
||||
installation();
|
||||
|
||||
edgeImitator = new EdgeImitator("localhost", 7070, edge.getRoutingKey(), edge.getSecret());
|
||||
edgeImitator.ignoreType(OAuth2UpdateMsg.class);
|
||||
edgeImitator.expectMessageAmount(21);
|
||||
edgeImitator.connect();
|
||||
|
||||
@ -538,6 +541,18 @@ abstract public class AbstractEdgeTest extends AbstractControllerTest {
|
||||
Assert.assertTrue(customer.isPublic());
|
||||
}
|
||||
|
||||
private void validateOAuth2() throws Exception {
|
||||
Optional<OAuth2UpdateMsg> oAuth2UpdateMsgOpt = edgeImitator.findMessageByType(OAuth2UpdateMsg.class);
|
||||
Assert.assertTrue(oAuth2UpdateMsgOpt.isPresent());
|
||||
OAuth2UpdateMsg oAuth2UpdateMsg = oAuth2UpdateMsgOpt.get();
|
||||
OAuth2Info oAuth2Info = JacksonUtil.fromString(oAuth2UpdateMsg.getEntity(), OAuth2Info.class, true);
|
||||
Assert.assertNotNull(oAuth2Info);
|
||||
OAuth2Info auth2Info = doGet("/api/oauth2/config", OAuth2Info.class);
|
||||
Assert.assertNotNull(auth2Info);
|
||||
Assert.assertEquals(oAuth2Info, auth2Info);
|
||||
testAutoGeneratedCodeByProtobuf(oAuth2UpdateMsg);
|
||||
}
|
||||
|
||||
private void validateSyncCompleted() {
|
||||
Optional<SyncCompletedMsg> syncCompletedMsgOpt = edgeImitator.findMessageByType(SyncCompletedMsg.class);
|
||||
Assert.assertTrue(syncCompletedMsgOpt.isPresent());
|
||||
|
||||
@ -0,0 +1,113 @@
|
||||
/**
|
||||
* Copyright © 2016-2024 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.edge;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.protobuf.AbstractMessage;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.thingsboard.common.util.JacksonUtil;
|
||||
import org.thingsboard.server.common.data.oauth2.MapperType;
|
||||
import org.thingsboard.server.common.data.oauth2.OAuth2CustomMapperConfig;
|
||||
import org.thingsboard.server.common.data.oauth2.OAuth2DomainInfo;
|
||||
import org.thingsboard.server.common.data.oauth2.OAuth2Info;
|
||||
import org.thingsboard.server.common.data.oauth2.OAuth2MapperConfig;
|
||||
import org.thingsboard.server.common.data.oauth2.OAuth2ParamsInfo;
|
||||
import org.thingsboard.server.common.data.oauth2.OAuth2RegistrationInfo;
|
||||
import org.thingsboard.server.common.data.oauth2.SchemeType;
|
||||
import org.thingsboard.server.dao.service.DaoSqlTest;
|
||||
import org.thingsboard.server.gen.edge.v1.OAuth2UpdateMsg;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.UUID;
|
||||
|
||||
@DaoSqlTest
|
||||
public class OAuth2EdgeTest extends AbstractEdgeTest {
|
||||
|
||||
@Test
|
||||
public void testOAuth2Support() throws Exception {
|
||||
loginSysAdmin();
|
||||
|
||||
// enable oauth
|
||||
edgeImitator.allowIgnoredTypes();
|
||||
edgeImitator.expectMessageAmount(1);
|
||||
OAuth2Info oAuth2Info = createDefaultOAuth2Info();
|
||||
oAuth2Info = doPost("/api/oauth2/config", oAuth2Info, OAuth2Info.class);
|
||||
Assert.assertTrue(edgeImitator.waitForMessages());
|
||||
AbstractMessage latestMessage = edgeImitator.getLatestMessage();
|
||||
Assert.assertTrue(latestMessage instanceof OAuth2UpdateMsg);
|
||||
OAuth2UpdateMsg oAuth2UpdateMsg = (OAuth2UpdateMsg) latestMessage;
|
||||
OAuth2Info result = JacksonUtil.fromString(oAuth2UpdateMsg.getEntity(), OAuth2Info.class, true);
|
||||
Assert.assertEquals(oAuth2Info, result);
|
||||
|
||||
// disable oauth support
|
||||
edgeImitator.expectMessageAmount(1);
|
||||
oAuth2Info.setEnabled(false);
|
||||
oAuth2Info.setEdgeEnabled(false);
|
||||
doPost("/api/oauth2/config", oAuth2Info, OAuth2Info.class);
|
||||
Assert.assertTrue(edgeImitator.waitForMessages());
|
||||
latestMessage = edgeImitator.getLatestMessage();
|
||||
Assert.assertTrue(latestMessage instanceof OAuth2UpdateMsg);
|
||||
oAuth2UpdateMsg = (OAuth2UpdateMsg) latestMessage;
|
||||
result = JacksonUtil.fromString(oAuth2UpdateMsg.getEntity(), OAuth2Info.class, true);
|
||||
Assert.assertEquals(oAuth2Info, result);
|
||||
|
||||
edgeImitator.ignoreType(OAuth2UpdateMsg.class);
|
||||
loginTenantAdmin();
|
||||
}
|
||||
|
||||
private OAuth2Info createDefaultOAuth2Info() {
|
||||
return new OAuth2Info(true, true, Lists.newArrayList(
|
||||
OAuth2ParamsInfo.builder()
|
||||
.domainInfos(Lists.newArrayList(
|
||||
OAuth2DomainInfo.builder().name("domain").scheme(SchemeType.MIXED).build()
|
||||
))
|
||||
.mobileInfos(Collections.emptyList())
|
||||
.clientRegistrations(Lists.newArrayList(
|
||||
validRegistrationInfo()
|
||||
))
|
||||
.build()
|
||||
));
|
||||
}
|
||||
|
||||
private OAuth2RegistrationInfo validRegistrationInfo() {
|
||||
return OAuth2RegistrationInfo.builder()
|
||||
.clientId(UUID.randomUUID().toString())
|
||||
.clientSecret(UUID.randomUUID().toString())
|
||||
.authorizationUri(UUID.randomUUID().toString())
|
||||
.accessTokenUri(UUID.randomUUID().toString())
|
||||
.scope(Arrays.asList(UUID.randomUUID().toString(), UUID.randomUUID().toString()))
|
||||
.platforms(Collections.emptyList())
|
||||
.userInfoUri(UUID.randomUUID().toString())
|
||||
.userNameAttributeName(UUID.randomUUID().toString())
|
||||
.jwkSetUri(UUID.randomUUID().toString())
|
||||
.clientAuthenticationMethod(UUID.randomUUID().toString())
|
||||
.loginButtonLabel(UUID.randomUUID().toString())
|
||||
.mapperConfig(
|
||||
OAuth2MapperConfig.builder()
|
||||
.type(MapperType.CUSTOM)
|
||||
.custom(
|
||||
OAuth2CustomMapperConfig.builder()
|
||||
.url(UUID.randomUUID().toString())
|
||||
.build()
|
||||
)
|
||||
.build()
|
||||
)
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
@ -44,6 +44,7 @@ import org.thingsboard.server.gen.edge.v1.DownlinkResponseMsg;
|
||||
import org.thingsboard.server.gen.edge.v1.EdgeConfiguration;
|
||||
import org.thingsboard.server.gen.edge.v1.EntityDataProto;
|
||||
import org.thingsboard.server.gen.edge.v1.EntityViewUpdateMsg;
|
||||
import org.thingsboard.server.gen.edge.v1.OAuth2UpdateMsg;
|
||||
import org.thingsboard.server.gen.edge.v1.OtaPackageUpdateMsg;
|
||||
import org.thingsboard.server.gen.edge.v1.QueueUpdateMsg;
|
||||
import org.thingsboard.server.gen.edge.v1.RelationUpdateMsg;
|
||||
@ -314,6 +315,11 @@ public class EdgeImitator {
|
||||
result.add(saveDownlinkMsg(resourceUpdateMsg));
|
||||
}
|
||||
}
|
||||
if (downlinkMsg.getOAuth2UpdateMsgCount() > 0) {
|
||||
for (OAuth2UpdateMsg oAuth2UpdateMsg : downlinkMsg.getOAuth2UpdateMsgList()) {
|
||||
result.add(saveDownlinkMsg(oAuth2UpdateMsg));
|
||||
}
|
||||
}
|
||||
if (downlinkMsg.hasEdgeConfiguration()) {
|
||||
result.add(saveDownlinkMsg(downlinkMsg.getEdgeConfiguration()));
|
||||
}
|
||||
|
||||
@ -46,6 +46,7 @@ import org.thingsboard.server.dao.edge.EdgeEventService;
|
||||
import org.thingsboard.server.dao.edge.EdgeService;
|
||||
import org.thingsboard.server.dao.edge.EdgeSynchronizationManager;
|
||||
import org.thingsboard.server.dao.entityview.EntityViewService;
|
||||
import org.thingsboard.server.dao.oauth2.OAuth2Service;
|
||||
import org.thingsboard.server.dao.ota.OtaPackageService;
|
||||
import org.thingsboard.server.dao.queue.QueueService;
|
||||
import org.thingsboard.server.dao.relation.RelationService;
|
||||
@ -81,6 +82,7 @@ import org.thingsboard.server.service.edge.rpc.constructor.edge.EdgeMsgConstruct
|
||||
import org.thingsboard.server.service.edge.rpc.constructor.entityview.EntityViewMsgConstructorFactory;
|
||||
import org.thingsboard.server.service.edge.rpc.constructor.entityview.EntityViewMsgConstructorV1;
|
||||
import org.thingsboard.server.service.edge.rpc.constructor.entityview.EntityViewMsgConstructorV2;
|
||||
import org.thingsboard.server.service.edge.rpc.constructor.oauth2.OAuth2MsgConstructor;
|
||||
import org.thingsboard.server.service.edge.rpc.constructor.ota.OtaPackageMsgConstructorFactory;
|
||||
import org.thingsboard.server.service.edge.rpc.constructor.ota.OtaPackageMsgConstructorV1;
|
||||
import org.thingsboard.server.service.edge.rpc.constructor.ota.OtaPackageMsgConstructorV2;
|
||||
@ -128,6 +130,7 @@ import org.thingsboard.server.service.edge.rpc.processor.device.profile.DevicePr
|
||||
import org.thingsboard.server.service.edge.rpc.processor.entityview.EntityViewProcessorFactory;
|
||||
import org.thingsboard.server.service.edge.rpc.processor.entityview.EntityViewProcessorV1;
|
||||
import org.thingsboard.server.service.edge.rpc.processor.entityview.EntityViewProcessorV2;
|
||||
import org.thingsboard.server.service.edge.rpc.processor.oauth2.OAuth2EdgeProcessor;
|
||||
import org.thingsboard.server.service.edge.rpc.processor.relation.RelationEdgeProcessorFactory;
|
||||
import org.thingsboard.server.service.edge.rpc.processor.relation.RelationEdgeProcessorV1;
|
||||
import org.thingsboard.server.service.edge.rpc.processor.relation.RelationEdgeProcessorV2;
|
||||
@ -239,6 +242,9 @@ public abstract class BaseEdgeProcessorTest {
|
||||
@MockBean
|
||||
protected ResourceService resourceService;
|
||||
|
||||
@MockBean
|
||||
protected OAuth2Service oAuth2Service;
|
||||
|
||||
@MockBean
|
||||
@Lazy
|
||||
protected TbQueueProducerProvider producerProvider;
|
||||
@ -360,6 +366,9 @@ public abstract class BaseEdgeProcessorTest {
|
||||
@MockBean
|
||||
protected WidgetMsgConstructorV2 widgetMsgConstructorV2;
|
||||
|
||||
@MockBean
|
||||
protected OAuth2MsgConstructor oAuth2MsgConstructor;
|
||||
|
||||
@MockBean
|
||||
protected AlarmEdgeProcessorV1 alarmProcessorV1;
|
||||
|
||||
@ -417,6 +426,9 @@ public abstract class BaseEdgeProcessorTest {
|
||||
@MockBean
|
||||
protected RelationEdgeProcessorV2 relationEdgeProcessorV2;
|
||||
|
||||
@MockBean
|
||||
protected OAuth2EdgeProcessor oAuth2EdgeProcessor;
|
||||
|
||||
@SpyBean
|
||||
protected RuleChainMsgConstructorFactory ruleChainMsgConstructorFactory;
|
||||
|
||||
|
||||
@ -24,6 +24,7 @@ import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public interface OAuth2Service {
|
||||
|
||||
List<OAuth2ClientInfo> getOAuth2Clients(String domainScheme, String domainName, String pkgName, PlatformType platformType);
|
||||
|
||||
void saveOAuth2Info(OAuth2Info oauth2Info);
|
||||
|
||||
@ -41,7 +41,8 @@ public enum EdgeEventType {
|
||||
ADMIN_SETTINGS(true, null),
|
||||
OTA_PACKAGE(true, EntityType.OTA_PACKAGE),
|
||||
QUEUE(true, EntityType.QUEUE),
|
||||
TB_RESOURCE(true, EntityType.TB_RESOURCE);
|
||||
TB_RESOURCE(true, EntityType.TB_RESOURCE),
|
||||
OAUTH2(true, null);
|
||||
|
||||
private final boolean allEdgesRelated;
|
||||
|
||||
|
||||
@ -35,6 +35,8 @@ import java.util.List;
|
||||
public class OAuth2Info {
|
||||
@Schema(description = "Whether OAuth2 settings are enabled or not")
|
||||
private boolean enabled;
|
||||
@Schema(description = "Whether OAuth2 settings are enabled on Edge or not")
|
||||
private boolean edgeEnabled;
|
||||
@Schema(description = "List of configured OAuth2 clients. Cannot contain null values", required = true)
|
||||
private List<OAuth2ParamsInfo> oauth2ParamsInfos;
|
||||
}
|
||||
|
||||
@ -30,11 +30,13 @@ import org.thingsboard.server.common.data.id.TenantId;
|
||||
public class OAuth2Params extends BaseData<OAuth2ParamsId> {
|
||||
|
||||
private boolean enabled;
|
||||
private boolean edgeEnabled;
|
||||
private TenantId tenantId;
|
||||
|
||||
public OAuth2Params(OAuth2Params oauth2Params) {
|
||||
super(oauth2Params);
|
||||
this.enabled = oauth2Params.enabled;
|
||||
this.edgeEnabled = oauth2Params.edgeEnabled;
|
||||
this.tenantId = oauth2Params.tenantId;
|
||||
}
|
||||
}
|
||||
|
||||
@ -467,6 +467,10 @@ message ResourceUpdateMsg {
|
||||
string entity = 11;
|
||||
}
|
||||
|
||||
message OAuth2UpdateMsg {
|
||||
string entity = 1;
|
||||
}
|
||||
|
||||
message RuleChainMetadataRequestMsg {
|
||||
int64 ruleChainIdMSB = 1;
|
||||
int64 ruleChainIdLSB = 2;
|
||||
@ -668,5 +672,6 @@ message DownlinkMsg {
|
||||
repeated TenantProfileUpdateMsg tenantProfileUpdateMsg = 27;
|
||||
repeated ResourceUpdateMsg resourceUpdateMsg = 28;
|
||||
repeated AlarmCommentUpdateMsg alarmCommentUpdateMsg = 29;
|
||||
repeated OAuth2UpdateMsg oAuth2UpdateMsg = 30;
|
||||
}
|
||||
|
||||
|
||||
@ -427,6 +427,7 @@ public class ModelConstants {
|
||||
*/
|
||||
public static final String OAUTH2_PARAMS_TABLE_NAME = "oauth2_params";
|
||||
public static final String OAUTH2_PARAMS_ENABLED_PROPERTY = "enabled";
|
||||
public static final String OAUTH2_PARAMS_EDGE_ENABLED_PROPERTY = "edge_enabled";
|
||||
public static final String OAUTH2_PARAMS_TENANT_ID_PROPERTY = TENANT_ID_PROPERTY;
|
||||
|
||||
public static final String OAUTH2_REGISTRATION_TABLE_NAME = "oauth2_registration";
|
||||
|
||||
@ -39,6 +39,9 @@ public class OAuth2ParamsEntity extends BaseSqlEntity<OAuth2Params> {
|
||||
@Column(name = ModelConstants.OAUTH2_PARAMS_ENABLED_PROPERTY)
|
||||
private Boolean enabled;
|
||||
|
||||
@Column(name = ModelConstants.OAUTH2_PARAMS_EDGE_ENABLED_PROPERTY)
|
||||
private Boolean edgeEnabled;
|
||||
|
||||
@Column(name = ModelConstants.OAUTH2_PARAMS_TENANT_ID_PROPERTY)
|
||||
private UUID tenantId;
|
||||
|
||||
@ -48,6 +51,7 @@ public class OAuth2ParamsEntity extends BaseSqlEntity<OAuth2Params> {
|
||||
}
|
||||
this.setCreatedTime(oauth2Params.getCreatedTime());
|
||||
this.enabled = oauth2Params.isEnabled();
|
||||
this.edgeEnabled = oauth2Params.isEdgeEnabled();
|
||||
if (oauth2Params.getTenantId() != null) {
|
||||
this.tenantId = oauth2Params.getTenantId().getId();
|
||||
}
|
||||
@ -60,6 +64,7 @@ public class OAuth2ParamsEntity extends BaseSqlEntity<OAuth2Params> {
|
||||
oauth2Params.setCreatedTime(createdTime);
|
||||
oauth2Params.setTenantId(TenantId.fromUUID(tenantId));
|
||||
oauth2Params.setEnabled(enabled);
|
||||
oauth2Params.setEdgeEnabled(edgeEnabled);
|
||||
return oauth2Params;
|
||||
}
|
||||
}
|
||||
|
||||
@ -40,6 +40,7 @@ import org.thingsboard.server.common.data.oauth2.PlatformType;
|
||||
import org.thingsboard.server.common.data.oauth2.SchemeType;
|
||||
import org.thingsboard.server.common.data.oauth2.TenantNameStrategyType;
|
||||
import org.thingsboard.server.dao.entity.AbstractEntityService;
|
||||
import org.thingsboard.server.dao.eventsourcing.SaveEntityEvent;
|
||||
import org.thingsboard.server.dao.exception.DataValidationException;
|
||||
import org.thingsboard.server.dao.exception.IncorrectParameterException;
|
||||
|
||||
@ -58,6 +59,7 @@ import static org.thingsboard.server.dao.service.Validator.validateString;
|
||||
@Slf4j
|
||||
@Service
|
||||
public class OAuth2ServiceImpl extends AbstractEntityService implements OAuth2Service {
|
||||
|
||||
public static final String INCORRECT_TENANT_ID = "Incorrect tenantId ";
|
||||
public static final String INCORRECT_CLIENT_REGISTRATION_ID = "Incorrect clientRegistrationId ";
|
||||
public static final String INCORRECT_DOMAIN_NAME = "Incorrect domainName ";
|
||||
@ -116,6 +118,7 @@ public class OAuth2ServiceImpl extends AbstractEntityService implements OAuth2Se
|
||||
});
|
||||
}
|
||||
});
|
||||
eventPublisher.publishEvent(SaveEntityEvent.builder().tenantId(TenantId.SYS_TENANT_ID).entity(oauth2Info).build());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -123,7 +126,8 @@ public class OAuth2ServiceImpl extends AbstractEntityService implements OAuth2Se
|
||||
log.trace("Executing findOAuth2Info");
|
||||
OAuth2Info oauth2Info = new OAuth2Info();
|
||||
List<OAuth2Params> oauth2ParamsList = oauth2ParamsDao.find(TenantId.SYS_TENANT_ID);
|
||||
oauth2Info.setEnabled(oauth2ParamsList.stream().anyMatch(param -> param.isEnabled()));
|
||||
oauth2Info.setEnabled(oauth2ParamsList.stream().anyMatch(OAuth2Params::isEnabled));
|
||||
oauth2Info.setEdgeEnabled(oauth2ParamsList.stream().anyMatch(OAuth2Params::isEdgeEnabled));
|
||||
List<OAuth2ParamsInfo> oauth2ParamsInfos = new ArrayList<>();
|
||||
oauth2Info.setOauth2ParamsInfos(oauth2ParamsInfos);
|
||||
oauth2ParamsList.stream().sorted(Comparator.comparing(BaseData::getUuidId)).forEach(oauth2Params -> {
|
||||
|
||||
@ -88,6 +88,7 @@ public class OAuth2Utils {
|
||||
public static OAuth2Params infoToOAuth2Params(OAuth2Info oauth2Info) {
|
||||
OAuth2Params oauth2Params = new OAuth2Params();
|
||||
oauth2Params.setEnabled(oauth2Info.isEnabled());
|
||||
oauth2Params.setEdgeEnabled(oauth2Info.isEdgeEnabled());
|
||||
oauth2Params.setTenantId(TenantId.SYS_TENANT_ID);
|
||||
return oauth2Params;
|
||||
}
|
||||
|
||||
@ -559,6 +559,7 @@ CREATE TABLE IF NOT EXISTS key_dictionary
|
||||
CREATE TABLE IF NOT EXISTS oauth2_params (
|
||||
id uuid NOT NULL CONSTRAINT oauth2_params_pkey PRIMARY KEY,
|
||||
enabled boolean,
|
||||
edge_enabled boolean,
|
||||
tenant_id uuid,
|
||||
created_time bigint NOT NULL
|
||||
);
|
||||
|
||||
@ -47,7 +47,7 @@ import java.util.stream.Collectors;
|
||||
|
||||
@DaoSqlTest
|
||||
public class OAuth2ServiceTest extends AbstractServiceTest {
|
||||
private static final OAuth2Info EMPTY_PARAMS = new OAuth2Info(false, Collections.emptyList());
|
||||
private static final OAuth2Info EMPTY_PARAMS = new OAuth2Info(false, false, Collections.emptyList());
|
||||
|
||||
@Autowired
|
||||
protected OAuth2Service oAuth2Service;
|
||||
@ -66,7 +66,7 @@ public class OAuth2ServiceTest extends AbstractServiceTest {
|
||||
|
||||
@Test
|
||||
public void testSaveHttpAndMixedDomainsTogether() {
|
||||
OAuth2Info oAuth2Info = new OAuth2Info(true, Lists.newArrayList(
|
||||
OAuth2Info oAuth2Info = new OAuth2Info(true, false, Lists.newArrayList(
|
||||
OAuth2ParamsInfo.builder()
|
||||
.domainInfos(Lists.newArrayList(
|
||||
OAuth2DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTP).build(),
|
||||
@ -87,7 +87,7 @@ public class OAuth2ServiceTest extends AbstractServiceTest {
|
||||
|
||||
@Test
|
||||
public void testSaveHttpsAndMixedDomainsTogether() {
|
||||
OAuth2Info oAuth2Info = new OAuth2Info(true, Lists.newArrayList(
|
||||
OAuth2Info oAuth2Info = new OAuth2Info(true, false, Lists.newArrayList(
|
||||
OAuth2ParamsInfo.builder()
|
||||
.domainInfos(Lists.newArrayList(
|
||||
OAuth2DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTPS).build(),
|
||||
@ -153,7 +153,7 @@ public class OAuth2ServiceTest extends AbstractServiceTest {
|
||||
Assert.assertNotNull(foundOAuth2Info);
|
||||
Assert.assertEquals(oAuth2Info, foundOAuth2Info);
|
||||
|
||||
OAuth2Info newOAuth2Info = new OAuth2Info(true, Lists.newArrayList(
|
||||
OAuth2Info newOAuth2Info = new OAuth2Info(true, false, Lists.newArrayList(
|
||||
OAuth2ParamsInfo.builder()
|
||||
.domainInfos(Lists.newArrayList(
|
||||
OAuth2DomainInfo.builder().name("another-domain").scheme(SchemeType.HTTPS).build()
|
||||
@ -194,7 +194,7 @@ public class OAuth2ServiceTest extends AbstractServiceTest {
|
||||
List<OAuth2RegistrationInfo> thirdGroup = Lists.newArrayList(
|
||||
validRegistrationInfo()
|
||||
);
|
||||
OAuth2Info oAuth2Info = new OAuth2Info(true, Lists.newArrayList(
|
||||
OAuth2Info oAuth2Info = new OAuth2Info(true, false, Lists.newArrayList(
|
||||
OAuth2ParamsInfo.builder()
|
||||
.domainInfos(Lists.newArrayList(
|
||||
OAuth2DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTP).build(),
|
||||
@ -318,7 +318,7 @@ public class OAuth2ServiceTest extends AbstractServiceTest {
|
||||
validRegistrationInfo(),
|
||||
validRegistrationInfo()
|
||||
);
|
||||
OAuth2Info oAuth2Info = new OAuth2Info(true, Lists.newArrayList(
|
||||
OAuth2Info oAuth2Info = new OAuth2Info(true, false, Lists.newArrayList(
|
||||
OAuth2ParamsInfo.builder()
|
||||
.domainInfos(Lists.newArrayList(
|
||||
OAuth2DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTP).build(),
|
||||
@ -363,7 +363,7 @@ public class OAuth2ServiceTest extends AbstractServiceTest {
|
||||
|
||||
@Test
|
||||
public void testGetDisabledOAuth2Clients() {
|
||||
OAuth2Info oAuth2Info = new OAuth2Info(true, Lists.newArrayList(
|
||||
OAuth2Info oAuth2Info = new OAuth2Info(true, false, Lists.newArrayList(
|
||||
OAuth2ParamsInfo.builder()
|
||||
.domainInfos(Lists.newArrayList(
|
||||
OAuth2DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTP).build(),
|
||||
@ -402,7 +402,7 @@ public class OAuth2ServiceTest extends AbstractServiceTest {
|
||||
|
||||
@Test
|
||||
public void testFindAllRegistrations() {
|
||||
OAuth2Info oAuth2Info = new OAuth2Info(true, Lists.newArrayList(
|
||||
OAuth2Info oAuth2Info = new OAuth2Info(true, false, Lists.newArrayList(
|
||||
OAuth2ParamsInfo.builder()
|
||||
.domainInfos(Lists.newArrayList(
|
||||
OAuth2DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTP).build(),
|
||||
@ -451,7 +451,7 @@ public class OAuth2ServiceTest extends AbstractServiceTest {
|
||||
|
||||
@Test
|
||||
public void testFindRegistrationById() {
|
||||
OAuth2Info oAuth2Info = new OAuth2Info(true, Lists.newArrayList(
|
||||
OAuth2Info oAuth2Info = new OAuth2Info(true, false, Lists.newArrayList(
|
||||
OAuth2ParamsInfo.builder()
|
||||
.domainInfos(Lists.newArrayList(
|
||||
OAuth2DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTP).build(),
|
||||
@ -495,7 +495,7 @@ public class OAuth2ServiceTest extends AbstractServiceTest {
|
||||
|
||||
@Test
|
||||
public void testFindAppSecret() {
|
||||
OAuth2Info oAuth2Info = new OAuth2Info(true, Lists.newArrayList(
|
||||
OAuth2Info oAuth2Info = new OAuth2Info(true, false, Lists.newArrayList(
|
||||
OAuth2ParamsInfo.builder()
|
||||
.domainInfos(Lists.newArrayList(
|
||||
OAuth2DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTP).build(),
|
||||
@ -547,7 +547,7 @@ public class OAuth2ServiceTest extends AbstractServiceTest {
|
||||
|
||||
@Test
|
||||
public void testFindClientsByPackageAndPlatform() {
|
||||
OAuth2Info oAuth2Info = new OAuth2Info(true, Lists.newArrayList(
|
||||
OAuth2Info oAuth2Info = new OAuth2Info(true, false, Lists.newArrayList(
|
||||
OAuth2ParamsInfo.builder()
|
||||
.domainInfos(Lists.newArrayList(
|
||||
OAuth2DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTP).build(),
|
||||
@ -596,7 +596,7 @@ public class OAuth2ServiceTest extends AbstractServiceTest {
|
||||
}
|
||||
|
||||
private OAuth2Info createDefaultOAuth2Info() {
|
||||
return new OAuth2Info(true, Lists.newArrayList(
|
||||
return new OAuth2Info(true, false, Lists.newArrayList(
|
||||
OAuth2ParamsInfo.builder()
|
||||
.domainInfos(Lists.newArrayList(
|
||||
OAuth2DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTP).build(),
|
||||
@ -664,4 +664,5 @@ public class OAuth2ServiceTest extends AbstractServiceTest {
|
||||
.appSecret(appSecret != null ? appSecret : StringUtils.randomAlphanumeric(24))
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -29,13 +29,18 @@
|
||||
<div style="height: 4px;" *ngIf="!(isLoading$ | async)"></div>
|
||||
<mat-card-content style="padding-top: 16px;">
|
||||
<form [formGroup]="oauth2SettingsForm" (ngSubmit)="save()">
|
||||
<fieldset [disabled]="isLoading$ | async">
|
||||
<mat-checkbox formControlName="enabled">
|
||||
{{ 'admin.oauth2.enable' | translate }}
|
||||
</mat-checkbox>
|
||||
<section *ngIf="oauth2SettingsForm.get('enabled').value" style="margin-top: 1em;">
|
||||
<fieldset class="tb-form-panel stroked gap-xs-12" style="margin-bottom: 16px" [disabled]="isLoading$ | async">
|
||||
<div class="tb-form-row no-border no-padding column-xs">
|
||||
<mat-chip-listbox formControlName="enabled">
|
||||
<mat-chip-option [value]="true">{{ 'admin.oauth2.enable' | translate }}</mat-chip-option>
|
||||
</mat-chip-listbox>
|
||||
<mat-chip-listbox formControlName="edgeEnabled">
|
||||
<mat-chip-option [value]="true">{{ 'admin.oauth2.edge-enable' | translate }}</mat-chip-option>
|
||||
</mat-chip-listbox>
|
||||
</div>
|
||||
<section *ngIf="oauth2SettingsForm.get('enabled').value && oauth2ParamsInfos.controls.length">
|
||||
<ng-container formArrayName="oauth2ParamsInfos">
|
||||
<div class="container">
|
||||
<div>
|
||||
<mat-accordion multi>
|
||||
<ng-container *ngFor="let oauth2ParamsInfo of oauth2ParamsInfos.controls; let i = index; trackBy: trackByItem">
|
||||
<mat-expansion-panel [formGroupName]="i">
|
||||
|
||||
@ -13,7 +13,20 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
@import '../../../../../scss/constants';
|
||||
|
||||
:host{
|
||||
.gap-xs-12 {
|
||||
@media #{$mat-xs} {
|
||||
gap: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.mdc-evolution-chip-set .mdc-evolution-chip {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.checkbox-row {
|
||||
margin-top: 1em;
|
||||
}
|
||||
@ -31,7 +44,7 @@
|
||||
}
|
||||
|
||||
.container{
|
||||
margin-bottom: 1em;
|
||||
margin-bottom: 16px;
|
||||
|
||||
.tb-highlight{
|
||||
margin: 0;
|
||||
|
||||
@ -204,13 +204,23 @@ export class OAuth2SettingsComponent extends PageComponent implements OnInit, Ha
|
||||
private buildOAuth2SettingsForm(): void {
|
||||
this.oauth2SettingsForm = this.fb.group({
|
||||
oauth2ParamsInfos: this.fb.array([]),
|
||||
enabled: [false]
|
||||
enabled: [false],
|
||||
edgeEnabled: [{value: false, disabled: true}]
|
||||
});
|
||||
|
||||
this.subscriptions.push(this.oauth2SettingsForm.get('enabled').valueChanges.subscribe(enabled => {
|
||||
if (enabled) {
|
||||
this.oauth2SettingsForm.get('edgeEnabled').enable();
|
||||
} else {
|
||||
this.oauth2SettingsForm.get('edgeEnabled').patchValue(false);
|
||||
this.oauth2SettingsForm.get('edgeEnabled').disable();
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
private initOAuth2Settings(oauth2Info: OAuth2Info): void {
|
||||
if (oauth2Info) {
|
||||
this.oauth2SettingsForm.patchValue({enabled: oauth2Info.enabled}, {emitEvent: false});
|
||||
this.oauth2SettingsForm.patchValue({enabled: oauth2Info.enabled, edgeEnabled: oauth2Info.edgeEnabled});
|
||||
oauth2Info.oauth2ParamsInfos.forEach((oauth2ParamsInfo) => {
|
||||
this.oauth2ParamsInfos.push(this.buildOAuth2ParamsInfoForm(oauth2ParamsInfo));
|
||||
});
|
||||
|
||||
@ -18,6 +18,7 @@ import { HasUUID } from '@shared/models/id/has-uuid';
|
||||
|
||||
export interface OAuth2Info {
|
||||
enabled: boolean;
|
||||
edgeEnabled: boolean;
|
||||
oauth2ParamsInfos: OAuth2ParamsInfo[];
|
||||
}
|
||||
|
||||
|
||||
@ -283,6 +283,7 @@
|
||||
"domain-schema-https": "HTTPS",
|
||||
"domain-schema-mixed": "HTTP+HTTPS",
|
||||
"enable": "Enable OAuth2 settings",
|
||||
"edge-enable": "Propagate to Edge",
|
||||
"domains": "Domains",
|
||||
"mobile-apps": "Mobile applications",
|
||||
"no-mobile-apps": "No applications configured",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user