Skip to content

Commit 8cd0760

Browse files
committed
Plugin update subscription filter issues fixed
1 parent d61ca68 commit 8cd0760

File tree

12 files changed

+96
-64
lines changed

12 files changed

+96
-64
lines changed

devicehive-auth/src/main/resources/messages.properties

+1
Original file line numberDiff line numberDiff line change
@@ -136,4 +136,5 @@ EMPTY_TOKEN=Token is empty
136136
PLUGIN_NOT_FOUND=Plugin is not found
137137
PLUGIN_NOT_ACTIVE=Plugin is not active
138138
PLUGIN_ALREADY_EXISTS=Plugin with name %s already exists
139+
ACTIVE_PLUGIN_UPDATED=Plugin's subscription filter can't be updated if plugin is ACTIVE
139140
NO_ACCESS_TO_PLUGIN=No access to plugin

devicehive-backend/src/main/resources/messages.properties

+1
Original file line numberDiff line numberDiff line change
@@ -130,4 +130,5 @@ EMPTY_TOKEN=Token is empty
130130
PLUGIN_NOT_FOUND=Plugin is not found
131131
PLUGIN_NOT_ACTIVE=Plugin is not active
132132
PLUGIN_ALREADY_EXISTS=Plugin with name %s already exists
133+
ACTIVE_PLUGIN_UPDATED=Plugin's subscription filter can't be updated if plugin is ACTIVE
133134
NO_ACCESS_TO_PLUGIN=No access to plugin

devicehive-common/src/main/java/com/devicehive/configuration/Messages.java

