rpcSubscriptionsToRemove = rpcSubscriptions.entrySet().stream().filter(kv -> System.currentTimeMillis() > kv.getValue()).map(Map.Entry::getKey).collect(Collectors.toSet());
+ log.warn("4.2) System.currentTimeMillis(): [{}]", System.currentTimeMillis());
+ log.warn("4.3) rpcSubscriptionsToRemove: [{}]", rpcSubscriptionsToRemove);
+ rpcSubscriptionsToRemove.forEach(rpcSubscriptions::remove);
+ }
+ log.warn("4.4) after rpcSubscriptions.size(): [{}]", rpcSubscriptions.size());
}
- public void sentRpcResponse(Lwm2mClientRpcRequest rpcRequest, String requestCode, String msg, String typeMsg) {
+ public void sentRpcResponse(LwM2mClientRpcRequest rpcRequest, String requestCode, String msg, String typeMsg) {
rpcRequest.setResponseCode(requestCode);
if (LOG_LW2M_ERROR.equals(typeMsg)) {
rpcRequest.setInfoMsg(null);
@@ -519,17 +539,6 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
log.info("[{}] toServerRpcResponse", toServerResponse);
}
- /**
- * Trigger Server path = "/1/0/8"
- *
- * Trigger bootStrap path = "/1/0/9" - have to implemented on client
- */
- @Override
- public void doTrigger(Registration registration, String path) {
- lwM2mTransportRequest.sendAllRequest(registration, path, EXECUTE,
- ContentFormat.TLV.getName(), null, this.config.getTimeout(), null);
- }
-
/**
* Deregister session in transport
*
@@ -572,7 +581,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
* @param registrationId - Id of Registration LwM2M Client
*/
@Override
- public void sendLogsToThingsboard2(String registrationId, String logMsg) {
+ public void sendLogsToThingsboard(String registrationId, String logMsg) {
sendLogsToThingsboard(clientContext.getClientByRegistrationId(registrationId), logMsg);
}
@@ -595,24 +604,23 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
* - Read Request to the client after registration to read all resource values for all objects
* - then Observe Request to the client marked as observe from the profile configuration.
*
- * @param registration - Registration LwM2M Client
- * @param lwM2MClient - object with All parameters off client
+ * @param lwM2MClient - object with All parameters off client
*/
- private void initLwM2mFromClientValue(Registration registration, LwM2mClient lwM2MClient) {
- LwM2mClientProfile lwM2MClientProfile = clientContext.getProfile(registration);
- Set clientObjects = clientContext.getSupportedIdVerInClient(registration);
+ private void initClientTelemetry(LwM2mClient lwM2MClient) {
+ LwM2mClientProfile lwM2MClientProfile = clientContext.getProfile(lwM2MClient.getProfileId());
+ Set clientObjects = clientContext.getSupportedIdVerInClient(lwM2MClient);
if (clientObjects != null && clientObjects.size() > 0) {
- if (LWM2M_STRATEGY_2 == LwM2mTransportUtil.getClientOnlyObserveAfterConnect(lwM2MClientProfile)) {
+ if (LwM2mTransportUtil.LwM2MClientStrategy.CLIENT_STRATEGY_2.code == lwM2MClientProfile.getClientStrategy()) {
// #2
lwM2MClient.getPendingReadRequests().addAll(clientObjects);
- clientObjects.forEach(path -> lwM2mTransportRequest.sendAllRequest(registration, path, READ, ContentFormat.TLV.getName(),
+ clientObjects.forEach(path -> lwM2mTransportRequest.sendAllRequest(lwM2MClient, path, READ,
null, this.config.getTimeout(), null));
}
// #1
- this.initReadAttrTelemetryObserveToClient(registration, lwM2MClient, READ, clientObjects);
- this.initReadAttrTelemetryObserveToClient(registration, lwM2MClient, OBSERVE, clientObjects);
- this.initReadAttrTelemetryObserveToClient(registration, lwM2MClient, WRITE_ATTRIBUTES, clientObjects);
- this.initReadAttrTelemetryObserveToClient(registration, lwM2MClient, DISCOVER, clientObjects);
+ this.initReadAttrTelemetryObserveToClient(lwM2MClient, READ, clientObjects);
+ this.initReadAttrTelemetryObserveToClient(lwM2MClient, OBSERVE, clientObjects);
+ this.initReadAttrTelemetryObserveToClient(lwM2MClient, WRITE_ATTRIBUTES, clientObjects);
+ this.initReadAttrTelemetryObserveToClient(lwM2MClient, DISCOVER, clientObjects);
}
}
@@ -659,60 +667,18 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
/** version != null
* set setClient_fw_info... = value
**/
- if (lwM2MClient.getFwUpdate().isInfoFwSwUpdate()) {
+ if (lwM2MClient.getFwUpdate() != null && lwM2MClient.getFwUpdate().isInfoFwSwUpdate()) {
lwM2MClient.getFwUpdate().initReadValue(this, this.lwM2mTransportRequest, path);
}
- if (lwM2MClient.getSwUpdate().isInfoFwSwUpdate()) {
+ if (lwM2MClient.getSwUpdate() != null && lwM2MClient.getSwUpdate().isInfoFwSwUpdate()) {
lwM2MClient.getSwUpdate().initReadValue(this, this.lwM2mTransportRequest, path);
}
- /**
- * Before operation Execute (FwUpdate) inspection Update Result :
- * - after finished operation Write result: success (FwUpdate): fw_state = DOWNLOADED
- * - before start operation Execute (FwUpdate) Update Result = 0 - Initial value
- * - start Execute (FwUpdate)
- * After finished operation Execute (FwUpdate) inspection Update Result :
- * - after start operation Execute (FwUpdate): fw_state = UPDATING
- * - after success finished operation Execute (FwUpdate) Update Result == 1 ("Firmware updated successfully")
- * - finished operation Execute (FwUpdate)
- */
- if (lwM2MClient.getFwUpdate() != null
- && (convertPathFromObjectIdToIdVer(FW_RESULT_ID, registration).equals(path))) {
- if (DOWNLOADED.name().equals(lwM2MClient.getFwUpdate().getStateUpdate())
- && lwM2MClient.getFwUpdate().conditionalFwExecuteStart()) {
- lwM2MClient.getFwUpdate().executeFwSwWare(this, this.lwM2mTransportRequest);
- } else if (UPDATING.name().equals(lwM2MClient.getFwUpdate().getStateUpdate())
- && lwM2MClient.getFwUpdate().conditionalFwExecuteAfterSuccess()) {
- lwM2MClient.getFwUpdate().finishFwSwUpdate(this, true);
- } else if (UPDATING.name().equals(lwM2MClient.getFwUpdate().getStateUpdate())
- && lwM2MClient.getFwUpdate().conditionalFwExecuteAfterError()) {
- lwM2MClient.getFwUpdate().finishFwSwUpdate(this, false);
- }
- }
-
- /**
- * Before operation Execute (SwUpdate) inspection Update Result :
- * - after finished operation Write result: success (SwUpdate): fw_state = DOWNLOADED
- * - before operation Execute (SwUpdate) Update Result = 3 - Successfully Downloaded and package integrity verified
- * - start Execute (SwUpdate)
- * After finished operation Execute (SwUpdate) inspection Update Result :
- * - after start operation Execute (SwUpdate): fw_state = UPDATING
- * - after success finished operation Execute (SwUpdate) Update Result == 2 "Software successfully installed.""
- * - after success finished operation Execute (SwUpdate) Update Result == 2 "Software successfully installed.""
- * - finished operation Execute (SwUpdate)
- */
- if (lwM2MClient.getSwUpdate() != null
- && (convertPathFromObjectIdToIdVer(SW_RESULT_ID, registration).equals(path))) {
- if (DOWNLOADED.name().equals(lwM2MClient.getSwUpdate().getStateUpdate())
- && lwM2MClient.getSwUpdate().conditionalSwUpdateExecute()) {
- lwM2MClient.getSwUpdate().executeFwSwWare(this, this.lwM2mTransportRequest);
- } else if (UPDATING.name().equals(lwM2MClient.getSwUpdate().getStateUpdate())
- && lwM2MClient.getSwUpdate().conditionalSwExecuteAfterSuccess()) {
- lwM2MClient.getSwUpdate().finishFwSwUpdate(this, true);
- } else if (UPDATING.name().equals(lwM2MClient.getSwUpdate().getStateUpdate())
- && lwM2MClient.getSwUpdate().conditionalSwExecuteAfterError()) {
- lwM2MClient.getSwUpdate().finishFwSwUpdate(this, false);
- }
+ if ((convertPathFromObjectIdToIdVer(FW_RESULT_ID, registration).equals(path)) ||
+ (convertPathFromObjectIdToIdVer(FW_STATE_ID, registration).equals(path))) {
+ LwM2mFwSwUpdate fwUpdate = lwM2MClient.getFwUpdate(clientContext);
+ log.warn("93) path: [{}] value: [{}]", path, lwM2mResource.getValue());
+ fwUpdate.updateStateOta(this, lwM2mTransportRequest, registration, path, ((Long) lwM2mResource.getValue()).intValue());
}
Set paths = new HashSet<>();
paths.add(path);
@@ -749,15 +715,8 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
}
}
- /**
- * Start observe/read: Attr/Telemetry
- * #1 - Analyze: path in resource profile == client resource
- *
- * @param registration -
- */
- private void initReadAttrTelemetryObserveToClient(Registration registration, LwM2mClient lwM2MClient,
- LwM2mTypeOper typeOper, Set clientObjects) {
- LwM2mClientProfile lwM2MClientProfile = clientContext.getProfile(registration);
+ private void initReadAttrTelemetryObserveToClient(LwM2mClient lwM2MClient, LwM2mTypeOper typeOper, Set clientObjects) {
+ LwM2mClientProfile lwM2MClientProfile = clientContext.getProfile(lwM2MClient.getProfileId());
Set result = null;
ConcurrentHashMap params = null;
if (READ.equals(typeOper)) {
@@ -777,28 +736,42 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
params = this.getPathForWriteAttributes(lwM2MClientProfile.getPostAttributeLwm2mProfile());
result = params.keySet();
}
- if (result != null && !result.isEmpty()) {
- // #1
- Set pathSend = result.stream().filter(target -> {
- return target.split(LWM2M_SEPARATOR_PATH).length < 3 ?
- clientObjects.contains("/" + target.split(LWM2M_SEPARATOR_PATH)[1]) :
- clientObjects.contains("/" + target.split(LWM2M_SEPARATOR_PATH)[1] + "/" + target.split(LWM2M_SEPARATOR_PATH)[2]);
- }
+ sendRequestsToClient(lwM2MClient, typeOper, clientObjects, result, params);
+ }
+
+ private void sendRequestsToClient(LwM2mClient lwM2MClient, LwM2mTypeOper operationType, Set supportedObjectIds, Set desiredObjectIds, ConcurrentHashMap params) {
+ if (desiredObjectIds != null && !desiredObjectIds.isEmpty()) {
+ Set targetObjectIds = desiredObjectIds.stream().filter(target -> isSupportedTargetId(supportedObjectIds, target)
).collect(Collectors.toUnmodifiableSet());
- if (!pathSend.isEmpty()) {
- lwM2MClient.getPendingReadRequests().addAll(pathSend);
- ConcurrentHashMap finalParams = params;
- pathSend.forEach(target -> {
- lwM2mTransportRequest.sendAllRequest(registration, target, typeOper, ContentFormat.TEXT.getName(),
- finalParams != null ? finalParams.get(target) : null, this.config.getTimeout(), null);
+ if (!targetObjectIds.isEmpty()) {
+ //TODO: remove this side effect?
+ lwM2MClient.getPendingReadRequests().addAll(targetObjectIds);
+ targetObjectIds.forEach(target -> {
+ Object additionalParams = params != null ? params.get(target) : null;
+ lwM2mTransportRequest.sendAllRequest(lwM2MClient, target, operationType, additionalParams, this.config.getTimeout(), null);
});
- if (OBSERVE.equals(typeOper)) {
+ if (OBSERVE.equals(operationType)) {
lwM2MClient.initReadValue(this, null);
}
}
}
}
+ private boolean isSupportedTargetId(Set supportedIds, String targetId) {
+ String[] targetIdParts = targetId.split(LWM2M_SEPARATOR_PATH);
+ if (targetIdParts.length <= 1) {
+ return false;
+ }
+ String targetIdSearch = targetIdParts[0];
+ for (int i = 1; i < targetIdParts.length; i++) {
+ targetIdSearch += "/" + targetIdParts[i];
+ if (supportedIds.contains(targetIdSearch)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
private ConcurrentHashMap getPathForWriteAttributes(JsonObject objectJson) {
ConcurrentHashMap pathAttributes = new Gson().fromJson(objectJson.toString(),
new TypeToken>() {
@@ -867,8 +840,9 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
valueKvProto = new JsonObject();
Object finalvalueKvProto = valueKvProto;
Gson gson = new GsonBuilder().create();
+ ResourceModel.Type finalCurrentType = currentType;
resourceValue.getInstances().forEach((k, v) -> {
- Object val = this.converter.convertValue(v, currentType, expectedType,
+ Object val = this.converter.convertValue(v, finalCurrentType, expectedType,
new LwM2mPath(convertPathFromIdVerToObjectId(pathIdVer)));
JsonElement element = gson.toJsonTree(val, val.getClass());
((JsonObject) finalvalueKvProto).add(String.valueOf(k), element);
@@ -878,6 +852,9 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
valueKvProto = this.converter.convertValue(resourceValue.getValue(), currentType, expectedType,
new LwM2mPath(convertPathFromIdVerToObjectId(pathIdVer)));
}
+ LwM2mOtaConvert lwM2mOtaConvert = convertOtaUpdateValueToString(pathIdVer, valueKvProto, currentType);
+ valueKvProto = lwM2mOtaConvert.getValue();
+ currentType = lwM2mOtaConvert.getCurrentType();
return valueKvProto != null ? this.helper.getKvAttrTelemetryToThingsboard(currentType, resourceName, valueKvProto, resourceValue.isMultiInstances()) : null;
}
} catch (Exception e) {
@@ -1023,7 +1000,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
if (sendAttrToThingsboard.getPathPostParametersAdd().size() > 0) {
// update value in Resources
clients.forEach(client -> {
- this.readObserveFromProfile(client.getRegistration(), sendAttrToThingsboard.getPathPostParametersAdd(), READ);
+ this.readObserveFromProfile(client, sendAttrToThingsboard.getPathPostParametersAdd(), READ);
});
}
// #4.2 del
@@ -1050,12 +1027,12 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
clients.forEach(client -> {
Registration registration = client.getRegistration();
if (postObserveAnalyzer.getPathPostParametersAdd().size() > 0) {
- this.readObserveFromProfile(registration, postObserveAnalyzer.getPathPostParametersAdd(), OBSERVE);
+ this.readObserveFromProfile(client, postObserveAnalyzer.getPathPostParametersAdd(), OBSERVE);
}
// 5.3 del
// send Request cancel observe to Client
if (postObserveAnalyzer.getPathPostParametersDel().size() > 0) {
- this.cancelObserveFromProfile(registration, postObserveAnalyzer.getPathPostParametersDel());
+ this.cancelObserveFromProfile(client, postObserveAnalyzer.getPathPostParametersDel());
}
});
}
@@ -1092,19 +1069,18 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
* Update Resource value after change RezAttrTelemetry in config Profile
* send response Read to Client and add path to pathResAttrTelemetry in LwM2MClient.getAttrTelemetryObserveValue()
*
- * @param registration - Registration LwM2M Client
- * @param targets - path Resources == [ "/2/0/0", "/2/0/1"]
+ * @param targets - path Resources == [ "/2/0/0", "/2/0/1"]
*/
- private void readObserveFromProfile(Registration registration, Set targets, LwM2mTypeOper typeOper) {
+ private void readObserveFromProfile(LwM2mClient client, Set targets, LwM2mTypeOper typeOper) {
targets.forEach(target -> {
LwM2mPath pathIds = new LwM2mPath(convertPathFromIdVerToObjectId(target));
if (pathIds.isResource()) {
if (READ.equals(typeOper)) {
- lwM2mTransportRequest.sendAllRequest(registration, target, typeOper,
- ContentFormat.TLV.getName(), null, this.config.getTimeout(), null);
+ lwM2mTransportRequest.sendAllRequest(client, target, typeOper,
+ null, this.config.getTimeout(), null);
} else if (OBSERVE.equals(typeOper)) {
- lwM2mTransportRequest.sendAllRequest(registration, target, typeOper,
- null, null, this.config.getTimeout(), null);
+ lwM2mTransportRequest.sendAllRequest(client, target, typeOper,
+ null, this.config.getTimeout(), null);
}
}
});
@@ -1153,13 +1129,12 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
// #6.2
if (analyzerParameters.getPathPostParametersAdd().size() > 0) {
clients.forEach(client -> {
- Registration registration = client.getRegistration();
- Set clientObjects = clientContext.getSupportedIdVerInClient(registration);
+ Set clientObjects = clientContext.getSupportedIdVerInClient(client);
Set pathSend = analyzerParameters.getPathPostParametersAdd().stream().filter(target -> clientObjects.contains("/" + target.split(LWM2M_SEPARATOR_PATH)[1]))
.collect(Collectors.toUnmodifiableSet());
if (!pathSend.isEmpty()) {
ConcurrentHashMap finalParams = lwm2mAttributesNew;
- pathSend.forEach(target -> lwM2mTransportRequest.sendAllRequest(registration, target, WRITE_ATTRIBUTES, ContentFormat.TEXT.getName(),
+ pathSend.forEach(target -> lwM2mTransportRequest.sendAllRequest(client, target, WRITE_ATTRIBUTES,
finalParams.get(target), this.config.getTimeout(), null));
}
});
@@ -1168,7 +1143,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
if (analyzerParameters.getPathPostParametersDel().size() > 0) {
clients.forEach(client -> {
Registration registration = client.getRegistration();
- Set clientObjects = clientContext.getSupportedIdVerInClient(registration);
+ Set clientObjects = clientContext.getSupportedIdVerInClient(client);
Set pathSend = analyzerParameters.getPathPostParametersDel().stream().filter(target -> clientObjects.contains("/" + target.split(LWM2M_SEPARATOR_PATH)[1]))
.collect(Collectors.toUnmodifiableSet());
if (!pathSend.isEmpty()) {
@@ -1176,8 +1151,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
Map params = (Map) lwm2mAttributesOld.get(target);
params.clear();
params.put(OBJECT_VERSION, "");
- lwM2mTransportRequest.sendAllRequest(registration, target, WRITE_ATTRIBUTES, ContentFormat.TEXT.getName(),
- params, this.config.getTimeout(), null);
+ lwM2mTransportRequest.sendAllRequest(client, target, WRITE_ATTRIBUTES, params, this.config.getTimeout(), null);
});
}
});
@@ -1185,12 +1159,10 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
}
- private void cancelObserveFromProfile(Registration registration, Set paramAnallyzer) {
- LwM2mClient lwM2MClient = clientContext.getClientByEndpoint(registration.getEndpoint());
+ private void cancelObserveFromProfile(LwM2mClient lwM2mClient, Set paramAnallyzer) {
paramAnallyzer.forEach(pathIdVer -> {
- if (this.getResourceValueFromLwM2MClient(lwM2MClient, pathIdVer) != null) {
- lwM2mTransportRequest.sendAllRequest(registration, pathIdVer, OBSERVE_CANCEL, null,
- null, this.config.getTimeout(), null);
+ if (this.getResourceValueFromLwM2MClient(lwM2mClient, pathIdVer) != null) {
+ lwM2mTransportRequest.sendAllRequest(lwM2mClient, pathIdVer, OBSERVE_CANCEL, null, this.config.getTimeout(), null);
}
}
);
@@ -1198,9 +1170,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
private void updateResourcesValueToClient(LwM2mClient lwM2MClient, Object valueOld, Object valueNew, String path) {
if (valueNew != null && (valueOld == null || !valueNew.toString().equals(valueOld.toString()))) {
- lwM2mTransportRequest.sendAllRequest(lwM2MClient.getRegistration(), path, WRITE_REPLACE,
- ContentFormat.TLV.getName(), valueNew,
- this.config.getTimeout(), null);
+ lwM2mTransportRequest.sendAllRequest(lwM2MClient, path, WRITE_REPLACE, valueNew, this.config.getTimeout(), null);
} else {
log.error("Failed update resource [{}] [{}]", path, valueNew);
String logMsg = String.format("%s: Failed update resource path - %s value - %s. Value is not changed or bad",
@@ -1349,8 +1319,8 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
}
}
- public void getInfoFirmwareUpdate(LwM2mClient lwM2MClient, Lwm2mClientRpcRequest rpcRequest) {
- if (lwM2MClient.getRegistration().getSupportedVersion(FW_ID) != null) {
+ public void getInfoFirmwareUpdate(LwM2mClient lwM2MClient, LwM2mClientRpcRequest rpcRequest) {
+ if (lwM2MClient.getRegistration().getSupportedVersion(FW_5_ID) != null) {
SessionInfoProto sessionInfo = this.getSessionInfo(lwM2MClient);
if (sessionInfo != null) {
DefaultLwM2MTransportMsgHandler handler = this;
@@ -1360,18 +1330,33 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
public void onSuccess(TransportProtos.GetOtaPackageResponseMsg response) {
if (TransportProtos.ResponseStatus.SUCCESS.equals(response.getResponseStatus())
&& response.getType().equals(OtaPackageType.FIRMWARE.name())) {
- log.warn("7) firmware start with ver: [{}]", response.getVersion());
- lwM2MClient.getFwUpdate().setRpcRequest(rpcRequest);
- lwM2MClient.getFwUpdate().setCurrentVersion(response.getVersion());
- lwM2MClient.getFwUpdate().setCurrentTitle(response.getTitle());
- lwM2MClient.getFwUpdate().setCurrentId(new OtaPackageId(new UUID(response.getOtaPackageIdMSB(), response.getOtaPackageIdLSB())).getId());
- if (rpcRequest == null) {
- lwM2MClient.getFwUpdate().sendReadObserveInfo(lwM2mTransportRequest);
+ LwM2mFwSwUpdate fwUpdate = lwM2MClient.getFwUpdate(clientContext);
+ if (rpcRequest != null) {
+ fwUpdate.setStateUpdate(INITIATED.name());
+ }
+ if (!FAILED.name().equals(fwUpdate.getStateUpdate())) {
+ log.warn("7) firmware start with ver: [{}]", response.getVersion());
+ fwUpdate.setRpcRequest(rpcRequest);
+ fwUpdate.setCurrentVersion(response.getVersion());
+ fwUpdate.setCurrentTitle(response.getTitle());
+ fwUpdate.setCurrentId(new UUID(response.getOtaPackageIdMSB(), response.getOtaPackageIdLSB()));
+ if (rpcRequest == null) {
+ fwUpdate.sendReadObserveInfo(lwM2mTransportRequest);
+ } else {
+ fwUpdate.writeFwSwWare(handler, lwM2mTransportRequest);
+ }
} else {
- lwM2MClient.getFwUpdate().writeFwSwWare(handler, lwM2mTransportRequest);
+ String msgError = String.format("OtaPackage device: %s, version: %s, stateUpdate: %s",
+ lwM2MClient.getDeviceName(), response.getVersion(), fwUpdate.getStateUpdate());
+ log.warn("7_1 [{}]", msgError);
}
} else {
- log.trace("OtaPackage [{}] [{}]", lwM2MClient.getDeviceName(), response.getResponseStatus().toString());
+ String msgError = String.format("OtaPackage device: %s, responseStatus: %s",
+ lwM2MClient.getDeviceName(), response.getResponseStatus().toString());
+ log.trace(msgError);
+ if (rpcRequest != null) {
+ sendErrorRpcResponse(rpcRequest, msgError, sessionInfo);
+ }
}
}
@@ -1384,7 +1369,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
}
}
- public void getInfoSoftwareUpdate(LwM2mClient lwM2MClient, Lwm2mClientRpcRequest rpcRequest) {
+ public void getInfoSoftwareUpdate(LwM2mClient lwM2MClient, LwM2mClientRpcRequest rpcRequest) {
if (lwM2MClient.getRegistration().getSupportedVersion(SW_ID) != null) {
SessionInfoProto sessionInfo = this.getSessionInfo(lwM2MClient);
if (sessionInfo != null) {
diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2mTransportService.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2mTransportService.java
index 865168aed6..9be164023d 100644
--- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2mTransportService.java
+++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2mTransportService.java
@@ -28,7 +28,6 @@ import org.eclipse.leshan.server.californium.registration.CaliforniumRegistratio
import org.eclipse.leshan.server.model.LwM2mModelProvider;
import org.eclipse.leshan.server.security.EditableSecurityStore;
import org.springframework.stereotype.Component;
-import org.thingsboard.common.util.ThingsBoardThreadFactory;
import org.thingsboard.server.common.data.StringUtils;
import org.thingsboard.server.queue.util.TbLwM2mTransportComponent;
import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig;
@@ -60,14 +59,13 @@ import java.security.spec.InvalidParameterSpecException;
import java.security.spec.KeySpec;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Arrays;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256;
import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8;
import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA256;
import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_PSK_WITH_AES_128_CCM_8;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mNetworkConfig.getCoapConfig;
+import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FIRMWARE_UPDATE_COAP_RECOURSE;
@Slf4j
@Component
@@ -83,7 +81,7 @@ public class DefaultLwM2mTransportService implements LwM2MTransportService {
private final LwM2mTransportContext context;
private final LwM2MTransportServerConfig config;
private final LwM2mTransportServerHelper helper;
- private final LwM2mTransportMsgHandler handler;
+ private final DefaultLwM2MTransportMsgHandler handler;
private final CaliforniumRegistrationStore registrationStore;
private final TbSecurityStore securityStore;
private final LwM2mClientContext lwM2mClientContext;
@@ -98,6 +96,17 @@ public class DefaultLwM2mTransportService implements LwM2MTransportService {
new LWM2MGenerationPSkRPkECC();
}
this.server = getLhServer();
+ /**
+ * Add a resource to the server.
+ * CoapResource ->
+ * path = FW_PACKAGE or SW_PACKAGE
+ * nameFile = "BC68JAR01A09_TO_BC68JAR01A10.bin"
+ * "coap://host:port/{path}/{token}/{nameFile}"
+ */
+
+
+ LwM2mTransportCoapResource otaCoapResource = new LwM2mTransportCoapResource(handler, FIRMWARE_UPDATE_COAP_RECOURSE);
+ this.server.coap().getServer().add(otaCoapResource);
this.startLhServer();
this.context.setServer(server);
}
@@ -128,7 +137,7 @@ public class DefaultLwM2mTransportService implements LwM2MTransportService {
builder.setEncoder(new DefaultLwM2mNodeEncoder(LwM2mValueConverterImpl.getInstance()));
/* Create CoAP Config */
- builder.setCoapConfig(getCoapConfig(config.getPort(), config.getSecurePort()));
+ builder.setCoapConfig(getCoapConfig(config.getPort(), config.getSecurePort(), config));
/* Define model provider (Create Models )*/
LwM2mModelProvider modelProvider = new LwM2mVersionedModelProvider(this.lwM2mClientContext, this.helper, this.context);
diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mNetworkConfig.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mNetworkConfig.java
index 280cb7dde4..00f70dbcf7 100644
--- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mNetworkConfig.java
+++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mNetworkConfig.java
@@ -16,10 +16,14 @@
package org.thingsboard.server.transport.lwm2m.server;
import org.eclipse.californium.core.network.config.NetworkConfig;
+import org.eclipse.californium.core.network.config.NetworkConfigDefaults;
+import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig;
+
+import static org.eclipse.californium.core.network.config.NetworkConfigDefaults.DEFAULT_BLOCKWISE_STATUS_LIFETIME;
public class LwM2mNetworkConfig {
- public static NetworkConfig getCoapConfig(Integer serverPortNoSec, Integer serverSecurePort) {
+ public static NetworkConfig getCoapConfig(Integer serverPortNoSec, Integer serverSecurePort, LwM2MTransportServerConfig config) {
NetworkConfig coapConfig = new NetworkConfig();
coapConfig.setInt(NetworkConfig.Keys.COAP_PORT,serverPortNoSec);
coapConfig.setInt(NetworkConfig.Keys.COAP_SECURE_PORT,serverSecurePort);
@@ -49,8 +53,15 @@ public class LwM2mNetworkConfig {
- value of true indicate that the server will response with block2 option event if no further blocks are required.
*/
coapConfig.setBoolean(NetworkConfig.Keys.BLOCKWISE_ENTITY_TOO_LARGE_AUTO_FAILOVER, true);
-
- coapConfig.setInt(NetworkConfig.Keys.BLOCKWISE_STATUS_LIFETIME, 300000);
+ /**
+ * The maximum amount of time (in milliseconds) allowed between
+ * transfers of individual blocks in a blockwise transfer before the
+ * blockwise transfer state is discarded.
+ *
+ * The default value of this property is
+ * {@link NetworkConfigDefaults#DEFAULT_BLOCKWISE_STATUS_LIFETIME} = 5 * 60 * 1000; // 5 mins [ms].
+ */
+ coapConfig.setLong(NetworkConfig.Keys.BLOCKWISE_STATUS_LIFETIME, DEFAULT_BLOCKWISE_STATUS_LIFETIME);
/**
!!! REQUEST_ENTITY_TOO_LARGE CODE=4.13
The maximum size of a resource body (in bytes) that will be accepted
diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mOtaConvert.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mOtaConvert.java
new file mode 100644
index 0000000000..7b7c56adb3
--- /dev/null
+++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mOtaConvert.java
@@ -0,0 +1,25 @@
+/**
+ * Copyright © 2016-2021 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.transport.lwm2m.server;
+
+import lombok.Data;
+import org.eclipse.leshan.core.model.ResourceModel;
+
+@Data
+public class LwM2mOtaConvert {
+ private ResourceModel.Type currentType;
+ private Object value;
+}
diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mServerListener.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mServerListener.java
index f1839e718a..b69825843e 100644
--- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mServerListener.java
+++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mServerListener.java
@@ -87,7 +87,7 @@ public class LwM2mServerListener {
@Override
public void cancelled(Observation observation) {
String msg = String.format("%s: Canceled Observation %s.", LOG_LW2M_INFO, observation.getPath());
- service.sendLogsToThingsboard2(observation.getRegistrationId(), msg);
+ service.sendLogsToThingsboard(observation.getRegistrationId(), msg);
log.warn(msg);
}
@@ -109,7 +109,7 @@ public class LwM2mServerListener {
String msg = String.format("%s: Successful start newObservation %s.", LOG_LW2M_INFO,
observation.getPath());
log.warn(msg);
- service.sendLogsToThingsboard2(registration.getId(), msg);
+ service.sendLogsToThingsboard(registration.getId(), msg);
}
};
}
diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportCoapResource.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportCoapResource.java
new file mode 100644
index 0000000000..1236c8b6d2
--- /dev/null
+++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportCoapResource.java
@@ -0,0 +1,158 @@
+/**
+ * Copyright © 2016-2021 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.transport.lwm2m.server;
+
+import lombok.extern.slf4j.Slf4j;
+import org.eclipse.californium.core.coap.CoAP;
+import org.eclipse.californium.core.coap.Request;
+import org.eclipse.californium.core.coap.Response;
+import org.eclipse.californium.core.network.Exchange;
+import org.eclipse.californium.core.observe.ObserveRelation;
+import org.eclipse.californium.core.server.resources.CoapExchange;
+import org.eclipse.californium.core.server.resources.Resource;
+import org.eclipse.californium.core.server.resources.ResourceObserver;
+
+import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FIRMWARE_UPDATE_COAP_RECOURSE;
+import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.SOFTWARE_UPDATE_COAP_RECOURSE;
+
+@Slf4j
+public class LwM2mTransportCoapResource extends AbstractLwM2mTransportResource {
+ private final ConcurrentMap tokenToObserveRelationMap = new ConcurrentHashMap<>();
+ private final ConcurrentMap tokenToObserveNotificationSeqMap = new ConcurrentHashMap<>();
+ private final LwM2mTransportMsgHandler handler;
+
+ public LwM2mTransportCoapResource(LwM2mTransportMsgHandler handler, String name) {
+ super(name);
+ this.handler = handler;
+ this.setObservable(true); // enable observing
+ this.addObserver(new CoapResourceObserver());
+ }
+
+
+ @Override
+ public void checkObserveRelation(Exchange exchange, Response response) {
+ String token = getTokenFromRequest(exchange.getRequest());
+ final ObserveRelation relation = exchange.getRelation();
+ if (relation == null || relation.isCanceled()) {
+ return; // because request did not try to establish a relation
+ }
+ if (CoAP.ResponseCode.isSuccess(response.getCode())) {
+
+ if (!relation.isEstablished()) {
+ relation.setEstablished();
+ addObserveRelation(relation);
+ }
+ AtomicInteger notificationCounter = tokenToObserveNotificationSeqMap.computeIfAbsent(token, s -> new AtomicInteger(0));
+ response.getOptions().setObserve(notificationCounter.getAndIncrement());
+ } // ObserveLayer takes care of the else case
+ }
+
+
+ @Override
+ protected void processHandleGet(CoapExchange exchange) {
+ log.warn("90) processHandleGet [{}]", exchange);
+ if (exchange.getRequestOptions().getUriPath().size() >= 2 &&
+ (FIRMWARE_UPDATE_COAP_RECOURSE.equals(exchange.getRequestOptions().getUriPath().get(exchange.getRequestOptions().getUriPath().size()-2)) ||
+ SOFTWARE_UPDATE_COAP_RECOURSE.equals(exchange.getRequestOptions().getUriPath().get(exchange.getRequestOptions().getUriPath().size()-2)))) {
+ this.sendOtaData(exchange);
+ }
+ }
+
+ @Override
+ protected void processHandlePost(CoapExchange exchange) {
+ log.warn("2) processHandleGet [{}]", exchange);
+ }
+
+ /**
+ * Override the default behavior so that requests to sub resources (typically /{name}/{token}) are handled by
+ * /name resource.
+ */
+ @Override
+ public Resource getChild(String name) {
+ return this;
+ }
+
+
+ private String getTokenFromRequest(Request request) {
+ return (request.getSourceContext() != null ? request.getSourceContext().getPeerAddress().getAddress().getHostAddress() : "null")
+ + ":" + (request.getSourceContext() != null ? request.getSourceContext().getPeerAddress().getPort() : -1) + ":" + request.getTokenString();
+ }
+
+ public class CoapResourceObserver implements ResourceObserver {
+
+ @Override
+ public void changedName(String old) {
+
+ }
+
+ @Override
+ public void changedPath(String old) {
+
+ }
+
+ @Override
+ public void addedChild(Resource child) {
+
+ }
+
+ @Override
+ public void removedChild(Resource child) {
+
+ }
+
+ @Override
+ public void addedObserveRelation(ObserveRelation relation) {
+
+ }
+
+ @Override
+ public void removedObserveRelation(ObserveRelation relation) {
+
+ }
+ }
+
+ private void sendOtaData(CoapExchange exchange) {
+ String idStr = exchange.getRequestOptions().getUriPath().get(exchange.getRequestOptions().getUriPath().size()-1
+ );
+ UUID currentId = UUID.fromString(idStr);
+ Response response = new Response(CoAP.ResponseCode.CONTENT);
+ byte[] fwData = this.getOtaData(currentId);
+ log.warn("91) read softWare data (length): [{}]", fwData.length);
+ if (fwData != null && fwData.length > 0) {
+ response.setPayload(fwData);
+ if (exchange.getRequestOptions().getBlock2() != null) {
+ int chunkSize = exchange.getRequestOptions().getBlock2().getSzx();
+ boolean moreFlag = fwData.length > chunkSize;
+ response.getOptions().setBlock2(chunkSize, moreFlag, 0);
+ log.warn("92) with blokc2 Send currentId: [{}], length: [{}], chunkSize [{}], moreFlag [{}]", currentId.toString(), fwData.length, chunkSize, moreFlag);
+ }
+ else {
+ log.warn("92) with block1 Send currentId: [{}], length: [{}], ", currentId.toString(), fwData.length);
+ }
+ exchange.respond(response);
+ }
+ }
+
+ private byte[] getOtaData(UUID currentId) {
+ return ((DefaultLwM2MTransportMsgHandler) handler).otaPackageDataCache.get(currentId.toString());
+ }
+
+}
diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportMsgHandler.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportMsgHandler.java
index 36f1209ff3..ee3b07da34 100644
--- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportMsgHandler.java
+++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportMsgHandler.java
@@ -23,7 +23,7 @@ import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.gen.transport.TransportProtos;
import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig;
import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient;
-import org.thingsboard.server.transport.lwm2m.server.client.Lwm2mClientRpcRequest;
+import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientRpcRequest;
import java.util.Collection;
import java.util.Optional;
@@ -40,7 +40,7 @@ public interface LwM2mTransportMsgHandler {
void setCancelObservationsAll(Registration registration);
- void onUpdateValueAfterReadResponse(Registration registration, String path, ReadResponse response, Lwm2mClientRpcRequest rpcRequest);
+ void onUpdateValueAfterReadResponse(Registration registration, String path, ReadResponse response, LwM2mClientRpcRequest rpcRequest);
void onAttributeUpdate(TransportProtos.AttributeUpdateNotificationMsg msg, TransportProtos.SessionInfoProto sessionInfo);
@@ -58,15 +58,13 @@ public interface LwM2mTransportMsgHandler {
void onToServerRpcResponse(TransportProtos.ToServerRpcResponseMsg toServerResponse);
- void doTrigger(Registration registration, String path);
-
void doDisconnect(TransportProtos.SessionInfoProto sessionInfo);
void onAwakeDev(Registration registration);
void sendLogsToThingsboard(LwM2mClient client, String msg);
- void sendLogsToThingsboard2(String registrationId, String msg);
+ void sendLogsToThingsboard(String registrationId, String msg);
LwM2MTransportServerConfig getConfig();
}
diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportRequest.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportRequest.java
index d382b0b734..3568000ead 100644
--- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportRequest.java
+++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportRequest.java
@@ -55,7 +55,7 @@ import org.thingsboard.server.queue.util.TbLwM2mTransportComponent;
import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig;
import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient;
import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext;
-import org.thingsboard.server.transport.lwm2m.server.client.Lwm2mClientRpcRequest;
+import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientRpcRequest;
import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl;
import javax.annotation.PostConstruct;
@@ -75,7 +75,7 @@ import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.DOWN
import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.FAILED;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportServerHelper.getContentFormatByResourceModelType;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.DEFAULT_TIMEOUT;
-import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_PACKAGE_ID;
+import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_PACKAGE_5_ID;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_UPDATE_ID;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_ERROR;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_INFO;
@@ -116,21 +116,19 @@ public class LwM2mTransportRequest {
new NamedThreadFactory(String.format("LwM2M %s channel response after request", RESPONSE_REQUEST_CHANNEL)));
}
- /**
- * Device management and service enablement, including Read, Write, Execute, Discover, Create, Delete and Write-Attributes
- *
- * @param registration -
- * @param targetIdVer -
- * @param typeOper -
- * @param contentFormatName -
- */
+ public void sendAllRequest(LwM2mClient lwM2MClient, String targetIdVer, LwM2mTypeOper typeOper, Object params, long timeoutInMs, LwM2mClientRpcRequest lwm2mClientRpcRequest) {
+ sendAllRequest(lwM2MClient, targetIdVer, typeOper, lwM2MClient.getDefaultContentFormat(), params, timeoutInMs, lwm2mClientRpcRequest);
+ }
- public void sendAllRequest(Registration registration, String targetIdVer, LwM2mTypeOper typeOper,
- String contentFormatName, Object params, long timeoutInMs, Lwm2mClientRpcRequest lwm2mClientRpcRequest) {
- LwM2mClient lwM2MClient = this.lwM2mClientContext.getClientByEndpoint(registration.getEndpoint());
+
+ public void sendAllRequest(LwM2mClient lwM2MClient, String targetIdVer, LwM2mTypeOper typeOper,
+ ContentFormat contentFormat, Object params, long timeoutInMs, LwM2mClientRpcRequest lwm2mClientRpcRequest) {
+ Registration registration = lwM2MClient.getRegistration();
try {
String target = convertPathFromIdVerToObjectId(targetIdVer);
- ContentFormat contentFormat = contentFormatName != null ? ContentFormat.fromName(contentFormatName.toUpperCase()) : ContentFormat.DEFAULT;
+ if(contentFormat == null){
+ contentFormat = ContentFormat.DEFAULT;
+ }
LwM2mPath resultIds = target != null ? new LwM2mPath(target) : null;
if (!OBSERVE_CANCEL.name().equals(typeOper.name()) && resultIds != null && registration != null && resultIds.getObjectId() >= 0 && lwM2MClient != null) {
if (lwM2MClient.isValidObjectVersion(targetIdVer)) {
@@ -143,7 +141,7 @@ public class LwM2mTransportRequest {
} catch (ClientSleepingException e) {
SimpleDownlinkRequest finalRequest = request;
long finalTimeoutInMs = timeoutInMs;
- Lwm2mClientRpcRequest finalRpcRequest = lwm2mClientRpcRequest;
+ LwM2mClientRpcRequest finalRpcRequest = lwm2mClientRpcRequest;
lwM2MClient.getQueuedRequests().add(() -> sendRequest(registration, lwM2MClient, finalRequest, finalTimeoutInMs, finalRpcRequest));
} catch (Exception e) {
log.error("[{}] [{}] [{}] Failed to send downlink.", registration.getEndpoint(), targetIdVer, typeOper.name(), e);
@@ -163,12 +161,12 @@ public class LwM2mTransportRequest {
if (lwm2mClientRpcRequest != null) {
ResourceModel resourceModel = lwM2MClient.getResourceModel(targetIdVer, this.config.getModelProvider());
String errorMsg = resourceModel == null ? String.format("Path %s not found in object version", targetIdVer) : "SendRequest - null";
- this.handler.sentRpcResponse(lwm2mClientRpcRequest, NOT_FOUND.getName(), errorMsg, LOG_LW2M_ERROR);
+ handler.sentRpcResponse(lwm2mClientRpcRequest, NOT_FOUND.getName(), errorMsg, LOG_LW2M_ERROR);
}
}
} else if (lwm2mClientRpcRequest != null) {
String errorMsg = String.format("Path %s not found in object version", targetIdVer);
- this.handler.sentRpcResponse(lwm2mClientRpcRequest, NOT_FOUND.getName(), errorMsg, LOG_LW2M_ERROR);
+ handler.sentRpcResponse(lwm2mClientRpcRequest, NOT_FOUND.getName(), errorMsg, LOG_LW2M_ERROR);
}
} else {
switch (typeOper) {
@@ -188,7 +186,7 @@ public class LwM2mTransportRequest {
this.handler.sendLogsToThingsboard(lwM2MClient, msg);
if (lwm2mClientRpcRequest != null) {
String valueMsg = String.format("Paths - %s", paths);
- this.handler.sentRpcResponse(lwm2mClientRpcRequest, CONTENT.name(), valueMsg, LOG_LW2M_VALUE);
+ handler.sentRpcResponse(lwm2mClientRpcRequest, CONTENT.name(), valueMsg, LOG_LW2M_VALUE);
}
break;
case OBSERVE_CANCEL:
@@ -208,7 +206,7 @@ public class LwM2mTransportRequest {
break;
// lwm2mClientRpcRequest != null
case FW_UPDATE:
- this.handler.getInfoFirmwareUpdate(lwM2MClient, lwm2mClientRpcRequest);
+ handler.getInfoFirmwareUpdate(lwM2MClient, lwm2mClientRpcRequest);
break;
}
}
@@ -225,7 +223,7 @@ public class LwM2mTransportRequest {
private SimpleDownlinkRequest createRequest(Registration registration, LwM2mClient lwM2MClient, LwM2mTypeOper typeOper,
ContentFormat contentFormat, String target, String targetIdVer,
- LwM2mPath resultIds, Object params, Lwm2mClientRpcRequest rpcRequest) {
+ LwM2mPath resultIds, Object params, LwM2mClientRpcRequest rpcRequest) {
SimpleDownlinkRequest request = null;
switch (typeOper) {
case READ:
@@ -330,7 +328,7 @@ public class LwM2mTransportRequest {
@SuppressWarnings({"error sendRequest"})
private void sendRequest(Registration registration, LwM2mClient lwM2MClient, SimpleDownlinkRequest request,
- long timeoutInMs, Lwm2mClientRpcRequest rpcRequest) {
+ long timeoutInMs, LwM2mClientRpcRequest rpcRequest) {
context.getServer().send(registration, request, timeoutInMs, (ResponseCallback>) response -> {
if (!lwM2MClient.isInit()) {
@@ -354,13 +352,13 @@ public class LwM2mTransportRequest {
/** Not Found
set setClient_fw_info... = empty
**/
- if (lwM2MClient.getFwUpdate().isInfoFwSwUpdate()) {
+ if (lwM2MClient.getFwUpdate() != null && lwM2MClient.getFwUpdate().isInfoFwSwUpdate()) {
lwM2MClient.getFwUpdate().initReadValue(handler, this, request.getPath().toString());
}
- if (lwM2MClient.getSwUpdate().isInfoFwSwUpdate()) {
+ if (lwM2MClient.getSwUpdate() != null && lwM2MClient.getSwUpdate().isInfoFwSwUpdate()) {
lwM2MClient.getSwUpdate().initReadValue(handler, this, request.getPath().toString());
}
- if (request.getPath().toString().equals(FW_PACKAGE_ID) || request.getPath().toString().equals(SW_PACKAGE_ID)) {
+ if (request.getPath().toString().equals(FW_PACKAGE_5_ID) || request.getPath().toString().equals(SW_PACKAGE_ID)) {
this.afterWriteFwSWUpdateError(registration, request, response.getErrorMessage());
}
if (request.getPath().toString().equals(FW_UPDATE_ID) || request.getPath().toString().equals(SW_INSTALL_ID)) {
@@ -371,13 +369,13 @@ public class LwM2mTransportRequest {
/** version == null
set setClient_fw_info... = empty
**/
- if (lwM2MClient.getFwUpdate().isInfoFwSwUpdate()) {
+ if (lwM2MClient.getFwUpdate() != null && lwM2MClient.getFwUpdate().isInfoFwSwUpdate()) {
lwM2MClient.getFwUpdate().initReadValue(handler, this, request.getPath().toString());
}
- if (lwM2MClient.getSwUpdate().isInfoFwSwUpdate()) {
+ if (lwM2MClient.getSwUpdate() != null && lwM2MClient.getSwUpdate().isInfoFwSwUpdate()) {
lwM2MClient.getSwUpdate().initReadValue(handler, this, request.getPath().toString());
}
- if (request.getPath().toString().equals(FW_PACKAGE_ID) || request.getPath().toString().equals(SW_PACKAGE_ID)) {
+ if (request.getPath().toString().equals(FW_PACKAGE_5_ID) || request.getPath().toString().equals(SW_PACKAGE_ID)) {
this.afterWriteFwSWUpdateError(registration, request, e.getMessage());
}
if (request.getPath().toString().equals(FW_UPDATE_ID) || request.getPath().toString().equals(SW_INSTALL_ID)) {
@@ -398,7 +396,7 @@ public class LwM2mTransportRequest {
private WriteRequest getWriteRequestSingleResource(ContentFormat contentFormat, Integer objectId, Integer instanceId,
Integer resourceId, Object value, ResourceModel.Type type,
- LwM2mClient client, Lwm2mClientRpcRequest rpcRequest) {
+ LwM2mClient client, LwM2mClientRpcRequest rpcRequest) {
try {
if (type != null) {
switch (type) {
@@ -444,7 +442,7 @@ public class LwM2mTransportRequest {
}
private void handleResponse(LwM2mClient lwM2mClient, final String path, LwM2mResponse response,
- SimpleDownlinkRequest request, Lwm2mClientRpcRequest rpcRequest) {
+ SimpleDownlinkRequest request, LwM2mClientRpcRequest rpcRequest) {
responseRequestExecutor.submit(() -> {
try {
this.sendResponse(lwM2mClient, path, response, request, rpcRequest);
@@ -457,12 +455,11 @@ public class LwM2mTransportRequest {
/**
* processing a response from a client
*
- * @param registration -
* @param path -
* @param response -
*/
private void sendResponse(LwM2mClient lwM2mClient, String path, LwM2mResponse response,
- SimpleDownlinkRequest request, Lwm2mClientRpcRequest rpcRequest) {
+ SimpleDownlinkRequest request, LwM2mClientRpcRequest rpcRequest) {
Registration registration = lwM2mClient.getRegistration();
String pathIdVer = convertPathFromObjectIdToIdVer(path, registration);
String msgLog = "";
@@ -510,7 +507,7 @@ public class LwM2mTransportRequest {
}
}
- private void infoWriteResponse(LwM2mClient lwM2mClient, LwM2mResponse response, SimpleDownlinkRequest request, Lwm2mClientRpcRequest rpcRequest) {
+ private void infoWriteResponse(LwM2mClient lwM2mClient, LwM2mResponse response, SimpleDownlinkRequest request, LwM2mClientRpcRequest rpcRequest) {
try {
Registration registration = lwM2mClient.getRegistration();
LwM2mNode node = ((WriteRequest) request).getNode();
@@ -548,7 +545,7 @@ public class LwM2mTransportRequest {
}
if (msg != null) {
handler.sendLogsToThingsboard(lwM2mClient, msg);
- if (request.getPath().toString().equals(FW_PACKAGE_ID) || request.getPath().toString().equals(SW_PACKAGE_ID)) {
+ if (request.getPath().toString().equals(FW_PACKAGE_5_ID) || request.getPath().toString().equals(SW_PACKAGE_ID)) {
this.afterWriteSuccessFwSwUpdate(registration, request);
if (rpcRequest != null) {
rpcRequest.setInfoMsg(msg);
@@ -570,7 +567,7 @@ public class LwM2mTransportRequest {
*/
private void afterWriteSuccessFwSwUpdate(Registration registration, SimpleDownlinkRequest request) {
LwM2mClient lwM2MClient = this.lwM2mClientContext.getClientByRegistrationId(registration.getId());
- if (request.getPath().toString().equals(FW_PACKAGE_ID) && lwM2MClient.getFwUpdate() != null) {
+ if (request.getPath().toString().equals(FW_PACKAGE_5_ID) && lwM2MClient.getFwUpdate() != null) {
lwM2MClient.getFwUpdate().setStateUpdate(DOWNLOADED.name());
lwM2MClient.getFwUpdate().sendLogs(this.handler, WRITE_REPLACE.name(), LOG_LW2M_INFO, null);
}
@@ -585,7 +582,7 @@ public class LwM2mTransportRequest {
*/
private void afterWriteFwSWUpdateError(Registration registration, SimpleDownlinkRequest request, String msgError) {
LwM2mClient lwM2MClient = this.lwM2mClientContext.getClientByRegistrationId(registration.getId());
- if (request.getPath().toString().equals(FW_PACKAGE_ID) && lwM2MClient.getFwUpdate() != null) {
+ if (request.getPath().toString().equals(FW_PACKAGE_5_ID) && lwM2MClient.getFwUpdate() != null) {
lwM2MClient.getFwUpdate().setStateUpdate(FAILED.name());
lwM2MClient.getFwUpdate().sendLogs(this.handler, WRITE_REPLACE.name(), LOG_LW2M_ERROR, msgError);
}
@@ -605,7 +602,7 @@ public class LwM2mTransportRequest {
}
}
- private void afterObserveCancel(LwM2mClient lwM2mClient, int observeCancelCnt, String observeCancelMsg, Lwm2mClientRpcRequest rpcRequest) {
+ private void afterObserveCancel(LwM2mClient lwM2mClient, int observeCancelCnt, String observeCancelMsg, LwM2mClientRpcRequest rpcRequest) {
handler.sendLogsToThingsboard(lwM2mClient, observeCancelMsg);
log.warn("[{}]", observeCancelMsg);
if (rpcRequest != null) {
diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportServerHelper.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportServerHelper.java
index 4334c8ac0f..a52fc0158d 100644
--- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportServerHelper.java
+++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportServerHelper.java
@@ -65,13 +65,11 @@ import static org.thingsboard.server.gen.transport.TransportProtos.KeyValueType.
public class LwM2mTransportServerHelper {
private final LwM2mTransportContext context;
- private final LwM2MJsonAdaptor adaptor;
private final AtomicInteger atomicTs = new AtomicInteger(0);
public long getTS() {
- int addTs = atomicTs.getAndIncrement() >= 1000 ? atomicTs.getAndSet(0) : atomicTs.get();
- return TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis()) * 1000L + addTs;
+ return TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis()) * 1000L + (atomicTs.getAndIncrement() % 1000);
}
/**
diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportUtil.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportUtil.java
index d420176ffa..1d1feab85e 100644
--- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportUtil.java
+++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportUtil.java
@@ -43,11 +43,11 @@ import org.eclipse.leshan.server.registration.Registration;
import org.nustaq.serialization.FSTConfiguration;
import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.common.data.device.profile.Lwm2mDeviceProfileTransportConfiguration;
+import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.ota.OtaPackageKey;
import org.thingsboard.server.common.data.ota.OtaPackageType;
import org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus;
import org.thingsboard.server.common.data.ota.OtaPackageUtil;
-import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.transport.TransportServiceCallback;
import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient;
import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientProfile;
@@ -77,18 +77,23 @@ import static org.eclipse.leshan.core.model.ResourceModel.Type.OBJLNK;
import static org.eclipse.leshan.core.model.ResourceModel.Type.OPAQUE;
import static org.eclipse.leshan.core.model.ResourceModel.Type.STRING;
import static org.eclipse.leshan.core.model.ResourceModel.Type.TIME;
+import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_KEY;
+import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_PATH;
import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.DOWNLOADED;
import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.DOWNLOADING;
import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.FAILED;
import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.UPDATED;
import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.UPDATING;
import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.VERIFIED;
-import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_KEY;
-import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_PATH;
@Slf4j
public class LwM2mTransportUtil {
+ public static final String EVENT_AWAKE = "AWAKE";
+ public static final String RESPONSE_REQUEST_CHANNEL = "RESP_REQ";
+ public static final String RESPONSE_CHANNEL = "RESP";
+ public static final String OBSERVE_CHANNEL = "OBSERVE";
+
public static final String TRANSPORT_DEFAULT_LWM2M_VERSION = "1.0";
public static final String CLIENT_LWM2M_SETTINGS = "clientLwM2mSettings";
public static final String BOOTSTRAP = "bootstrap";
@@ -116,9 +121,6 @@ public class LwM2mTransportUtil {
public static final String LOG_LW2M_WARN = "warn";
public static final String LOG_LW2M_VALUE = "value";
- public static final int LWM2M_STRATEGY_1 = 1;
- public static final int LWM2M_STRATEGY_2 = 2;
-
public static final String CLIENT_NOT_AUTHORIZED = "Client not authorized";
public static final String LWM2M_VERSION_DEFAULT = "1.0";
@@ -132,18 +134,23 @@ public class LwM2mTransportUtil {
public static final String FINISH_VALUE_KEY = ",";
public static final String START_JSON_KEY = "{";
public static final String FINISH_JSON_KEY = "}";
- // public static final String contentFormatNameKey = "contentFormatName";
public static final String INFO_KEY = "info";
- // public static final String TIME_OUT_IN_MS = "timeOutInMs";
public static final String RESULT_KEY = "result";
public static final String ERROR_KEY = "error";
public static final String METHOD_KEY = "methodName";
+
// Firmware
+ public static final String FIRMWARE_UPDATE_COAP_RECOURSE = "firmwareUpdateCoapRecourse";
public static final String FW_UPDATE = "Firmware update";
- public static final Integer FW_ID = 5;
+ public static final Integer FW_5_ID = 5;
+ public static final Integer FW_19_ID = 19;
+
// Package W
- public static final String FW_PACKAGE_ID = "/5/0/0";
+ public static final String FW_PACKAGE_5_ID = "/5/0/0";
+ public static final String FW_PACKAGE_19_ID = "/19/0/0";
+ // Package URI
+ public static final String FW_PACKAGE_URI_ID = "/5/0/1";
// State R
public static final String FW_STATE_ID = "/5/0/3";
// Update Result R
@@ -151,15 +158,28 @@ public class LwM2mTransportUtil {
// PkgName R
public static final String FW_NAME_ID = "/5/0/6";
// PkgVersion R
- public static final String FW_VER_ID = "/5/0/7";
+ public static final String FW_5_VER_ID = "/5/0/7";
+ /**
+ * Quectel@Hi15RM1-HLB_V1.0@BC68JAR01A10,V150R100C20B300SP7,V150R100C20B300SP7@8
+ * BC68JAR01A10
+ * # Request prodct type number
+ * ATI
+ * Quectel
+ * BC68
+ * Revision:BC68JAR01A10
+ */
+ public static final String FW_3_VER_ID = "/3/0/3";
// Update E
public static final String FW_UPDATE_ID = "/5/0/2";
// Software
+ public static final String SOFTWARE_UPDATE_COAP_RECOURSE = "softwareUpdateCoapRecourse";
public static final String SW_UPDATE = "Software update";
public static final Integer SW_ID = 9;
// Package W
public static final String SW_PACKAGE_ID = "/9/0/2";
+ // Package URI
+ public static final String SW_PACKAGE_URI_ID = "/9/0/3";
// Update State R
public static final String SW_UPDATE_STATE_ID = "/9/0/7";
// Update Result R
@@ -232,7 +252,7 @@ public class LwM2mTransportUtil {
DELETE(11, "Delete"),
// only for RPC
- FW_UPDATE(12,"FirmwareUpdate");
+ FW_UPDATE(12, "FirmwareUpdate");
// FW_READ_INFO(12, "FirmwareReadInfo"),
// SW_READ_INFO(15, "SoftwareReadInfo"),
@@ -355,20 +375,11 @@ public class LwM2mTransportUtil {
* FirmwareUpdateStatus {
* DOWNLOADING, DOWNLOADED, VERIFIED, UPDATING, UPDATED, FAILED
*/
- public static OtaPackageUpdateStatus EqualsFwSateToFirmwareUpdateStatus(StateFw stateFw, UpdateResultFw updateResultFw) {
+ public static OtaPackageUpdateStatus equalsFwSateFwResultToFirmwareUpdateStatus(StateFw stateFw, UpdateResultFw updateResultFw) {
switch (updateResultFw) {
case INITIAL:
- switch (stateFw) {
- case IDLE:
- return VERIFIED;
- case DOWNLOADING:
- return DOWNLOADING;
- case DOWNLOADED:
- return DOWNLOADED;
- case UPDATING:
- return UPDATING;
- }
- case UPDATE_SUCCESSFULLY:
+ return equalsFwSateToFirmwareUpdateStatus(stateFw);
+ case UPDATE_SUCCESSFULLY:
return UPDATED;
case NOT_ENOUGH:
case OUT_OFF_MEMORY:
@@ -384,6 +395,41 @@ public class LwM2mTransportUtil {
}
}
+ public static OtaPackageUpdateStatus equalsFwResultToFirmwareUpdateStatus(UpdateResultFw updateResultFw) {
+ switch (updateResultFw) {
+ case INITIAL:
+ return VERIFIED;
+ case UPDATE_SUCCESSFULLY:
+ return UPDATED;
+ case NOT_ENOUGH:
+ case OUT_OFF_MEMORY:
+ case CONNECTION_LOST:
+ case INTEGRITY_CHECK_FAILURE:
+ case UNSUPPORTED_TYPE:
+ case INVALID_URI:
+ case UPDATE_FAILED:
+ case UNSUPPORTED_PROTOCOL:
+ return FAILED;
+ default:
+ throw new CodecException("Invalid value stateFw %s for FirmwareUpdateStatus.", updateResultFw.name());
+ }
+ }
+
+ public static OtaPackageUpdateStatus equalsFwSateToFirmwareUpdateStatus(StateFw stateFw) {
+ switch (stateFw) {
+ case IDLE:
+ return VERIFIED;
+ case DOWNLOADING:
+ return DOWNLOADING;
+ case DOWNLOADED:
+ return DOWNLOADED;
+ case UPDATING:
+ return UPDATING;
+ default:
+ throw new CodecException("Invalid value stateFw %d for FirmwareUpdateStatus.", stateFw);
+ }
+ }
+
/**
* SW Update State R
* 0: INITIAL Before downloading. (see 5.1.2.1)
@@ -497,6 +543,101 @@ public class LwM2mTransportUtil {
}
}
+ public enum LwM2MClientStrategy {
+ CLIENT_STRATEGY_1(1, "Read only resources marked as observation"),
+ CLIENT_STRATEGY_2(2, "Read all client resources");
+
+ public int code;
+ public String type;
+
+ LwM2MClientStrategy(int code, String type) {
+ this.code = code;
+ this.type = type;
+ }
+
+ public static LwM2MClientStrategy fromStrategyClientByType(String type) {
+ for (LwM2MClientStrategy to : LwM2MClientStrategy.values()) {
+ if (to.type.equals(type)) {
+ return to;
+ }
+ }
+ throw new IllegalArgumentException(String.format("Unsupported Client Strategy type : %s", type));
+ }
+
+ public static LwM2MClientStrategy fromStrategyClientByCode(int code) {
+ for (LwM2MClientStrategy to : LwM2MClientStrategy.values()) {
+ if (to.code == code) {
+ return to;
+ }
+ }
+ throw new IllegalArgumentException(String.format("Unsupported Client Strategy code : %s", code));
+ }
+ }
+
+ public enum LwM2MFirmwareUpdateStrategy {
+ OBJ_5_BINARY(1, "ObjectId 5, Binary"),
+ OBJ_5_TEMP_URL(2, "ObjectId 5, URI"),
+ OBJ_19_BINARY(3, "ObjectId 19, Binary");
+
+ public int code;
+ public String type;
+
+ LwM2MFirmwareUpdateStrategy(int code, String type) {
+ this.code = code;
+ this.type = type;
+ }
+
+ public static LwM2MFirmwareUpdateStrategy fromStrategyFwByType(String type) {
+ for (LwM2MFirmwareUpdateStrategy to : LwM2MFirmwareUpdateStrategy.values()) {
+ if (to.type.equals(type)) {
+ return to;
+ }
+ }
+ throw new IllegalArgumentException(String.format("Unsupported FW State type : %s", type));
+ }
+
+ public static LwM2MFirmwareUpdateStrategy fromStrategyFwByCode(int code) {
+ for (LwM2MFirmwareUpdateStrategy to : LwM2MFirmwareUpdateStrategy.values()) {
+ if (to.code == code) {
+ return to;
+ }
+ }
+ throw new IllegalArgumentException(String.format("Unsupported FW Strategy code : %s", code));
+ }
+ }
+
+ public enum LwM2MSoftwareUpdateStrategy {
+ BINARY(1, "ObjectId 9, Binary"),
+ TEMP_URL(2, "ObjectId 9, URI");
+
+ public int code;
+ public String type;
+
+ LwM2MSoftwareUpdateStrategy(int code, String type) {
+ this.code = code;
+ this.type = type;
+ }
+
+ public static LwM2MSoftwareUpdateStrategy fromStrategySwByType(String type) {
+ for (LwM2MSoftwareUpdateStrategy to : LwM2MSoftwareUpdateStrategy.values()) {
+ if (to.type.equals(type)) {
+ return to;
+ }
+ }
+ throw new IllegalArgumentException(String.format("Unsupported SW Strategy type : %s", type));
+ }
+
+ public static LwM2MSoftwareUpdateStrategy fromStrategySwByCode(int code) {
+ for (LwM2MSoftwareUpdateStrategy to : LwM2MSoftwareUpdateStrategy.values()) {
+ if (to.code == code) {
+ return to;
+ }
+ }
+ throw new IllegalArgumentException(String.format("Unsupported SW Strategy code : %s", code));
+ }
+
+ }
+
/**
* FirmwareUpdateStatus {
* DOWNLOADING, DOWNLOADED, VERIFIED, UPDATING, UPDATED, FAILED
@@ -534,10 +675,6 @@ public class LwM2mTransportUtil {
}
}
- public static final String EVENT_AWAKE = "AWAKE";
- public static final String RESPONSE_REQUEST_CHANNEL = "RESP_REQ";
- public static final String RESPONSE_CHANNEL = "RESP";
- public static final String OBSERVE_CHANNEL = "OBSERVE";
public static boolean equalsResourceValue(Object valueOld, Object valueNew, ResourceModel.Type type, LwM2mPath
resourcePath) throws CodecException {
@@ -558,6 +695,36 @@ public class LwM2mTransportUtil {
}
}
+ public static LwM2mOtaConvert convertOtaUpdateValueToString (String pathIdVer, Object value, ResourceModel.Type currentType) {
+ String path = convertPathFromIdVerToObjectId(pathIdVer);
+ LwM2mOtaConvert lwM2mOtaConvert = new LwM2mOtaConvert();
+ if (path != null) {
+ if (FW_STATE_ID.equals(path)) {
+ lwM2mOtaConvert.setCurrentType(STRING);
+ lwM2mOtaConvert.setValue(StateFw.fromStateFwByCode(((Long) value).intValue()).type);
+ return lwM2mOtaConvert;
+ }
+ else if (FW_RESULT_ID.equals(path)) {
+ lwM2mOtaConvert.setCurrentType(STRING);
+ lwM2mOtaConvert.setValue(UpdateResultFw.fromUpdateResultFwByCode(((Long) value).intValue()).type);
+ return lwM2mOtaConvert;
+ }
+ else if (SW_UPDATE_STATE_ID.equals(path)) {
+ lwM2mOtaConvert.setCurrentType(STRING);
+ lwM2mOtaConvert.setValue(UpdateStateSw.fromUpdateStateSwByCode(((Long) value).intValue()).type);
+ return lwM2mOtaConvert;
+ }
+ else if (SW_RESULT_ID.equals(path)) {
+ lwM2mOtaConvert.setCurrentType(STRING);
+ lwM2mOtaConvert.setValue(UpdateResultSw.fromUpdateResultSwByCode(((Long) value).intValue()).type);
+ return lwM2mOtaConvert;
+ }
+ }
+ lwM2mOtaConvert.setCurrentType(currentType);
+ lwM2mOtaConvert.setValue(value);
+ return lwM2mOtaConvert;
+ }
+
public static LwM2mNode getLvM2mNodeToObject(LwM2mNode content) {
if (content instanceof LwM2mObject) {
return (LwM2mObject) content;
@@ -633,11 +800,6 @@ public class LwM2mTransportUtil {
return null;
}
- public static int getClientOnlyObserveAfterConnect(LwM2mClientProfile profile) {
- return profile.getPostClientLwM2mSettings().getAsJsonObject().has("clientOnlyObserveAfterConnect") ?
- profile.getPostClientLwM2mSettings().getAsJsonObject().get("clientOnlyObserveAfterConnect").getAsInt() : 1;
- }
-
private static boolean getValidateCredentialsBodyFromThingsboard(JsonObject objectMsg) {
return (objectMsg != null &&
!objectMsg.isJsonNull() &&
@@ -914,7 +1076,7 @@ public class LwM2mTransportUtil {
case GREATER_THAN:
case LESSER_THAN:
case STEP:
- if (value.getClass().getSimpleName().equals("String") ) {
+ if (value.getClass().getSimpleName().equals("String")) {
value = Double.valueOf((String) value);
}
return serviceImpl.converter.convertValue(value, equalsResourceTypeGetSimpleName(value), FLOAT, new LwM2mPath(target));
@@ -928,11 +1090,11 @@ public class LwM2mTransportUtil {
return new Attribute(key, attrValue);
} catch (Exception e) {
log.error("CreateAttribute, not valid parameter key: [{}], attrValue: [{}], error: [{}]", key, attrValue, e.getMessage());
- return null;
+ return null;
}
}
- public static boolean isFwSwWords (String pathName) {
+ public static boolean isFwSwWords(String pathName) {
return OtaPackageUtil.getAttributeKey(OtaPackageType.FIRMWARE, OtaPackageKey.VERSION).equals(pathName)
|| OtaPackageUtil.getAttributeKey(OtaPackageType.FIRMWARE, OtaPackageKey.TITLE).equals(pathName)
|| OtaPackageUtil.getAttributeKey(OtaPackageType.FIRMWARE, OtaPackageKey.CHECKSUM).equals(pathName)
diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClient.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClient.java
index 1fc876cc45..78f9ffb349 100644
--- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClient.java
+++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClient.java
@@ -26,6 +26,7 @@ import org.eclipse.leshan.core.node.LwM2mObjectInstance;
import org.eclipse.leshan.core.node.LwM2mPath;
import org.eclipse.leshan.core.node.LwM2mResource;
import org.eclipse.leshan.core.node.LwM2mSingleResource;
+import org.eclipse.leshan.core.request.ContentFormat;
import org.eclipse.leshan.server.model.LwM2mModelProvider;
import org.eclipse.leshan.server.registration.Registration;
import org.eclipse.leshan.server.security.SecurityInfo;
@@ -69,7 +70,8 @@ public class LwM2mClient implements Cloneable {
@Getter
private final String endpoint;
private final Lock lock;
- @Getter @Setter
+ @Getter
+ @Setter
private LwM2MClientState state;
@Getter
private final Map resources;
@@ -92,8 +94,6 @@ public class LwM2mClient implements Cloneable {
@Getter
private UUID deviceId;
@Getter
- private UUID sessionId;
- @Getter
private SessionInfoProto session;
@Getter
private UUID profileId;
@@ -133,8 +133,6 @@ public class LwM2mClient implements Cloneable {
this.credentials = credentials;
this.profileId = profileId;
this.init = false;
- this.fwUpdate = new LwM2mFwSwUpdate(this, OtaPackageType.FIRMWARE);
- this.swUpdate = new LwM2mFwSwUpdate(this, OtaPackageType.SOFTWARE);
if (this.credentials != null && this.credentials.hasDeviceInfo()) {
this.session = createSession(nodeId, sessionId, credentials);
this.deviceId = new UUID(session.getDeviceIdMSB(), session.getDeviceIdLSB());
@@ -385,5 +383,31 @@ public class LwM2mClient implements Cloneable {
}
}
+ public ContentFormat getDefaultContentFormat() {
+ if (registration == null) {
+ return ContentFormat.DEFAULT;
+ } else if (registration.getLwM2mVersion().equals("1.0")) {
+ return ContentFormat.TLV;
+ } else {
+ return ContentFormat.TEXT;
+ }
+ }
+
+ public LwM2mFwSwUpdate getFwUpdate (LwM2mClientContext clientContext) {
+ if (this.fwUpdate == null) {
+ LwM2mClientProfile lwM2mClientProfile = clientContext.getProfile(this.getProfileId());
+ this.fwUpdate = new LwM2mFwSwUpdate(this, OtaPackageType.FIRMWARE, lwM2mClientProfile.getFwUpdateStrategy());
+ }
+ return this.fwUpdate;
+ }
+
+ public LwM2mFwSwUpdate getSwUpdate (LwM2mClientContext clientContext) {
+ if (this.swUpdate == null) {
+ LwM2mClientProfile lwM2mClientProfile = clientContext.getProfile(this.getProfileId());
+ this.swUpdate = new LwM2mFwSwUpdate(this, OtaPackageType.SOFTWARE, lwM2mClientProfile.getSwUpdateStrategy());
+ }
+ return this.fwUpdate;
+ }
+
}
diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientContext.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientContext.java
index e2e24ad1ff..613a8b7971 100644
--- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientContext.java
+++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientContext.java
@@ -16,7 +16,6 @@
package org.thingsboard.server.transport.lwm2m.server.client;
import org.eclipse.leshan.server.registration.Registration;
-import org.eclipse.leshan.server.security.SecurityInfo;
import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse;
import org.thingsboard.server.gen.transport.TransportProtos;
@@ -40,15 +39,6 @@ public interface LwM2mClientContext {
void unregister(LwM2mClient client, Registration registration) throws LwM2MClientStateException;
-
-// LwM2mClient getOrRegister(Registration registration);
-
-// LwM2mClient registerOrUpdate(Registration registration);
-
-// LwM2mClient fetchClientByEndpoint(String endpoint);
-
-// Registration getRegistration(String registrationId);
-
Collection getLwM2mClients();
Map getProfiles();
@@ -61,7 +51,7 @@ public interface LwM2mClientContext {
LwM2mClientProfile profileUpdate(DeviceProfile deviceProfile);
- Set getSupportedIdVerInClient(Registration registration);
+ Set getSupportedIdVerInClient(LwM2mClient registration);
LwM2mClient getClientByDeviceId(UUID deviceId);
diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientContextImpl.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientContextImpl.java
index aa204ae868..02d3425ede 100644
--- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientContextImpl.java
+++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientContextImpl.java
@@ -36,6 +36,7 @@ import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.Predicate;
import static org.eclipse.leshan.core.SecurityMode.NO_SEC;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertPathFromObjectIdToIdVer;
@@ -96,12 +97,7 @@ public class LwM2mClientContextImpl implements LwM2mClientContext {
if (!LwM2MClientState.REGISTERED.equals(lwM2MClient.getState())) {
throw new LwM2MClientStateException(lwM2MClient.getState(), "Client is in invalid state.");
}
- Registration currentRegistration = lwM2MClient.getRegistration();
- if (currentRegistration.getId().equals(registration.getId())) {
- lwM2MClient.setRegistration(registration);
- } else {
- throw new LwM2MClientStateException(lwM2MClient.getState(), "Client has different registration.");
- }
+ lwM2MClient.setRegistration(registration);
} finally {
lwM2MClient.unlock();
}
@@ -120,7 +116,6 @@ public class LwM2mClientContextImpl implements LwM2mClientContext {
lwM2MClient.setState(LwM2MClientState.UNREGISTERED);
lwM2mClientsByEndpoint.remove(lwM2MClient.getEndpoint());
this.securityStore.remove(lwM2MClient.getEndpoint());
- this.lwM2mClientsByRegistrationId.remove(registration.getId());
UUID profileId = lwM2MClient.getProfileId();
if (profileId != null) {
Optional otherClients = lwM2mClientsByRegistrationId.values().stream().filter(e -> e.getProfileId().equals(profileId)).findFirst();
@@ -143,14 +138,19 @@ public class LwM2mClientContextImpl implements LwM2mClientContext {
@Override
public LwM2mClient getClientBySessionInfo(TransportProtos.SessionInfoProto sessionInfo) {
- LwM2mClient lwM2mClient = lwM2mClientsByEndpoint.values().stream().filter(c ->
+ LwM2mClient lwM2mClient = null;
+ Predicate isClientFilter = c ->
(new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB()))
- .equals((new UUID(c.getSession().getSessionIdMSB(), c.getSession().getSessionIdLSB())))
-
- ).findAny().orElse(null);
+ .equals((new UUID(c.getSession().getSessionIdMSB(), c.getSession().getSessionIdLSB())));
+ if (this.lwM2mClientsByEndpoint.size() > 0) {
+ lwM2mClient = this.lwM2mClientsByEndpoint.values().stream().filter(isClientFilter).findAny().orElse(null);
+ }
+ if (lwM2mClient == null && this.lwM2mClientsByRegistrationId.size() > 0) {
+ lwM2mClient = this.lwM2mClientsByRegistrationId.values().stream().filter(isClientFilter).findAny().orElse(null);
+ }
if (lwM2mClient == null) {
log.warn("Device TimeOut? lwM2mClient is null.");
- log.warn("SessionInfo input [{}], lwM2mClientsByEndpoint size: [{}]", sessionInfo, lwM2mClientsByEndpoint.values().size());
+ log.warn("SessionInfo input [{}], lwM2mClientsByEndpoint size: [{}] lwM2mClientsByRegistrationId: [{}]", sessionInfo, lwM2mClientsByEndpoint.values(), lwM2mClientsByRegistrationId.values());
log.error("", new RuntimeException());
}
return lwM2mClient;
@@ -205,19 +205,13 @@ public class LwM2mClientContextImpl implements LwM2mClientContext {
}
}
- /**
- * if isVer - ok or default ver=DEFAULT_LWM2M_VERSION
- *
- * @param registration -
- * @return - all objectIdVer in client
- */
@Override
- public Set getSupportedIdVerInClient(Registration registration) {
+ public Set getSupportedIdVerInClient(LwM2mClient client) {
Set clientObjects = ConcurrentHashMap.newKeySet();
- Arrays.stream(registration.getObjectLinks()).forEach(url -> {
- LwM2mPath pathIds = new LwM2mPath(url.getUrl());
+ Arrays.stream(client.getRegistration().getObjectLinks()).forEach(link -> {
+ LwM2mPath pathIds = new LwM2mPath(link.getUrl());
if (!pathIds.isRoot()) {
- clientObjects.add(convertPathFromObjectIdToIdVer(url.getUrl(), registration));
+ clientObjects.add(convertPathFromObjectIdToIdVer(link.getUrl(), client.getRegistration()));
}
});
return (clientObjects.size() > 0) ? clientObjects : null;
diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientProfile.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientProfile.java
index 19af453f3c..67edbf2747 100644
--- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientProfile.java
+++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientProfile.java
@@ -20,15 +20,23 @@ import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import lombok.Data;
import org.thingsboard.server.common.data.id.TenantId;
+import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2MClientStrategy;
+import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2MFirmwareUpdateStrategy;
+import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2MSoftwareUpdateStrategy;
@Data
public class LwM2mClientProfile {
+ private final String clientStrategyStr = "clientStrategy";
+ private final String fwUpdateStrategyStr = "fwUpdateStrategy";
+ private final String swUpdateStrategyStr = "swUpdateStrategy";
private TenantId tenantId;
/**
- * {"clientLwM2mSettings": {
- * clientUpdateValueAfterConnect: false;
- * }
+ * "clientLwM2mSettings": {
+ * "fwUpdateStrategy": "1",
+ * "swUpdateStrategy": "1",
+ * "clientStrategy": "1"
+ * }
**/
private JsonObject postClientLwM2mSettings;
@@ -85,5 +93,21 @@ public class LwM2mClientProfile {
}
}
+ public int getClientStrategy() {
+ return this.postClientLwM2mSettings.getAsJsonObject().has(this.clientStrategyStr) ?
+ Integer.parseInt(this.postClientLwM2mSettings.getAsJsonObject().get(this.clientStrategyStr).getAsString()) :
+ LwM2MClientStrategy.CLIENT_STRATEGY_1.code;
+ }
+ public int getFwUpdateStrategy() {
+ return this.postClientLwM2mSettings.getAsJsonObject().has(this.fwUpdateStrategyStr) ?
+ Integer.parseInt(this.postClientLwM2mSettings.getAsJsonObject().get(this.fwUpdateStrategyStr).getAsString()) :
+ LwM2MFirmwareUpdateStrategy.OBJ_5_BINARY.code;
+ }
+
+ public int getSwUpdateStrategy() {
+ return this.postClientLwM2mSettings.getAsJsonObject().has(this.swUpdateStrategyStr) ?
+ Integer.parseInt(this.postClientLwM2mSettings.getAsJsonObject().get(this.swUpdateStrategyStr).getAsString()) :
+ LwM2MSoftwareUpdateStrategy.BINARY.code;
+ }
}
diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/Lwm2mClientRpcRequest.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientRpcRequest.java
similarity index 98%
rename from common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/Lwm2mClientRpcRequest.java
rename to common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientRpcRequest.java
index 40dace0b5e..33525426e3 100644
--- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/Lwm2mClientRpcRequest.java
+++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientRpcRequest.java
@@ -57,7 +57,7 @@ import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.v
@Slf4j
@Data
-public class Lwm2mClientRpcRequest {
+public class LwM2mClientRpcRequest {
private Registration registration;
private TransportProtos.SessionInfoProto sessionInfo;
@@ -75,10 +75,10 @@ public class Lwm2mClientRpcRequest {
private String infoMsg;
private String responseCode;
- public Lwm2mClientRpcRequest() {
+ public LwM2mClientRpcRequest() {
}
- public Lwm2mClientRpcRequest(LwM2mTypeOper lwM2mTypeOper, String bodyParams, int requestId,
+ public LwM2mClientRpcRequest(LwM2mTypeOper lwM2mTypeOper, String bodyParams, int requestId,
TransportProtos.SessionInfoProto sessionInfo, Registration registration, DefaultLwM2MTransportMsgHandler handler) {
this.registration = registration;
this.sessionInfo = sessionInfo;
diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mFwSwUpdate.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mFwSwUpdate.java
index 7a93d15988..6828761fb0 100644
--- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mFwSwUpdate.java
+++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mFwSwUpdate.java
@@ -20,6 +20,7 @@ import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.leshan.core.request.ContentFormat;
+import org.eclipse.leshan.server.registration.Registration;
import org.thingsboard.server.common.data.ota.OtaPackageType;
import org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus;
import org.thingsboard.server.gen.transport.TransportProtos;
@@ -32,21 +33,32 @@ import java.util.List;
import java.util.UUID;
import java.util.concurrent.CopyOnWriteArrayList;
+import static org.eclipse.californium.core.coap.CoAP.ResponseCode.CONTENT;
import static org.thingsboard.server.common.data.ota.OtaPackageKey.STATE;
import static org.thingsboard.server.common.data.ota.OtaPackageType.FIRMWARE;
import static org.thingsboard.server.common.data.ota.OtaPackageType.SOFTWARE;
+import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.DOWNLOADED;
+import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.FAILED;
+import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.INITIATED;
+import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.UPDATED;
import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.UPDATING;
import static org.thingsboard.server.common.data.ota.OtaPackageUtil.getAttributeKey;
-import static org.eclipse.californium.core.coap.CoAP.ResponseCode.CONTENT;
+import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FIRMWARE_UPDATE_COAP_RECOURSE;
+import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_3_VER_ID;
+import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_5_VER_ID;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_NAME_ID;
-import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_PACKAGE_ID;
+import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_PACKAGE_19_ID;
+import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_PACKAGE_5_ID;
+import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_PACKAGE_URI_ID;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_RESULT_ID;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_STATE_ID;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_UPDATE;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_UPDATE_ID;
-import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_VER_ID;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_ERROR;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_INFO;
+import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2MFirmwareUpdateStrategy.OBJ_19_BINARY;
+import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2MFirmwareUpdateStrategy.OBJ_5_BINARY;
+import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2MFirmwareUpdateStrategy.OBJ_5_TEMP_URL;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.EXECUTE;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.OBSERVE;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.WRITE_REPLACE;
@@ -59,6 +71,7 @@ import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.S
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.SW_UPDATE_STATE_ID;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.SW_VER_ID;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertPathFromObjectIdToIdVer;
+import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.equalsFwSateToFirmwareUpdateStatus;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.splitCamelCaseString;
@Slf4j
@@ -106,23 +119,29 @@ public class LwM2mFwSwUpdate {
private final List pendingInfoRequestsStart;
@Getter
@Setter
- private volatile Lwm2mClientRpcRequest rpcRequest;
+ private volatile LwM2mClientRpcRequest rpcRequest;
+ @Getter
+ @Setter
+ private volatile int updateStrategy;
- public LwM2mFwSwUpdate(LwM2mClient lwM2MClient, OtaPackageType type) {
+ public LwM2mFwSwUpdate(LwM2mClient lwM2MClient, OtaPackageType type, int updateStrategy) {
this.lwM2MClient = lwM2MClient;
this.pendingInfoRequestsStart = new CopyOnWriteArrayList<>();
this.type = type;
this.stateUpdate = null;
+ this.updateStrategy = updateStrategy;
this.initPathId();
}
private void initPathId() {
if (FIRMWARE.equals(this.type)) {
- this.pathPackageId = FW_PACKAGE_ID;
+ this.pathPackageId = LwM2mTransportUtil.LwM2MFirmwareUpdateStrategy.OBJ_5_BINARY.code == this.updateStrategy ?
+ FW_PACKAGE_5_ID : LwM2mTransportUtil.LwM2MFirmwareUpdateStrategy.OBJ_5_TEMP_URL.code == this.updateStrategy ?
+ FW_PACKAGE_URI_ID : FW_PACKAGE_19_ID;
this.pathStateId = FW_STATE_ID;
this.pathResultId = FW_RESULT_ID;
this.pathNameId = FW_NAME_ID;
- this.pathVerId = FW_VER_ID;
+ this.pathVerId = FW_5_VER_ID;
this.pathInstallId = FW_UPDATE_ID;
this.wUpdate = FW_UPDATE;
} else if (SOFTWARE.equals(this.type)) {
@@ -143,13 +162,13 @@ public class LwM2mFwSwUpdate {
}
if (this.pendingInfoRequestsStart.size() == 0) {
this.infoFwSwUpdate = false;
- if (!OtaPackageUpdateStatus.DOWNLOADING.name().equals(this.stateUpdate)) {
- boolean conditionalStart = this.type.equals(FIRMWARE) ? this.conditionalFwUpdateStart() :
- this.conditionalSwUpdateStart();
- if (conditionalStart) {
- this.writeFwSwWare(handler, request);
- }
+// if (!FAILED.name().equals(this.stateUpdate)) {
+ boolean conditionalStart = this.type.equals(FIRMWARE) ? this.conditionalFwUpdateStart(handler) :
+ this.conditionalSwUpdateStart(handler);
+ if (conditionalStart) {
+ this.writeFwSwWare(handler, request);
}
+// }
}
}
@@ -159,32 +178,41 @@ public class LwM2mFwSwUpdate {
*/
public void writeFwSwWare(DefaultLwM2MTransportMsgHandler handler, LwM2mTransportRequest request) {
if (this.currentId != null) {
- this.stateUpdate = OtaPackageUpdateStatus.DOWNLOADING.name();
+ this.stateUpdate = OtaPackageUpdateStatus.INITIATED.name();
this.sendLogs(handler, WRITE_REPLACE.name(), LOG_LW2M_INFO, null);
- int chunkSize = 0;
- int chunk = 0;
- byte[] firmwareChunk = handler.otaPackageDataCache.get(this.currentId.toString(), chunkSize, chunk);
String targetIdVer = convertPathFromObjectIdToIdVer(this.pathPackageId, this.lwM2MClient.getRegistration());
String fwMsg = String.format("%s: Start type operation %s paths: %s", LOG_LW2M_INFO,
- LwM2mTransportUtil.LwM2mTypeOper.FW_UPDATE.name(), FW_PACKAGE_ID);
- handler.sendLogsToThingsboard(lwM2MClient, fwMsg);
+ LwM2mTransportUtil.LwM2mTypeOper.FW_UPDATE.name(), this.pathPackageId);
+ handler.sendLogsToThingsboard(fwMsg, lwM2MClient.getRegistration().getId());
log.warn("8) Start firmware Update. Send save to: [{}] ver: [{}] path: [{}]", this.lwM2MClient.getDeviceName(), this.currentVersion, targetIdVer);
- request.sendAllRequest(this.lwM2MClient.getRegistration(), targetIdVer, WRITE_REPLACE, ContentFormat.OPAQUE.getName(),
- firmwareChunk, handler.config.getTimeout(), this.rpcRequest);
- }
- else {
+ if (LwM2mTransportUtil.LwM2MFirmwareUpdateStrategy.OBJ_5_BINARY.code == this.updateStrategy) {
+ int chunkSize = 0;
+ int chunk = 0;
+ byte[] firmwareChunk = handler.otaPackageDataCache.get(this.currentId.toString(), chunkSize, chunk);
+ request.sendAllRequest(this.lwM2MClient, targetIdVer, WRITE_REPLACE, ContentFormat.OPAQUE,
+ firmwareChunk, handler.config.getTimeout(), this.rpcRequest);
+ } else if (LwM2mTransportUtil.LwM2MFirmwareUpdateStrategy.OBJ_5_TEMP_URL.code == this.updateStrategy) {
+ String apiFont = "coap://176.36.143.9:5685";
+ String uri = apiFont + "/" + FIRMWARE_UPDATE_COAP_RECOURSE + "/" + this.currentId.toString();
+ log.warn("89) coapUri: [{}]", uri);
+ request.sendAllRequest(this.lwM2MClient, targetIdVer, WRITE_REPLACE, null,
+ uri, handler.config.getTimeout(), this.rpcRequest);
+ } else if (LwM2mTransportUtil.LwM2MFirmwareUpdateStrategy.OBJ_19_BINARY.code == this.updateStrategy) {
+
+ }
+ } else {
String msgError = "FirmWareId is null.";
log.warn("6) [{}]", msgError);
if (this.rpcRequest != null) {
handler.sentRpcResponse(this.rpcRequest, CONTENT.name(), msgError, LOG_LW2M_ERROR);
}
- log.error (msgError);
+ log.error(msgError);
this.sendLogs(handler, WRITE_REPLACE.name(), LOG_LW2M_ERROR, msgError);
}
}
public void sendLogs(DefaultLwM2MTransportMsgHandler handler, String typeOper, String typeInfo, String msgError) {
- this.sendSateOnThingsBoard(handler);
+// this.sendSateOnThingsBoard(handler);
String msg = String.format("%s: %s, %s, pkgVer: %s: pkgName - %s state - %s.",
typeInfo, this.wUpdate, typeOper, this.currentVersion, this.currentTitle, this.stateUpdate);
if (LOG_LW2M_ERROR.equals(typeInfo)) {
@@ -200,32 +228,49 @@ public class LwM2mFwSwUpdate {
* send execute
*/
public void executeFwSwWare(DefaultLwM2MTransportMsgHandler handler, LwM2mTransportRequest request) {
- this.setStateUpdate(UPDATING.name());
this.sendLogs(handler, EXECUTE.name(), LOG_LW2M_INFO, null);
- request.sendAllRequest(this.lwM2MClient.getRegistration(), this.pathInstallId, EXECUTE, ContentFormat.TLV.getName(),
- null, 0, this.rpcRequest);
+ request.sendAllRequest(this.lwM2MClient, this.pathInstallId, EXECUTE, null, 0, this.rpcRequest);
}
/**
- * Firmware start:
+ * Firmware start: Check if the version has changed and launch a new update.
+ * -ObjectId 5, Binary or ObjectId 5, URI
* -- If the result of the update - errors (more than 1) - This means that the previous. the update failed.
* - We launch the update regardless of the state of the firmware and its version.
- * -- If the result of the update is not errors (equal to 1 or 0) and ver is not empty - This means that before the update has passed.
- * -- If the result of the update is not errors and is empty - This means that there has not been an update yet.
- * - Check if the version has changed and launch a new update.
+ * -- If the result of the update - errors (more than 1) - This means that the previous. the update failed.
+ * * ObjectId 5, Binary
+ * -- If the result of the update is not errors (equal to 1 or 0) and ver in Object 5 is not empty - it means that the previous update has passed.
+ * Compare current versions by equals.
+ * * ObjectId 5, URI
+ * -- If the result of the update is not errors (equal to 1 or 0) and ver in Object 5 is not empty - it means that the previous update has passed.
+ * Compare current versions by contains.
*/
- private boolean conditionalFwUpdateStart() {
+ private boolean conditionalFwUpdateStart(DefaultLwM2MTransportMsgHandler handler) {
Long updateResultFw = (Long) this.lwM2MClient.getResourceValue(null, this.pathResultId);
+ String ver5 = (String) this.lwM2MClient.getResourceValue(null, this.pathVerId);
+ String pathName = (String) this.lwM2MClient.getResourceValue(null, this.pathNameId);
+ String ver3 = (String) this.lwM2MClient.getResourceValue(null, FW_3_VER_ID);
// #1/#2
- return updateResultFw > LwM2mTransportUtil.UpdateResultFw.UPDATE_SUCCESSFULLY.code ||
- (
- (updateResultFw <= LwM2mTransportUtil.UpdateResultFw.UPDATE_SUCCESSFULLY.code
- ) &&
- (
- (this.currentVersion != null && !this.currentVersion.equals(this.lwM2MClient.getResourceValue(null, this.pathVerId))) ||
- (this.currentTitle != null && !this.currentTitle.equals(this.lwM2MClient.getResourceValue(null, this.pathNameId)))
- )
- );
+ String fwMsg = null;
+ if ((this.currentVersion != null && (
+ ver5 != null && ver5.equals(this.currentVersion) ||
+ ver3 != null && ver3.contains(this.currentVersion)
+ )) ||
+ (this.currentTitle != null && pathName != null && this.currentTitle.equals(pathName))) {
+ fwMsg = String.format("%s: The update was interrupted. The device has the same version: %s.", LOG_LW2M_ERROR,
+ this.currentVersion);
+ }
+ else if (updateResultFw != null && updateResultFw > LwM2mTransportUtil.UpdateResultFw.UPDATE_SUCCESSFULLY.code) {
+ fwMsg = String.format("%s: The update was interrupted. The device has the status UpdateResult: error (%d).", LOG_LW2M_ERROR,
+ updateResultFw);
+ }
+ if (fwMsg != null) {
+ handler.sendLogsToThingsboard(fwMsg, lwM2MClient.getRegistration().getId());
+ return false;
+ }
+ else {
+ return true;
+ }
}
@@ -249,7 +294,7 @@ public class LwM2mFwSwUpdate {
/**
* After operation Execute success inspection Update Result :
- * > 1 error: "Firmware updated successfully"
+ * > 1 error: "Firmware updated successfully"
*/
public boolean conditionalFwExecuteAfterError() {
Long updateResult = (Long) this.lwM2MClient.getResourceValue(null, this.pathResultId);
@@ -265,7 +310,7 @@ public class LwM2mFwSwUpdate {
* - If Update Result is not errors and ver is not empty - This means that before unInstall update
* * - Check if the version has changed and launch a new update.
*/
- private boolean conditionalSwUpdateStart() {
+ private boolean conditionalSwUpdateStart(DefaultLwM2MTransportMsgHandler handler) {
Long updateResultSw = (Long) this.lwM2MClient.getResourceValue(null, this.pathResultId);
// #1/#2
return updateResultSw >= LwM2mTransportUtil.UpdateResultSw.NOT_ENOUGH_STORAGE.code ||
@@ -293,7 +338,7 @@ public class LwM2mFwSwUpdate {
* -- inspection Update Result:
* ---- FW если Update Result == 1 ("Firmware updated successfully") или SW если Update Result == 2 ("Software successfully installed.")
* -- fw_state/sw_state = UPDATED
- *
+ *
* After finish operation Execute (error):
* -- inspection updateResult and send to thingsboard info about error
* --- send to telemetry ( key - this is name Update Result in model) (
@@ -326,7 +371,7 @@ public class LwM2mFwSwUpdate {
/**
* After operation Execute success inspection Update Result :
- * >= 50 - error "NOT_ENOUGH_STORAGE"
+ * >= 50 - error "NOT_ENOUGH_STORAGE"
*/
public boolean conditionalSwExecuteAfterError() {
Long updateResult = (Long) this.lwM2MClient.getResourceValue(null, this.pathResultId);
@@ -334,10 +379,10 @@ public class LwM2mFwSwUpdate {
}
private void observeStateUpdate(DefaultLwM2MTransportMsgHandler handler, LwM2mTransportRequest request) {
- request.sendAllRequest(lwM2MClient.getRegistration(),
+ request.sendAllRequest(lwM2MClient,
convertPathFromObjectIdToIdVer(this.pathStateId, this.lwM2MClient.getRegistration()), OBSERVE,
null, null, 0, null);
- request.sendAllRequest(lwM2MClient.getRegistration(),
+ request.sendAllRequest(lwM2MClient,
convertPathFromObjectIdToIdVer(this.pathResultId, this.lwM2MClient.getRegistration()), OBSERVE,
null, null, 0, null);
}
@@ -355,18 +400,75 @@ public class LwM2mFwSwUpdate {
public void sendReadObserveInfo(LwM2mTransportRequest request) {
this.infoFwSwUpdate = true;
- this.pendingInfoRequestsStart.add(convertPathFromObjectIdToIdVer(
- this.pathVerId, this.lwM2MClient.getRegistration()));
- this.pendingInfoRequestsStart.add(convertPathFromObjectIdToIdVer(
- this.pathNameId, this.lwM2MClient.getRegistration()));
this.pendingInfoRequestsStart.add(convertPathFromObjectIdToIdVer(
this.pathStateId, this.lwM2MClient.getRegistration()));
this.pendingInfoRequestsStart.add(convertPathFromObjectIdToIdVer(
this.pathResultId, this.lwM2MClient.getRegistration()));
+ this.pendingInfoRequestsStart.add(convertPathFromObjectIdToIdVer(
+ FW_3_VER_ID, this.lwM2MClient.getRegistration()));
+ if (LwM2mTransportUtil.LwM2MFirmwareUpdateStrategy.OBJ_5_BINARY.code == this.updateStrategy ||
+ LwM2mTransportUtil.LwM2MFirmwareUpdateStrategy.OBJ_19_BINARY.code == this.updateStrategy ||
+ SOFTWARE.equals(this.type)) {
+ this.pendingInfoRequestsStart.add(convertPathFromObjectIdToIdVer(
+ this.pathVerId, this.lwM2MClient.getRegistration()));
+ this.pendingInfoRequestsStart.add(convertPathFromObjectIdToIdVer(
+ this.pathNameId, this.lwM2MClient.getRegistration()));
+ }
this.pendingInfoRequestsStart.forEach(pathIdVer -> {
- request.sendAllRequest(this.lwM2MClient.getRegistration(), pathIdVer, OBSERVE, ContentFormat.TLV.getName(),
- null, 0, this.rpcRequest);
+ request.sendAllRequest(this.lwM2MClient, pathIdVer, OBSERVE, null, 0, this.rpcRequest);
});
}
+
+ /**
+ * Before operation Execute (FwUpdate) inspection Update Result :
+ * - after finished operation Write result: success (FwUpdate): fw_state = DOWNLOADED
+ * - before start operation Execute (FwUpdate) Update Result = 0 - Initial value
+ * - start Execute (FwUpdate)
+ * After finished operation Execute (FwUpdate) inspection Update Result :
+ * - after start operation Execute (FwUpdate): fw_state = UPDATING
+ * - after success finished operation Execute (FwUpdate) Update Result == 1 ("Firmware updated successfully")
+ * - finished operation Execute (FwUpdate)
+ */
+ public void updateStateOta(DefaultLwM2MTransportMsgHandler handler, LwM2mTransportRequest request,
+ Registration registration, String path, int value) {
+ if (OBJ_5_BINARY.code == this.getUpdateStrategy()) {
+ if ((convertPathFromObjectIdToIdVer(FW_RESULT_ID, registration).equals(path))) {
+ if (DOWNLOADED.name().equals(this.getStateUpdate())
+ && this.conditionalFwExecuteStart()) {
+ this.executeFwSwWare(handler, request);
+ } else if (UPDATING.name().equals(this.getStateUpdate())
+ && this.conditionalFwExecuteAfterSuccess()) {
+ this.finishFwSwUpdate(handler, true);
+ } else if (UPDATING.name().equals(this.getStateUpdate())
+ && this.conditionalFwExecuteAfterError()) {
+ this.finishFwSwUpdate(handler, false);
+ }
+ }
+ } else if (OBJ_5_TEMP_URL.code == this.getUpdateStrategy()) {
+ if (this.currentId != null && (convertPathFromObjectIdToIdVer(FW_STATE_ID, registration).equals(path))) {
+ String state = equalsFwSateToFirmwareUpdateStatus(LwM2mTransportUtil.StateFw.fromStateFwByCode(value)).name();
+ if (StringUtils.isNotEmpty(state) && !FAILED.name().equals(this.stateUpdate) && !state.equals(this.stateUpdate)) {
+ this.stateUpdate = state;
+ this.sendSateOnThingsBoard(handler);
+ }
+ if (value == LwM2mTransportUtil.StateFw.DOWNLOADED.code) {
+ this.executeFwSwWare(handler, request);
+ }
+ handler.firmwareUpdateState.put(lwM2MClient.getEndpoint(), value);
+ }
+ if ((convertPathFromObjectIdToIdVer(FW_RESULT_ID, registration).equals(path))) {
+ if (this.currentId != null && value == LwM2mTransportUtil.UpdateResultFw.INITIAL.code) {
+ this.setStateUpdate(INITIATED.name());
+ } else if (this.currentId != null && value == LwM2mTransportUtil.UpdateResultFw.UPDATE_SUCCESSFULLY.code) {
+ this.setStateUpdate(UPDATED.name());
+ } else if (value > LwM2mTransportUtil.UpdateResultFw.UPDATE_SUCCESSFULLY.code) {
+ this.setStateUpdate(FAILED.name());
+ }
+ this.sendSateOnThingsBoard(handler);
+ }
+ } else if (OBJ_19_BINARY.code == this.getUpdateStrategy()) {
+
+ }
+ }
}
diff --git a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/session/GatewaySessionHandler.java b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/session/GatewaySessionHandler.java
index 7882ad2410..891c466151 100644
--- a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/session/GatewaySessionHandler.java
+++ b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/session/GatewaySessionHandler.java
@@ -259,8 +259,10 @@ public class GatewaySessionHandler {
transportService.process(TransportProtos.TransportToDeviceActorMsg.newBuilder()
.setSessionInfo(deviceSessionInfo)
.setSessionEvent(DefaultTransportService.getSessionEventMsg(TransportProtos.SessionEvent.OPEN))
- .setSubscribeToAttributes(TransportProtos.SubscribeToAttributeUpdatesMsg.newBuilder().build())
- .setSubscribeToRPC(TransportProtos.SubscribeToRPCMsg.newBuilder().build())
+ .setSubscribeToAttributes(TransportProtos.SubscribeToAttributeUpdatesMsg.newBuilder()
+ .setSessionType(TransportProtos.SessionType.ASYNC).build())
+ .setSubscribeToRPC(TransportProtos.SubscribeToRPCMsg.newBuilder()
+ .setSessionType(TransportProtos.SessionType.ASYNC).build())
.build(), null);
}
futureToSet.set(devices.get(deviceName));
diff --git a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileServiceImpl.java
index e41289e97b..7ec1e662af 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileServiceImpl.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileServiceImpl.java
@@ -434,7 +434,7 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D
if (!firmware.getType().equals(OtaPackageType.FIRMWARE)) {
throw new DataValidationException("Can't assign firmware with type: " + firmware.getType());
}
- if (firmware.getData() == null) {
+ if (firmware.getData() == null && !firmware.hasUrl()) {
throw new DataValidationException("Can't assign firmware with empty data!");
}
if (!firmware.getDeviceProfileId().equals(deviceProfile.getId())) {
@@ -450,7 +450,7 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D
if (!software.getType().equals(OtaPackageType.SOFTWARE)) {
throw new DataValidationException("Can't assign software with type: " + software.getType());
}
- if (software.getData() == null) {
+ if (software.getData() == null && !software.hasUrl()) {
throw new DataValidationException("Can't assign software with empty data!");
}
if (!software.getDeviceProfileId().equals(deviceProfile.getId())) {
diff --git a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceServiceImpl.java
index 34aa462a6d..f1470ff5ad 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceServiceImpl.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceServiceImpl.java
@@ -716,7 +716,7 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe
if (!firmware.getType().equals(OtaPackageType.FIRMWARE)) {
throw new DataValidationException("Can't assign firmware with type: " + firmware.getType());
}
- if (firmware.getData() == null) {
+ if (firmware.getData() == null && !firmware.hasUrl()) {
throw new DataValidationException("Can't assign firmware with empty data!");
}
if (!firmware.getDeviceProfileId().equals(device.getDeviceProfileId())) {
@@ -732,7 +732,7 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe
if (!software.getType().equals(OtaPackageType.SOFTWARE)) {
throw new DataValidationException("Can't assign software with type: " + software.getType());
}
- if (software.getData() == null) {
+ if (software.getData() == null && !software.hasUrl()) {
throw new DataValidationException("Can't assign software with empty data!");
}
if (!software.getDeviceProfileId().equals(device.getDeviceProfileId())) {
diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java b/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java
index bfb530dd35..87cee53991 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java
@@ -408,10 +408,20 @@ public class ModelConstants {
/**
* OAuth2 client registration constants.
*/
- public static final String OAUTH2_TENANT_ID_PROPERTY = TENANT_ID_PROPERTY;
+
+ public static final String OAUTH2_PARAMS_COLUMN_FAMILY_NAME = "oauth2_params";
+ public static final String OAUTH2_PARAMS_ENABLED_PROPERTY = "enabled";
+ public static final String OAUTH2_PARAMS_TENANT_ID_PROPERTY = TENANT_ID_PROPERTY;
+
+ public static final String OAUTH2_REGISTRATION_COLUMN_FAMILY_NAME = "oauth2_registration";
+ public static final String OAUTH2_DOMAIN_COLUMN_FAMILY_NAME = "oauth2_domain";
+ public static final String OAUTH2_MOBILE_COLUMN_FAMILY_NAME = "oauth2_mobile";
+ public static final String OAUTH2_PARAMS_ID_PROPERTY = "oauth2_params_id";
+ public static final String OAUTH2_PKG_NAME_PROPERTY = "pkg_name";
+ public static final String OAUTH2_APP_SECRET_PROPERTY = "app_secret";
+
public static final String OAUTH2_CLIENT_REGISTRATION_INFO_COLUMN_FAMILY_NAME = "oauth2_client_registration_info";
public static final String OAUTH2_CLIENT_REGISTRATION_COLUMN_FAMILY_NAME = "oauth2_client_registration";
- public static final String OAUTH2_CLIENT_REGISTRATION_TO_DOMAIN_COLUMN_FAMILY_NAME = "oauth2_client_registration_to_domain";
public static final String OAUTH2_CLIENT_REGISTRATION_TEMPLATE_COLUMN_FAMILY_NAME = "oauth2_client_registration_template";
public static final String OAUTH2_ENABLED_PROPERTY = "enabled";
public static final String OAUTH2_TEMPLATE_PROVIDER_ID_PROPERTY = "provider_id";
@@ -422,8 +432,8 @@ public class ModelConstants {
public static final String OAUTH2_CLIENT_SECRET_PROPERTY = "client_secret";
public static final String OAUTH2_AUTHORIZATION_URI_PROPERTY = "authorization_uri";
public static final String OAUTH2_TOKEN_URI_PROPERTY = "token_uri";
- public static final String OAUTH2_REDIRECT_URI_TEMPLATE_PROPERTY = "redirect_uri_template";
public static final String OAUTH2_SCOPE_PROPERTY = "scope";
+ public static final String OAUTH2_PLATFORMS_PROPERTY = "platforms";
public static final String OAUTH2_USER_INFO_URI_PROPERTY = "user_info_uri";
public static final String OAUTH2_USER_NAME_ATTRIBUTE_NAME_PROPERTY = "user_name_attribute_name";
public static final String OAUTH2_JWK_SET_URI_PROPERTY = "jwk_set_uri";
diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/OAuth2DomainEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/OAuth2DomainEntity.java
new file mode 100644
index 0000000000..f1dbe6fff7
--- /dev/null
+++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/OAuth2DomainEntity.java
@@ -0,0 +1,76 @@
+/**
+ * Copyright © 2016-2021 The Thingsboard Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.thingsboard.server.dao.model.sql;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.thingsboard.server.common.data.id.OAuth2DomainId;
+import org.thingsboard.server.common.data.id.OAuth2ParamsId;
+import org.thingsboard.server.common.data.oauth2.OAuth2Domain;
+import org.thingsboard.server.common.data.oauth2.SchemeType;
+import org.thingsboard.server.dao.model.BaseSqlEntity;
+import org.thingsboard.server.dao.model.ModelConstants;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.Table;
+import java.util.UUID;
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+@Entity
+@Table(name = ModelConstants.OAUTH2_DOMAIN_COLUMN_FAMILY_NAME)
+public class OAuth2DomainEntity extends BaseSqlEntity {
+
+ @Column(name = ModelConstants.OAUTH2_PARAMS_ID_PROPERTY)
+ private UUID oauth2ParamsId;
+
+ @Column(name = ModelConstants.OAUTH2_DOMAIN_NAME_PROPERTY)
+ private String domainName;
+
+ @Enumerated(EnumType.STRING)
+ @Column(name = ModelConstants.OAUTH2_DOMAIN_SCHEME_PROPERTY)
+ private SchemeType domainScheme;
+
+ public OAuth2DomainEntity() {
+ super();
+ }
+
+ public OAuth2DomainEntity(OAuth2Domain domain) {
+ if (domain.getId() != null) {
+ this.setUuid(domain.getId().getId());
+ }
+ this.setCreatedTime(domain.getCreatedTime());
+ if (domain.getOauth2ParamsId() != null) {
+ this.oauth2ParamsId = domain.getOauth2ParamsId().getId();
+ }
+ this.domainName = domain.getDomainName();
+ this.domainScheme = domain.getDomainScheme();
+ }
+
+ @Override
+ public OAuth2Domain toData() {
+ OAuth2Domain domain = new OAuth2Domain();
+ domain.setId(new OAuth2DomainId(id));
+ domain.setCreatedTime(createdTime);
+ domain.setOauth2ParamsId(new OAuth2ParamsId(oauth2ParamsId));
+ domain.setDomainName(domainName);
+ domain.setDomainScheme(domainScheme);
+ return domain;
+ }
+}
diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/OAuth2MobileEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/OAuth2MobileEntity.java
new file mode 100644
index 0000000000..a6517011b0
--- /dev/null
+++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/OAuth2MobileEntity.java
@@ -0,0 +1,72 @@
+/**
+ * Copyright © 2016-2021 The Thingsboard Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.thingsboard.server.dao.model.sql;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.thingsboard.server.common.data.id.OAuth2MobileId;
+import org.thingsboard.server.common.data.id.OAuth2ParamsId;
+import org.thingsboard.server.common.data.oauth2.OAuth2Mobile;
+import org.thingsboard.server.dao.model.BaseSqlEntity;
+import org.thingsboard.server.dao.model.ModelConstants;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Table;
+import java.util.UUID;
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+@Entity
+@Table(name = ModelConstants.OAUTH2_MOBILE_COLUMN_FAMILY_NAME)
+public class OAuth2MobileEntity extends BaseSqlEntity {
+
+ @Column(name = ModelConstants.OAUTH2_PARAMS_ID_PROPERTY)
+ private UUID oauth2ParamsId;
+
+ @Column(name = ModelConstants.OAUTH2_PKG_NAME_PROPERTY)
+ private String pkgName;
+
+ @Column(name = ModelConstants.OAUTH2_APP_SECRET_PROPERTY)
+ private String appSecret;
+
+ public OAuth2MobileEntity() {
+ super();
+ }
+
+ public OAuth2MobileEntity(OAuth2Mobile mobile) {
+ if (mobile.getId() != null) {
+ this.setUuid(mobile.getId().getId());
+ }
+ this.setCreatedTime(mobile.getCreatedTime());
+ if (mobile.getOauth2ParamsId() != null) {
+ this.oauth2ParamsId = mobile.getOauth2ParamsId().getId();
+ }
+ this.pkgName = mobile.getPkgName();
+ this.appSecret = mobile.getAppSecret();
+ }
+
+ @Override
+ public OAuth2Mobile toData() {
+ OAuth2Mobile mobile = new OAuth2Mobile();
+ mobile.setId(new OAuth2MobileId(id));
+ mobile.setCreatedTime(createdTime);
+ mobile.setOauth2ParamsId(new OAuth2ParamsId(oauth2ParamsId));
+ mobile.setPkgName(pkgName);
+ mobile.setAppSecret(appSecret);
+ return mobile;
+ }
+}
diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/OAuth2ParamsEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/OAuth2ParamsEntity.java
new file mode 100644
index 0000000000..f2c893f6f3
--- /dev/null
+++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/OAuth2ParamsEntity.java
@@ -0,0 +1,65 @@
+/**
+ * Copyright © 2016-2021 The Thingsboard Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.thingsboard.server.dao.model.sql;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import org.thingsboard.server.common.data.id.OAuth2ParamsId;
+import org.thingsboard.server.common.data.id.TenantId;
+import org.thingsboard.server.common.data.oauth2.OAuth2Params;
+import org.thingsboard.server.dao.model.BaseSqlEntity;
+import org.thingsboard.server.dao.model.ModelConstants;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Table;
+import java.util.UUID;
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+@Entity
+@Table(name = ModelConstants.OAUTH2_PARAMS_COLUMN_FAMILY_NAME)
+@NoArgsConstructor
+public class OAuth2ParamsEntity extends BaseSqlEntity {
+
+ @Column(name = ModelConstants.OAUTH2_PARAMS_ENABLED_PROPERTY)
+ private Boolean enabled;
+
+ @Column(name = ModelConstants.OAUTH2_PARAMS_TENANT_ID_PROPERTY)
+ private UUID tenantId;
+
+ public OAuth2ParamsEntity(OAuth2Params oauth2Params) {
+ if (oauth2Params.getId() != null) {
+ this.setUuid(oauth2Params.getUuidId());
+ }
+ this.setCreatedTime(oauth2Params.getCreatedTime());
+ this.enabled = oauth2Params.isEnabled();
+ if (oauth2Params.getTenantId() != null) {
+ this.tenantId = oauth2Params.getTenantId().getId();
+ }
+ }
+
+ @Override
+ public OAuth2Params toData() {
+ OAuth2Params oauth2Params = new OAuth2Params();
+ oauth2Params.setId(new OAuth2ParamsId(id));
+ oauth2Params.setCreatedTime(createdTime);
+ oauth2Params.setTenantId(new TenantId(tenantId));
+ oauth2Params.setEnabled(enabled);
+ return oauth2Params;
+ }
+}
diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/OAuth2RegistrationEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/OAuth2RegistrationEntity.java
new file mode 100644
index 0000000000..ca32bad322
--- /dev/null
+++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/OAuth2RegistrationEntity.java
@@ -0,0 +1,221 @@
+/**
+ * Copyright © 2016-2021 The Thingsboard Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.thingsboard.server.dao.model.sql;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import io.micrometer.core.instrument.util.StringUtils;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.hibernate.annotations.Type;
+import org.hibernate.annotations.TypeDef;
+import org.thingsboard.server.common.data.id.OAuth2ParamsId;
+import org.thingsboard.server.common.data.id.OAuth2RegistrationId;
+import org.thingsboard.server.common.data.oauth2.MapperType;
+import org.thingsboard.server.common.data.oauth2.OAuth2BasicMapperConfig;
+import org.thingsboard.server.common.data.oauth2.OAuth2CustomMapperConfig;
+import org.thingsboard.server.common.data.oauth2.OAuth2MapperConfig;
+import org.thingsboard.server.common.data.oauth2.OAuth2Registration;
+import org.thingsboard.server.common.data.oauth2.PlatformType;
+import org.thingsboard.server.common.data.oauth2.TenantNameStrategyType;
+import org.thingsboard.server.dao.model.BaseSqlEntity;
+import org.thingsboard.server.dao.model.ModelConstants;
+import org.thingsboard.server.dao.util.mapping.JsonStringType;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.Table;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.UUID;
+import java.util.stream.Collectors;
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+@Entity
+@TypeDef(name = "json", typeClass = JsonStringType.class)
+@Table(name = ModelConstants.OAUTH2_REGISTRATION_COLUMN_FAMILY_NAME)
+public class OAuth2RegistrationEntity extends BaseSqlEntity {
+
+ @Column(name = ModelConstants.OAUTH2_PARAMS_ID_PROPERTY)
+ private UUID oauth2ParamsId;
+ @Column(name = ModelConstants.OAUTH2_CLIENT_ID_PROPERTY)
+ private String clientId;
+ @Column(name = ModelConstants.OAUTH2_CLIENT_SECRET_PROPERTY)
+ private String clientSecret;
+ @Column(name = ModelConstants.OAUTH2_AUTHORIZATION_URI_PROPERTY)
+ private String authorizationUri;
+ @Column(name = ModelConstants.OAUTH2_TOKEN_URI_PROPERTY)
+ private String tokenUri;
+ @Column(name = ModelConstants.OAUTH2_SCOPE_PROPERTY)
+ private String scope;
+ @Column(name = ModelConstants.OAUTH2_PLATFORMS_PROPERTY)
+ private String platforms;
+ @Column(name = ModelConstants.OAUTH2_USER_INFO_URI_PROPERTY)
+ private String userInfoUri;
+ @Column(name = ModelConstants.OAUTH2_USER_NAME_ATTRIBUTE_NAME_PROPERTY)
+ private String userNameAttributeName;
+ @Column(name = ModelConstants.OAUTH2_JWK_SET_URI_PROPERTY)
+ private String jwkSetUri;
+ @Column(name = ModelConstants.OAUTH2_CLIENT_AUTHENTICATION_METHOD_PROPERTY)
+ private String clientAuthenticationMethod;
+ @Column(name = ModelConstants.OAUTH2_LOGIN_BUTTON_LABEL_PROPERTY)
+ private String loginButtonLabel;
+ @Column(name = ModelConstants.OAUTH2_LOGIN_BUTTON_ICON_PROPERTY)
+ private String loginButtonIcon;
+ @Column(name = ModelConstants.OAUTH2_ALLOW_USER_CREATION_PROPERTY)
+ private Boolean allowUserCreation;
+ @Column(name = ModelConstants.OAUTH2_ACTIVATE_USER_PROPERTY)
+ private Boolean activateUser;
+ @Enumerated(EnumType.STRING)
+ @Column(name = ModelConstants.OAUTH2_MAPPER_TYPE_PROPERTY)
+ private MapperType type;
+ @Column(name = ModelConstants.OAUTH2_EMAIL_ATTRIBUTE_KEY_PROPERTY)
+ private String emailAttributeKey;
+ @Column(name = ModelConstants.OAUTH2_FIRST_NAME_ATTRIBUTE_KEY_PROPERTY)
+ private String firstNameAttributeKey;
+ @Column(name = ModelConstants.OAUTH2_LAST_NAME_ATTRIBUTE_KEY_PROPERTY)
+ private String lastNameAttributeKey;
+ @Enumerated(EnumType.STRING)
+ @Column(name = ModelConstants.OAUTH2_TENANT_NAME_STRATEGY_PROPERTY)
+ private TenantNameStrategyType tenantNameStrategy;
+ @Column(name = ModelConstants.OAUTH2_TENANT_NAME_PATTERN_PROPERTY)
+ private String tenantNamePattern;
+ @Column(name = ModelConstants.OAUTH2_CUSTOMER_NAME_PATTERN_PROPERTY)
+ private String customerNamePattern;
+ @Column(name = ModelConstants.OAUTH2_DEFAULT_DASHBOARD_NAME_PROPERTY)
+ private String defaultDashboardName;
+ @Column(name = ModelConstants.OAUTH2_ALWAYS_FULL_SCREEN_PROPERTY)
+ private Boolean alwaysFullScreen;
+ @Column(name = ModelConstants.OAUTH2_MAPPER_URL_PROPERTY)
+ private String url;
+ @Column(name = ModelConstants.OAUTH2_MAPPER_USERNAME_PROPERTY)
+ private String username;
+ @Column(name = ModelConstants.OAUTH2_MAPPER_PASSWORD_PROPERTY)
+ private String password;
+ @Column(name = ModelConstants.OAUTH2_MAPPER_SEND_TOKEN_PROPERTY)
+ private Boolean sendToken;
+
+ @Type(type = "json")
+ @Column(name = ModelConstants.OAUTH2_ADDITIONAL_INFO_PROPERTY)
+ private JsonNode additionalInfo;
+
+ public OAuth2RegistrationEntity() {
+ super();
+ }
+
+ public OAuth2RegistrationEntity(OAuth2Registration registration) {
+ if (registration.getId() != null) {
+ this.setUuid(registration.getId().getId());
+ }
+ this.setCreatedTime(registration.getCreatedTime());
+ if (registration.getOauth2ParamsId() != null) {
+ this.oauth2ParamsId = registration.getOauth2ParamsId().getId();
+ }
+ this.clientId = registration.getClientId();
+ this.clientSecret = registration.getClientSecret();
+ this.authorizationUri = registration.getAuthorizationUri();
+ this.tokenUri = registration.getAccessTokenUri();
+ this.scope = registration.getScope().stream().reduce((result, element) -> result + "," + element).orElse("");
+ this.platforms = registration.getPlatforms() != null ? registration.getPlatforms().stream().map(Enum::name).reduce((result, element) -> result + "," + element).orElse("") : "";
+ this.userInfoUri = registration.getUserInfoUri();
+ this.userNameAttributeName = registration.getUserNameAttributeName();
+ this.jwkSetUri = registration.getJwkSetUri();
+ this.clientAuthenticationMethod = registration.getClientAuthenticationMethod();
+ this.loginButtonLabel = registration.getLoginButtonLabel();
+ this.loginButtonIcon = registration.getLoginButtonIcon();
+ this.additionalInfo = registration.getAdditionalInfo();
+ OAuth2MapperConfig mapperConfig = registration.getMapperConfig();
+ if (mapperConfig != null) {
+ this.allowUserCreation = mapperConfig.isAllowUserCreation();
+ this.activateUser = mapperConfig.isActivateUser();
+ this.type = mapperConfig.getType();
+ OAuth2BasicMapperConfig basicConfig = mapperConfig.getBasic();
+ if (basicConfig != null) {
+ this.emailAttributeKey = basicConfig.getEmailAttributeKey();
+ this.firstNameAttributeKey = basicConfig.getFirstNameAttributeKey();
+ this.lastNameAttributeKey = basicConfig.getLastNameAttributeKey();
+ this.tenantNameStrategy = basicConfig.getTenantNameStrategy();
+ this.tenantNamePattern = basicConfig.getTenantNamePattern();
+ this.customerNamePattern = basicConfig.getCustomerNamePattern();
+ this.defaultDashboardName = basicConfig.getDefaultDashboardName();
+ this.alwaysFullScreen = basicConfig.isAlwaysFullScreen();
+ }
+ OAuth2CustomMapperConfig customConfig = mapperConfig.getCustom();
+ if (customConfig != null) {
+ this.url = customConfig.getUrl();
+ this.username = customConfig.getUsername();
+ this.password = customConfig.getPassword();
+ this.sendToken = customConfig.isSendToken();
+ }
+ }
+ }
+
+ @Override
+ public OAuth2Registration toData() {
+ OAuth2Registration registration = new OAuth2Registration();
+ registration.setId(new OAuth2RegistrationId(id));
+ registration.setCreatedTime(createdTime);
+ registration.setOauth2ParamsId(new OAuth2ParamsId(oauth2ParamsId));
+ registration.setAdditionalInfo(additionalInfo);
+ registration.setMapperConfig(
+ OAuth2MapperConfig.builder()
+ .allowUserCreation(allowUserCreation)
+ .activateUser(activateUser)
+ .type(type)
+ .basic(
+ (type == MapperType.BASIC || type == MapperType.GITHUB || type == MapperType.APPLE) ?
+ OAuth2BasicMapperConfig.builder()
+ .emailAttributeKey(emailAttributeKey)
+ .firstNameAttributeKey(firstNameAttributeKey)
+ .lastNameAttributeKey(lastNameAttributeKey)
+ .tenantNameStrategy(tenantNameStrategy)
+ .tenantNamePattern(tenantNamePattern)
+ .customerNamePattern(customerNamePattern)
+ .defaultDashboardName(defaultDashboardName)
+ .alwaysFullScreen(alwaysFullScreen)
+ .build()
+ : null
+ )
+ .custom(
+ type == MapperType.CUSTOM ?
+ OAuth2CustomMapperConfig.builder()
+ .url(url)
+ .username(username)
+ .password(password)
+ .sendToken(sendToken)
+ .build()
+ : null
+ )
+ .build()
+ );
+ registration.setClientId(clientId);
+ registration.setClientSecret(clientSecret);
+ registration.setAuthorizationUri(authorizationUri);
+ registration.setAccessTokenUri(tokenUri);
+ registration.setScope(Arrays.asList(scope.split(",")));
+ registration.setPlatforms(StringUtils.isNotEmpty(platforms) ? Arrays.stream(platforms.split(","))
+ .map(str -> PlatformType.valueOf(str)).collect(Collectors.toList()) : Collections.emptyList());
+ registration.setUserInfoUri(userInfoUri);
+ registration.setUserNameAttributeName(userNameAttributeName);
+ registration.setJwkSetUri(jwkSetUri);
+ registration.setClientAuthenticationMethod(clientAuthenticationMethod);
+ registration.setLoginButtonLabel(loginButtonLabel);
+ registration.setLoginButtonIcon(loginButtonIcon);
+ return registration;
+ }
+}
diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractOAuth2ClientRegistrationInfoEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/deprecated/AbstractOAuth2ClientRegistrationInfoEntity.java
similarity index 97%
rename from dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractOAuth2ClientRegistrationInfoEntity.java
rename to dao/src/main/java/org/thingsboard/server/dao/model/sql/deprecated/AbstractOAuth2ClientRegistrationInfoEntity.java
index 4799087457..616f128920 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractOAuth2ClientRegistrationInfoEntity.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/deprecated/AbstractOAuth2ClientRegistrationInfoEntity.java
@@ -13,22 +13,25 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.thingsboard.server.dao.model.sql;
+package org.thingsboard.server.dao.model.sql.deprecated;
import com.fasterxml.jackson.databind.JsonNode;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.hibernate.annotations.Type;
import org.hibernate.annotations.TypeDef;
-import org.thingsboard.server.common.data.id.OAuth2ClientRegistrationInfoId;
+import org.thingsboard.server.common.data.id.deprecated.OAuth2ClientRegistrationInfoId;
import org.thingsboard.server.common.data.oauth2.*;
+import org.thingsboard.server.common.data.oauth2.deprecated.OAuth2ClientRegistrationInfo;
import org.thingsboard.server.dao.model.BaseSqlEntity;
import org.thingsboard.server.dao.model.ModelConstants;
+import org.thingsboard.server.dao.model.sql.deprecated.OAuth2ClientRegistrationInfoEntity;
import org.thingsboard.server.dao.util.mapping.JsonStringType;
import javax.persistence.*;
import java.util.Arrays;
+@Deprecated
@Data
@EqualsAndHashCode(callSuper = true)
@TypeDef(name = "json", typeClass = JsonStringType.class)
diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/ExtendedOAuth2ClientRegistrationInfoEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/deprecated/ExtendedOAuth2ClientRegistrationInfoEntity.java
similarity index 91%
rename from dao/src/main/java/org/thingsboard/server/dao/model/sql/ExtendedOAuth2ClientRegistrationInfoEntity.java
rename to dao/src/main/java/org/thingsboard/server/dao/model/sql/deprecated/ExtendedOAuth2ClientRegistrationInfoEntity.java
index 129bcf730b..beb525e2e0 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/ExtendedOAuth2ClientRegistrationInfoEntity.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/deprecated/ExtendedOAuth2ClientRegistrationInfoEntity.java
@@ -13,13 +13,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.thingsboard.server.dao.model.sql;
+package org.thingsboard.server.dao.model.sql.deprecated;
import lombok.Data;
import lombok.EqualsAndHashCode;
-import org.thingsboard.server.common.data.oauth2.ExtendedOAuth2ClientRegistrationInfo;
+import org.thingsboard.server.common.data.oauth2.deprecated.ExtendedOAuth2ClientRegistrationInfo;
import org.thingsboard.server.common.data.oauth2.SchemeType;
+@Deprecated
@Data
@EqualsAndHashCode(callSuper = true)
public class ExtendedOAuth2ClientRegistrationInfoEntity extends AbstractOAuth2ClientRegistrationInfoEntity {
diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/OAuth2ClientRegistrationEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/deprecated/OAuth2ClientRegistrationEntity.java
similarity index 89%
rename from dao/src/main/java/org/thingsboard/server/dao/model/sql/OAuth2ClientRegistrationEntity.java
rename to dao/src/main/java/org/thingsboard/server/dao/model/sql/deprecated/OAuth2ClientRegistrationEntity.java
index 505f2facf1..9de0b9daea 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/OAuth2ClientRegistrationEntity.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/deprecated/OAuth2ClientRegistrationEntity.java
@@ -13,22 +13,23 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.thingsboard.server.dao.model.sql;
+package org.thingsboard.server.dao.model.sql.deprecated;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.hibernate.annotations.TypeDef;
-import org.thingsboard.server.common.data.id.OAuth2ClientRegistrationId;
-import org.thingsboard.server.common.data.id.OAuth2ClientRegistrationInfoId;
+import org.thingsboard.server.common.data.id.deprecated.OAuth2ClientRegistrationId;
+import org.thingsboard.server.common.data.id.deprecated.OAuth2ClientRegistrationInfoId;
import org.thingsboard.server.common.data.oauth2.*;
+import org.thingsboard.server.common.data.oauth2.deprecated.OAuth2ClientRegistration;
import org.thingsboard.server.dao.model.BaseSqlEntity;
import org.thingsboard.server.dao.model.ModelConstants;
import org.thingsboard.server.dao.util.mapping.JsonStringType;
import javax.persistence.*;
-import java.util.Arrays;
import java.util.UUID;
+@Deprecated
@Data
@EqualsAndHashCode(callSuper = true)
@Entity
diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/OAuth2ClientRegistrationInfoEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/deprecated/OAuth2ClientRegistrationInfoEntity.java
similarity index 91%
rename from dao/src/main/java/org/thingsboard/server/dao/model/sql/OAuth2ClientRegistrationInfoEntity.java
rename to dao/src/main/java/org/thingsboard/server/dao/model/sql/deprecated/OAuth2ClientRegistrationInfoEntity.java
index 1a379baf23..fbb9ec3fca 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/OAuth2ClientRegistrationInfoEntity.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/deprecated/OAuth2ClientRegistrationInfoEntity.java
@@ -13,18 +13,19 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.thingsboard.server.dao.model.sql;
+package org.thingsboard.server.dao.model.sql.deprecated;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.hibernate.annotations.TypeDef;
-import org.thingsboard.server.common.data.oauth2.OAuth2ClientRegistrationInfo;
+import org.thingsboard.server.common.data.oauth2.deprecated.OAuth2ClientRegistrationInfo;
import org.thingsboard.server.dao.model.ModelConstants;
import org.thingsboard.server.dao.util.mapping.JsonStringType;
import javax.persistence.Entity;
import javax.persistence.Table;
+@Deprecated
@Data
@EqualsAndHashCode(callSuper = true)
@Entity
diff --git a/dao/src/main/java/org/thingsboard/server/dao/oauth2/HybridClientRegistrationRepository.java b/dao/src/main/java/org/thingsboard/server/dao/oauth2/HybridClientRegistrationRepository.java
index 7361dc21d2..feba5c0158 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/oauth2/HybridClientRegistrationRepository.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/oauth2/HybridClientRegistrationRepository.java
@@ -21,7 +21,7 @@ import org.springframework.security.oauth2.client.registration.ClientRegistratio
import org.springframework.security.oauth2.core.AuthorizationGrantType;
import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
import org.springframework.stereotype.Component;
-import org.thingsboard.server.common.data.oauth2.OAuth2ClientRegistrationInfo;
+import org.thingsboard.server.common.data.oauth2.OAuth2Registration;
import java.util.UUID;
@@ -34,25 +34,25 @@ public class HybridClientRegistrationRepository implements ClientRegistrationRep
@Override
public ClientRegistration findByRegistrationId(String registrationId) {
- OAuth2ClientRegistrationInfo oAuth2ClientRegistrationInfo = oAuth2Service.findClientRegistrationInfo(UUID.fromString(registrationId));
- return oAuth2ClientRegistrationInfo == null ?
- null : toSpringClientRegistration(oAuth2ClientRegistrationInfo);
+ OAuth2Registration registration = oAuth2Service.findRegistration(UUID.fromString(registrationId));
+ return registration == null ?
+ null : toSpringClientRegistration(registration);
}
- private ClientRegistration toSpringClientRegistration(OAuth2ClientRegistrationInfo localClientRegistration){
- String registrationId = localClientRegistration.getUuidId().toString();
+ private ClientRegistration toSpringClientRegistration(OAuth2Registration registration){
+ String registrationId = registration.getUuidId().toString();
return ClientRegistration.withRegistrationId(registrationId)
- .clientName(localClientRegistration.getName())
- .clientId(localClientRegistration.getClientId())
- .authorizationUri(localClientRegistration.getAuthorizationUri())
- .clientSecret(localClientRegistration.getClientSecret())
- .tokenUri(localClientRegistration.getAccessTokenUri())
- .scope(localClientRegistration.getScope())
+ .clientName(registration.getName())
+ .clientId(registration.getClientId())
+ .authorizationUri(registration.getAuthorizationUri())
+ .clientSecret(registration.getClientSecret())
+ .tokenUri(registration.getAccessTokenUri())
+ .scope(registration.getScope())
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
- .userInfoUri(localClientRegistration.getUserInfoUri())
- .userNameAttributeName(localClientRegistration.getUserNameAttributeName())
- .jwkSetUri(localClientRegistration.getJwkSetUri())
- .clientAuthenticationMethod(new ClientAuthenticationMethod(localClientRegistration.getClientAuthenticationMethod()))
+ .userInfoUri(registration.getUserInfoUri())
+ .userNameAttributeName(registration.getUserNameAttributeName())
+ .jwkSetUri(registration.getJwkSetUri())
+ .clientAuthenticationMethod(new ClientAuthenticationMethod(registration.getClientAuthenticationMethod()))
.redirectUri(defaultRedirectUriTemplate)
.build();
}
diff --git a/dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2DomainDao.java b/dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2DomainDao.java
new file mode 100644
index 0000000000..78c237d943
--- /dev/null
+++ b/dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2DomainDao.java
@@ -0,0 +1,28 @@
+/**
+ * Copyright © 2016-2021 The Thingsboard Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.thingsboard.server.dao.oauth2;
+
+import org.thingsboard.server.common.data.oauth2.OAuth2Domain;
+import org.thingsboard.server.dao.Dao;
+
+import java.util.List;
+import java.util.UUID;
+
+public interface OAuth2DomainDao extends Dao {
+
+ List findByOAuth2ParamsId(UUID oauth2ParamsId);
+
+}
diff --git a/dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2MobileDao.java b/dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2MobileDao.java
new file mode 100644
index 0000000000..3bccb61b0b
--- /dev/null
+++ b/dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2MobileDao.java
@@ -0,0 +1,28 @@
+/**
+ * Copyright © 2016-2021 The Thingsboard Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.thingsboard.server.dao.oauth2;
+
+import org.thingsboard.server.common.data.oauth2.OAuth2Mobile;
+import org.thingsboard.server.dao.Dao;
+
+import java.util.List;
+import java.util.UUID;
+
+public interface OAuth2MobileDao extends Dao {
+
+ List findByOAuth2ParamsId(UUID oauth2ParamsId);
+
+}
diff --git a/dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ParamsDao.java b/dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ParamsDao.java
new file mode 100644
index 0000000000..5821431444
--- /dev/null
+++ b/dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ParamsDao.java
@@ -0,0 +1,23 @@
+/**
+ * Copyright © 2016-2021 The Thingsboard Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.thingsboard.server.dao.oauth2;
+
+import org.thingsboard.server.common.data.oauth2.OAuth2Params;
+import org.thingsboard.server.dao.Dao;
+
+public interface OAuth2ParamsDao extends Dao {
+ void deleteAll();
+}
diff --git a/dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2RegistrationDao.java b/dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2RegistrationDao.java
new file mode 100644
index 0000000000..87f0d56460
--- /dev/null
+++ b/dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2RegistrationDao.java
@@ -0,0 +1,34 @@
+/**
+ * Copyright © 2016-2021 The Thingsboard Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.thingsboard.server.dao.oauth2;
+
+import org.thingsboard.server.common.data.oauth2.OAuth2Registration;
+import org.thingsboard.server.common.data.oauth2.PlatformType;
+import org.thingsboard.server.common.data.oauth2.SchemeType;
+import org.thingsboard.server.dao.Dao;
+
+import java.util.List;
+import java.util.UUID;
+
+public interface OAuth2RegistrationDao extends Dao {
+
+ List findEnabledByDomainSchemesDomainNameAndPkgNameAndPlatformType(List domainSchemes, String domainName, String pkgName, PlatformType platformType);
+
+ List findByOAuth2ParamsId(UUID oauth2ParamsId);
+
+ String findAppSecret(UUID id, String pkgName);
+
+}
diff --git a/dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ServiceImpl.java
index acde25f8ed..6d7dde1f21 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ServiceImpl.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ServiceImpl.java
@@ -19,14 +19,44 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
+import org.thingsboard.server.common.data.BaseData;
import org.thingsboard.server.common.data.id.TenantId;
-import org.thingsboard.server.common.data.oauth2.*;
+import org.thingsboard.server.common.data.oauth2.MapperType;
+import org.thingsboard.server.common.data.oauth2.OAuth2BasicMapperConfig;
+import org.thingsboard.server.common.data.oauth2.OAuth2ClientInfo;
+import org.thingsboard.server.common.data.oauth2.OAuth2CustomMapperConfig;
+import org.thingsboard.server.common.data.oauth2.OAuth2Domain;
+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.OAuth2Mobile;
+import org.thingsboard.server.common.data.oauth2.OAuth2MobileInfo;
+import org.thingsboard.server.common.data.oauth2.OAuth2Params;
+import org.thingsboard.server.common.data.oauth2.OAuth2ParamsInfo;
+import org.thingsboard.server.common.data.oauth2.OAuth2Registration;
+import org.thingsboard.server.common.data.oauth2.OAuth2RegistrationInfo;
+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.common.data.oauth2.deprecated.ClientRegistrationDto;
+import org.thingsboard.server.common.data.oauth2.deprecated.DomainInfo;
+import org.thingsboard.server.common.data.oauth2.deprecated.ExtendedOAuth2ClientRegistrationInfo;
+import org.thingsboard.server.common.data.oauth2.deprecated.OAuth2ClientRegistration;
+import org.thingsboard.server.common.data.oauth2.deprecated.OAuth2ClientRegistrationInfo;
+import org.thingsboard.server.common.data.oauth2.deprecated.OAuth2ClientsDomainParams;
+import org.thingsboard.server.common.data.oauth2.deprecated.OAuth2ClientsParams;
import org.thingsboard.server.dao.entity.AbstractEntityService;
import org.thingsboard.server.dao.exception.DataValidationException;
import org.thingsboard.server.dao.exception.IncorrectParameterException;
+import org.thingsboard.server.dao.oauth2.deprecated.OAuth2ClientRegistrationDao;
+import org.thingsboard.server.dao.oauth2.deprecated.OAuth2ClientRegistrationInfoDao;
import javax.transaction.Transactional;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.List;
+import java.util.UUID;
import java.util.function.Consumer;
import java.util.stream.Collectors;
@@ -45,10 +75,18 @@ public class OAuth2ServiceImpl extends AbstractEntityService implements OAuth2Se
private OAuth2ClientRegistrationInfoDao clientRegistrationInfoDao;
@Autowired
private OAuth2ClientRegistrationDao clientRegistrationDao;
+ @Autowired
+ private OAuth2ParamsDao oauth2ParamsDao;
+ @Autowired
+ private OAuth2RegistrationDao oauth2RegistrationDao;
+ @Autowired
+ private OAuth2DomainDao oauth2DomainDao;
+ @Autowired
+ private OAuth2MobileDao oauth2MobileDao;
@Override
- public List getOAuth2Clients(String domainSchemeStr, String domainName) {
- log.trace("Executing getOAuth2Clients [{}://{}]", domainSchemeStr, domainName);
+ public List getOAuth2Clients(String domainSchemeStr, String domainName, String pkgName, PlatformType platformType) {
+ log.trace("Executing getOAuth2Clients [{}://{}] pkgName=[{}] platformType=[{}]", domainSchemeStr, domainName, pkgName, platformType);
if (domainSchemeStr == null) {
throw new IncorrectParameterException(INCORRECT_DOMAIN_SCHEME);
}
@@ -59,12 +97,14 @@ public class OAuth2ServiceImpl extends AbstractEntityService implements OAuth2Se
throw new IncorrectParameterException(INCORRECT_DOMAIN_SCHEME);
}
validateString(domainName, INCORRECT_DOMAIN_NAME + domainName);
- return clientRegistrationInfoDao.findByDomainSchemesAndDomainName(Arrays.asList(domainScheme, SchemeType.MIXED), domainName).stream()
- .filter(OAuth2ClientRegistrationInfo::isEnabled)
+ return oauth2RegistrationDao.findEnabledByDomainSchemesDomainNameAndPkgNameAndPlatformType(
+ Arrays.asList(domainScheme, SchemeType.MIXED), domainName, pkgName, platformType)
+ .stream()
.map(OAuth2Utils::toClientInfo)
.collect(Collectors.toList());
}
+ @Deprecated
@Override
@Transactional
public void saveOAuth2Params(OAuth2ClientsParams oauth2Params) {
@@ -85,6 +125,33 @@ public class OAuth2ServiceImpl extends AbstractEntityService implements OAuth2Se
});
}
+ @Override
+ @Transactional
+ public void saveOAuth2Info(OAuth2Info oauth2Info) {
+ log.trace("Executing saveOAuth2Info [{}]", oauth2Info);
+ oauth2InfoValidator.accept(oauth2Info);
+ oauth2ParamsDao.deleteAll();
+ oauth2Info.getOauth2ParamsInfos().forEach(oauth2ParamsInfo -> {
+ OAuth2Params oauth2Params = OAuth2Utils.infoToOAuth2Params(oauth2Info);
+ OAuth2Params savedOauth2Params = oauth2ParamsDao.save(TenantId.SYS_TENANT_ID, oauth2Params);
+ oauth2ParamsInfo.getClientRegistrations().forEach(registrationInfo -> {
+ OAuth2Registration registration = OAuth2Utils.toOAuth2Registration(savedOauth2Params.getId(), registrationInfo);
+ oauth2RegistrationDao.save(TenantId.SYS_TENANT_ID, registration);
+ });
+ oauth2ParamsInfo.getDomainInfos().forEach(domainInfo -> {
+ OAuth2Domain domain = OAuth2Utils.toOAuth2Domain(savedOauth2Params.getId(), domainInfo);
+ oauth2DomainDao.save(TenantId.SYS_TENANT_ID, domain);
+ });
+ if (oauth2ParamsInfo.getMobileInfos() != null) {
+ oauth2ParamsInfo.getMobileInfos().forEach(mobileInfo -> {
+ OAuth2Mobile mobile = OAuth2Utils.toOAuth2Mobile(savedOauth2Params.getId(), mobileInfo);
+ oauth2MobileDao.save(TenantId.SYS_TENANT_ID, mobile);
+ });
+ }
+ });
+ }
+
+ @Deprecated
@Override
public OAuth2ClientsParams findOAuth2Params() {
log.trace("Executing findOAuth2Params");
@@ -93,16 +160,42 @@ public class OAuth2ServiceImpl extends AbstractEntityService implements OAuth2Se
}
@Override
- public OAuth2ClientRegistrationInfo findClientRegistrationInfo(UUID id) {
- log.trace("Executing findClientRegistrationInfo [{}]", id);
+ public OAuth2Info findOAuth2Info() {
+ log.trace("Executing findOAuth2Info");
+ OAuth2Info oauth2Info = new OAuth2Info();
+ List oauth2ParamsList = oauth2ParamsDao.find(TenantId.SYS_TENANT_ID);
+ oauth2Info.setEnabled(oauth2ParamsList.stream().anyMatch(param -> param.isEnabled()));
+ List oauth2ParamsInfos = new ArrayList<>();
+ oauth2Info.setOauth2ParamsInfos(oauth2ParamsInfos);
+ oauth2ParamsList.stream().sorted(Comparator.comparing(BaseData::getUuidId)).forEach(oauth2Params -> {
+ List registrations = oauth2RegistrationDao.findByOAuth2ParamsId(oauth2Params.getId().getId());
+ List domains = oauth2DomainDao.findByOAuth2ParamsId(oauth2Params.getId().getId());
+ List mobiles = oauth2MobileDao.findByOAuth2ParamsId(oauth2Params.getId().getId());
+ oauth2ParamsInfos.add(OAuth2Utils.toOAuth2ParamsInfo(registrations, domains, mobiles));
+ });
+ return oauth2Info;
+ }
+
+ @Override
+ public OAuth2Registration findRegistration(UUID id) {
+ log.trace("Executing findRegistration [{}]", id);
+ validateId(id, INCORRECT_CLIENT_REGISTRATION_ID + id);
+ return oauth2RegistrationDao.findById(null, id);
+ }
+
+ @Override
+ public String findAppSecret(UUID id, String pkgName) {
+ log.trace("Executing findAppSecret [{}][{}]", id, pkgName);
validateId(id, INCORRECT_CLIENT_REGISTRATION_ID + id);
- return clientRegistrationInfoDao.findById(null, id);
+ validateString(pkgName, "Incorrect package name");
+ return oauth2RegistrationDao.findAppSecret(id, pkgName);
}
+
@Override
- public List findAllClientRegistrationInfos() {
- log.trace("Executing findAllClientRegistrationInfos");
- return clientRegistrationInfoDao.findAll();
+ public List findAllRegistrations() {
+ log.trace("Executing findAllRegistrations");
+ return oauth2RegistrationDao.find(TenantId.SYS_TENANT_ID);
}
private final Consumer clientParamsValidator = oauth2Params -> {
@@ -212,4 +305,136 @@ public class OAuth2ServiceImpl extends AbstractEntityService implements OAuth2Se
}
}
};
+
+ private final Consumer oauth2InfoValidator = oauth2Info -> {
+ if (oauth2Info == null
+ || oauth2Info.getOauth2ParamsInfos() == null) {
+ throw new DataValidationException("OAuth2 param infos should be specified!");
+ }
+ for (OAuth2ParamsInfo oauth2Params : oauth2Info.getOauth2ParamsInfos()) {
+ if (oauth2Params.getDomainInfos() == null
+ || oauth2Params.getDomainInfos().isEmpty()) {
+ throw new DataValidationException("List of domain configuration should be specified!");
+ }
+ for (OAuth2DomainInfo domainInfo : oauth2Params.getDomainInfos()) {
+ if (StringUtils.isEmpty(domainInfo.getName())) {
+ throw new DataValidationException("Domain name should be specified!");
+ }
+ if (domainInfo.getScheme() == null) {
+ throw new DataValidationException("Domain scheme should be specified!");
+ }
+ }
+ oauth2Params.getDomainInfos().stream()
+ .collect(Collectors.groupingBy(OAuth2DomainInfo::getName))
+ .forEach((domainName, domainInfos) -> {
+ if (domainInfos.size() > 1 && domainInfos.stream().anyMatch(domainInfo -> domainInfo.getScheme() == SchemeType.MIXED)) {
+ throw new DataValidationException("MIXED scheme type shouldn't be combined with another scheme type!");
+ }
+ domainInfos.stream()
+ .collect(Collectors.groupingBy(OAuth2DomainInfo::getScheme))
+ .forEach((schemeType, domainInfosBySchemeType) -> {
+ if (domainInfosBySchemeType.size() > 1) {
+ throw new DataValidationException("Domain name and protocol must be unique within OAuth2 parameters!");
+ }
+ });
+ });
+ if (oauth2Params.getMobileInfos() != null) {
+ for (OAuth2MobileInfo mobileInfo : oauth2Params.getMobileInfos()) {
+ if (StringUtils.isEmpty(mobileInfo.getPkgName())) {
+ throw new DataValidationException("Package should be specified!");
+ }
+ if (StringUtils.isEmpty(mobileInfo.getAppSecret())) {
+ throw new DataValidationException("Application secret should be specified!");
+ }
+ if (mobileInfo.getAppSecret().length() < 16) {
+ throw new DataValidationException("Application secret should be at least 16 characters!");
+ }
+ }
+ oauth2Params.getMobileInfos().stream()
+ .collect(Collectors.groupingBy(OAuth2MobileInfo::getPkgName))
+ .forEach((pkgName, mobileInfos) -> {
+ if (mobileInfos.size() > 1) {
+ throw new DataValidationException("Mobile app package name must be unique within OAuth2 parameters!");
+ }
+ });
+ }
+ if (oauth2Params.getClientRegistrations() == null || oauth2Params.getClientRegistrations().isEmpty()) {
+ throw new DataValidationException("Client registrations should be specified!");
+ }
+ for (OAuth2RegistrationInfo clientRegistration : oauth2Params.getClientRegistrations()) {
+ if (StringUtils.isEmpty(clientRegistration.getClientId())) {
+ throw new DataValidationException("Client ID should be specified!");
+ }
+ if (StringUtils.isEmpty(clientRegistration.getClientSecret())) {
+ throw new DataValidationException("Client secret should be specified!");
+ }
+ if (StringUtils.isEmpty(clientRegistration.getAuthorizationUri())) {
+ throw new DataValidationException("Authorization uri should be specified!");
+ }
+ if (StringUtils.isEmpty(clientRegistration.getAccessTokenUri())) {
+ throw new DataValidationException("Token uri should be specified!");
+ }
+ if (StringUtils.isEmpty(clientRegistration.getScope())) {
+ throw new DataValidationException("Scope should be specified!");
+ }
+ if (StringUtils.isEmpty(clientRegistration.getUserNameAttributeName())) {
+ throw new DataValidationException("User name attribute name should be specified!");
+ }
+ if (StringUtils.isEmpty(clientRegistration.getClientAuthenticationMethod())) {
+ throw new DataValidationException("Client authentication method should be specified!");
+ }
+ if (StringUtils.isEmpty(clientRegistration.getLoginButtonLabel())) {
+ throw new DataValidationException("Login button label should be specified!");
+ }
+ OAuth2MapperConfig mapperConfig = clientRegistration.getMapperConfig();
+ if (mapperConfig == null) {
+ throw new DataValidationException("Mapper config should be specified!");
+ }
+ if (mapperConfig.getType() == null) {
+ throw new DataValidationException("Mapper config type should be specified!");
+ }
+ if (mapperConfig.getType() == MapperType.BASIC) {
+ OAuth2BasicMapperConfig basicConfig = mapperConfig.getBasic();
+ if (basicConfig == null) {
+ throw new DataValidationException("Basic config should be specified!");
+ }
+ if (StringUtils.isEmpty(basicConfig.getEmailAttributeKey())) {
+ throw new DataValidationException("Email attribute key should be specified!");
+ }
+ if (basicConfig.getTenantNameStrategy() == null) {
+ throw new DataValidationException("Tenant name strategy should be specified!");
+ }
+ if (basicConfig.getTenantNameStrategy() == TenantNameStrategyType.CUSTOM
+ && StringUtils.isEmpty(basicConfig.getTenantNamePattern())) {
+ throw new DataValidationException("Tenant name pattern should be specified!");
+ }
+ }
+ if (mapperConfig.getType() == MapperType.GITHUB) {
+ OAuth2BasicMapperConfig basicConfig = mapperConfig.getBasic();
+ if (basicConfig == null) {
+ throw new DataValidationException("Basic config should be specified!");
+ }
+ if (!StringUtils.isEmpty(basicConfig.getEmailAttributeKey())) {
+ throw new DataValidationException("Email attribute key cannot be configured for GITHUB mapper type!");
+ }
+ if (basicConfig.getTenantNameStrategy() == null) {
+ throw new DataValidationException("Tenant name strategy should be specified!");
+ }
+ if (basicConfig.getTenantNameStrategy() == TenantNameStrategyType.CUSTOM
+ && StringUtils.isEmpty(basicConfig.getTenantNamePattern())) {
+ throw new DataValidationException("Tenant name pattern should be specified!");
+ }
+ }
+ if (mapperConfig.getType() == MapperType.CUSTOM) {
+ OAuth2CustomMapperConfig customConfig = mapperConfig.getCustom();
+ if (customConfig == null) {
+ throw new DataValidationException("Custom config should be specified!");
+ }
+ if (StringUtils.isEmpty(customConfig.getUrl())) {
+ throw new DataValidationException("Custom mapper URL should be specified!");
+ }
+ }
+ }
+ }
+ };
}
diff --git a/dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2Utils.java b/dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2Utils.java
index 2a59ccb829..c34875d014 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2Utils.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2Utils.java
@@ -15,19 +15,30 @@
*/
package org.thingsboard.server.dao.oauth2;
-import org.thingsboard.server.common.data.id.OAuth2ClientRegistrationInfoId;
+import org.thingsboard.server.common.data.BaseData;
+import org.thingsboard.server.common.data.id.OAuth2ParamsId;
+import org.thingsboard.server.common.data.id.TenantId;
+import org.thingsboard.server.common.data.id.deprecated.OAuth2ClientRegistrationInfoId;
import org.thingsboard.server.common.data.oauth2.*;
+import org.thingsboard.server.common.data.oauth2.deprecated.ClientRegistrationDto;
+import org.thingsboard.server.common.data.oauth2.deprecated.DomainInfo;
+import org.thingsboard.server.common.data.oauth2.deprecated.ExtendedOAuth2ClientRegistrationInfo;
+import org.thingsboard.server.common.data.oauth2.deprecated.OAuth2ClientRegistration;
+import org.thingsboard.server.common.data.oauth2.deprecated.OAuth2ClientRegistrationInfo;
+import org.thingsboard.server.common.data.oauth2.deprecated.OAuth2ClientsDomainParams;
+import org.thingsboard.server.common.data.oauth2.deprecated.OAuth2ClientsParams;
import java.util.*;
+import java.util.stream.Collectors;
public class OAuth2Utils {
public static final String OAUTH2_AUTHORIZATION_PATH_TEMPLATE = "/oauth2/authorization/%s";
- public static OAuth2ClientInfo toClientInfo(OAuth2ClientRegistrationInfo clientRegistrationInfo) {
+ public static OAuth2ClientInfo toClientInfo(OAuth2Registration registration) {
OAuth2ClientInfo client = new OAuth2ClientInfo();
- client.setName(clientRegistrationInfo.getLoginButtonLabel());
- client.setUrl(String.format(OAUTH2_AUTHORIZATION_PATH_TEMPLATE, clientRegistrationInfo.getUuidId().toString()));
- client.setIcon(clientRegistrationInfo.getLoginButtonIcon());
+ client.setName(registration.getLoginButtonLabel());
+ client.setUrl(String.format(OAUTH2_AUTHORIZATION_PATH_TEMPLATE, registration.getUuidId().toString()));
+ client.setIcon(registration.getLoginButtonIcon());
return client;
}
@@ -99,4 +110,130 @@ public class OAuth2Utils {
clientRegistration.setDomainScheme(domainScheme);
return clientRegistration;
}
+
+ public static OAuth2ParamsInfo toOAuth2ParamsInfo(List registrations, List domains, List mobiles) {
+ OAuth2ParamsInfo oauth2ParamsInfo = new OAuth2ParamsInfo();
+ oauth2ParamsInfo.setClientRegistrations(registrations.stream().sorted(Comparator.comparing(BaseData::getUuidId)).map(OAuth2Utils::toOAuth2RegistrationInfo).collect(Collectors.toList()));
+ oauth2ParamsInfo.setDomainInfos(domains.stream().sorted(Comparator.comparing(BaseData::getUuidId)).map(OAuth2Utils::toOAuth2DomainInfo).collect(Collectors.toList()));
+ oauth2ParamsInfo.setMobileInfos(mobiles.stream().sorted(Comparator.comparing(BaseData::getUuidId)).map(OAuth2Utils::toOAuth2MobileInfo).collect(Collectors.toList()));
+ return oauth2ParamsInfo;
+ }
+
+ public static OAuth2RegistrationInfo toOAuth2RegistrationInfo(OAuth2Registration registration) {
+ return OAuth2RegistrationInfo.builder()
+ .mapperConfig(registration.getMapperConfig())
+ .clientId(registration.getClientId())
+ .clientSecret(registration.getClientSecret())
+ .authorizationUri(registration.getAuthorizationUri())
+ .accessTokenUri(registration.getAccessTokenUri())
+ .scope(registration.getScope())
+ .platforms(registration.getPlatforms())
+ .userInfoUri(registration.getUserInfoUri())
+ .userNameAttributeName(registration.getUserNameAttributeName())
+ .jwkSetUri(registration.getJwkSetUri())
+ .clientAuthenticationMethod(registration.getClientAuthenticationMethod())
+ .loginButtonLabel(registration.getLoginButtonLabel())
+ .loginButtonIcon(registration.getLoginButtonIcon())
+ .additionalInfo(registration.getAdditionalInfo())
+ .build();
+ }
+
+ public static OAuth2DomainInfo toOAuth2DomainInfo(OAuth2Domain domain) {
+ return OAuth2DomainInfo.builder()
+ .name(domain.getDomainName())
+ .scheme(domain.getDomainScheme())
+ .build();
+ }
+
+ public static OAuth2MobileInfo toOAuth2MobileInfo(OAuth2Mobile mobile) {
+ return OAuth2MobileInfo.builder()
+ .pkgName(mobile.getPkgName())
+ .appSecret(mobile.getAppSecret())
+ .build();
+ }
+
+ public static OAuth2Params infoToOAuth2Params(OAuth2Info oauth2Info) {
+ OAuth2Params oauth2Params = new OAuth2Params();
+ oauth2Params.setEnabled(oauth2Info.isEnabled());
+ oauth2Params.setTenantId(TenantId.SYS_TENANT_ID);
+ return oauth2Params;
+ }
+
+ public static OAuth2Registration toOAuth2Registration(OAuth2ParamsId oauth2ParamsId, OAuth2RegistrationInfo registrationInfo) {
+ OAuth2Registration registration = new OAuth2Registration();
+ registration.setOauth2ParamsId(oauth2ParamsId);
+ registration.setMapperConfig(registrationInfo.getMapperConfig());
+ registration.setClientId(registrationInfo.getClientId());
+ registration.setClientSecret(registrationInfo.getClientSecret());
+ registration.setAuthorizationUri(registrationInfo.getAuthorizationUri());
+ registration.setAccessTokenUri(registrationInfo.getAccessTokenUri());
+ registration.setScope(registrationInfo.getScope());
+ registration.setPlatforms(registrationInfo.getPlatforms());
+ registration.setUserInfoUri(registrationInfo.getUserInfoUri());
+ registration.setUserNameAttributeName(registrationInfo.getUserNameAttributeName());
+ registration.setJwkSetUri(registrationInfo.getJwkSetUri());
+ registration.setClientAuthenticationMethod(registrationInfo.getClientAuthenticationMethod());
+ registration.setLoginButtonLabel(registrationInfo.getLoginButtonLabel());
+ registration.setLoginButtonIcon(registrationInfo.getLoginButtonIcon());
+ registration.setAdditionalInfo(registrationInfo.getAdditionalInfo());
+ return registration;
+ }
+
+ public static OAuth2Domain toOAuth2Domain(OAuth2ParamsId oauth2ParamsId, OAuth2DomainInfo domainInfo) {
+ OAuth2Domain domain = new OAuth2Domain();
+ domain.setOauth2ParamsId(oauth2ParamsId);
+ domain.setDomainName(domainInfo.getName());
+ domain.setDomainScheme(domainInfo.getScheme());
+ return domain;
+ }
+
+ public static OAuth2Mobile toOAuth2Mobile(OAuth2ParamsId oauth2ParamsId, OAuth2MobileInfo mobileInfo) {
+ OAuth2Mobile mobile = new OAuth2Mobile();
+ mobile.setOauth2ParamsId(oauth2ParamsId);
+ mobile.setPkgName(mobileInfo.getPkgName());
+ mobile.setAppSecret(mobileInfo.getAppSecret());
+ return mobile;
+ }
+
+ @Deprecated
+ public static OAuth2Info clientParamsToOAuth2Info(OAuth2ClientsParams clientsParams) {
+ OAuth2Info oauth2Info = new OAuth2Info();
+ oauth2Info.setEnabled(clientsParams.isEnabled());
+ oauth2Info.setOauth2ParamsInfos(clientsParams.getDomainsParams().stream().map(OAuth2Utils::clientsDomainParamsToOAuth2ParamsInfo).collect(Collectors.toList()));
+ return oauth2Info;
+ }
+
+ private static OAuth2ParamsInfo clientsDomainParamsToOAuth2ParamsInfo(OAuth2ClientsDomainParams clientsDomainParams) {
+ OAuth2ParamsInfo oauth2ParamsInfo = new OAuth2ParamsInfo();
+ oauth2ParamsInfo.setMobileInfos(Collections.emptyList());
+ oauth2ParamsInfo.setClientRegistrations(clientsDomainParams.getClientRegistrations().stream().map(OAuth2Utils::clientRegistrationDtoToOAuth2RegistrationInfo).collect(Collectors.toList()));
+ oauth2ParamsInfo.setDomainInfos(clientsDomainParams.getDomainInfos().stream().map(OAuth2Utils::domainInfoToOAuth2DomainInfo).collect(Collectors.toList()));
+ return oauth2ParamsInfo;
+ }
+
+ private static OAuth2RegistrationInfo clientRegistrationDtoToOAuth2RegistrationInfo(ClientRegistrationDto clientRegistrationDto) {
+ return OAuth2RegistrationInfo.builder()
+ .mapperConfig(clientRegistrationDto.getMapperConfig())
+ .clientId(clientRegistrationDto.getClientId())
+ .clientSecret(clientRegistrationDto.getClientSecret())
+ .authorizationUri(clientRegistrationDto.getAuthorizationUri())
+ .accessTokenUri(clientRegistrationDto.getAccessTokenUri())
+ .scope(clientRegistrationDto.getScope())
+ .userInfoUri(clientRegistrationDto.getUserInfoUri())
+ .userNameAttributeName(clientRegistrationDto.getUserNameAttributeName())
+ .jwkSetUri(clientRegistrationDto.getJwkSetUri())
+ .clientAuthenticationMethod(clientRegistrationDto.getClientAuthenticationMethod())
+ .loginButtonLabel(clientRegistrationDto.getLoginButtonLabel())
+ .loginButtonIcon(clientRegistrationDto.getLoginButtonIcon())
+ .additionalInfo(clientRegistrationDto.getAdditionalInfo())
+ .platforms(Collections.emptyList())
+ .build();
+ }
+
+ private static OAuth2DomainInfo domainInfoToOAuth2DomainInfo(DomainInfo domainInfo) {
+ return OAuth2DomainInfo.builder()
+ .name(domainInfo.getName())
+ .scheme(domainInfo.getScheme())
+ .build();
+ }
}
diff --git a/dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ClientRegistrationDao.java b/dao/src/main/java/org/thingsboard/server/dao/oauth2/deprecated/OAuth2ClientRegistrationDao.java
similarity index 83%
rename from dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ClientRegistrationDao.java
rename to dao/src/main/java/org/thingsboard/server/dao/oauth2/deprecated/OAuth2ClientRegistrationDao.java
index 2f4f2c1be2..63b2c46034 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ClientRegistrationDao.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/oauth2/deprecated/OAuth2ClientRegistrationDao.java
@@ -13,11 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.thingsboard.server.dao.oauth2;
+package org.thingsboard.server.dao.oauth2.deprecated;
-import org.thingsboard.server.common.data.oauth2.OAuth2ClientRegistration;
+import org.thingsboard.server.common.data.oauth2.deprecated.OAuth2ClientRegistration;
import org.thingsboard.server.dao.Dao;
+@Deprecated
public interface OAuth2ClientRegistrationDao extends Dao {
void deleteAll();
}
diff --git a/dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ClientRegistrationInfoDao.java b/dao/src/main/java/org/thingsboard/server/dao/oauth2/deprecated/OAuth2ClientRegistrationInfoDao.java
similarity index 81%
rename from dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ClientRegistrationInfoDao.java
rename to dao/src/main/java/org/thingsboard/server/dao/oauth2/deprecated/OAuth2ClientRegistrationInfoDao.java
index 6fe93bacf4..9f44335602 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ClientRegistrationInfoDao.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/oauth2/deprecated/OAuth2ClientRegistrationInfoDao.java
@@ -13,16 +13,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.thingsboard.server.dao.oauth2;
+package org.thingsboard.server.dao.oauth2.deprecated;
-import org.thingsboard.server.common.data.oauth2.ExtendedOAuth2ClientRegistrationInfo;
-import org.thingsboard.server.common.data.oauth2.OAuth2ClientRegistrationInfo;
+import org.thingsboard.server.common.data.oauth2.deprecated.ExtendedOAuth2ClientRegistrationInfo;
+import org.thingsboard.server.common.data.oauth2.deprecated.OAuth2ClientRegistrationInfo;
import org.thingsboard.server.common.data.oauth2.SchemeType;
import org.thingsboard.server.dao.Dao;
import java.util.List;
-import java.util.Set;
+@Deprecated
public interface OAuth2ClientRegistrationInfoDao extends Dao {
List findAll();
diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/JpaOAuth2DomainDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/JpaOAuth2DomainDao.java
new file mode 100644
index 0000000000..0d74821678
--- /dev/null
+++ b/dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/JpaOAuth2DomainDao.java
@@ -0,0 +1,52 @@
+/**
+ * Copyright © 2016-2021 The Thingsboard Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.thingsboard.server.dao.sql.oauth2;
+
+import lombok.RequiredArgsConstructor;
+import org.springframework.data.repository.CrudRepository;
+import org.springframework.stereotype.Component;
+import org.thingsboard.server.common.data.oauth2.OAuth2Domain;
+import org.thingsboard.server.dao.DaoUtil;
+import org.thingsboard.server.dao.model.sql.OAuth2DomainEntity;
+import org.thingsboard.server.dao.oauth2.OAuth2DomainDao;
+import org.thingsboard.server.dao.sql.JpaAbstractDao;
+
+import java.util.List;
+import java.util.UUID;
+
+@Component
+@RequiredArgsConstructor
+public class JpaOAuth2DomainDao extends JpaAbstractDao implements OAuth2DomainDao {
+
+ private final OAuth2DomainRepository repository;
+
+ @Override
+ protected Class getEntityClass() {
+ return OAuth2DomainEntity.class;
+ }
+
+ @Override
+ protected CrudRepository getCrudRepository() {
+ return repository;
+ }
+
+ @Override
+ public List findByOAuth2ParamsId(UUID oauth2ParamsId) {
+ return DaoUtil.convertDataList(repository.findByOauth2ParamsId(oauth2ParamsId));
+ }
+
+}
+
diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/JpaOAuth2MobileDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/JpaOAuth2MobileDao.java
new file mode 100644
index 0000000000..6f216b23f2
--- /dev/null
+++ b/dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/JpaOAuth2MobileDao.java
@@ -0,0 +1,52 @@
+/**
+ * Copyright © 2016-2021 The Thingsboard Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.thingsboard.server.dao.sql.oauth2;
+
+import lombok.RequiredArgsConstructor;
+import org.springframework.data.repository.CrudRepository;
+import org.springframework.stereotype.Component;
+import org.thingsboard.server.common.data.oauth2.OAuth2Mobile;
+import org.thingsboard.server.dao.DaoUtil;
+import org.thingsboard.server.dao.model.sql.OAuth2MobileEntity;
+import org.thingsboard.server.dao.oauth2.OAuth2MobileDao;
+import org.thingsboard.server.dao.sql.JpaAbstractDao;
+
+import java.util.List;
+import java.util.UUID;
+
+@Component
+@RequiredArgsConstructor
+public class JpaOAuth2MobileDao extends JpaAbstractDao implements OAuth2MobileDao {
+
+ private final OAuth2MobileRepository repository;
+
+ @Override
+ protected Class getEntityClass() {
+ return OAuth2MobileEntity.class;
+ }
+
+ @Override
+ protected CrudRepository getCrudRepository() {
+ return repository;
+ }
+
+ @Override
+ public List findByOAuth2ParamsId(UUID oauth2ParamsId) {
+ return DaoUtil.convertDataList(repository.findByOauth2ParamsId(oauth2ParamsId));
+ }
+
+}
+
diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/JpaOAuth2ParamsDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/JpaOAuth2ParamsDao.java
new file mode 100644
index 0000000000..2f28cb58f6
--- /dev/null
+++ b/dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/JpaOAuth2ParamsDao.java
@@ -0,0 +1,47 @@
+/**
+ * Copyright © 2016-2021 The Thingsboard Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.thingsboard.server.dao.sql.oauth2;
+
+import lombok.RequiredArgsConstructor;
+import org.springframework.data.repository.CrudRepository;
+import org.springframework.stereotype.Component;
+import org.thingsboard.server.common.data.oauth2.OAuth2Params;
+import org.thingsboard.server.dao.model.sql.OAuth2ParamsEntity;
+import org.thingsboard.server.dao.oauth2.OAuth2ParamsDao;
+import org.thingsboard.server.dao.sql.JpaAbstractDao;
+
+import java.util.UUID;
+
+@Component
+@RequiredArgsConstructor
+public class JpaOAuth2ParamsDao extends JpaAbstractDao implements OAuth2ParamsDao {
+ private final OAuth2ParamsRepository repository;
+
+ @Override
+ protected Class getEntityClass() {
+ return OAuth2ParamsEntity.class;
+ }
+
+ @Override
+ protected CrudRepository getCrudRepository() {
+ return repository;
+ }
+
+ @Override
+ public void deleteAll() {
+ repository.deleteAll();
+ }
+}
diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/JpaOAuth2RegistrationDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/JpaOAuth2RegistrationDao.java
new file mode 100644
index 0000000000..ef35371b6e
--- /dev/null
+++ b/dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/JpaOAuth2RegistrationDao.java
@@ -0,0 +1,64 @@
+/**
+ * Copyright © 2016-2021 The Thingsboard Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.thingsboard.server.dao.sql.oauth2;
+
+import lombok.RequiredArgsConstructor;
+import org.springframework.data.repository.CrudRepository;
+import org.springframework.stereotype.Component;
+import org.thingsboard.server.common.data.oauth2.OAuth2Registration;
+import org.thingsboard.server.common.data.oauth2.PlatformType;
+import org.thingsboard.server.common.data.oauth2.SchemeType;
+import org.thingsboard.server.dao.DaoUtil;
+import org.thingsboard.server.dao.model.sql.OAuth2RegistrationEntity;
+import org.thingsboard.server.dao.oauth2.OAuth2RegistrationDao;
+import org.thingsboard.server.dao.sql.JpaAbstractDao;
+
+import java.util.List;
+import java.util.UUID;
+
+@Component
+@RequiredArgsConstructor
+public class JpaOAuth2RegistrationDao extends JpaAbstractDao implements OAuth2RegistrationDao {
+
+ private final OAuth2RegistrationRepository repository;
+
+ @Override
+ protected Class getEntityClass() {
+ return OAuth2RegistrationEntity.class;
+ }
+
+ @Override
+ protected CrudRepository getCrudRepository() {
+ return repository;
+ }
+
+ @Override
+ public List findEnabledByDomainSchemesDomainNameAndPkgNameAndPlatformType(List domainSchemes, String domainName, String pkgName, PlatformType platformType) {
+ return DaoUtil.convertDataList(repository.findEnabledByDomainSchemesDomainNameAndPkgNameAndPlatformType(domainSchemes, domainName, pkgName,
+ platformType != null ? "%" + platformType.name() + "%" : null));
+ }
+
+ @Override
+ public List findByOAuth2ParamsId(UUID oauth2ParamsId) {
+ return DaoUtil.convertDataList(repository.findByOauth2ParamsId(oauth2ParamsId));
+ }
+
+ @Override
+ public String findAppSecret(UUID id, String pkgName) {
+ return repository.findAppSecret(id, pkgName);
+ }
+
+}
diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/OAuth2DomainRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/OAuth2DomainRepository.java
new file mode 100644
index 0000000000..26d084f613
--- /dev/null
+++ b/dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/OAuth2DomainRepository.java
@@ -0,0 +1,29 @@
+/**
+ * Copyright © 2016-2021 The Thingsboard Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.thingsboard.server.dao.sql.oauth2;
+
+import org.springframework.data.repository.CrudRepository;
+import org.thingsboard.server.dao.model.sql.OAuth2DomainEntity;
+
+import java.util.List;
+import java.util.UUID;
+
+public interface OAuth2DomainRepository extends CrudRepository {
+
+ List findByOauth2ParamsId(UUID oauth2ParamsId);
+
+}
+
diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/OAuth2MobileRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/OAuth2MobileRepository.java
new file mode 100644
index 0000000000..d4660ef2ee
--- /dev/null
+++ b/dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/OAuth2MobileRepository.java
@@ -0,0 +1,28 @@
+/**
+ * Copyright © 2016-2021 The Thingsboard Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.thingsboard.server.dao.sql.oauth2;
+
+import org.springframework.data.repository.CrudRepository;
+import org.thingsboard.server.dao.model.sql.OAuth2MobileEntity;
+
+import java.util.List;
+import java.util.UUID;
+
+public interface OAuth2MobileRepository extends CrudRepository {
+
+ List findByOauth2ParamsId(UUID oauth2ParamsId);
+
+}
diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/OAuth2ParamsRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/OAuth2ParamsRepository.java
new file mode 100644
index 0000000000..8e53b34e31
--- /dev/null
+++ b/dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/OAuth2ParamsRepository.java
@@ -0,0 +1,24 @@
+/**
+ * Copyright © 2016-2021 The Thingsboard Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.thingsboard.server.dao.sql.oauth2;
+
+import org.springframework.data.repository.CrudRepository;
+import org.thingsboard.server.dao.model.sql.OAuth2ParamsEntity;
+
+import java.util.UUID;
+
+public interface OAuth2ParamsRepository extends CrudRepository {
+}
diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/OAuth2RegistrationRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/OAuth2RegistrationRepository.java
new file mode 100644
index 0000000000..5c6e34661f
--- /dev/null
+++ b/dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/OAuth2RegistrationRepository.java
@@ -0,0 +1,53 @@
+/**
+ * Copyright © 2016-2021 The Thingsboard Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.thingsboard.server.dao.sql.oauth2;
+
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.CrudRepository;
+import org.springframework.data.repository.query.Param;
+import org.thingsboard.server.common.data.oauth2.SchemeType;
+import org.thingsboard.server.dao.model.sql.OAuth2RegistrationEntity;
+
+import java.util.List;
+import java.util.UUID;
+
+public interface OAuth2RegistrationRepository extends CrudRepository {
+
+ @Query("SELECT reg " +
+ "FROM OAuth2RegistrationEntity reg " +
+ "LEFT JOIN OAuth2ParamsEntity params on reg.oauth2ParamsId = params.id " +
+ "LEFT JOIN OAuth2DomainEntity domain on reg.oauth2ParamsId = domain.oauth2ParamsId " +
+ "WHERE params.enabled = true " +
+ "AND domain.domainName = :domainName " +
+ "AND domain.domainScheme IN (:domainSchemes) " +
+ "AND (:pkgName IS NULL OR EXISTS (SELECT mobile FROM OAuth2MobileEntity mobile WHERE mobile.oauth2ParamsId = reg.oauth2ParamsId AND mobile.pkgName = :pkgName)) " +
+ "AND (:platformFilter IS NULL OR reg.platforms IS NULL OR reg.platforms = '' OR reg.platforms LIKE :platformFilter)")
+ List findEnabledByDomainSchemesDomainNameAndPkgNameAndPlatformType(@Param("domainSchemes") List domainSchemes,
+ @Param("domainName") String domainName,
+ @Param("pkgName") String pkgName,
+ @Param("platformFilter") String platformFilter);
+
+ List findByOauth2ParamsId(UUID oauth2ParamsId);
+
+ @Query("SELECT mobile.appSecret " +
+ "FROM OAuth2MobileEntity mobile " +
+ "LEFT JOIN OAuth2RegistrationEntity reg on mobile.oauth2ParamsId = reg.oauth2ParamsId " +
+ "WHERE reg.id = :registrationId " +
+ "AND mobile.pkgName = :pkgName")
+ String findAppSecret(@Param("registrationId") UUID id,
+ @Param("pkgName") String pkgName);
+
+}
diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/JpaOAuth2ClientRegistrationDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/deprecated/JpaOAuth2ClientRegistrationDao.java
similarity index 82%
rename from dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/JpaOAuth2ClientRegistrationDao.java
rename to dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/deprecated/JpaOAuth2ClientRegistrationDao.java
index 8aea9c9c3f..8dfe92b18d 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/JpaOAuth2ClientRegistrationDao.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/deprecated/JpaOAuth2ClientRegistrationDao.java
@@ -13,19 +13,19 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.thingsboard.server.dao.sql.oauth2;
+package org.thingsboard.server.dao.sql.oauth2.deprecated;
import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Component;
-import org.thingsboard.server.common.data.oauth2.OAuth2ClientRegistration;
-import org.thingsboard.server.dao.model.sql.OAuth2ClientRegistrationEntity;
-import org.thingsboard.server.dao.oauth2.OAuth2ClientRegistrationDao;
+import org.thingsboard.server.common.data.oauth2.deprecated.OAuth2ClientRegistration;
+import org.thingsboard.server.dao.model.sql.deprecated.OAuth2ClientRegistrationEntity;
+import org.thingsboard.server.dao.oauth2.deprecated.OAuth2ClientRegistrationDao;
import org.thingsboard.server.dao.sql.JpaAbstractDao;
import java.util.UUID;
+@Deprecated
@Component
@RequiredArgsConstructor
public class JpaOAuth2ClientRegistrationDao extends JpaAbstractDao implements OAuth2ClientRegistrationDao {
diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/JpaOAuth2ClientRegistrationInfoDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/deprecated/JpaOAuth2ClientRegistrationInfoDao.java
similarity index 85%
rename from dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/JpaOAuth2ClientRegistrationInfoDao.java
rename to dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/deprecated/JpaOAuth2ClientRegistrationInfoDao.java
index 0a25678e16..d37ca981f2 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/JpaOAuth2ClientRegistrationInfoDao.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/deprecated/JpaOAuth2ClientRegistrationInfoDao.java
@@ -13,17 +13,17 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.thingsboard.server.dao.sql.oauth2;
+package org.thingsboard.server.dao.sql.oauth2.deprecated;
import lombok.RequiredArgsConstructor;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Component;
-import org.thingsboard.server.common.data.oauth2.ExtendedOAuth2ClientRegistrationInfo;
-import org.thingsboard.server.common.data.oauth2.OAuth2ClientRegistrationInfo;
+import org.thingsboard.server.common.data.oauth2.deprecated.ExtendedOAuth2ClientRegistrationInfo;
+import org.thingsboard.server.common.data.oauth2.deprecated.OAuth2ClientRegistrationInfo;
import org.thingsboard.server.common.data.oauth2.SchemeType;
import org.thingsboard.server.dao.DaoUtil;
-import org.thingsboard.server.dao.model.sql.OAuth2ClientRegistrationInfoEntity;
-import org.thingsboard.server.dao.oauth2.OAuth2ClientRegistrationInfoDao;
+import org.thingsboard.server.dao.model.sql.deprecated.OAuth2ClientRegistrationInfoEntity;
+import org.thingsboard.server.dao.oauth2.deprecated.OAuth2ClientRegistrationInfoDao;
import org.thingsboard.server.dao.sql.JpaAbstractDao;
import java.util.ArrayList;
@@ -31,6 +31,7 @@ import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
+@Deprecated
@Component
@RequiredArgsConstructor
public class JpaOAuth2ClientRegistrationInfoDao extends JpaAbstractDao implements OAuth2ClientRegistrationInfoDao {
diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/OAuth2ClientRegistrationInfoRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/deprecated/OAuth2ClientRegistrationInfoRepository.java
similarity index 81%
rename from dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/OAuth2ClientRegistrationInfoRepository.java
rename to dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/deprecated/OAuth2ClientRegistrationInfoRepository.java
index 18ac3be05a..73a2ca9bba 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/OAuth2ClientRegistrationInfoRepository.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/deprecated/OAuth2ClientRegistrationInfoRepository.java
@@ -13,18 +13,19 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.thingsboard.server.dao.sql.oauth2;
+package org.thingsboard.server.dao.sql.oauth2.deprecated;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;
import org.thingsboard.server.common.data.oauth2.SchemeType;
-import org.thingsboard.server.dao.model.sql.ExtendedOAuth2ClientRegistrationInfoEntity;
-import org.thingsboard.server.dao.model.sql.OAuth2ClientRegistrationInfoEntity;
+import org.thingsboard.server.dao.model.sql.deprecated.ExtendedOAuth2ClientRegistrationInfoEntity;
+import org.thingsboard.server.dao.model.sql.deprecated.OAuth2ClientRegistrationInfoEntity;
import java.util.List;
import java.util.UUID;
+@Deprecated
public interface OAuth2ClientRegistrationInfoRepository extends CrudRepository {
@Query("SELECT new OAuth2ClientRegistrationInfoEntity(cr_info) " +
"FROM OAuth2ClientRegistrationInfoEntity cr_info " +
@@ -34,7 +35,7 @@ public interface OAuth2ClientRegistrationInfoRepository extends CrudRepository findAllByDomainSchemesAndName(@Param("domainSchemes") List domainSchemes,
@Param("domainName") String domainName);
- @Query("SELECT new org.thingsboard.server.dao.model.sql.ExtendedOAuth2ClientRegistrationInfoEntity(cr_info, cr.domainName, cr.domainScheme) " +
+ @Query("SELECT new org.thingsboard.server.dao.model.sql.deprecated.ExtendedOAuth2ClientRegistrationInfoEntity(cr_info, cr.domainName, cr.domainScheme) " +
"FROM OAuth2ClientRegistrationInfoEntity cr_info " +
"LEFT JOIN OAuth2ClientRegistrationEntity cr on cr_info.id = cr.clientRegistrationInfoId ")
List findAllExtended();
diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/OAuth2ClientRegistrationRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/deprecated/OAuth2ClientRegistrationRepository.java
similarity index 83%
rename from dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/OAuth2ClientRegistrationRepository.java
rename to dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/deprecated/OAuth2ClientRegistrationRepository.java
index 1849f46514..1f4e4783ab 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/OAuth2ClientRegistrationRepository.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/deprecated/OAuth2ClientRegistrationRepository.java
@@ -13,12 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.thingsboard.server.dao.sql.oauth2;
+package org.thingsboard.server.dao.sql.oauth2.deprecated;
import org.springframework.data.repository.CrudRepository;
-import org.thingsboard.server.dao.model.sql.OAuth2ClientRegistrationEntity;
+import org.thingsboard.server.dao.model.sql.deprecated.OAuth2ClientRegistrationEntity;
import java.util.UUID;
+@Deprecated
public interface OAuth2ClientRegistrationRepository extends CrudRepository {
}
diff --git a/dao/src/main/resources/sql/schema-entities-hsql.sql b/dao/src/main/resources/sql/schema-entities-hsql.sql
index 2c5113867a..ca7cd73604 100644
--- a/dao/src/main/resources/sql/schema-entities-hsql.sql
+++ b/dao/src/main/resources/sql/schema-entities-hsql.sql
@@ -374,16 +374,24 @@ CREATE TABLE IF NOT EXISTS ts_kv_dictionary (
CONSTRAINT ts_key_id_pkey PRIMARY KEY (key)
);
-CREATE TABLE IF NOT EXISTS oauth2_client_registration_info (
- id uuid NOT NULL CONSTRAINT oauth2_client_registration_info_pkey PRIMARY KEY,
+CREATE TABLE IF NOT EXISTS oauth2_params (
+ id uuid NOT NULL CONSTRAINT oauth2_params_pkey PRIMARY KEY,
enabled boolean,
+ tenant_id uuid,
+ created_time bigint NOT NULL
+);
+
+CREATE TABLE IF NOT EXISTS oauth2_registration (
+ id uuid NOT NULL CONSTRAINT oauth2_registration_pkey PRIMARY KEY,
+ oauth2_params_id uuid NOT NULL,
created_time bigint NOT NULL,
additional_info varchar,
client_id varchar(255),
- client_secret varchar(255),
+ client_secret varchar(2048),
authorization_uri varchar(255),
token_uri varchar(255),
scope varchar(255),
+ platforms varchar(255),
user_info_uri varchar(255),
user_name_attribute_name varchar(255),
jwk_set_uri varchar(255),
@@ -404,15 +412,28 @@ CREATE TABLE IF NOT EXISTS oauth2_client_registration_info (
custom_url varchar(255),
custom_username varchar(255),
custom_password varchar(255),
- custom_send_token boolean
+ custom_send_token boolean,
+ CONSTRAINT fk_registration_oauth2_params FOREIGN KEY (oauth2_params_id) REFERENCES oauth2_params(id) ON DELETE CASCADE
);
-CREATE TABLE IF NOT EXISTS oauth2_client_registration (
- id uuid NOT NULL CONSTRAINT oauth2_client_registration_pkey PRIMARY KEY,
+CREATE TABLE IF NOT EXISTS oauth2_domain (
+ id uuid NOT NULL CONSTRAINT oauth2_domain_pkey PRIMARY KEY,
+ oauth2_params_id uuid NOT NULL,
created_time bigint NOT NULL,
domain_name varchar(255),
domain_scheme varchar(31),
- client_registration_info_id uuid
+ CONSTRAINT fk_domain_oauth2_params FOREIGN KEY (oauth2_params_id) REFERENCES oauth2_params(id) ON DELETE CASCADE,
+ CONSTRAINT oauth2_domain_unq_key UNIQUE (oauth2_params_id, domain_name, domain_scheme)
+);
+
+CREATE TABLE IF NOT EXISTS oauth2_mobile (
+ id uuid NOT NULL CONSTRAINT oauth2_mobile_pkey PRIMARY KEY,
+ oauth2_params_id uuid NOT NULL,
+ created_time bigint NOT NULL,
+ pkg_name varchar(255),
+ app_secret varchar(2048),
+ CONSTRAINT fk_mobile_oauth2_params FOREIGN KEY (oauth2_params_id) REFERENCES oauth2_params(id) ON DELETE CASCADE,
+ CONSTRAINT oauth2_mobile_unq_key UNIQUE (oauth2_params_id, pkg_name)
);
CREATE TABLE IF NOT EXISTS oauth2_client_registration_template (
@@ -443,6 +464,49 @@ CREATE TABLE IF NOT EXISTS oauth2_client_registration_template (
CONSTRAINT oauth2_template_provider_id_unq_key UNIQUE (provider_id)
);
+-- Deprecated
+CREATE TABLE IF NOT EXISTS oauth2_client_registration_info (
+ id uuid NOT NULL CONSTRAINT oauth2_client_registration_info_pkey PRIMARY KEY,
+ enabled boolean,
+ created_time bigint NOT NULL,
+ additional_info varchar,
+ client_id varchar(255),
+ client_secret varchar(255),
+ authorization_uri varchar(255),
+ token_uri varchar(255),
+ scope varchar(255),
+ user_info_uri varchar(255),
+ user_name_attribute_name varchar(255),
+ jwk_set_uri varchar(255),
+ client_authentication_method varchar(255),
+ login_button_label varchar(255),
+ login_button_icon varchar(255),
+ allow_user_creation boolean,
+ activate_user boolean,
+ type varchar(31),
+ basic_email_attribute_key varchar(31),
+ basic_first_name_attribute_key varchar(31),
+ basic_last_name_attribute_key varchar(31),
+ basic_tenant_name_strategy varchar(31),
+ basic_tenant_name_pattern varchar(255),
+ basic_customer_name_pattern varchar(255),
+ basic_default_dashboard_name varchar(255),
+ basic_always_full_screen boolean,
+ custom_url varchar(255),
+ custom_username varchar(255),
+ custom_password varchar(255),
+ custom_send_token boolean
+);
+
+-- Deprecated
+CREATE TABLE IF NOT EXISTS oauth2_client_registration (
+ id uuid NOT NULL CONSTRAINT oauth2_client_registration_pkey PRIMARY KEY,
+ created_time bigint NOT NULL,
+ domain_name varchar(255),
+ domain_scheme varchar(31),
+ client_registration_info_id uuid
+);
+
CREATE TABLE IF NOT EXISTS api_usage_state (
id uuid NOT NULL CONSTRAINT usage_record_pkey PRIMARY KEY,
created_time bigint NOT NULL,
diff --git a/dao/src/main/resources/sql/schema-entities.sql b/dao/src/main/resources/sql/schema-entities.sql
index 3140ff83d6..303bf6f0f9 100644
--- a/dao/src/main/resources/sql/schema-entities.sql
+++ b/dao/src/main/resources/sql/schema-entities.sql
@@ -411,16 +411,24 @@ CREATE TABLE IF NOT EXISTS ts_kv_dictionary
CONSTRAINT ts_key_id_pkey PRIMARY KEY (key)
);
-CREATE TABLE IF NOT EXISTS oauth2_client_registration_info (
- id uuid NOT NULL CONSTRAINT oauth2_client_registration_info_pkey PRIMARY KEY,
+CREATE TABLE IF NOT EXISTS oauth2_params (
+ id uuid NOT NULL CONSTRAINT oauth2_params_pkey PRIMARY KEY,
enabled boolean,
+ tenant_id uuid,
+ created_time bigint NOT NULL
+);
+
+CREATE TABLE IF NOT EXISTS oauth2_registration (
+ id uuid NOT NULL CONSTRAINT oauth2_registration_pkey PRIMARY KEY,
+ oauth2_params_id uuid NOT NULL,
created_time bigint NOT NULL,
additional_info varchar,
client_id varchar(255),
- client_secret varchar(255),
+ client_secret varchar(2048),
authorization_uri varchar(255),
token_uri varchar(255),
scope varchar(255),
+ platforms varchar(255),
user_info_uri varchar(255),
user_name_attribute_name varchar(255),
jwk_set_uri varchar(255),
@@ -441,15 +449,28 @@ CREATE TABLE IF NOT EXISTS oauth2_client_registration_info (
custom_url varchar(255),
custom_username varchar(255),
custom_password varchar(255),
- custom_send_token boolean
+ custom_send_token boolean,
+ CONSTRAINT fk_registration_oauth2_params FOREIGN KEY (oauth2_params_id) REFERENCES oauth2_params(id) ON DELETE CASCADE
);
-CREATE TABLE IF NOT EXISTS oauth2_client_registration (
- id uuid NOT NULL CONSTRAINT oauth2_client_registration_pkey PRIMARY KEY,
+CREATE TABLE IF NOT EXISTS oauth2_domain (
+ id uuid NOT NULL CONSTRAINT oauth2_domain_pkey PRIMARY KEY,
+ oauth2_params_id uuid NOT NULL,
created_time bigint NOT NULL,
domain_name varchar(255),
domain_scheme varchar(31),
- client_registration_info_id uuid
+ CONSTRAINT fk_domain_oauth2_params FOREIGN KEY (oauth2_params_id) REFERENCES oauth2_params(id) ON DELETE CASCADE,
+ CONSTRAINT oauth2_domain_unq_key UNIQUE (oauth2_params_id, domain_name, domain_scheme)
+);
+
+CREATE TABLE IF NOT EXISTS oauth2_mobile (
+ id uuid NOT NULL CONSTRAINT oauth2_mobile_pkey PRIMARY KEY,
+ oauth2_params_id uuid NOT NULL,
+ created_time bigint NOT NULL,
+ pkg_name varchar(255),
+ app_secret varchar(2048),
+ CONSTRAINT fk_mobile_oauth2_params FOREIGN KEY (oauth2_params_id) REFERENCES oauth2_params(id) ON DELETE CASCADE,
+ CONSTRAINT oauth2_mobile_unq_key UNIQUE (oauth2_params_id, pkg_name)
);
CREATE TABLE IF NOT EXISTS oauth2_client_registration_template (
@@ -480,6 +501,49 @@ CREATE TABLE IF NOT EXISTS oauth2_client_registration_template (
CONSTRAINT oauth2_template_provider_id_unq_key UNIQUE (provider_id)
);
+-- Deprecated
+CREATE TABLE IF NOT EXISTS oauth2_client_registration_info (
+ id uuid NOT NULL CONSTRAINT oauth2_client_registration_info_pkey PRIMARY KEY,
+ enabled boolean,
+ created_time bigint NOT NULL,
+ additional_info varchar,
+ client_id varchar(255),
+ client_secret varchar(255),
+ authorization_uri varchar(255),
+ token_uri varchar(255),
+ scope varchar(255),
+ user_info_uri varchar(255),
+ user_name_attribute_name varchar(255),
+ jwk_set_uri varchar(255),
+ client_authentication_method varchar(255),
+ login_button_label varchar(255),
+ login_button_icon varchar(255),
+ allow_user_creation boolean,
+ activate_user boolean,
+ type varchar(31),
+ basic_email_attribute_key varchar(31),
+ basic_first_name_attribute_key varchar(31),
+ basic_last_name_attribute_key varchar(31),
+ basic_tenant_name_strategy varchar(31),
+ basic_tenant_name_pattern varchar(255),
+ basic_customer_name_pattern varchar(255),
+ basic_default_dashboard_name varchar(255),
+ basic_always_full_screen boolean,
+ custom_url varchar(255),
+ custom_username varchar(255),
+ custom_password varchar(255),
+ custom_send_token boolean
+);
+
+-- Deprecated
+CREATE TABLE IF NOT EXISTS oauth2_client_registration (
+ id uuid NOT NULL CONSTRAINT oauth2_client_registration_pkey PRIMARY KEY,
+ created_time bigint NOT NULL,
+ domain_name varchar(255),
+ domain_scheme varchar(31),
+ client_registration_info_id uuid
+);
+
CREATE TABLE IF NOT EXISTS api_usage_state (
id uuid NOT NULL CONSTRAINT usage_record_pkey PRIMARY KEY,
created_time bigint NOT NULL,
diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/BaseOAuth2ServiceTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/BaseOAuth2ServiceTest.java
index ebfbfccd2a..4077bb2176 100644
--- a/dao/src/test/java/org/thingsboard/server/dao/service/BaseOAuth2ServiceTest.java
+++ b/dao/src/test/java/org/thingsboard/server/dao/service/BaseOAuth2ServiceTest.java
@@ -16,208 +16,227 @@
package org.thingsboard.server.dao.service;
import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
+import org.apache.commons.lang3.RandomStringUtils;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
-import org.thingsboard.server.common.data.oauth2.*;
+import org.thingsboard.server.common.data.oauth2.MapperType;
+import org.thingsboard.server.common.data.oauth2.OAuth2ClientInfo;
+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.OAuth2MobileInfo;
+import org.thingsboard.server.common.data.oauth2.OAuth2ParamsInfo;
+import org.thingsboard.server.common.data.oauth2.OAuth2Registration;
+import org.thingsboard.server.common.data.oauth2.OAuth2RegistrationInfo;
+import org.thingsboard.server.common.data.oauth2.PlatformType;
+import org.thingsboard.server.common.data.oauth2.SchemeType;
import org.thingsboard.server.dao.exception.DataValidationException;
import org.thingsboard.server.dao.oauth2.OAuth2Service;
-import java.util.*;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.UUID;
import java.util.stream.Collectors;
public class BaseOAuth2ServiceTest extends AbstractServiceTest {
- private static final OAuth2ClientsParams EMPTY_PARAMS = new OAuth2ClientsParams(false, new ArrayList<>());
+ private static final OAuth2Info EMPTY_PARAMS = new OAuth2Info(false, Collections.emptyList());
@Autowired
protected OAuth2Service oAuth2Service;
@Before
public void beforeRun() {
- Assert.assertTrue(oAuth2Service.findAllClientRegistrationInfos().isEmpty());
+ Assert.assertTrue(oAuth2Service.findAllRegistrations().isEmpty());
}
@After
public void after() {
- oAuth2Service.saveOAuth2Params(EMPTY_PARAMS);
- Assert.assertTrue(oAuth2Service.findAllClientRegistrationInfos().isEmpty());
- Assert.assertTrue(oAuth2Service.findOAuth2Params().getDomainsParams().isEmpty());
+ oAuth2Service.saveOAuth2Info(EMPTY_PARAMS);
+ Assert.assertTrue(oAuth2Service.findAllRegistrations().isEmpty());
+ Assert.assertTrue(oAuth2Service.findOAuth2Info().getOauth2ParamsInfos().isEmpty());
}
@Test(expected = DataValidationException.class)
public void testSaveHttpAndMixedDomainsTogether() {
- OAuth2ClientsParams clientsParams = new OAuth2ClientsParams(true, Lists.newArrayList(
- OAuth2ClientsDomainParams.builder()
+ OAuth2Info oAuth2Info = new OAuth2Info(true, Lists.newArrayList(
+ OAuth2ParamsInfo.builder()
.domainInfos(Lists.newArrayList(
- DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTP).build(),
- DomainInfo.builder().name("first-domain").scheme(SchemeType.MIXED).build(),
- DomainInfo.builder().name("third-domain").scheme(SchemeType.HTTPS).build()
+ OAuth2DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTP).build(),
+ OAuth2DomainInfo.builder().name("first-domain").scheme(SchemeType.MIXED).build(),
+ OAuth2DomainInfo.builder().name("third-domain").scheme(SchemeType.HTTPS).build()
))
.clientRegistrations(Lists.newArrayList(
- validClientRegistrationDto(),
- validClientRegistrationDto(),
- validClientRegistrationDto()
+ validRegistrationInfo(),
+ validRegistrationInfo(),
+ validRegistrationInfo()
))
.build()
));
- oAuth2Service.saveOAuth2Params(clientsParams);
+ oAuth2Service.saveOAuth2Info(oAuth2Info);
}
@Test(expected = DataValidationException.class)
public void testSaveHttpsAndMixedDomainsTogether() {
- OAuth2ClientsParams clientsParams = new OAuth2ClientsParams(true, Lists.newArrayList(
- OAuth2ClientsDomainParams.builder()
+ OAuth2Info oAuth2Info = new OAuth2Info(true, Lists.newArrayList(
+ OAuth2ParamsInfo.builder()
.domainInfos(Lists.newArrayList(
- DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTPS).build(),
- DomainInfo.builder().name("first-domain").scheme(SchemeType.MIXED).build(),
- DomainInfo.builder().name("third-domain").scheme(SchemeType.HTTPS).build()
+ OAuth2DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTPS).build(),
+ OAuth2DomainInfo.builder().name("first-domain").scheme(SchemeType.MIXED).build(),
+ OAuth2DomainInfo.builder().name("third-domain").scheme(SchemeType.HTTPS).build()
))
.clientRegistrations(Lists.newArrayList(
- validClientRegistrationDto(),
- validClientRegistrationDto(),
- validClientRegistrationDto()
+ validRegistrationInfo(),
+ validRegistrationInfo(),
+ validRegistrationInfo()
))
.build()
));
- oAuth2Service.saveOAuth2Params(clientsParams);
+ oAuth2Service.saveOAuth2Info(oAuth2Info);
}
@Test
public void testCreateAndFindParams() {
- OAuth2ClientsParams clientsParams = createDefaultClientsParams();
- oAuth2Service.saveOAuth2Params(clientsParams);
- OAuth2ClientsParams foundClientsParams = oAuth2Service.findOAuth2Params();
- Assert.assertNotNull(foundClientsParams);
+ OAuth2Info oAuth2Info = createDefaultOAuth2Info();
+ oAuth2Service.saveOAuth2Info(oAuth2Info);
+ OAuth2Info foundOAuth2Info = oAuth2Service.findOAuth2Info();
+ Assert.assertNotNull(foundOAuth2Info);
// TODO ask if it's safe to check equality on AdditionalProperties
- Assert.assertEquals(clientsParams, foundClientsParams);
+ Assert.assertEquals(oAuth2Info, foundOAuth2Info);
}
@Test
public void testDisableParams() {
- OAuth2ClientsParams clientsParams = createDefaultClientsParams();
- clientsParams.setEnabled(true);
- oAuth2Service.saveOAuth2Params(clientsParams);
- OAuth2ClientsParams foundClientsParams = oAuth2Service.findOAuth2Params();
- Assert.assertNotNull(foundClientsParams);
- Assert.assertEquals(clientsParams, foundClientsParams);
-
- clientsParams.setEnabled(false);
- oAuth2Service.saveOAuth2Params(clientsParams);
- OAuth2ClientsParams foundDisabledClientsParams = oAuth2Service.findOAuth2Params();
- Assert.assertEquals(clientsParams, foundDisabledClientsParams);
+ OAuth2Info oAuth2Info = createDefaultOAuth2Info();
+ oAuth2Info.setEnabled(true);
+ oAuth2Service.saveOAuth2Info(oAuth2Info);
+ OAuth2Info foundOAuth2Info = oAuth2Service.findOAuth2Info();
+ Assert.assertNotNull(foundOAuth2Info);
+ Assert.assertEquals(oAuth2Info, foundOAuth2Info);
+
+ oAuth2Info.setEnabled(false);
+ oAuth2Service.saveOAuth2Info(oAuth2Info);
+ OAuth2Info foundDisabledOAuth2Info = oAuth2Service.findOAuth2Info();
+ Assert.assertEquals(oAuth2Info, foundDisabledOAuth2Info);
}
@Test
public void testClearDomainParams() {
- OAuth2ClientsParams clientsParams = createDefaultClientsParams();
- oAuth2Service.saveOAuth2Params(clientsParams);
- OAuth2ClientsParams foundClientsParams = oAuth2Service.findOAuth2Params();
- Assert.assertNotNull(foundClientsParams);
- Assert.assertEquals(clientsParams, foundClientsParams);
-
- oAuth2Service.saveOAuth2Params(EMPTY_PARAMS);
- OAuth2ClientsParams foundAfterClearClientsParams = oAuth2Service.findOAuth2Params();
+ OAuth2Info oAuth2Info = createDefaultOAuth2Info();
+ oAuth2Service.saveOAuth2Info(oAuth2Info);
+ OAuth2Info foundOAuth2Info = oAuth2Service.findOAuth2Info();
+ Assert.assertNotNull(foundOAuth2Info);
+ Assert.assertEquals(oAuth2Info, foundOAuth2Info);
+
+ oAuth2Service.saveOAuth2Info(EMPTY_PARAMS);
+ OAuth2Info foundAfterClearClientsParams = oAuth2Service.findOAuth2Info();
Assert.assertNotNull(foundAfterClearClientsParams);
Assert.assertEquals(EMPTY_PARAMS, foundAfterClearClientsParams);
}
@Test
public void testUpdateClientsParams() {
- OAuth2ClientsParams clientsParams = createDefaultClientsParams();
- oAuth2Service.saveOAuth2Params(clientsParams);
- OAuth2ClientsParams foundClientsParams = oAuth2Service.findOAuth2Params();
- Assert.assertNotNull(foundClientsParams);
- Assert.assertEquals(clientsParams, foundClientsParams);
-
- OAuth2ClientsParams newClientsParams = new OAuth2ClientsParams(true, Lists.newArrayList(
- OAuth2ClientsDomainParams.builder()
+ OAuth2Info oAuth2Info = createDefaultOAuth2Info();
+ oAuth2Service.saveOAuth2Info(oAuth2Info);
+ OAuth2Info foundOAuth2Info = oAuth2Service.findOAuth2Info();
+ Assert.assertNotNull(foundOAuth2Info);
+ Assert.assertEquals(oAuth2Info, foundOAuth2Info);
+
+ OAuth2Info newOAuth2Info = new OAuth2Info(true, Lists.newArrayList(
+ OAuth2ParamsInfo.builder()
.domainInfos(Lists.newArrayList(
- DomainInfo.builder().name("another-domain").scheme(SchemeType.HTTPS).build()
+ OAuth2DomainInfo.builder().name("another-domain").scheme(SchemeType.HTTPS).build()
))
+ .mobileInfos(Collections.emptyList())
.clientRegistrations(Lists.newArrayList(
- validClientRegistrationDto()
+ validRegistrationInfo()
))
.build(),
- OAuth2ClientsDomainParams.builder()
+ OAuth2ParamsInfo.builder()
.domainInfos(Lists.newArrayList(
- DomainInfo.builder().name("test-domain").scheme(SchemeType.MIXED).build()
+ OAuth2DomainInfo.builder().name("test-domain").scheme(SchemeType.MIXED).build()
))
+ .mobileInfos(Collections.emptyList())
.clientRegistrations(Lists.newArrayList(
- validClientRegistrationDto()
+ validRegistrationInfo()
))
.build()
));
- oAuth2Service.saveOAuth2Params(newClientsParams);
- OAuth2ClientsParams foundAfterUpdateClientsParams = oAuth2Service.findOAuth2Params();
- Assert.assertNotNull(foundAfterUpdateClientsParams);
- Assert.assertEquals(newClientsParams, foundAfterUpdateClientsParams);
+ oAuth2Service.saveOAuth2Info(newOAuth2Info);
+ OAuth2Info foundAfterUpdateOAuth2Info = oAuth2Service.findOAuth2Info();
+ Assert.assertNotNull(foundAfterUpdateOAuth2Info);
+ Assert.assertEquals(newOAuth2Info, foundAfterUpdateOAuth2Info);
}
@Test
public void testGetOAuth2Clients() {
- List firstGroup = Lists.newArrayList(
- validClientRegistrationDto(),
- validClientRegistrationDto(),
- validClientRegistrationDto(),
- validClientRegistrationDto()
+ List firstGroup = Lists.newArrayList(
+ validRegistrationInfo(),
+ validRegistrationInfo(),
+ validRegistrationInfo(),
+ validRegistrationInfo()
);
- List secondGroup = Lists.newArrayList(
- validClientRegistrationDto(),
- validClientRegistrationDto()
+ List secondGroup = Lists.newArrayList(
+ validRegistrationInfo(),
+ validRegistrationInfo()
);
- List thirdGroup = Lists.newArrayList(
- validClientRegistrationDto()
+ List thirdGroup = Lists.newArrayList(
+ validRegistrationInfo()
);
- OAuth2ClientsParams clientsParams = new OAuth2ClientsParams(true, Lists.newArrayList(
- OAuth2ClientsDomainParams.builder()
+ OAuth2Info oAuth2Info = new OAuth2Info(true, Lists.newArrayList(
+ OAuth2ParamsInfo.builder()
.domainInfos(Lists.newArrayList(
- DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTP).build(),
- DomainInfo.builder().name("second-domain").scheme(SchemeType.MIXED).build(),
- DomainInfo.builder().name("third-domain").scheme(SchemeType.HTTPS).build()
+ OAuth2DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTP).build(),
+ OAuth2DomainInfo.builder().name("second-domain").scheme(SchemeType.MIXED).build(),
+ OAuth2DomainInfo.builder().name("third-domain").scheme(SchemeType.HTTPS).build()
))
+ .mobileInfos(Collections.emptyList())
.clientRegistrations(firstGroup)
.build(),
- OAuth2ClientsDomainParams.builder()
+ OAuth2ParamsInfo.builder()
.domainInfos(Lists.newArrayList(
- DomainInfo.builder().name("second-domain").scheme(SchemeType.HTTP).build(),
- DomainInfo.builder().name("fourth-domain").scheme(SchemeType.MIXED).build()
+ OAuth2DomainInfo.builder().name("second-domain").scheme(SchemeType.HTTP).build(),
+ OAuth2DomainInfo.builder().name("fourth-domain").scheme(SchemeType.MIXED).build()
))
+ .mobileInfos(Collections.emptyList())
.clientRegistrations(secondGroup)
.build(),
- OAuth2ClientsDomainParams.builder()
+ OAuth2ParamsInfo.builder()
.domainInfos(Lists.newArrayList(
- DomainInfo.builder().name("second-domain").scheme(SchemeType.HTTPS).build(),
- DomainInfo.builder().name("fifth-domain").scheme(SchemeType.HTTP).build()
+ OAuth2DomainInfo.builder().name("second-domain").scheme(SchemeType.HTTPS).build(),
+ OAuth2DomainInfo.builder().name("fifth-domain").scheme(SchemeType.HTTP).build()
))
+ .mobileInfos(Collections.emptyList())
.clientRegistrations(thirdGroup)
.build()
));
- oAuth2Service.saveOAuth2Params(clientsParams);
- OAuth2ClientsParams foundClientsParams = oAuth2Service.findOAuth2Params();
- Assert.assertNotNull(foundClientsParams);
- Assert.assertEquals(clientsParams, foundClientsParams);
+ oAuth2Service.saveOAuth2Info(oAuth2Info);
+ OAuth2Info foundOAuth2Info = oAuth2Service.findOAuth2Info();
+ Assert.assertNotNull(foundOAuth2Info);
+ Assert.assertEquals(oAuth2Info, foundOAuth2Info);
List firstGroupClientInfos = firstGroup.stream()
- .map(clientRegistrationDto -> new OAuth2ClientInfo(
- clientRegistrationDto.getLoginButtonLabel(), clientRegistrationDto.getLoginButtonIcon(), null))
+ .map(registrationInfo -> new OAuth2ClientInfo(
+ registrationInfo.getLoginButtonLabel(), registrationInfo.getLoginButtonIcon(), null))
.collect(Collectors.toList());
List secondGroupClientInfos = secondGroup.stream()
- .map(clientRegistrationDto -> new OAuth2ClientInfo(
- clientRegistrationDto.getLoginButtonLabel(), clientRegistrationDto.getLoginButtonIcon(), null))
+ .map(registrationInfo -> new OAuth2ClientInfo(
+ registrationInfo.getLoginButtonLabel(), registrationInfo.getLoginButtonIcon(), null))
.collect(Collectors.toList());
List thirdGroupClientInfos = thirdGroup.stream()
- .map(clientRegistrationDto -> new OAuth2ClientInfo(
- clientRegistrationDto.getLoginButtonLabel(), clientRegistrationDto.getLoginButtonIcon(), null))
+ .map(registrationInfo -> new OAuth2ClientInfo(
+ registrationInfo.getLoginButtonLabel(), registrationInfo.getLoginButtonIcon(), null))
.collect(Collectors.toList());
- List nonExistentDomainClients = oAuth2Service.getOAuth2Clients("http", "non-existent-domain");
+ List nonExistentDomainClients = oAuth2Service.getOAuth2Clients("http", "non-existent-domain", null, null);
Assert.assertTrue(nonExistentDomainClients.isEmpty());
- List firstDomainHttpClients = oAuth2Service.getOAuth2Clients("http", "first-domain");
+ List firstDomainHttpClients = oAuth2Service.getOAuth2Clients("http", "first-domain", null, null);
Assert.assertEquals(firstGroupClientInfos.size(), firstDomainHttpClients.size());
firstGroupClientInfos.forEach(firstGroupClientInfo -> {
Assert.assertTrue(
@@ -227,10 +246,10 @@ public class BaseOAuth2ServiceTest extends AbstractServiceTest {
);
});
- List firstDomainHttpsClients = oAuth2Service.getOAuth2Clients("https", "first-domain");
+ List firstDomainHttpsClients = oAuth2Service.getOAuth2Clients("https", "first-domain", null, null);
Assert.assertTrue(firstDomainHttpsClients.isEmpty());
- List fourthDomainHttpClients = oAuth2Service.getOAuth2Clients("http", "fourth-domain");
+ List fourthDomainHttpClients = oAuth2Service.getOAuth2Clients("http", "fourth-domain", null, null);
Assert.assertEquals(secondGroupClientInfos.size(), fourthDomainHttpClients.size());
secondGroupClientInfos.forEach(secondGroupClientInfo -> {
Assert.assertTrue(
@@ -239,7 +258,7 @@ public class BaseOAuth2ServiceTest extends AbstractServiceTest {
&& clientInfo.getName().equals(secondGroupClientInfo.getName()))
);
});
- List fourthDomainHttpsClients = oAuth2Service.getOAuth2Clients("https", "fourth-domain");
+ List fourthDomainHttpsClients = oAuth2Service.getOAuth2Clients("https", "fourth-domain", null, null);
Assert.assertEquals(secondGroupClientInfos.size(), fourthDomainHttpsClients.size());
secondGroupClientInfos.forEach(secondGroupClientInfo -> {
Assert.assertTrue(
@@ -249,7 +268,7 @@ public class BaseOAuth2ServiceTest extends AbstractServiceTest {
);
});
- List secondDomainHttpClients = oAuth2Service.getOAuth2Clients("http", "second-domain");
+ List secondDomainHttpClients = oAuth2Service.getOAuth2Clients("http", "second-domain", null, null);
Assert.assertEquals(firstGroupClientInfos.size() + secondGroupClientInfos.size(), secondDomainHttpClients.size());
firstGroupClientInfos.forEach(firstGroupClientInfo -> {
Assert.assertTrue(
@@ -266,7 +285,7 @@ public class BaseOAuth2ServiceTest extends AbstractServiceTest {
);
});
- List secondDomainHttpsClients = oAuth2Service.getOAuth2Clients("https", "second-domain");
+ List secondDomainHttpsClients = oAuth2Service.getOAuth2Clients("https", "second-domain", null, null);
Assert.assertEquals(firstGroupClientInfos.size() + thirdGroupClientInfos.size(), secondDomainHttpsClients.size());
firstGroupClientInfos.forEach(firstGroupClientInfo -> {
Assert.assertTrue(
@@ -286,34 +305,35 @@ public class BaseOAuth2ServiceTest extends AbstractServiceTest {
@Test
public void testGetOAuth2ClientsForHttpAndHttps() {
- List firstGroup = Lists.newArrayList(
- validClientRegistrationDto(),
- validClientRegistrationDto(),
- validClientRegistrationDto(),
- validClientRegistrationDto()
+ List firstGroup = Lists.newArrayList(
+ validRegistrationInfo(),
+ validRegistrationInfo(),
+ validRegistrationInfo(),
+ validRegistrationInfo()
);
- OAuth2ClientsParams clientsParams = new OAuth2ClientsParams(true, Lists.newArrayList(
- OAuth2ClientsDomainParams.builder()
+ OAuth2Info oAuth2Info = new OAuth2Info(true, Lists.newArrayList(
+ OAuth2ParamsInfo.builder()
.domainInfos(Lists.newArrayList(
- DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTP).build(),
- DomainInfo.builder().name("second-domain").scheme(SchemeType.MIXED).build(),
- DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTPS).build()
+ OAuth2DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTP).build(),
+ OAuth2DomainInfo.builder().name("second-domain").scheme(SchemeType.MIXED).build(),
+ OAuth2DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTPS).build()
))
+ .mobileInfos(Collections.emptyList())
.clientRegistrations(firstGroup)
.build()
));
- oAuth2Service.saveOAuth2Params(clientsParams);
- OAuth2ClientsParams foundClientsParams = oAuth2Service.findOAuth2Params();
- Assert.assertNotNull(foundClientsParams);
- Assert.assertEquals(clientsParams, foundClientsParams);
+ oAuth2Service.saveOAuth2Info(oAuth2Info);
+ OAuth2Info foundOAuth2Info = oAuth2Service.findOAuth2Info();
+ Assert.assertNotNull(foundOAuth2Info);
+ Assert.assertEquals(oAuth2Info, foundOAuth2Info);
List firstGroupClientInfos = firstGroup.stream()
- .map(clientRegistrationDto -> new OAuth2ClientInfo(
- clientRegistrationDto.getLoginButtonLabel(), clientRegistrationDto.getLoginButtonIcon(), null))
+ .map(registrationInfo -> new OAuth2ClientInfo(
+ registrationInfo.getLoginButtonLabel(), registrationInfo.getLoginButtonIcon(), null))
.collect(Collectors.toList());
- List firstDomainHttpClients = oAuth2Service.getOAuth2Clients("http", "first-domain");
+ List firstDomainHttpClients = oAuth2Service.getOAuth2Clients("http", "first-domain", null, null);
Assert.assertEquals(firstGroupClientInfos.size(), firstDomainHttpClients.size());
firstGroupClientInfos.forEach(firstGroupClientInfo -> {
Assert.assertTrue(
@@ -323,7 +343,7 @@ public class BaseOAuth2ServiceTest extends AbstractServiceTest {
);
});
- List firstDomainHttpsClients = oAuth2Service.getOAuth2Clients("https", "first-domain");
+ List firstDomainHttpsClients = oAuth2Service.getOAuth2Clients("https", "first-domain", null, null);
Assert.assertEquals(firstGroupClientInfos.size(), firstDomainHttpsClients.size());
firstGroupClientInfos.forEach(firstGroupClientInfo -> {
Assert.assertTrue(
@@ -336,176 +356,285 @@ public class BaseOAuth2ServiceTest extends AbstractServiceTest {
@Test
public void testGetDisabledOAuth2Clients() {
- OAuth2ClientsParams clientsParams = new OAuth2ClientsParams(true, Lists.newArrayList(
- OAuth2ClientsDomainParams.builder()
+ OAuth2Info oAuth2Info = new OAuth2Info(true, Lists.newArrayList(
+ OAuth2ParamsInfo.builder()
.domainInfos(Lists.newArrayList(
- DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTP).build(),
- DomainInfo.builder().name("second-domain").scheme(SchemeType.MIXED).build(),
- DomainInfo.builder().name("third-domain").scheme(SchemeType.HTTPS).build()
+ OAuth2DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTP).build(),
+ OAuth2DomainInfo.builder().name("second-domain").scheme(SchemeType.MIXED).build(),
+ OAuth2DomainInfo.builder().name("third-domain").scheme(SchemeType.HTTPS).build()
))
.clientRegistrations(Lists.newArrayList(
- validClientRegistrationDto(),
- validClientRegistrationDto(),
- validClientRegistrationDto()
+ validRegistrationInfo(),
+ validRegistrationInfo(),
+ validRegistrationInfo()
))
.build(),
- OAuth2ClientsDomainParams.builder()
+ OAuth2ParamsInfo.builder()
.domainInfos(Lists.newArrayList(
- DomainInfo.builder().name("second-domain").scheme(SchemeType.HTTP).build(),
- DomainInfo.builder().name("fourth-domain").scheme(SchemeType.MIXED).build()
+ OAuth2DomainInfo.builder().name("second-domain").scheme(SchemeType.HTTP).build(),
+ OAuth2DomainInfo.builder().name("fourth-domain").scheme(SchemeType.MIXED).build()
))
.clientRegistrations(Lists.newArrayList(
- validClientRegistrationDto(),
- validClientRegistrationDto()
+ validRegistrationInfo(),
+ validRegistrationInfo()
))
.build()
));
- oAuth2Service.saveOAuth2Params(clientsParams);
+ oAuth2Service.saveOAuth2Info(oAuth2Info);
- List secondDomainHttpClients = oAuth2Service.getOAuth2Clients("http", "second-domain");
+ List secondDomainHttpClients = oAuth2Service.getOAuth2Clients("http", "second-domain", null, null);
Assert.assertEquals(5, secondDomainHttpClients.size());
- clientsParams.setEnabled(false);
- oAuth2Service.saveOAuth2Params(clientsParams);
+ oAuth2Info.setEnabled(false);
+ oAuth2Service.saveOAuth2Info(oAuth2Info);
- List secondDomainHttpDisabledClients = oAuth2Service.getOAuth2Clients("http", "second-domain");
+ List secondDomainHttpDisabledClients = oAuth2Service.getOAuth2Clients("http", "second-domain", null, null);
Assert.assertEquals(0, secondDomainHttpDisabledClients.size());
}
@Test
- public void testFindAllClientRegistrationInfos() {
- OAuth2ClientsParams clientsParams = new OAuth2ClientsParams(true, Lists.newArrayList(
- OAuth2ClientsDomainParams.builder()
+ public void testFindAllRegistrations() {
+ OAuth2Info oAuth2Info = new OAuth2Info(true, Lists.newArrayList(
+ OAuth2ParamsInfo.builder()
.domainInfos(Lists.newArrayList(
- DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTP).build(),
- DomainInfo.builder().name("second-domain").scheme(SchemeType.MIXED).build(),
- DomainInfo.builder().name("third-domain").scheme(SchemeType.HTTPS).build()
+ OAuth2DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTP).build(),
+ OAuth2DomainInfo.builder().name("second-domain").scheme(SchemeType.MIXED).build(),
+ OAuth2DomainInfo.builder().name("third-domain").scheme(SchemeType.HTTPS).build()
))
.clientRegistrations(Lists.newArrayList(
- validClientRegistrationDto(),
- validClientRegistrationDto(),
- validClientRegistrationDto()
+ validRegistrationInfo(),
+ validRegistrationInfo(),
+ validRegistrationInfo()
))
.build(),
- OAuth2ClientsDomainParams.builder()
+ OAuth2ParamsInfo.builder()
.domainInfos(Lists.newArrayList(
- DomainInfo.builder().name("second-domain").scheme(SchemeType.HTTP).build(),
- DomainInfo.builder().name("fourth-domain").scheme(SchemeType.MIXED).build()
+ OAuth2DomainInfo.builder().name("second-domain").scheme(SchemeType.HTTP).build(),
+ OAuth2DomainInfo.builder().name("fourth-domain").scheme(SchemeType.MIXED).build()
))
.clientRegistrations(Lists.newArrayList(
- validClientRegistrationDto(),
- validClientRegistrationDto()
+ validRegistrationInfo(),
+ validRegistrationInfo()
))
.build(),
- OAuth2ClientsDomainParams.builder()
+ OAuth2ParamsInfo.builder()
.domainInfos(Lists.newArrayList(
- DomainInfo.builder().name("second-domain").scheme(SchemeType.HTTPS).build(),
- DomainInfo.builder().name("fifth-domain").scheme(SchemeType.HTTP).build()
+ OAuth2DomainInfo.builder().name("second-domain").scheme(SchemeType.HTTPS).build(),
+ OAuth2DomainInfo.builder().name("fifth-domain").scheme(SchemeType.HTTP).build()
))
.clientRegistrations(Lists.newArrayList(
- validClientRegistrationDto()
+ validRegistrationInfo()
))
.build()
));
- oAuth2Service.saveOAuth2Params(clientsParams);
- List foundClientRegistrationInfos = oAuth2Service.findAllClientRegistrationInfos();
- Assert.assertEquals(6, foundClientRegistrationInfos.size());
- clientsParams.getDomainsParams().stream()
- .flatMap(domainParams -> domainParams.getClientRegistrations().stream())
- .forEach(clientRegistrationDto ->
+ oAuth2Service.saveOAuth2Info(oAuth2Info);
+ List foundRegistrations = oAuth2Service.findAllRegistrations();
+ Assert.assertEquals(6, foundRegistrations.size());
+ oAuth2Info.getOauth2ParamsInfos().stream()
+ .flatMap(paramsInfo -> paramsInfo.getClientRegistrations().stream())
+ .forEach(registrationInfo ->
Assert.assertTrue(
- foundClientRegistrationInfos.stream()
- .anyMatch(clientRegistrationInfo -> clientRegistrationInfo.getClientId().equals(clientRegistrationDto.getClientId()))
+ foundRegistrations.stream()
+ .anyMatch(registration -> registration.getClientId().equals(registrationInfo.getClientId()))
)
);
}
@Test
- public void testFindClientRegistrationById() {
- OAuth2ClientsParams clientsParams = new OAuth2ClientsParams(true, Lists.newArrayList(
- OAuth2ClientsDomainParams.builder()
+ public void testFindRegistrationById() {
+ OAuth2Info oAuth2Info = new OAuth2Info(true, Lists.newArrayList(
+ OAuth2ParamsInfo.builder()
.domainInfos(Lists.newArrayList(
- DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTP).build(),
- DomainInfo.builder().name("second-domain").scheme(SchemeType.MIXED).build(),
- DomainInfo.builder().name("third-domain").scheme(SchemeType.HTTPS).build()
+ OAuth2DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTP).build(),
+ OAuth2DomainInfo.builder().name("second-domain").scheme(SchemeType.MIXED).build(),
+ OAuth2DomainInfo.builder().name("third-domain").scheme(SchemeType.HTTPS).build()
))
.clientRegistrations(Lists.newArrayList(
- validClientRegistrationDto(),
- validClientRegistrationDto(),
- validClientRegistrationDto()
+ validRegistrationInfo(),
+ validRegistrationInfo(),
+ validRegistrationInfo()
))
.build(),
- OAuth2ClientsDomainParams.builder()
+ OAuth2ParamsInfo.builder()
.domainInfos(Lists.newArrayList(
- DomainInfo.builder().name("second-domain").scheme(SchemeType.HTTP).build(),
- DomainInfo.builder().name("fourth-domain").scheme(SchemeType.MIXED).build()
+ OAuth2DomainInfo.builder().name("second-domain").scheme(SchemeType.HTTP).build(),
+ OAuth2DomainInfo.builder().name("fourth-domain").scheme(SchemeType.MIXED).build()
))
.clientRegistrations(Lists.newArrayList(
- validClientRegistrationDto(),
- validClientRegistrationDto()
+ validRegistrationInfo(),
+ validRegistrationInfo()
))
.build(),
- OAuth2ClientsDomainParams.builder()
+ OAuth2ParamsInfo.builder()
.domainInfos(Lists.newArrayList(
- DomainInfo.builder().name("second-domain").scheme(SchemeType.HTTPS).build(),
- DomainInfo.builder().name("fifth-domain").scheme(SchemeType.HTTP).build()
+ OAuth2DomainInfo.builder().name("second-domain").scheme(SchemeType.HTTPS).build(),
+ OAuth2DomainInfo.builder().name("fifth-domain").scheme(SchemeType.HTTP).build()
))
.clientRegistrations(Lists.newArrayList(
- validClientRegistrationDto()
+ validRegistrationInfo()
))
.build()
));
- oAuth2Service.saveOAuth2Params(clientsParams);
- List clientRegistrationInfos = oAuth2Service.findAllClientRegistrationInfos();
- clientRegistrationInfos.forEach(clientRegistrationInfo -> {
- OAuth2ClientRegistrationInfo foundClientRegistrationInfo = oAuth2Service.findClientRegistrationInfo(clientRegistrationInfo.getUuidId());
- Assert.assertEquals(clientRegistrationInfo, foundClientRegistrationInfo);
+ oAuth2Service.saveOAuth2Info(oAuth2Info);
+ List foundRegistrations = oAuth2Service.findAllRegistrations();
+ foundRegistrations.forEach(registration -> {
+ OAuth2Registration foundRegistration = oAuth2Service.findRegistration(registration.getUuidId());
+ Assert.assertEquals(registration, foundRegistration);
});
}
- private OAuth2ClientsParams createDefaultClientsParams() {
- return new OAuth2ClientsParams(true, Lists.newArrayList(
- OAuth2ClientsDomainParams.builder()
+ @Test
+ public void testFindAppSecret() {
+ OAuth2Info oAuth2Info = new OAuth2Info(true, Lists.newArrayList(
+ OAuth2ParamsInfo.builder()
+ .domainInfos(Lists.newArrayList(
+ OAuth2DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTP).build(),
+ OAuth2DomainInfo.builder().name("second-domain").scheme(SchemeType.MIXED).build(),
+ OAuth2DomainInfo.builder().name("third-domain").scheme(SchemeType.HTTPS).build()
+ ))
+ .mobileInfos(Lists.newArrayList(
+ validMobileInfo("com.test.pkg1", "testPkg1AppSecret"),
+ validMobileInfo("com.test.pkg2", "testPkg2AppSecret")
+ ))
+ .clientRegistrations(Lists.newArrayList(
+ validRegistrationInfo(),
+ validRegistrationInfo(),
+ validRegistrationInfo()
+ ))
+ .build(),
+ OAuth2ParamsInfo.builder()
+ .domainInfos(Lists.newArrayList(
+ OAuth2DomainInfo.builder().name("second-domain").scheme(SchemeType.HTTP).build(),
+ OAuth2DomainInfo.builder().name("fourth-domain").scheme(SchemeType.MIXED).build()
+ ))
+ .mobileInfos(Collections.emptyList())
+ .clientRegistrations(Lists.newArrayList(
+ validRegistrationInfo(),
+ validRegistrationInfo()
+ ))
+ .build()
+ ));
+ oAuth2Service.saveOAuth2Info(oAuth2Info);
+
+ OAuth2Info foundOAuth2Info = oAuth2Service.findOAuth2Info();
+ Assert.assertEquals(oAuth2Info, foundOAuth2Info);
+
+ List firstDomainHttpClients = oAuth2Service.getOAuth2Clients("http", "first-domain", "com.test.pkg1", null);
+ Assert.assertEquals(3, firstDomainHttpClients.size());
+ for (OAuth2ClientInfo clientInfo : firstDomainHttpClients) {
+ String[] segments = clientInfo.getUrl().split("/");
+ String registrationId = segments[segments.length-1];
+ String appSecret = oAuth2Service.findAppSecret(UUID.fromString(registrationId), "com.test.pkg1");
+ Assert.assertNotNull(appSecret);
+ Assert.assertEquals("testPkg1AppSecret", appSecret);
+ appSecret = oAuth2Service.findAppSecret(UUID.fromString(registrationId), "com.test.pkg2");
+ Assert.assertNotNull(appSecret);
+ Assert.assertEquals("testPkg2AppSecret", appSecret);
+ appSecret = oAuth2Service.findAppSecret(UUID.fromString(registrationId), "com.test.pkg3");
+ Assert.assertNull(appSecret);
+ }
+ }
+
+ @Test
+ public void testFindClientsByPackageAndPlatform() {
+ OAuth2Info oAuth2Info = new OAuth2Info(true, Lists.newArrayList(
+ OAuth2ParamsInfo.builder()
.domainInfos(Lists.newArrayList(
- DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTP).build(),
- DomainInfo.builder().name("second-domain").scheme(SchemeType.MIXED).build(),
- DomainInfo.builder().name("third-domain").scheme(SchemeType.HTTPS).build()
+ OAuth2DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTP).build(),
+ OAuth2DomainInfo.builder().name("second-domain").scheme(SchemeType.MIXED).build(),
+ OAuth2DomainInfo.builder().name("third-domain").scheme(SchemeType.HTTPS).build()
+ ))
+ .mobileInfos(Lists.newArrayList(
+ validMobileInfo("com.test.pkg1", "testPkg1Callback"),
+ validMobileInfo("com.test.pkg2", "testPkg2Callback")
))
.clientRegistrations(Lists.newArrayList(
- validClientRegistrationDto(),
- validClientRegistrationDto(),
- validClientRegistrationDto(),
- validClientRegistrationDto()
+ validRegistrationInfo("Google", Arrays.asList(PlatformType.WEB, PlatformType.ANDROID)),
+ validRegistrationInfo("Facebook", Arrays.asList(PlatformType.IOS)),
+ validRegistrationInfo("GitHub", Collections.emptyList())
))
.build(),
- OAuth2ClientsDomainParams.builder()
+ OAuth2ParamsInfo.builder()
.domainInfos(Lists.newArrayList(
- DomainInfo.builder().name("second-domain").scheme(SchemeType.MIXED).build(),
- DomainInfo.builder().name("fourth-domain").scheme(SchemeType.MIXED).build()
+ OAuth2DomainInfo.builder().name("second-domain").scheme(SchemeType.HTTP).build(),
+ OAuth2DomainInfo.builder().name("fourth-domain").scheme(SchemeType.MIXED).build()
))
+ .mobileInfos(Collections.emptyList())
.clientRegistrations(Lists.newArrayList(
- validClientRegistrationDto(),
- validClientRegistrationDto()
+ validRegistrationInfo(),
+ validRegistrationInfo()
))
.build()
));
+ oAuth2Service.saveOAuth2Info(oAuth2Info);
+
+ OAuth2Info foundOAuth2Info = oAuth2Service.findOAuth2Info();
+ Assert.assertEquals(oAuth2Info, foundOAuth2Info);
+
+ List firstDomainHttpClients = oAuth2Service.getOAuth2Clients("http", "first-domain", null, null);
+ Assert.assertEquals(3, firstDomainHttpClients.size());
+ List pkg1Clients = oAuth2Service.getOAuth2Clients("http", "first-domain", "com.test.pkg1", null);
+ Assert.assertEquals(3, pkg1Clients.size());
+ List pkg1AndroidClients = oAuth2Service.getOAuth2Clients("http", "first-domain", "com.test.pkg1", PlatformType.ANDROID);
+ Assert.assertEquals(2, pkg1AndroidClients.size());
+ Assert.assertTrue(pkg1AndroidClients.stream().anyMatch(client -> client.getName().equals("Google")));
+ Assert.assertTrue(pkg1AndroidClients.stream().anyMatch(client -> client.getName().equals("GitHub")));
+ List pkg1IOSClients = oAuth2Service.getOAuth2Clients("http", "first-domain", "com.test.pkg1", PlatformType.IOS);
+ Assert.assertEquals(2, pkg1IOSClients.size());
+ Assert.assertTrue(pkg1IOSClients.stream().anyMatch(client -> client.getName().equals("Facebook")));
+ Assert.assertTrue(pkg1IOSClients.stream().anyMatch(client -> client.getName().equals("GitHub")));
}
- private ClientRegistrationDto validClientRegistrationDto() {
- return ClientRegistrationDto.builder()
+ private OAuth2Info createDefaultOAuth2Info() {
+ return new OAuth2Info(true, Lists.newArrayList(
+ OAuth2ParamsInfo.builder()
+ .domainInfos(Lists.newArrayList(
+ OAuth2DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTP).build(),
+ OAuth2DomainInfo.builder().name("second-domain").scheme(SchemeType.MIXED).build(),
+ OAuth2DomainInfo.builder().name("third-domain").scheme(SchemeType.HTTPS).build()
+ ))
+ .mobileInfos(Collections.emptyList())
+ .clientRegistrations(Lists.newArrayList(
+ validRegistrationInfo(),
+ validRegistrationInfo(),
+ validRegistrationInfo(),
+ validRegistrationInfo()
+ ))
+ .build(),
+ OAuth2ParamsInfo.builder()
+ .domainInfos(Lists.newArrayList(
+ OAuth2DomainInfo.builder().name("second-domain").scheme(SchemeType.MIXED).build(),
+ OAuth2DomainInfo.builder().name("fourth-domain").scheme(SchemeType.MIXED).build()
+ ))
+ .mobileInfos(Collections.emptyList())
+ .clientRegistrations(Lists.newArrayList(
+ validRegistrationInfo(),
+ validRegistrationInfo()
+ ))
+ .build()
+ ));
+ }
+
+ private OAuth2RegistrationInfo validRegistrationInfo() {
+ return validRegistrationInfo(null, Collections.emptyList());
+ }
+
+ private OAuth2RegistrationInfo validRegistrationInfo(String label, List platforms) {
+ 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(platforms == null ? Collections.emptyList() : platforms)
.userInfoUri(UUID.randomUUID().toString())
.userNameAttributeName(UUID.randomUUID().toString())
.jwkSetUri(UUID.randomUUID().toString())
.clientAuthenticationMethod(UUID.randomUUID().toString())
- .loginButtonLabel(UUID.randomUUID().toString())
+ .loginButtonLabel(label != null ? label : UUID.randomUUID().toString())
.loginButtonIcon(UUID.randomUUID().toString())
.additionalInfo(mapper.createObjectNode().put(UUID.randomUUID().toString(), UUID.randomUUID().toString()))
.mapperConfig(
@@ -522,4 +651,10 @@ public class BaseOAuth2ServiceTest extends AbstractServiceTest {
)
.build();
}
+
+ private OAuth2MobileInfo validMobileInfo(String pkgName, String appSecret) {
+ return OAuth2MobileInfo.builder().pkgName(pkgName)
+ .appSecret(appSecret != null ? appSecret : RandomStringUtils.randomAlphanumeric(24))
+ .build();
+ }
}
diff --git a/dao/src/test/resources/sql/hsql/drop-all-tables.sql b/dao/src/test/resources/sql/hsql/drop-all-tables.sql
index 726b4ba412..f7b1b4118d 100644
--- a/dao/src/test/resources/sql/hsql/drop-all-tables.sql
+++ b/dao/src/test/resources/sql/hsql/drop-all-tables.sql
@@ -24,9 +24,13 @@ DROP TABLE IF EXISTS dashboard;
DROP TABLE IF EXISTS rule_node_state;
DROP TABLE IF EXISTS rule_node;
DROP TABLE IF EXISTS rule_chain;
+DROP TABLE IF EXISTS oauth2_mobile;
+DROP TABLE IF EXISTS oauth2_domain;
+DROP TABLE IF EXISTS oauth2_registration;
+DROP TABLE IF EXISTS oauth2_params;
+DROP TABLE IF EXISTS oauth2_client_registration_template;
DROP TABLE IF EXISTS oauth2_client_registration;
DROP TABLE IF EXISTS oauth2_client_registration_info;
-DROP TABLE IF EXISTS oauth2_client_registration_template;
DROP TABLE IF EXISTS api_usage_state;
DROP TABLE IF EXISTS resource;
DROP TABLE IF EXISTS ota_package;
diff --git a/dao/src/test/resources/sql/psql/drop-all-tables.sql b/dao/src/test/resources/sql/psql/drop-all-tables.sql
index 855a53df2d..a29dea43c2 100644
--- a/dao/src/test/resources/sql/psql/drop-all-tables.sql
+++ b/dao/src/test/resources/sql/psql/drop-all-tables.sql
@@ -25,9 +25,13 @@ DROP TABLE IF EXISTS rule_node_state;
DROP TABLE IF EXISTS rule_node;
DROP TABLE IF EXISTS rule_chain;
DROP TABLE IF EXISTS tb_schema_settings;
+DROP TABLE IF EXISTS oauth2_mobile;
+DROP TABLE IF EXISTS oauth2_domain;
+DROP TABLE IF EXISTS oauth2_registration;
+DROP TABLE IF EXISTS oauth2_params;
+DROP TABLE IF EXISTS oauth2_client_registration_template;
DROP TABLE IF EXISTS oauth2_client_registration;
DROP TABLE IF EXISTS oauth2_client_registration_info;
-DROP TABLE IF EXISTS oauth2_client_registration_template;
DROP TABLE IF EXISTS api_usage_state;
DROP TABLE IF EXISTS resource;
DROP TABLE IF EXISTS firmware;
diff --git a/netty-mqtt/src/main/java/org/thingsboard/mqtt/MqttChannelHandler.java b/netty-mqtt/src/main/java/org/thingsboard/mqtt/MqttChannelHandler.java
index 7ae7d5989d..534883f337 100644
--- a/netty-mqtt/src/main/java/org/thingsboard/mqtt/MqttChannelHandler.java
+++ b/netty-mqtt/src/main/java/org/thingsboard/mqtt/MqttChannelHandler.java
@@ -200,7 +200,6 @@ final class MqttChannelHandler extends SimpleChannelInboundHandler
MqttIncomingQos2Publish incomingQos2Publish = new MqttIncomingQos2Publish(message);
this.client.getQos2PendingIncomingPublishes().put(message.variableHeader().packetId(), incomingQos2Publish);
- message.payload().retain();
channel.writeAndFlush(pubrecMessage);
}
diff --git a/rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java b/rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java
index 8ad95805a5..b716935b2a 100644
--- a/rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java
+++ b/rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java
@@ -103,7 +103,7 @@ import org.thingsboard.server.common.data.kv.AttributeKvEntry;
import org.thingsboard.server.common.data.kv.TsKvEntry;
import org.thingsboard.server.common.data.oauth2.OAuth2ClientInfo;
import org.thingsboard.server.common.data.oauth2.OAuth2ClientRegistrationTemplate;
-import org.thingsboard.server.common.data.oauth2.OAuth2ClientsParams;
+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;
@@ -142,7 +142,6 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
-import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
@@ -1773,21 +1772,28 @@ public class RestClient implements ClientHttpRequestInterceptor, Closeable {
}).getBody();
}
- public List getOAuth2Clients() {
+ public List getOAuth2Clients(String pkgName) {
+ Map params = new HashMap<>();
+ StringBuilder urlBuilder = new StringBuilder(baseURL);
+ urlBuilder.append("/api/noauth/oauth2Clients");
+ if (pkgName != null) {
+ urlBuilder.append("?pkgName={pkgName}");
+ params.put("pkgName", pkgName);
+ }
return restTemplate.exchange(
- baseURL + "/api/noauth/oauth2Clients",
+ urlBuilder.toString(),
HttpMethod.POST,
HttpEntity.EMPTY,
new ParameterizedTypeReference>() {
- }).getBody();
+ }, params).getBody();
}
- public OAuth2ClientsParams getCurrentOAuth2Params() {
- return restTemplate.getForEntity(baseURL + "/api/oauth2/config", OAuth2ClientsParams.class).getBody();
+ public OAuth2Info getCurrentOAuth2Info() {
+ return restTemplate.getForEntity(baseURL + "/api/oauth2/config", OAuth2Info.class).getBody();
}
- public OAuth2ClientsParams saveOAuth2Params(OAuth2ClientsParams oauth2Params) {
- return restTemplate.postForEntity(baseURL + "/api/oauth2/config", oauth2Params, OAuth2ClientsParams.class).getBody();
+ public OAuth2Info saveOAuth2Info(OAuth2Info oauth2Info) {
+ return restTemplate.postForEntity(baseURL + "/api/oauth2/config", oauth2Info, OAuth2Info.class).getBody();
}
public String getLoginProcessingUrl() {
@@ -2965,7 +2971,7 @@ public class RestClient implements ClientHttpRequestInterceptor, Closeable {
return restTemplate.postForEntity(baseURL + "/api/otaPackage", otaPackageInfo, OtaPackageInfo.class).getBody();
}
- public OtaPackage saveOtaPackageData(OtaPackageId otaPackageId, String checkSum, ChecksumAlgorithm checksumAlgorithm, MultipartFile file) throws Exception {
+ public OtaPackageInfo saveOtaPackageData(OtaPackageId otaPackageId, String checkSum, ChecksumAlgorithm checksumAlgorithm, MultipartFile file) throws Exception {
HttpHeaders header = new HttpHeaders();
header.setContentType(MediaType.MULTIPART_FORM_DATA);
@@ -2987,7 +2993,7 @@ public class RestClient implements ClientHttpRequestInterceptor, Closeable {
}
return restTemplate.postForEntity(
- baseURL + url, requestEntity, OtaPackage.class, params
+ baseURL + url, requestEntity, OtaPackageInfo.class, params
).getBody();
}
diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/AlarmState.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/AlarmState.java
index 445b9653a2..614cfd4b9c 100644
--- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/AlarmState.java
+++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/AlarmState.java
@@ -34,6 +34,7 @@ import org.thingsboard.server.common.data.alarm.AlarmStatus;
import org.thingsboard.server.common.data.device.profile.AlarmConditionKeyType;
import org.thingsboard.server.common.data.device.profile.AlarmConditionSpecType;
import org.thingsboard.server.common.data.device.profile.DeviceProfileAlarm;
+import org.thingsboard.server.common.data.id.DashboardId;
import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.msg.TbMsg;
import org.thingsboard.server.common.msg.TbMsgMetaData;
@@ -269,16 +270,22 @@ class AlarmState {
private JsonNode createDetails(AlarmRuleState ruleState) {
JsonNode alarmDetails;
String alarmDetailsStr = ruleState.getAlarmRule().getAlarmDetails();
+ DashboardId dashboardId = ruleState.getAlarmRule().getDashboardId();
- if (StringUtils.isNotEmpty(alarmDetailsStr)) {
- for (var keyFilter : ruleState.getAlarmRule().getCondition().getCondition()) {
- EntityKeyValue entityKeyValue = dataSnapshot.getValue(keyFilter.getKey());
- if (entityKeyValue != null) {
- alarmDetailsStr = alarmDetailsStr.replaceAll(String.format("\\$\\{%s}", keyFilter.getKey().getKey()), getValueAsString(entityKeyValue));
+ if (StringUtils.isNotEmpty(alarmDetailsStr) || dashboardId != null) {
+ ObjectNode newDetails = JacksonUtil.newObjectNode();
+ if (StringUtils.isNotEmpty(alarmDetailsStr)) {
+ for (var keyFilter : ruleState.getAlarmRule().getCondition().getCondition()) {
+ EntityKeyValue entityKeyValue = dataSnapshot.getValue(keyFilter.getKey());
+ if (entityKeyValue != null) {
+ alarmDetailsStr = alarmDetailsStr.replaceAll(String.format("\\$\\{%s}", keyFilter.getKey().getKey()), getValueAsString(entityKeyValue));
+ }
}
+ newDetails.put("data", alarmDetailsStr);
+ }
+ if (dashboardId != null) {
+ newDetails.put("dashboardId", dashboardId.getId().toString());
}
- ObjectNode newDetails = JacksonUtil.newObjectNode();
- newDetails.put("data", alarmDetailsStr);
alarmDetails = newDetails;
} else if (currentAlarm != null) {
alarmDetails = currentAlarm.getDetails();
diff --git a/transport/lwm2m/src/main/resources/tb-lwm2m-transport.yml b/transport/lwm2m/src/main/resources/tb-lwm2m-transport.yml
index 39acda4590..d81b28a5ff 100644
--- a/transport/lwm2m/src/main/resources/tb-lwm2m-transport.yml
+++ b/transport/lwm2m/src/main/resources/tb-lwm2m-transport.yml
@@ -114,13 +114,14 @@ transport:
private_encoded: "${LWM2M_SERVER_PRIVATE_ENCODED:308193020100301306072a8648ce3d020106082a8648ce3d030107047930770201010420dc774b309e547ceb48fee547e104ce201a9c48c449dc5414cd04e7f5cf05f67ba00a06082a8648ce3d030107a1440342000405064b9e6762dd8d8b8a52355d7b4d8b9a3d64e6d2ee277d76c248861353f3585eeb1838e4f9e37b31fa347aef5ce3431eb54e0a2506910c5e0298817445721b}"
# Only Certificate_x509:
alias: "${LWM2M_KEYSTORE_ALIAS_SERVER:server}"
+ skip_validity_check_for_client_cert: "${TB_LWM2M_SERVER_SECURITY_SKIP_VALIDITY_CHECK_FOR_CLIENT_CERT:false}"
bootstrap:
enable: "${LWM2M_ENABLED_BS:true}"
id: "${LWM2M_SERVER_ID_BS:111}"
bind_address: "${LWM2M_BIND_ADDRESS_BS:0.0.0.0}"
bind_port: "${LWM2M_BIND_PORT_BS:5687}"
security:
- bind_address: "${LWM2M_BIND_ADDRESS_BS:0.0.0.0}"
+ bind_address: "${LWM2M_BIND_ADDRESS_SECURITY_BS:0.0.0.0}"
bind_port: "${LWM2M_BIND_PORT_SECURITY_BS:5688}"
# Only for RPK: Public & Private Key. If the keystore file is missing or not working
public_x: "${LWM2M_SERVER_PUBLIC_X_BS:5017c87a1c1768264656b3b355434b0def6edb8b9bf166a4762d9930cd730f91}"
diff --git a/ui-ngx/src/app/app.component.ts b/ui-ngx/src/app/app.component.ts
index 3ad4038066..39d51ced92 100644
--- a/ui-ngx/src/app/app.component.ts
+++ b/ui-ngx/src/app/app.component.ts
@@ -89,6 +89,13 @@ export class AppComponent implements OnInit {
)
);
+ this.matIconRegistry.addSvgIconLiteral(
+ 'apple-logo',
+ this.domSanitizer.bypassSecurityTrustHtml(
+ ''
+ )
+ );
+
this.storageService.testLocalStorage();
this.setupTranslate();
diff --git a/ui-ngx/src/app/core/api/data-aggregator.ts b/ui-ngx/src/app/core/api/data-aggregator.ts
index 02c1c8649a..971f037282 100644
--- a/ui-ngx/src/app/core/api/data-aggregator.ts
+++ b/ui-ngx/src/app/core/api/data-aggregator.ts
@@ -16,16 +16,17 @@
import { SubscriptionData, SubscriptionDataHolder } from '@app/shared/models/telemetry/telemetry.models';
import {
- AggregationType, calculateIntervalComparisonEndTime,
- calculateIntervalEndTime, calculateIntervalStartEndTime,
+ AggregationType,
+ calculateIntervalComparisonEndTime,
+ calculateIntervalEndTime,
+ calculateIntervalStartEndTime,
getCurrentTime,
- getCurrentTimeForComparison, getTime,
+ getTime,
SubscriptionTimewindow
} from '@shared/models/time/time.models';
import { UtilsService } from '@core/services/utils.service';
-import { deepClone } from '@core/utils';
+import { deepClone, isNumeric } from '@core/utils';
import Timeout = NodeJS.Timeout;
-import * as moment_ from 'moment';
export declare type onAggregatedData = (data: SubscriptionData, detectChanges: boolean) => void;
@@ -407,24 +408,11 @@ export class DataAggregator {
}
}
- private isNumeric(val: any): boolean {
- return (val - parseFloat( val ) + 1) >= 0;
- }
-
private convertValue(val: string): any {
- if (!this.noAggregation || val && this.isNumeric(val)) {
+ if (!this.noAggregation || val && isNumeric(val) && Number(val).toString() === val) {
return Number(val);
- } else {
- return val;
- }
- }
-
- private getCurrentTime() {
- if (this.subsTw.timeForComparison) {
- return getCurrentTimeForComparison(this.subsTw.timeForComparison as moment_.unitOfTime.DurationConstructor, this.subsTw.timezone);
- } else {
- return getCurrentTime(this.subsTw.timezone);
}
+ return val;
}
}
diff --git a/ui-ngx/src/app/core/api/entity-data-subscription.ts b/ui-ngx/src/app/core/api/entity-data-subscription.ts
index 9c769f3777..ff828cc2ac 100644
--- a/ui-ngx/src/app/core/api/entity-data-subscription.ts
+++ b/ui-ngx/src/app/core/api/entity-data-subscription.ts
@@ -38,7 +38,7 @@ import {
} from '@shared/models/telemetry/telemetry.models';
import { UtilsService } from '@core/services/utils.service';
import { EntityDataListener, EntityDataLoadResult } from '@core/api/entity-data.service';
-import { deepClone, isDefined, isDefinedAndNotNull, isObject, objectHashCode } from '@core/utils';
+import { deepClone, isDefined, isDefinedAndNotNull, isNumeric, isObject, objectHashCode } from '@core/utils';
import { PageData } from '@shared/models/page/page-data';
import { DataAggregator } from '@core/api/data-aggregator';
import { NULL_UUID } from '@shared/models/id/has-uuid';
@@ -667,8 +667,7 @@ export class EntityDataSubscription {
if (prevDataCb) {
dataAggregator.updateOnDataCb(prevDataCb);
}
- }
- if (!this.history && !isUpdate) {
+ } else if (!this.history && !isUpdate) {
this.onData(subscriptionData, DataKeyType.timeseries, dataIndex, true, dataUpdatedCb);
}
}
@@ -743,16 +742,11 @@ export class EntityDataSubscription {
}
}
- private isNumeric(val: any): boolean {
- return (val - parseFloat( val ) + 1) >= 0;
- }
-
private convertValue(val: string): any {
- if (val && this.isNumeric(val) && Number(val).toString() === val) {
+ if (val && isNumeric(val) && Number(val).toString() === val) {
return Number(val);
- } else {
- return val;
}
+ return val;
}
private toSubscriptionData(sourceData: {[key: string]: TsValue | TsValue[]}, isTs: boolean): SubscriptionData {
diff --git a/ui-ngx/src/app/core/auth/auth.service.ts b/ui-ngx/src/app/core/auth/auth.service.ts
index c17d993bf7..42b213f558 100644
--- a/ui-ngx/src/app/core/auth/auth.service.ts
+++ b/ui-ngx/src/app/core/auth/auth.service.ts
@@ -44,8 +44,8 @@ import { AdminService } from '@core/http/admin.service';
import { ActionNotificationShow } from '@core/notification/notification.actions';
import { MatDialog, MatDialogConfig } from '@angular/material/dialog';
import { AlertDialogComponent } from '@shared/components/dialog/alert-dialog.component';
-import { OAuth2ClientInfo } from '@shared/models/oauth2.models';
-import { isMobileApp } from '@core/utils';
+import { OAuth2ClientInfo, PlatformType } from '@shared/models/oauth2.models';
+import { isDefinedAndNotNull, isMobileApp } from '@core/utils';
@Injectable({
providedIn: 'root'
@@ -205,7 +205,8 @@ export class AuthService {
}
public loadOAuth2Clients(): Observable> {
- return this.http.post>(`/api/noauth/oauth2Clients`,
+ const url = '/api/noauth/oauth2Clients?platform=' + PlatformType.WEB;
+ return this.http.post>(url,
null, defaultHttpOptions()).pipe(
catchError(err => of([])),
tap((OAuth2Clients) => {
diff --git a/ui-ngx/src/app/core/http/device-profile.service.ts b/ui-ngx/src/app/core/http/device-profile.service.ts
index 7e3183255a..6107a0853e 100644
--- a/ui-ngx/src/app/core/http/device-profile.service.ts
+++ b/ui-ngx/src/app/core/http/device-profile.service.ts
@@ -14,24 +14,29 @@
/// limitations under the License.
///
-import {Injectable} from '@angular/core';
-import {HttpClient} from '@angular/common/http';
-import {PageLink} from '@shared/models/page/page-link';
-import {defaultHttpOptionsFromConfig, RequestConfig} from './http-utils';
-import {Observable} from 'rxjs';
-import {PageData} from '@shared/models/page/page-data';
-import {DeviceProfile, DeviceProfileInfo, DeviceTransportType} from '@shared/models/device.models';
-import {isDefinedAndNotNull, isEmptyStr} from '@core/utils';
-import {ObjectLwM2M, ServerSecurityConfig} from '@home/components/profile/device/lwm2m/lwm2m-profile-config.models';
-import {SortOrder} from '@shared/models/page/sort-order';
+import { Injectable } from '@angular/core';
+import { HttpClient } from '@angular/common/http';
+import { PageLink } from '@shared/models/page/page-link';
+import { defaultHttpOptionsFromConfig, RequestConfig } from './http-utils';
+import { Observable, of, throwError } from 'rxjs';
+import { PageData } from '@shared/models/page/page-data';
+import { DeviceProfile, DeviceProfileInfo, DeviceTransportType } from '@shared/models/device.models';
+import { isDefinedAndNotNull, isEmptyStr } from '@core/utils';
+import { ObjectLwM2M, ServerSecurityConfig } from '@home/components/profile/device/lwm2m/lwm2m-profile-config.models';
+import { SortOrder } from '@shared/models/page/sort-order';
+import { OtaPackageService } from '@core/http/ota-package.service';
+import { mergeMap, tap } from 'rxjs/operators';
@Injectable({
providedIn: 'root'
})
export class DeviceProfileService {
+ private lwm2mBootstrapSecurityInfoInMemoryCache = new Map();
+
constructor(
- private http: HttpClient
+ private http: HttpClient,
+ private otaPackageService: OtaPackageService
) {
}
@@ -55,12 +60,18 @@ export class DeviceProfileService {
return this.http.get>(url, defaultHttpOptionsFromConfig(config));
}
- public getLwm2mBootstrapSecurityInfo(securityMode: string, bootstrapServerIs: boolean,
- config?: RequestConfig): Observable {
- return this.http.get(
- `/api/lwm2m/deviceProfile/bootstrap/${securityMode}/${bootstrapServerIs}`,
- defaultHttpOptionsFromConfig(config)
- );
+ public getLwm2mBootstrapSecurityInfo(isBootstrapServer: boolean, config?: RequestConfig): Observable {
+ const securityConfig = this.lwm2mBootstrapSecurityInfoInMemoryCache.get(isBootstrapServer);
+ if (securityConfig) {
+ return of(securityConfig);
+ } else {
+ return this.http.get(
+ `/api/lwm2m/deviceProfile/bootstrap/${isBootstrapServer}`,
+ defaultHttpOptionsFromConfig(config)
+ ).pipe(
+ tap(serverConfig => this.lwm2mBootstrapSecurityInfoInMemoryCache.set(isBootstrapServer, serverConfig))
+ );
+ }
}
public getLwm2mObjectsPage(pageLink: PageLink, config?: RequestConfig): Observable> {
@@ -70,6 +81,13 @@ export class DeviceProfileService {
);
}
+ public saveDeviceProfileAndConfirmOtaChange(originDeviceProfile: DeviceProfile, deviceProfile: DeviceProfile,
+ config?: RequestConfig): Observable {
+ return this.otaPackageService.confirmDialogUpdatePackage(deviceProfile, originDeviceProfile).pipe(
+ mergeMap((update) => update ? this.saveDeviceProfile(deviceProfile, config) : throwError('Canceled saving device profiles'))
+ );
+ }
+
public saveDeviceProfile(deviceProfile: DeviceProfile, config?: RequestConfig): Observable {
return this.http.post('/api/deviceProfile', deviceProfile, defaultHttpOptionsFromConfig(config));
}
diff --git a/ui-ngx/src/app/core/http/oauth2.service.ts b/ui-ngx/src/app/core/http/oauth2.service.ts
index e81d472130..72a6bc77af 100644
--- a/ui-ngx/src/app/core/http/oauth2.service.ts
+++ b/ui-ngx/src/app/core/http/oauth2.service.ts
@@ -18,7 +18,7 @@ import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { defaultHttpOptionsFromConfig, RequestConfig } from '@core/http/http-utils';
import { Observable } from 'rxjs';
-import { OAuth2ClientRegistrationTemplate, OAuth2ClientsParams } from '@shared/models/oauth2.models';
+import { OAuth2ClientRegistrationTemplate, OAuth2Info } from '@shared/models/oauth2.models';
@Injectable({
providedIn: 'root'
@@ -29,16 +29,16 @@ export class OAuth2Service {
private http: HttpClient
) { }
- public getOAuth2Settings(config?: RequestConfig): Observable {
- return this.http.get(`/api/oauth2/config`, defaultHttpOptionsFromConfig(config));
+ public getOAuth2Settings(config?: RequestConfig): Observable {
+ return this.http.get(`/api/oauth2/config`, defaultHttpOptionsFromConfig(config));
}
public getOAuth2Template(config?: RequestConfig): Observable> {
return this.http.get>(`/api/oauth2/config/template`, defaultHttpOptionsFromConfig(config));
}
- public saveOAuth2Settings(OAuth2Setting: OAuth2ClientsParams, config?: RequestConfig): Observable {
- return this.http.post('/api/oauth2/config', OAuth2Setting,
+ public saveOAuth2Settings(OAuth2Setting: OAuth2Info, config?: RequestConfig): Observable {
+ return this.http.post('/api/oauth2/config', OAuth2Setting,
defaultHttpOptionsFromConfig(config));
}
diff --git a/ui-ngx/src/app/core/http/ota-package.service.ts b/ui-ngx/src/app/core/http/ota-package.service.ts
index 6afeb6e78d..1f9a36882a 100644
--- a/ui-ngx/src/app/core/http/ota-package.service.ts
+++ b/ui-ngx/src/app/core/http/ota-package.service.ts
@@ -18,18 +18,30 @@ import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { PageLink } from '@shared/models/page/page-link';
import { defaultHttpOptionsFromConfig, defaultHttpUploadOptions, RequestConfig } from '@core/http/http-utils';
-import { Observable } from 'rxjs';
+import { forkJoin, Observable, of } from 'rxjs';
import { PageData } from '@shared/models/page/page-data';
-import { ChecksumAlgorithm, OtaPackage, OtaPackageInfo, OtaUpdateType } from '@shared/models/ota-package.models';
+import {
+ ChecksumAlgorithm,
+ OtaPackage,
+ OtaPackageInfo,
+ OtaPagesIds,
+ OtaUpdateType
+} from '@shared/models/ota-package.models';
import { catchError, map, mergeMap } from 'rxjs/operators';
import { deepClone } from '@core/utils';
+import { BaseData } from '@shared/models/base-data';
+import { EntityId } from '@shared/models/id/entity-id';
+import { TranslateService } from '@ngx-translate/core';
+import { DialogService } from '@core/services/dialog.service';
@Injectable({
providedIn: 'root'
})
export class OtaPackageService {
constructor(
- private http: HttpClient
+ private http: HttpClient,
+ private translate: TranslateService,
+ private dialogService: DialogService
) {
}
@@ -39,7 +51,7 @@ export class OtaPackageService {
}
public getOtaPackagesInfoByDeviceProfileId(pageLink: PageLink, deviceProfileId: string, type: OtaUpdateType,
- hasData = true, config?: RequestConfig): Observable> {
+ config?: RequestConfig): Observable> {
const url = `/api/otaPackages/${deviceProfileId}/${type}${pageLink.toQuery()}`;
return this.http.get>(url, defaultHttpOptionsFromConfig(config));
}
@@ -120,4 +132,36 @@ export class OtaPackageService {
return this.http.delete(`/api/otaPackage/${otaPackageId}`, defaultHttpOptionsFromConfig(config));
}
+ public countUpdateDeviceAfterChangePackage(type: OtaUpdateType, entityId: EntityId, config?: RequestConfig): Observable {
+ return this.http.get(`/api/devices/count/${type}?deviceProfileId=${entityId.id}`, defaultHttpOptionsFromConfig(config));
+ }
+
+ public confirmDialogUpdatePackage(entity: BaseData&OtaPagesIds,
+ originEntity: BaseData&OtaPagesIds): Observable {
+ const tasks: Observable[] = [];
+ if (originEntity?.id?.id && originEntity.firmwareId?.id !== entity.firmwareId?.id) {
+ tasks.push(this.countUpdateDeviceAfterChangePackage(OtaUpdateType.FIRMWARE, entity.id));
+ } else {
+ tasks.push(of(0));
+ }
+ if (originEntity?.id?.id && originEntity.softwareId?.id !== entity.softwareId?.id) {
+ tasks.push(this.countUpdateDeviceAfterChangePackage(OtaUpdateType.SOFTWARE, entity.id));
+ } else {
+ tasks.push(of(0));
+ }
+ return forkJoin(tasks).pipe(
+ mergeMap(([deviceFirmwareUpdate, deviceSoftwareUpdate]) => {
+ let text = '';
+ if (deviceFirmwareUpdate > 0) {
+ text += this.translate.instant('ota-update.change-firmware', {count: deviceFirmwareUpdate});
+ }
+ if (deviceSoftwareUpdate > 0) {
+ text += text.length ? ' ' : '';
+ text += this.translate.instant('ota-update.change-software', {count: deviceSoftwareUpdate});
+ }
+ return text !== '' ? this.dialogService.confirm('', text, null, this.translate.instant('common.proceed')) : of(true);
+ })
+ );
+ }
+
}
diff --git a/ui-ngx/src/app/core/services/dashboard-utils.service.ts b/ui-ngx/src/app/core/services/dashboard-utils.service.ts
index f667fb5788..0dc143e6cb 100644
--- a/ui-ngx/src/app/core/services/dashboard-utils.service.ts
+++ b/ui-ngx/src/app/core/services/dashboard-utils.service.ts
@@ -231,7 +231,6 @@ export class DashboardUtilsService {
private createDefaultGridSettings(): GridSettings {
return {
backgroundColor: '#eeeeee',
- color: 'rgba(0,0,0,0.870588)',
columns: 24,
margin: 10,
backgroundSizeMode: '100%'
diff --git a/ui-ngx/src/app/core/services/mobile.service.ts b/ui-ngx/src/app/core/services/mobile.service.ts
index 800651356a..cc940d6f85 100644
--- a/ui-ngx/src/app/core/services/mobile.service.ts
+++ b/ui-ngx/src/app/core/services/mobile.service.ts
@@ -27,6 +27,7 @@ import { AuthService } from '@core/auth/auth.service';
const dashboardStateNameHandler = 'tbMobileDashboardStateNameHandler';
const dashboardLoadedHandler = 'tbMobileDashboardLoadedHandler';
+const dashboardLayoutHandler = 'tbMobileDashboardLayoutHandler';
const navigationHandler = 'tbMobileNavigationHandler';
const mobileHandler = 'tbMobileHandler';
@@ -43,6 +44,7 @@ export class MobileService {
private reloadUserObservable: Observable;
private lastDashboardId: string;
+ private toggleLayoutFunction: () => void;
constructor(@Inject(WINDOW) private window: Window,
private router: Router,
@@ -65,12 +67,26 @@ export class MobileService {
}
}
- public onDashboardLoaded() {
+ public onDashboardLoaded(hasRightLayout: boolean, rightLayoutOpened: boolean) {
if (this.mobileApp) {
- this.mobileChannel.callHandler(dashboardLoadedHandler);
+ this.mobileChannel.callHandler(dashboardLoadedHandler, hasRightLayout, rightLayoutOpened);
}
}
+ public onDashboardRightLayoutChanged(opened: boolean) {
+ if (this.mobileApp) {
+ this.mobileChannel.callHandler(dashboardLayoutHandler, opened);
+ }
+ }
+
+ public registerToggleLayoutFunction(toggleLayoutFunction: () => void) {
+ this.toggleLayoutFunction = toggleLayoutFunction;
+ }
+
+ public unregisterToggleLayoutFunction() {
+ this.toggleLayoutFunction = null;
+ }
+
public handleWidgetMobileAction(type: WidgetMobileActionType, ...args: any[]):
Observable> {
if (this.mobileApp) {
@@ -110,6 +126,11 @@ export class MobileService {
const reloadUserMessage: ReloadUserMessage = message.data;
this.reloadUser(reloadUserMessage);
break;
+ case 'toggleDashboardLayout':
+ if (this.toggleLayoutFunction) {
+ this.toggleLayoutFunction();
+ }
+ break;
}
}
}
diff --git a/ui-ngx/src/app/core/utils.ts b/ui-ngx/src/app/core/utils.ts
index a287802ec2..aa52c55cbe 100644
--- a/ui-ngx/src/app/core/utils.ts
+++ b/ui-ngx/src/app/core/utils.ts
@@ -445,3 +445,14 @@ export function validateEntityId(entityId: EntityId | null): boolean {
export function isMobileApp(): boolean {
return isDefined((window as any).flutter_inappwebview);
}
+
+const alphanumericCharacters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
+const alphanumericCharactersLength = alphanumericCharacters.length;
+
+export function randomAlphanumeric(length: number): string {
+ let result = '';
+ for ( let i = 0; i < length; i++ ) {
+ result += alphanumericCharacters.charAt(Math.floor(Math.random() * alphanumericCharactersLength));
+ }
+ return result;
+}
diff --git a/ui-ngx/src/app/modules/home/components/alias/entity-aliases-dialog.component.ts b/ui-ngx/src/app/modules/home/components/alias/entity-aliases-dialog.component.ts
index 08119e6ce8..aeb0f9c286 100644
--- a/ui-ngx/src/app/modules/home/components/alias/entity-aliases-dialog.component.ts
+++ b/ui-ngx/src/app/modules/home/components/alias/entity-aliases-dialog.component.ts
@@ -98,24 +98,17 @@ export class EntityAliasesDialogComponent extends DialogComponent {
if (widget.type === widgetType.rpc) {
if (widget.config.targetDeviceAliasIds && widget.config.targetDeviceAliasIds.length > 0) {
- const targetDeviceAliasId = widget.config.targetDeviceAliasIds[0];
- widgetsTitleList = this.aliasToWidgetsMap[targetDeviceAliasId];
- if (!widgetsTitleList) {
- widgetsTitleList = [];
- this.aliasToWidgetsMap[targetDeviceAliasId] = widgetsTitleList;
- }
- widgetsTitleList.push(widget.config.title);
+ this.addWidgetTitleToWidgetsMap(widget.config.targetDeviceAliasIds[0], widget.config.title);
+ }
+ } else if (widget.type === widgetType.alarm) {
+ if (widget.config.alarmSource) {
+ this.addWidgetTitleToWidgetsMap(widget.config.alarmSource.entityAliasId, widget.config.title);
}
} else {
const datasources = this.utils.validateDatasources(widget.config.datasources);
datasources.forEach((datasource) => {
if (datasource.type === DatasourceType.entity && datasource.entityAliasId) {
- widgetsTitleList = this.aliasToWidgetsMap[datasource.entityAliasId];
- if (!widgetsTitleList) {
- widgetsTitleList = [];
- this.aliasToWidgetsMap[datasource.entityAliasId] = widgetsTitleList;
- }
- widgetsTitleList.push(widget.config.title);
+ this.addWidgetTitleToWidgetsMap(datasource.entityAliasId, widget.config.title);
}
});
}
@@ -141,6 +134,15 @@ export class EntityAliasesDialogComponent extends DialogComponent = this.aliasToWidgetsMap[aliasId];
+ if (!widgetsTitleList) {
+ widgetsTitleList = [];
+ this.aliasToWidgetsMap[aliasId] = widgetsTitleList;
+ }
+ widgetsTitleList.push(widgetTitle);
+ }
+
private createEntityAliasFormControl(aliasId: string, entityAlias: EntityAlias): AbstractControl {
const aliasFormControl = this.fb.group({
id: [aliasId],
diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.ts b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.ts
index 89629bfe49..cc19e98a99 100644
--- a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.ts
+++ b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.ts
@@ -149,8 +149,16 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC
@Input()
currentState: string;
+ private hideToolbarValue = false;
+
@Input()
- hideToolbar: boolean;
+ set hideToolbar(hideToolbar: boolean) {
+ this.hideToolbarValue = hideToolbar;
+ }
+
+ get hideToolbar(): boolean {
+ return (this.hideToolbarValue || this.hideToolbarSetting()) && !this.isEdit;
+ }
@Input()
syncStateWithQueryParam = true;
@@ -269,6 +277,7 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC
return !this.widgetEditMode && !this.hideToolbar &&
(this.toolbarAlwaysOpen() || this.isToolbarOpened || this.isEdit || this.showRightLayoutSwitch());
}
+
set toolbarOpened(toolbarOpened: boolean) {
}
@@ -329,7 +338,7 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC
this.dashboardCtx.aliasController.updateAliases();
setTimeout(() => {
this.mobileService.handleDashboardStateName(this.dashboardCtx.stateController.getCurrentStateName());
- this.mobileService.onDashboardLoaded();
+ this.mobileService.onDashboardLoaded(this.layouts.right.show, this.isRightLayoutOpened);
});
}
}
@@ -340,6 +349,14 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC
this.isMobile = !state.matches;
}
));
+ if (this.isMobileApp) {
+ this.mobileService.registerToggleLayoutFunction(() => {
+ setTimeout(() => {
+ this.toggleLayouts();
+ this.cd.detectChanges();
+ });
+ });
+ }
}
private init(data: any) {
@@ -430,6 +447,9 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC
}
ngOnDestroy(): void {
+ if (this.isMobileApp) {
+ this.mobileService.unregisterToggleLayoutFunction();
+ }
this.rxSubscriptions.forEach((subscription) => {
subscription.unsubscribe();
});
@@ -469,6 +489,15 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC
}
}
+ private hideToolbarSetting(): boolean {
+ if (this.dashboard.configuration.settings &&
+ isDefined(this.dashboard.configuration.settings.hideToolbar)) {
+ return this.dashboard.configuration.settings.hideToolbar;
+ } else {
+ return false;
+ }
+ }
+
public displayTitle(): boolean {
if (this.dashboard.configuration.settings &&
isDefined(this.dashboard.configuration.settings.showTitle)) {
@@ -546,15 +575,17 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC
}
public showRightLayoutSwitch(): boolean {
- return this.isMobile && this.layouts.right.show;
+ return this.isMobile && !this.isMobileApp && this.layouts.right.show;
}
public toggleLayouts() {
this.isRightLayoutOpened = !this.isRightLayoutOpened;
+ this.mobileService.onDashboardRightLayoutChanged(this.isRightLayoutOpened);
}
public openRightLayout() {
this.isRightLayoutOpened = true;
+ this.mobileService.onDashboardRightLayoutChanged(this.isRightLayoutOpened);
}
public mainLayoutWidth(): string {
@@ -782,7 +813,7 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC
this.updateLayouts(layoutsData);
}
setTimeout(() => {
- this.mobileService.onDashboardLoaded();
+ this.mobileService.onDashboardLoaded(this.layouts.right.show, this.isRightLayoutOpened);
});
}
diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-settings-dialog.component.html b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-settings-dialog.component.html
index f84405faed..14c2df301b 100644
--- a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-settings-dialog.component.html
+++ b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-settings-dialog.component.html
@@ -15,7 +15,7 @@
limitations under the License.
-->
-