+1
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ public class Messages {
138138
public static final String PLUGIN_NOT_FOUND = BidBundle.get("PLUGIN_NOT_FOUND");
139139
public static final String PLUGIN_NOT_ACTIVE = BidBundle.get("PLUGIN_NOT_ACTIVE");
140140
public static final String PLUGIN_ALREADY_EXISTS = BidBundle.get("PLUGIN_ALREADY_EXISTS");
141+
public static final String ACTIVE_PLUGIN_UPDATED = BidBundle.get("ACTIVE_PLUGIN_UPDATED");
141142
public static final String NO_ACCESS_TO_PLUGIN = BidBundle.get("NO_ACCESS_TO_PLUGIN");
142143

143144
/**

devicehive-common/src/main/java/com/devicehive/model/enums/PluginStatus.java

+4
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,8 @@ public int getValue() {
3939
public static PluginStatus getValueForIndex(int index){
4040
return values()[index];
4141
}
42+
43+
public static PluginStatus fromString(final String s) {
44+
return PluginStatus.valueOf(s.toUpperCase());
45+
}
4246
}

devicehive-frontend/src/main/resources/messages.properties

+1
Original file line numberDiff line numberDiff line change
@@ -136,4 +136,5 @@ EMPTY_TOKEN=Token is empty
136136
PLUGIN_NOT_FOUND=Plugin is not found
137137
PLUGIN_NOT_ACTIVE=Plugin is not active
138138
PLUGIN_ALREADY_EXISTS=Plugin with name %s already exists
139+
ACTIVE_PLUGIN_UPDATED=Plugin's subscription filter can't be updated if plugin is ACTIVE
139140
NO_ACCESS_TO_PLUGIN=No access to plugin

devicehive-plugin/src/main/java/com/devicehive/model/FilterEntity.java

+23-6
Original file line numberDiff line numberDiff line change
@@ -38,20 +38,37 @@ public class FilterEntity {
3838

3939
private boolean returnNotifications;
4040

41+
public FilterEntity(String deviceId, String networkIds, String deviceTypeIds, String names, boolean returnCommands,
42+
boolean returnUpdatedCommands, boolean returnNotifications) {
43+
this.deviceId = deviceId;
44+
this.networkIds = networkIds;
45+
this.deviceTypeIds = deviceTypeIds;
46+
this.names = names;
47+
this.returnCommands = returnCommands;
48+
this.returnUpdatedCommands = returnUpdatedCommands;
49+
this.returnNotifications = returnNotifications;
50+
}
51+
4152
public FilterEntity(String filterString) {
4253
String[] filters = filterString.split("/");
4354

4455
String typesString = filters[0];
45-
if (typesString.equals(COMMAND)) {
56+
if (typesString.equals(ANY)) {
4657
returnCommands = true;
47-
} else if (typesString.equals(COMMAND_UPDATE)) {
4858
returnUpdatedCommands = true;
49-
} else if (typesString.equals(NOTIFICATION)) {
5059
returnNotifications = true;
5160
} else {
52-
returnCommands = true;
53-
returnUpdatedCommands = true;
54-
returnNotifications = true;
61+
if (typesString.contains(COMMAND)) {
62+
returnCommands = true;
63+
}
64+
65+
if (typesString.contains(COMMAND_UPDATE)) {
66+
returnUpdatedCommands = true;
67+
}
68+
69+
if (typesString.contains(NOTIFICATION)) {
70+
returnNotifications = true;
71+
}
5572
}
5673

5774
networkIds = filters[1];

devicehive-plugin/src/main/java/com/devicehive/model/query/PluginReqisterQuery.java

+33-22
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,16 @@
2020
* #L%
2121
*/
2222

23+
import com.devicehive.model.FilterEntity;
2324
import com.devicehive.model.rpc.PluginSubscribeRequest;
2425
import com.devicehive.service.FilterService;
2526
import io.swagger.annotations.ApiParam;
2627

2728
import javax.ws.rs.QueryParam;
2829

30+
import java.util.Optional;
31+
import java.util.StringJoiner;
32+
2933
import static com.devicehive.configuration.Constants.*;
3034

3135

@@ -128,47 +132,54 @@ public PluginSubscribeRequest toRequest(FilterService filterService) {
128132
// Filter format <notification/command/command_update>/<networkIDs>/<deviceTypeIDs>/<deviceID>/<eventNames>
129133
// TODO - change to embedded entity for better code readability
130134
public String constructFilterString() {
131-
StringBuilder sb = new StringBuilder();
132-
if (returnCommands && returnUpdatedCommands && returnNotifications) {
133-
sb.append(ANY);
134-
} else if (returnCommands) {
135-
sb.append(COMMAND);
136-
} else if (returnUpdatedCommands) {
137-
sb.append(COMMAND_UPDATE);
135+
StringJoiner sj = new StringJoiner("/");
136+
returnCommands = Optional.ofNullable(returnCommands).orElse(false);
137+
returnUpdatedCommands = Optional.ofNullable(returnUpdatedCommands).orElse(false);
138+
returnNotifications = Optional.ofNullable(returnNotifications).orElse(false);
139+
140+
if (returnCommands || returnUpdatedCommands || returnNotifications) {
141+
StringJoiner dataSj = new StringJoiner(",");
142+
if (returnCommands) {
143+
dataSj.add(COMMAND);
144+
}
145+
146+
if (returnUpdatedCommands) {
147+
dataSj.add(COMMAND_UPDATE);
148+
}
149+
150+
if (returnNotifications) {
151+
dataSj.add(NOTIFICATION);
152+
}
153+
sj.add(dataSj.toString());
138154
} else {
139-
sb.append(NOTIFICATION);
155+
sj.add(ANY);
140156
}
141-
sb.append("/");
142157

143158
if (networkIds != null && !networkIds.isEmpty()) {
144-
sb.append(networkIds);
159+
sj.add(networkIds);
145160
} else {
146-
sb.append(ANY);
161+
sj.add(ANY);
147162
}
148-
sb.append("/");
149163

150164
if (deviceTypeIds != null && !deviceTypeIds.isEmpty()) {
151-
sb.append(deviceTypeIds);
165+
sj.add(deviceTypeIds);
152166
} else {
153-
sb.append(ANY);
167+
sj.add(ANY);
154168
}
155-
sb.append("/");
156169

157170
if (deviceId != null && !deviceId.isEmpty()) {
158-
sb.append(deviceId);
171+
sj.add(deviceId);
159172
} else {
160-
sb.append(ANY);
173+
sj.add(ANY);
161174
}
162-
sb.append("/");
163175

164176
if (names != null && !names.isEmpty()) {
165-
sb.append(names);
177+
sj.add(names);
166178
} else {
167-
sb.append(ANY);
179+
sj.add(ANY);
168180
}
169181

170-
return sb.toString();
182+
return sj.toString();
171183
}
172-
173184

174185
}

devicehive-plugin/src/main/java/com/devicehive/proxy/PluginProxyClient.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ private void pingServer() {
136136
}
137137
}
138138
if (connected) {
139-
logger.info("Successfully connected to RpcServer");
139+
logger.info("Successfully connected to Websocket Proxy");
140140
} else {
141141
logger.error("Unable to reach out RpcServer in {} attempts", attempts);
142142
throw new RuntimeException("RpcServer is not reachable");

devicehive-plugin/src/main/java/com/devicehive/resource/PluginResource.java

+6
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,9 @@ void update(
156156
String topicName,
157157
@BeanParam
158158
PluginUpdateQuery updateQuery,
159+
@ApiParam(name = "Authorization", value = "Authorization token", required = true)
160+
@HeaderParam("Authorization")
161+
String authorization,
159162
@Suspended final AsyncResponse asyncResponse);
160163

161164
@DELETE
@@ -168,5 +171,8 @@ void update(
168171
void delete(
169172
@QueryParam("topicName")
170173
String topicName,
174+
@ApiParam(name = "Authorization", value = "Authorization token", required = true)
175+
@HeaderParam("Authorization")
176+
String authorization,
171177
@Suspended final AsyncResponse asyncResponse);
172178
}

devicehive-plugin/src/main/java/com/devicehive/resource/impl/PluginResourceImpl.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ public void register(PluginReqisterQuery pluginReqisterQuery, PluginUpdate plugi
140140
}
141141

142142
@Override
143-
public void update(String topicName, PluginUpdateQuery updateQuery, AsyncResponse asyncResponse) {
143+
public void update(String topicName, PluginUpdateQuery updateQuery, String authorization, AsyncResponse asyncResponse) {
144144
HivePrincipal principal = (HivePrincipal) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
145145
UserVO user = principal.getUser();
146146

@@ -153,7 +153,7 @@ public void update(String topicName, PluginUpdateQuery updateQuery, AsyncRespons
153153
}
154154

155155
@Override
156-
public void delete(String topicName, AsyncResponse asyncResponse) {
156+
public void delete(String topicName, String authorization, AsyncResponse asyncResponse) {
157157
HivePrincipal principal = (HivePrincipal) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
158158
UserVO user = principal.getUser();
159159

devicehive-plugin/src/main/java/com/devicehive/service/PluginRegisterService.java

+21-32
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
import com.devicehive.shim.api.client.RpcClient;
4242
import com.devicehive.shim.kafka.topic.KafkaTopicService;
4343
import com.devicehive.util.HiveValidator;
44+
import com.devicehive.vo.ApiInfoVO;
4445
import com.devicehive.vo.JwtTokenVO;
4546
import com.devicehive.vo.PluginVO;
4647
import com.google.gson.Gson;
@@ -111,6 +112,8 @@ public CompletableFuture<Response> register(Long userId, PluginReqisterQuery plu
111112
throw new HiveException(String.format(Messages.PLUGIN_ALREADY_EXISTS, pluginUpdate.getName()), BAD_REQUEST.getStatusCode());
112113
}
113114

115+
checkAuthServiceAvailable();
116+
114117
return persistPlugin(pluginUpdate, pluginReqisterQuery.constructFilterString(), userId).thenApply(pluginVO -> {
115118
JwtTokenVO jwtTokenVO = createPluginTokens(pluginVO.getTopicName(), authorization);
116119
JsonObject response = createTokenResponse(pluginVO.getTopicName(), jwtTokenVO);
@@ -215,46 +218,29 @@ private CompletableFuture<PluginVO> updatePlugin(PluginVO existingPlugin, Plugin
215218
existingPlugin.setParameters(pluginUpdateQuery.getParameters());
216219
}
217220

218-
if (pluginUpdateQuery.getStatus() != null) {
219-
existingPlugin.setStatus(pluginUpdateQuery.getStatus());
220-
}
221-
222-
// if no new information about filters is provided in PluginUpdateQuery, we should keep the same filters
223-
FilterEntity filterEntity = new FilterEntity(existingPlugin.getFilter());
224-
if (pluginUpdateQuery.getDeviceId() == null) {
225-
pluginUpdateQuery.setDeviceId(filterEntity.getDeviceId());
226-
}
227-
228-
if (pluginUpdateQuery.getNetworkIds() == null) {
229-
pluginUpdateQuery.setNetworkIds(filterEntity.getNetworkIds());
230-
}
231-
232-
if (pluginUpdateQuery.getDeviceTypeIds() == null) {
233-
pluginUpdateQuery.setDeviceTypeIds(filterEntity.getDeviceTypeIds());
234-
}
235-
236-
if (pluginUpdateQuery.getNames() == null) {
237-
pluginUpdateQuery.setNames(filterEntity.getNames());
238-
}
221+
final boolean isFilterChanges = pluginUpdateQuery.getDeviceId() != null || pluginUpdateQuery.getNetworkIds() != null ||
222+
pluginUpdateQuery.getDeviceTypeIds() != null || pluginUpdateQuery.getNames() != null ||
223+
pluginUpdateQuery.isReturnCommands() != null || pluginUpdateQuery.isReturnUpdatedCommands() != null ||
224+
pluginUpdateQuery.isReturnNotifications() != null;
239225

240-
if (pluginUpdateQuery.isReturnCommands() == null) {
241-
pluginUpdateQuery.setReturnCommands(filterEntity.isReturnCommands());
242-
}
226+
final boolean isStatusUpdated = pluginUpdateQuery.getStatus() != null &&
227+
!pluginUpdateQuery.getStatus().equals(existingPlugin.getStatus());
243228

244-
if (pluginUpdateQuery.isReturnUpdatedCommands() == null) {
245-
pluginUpdateQuery.setReturnUpdatedCommands(filterEntity.isReturnUpdatedCommands());
229+
if (isFilterChanges && !isStatusUpdated && existingPlugin.getStatus().equals(PluginStatus.ACTIVE)) {
230+
logger.error("Plugin's subscription filter can't be updated if plugin is ACTIVE");
231+
throw new HiveException(Messages.ACTIVE_PLUGIN_UPDATED, BAD_REQUEST.getStatusCode());
246232
}
247233

248-
if (pluginUpdateQuery.isReturnNotifications() == null) {
249-
pluginUpdateQuery.setReturnNotifications(filterEntity.isReturnNotifications());
234+
if (isStatusUpdated) {
235+
existingPlugin.setStatus(pluginUpdateQuery.getStatus());
250236
}
251237

252238
existingPlugin.setFilter(pluginUpdateQuery.constructFilterString());
253239

254240
CompletableFuture<com.devicehive.shim.api.Response> future = new CompletableFuture<>();
255241

256242
BasePluginRequest request = null;
257-
if (pluginUpdateQuery.getStatus() != null) {
243+
if (isStatusUpdated) {
258244
if (pluginUpdateQuery.getStatus().equals(PluginStatus.ACTIVE) && existingPlugin.getSubscriptionId() == null) {
259245
final Long subscriptionId = idGenerator.generate();
260246
request = pluginUpdateQuery.toRequest(filterService);
@@ -283,19 +269,22 @@ private CompletableFuture<PluginVO> updatePlugin(PluginVO existingPlugin, Plugin
283269

284270
}
285271

272+
private void checkAuthServiceAvailable() {
273+
httpRestHelper.get(authBaseUrl + "/info", ApiInfoVO.class, null);
274+
}
275+
286276
private JwtTokenVO createPluginTokens(String topicName, String authorization) {
287277
JwtPluginPayload jwtPluginPayload = new JwtPluginPayload(Collections.singleton(MANAGE_PLUGIN.getId()), topicName, null, null);
288278

289279
JwtTokenVO jwtToken = null;
290280
try {
291281
jwtToken = httpRestHelper.post(authBaseUrl + "/token/plugin/create", gson.toJson(jwtPluginPayload), JwtTokenVO.class, authorization);
292282
} catch (ServiceUnavailableException e) {
293-
logger.warn("Service is not available");
294-
throw new HiveException(e.getMessage(), SC_SERVICE_UNAVAILABLE);
283+
logger.error("Authentication service is not available");
284+
throw new HiveException(e.getMessage(), SERVICE_UNAVAILABLE.getStatusCode());
295285
}
296286

297287
return jwtToken;
298-
299288
}
300289

301290
private JsonObject createTokenResponse(String topicName, JwtTokenVO jwtTokenVO) {

devicehive-plugin/src/main/resources/messages.properties

+2-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ UNPARSEABLE_TIMESTAMP=Unparseable timestamp
2525
UNPARSEABLE_SORT_ORDER=Unparseable sort order : %s
2626
SORT_ORDER_IS_NULL=Sort order cannot be null
2727
INVALID_REQUEST_PARAMETERS=Invalid request parameters
28-
HEALTH_CHECK_FAILED=Health check failed
28+
HEALTH_CHECK_FAILED=Authentication service is not available
2929
DUPLICATE_LABEL_FOUND=Access key with this label already exists
3030
JSON_SYNTAX_ERROR=JSON syntax error
3131
CONFIG_NOT_FOUND=Requested config with name = %s not found in the database
@@ -136,4 +136,5 @@ NO_ACCESS_TO_DEVICE_TYPE=No access to device type!
136136
DEVICE_TYPE_CREATION_NOT_ALLOWED=No permissions to create device type!
137137
DEVICE_TYPE_ASSIGNMENT_NOT_ALLOWED=Cannot assign device type to user with all device types allowed
138138
NO_ACCESS_TO_DEVICE_TYPES_OR_NETWORKS=No access to any device type or network
139+
ACTIVE_PLUGIN_UPDATED=Plugin's subscription filter can't be updated if plugin is ACTIVE
139140
NO_ACCESS_TO_PLUGIN=No access to plugin

0 commit comments

Comments
 (0)