Merge branch 'master' into Reduce_Duplicate_Code
Conflicts: hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/HawkbitCommonUtil.java Signed-off-by: SirWayne <dennis.melzer@bosch-si.com>
This commit is contained in:
@@ -14,6 +14,11 @@ see [hawkBit Wiki](https://github.com/eclipse/hawkbit/wiki)
|
|||||||
* Having issues with hawkBit? Open a [GitHub issue](https://github.com/eclipse/hawkbit/issues).
|
* Having issues with hawkBit? Open a [GitHub issue](https://github.com/eclipse/hawkbit/issues).
|
||||||
* You can also check out our [Project Homepage](https://projects.eclipse.org/projects/iot.hawkbit) for further contact options.
|
* You can also check out our [Project Homepage](https://projects.eclipse.org/projects/iot.hawkbit) for further contact options.
|
||||||
|
|
||||||
|
# hawkBit sandbox
|
||||||
|
|
||||||
|
We offer a sandbox installation that is free for everyone to try out hawkBit. However, keep in mind that the sandbox database will be reset from time to time. It is also not possible to upload any artifacts into the sandbox. But you can use it to try out the Management UI, Management API and DDI API.
|
||||||
|
|
||||||
|
https://hawkbit.eu-gb.mybluemix.net/UI/
|
||||||
|
|
||||||
# Compile, Run and Getting Started
|
# Compile, Run and Getting Started
|
||||||
|
|
||||||
|
|||||||
20
deployHawkBitSandbox.sh
Normal file
20
deployHawkBitSandbox.sh
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||||
|
#
|
||||||
|
# All rights reserved. This program and the accompanying materials
|
||||||
|
# are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
# which accompanies this distribution, and is available at
|
||||||
|
# http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
#
|
||||||
|
|
||||||
|
# This script allows the deployment of the complete hawkBit sandbox including
|
||||||
|
# data example to a cloud foundry enviroment. Expects existing CF CLI
|
||||||
|
# installation and login to be existing already.
|
||||||
|
|
||||||
|
cd examples/hawkbit-example-app/target/
|
||||||
|
cf push
|
||||||
|
cd ../..
|
||||||
|
java -jar hawkbit-mgmt-api-client/target/hawkbit-mgmt-api-client-0.2.0-SNAPSHOT.jar --hawkbit.url=hawkbit.eu-gb.mybluemix.net
|
||||||
|
cd hawkbit-device-simulator/target/
|
||||||
|
cf push
|
||||||
|
cd ../../..
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
The device simulator handles software update commands from the update server.
|
The device simulator handles software update commands from the update server.
|
||||||
|
|
||||||
## Run
|
## Run on your own workstation
|
||||||
```
|
```
|
||||||
java -jar examples/hawkbit-device-simulator/target/hawkbit-device-simulator-*-SNAPSHOT.jar
|
java -jar examples/hawkbit-device-simulator/target/hawkbit-device-simulator-*-SNAPSHOT.jar
|
||||||
```
|
```
|
||||||
@@ -11,6 +11,11 @@ Or:
|
|||||||
run org.eclipse.hawkbit.simulator.DeviceSimulator
|
run org.eclipse.hawkbit.simulator.DeviceSimulator
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Deploy to cloud foundry environment
|
||||||
|
|
||||||
|
- Go to ```target``` subfolder.
|
||||||
|
- Run ```cf push```
|
||||||
|
|
||||||
## Notes
|
## Notes
|
||||||
|
|
||||||
The simulator has user authentication enabled in **cloud profile**. Default credentials:
|
The simulator has user authentication enabled in **cloud profile**. Default credentials:
|
||||||
@@ -30,9 +35,9 @@ http://localhost:8083
|
|||||||
```
|
```
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||

|

|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
|
||||||
@@ -54,12 +59,12 @@ Example: for 20 simulated devices (default)
|
|||||||
http://localhost:8083/start
|
http://localhost:8083/start
|
||||||
```
|
```
|
||||||
|
|
||||||
Example: for 10 simulated devices that start with the name prefix "activeSim":
|
Example: for 10 simulated devices that start with the name prefix "activeSim":
|
||||||
```
|
```
|
||||||
http://localhost:8083/start?amount=10&name=activeSim
|
http://localhost:8083/start?amount=10&name=activeSim
|
||||||
```
|
```
|
||||||
|
|
||||||
Example: for 5 simulated devices that start with the name prefix "ddi" using the Direct Device Integration API (http):
|
Example: for 5 simulated devices that start with the name prefix "ddi" using the Direct Device Integration API (http):
|
||||||
```
|
```
|
||||||
http://localhost:8083/start?amount=5&name=ddi?api=ddi
|
http://localhost:8083/start?amount=5&name=ddi?api=ddi
|
||||||
```
|
```
|
||||||
|
|||||||
22
examples/hawkbit-device-simulator/cf/manifest.yml
Normal file
22
examples/hawkbit-device-simulator/cf/manifest.yml
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||||
|
#
|
||||||
|
# All rights reserved. This program and the accompanying materials
|
||||||
|
# are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
# which accompanies this distribution, and is available at
|
||||||
|
# http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
#
|
||||||
|
|
||||||
|
---
|
||||||
|
applications:
|
||||||
|
- name: hawkbit-simulator
|
||||||
|
memory: 1024M
|
||||||
|
instances: 1
|
||||||
|
buildpack: https://github.com/cloudfoundry/java-buildpack
|
||||||
|
path: ${project.build.finalName}.jar
|
||||||
|
services:
|
||||||
|
- dmf-rabbit
|
||||||
|
env:
|
||||||
|
SPRING_PROFILES_ACTIVE: cloud,amqp
|
||||||
|
CF_STAGING_TIMEOUT: 15
|
||||||
|
CF_STARTUP_TIMEOUT: 15
|
||||||
@@ -42,6 +42,19 @@
|
|||||||
</executions>
|
</executions>
|
||||||
</plugin>
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
|
<resources>
|
||||||
|
<resource>
|
||||||
|
<directory>src/main/resources</directory>
|
||||||
|
</resource>
|
||||||
|
<resource>
|
||||||
|
<directory>cf</directory>
|
||||||
|
<filtering>true</filtering>
|
||||||
|
<targetPath>${project.build.directory}</targetPath>
|
||||||
|
<includes>
|
||||||
|
<include>manifest.yml</include>
|
||||||
|
</includes>
|
||||||
|
</resource>
|
||||||
|
</resources>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import java.util.concurrent.Executors;
|
|||||||
import java.util.concurrent.ScheduledExecutorService;
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import org.eclipse.hawkbit.simulator.AbstractSimulatedDevice.Protocol;
|
||||||
import org.eclipse.hawkbit.simulator.amqp.SpSenderService;
|
import org.eclipse.hawkbit.simulator.amqp.SpSenderService;
|
||||||
import org.eclipse.hawkbit.simulator.event.InitUpdate;
|
import org.eclipse.hawkbit.simulator.event.InitUpdate;
|
||||||
import org.eclipse.hawkbit.simulator.event.ProgressUpdate;
|
import org.eclipse.hawkbit.simulator.event.ProgressUpdate;
|
||||||
@@ -34,6 +35,9 @@ public class DeviceSimulatorUpdater {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private SpSenderService spSenderService;
|
private SpSenderService spSenderService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SimulatedDeviceFactory deviceFactory;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private EventBus eventbus;
|
private EventBus eventbus;
|
||||||
|
|
||||||
@@ -58,7 +62,13 @@ public class DeviceSimulatorUpdater {
|
|||||||
*/
|
*/
|
||||||
public void startUpdate(final String tenant, final String id, final long actionId, final String swVersion,
|
public void startUpdate(final String tenant, final String id, final long actionId, final String swVersion,
|
||||||
final UpdaterCallback callback) {
|
final UpdaterCallback callback) {
|
||||||
final AbstractSimulatedDevice device = repository.get(tenant, id);
|
AbstractSimulatedDevice device = repository.get(tenant, id);
|
||||||
|
|
||||||
|
// plug and play - non existing device will be auto created
|
||||||
|
if (device == null) {
|
||||||
|
device = repository.add(deviceFactory.createSimulatedDevice(id, tenant, Protocol.DMF_AMQP, -1, null, null));
|
||||||
|
}
|
||||||
|
|
||||||
device.setProgress(0.0);
|
device.setProgress(0.0);
|
||||||
device.setSwversion(swVersion);
|
device.setSwversion(swVersion);
|
||||||
eventbus.post(new InitUpdate(device));
|
eventbus.post(new InitUpdate(device));
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ public class SimulationController {
|
|||||||
* number of delay in milliseconds to delay polling of DDI
|
* number of delay in milliseconds to delay polling of DDI
|
||||||
* devices
|
* devices
|
||||||
* @param gatewayToken
|
* @param gatewayToken
|
||||||
* the hawkbit-update-server gatwaytoken in case authentication
|
* the hawkbit-update-server gatewaytoken in case authentication
|
||||||
* is enforced in hawkbit
|
* is enforced in hawkbit
|
||||||
* @return a response string that devices has been created
|
* @return a response string that devices has been created
|
||||||
* @throws MalformedURLException
|
* @throws MalformedURLException
|
||||||
@@ -68,7 +68,7 @@ public class SimulationController {
|
|||||||
@RequestParam(value = "endpoint", defaultValue = "http://localhost:8080") final String endpoint,
|
@RequestParam(value = "endpoint", defaultValue = "http://localhost:8080") final String endpoint,
|
||||||
@RequestParam(value = "polldelay", defaultValue = "30") final int pollDelay,
|
@RequestParam(value = "polldelay", defaultValue = "30") final int pollDelay,
|
||||||
@RequestParam(value = "gatewaytoken", defaultValue = "") final String gatewayToken)
|
@RequestParam(value = "gatewaytoken", defaultValue = "") final String gatewayToken)
|
||||||
throws MalformedURLException {
|
throws MalformedURLException {
|
||||||
|
|
||||||
final Protocol protocol;
|
final Protocol protocol;
|
||||||
switch (api.toLowerCase()) {
|
switch (api.toLowerCase()) {
|
||||||
|
|||||||
@@ -0,0 +1,136 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||||
|
*
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*/
|
||||||
|
package org.eclipse.hawkbit.simulator;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.eclipse.hawkbit.simulator.AbstractSimulatedDevice.Protocol;
|
||||||
|
import org.hibernate.validator.constraints.NotEmpty;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* General simulator service properties.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
@ConfigurationProperties("hawkbit.device.simulator")
|
||||||
|
public class SimulationProperties {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of tenants where the simulator should auto start simulations after
|
||||||
|
* startup.
|
||||||
|
*/
|
||||||
|
private final List<Autostart> autostarts = new ArrayList<>();
|
||||||
|
|
||||||
|
public List<Autostart> getAutostarts() {
|
||||||
|
return this.autostarts;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Auto start configuration for simulation setups that the simulator begins
|
||||||
|
* after startup.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public static class Autostart {
|
||||||
|
/**
|
||||||
|
* Name prefix of simulated devices, followed by counter, e.g.
|
||||||
|
* simulated0, simulated1, simulated2....
|
||||||
|
*/
|
||||||
|
private String name = "simulated";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Amount of simulated devices.
|
||||||
|
*/
|
||||||
|
private int amount = 20;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tenant name for the simulation.
|
||||||
|
*/
|
||||||
|
@NotEmpty
|
||||||
|
private String tenant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* API for simulation.
|
||||||
|
*/
|
||||||
|
private Protocol api = Protocol.DMF_AMQP;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Endpoint in case of DDI API based simulation.
|
||||||
|
*/
|
||||||
|
private String endpoint = "http://localhost:8080";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Poll time in case of DDI API based simulation.
|
||||||
|
*/
|
||||||
|
private int pollDelay = 30;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Optional gateway token for DDI API based simulation.
|
||||||
|
*/
|
||||||
|
private String gatewayToken = "";
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(final String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getAmount() {
|
||||||
|
return amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAmount(final int amount) {
|
||||||
|
this.amount = amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTenant() {
|
||||||
|
return tenant;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTenant(final String tenant) {
|
||||||
|
this.tenant = tenant;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Protocol getApi() {
|
||||||
|
return api;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setApi(final Protocol api) {
|
||||||
|
this.api = api;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getEndpoint() {
|
||||||
|
return endpoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEndpoint(final String endpoint) {
|
||||||
|
this.endpoint = endpoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPollDelay() {
|
||||||
|
return pollDelay;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPollDelay(final int pollDelay) {
|
||||||
|
this.pollDelay = pollDelay;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getGatewayToken() {
|
||||||
|
return gatewayToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGatewayToken(final String gatewayToken) {
|
||||||
|
this.gatewayToken = gatewayToken;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||||
|
*
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*/
|
||||||
|
package org.eclipse.hawkbit.simulator;
|
||||||
|
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
import org.eclipse.hawkbit.simulator.amqp.SpSenderService;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.ApplicationListener;
|
||||||
|
import org.springframework.context.event.ContextRefreshedEvent;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execution of operations after startup. Set up of simulations.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class SimulatorStartup implements ApplicationListener<ContextRefreshedEvent> {
|
||||||
|
private static final Logger LOGGER = LoggerFactory.getLogger(SimulatorStartup.class);
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SimulationProperties simulationProperties;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SpSenderService spSenderService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private DeviceSimulatorRepository repository;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SimulatedDeviceFactory deviceFactory;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onApplicationEvent(final ContextRefreshedEvent event) {
|
||||||
|
simulationProperties.getAutostarts().forEach(autostart -> {
|
||||||
|
for (int i = 0; i < autostart.getAmount(); i++) {
|
||||||
|
final String deviceId = autostart.getName() + i;
|
||||||
|
try {
|
||||||
|
repository.add(deviceFactory.createSimulatedDevice(deviceId, autostart.getTenant(),
|
||||||
|
autostart.getApi(), autostart.getPollDelay(), new URL(autostart.getEndpoint()),
|
||||||
|
autostart.getGatewayToken()));
|
||||||
|
} catch (final MalformedURLException e) {
|
||||||
|
LOGGER.error("Creation of simulated device at startup failed.", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
spSenderService.createOrUpdateThing(autostart.getTenant(), deviceId);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -59,7 +59,8 @@ public class AmqpConfiguration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create the receiver queue from sp. Receive messages from sp.
|
* Creates the receiver queue from update server for receiving message from
|
||||||
|
* update server.
|
||||||
*
|
*
|
||||||
* @return the queue
|
* @return the queue
|
||||||
*/
|
*/
|
||||||
@@ -70,7 +71,7 @@ public class AmqpConfiguration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create the recevier exchange. Sp send messages to this exchange.
|
* Creates the receiver exchange for sending messages to update server.
|
||||||
*
|
*
|
||||||
* @return the exchange
|
* @return the exchange
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -19,26 +19,25 @@ import org.springframework.stereotype.Component;
|
|||||||
@Component
|
@Component
|
||||||
@ConfigurationProperties("hawkbit.device.simulator.amqp")
|
@ConfigurationProperties("hawkbit.device.simulator.amqp")
|
||||||
public class AmqpProperties {
|
public class AmqpProperties {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Queue for receiving DMF messages from update server.
|
* Queue for receiving DMF messages from update server.
|
||||||
*/
|
*/
|
||||||
private String receiverConnectorQueueFromSp;
|
private String receiverConnectorQueueFromSp = "simulator_receiver";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exchange for sending DMF messages to update server.
|
* Exchange for sending DMF messages to update server.
|
||||||
*/
|
*/
|
||||||
private String senderForSpExchange;
|
private String senderForSpExchange = "simulator.replyTo";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simulator dead letter queue.
|
* Simulator dead letter queue.
|
||||||
*/
|
*/
|
||||||
private String deadLetterQueue;
|
private String deadLetterQueue = "simulator_deadletter";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simulator dead letter exchange.
|
* Simulator dead letter exchange.
|
||||||
*/
|
*/
|
||||||
private String deadLetterExchange;
|
private String deadLetterExchange = "simulator.deadletter";
|
||||||
|
|
||||||
public String getReceiverConnectorQueueFromSp() {
|
public String getReceiverConnectorQueueFromSp() {
|
||||||
return receiverConnectorQueueFromSp;
|
return receiverConnectorQueueFromSp;
|
||||||
|
|||||||
@@ -26,14 +26,11 @@ import org.springframework.messaging.handler.annotation.Header;
|
|||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle all incoming Messages from SP.
|
* Handle all incoming Messages from hawkBit update server.
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
public class SpReceiverService extends ReceiverService {
|
public class SpReceiverService extends ReceiverService {
|
||||||
|
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(ReceiverService.class);
|
private static final Logger LOGGER = LoggerFactory.getLogger(ReceiverService.class);
|
||||||
|
|
||||||
public static final String SOFTWARE_MODULE_FIRMWARE = "firmware";
|
public static final String SOFTWARE_MODULE_FIRMWARE = "firmware";
|
||||||
@@ -44,17 +41,6 @@ public class SpReceiverService extends ReceiverService {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
*
|
|
||||||
* @param rabbitTemplate
|
|
||||||
* the rabbit template
|
|
||||||
* @param amqpProperties
|
|
||||||
* the amqp properties
|
|
||||||
* @param lwm2mSenderService
|
|
||||||
* the lwm2mSenderService
|
|
||||||
* @param spSenderService
|
|
||||||
* the spSenderService
|
|
||||||
* @param deviceUpdater
|
|
||||||
* the updater service to simulate update process
|
|
||||||
*/
|
*/
|
||||||
@Autowired
|
@Autowired
|
||||||
public SpReceiverService(final RabbitTemplate rabbitTemplate, final AmqpProperties amqpProperties,
|
public SpReceiverService(final RabbitTemplate rabbitTemplate, final AmqpProperties amqpProperties,
|
||||||
@@ -62,12 +48,11 @@ public class SpReceiverService extends ReceiverService {
|
|||||||
super(rabbitTemplate, amqpProperties);
|
super(rabbitTemplate, amqpProperties);
|
||||||
this.spSenderService = spSenderService;
|
this.spSenderService = spSenderService;
|
||||||
this.deviceUpdater = deviceUpdater;
|
this.deviceUpdater = deviceUpdater;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle the incoming Message from Queue with the property
|
* Handle the incoming Message from Queue with the property
|
||||||
* (com.bosch.sp.lwm2m.connector.amqp.receiverConnectorQueueFromSp).
|
* (hawkbit.device.simulator.amqp.receiverConnectorQueueFromSp).
|
||||||
*
|
*
|
||||||
* @param message
|
* @param message
|
||||||
* the incoming message
|
* the incoming message
|
||||||
|
|||||||
@@ -7,18 +7,17 @@
|
|||||||
# http://www.eclipse.org/legal/epl-v10.html
|
# http://www.eclipse.org/legal/epl-v10.html
|
||||||
#
|
#
|
||||||
|
|
||||||
|
## Configuration for DMF communication
|
||||||
#########################################################################################
|
|
||||||
# PUBLIC configuration, i.e. can be changed by users at runtime (defaults provided here)
|
|
||||||
#########################################################################################
|
|
||||||
## Configuration for RabbitMQ communication
|
|
||||||
hawkbit.device.simulator.amqp.receiverConnectorQueueFromSp=simulator_receiver
|
hawkbit.device.simulator.amqp.receiverConnectorQueueFromSp=simulator_receiver
|
||||||
hawkbit.device.simulator.amqp.deadLetterQueue=simulator_deadletter
|
hawkbit.device.simulator.amqp.deadLetterQueue=simulator_deadletter
|
||||||
hawkbit.device.simulator.amqp.deadLetterExchange=simulator.deadletter
|
hawkbit.device.simulator.amqp.deadLetterExchange=simulator.deadletter
|
||||||
hawkbit.device.simulator.amqp.senderForSpExchange=simulator.replyTo
|
hawkbit.device.simulator.amqp.senderForSpExchange=simulator.replyTo
|
||||||
|
|
||||||
|
## Configuration for simulations
|
||||||
|
hawkbit.device.simulator.autostarts.[0].tenant=DEFAULT
|
||||||
|
|
||||||
## Configuration for RabbitMQ integration
|
|
||||||
|
## Configuration for local RabbitMQ integration
|
||||||
spring.rabbitmq.username=guest
|
spring.rabbitmq.username=guest
|
||||||
spring.rabbitmq.password=guest
|
spring.rabbitmq.password=guest
|
||||||
spring.rabbitmq.virtualHost=/
|
spring.rabbitmq.virtualHost=/
|
||||||
|
|||||||
@@ -1,7 +1,15 @@
|
|||||||
# hawkBit Example Application
|
# hawkBit Example Application
|
||||||
The hawkBit example application is a standalone spring-boot application with an embedded servlet container to start the hawkBit.
|
The hawkBit example application is a standalone spring-boot application with an embedded servlet container to host the hawkBit Update Server.
|
||||||
|
|
||||||
## Run
|
We have have described several options for you to get access to the example.
|
||||||
|
|
||||||
|
## Try out the example application in our hawkBit sandbox on Bluemix
|
||||||
|
- try out Management UI https://hawkbit.eu-gb.mybluemix.net/UI
|
||||||
|
- try out Management API https://hawkbit.eu-gb.mybluemix.net/rest/v1/targets (don't forget basic auth header)
|
||||||
|
- try out DDI API https://hawkbit.eu-gb.mybluemix.net/DEFAULT/controller/v1/MYTESTDEVICE
|
||||||
|
|
||||||
|
## On your own workstation
|
||||||
|
### Run
|
||||||
```
|
```
|
||||||
java -jar examples/hawkbit-example-app/target/hawkbit-example-app-*-SNAPSHOT.jar
|
java -jar examples/hawkbit-example-app/target/hawkbit-example-app-*-SNAPSHOT.jar
|
||||||
```
|
```
|
||||||
@@ -10,6 +18,14 @@ Or:
|
|||||||
run org eclipse.hawkbit.app.Start
|
run org eclipse.hawkbit.app.Start
|
||||||
```
|
```
|
||||||
|
|
||||||
## Usage
|
### Usage
|
||||||
The UI can be accessed via _http://localhost:8080/UI_.
|
The Management UI can be accessed via http://localhost:8080/UI
|
||||||
The REST API can be accessed via _http://localhost:8080/rest/v1_.
|
The Management API can be accessed via http://localhost:8080/rest/v1
|
||||||
|
|
||||||
|
## Deploy example app to Cloud Foundry
|
||||||
|
|
||||||
|
- Go to ```target``` subfolder.
|
||||||
|
- Select one of the two manifests
|
||||||
|
- **manifest-simple.yml** for a standalone hawkBit installation with embedded H2.
|
||||||
|
- **manifest.yml** for a standalone hawkBit installation with embedded H2 and RabbitMQ service binding for DMF integration (note: this manifest is used for the sandbox above).
|
||||||
|
- Run ```cf push``` against you cloud foundry environment.
|
||||||
|
|||||||
20
examples/hawkbit-example-app/cf/manifest-simple.yml
Normal file
20
examples/hawkbit-example-app/cf/manifest-simple.yml
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||||
|
#
|
||||||
|
# All rights reserved. This program and the accompanying materials
|
||||||
|
# are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
# which accompanies this distribution, and is available at
|
||||||
|
# http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
#
|
||||||
|
|
||||||
|
---
|
||||||
|
applications:
|
||||||
|
- name: hawkbit-simple
|
||||||
|
memory: 1024M
|
||||||
|
instances: 1
|
||||||
|
buildpack: https://github.com/cloudfoundry/java-buildpack
|
||||||
|
path: ${project.build.finalName}.jar
|
||||||
|
env:
|
||||||
|
SPRING_PROFILES_ACTIVE: cloudsandbox
|
||||||
|
CF_STAGING_TIMEOUT: 15
|
||||||
|
CF_STARTUP_TIMEOUT: 15
|
||||||
22
examples/hawkbit-example-app/cf/manifest.yml
Normal file
22
examples/hawkbit-example-app/cf/manifest.yml
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||||
|
#
|
||||||
|
# All rights reserved. This program and the accompanying materials
|
||||||
|
# are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
# which accompanies this distribution, and is available at
|
||||||
|
# http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
#
|
||||||
|
|
||||||
|
---
|
||||||
|
applications:
|
||||||
|
- name: hawkbit
|
||||||
|
memory: 1024M
|
||||||
|
instances: 1
|
||||||
|
buildpack: https://github.com/cloudfoundry/java-buildpack
|
||||||
|
path: ${project.build.finalName}.jar
|
||||||
|
services:
|
||||||
|
- dmf-rabbit
|
||||||
|
env:
|
||||||
|
SPRING_PROFILES_ACTIVE: cloudsandbox,amqp
|
||||||
|
CF_STAGING_TIMEOUT: 15
|
||||||
|
CF_STARTUP_TIMEOUT: 15
|
||||||
@@ -39,6 +39,20 @@
|
|||||||
</executions>
|
</executions>
|
||||||
</plugin>
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
|
<resources>
|
||||||
|
<resource>
|
||||||
|
<directory>src/main/resources</directory>
|
||||||
|
</resource>
|
||||||
|
<resource>
|
||||||
|
<directory>cf</directory>
|
||||||
|
<filtering>true</filtering>
|
||||||
|
<targetPath>${project.build.directory}</targetPath>
|
||||||
|
<includes>
|
||||||
|
<include>manifest.yml</include>
|
||||||
|
<include>manifest-simple.yml</include>
|
||||||
|
</includes>
|
||||||
|
</resource>
|
||||||
|
</resources>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||||
|
#
|
||||||
|
# All rights reserved. This program and the accompanying materials
|
||||||
|
# are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
# which accompanies this distribution, and is available at
|
||||||
|
# http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
#
|
||||||
|
|
||||||
|
vaadin.servlet.productionMode=true
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
# HawkBit management API example
|
# hawkBit Management API example client
|
||||||
|
|
||||||
Example client that shows how to efficiently use the hawkBit management API.
|
Example client that shows how to efficiently use the hawkBit management API.
|
||||||
|
|
||||||
@@ -36,4 +36,3 @@ In rollout mode:
|
|||||||
* assigning software modules to distribution sets
|
* assigning software modules to distribution sets
|
||||||
* creating a rollout
|
* creating a rollout
|
||||||
* starting a rollout
|
* starting a rollout
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import org.springframework.cloud.netflix.feign.FeignClient;
|
|||||||
/**
|
/**
|
||||||
* Client binding for the DistributionSet resource of the management API.
|
* Client binding for the DistributionSet resource of the management API.
|
||||||
*/
|
*/
|
||||||
@FeignClient(url = "${hawkbit.endpoint.url:localhost:8080}/rest/v1/distributionsets")
|
@FeignClient(url = "${hawkbit.url:localhost:8080}/rest/v1/distributionsets")
|
||||||
public interface DistributionSetResourceClient extends DistributionSetRestApi {
|
public interface DistributionSetResourceClient extends DistributionSetRestApi {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import org.springframework.cloud.netflix.feign.FeignClient;
|
|||||||
/**
|
/**
|
||||||
* Client binding for the DistributionSetTag resource of the management API.
|
* Client binding for the DistributionSetTag resource of the management API.
|
||||||
*/
|
*/
|
||||||
@FeignClient(url = "${hawkbit.endpoint.url:localhost:8080}/rest/v1/distributionsettags")
|
@FeignClient(url = "${hawkbit.url:localhost:8080}/rest/v1/distributionsettags")
|
||||||
public interface DistributionSetTagResourceClient extends DistributionSetTagRestApi {
|
public interface DistributionSetTagResourceClient extends DistributionSetTagRestApi {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import org.springframework.cloud.netflix.feign.FeignClient;
|
|||||||
* Client binding for the DistributionSetType resource of the management API.
|
* Client binding for the DistributionSetType resource of the management API.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@FeignClient(url = "${hawkbit.endpoint.url:localhost:8080}/rest/v1/distributionsettypes")
|
@FeignClient(url = "${hawkbit.url:localhost:8080}/rest/v1/distributionsettypes")
|
||||||
public interface DistributionSetTypeResourceClient extends DistributionSetTypeRestApi {
|
public interface DistributionSetTypeResourceClient extends DistributionSetTypeRestApi {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import org.springframework.cloud.netflix.feign.FeignClient;
|
|||||||
/**
|
/**
|
||||||
* Client binding for the Rollout resource of the management API.
|
* Client binding for the Rollout resource of the management API.
|
||||||
*/
|
*/
|
||||||
@FeignClient(url = "${hawkbit.endpoint.url:localhost:8080}/rest/v1/rollouts")
|
@FeignClient(url = "${hawkbit.url:localhost:8080}/rest/v1/rollouts")
|
||||||
public interface RolloutResourceClient extends RolloutRestApi {
|
public interface RolloutResourceClient extends RolloutRestApi {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import org.springframework.cloud.netflix.feign.FeignClient;
|
|||||||
/**
|
/**
|
||||||
* Client binding for the SoftwareModule resource of the management API.
|
* Client binding for the SoftwareModule resource of the management API.
|
||||||
*/
|
*/
|
||||||
@FeignClient(url = "${hawkbit.endpoint.url:localhost:8080}/rest/v1/softwaremodules")
|
@FeignClient(url = "${hawkbit.url:localhost:8080}/rest/v1/softwaremodules")
|
||||||
public interface SoftwareModuleResourceClient extends SoftwareModuleRestAPI {
|
public interface SoftwareModuleResourceClient extends SoftwareModuleRestAPI {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import org.springframework.cloud.netflix.feign.FeignClient;
|
|||||||
/**
|
/**
|
||||||
* Client binding for the oftwareModuleType resource of the management API.
|
* Client binding for the oftwareModuleType resource of the management API.
|
||||||
*/
|
*/
|
||||||
@FeignClient(url = "${hawkbit.endpoint.url:localhost:8080}/rest/v1/softwaremoduletypes")
|
@FeignClient(url = "${hawkbit.url:localhost:8080}/rest/v1/softwaremoduletypes")
|
||||||
public interface SoftwareModuleTypeResourceClient extends SoftwareModuleTypeRestApi {
|
public interface SoftwareModuleTypeResourceClient extends SoftwareModuleTypeRestApi {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import org.springframework.cloud.netflix.feign.FeignClient;
|
|||||||
/**
|
/**
|
||||||
* Client binding for the Target resource of the management API.
|
* Client binding for the Target resource of the management API.
|
||||||
*/
|
*/
|
||||||
@FeignClient(url = "${hawkbit.endpoint.url:localhost:8080}/rest/v1/targets")
|
@FeignClient(url = "${hawkbit.url:localhost:8080}/rest/v1/targets")
|
||||||
public interface TargetResourceClient extends TargetRestApi {
|
public interface TargetResourceClient extends TargetRestApi {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import org.springframework.cloud.netflix.feign.FeignClient;
|
|||||||
/**
|
/**
|
||||||
* Client binding for the TargetTag resource of the management API.
|
* Client binding for the TargetTag resource of the management API.
|
||||||
*/
|
*/
|
||||||
@FeignClient(url = "${hawkbit.endpoint.url:localhost:8080}/rest/v1/targettags")
|
@FeignClient(url = "${hawkbit.url:localhost:8080}/rest/v1/targettags")
|
||||||
public interface TargetTagResourceClient extends TargetTagRestApi {
|
public interface TargetTagResourceClient extends TargetTagRestApi {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,11 +16,7 @@ import org.eclipse.hawkbit.rest.resource.model.distributionset.DistributionSetRe
|
|||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* Builder pattern for building {@link DistributionSetRequestBodyPost}.
|
* Builder pattern for building {@link DistributionSetRequestBodyPost}.
|
||||||
*
|
|
||||||
* @author Jonathan Knoblauch
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public class DistributionSetBuilder {
|
public class DistributionSetBuilder {
|
||||||
|
|
||||||
|
|||||||
@@ -19,8 +19,6 @@ import com.google.common.collect.Lists;
|
|||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Builder pattern for building {@link DistributionSetTypeRequestBodyPost}.
|
* Builder pattern for building {@link DistributionSetTypeRequestBodyPost}.
|
||||||
*
|
|
||||||
* @author Jonathan Knoblauch
|
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class DistributionSetTypeBuilder {
|
public class DistributionSetTypeBuilder {
|
||||||
|
|||||||
@@ -15,8 +15,6 @@ import org.eclipse.hawkbit.rest.resource.model.rollout.RolloutRestRequestBody;
|
|||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Builder pattern for building {@link RolloutRestRequestBody}.
|
* Builder pattern for building {@link RolloutRestRequestBody}.
|
||||||
*
|
|
||||||
* @author Jonathan Knoblauch
|
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class RolloutBuilder {
|
public class RolloutBuilder {
|
||||||
|
|||||||
@@ -16,8 +16,6 @@ import org.eclipse.hawkbit.rest.resource.model.softwaremodule.SoftwareModuleAssi
|
|||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Builder pattern for building {@link SoftwareModuleAssigmentRest}.
|
* Builder pattern for building {@link SoftwareModuleAssigmentRest}.
|
||||||
*
|
|
||||||
* @author Jonathan Knoblauch
|
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class SoftwareModuleAssigmentBuilder {
|
public class SoftwareModuleAssigmentBuilder {
|
||||||
|
|||||||
@@ -19,8 +19,6 @@ import com.google.common.collect.Lists;
|
|||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Builder pattern for building {@link SoftwareModuleRequestBodyPost}.
|
* Builder pattern for building {@link SoftwareModuleRequestBodyPost}.
|
||||||
*
|
|
||||||
* @author Jonathan Knoblauch
|
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class SoftwareModuleBuilder {
|
public class SoftwareModuleBuilder {
|
||||||
|
|||||||
@@ -19,8 +19,6 @@ import com.google.common.collect.Lists;
|
|||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Builder pattern for building {@link SoftwareModuleRequestBodyPost}.
|
* Builder pattern for building {@link SoftwareModuleRequestBodyPost}.
|
||||||
*
|
|
||||||
* @author Jonathan Knoblauch
|
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class SoftwareModuleTypeBuilder {
|
public class SoftwareModuleTypeBuilder {
|
||||||
|
|||||||
@@ -17,8 +17,6 @@ import com.google.common.collect.Lists;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Builder pattern for building {@link TagRequestBodyPut}.
|
* Builder pattern for building {@link TagRequestBodyPut}.
|
||||||
*
|
|
||||||
* @author Jonathan Knoblauch
|
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class TagBuilder {
|
public class TagBuilder {
|
||||||
|
|||||||
@@ -19,8 +19,6 @@ import com.google.common.collect.Lists;
|
|||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Builder pattern for building {@link TargetRequestBody}.
|
* Builder pattern for building {@link TargetRequestBody}.
|
||||||
*
|
|
||||||
* @author Jonathan Knoblauch
|
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class TargetBuilder {
|
public class TargetBuilder {
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ public class CreateStartedRolloutExample {
|
|||||||
private static final String SM_MODULE_TYPE = "firmware";
|
private static final String SM_MODULE_TYPE = "firmware";
|
||||||
|
|
||||||
/* known distribution set type name and key */
|
/* known distribution set type name and key */
|
||||||
private static final String DS_MODULE_TYPE = "firmware";
|
private static final String DS_MODULE_TYPE = SM_MODULE_TYPE;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private DistributionSetResourceClient distributionSetResource;
|
private DistributionSetResourceClient distributionSetResource;
|
||||||
|
|||||||
@@ -41,13 +41,13 @@ public class GettingStartedDefaultScenario {
|
|||||||
private static final String SM_MODULE_TYPE = "gettingstarted";
|
private static final String SM_MODULE_TYPE = "gettingstarted";
|
||||||
|
|
||||||
/* known distribution set type name and key */
|
/* known distribution set type name and key */
|
||||||
private static final String DS_MODULE_TYPE = "gettingstarted";
|
private static final String DS_MODULE_TYPE = SM_MODULE_TYPE;
|
||||||
|
|
||||||
/* known distribution name of this getting started example */
|
/* known distribution name of this getting started example */
|
||||||
private static final String SM_EXAMPLE_NAME = "gettingstarted-example";
|
private static final String SM_EXAMPLE_NAME = "gettingstarted-example";
|
||||||
|
|
||||||
/* known distribution name of this getting started example */
|
/* known distribution name of this getting started example */
|
||||||
private static final String DS_EXAMPLE_NAME = "gettingstarted-example";
|
private static final String DS_EXAMPLE_NAME = SM_EXAMPLE_NAME;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private DistributionSetResourceClient distributionSetResource;
|
private DistributionSetResourceClient distributionSetResource;
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ package org.eclipse.hawkbit.autoconfigure.security;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.Collections;
|
|
||||||
|
|
||||||
import javax.annotation.PostConstruct;
|
import javax.annotation.PostConstruct;
|
||||||
import javax.servlet.Filter;
|
import javax.servlet.Filter;
|
||||||
@@ -35,6 +34,7 @@ import org.eclipse.hawkbit.security.ControllerTenantAwareAuthenticationDetailsSo
|
|||||||
import org.eclipse.hawkbit.security.DdiSecurityProperties;
|
import org.eclipse.hawkbit.security.DdiSecurityProperties;
|
||||||
import org.eclipse.hawkbit.security.DosFilter;
|
import org.eclipse.hawkbit.security.DosFilter;
|
||||||
import org.eclipse.hawkbit.security.HawkbitSecurityProperties;
|
import org.eclipse.hawkbit.security.HawkbitSecurityProperties;
|
||||||
|
import org.eclipse.hawkbit.security.HttpControllerPreAuthenticateAnonymousDownloadFilter;
|
||||||
import org.eclipse.hawkbit.security.HttpControllerPreAuthenticateSecurityTokenFilter;
|
import org.eclipse.hawkbit.security.HttpControllerPreAuthenticateSecurityTokenFilter;
|
||||||
import org.eclipse.hawkbit.security.HttpControllerPreAuthenticatedGatewaySecurityTokenFilter;
|
import org.eclipse.hawkbit.security.HttpControllerPreAuthenticatedGatewaySecurityTokenFilter;
|
||||||
import org.eclipse.hawkbit.security.HttpControllerPreAuthenticatedSecurityHeaderFilter;
|
import org.eclipse.hawkbit.security.HttpControllerPreAuthenticatedSecurityHeaderFilter;
|
||||||
@@ -83,6 +83,8 @@ import org.vaadin.spring.security.web.VaadinRedirectStrategy;
|
|||||||
import org.vaadin.spring.security.web.authentication.VaadinAuthenticationSuccessHandler;
|
import org.vaadin.spring.security.web.authentication.VaadinAuthenticationSuccessHandler;
|
||||||
import org.vaadin.spring.security.web.authentication.VaadinUrlAuthenticationSuccessHandler;
|
import org.vaadin.spring.security.web.authentication.VaadinUrlAuthenticationSuccessHandler;
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* All configurations related to SP authentication and authorization layer.
|
* All configurations related to SP authentication and authorization layer.
|
||||||
*
|
*
|
||||||
@@ -147,6 +149,12 @@ public class SecurityManagedConfiguration {
|
|||||||
gatewaySecurityTokenFilter.setCheckForPrincipalChanges(true);
|
gatewaySecurityTokenFilter.setCheckForPrincipalChanges(true);
|
||||||
gatewaySecurityTokenFilter.setAuthenticationDetailsSource(authenticationDetailsSource);
|
gatewaySecurityTokenFilter.setAuthenticationDetailsSource(authenticationDetailsSource);
|
||||||
|
|
||||||
|
final HttpControllerPreAuthenticateAnonymousDownloadFilter controllerAnonymousDownloadFilter = new HttpControllerPreAuthenticateAnonymousDownloadFilter(
|
||||||
|
tenantConfigurationManagement, tenantAware, systemSecurityContext);
|
||||||
|
controllerAnonymousDownloadFilter.setAuthenticationManager(authenticationManager());
|
||||||
|
controllerAnonymousDownloadFilter.setCheckForPrincipalChanges(true);
|
||||||
|
controllerAnonymousDownloadFilter.setAuthenticationDetailsSource(authenticationDetailsSource);
|
||||||
|
|
||||||
HttpSecurity httpSec = http.csrf().disable().headers()
|
HttpSecurity httpSec = http.csrf().disable().headers()
|
||||||
.addHeaderWriter(new XFrameOptionsHeaderWriter(XFrameOptionsMode.DENY)).contentTypeOptions()
|
.addHeaderWriter(new XFrameOptionsHeaderWriter(XFrameOptionsMode.DENY)).contentTypeOptions()
|
||||||
.xssProtection().httpStrictTransportSecurity().and();
|
.xssProtection().httpStrictTransportSecurity().and();
|
||||||
@@ -159,15 +167,17 @@ public class SecurityManagedConfiguration {
|
|||||||
LOG.info(
|
LOG.info(
|
||||||
"******************\n** Anonymous controller security enabled, should only use for developing purposes **\n******************");
|
"******************\n** Anonymous controller security enabled, should only use for developing purposes **\n******************");
|
||||||
final AnonymousAuthenticationFilter anoymousFilter = new AnonymousAuthenticationFilter(
|
final AnonymousAuthenticationFilter anoymousFilter = new AnonymousAuthenticationFilter(
|
||||||
"controllerAnonymousFilter", "anonymous", Collections.singletonList(
|
"controllerAnonymousFilter", "anonymous",
|
||||||
new SimpleGrantedAuthority(SpringEvalExpressions.CONTROLLER_ROLE_ANONYMOUS)));
|
Lists.newArrayList(new SimpleGrantedAuthority(SpringEvalExpressions.CONTROLLER_ROLE_ANONYMOUS),
|
||||||
|
new SimpleGrantedAuthority(SpringEvalExpressions.CONTROLLER_DOWNLOAD_ROLE)));
|
||||||
anoymousFilter.setAuthenticationDetailsSource(authenticationDetailsSource);
|
anoymousFilter.setAuthenticationDetailsSource(authenticationDetailsSource);
|
||||||
httpSec.requestMatchers().antMatchers("/*/controller/v1/**", "/*/controller/artifacts/v1/**").and()
|
httpSec.requestMatchers().antMatchers("/*/controller/v1/**", "/*/controller/artifacts/v1/**").and()
|
||||||
.securityContext().disable().anonymous().authenticationFilter(anoymousFilter);
|
.securityContext().disable().anonymous().authenticationFilter(anoymousFilter);
|
||||||
} else {
|
} else {
|
||||||
httpSec.addFilter(securityHeaderFilter).addFilter(securityTokenFilter)
|
httpSec.addFilter(securityHeaderFilter).addFilter(securityTokenFilter)
|
||||||
.addFilter(gatewaySecurityTokenFilter).antMatcher("/*/controller/**").anonymous().disable()
|
.addFilter(gatewaySecurityTokenFilter).addFilter(controllerAnonymousDownloadFilter)
|
||||||
.authorizeRequests().anyRequest().authenticated().and().exceptionHandling()
|
.antMatcher("/*/controller/**").anonymous().disable().authorizeRequests().anyRequest()
|
||||||
|
.authenticated().and().exceptionHandling()
|
||||||
.authenticationEntryPoint((request, response, authException) -> response
|
.authenticationEntryPoint((request, response, authException) -> response
|
||||||
.setStatus(HttpStatus.UNAUTHORIZED.value()))
|
.setStatus(HttpStatus.UNAUTHORIZED.value()))
|
||||||
.and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
|
.and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||||
|
*
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*/
|
||||||
|
package org.eclipse.hawkbit.api;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface declaration of the {@link ArtifactUrlHandler} which generates the
|
||||||
|
* URLs to specific artifacts.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface ArtifactUrlHandler {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a generated download URL for a given artifact parameters for a
|
||||||
|
* specific protocol.
|
||||||
|
*
|
||||||
|
* @param controllerId
|
||||||
|
* the authenticated controller id
|
||||||
|
* @param softwareModuleId
|
||||||
|
* the softwareModuleId belonging to the artifact
|
||||||
|
* @param filename
|
||||||
|
* the filename of the artifact
|
||||||
|
* @param sha1Hash
|
||||||
|
* the sha1Hash of the artifact
|
||||||
|
* @param protocol
|
||||||
|
* the protocol the URL should be generated
|
||||||
|
* @return an URL for the given artifact parameters in a given protocol
|
||||||
|
*/
|
||||||
|
String getUrl(String controllerId, final Long softwareModuleId, final String filename, final String sha1Hash,
|
||||||
|
final UrlProtocol protocol);
|
||||||
|
}
|
||||||
@@ -6,13 +6,13 @@
|
|||||||
* which accompanies this distribution, and is available at
|
* which accompanies this distribution, and is available at
|
||||||
* http://www.eclipse.org/legal/epl-v10.html
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
*/
|
*/
|
||||||
package org.eclipse.hawkbit.util;
|
package org.eclipse.hawkbit.api;
|
||||||
|
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Artifact handler properties class for holding all supported protocols with
|
||||||
*
|
* host, ip, port and download pattern.
|
||||||
*/
|
*/
|
||||||
@ConfigurationProperties("hawkbit.artifact.url")
|
@ConfigurationProperties("hawkbit.artifact.url")
|
||||||
public class ArtifactUrlHandlerProperties {
|
public class ArtifactUrlHandlerProperties {
|
||||||
@@ -23,23 +23,14 @@ public class ArtifactUrlHandlerProperties {
|
|||||||
private final Https https = new Https();
|
private final Https https = new Https();
|
||||||
private final Coap coap = new Coap();
|
private final Coap coap = new Coap();
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the http
|
|
||||||
*/
|
|
||||||
public Http getHttp() {
|
public Http getHttp() {
|
||||||
return http;
|
return http;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the https
|
|
||||||
*/
|
|
||||||
public Https getHttps() {
|
public Https getHttps() {
|
||||||
return https;
|
return https;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the coap
|
|
||||||
*/
|
|
||||||
public Coap getCoap() {
|
public Coap getCoap() {
|
||||||
return coap;
|
return coap;
|
||||||
}
|
}
|
||||||
@@ -66,9 +57,6 @@ public class ArtifactUrlHandlerProperties {
|
|||||||
/**
|
/**
|
||||||
* Interface for declaring common properties through all supported protocols
|
* Interface for declaring common properties through all supported protocols
|
||||||
* pattern.
|
* pattern.
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public interface ProtocolProperties {
|
public interface ProtocolProperties {
|
||||||
/**
|
/**
|
||||||
@@ -94,9 +82,6 @@ public class ArtifactUrlHandlerProperties {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Object to hold the properties for the HTTP protocol.
|
* Object to hold the properties for the HTTP protocol.
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public static class Http implements ProtocolProperties {
|
public static class Http implements ProtocolProperties {
|
||||||
private String hostname = LOCALHOST;
|
private String hostname = LOCALHOST;
|
||||||
@@ -108,66 +93,38 @@ public class ArtifactUrlHandlerProperties {
|
|||||||
*/
|
*/
|
||||||
private String pattern = "{protocol}://{hostname}:{port}/{tenant}/controller/v1/{targetId}/softwaremodules/{softwareModuleId}/artifacts/{artifactFileName}";
|
private String pattern = "{protocol}://{hostname}:{port}/{tenant}/controller/v1/{targetId}/softwaremodules/{softwareModuleId}/artifacts/{artifactFileName}";
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the hostname
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public String getHostname() {
|
public String getHostname() {
|
||||||
return hostname;
|
return hostname;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param hostname
|
|
||||||
* the hostname to set
|
|
||||||
*/
|
|
||||||
public void setHostname(final String hostname) {
|
public void setHostname(final String hostname) {
|
||||||
this.hostname = hostname;
|
this.hostname = hostname;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the ip
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public String getIp() {
|
public String getIp() {
|
||||||
return ip;
|
return ip;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param ip
|
|
||||||
* the ip to set
|
|
||||||
*/
|
|
||||||
public void setIp(final String ip) {
|
public void setIp(final String ip) {
|
||||||
this.ip = ip;
|
this.ip = ip;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the urlPattern
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public String getPattern() {
|
public String getPattern() {
|
||||||
return pattern;
|
return pattern;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param urlPattern
|
|
||||||
* the urlPattern to set
|
|
||||||
*/
|
|
||||||
public void setPattern(final String urlPattern) {
|
public void setPattern(final String urlPattern) {
|
||||||
this.pattern = urlPattern;
|
this.pattern = urlPattern;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the port
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public String getPort() {
|
public String getPort() {
|
||||||
return port;
|
return port;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param port
|
|
||||||
* the port to set
|
|
||||||
*/
|
|
||||||
public void setPort(final String port) {
|
public void setPort(final String port) {
|
||||||
this.port = port;
|
this.port = port;
|
||||||
}
|
}
|
||||||
@@ -175,9 +132,6 @@ public class ArtifactUrlHandlerProperties {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Object to hold the properties for the HTTP protocol.
|
* Object to hold the properties for the HTTP protocol.
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public static class Https implements ProtocolProperties {
|
public static class Https implements ProtocolProperties {
|
||||||
private String hostname = LOCALHOST;
|
private String hostname = LOCALHOST;
|
||||||
@@ -189,66 +143,38 @@ public class ArtifactUrlHandlerProperties {
|
|||||||
*/
|
*/
|
||||||
private String pattern = "{protocol}://{hostname}:{port}/{tenant}/controller/v1/{targetId}/softwaremodules/{softwareModuleId}/artifacts/{artifactFileName}";
|
private String pattern = "{protocol}://{hostname}:{port}/{tenant}/controller/v1/{targetId}/softwaremodules/{softwareModuleId}/artifacts/{artifactFileName}";
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the hostname
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public String getHostname() {
|
public String getHostname() {
|
||||||
return hostname;
|
return hostname;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param hostname
|
|
||||||
* the hostname to set
|
|
||||||
*/
|
|
||||||
public void setHostname(final String hostname) {
|
public void setHostname(final String hostname) {
|
||||||
this.hostname = hostname;
|
this.hostname = hostname;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the ip
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public String getIp() {
|
public String getIp() {
|
||||||
return ip;
|
return ip;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param ip
|
|
||||||
* the ip to set
|
|
||||||
*/
|
|
||||||
public void setIp(final String ip) {
|
public void setIp(final String ip) {
|
||||||
this.ip = ip;
|
this.ip = ip;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the urlPattern
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public String getPattern() {
|
public String getPattern() {
|
||||||
return pattern;
|
return pattern;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param urlPattern
|
|
||||||
* the urlPattern to set
|
|
||||||
*/
|
|
||||||
public void setPattern(final String urlPattern) {
|
public void setPattern(final String urlPattern) {
|
||||||
this.pattern = urlPattern;
|
this.pattern = urlPattern;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the port
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public String getPort() {
|
public String getPort() {
|
||||||
return port;
|
return port;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param port
|
|
||||||
* the port to set
|
|
||||||
*/
|
|
||||||
public void setPort(final String port) {
|
public void setPort(final String port) {
|
||||||
this.port = port;
|
this.port = port;
|
||||||
}
|
}
|
||||||
@@ -256,9 +182,6 @@ public class ArtifactUrlHandlerProperties {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Object to hold the properties for the HTTP protocol.
|
* Object to hold the properties for the HTTP protocol.
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public static class Coap implements ProtocolProperties {
|
public static class Coap implements ProtocolProperties {
|
||||||
private String hostname = LOCALHOST;
|
private String hostname = LOCALHOST;
|
||||||
@@ -270,68 +193,41 @@ public class ArtifactUrlHandlerProperties {
|
|||||||
*/
|
*/
|
||||||
private String pattern = "{protocol}://{ip}:{port}/fw/{tenant}/{targetId}/sha1/{artifactSHA1}";
|
private String pattern = "{protocol}://{ip}:{port}/fw/{tenant}/{targetId}/sha1/{artifactSHA1}";
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the hostname
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public String getHostname() {
|
public String getHostname() {
|
||||||
return hostname;
|
return hostname;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param hostname
|
|
||||||
* the hostname to set
|
|
||||||
*/
|
|
||||||
public void setHostname(final String hostname) {
|
public void setHostname(final String hostname) {
|
||||||
this.hostname = hostname;
|
this.hostname = hostname;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the ip
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public String getIp() {
|
public String getIp() {
|
||||||
return ip;
|
return ip;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param ip
|
|
||||||
* the ip to set
|
|
||||||
*/
|
|
||||||
public void setIp(final String ip) {
|
public void setIp(final String ip) {
|
||||||
this.ip = ip;
|
this.ip = ip;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the urlPattern
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public String getPattern() {
|
public String getPattern() {
|
||||||
return pattern;
|
return pattern;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param urlPattern
|
|
||||||
* the urlPattern to set
|
|
||||||
*/
|
|
||||||
public void setPattern(final String urlPattern) {
|
public void setPattern(final String urlPattern) {
|
||||||
this.pattern = urlPattern;
|
this.pattern = urlPattern;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the port
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public String getPort() {
|
public String getPort() {
|
||||||
return port;
|
return port;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param port
|
|
||||||
* the port to set
|
|
||||||
*/
|
|
||||||
public void setPort(final String port) {
|
public void setPort(final String port) {
|
||||||
this.port = port;
|
this.port = port;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -6,17 +6,15 @@
|
|||||||
* which accompanies this distribution, and is available at
|
* which accompanies this distribution, and is available at
|
||||||
* http://www.eclipse.org/legal/epl-v10.html
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
*/
|
*/
|
||||||
package org.eclipse.hawkbit.util;
|
package org.eclipse.hawkbit.api;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.eclipse.hawkbit.dmf.json.model.Artifact;
|
import org.eclipse.hawkbit.api.ArtifactUrlHandlerProperties.ProtocolProperties;
|
||||||
import org.eclipse.hawkbit.repository.model.LocalArtifact;
|
|
||||||
import org.eclipse.hawkbit.tenancy.TenantAware;
|
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||||
import org.eclipse.hawkbit.util.ArtifactUrlHandlerProperties.ProtocolProperties;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
@@ -24,8 +22,8 @@ import org.springframework.stereotype.Component;
|
|||||||
import com.google.common.base.Strings;
|
import com.google.common.base.Strings;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Implementation for ArtifactUrlHandler for creating urls to download resource
|
||||||
*
|
* based on pattern.
|
||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
@EnableConfigurationProperties(ArtifactUrlHandlerProperties.class)
|
@EnableConfigurationProperties(ArtifactUrlHandlerProperties.class)
|
||||||
@@ -48,7 +46,9 @@ public class PropertyBasedArtifactUrlHandler implements ArtifactUrlHandler {
|
|||||||
private TenantAware tenantAware;
|
private TenantAware tenantAware;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getUrl(final String targetId, final LocalArtifact artifact, final Artifact.UrlProtocol protocol) {
|
public String getUrl(final String targetId, final Long softwareModuleId, final String filename,
|
||||||
|
final String sha1Hash, final UrlProtocol protocol) {
|
||||||
|
|
||||||
final String protocolString = protocol.name().toLowerCase();
|
final String protocolString = protocol.name().toLowerCase();
|
||||||
final ProtocolProperties properties = urlHandlerProperties.getProperties(protocolString);
|
final ProtocolProperties properties = urlHandlerProperties.getProperties(protocolString);
|
||||||
if (properties == null || properties.getPattern() == null) {
|
if (properties == null || properties.getPattern() == null) {
|
||||||
@@ -56,8 +56,8 @@ public class PropertyBasedArtifactUrlHandler implements ArtifactUrlHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
String urlPattern = properties.getPattern();
|
String urlPattern = properties.getPattern();
|
||||||
final Set<Entry<String, String>> entrySet = getReplaceMap(targetId, artifact, protocolString, properties)
|
final Set<Entry<String, String>> entrySet = getReplaceMap(targetId, softwareModuleId, filename, sha1Hash,
|
||||||
.entrySet();
|
protocolString, properties).entrySet();
|
||||||
for (final Entry<String, String> entry : entrySet) {
|
for (final Entry<String, String> entry : entrySet) {
|
||||||
if (entry.getKey().equals(PORT_PLACEHOLDER)) {
|
if (entry.getKey().equals(PORT_PLACEHOLDER)) {
|
||||||
urlPattern = urlPattern.replace(":{" + entry.getKey() + "}",
|
urlPattern = urlPattern.replace(":{" + entry.getKey() + "}",
|
||||||
@@ -69,18 +69,18 @@ public class PropertyBasedArtifactUrlHandler implements ArtifactUrlHandler {
|
|||||||
return urlPattern;
|
return urlPattern;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<String, String> getReplaceMap(final String targetId, final LocalArtifact artifact,
|
private Map<String, String> getReplaceMap(final String targetId, final Long softwareModuleId, final String filename,
|
||||||
final String protocol, final ProtocolProperties properties) {
|
final String sha1Hash, final String protocol, final ProtocolProperties properties) {
|
||||||
final Map<String, String> replaceMap = new HashMap<>();
|
final Map<String, String> replaceMap = new HashMap<>();
|
||||||
replaceMap.put(IP_PLACEHOLDER, properties.getIp());
|
replaceMap.put(IP_PLACEHOLDER, properties.getIp());
|
||||||
replaceMap.put(HOSTNAME_PLACEHOLDER, properties.getHostname());
|
replaceMap.put(HOSTNAME_PLACEHOLDER, properties.getHostname());
|
||||||
replaceMap.put(ARTIFACT_FILENAME_PLACEHOLDER, artifact.getFilename());
|
replaceMap.put(ARTIFACT_FILENAME_PLACEHOLDER, filename);
|
||||||
replaceMap.put(ARTIFACT_SHA1_PLACEHOLDER, artifact.getSha1Hash());
|
replaceMap.put(ARTIFACT_SHA1_PLACEHOLDER, sha1Hash);
|
||||||
replaceMap.put(PROTOCOL_PLACEHOLDER, protocol);
|
replaceMap.put(PROTOCOL_PLACEHOLDER, protocol);
|
||||||
replaceMap.put(PORT_PLACEHOLDER, properties.getPort());
|
replaceMap.put(PORT_PLACEHOLDER, properties.getPort());
|
||||||
replaceMap.put(TENANT_PLACEHOLDER, tenantAware.getCurrentTenant());
|
replaceMap.put(TENANT_PLACEHOLDER, tenantAware.getCurrentTenant());
|
||||||
replaceMap.put(TARGET_ID_PLACEHOLDER, targetId);
|
replaceMap.put(TARGET_ID_PLACEHOLDER, targetId);
|
||||||
replaceMap.put(SOFTWARE_MODULE_ID_PLACDEHOLDER, String.valueOf(artifact.getSoftwareModule().getId()));
|
replaceMap.put(SOFTWARE_MODULE_ID_PLACDEHOLDER, String.valueOf(softwareModuleId));
|
||||||
return replaceMap;
|
return replaceMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||||
|
*
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*/
|
||||||
|
package org.eclipse.hawkbit.api;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represented the supported protocols for artifact url's.
|
||||||
|
*/
|
||||||
|
public enum UrlProtocol {
|
||||||
|
COAP, HTTP, HTTPS
|
||||||
|
}
|
||||||
@@ -30,40 +30,60 @@ public enum TenantConfigurationKey {
|
|||||||
/**
|
/**
|
||||||
* boolean value {@code true} {@code false}.
|
* boolean value {@code true} {@code false}.
|
||||||
*/
|
*/
|
||||||
AUTHENTICATION_MODE_HEADER_ENABLED("authentication.header.enabled", "hawkbit.server.ddi.security.authentication.header.enabled", Boolean.class, Boolean.FALSE.toString(), TenantConfigurationBooleanValidator.class),
|
AUTHENTICATION_MODE_HEADER_ENABLED("authentication.header.enabled",
|
||||||
|
"hawkbit.server.ddi.security.authentication.header.enabled", Boolean.class, Boolean.FALSE.toString(),
|
||||||
|
TenantConfigurationBooleanValidator.class),
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
AUTHENTICATION_MODE_HEADER_AUTHORITY_NAME("authentication.header.authority", "hawkbit.server.ddi.security.authentication.header.authority", String.class, Boolean.FALSE.toString(), TenantConfigurationStringValidator.class),
|
AUTHENTICATION_MODE_HEADER_AUTHORITY_NAME("authentication.header.authority",
|
||||||
|
"hawkbit.server.ddi.security.authentication.header.authority", String.class, Boolean.FALSE.toString(),
|
||||||
|
TenantConfigurationStringValidator.class),
|
||||||
/**
|
/**
|
||||||
* boolean value {@code true} {@code false}.
|
* boolean value {@code true} {@code false}.
|
||||||
*/
|
*/
|
||||||
AUTHENTICATION_MODE_TARGET_SECURITY_TOKEN_ENABLED("authentication.targettoken.enabled", "hawkbit.server.ddi.security.authentication.targettoken.enabled", Boolean.class, Boolean.FALSE.toString(), TenantConfigurationBooleanValidator.class),
|
AUTHENTICATION_MODE_TARGET_SECURITY_TOKEN_ENABLED("authentication.targettoken.enabled",
|
||||||
|
"hawkbit.server.ddi.security.authentication.targettoken.enabled", Boolean.class, Boolean.FALSE.toString(),
|
||||||
|
TenantConfigurationBooleanValidator.class),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* boolean value {@code true} {@code false}.
|
* boolean value {@code true} {@code false}.
|
||||||
*/
|
*/
|
||||||
AUTHENTICATION_MODE_GATEWAY_SECURITY_TOKEN_ENABLED("authentication.gatewaytoken.enabled", "hawkbit.server.ddi.security.authentication.gatewaytoken.enabled", Boolean.class, Boolean.FALSE.toString(), TenantConfigurationBooleanValidator.class),
|
AUTHENTICATION_MODE_GATEWAY_SECURITY_TOKEN_ENABLED("authentication.gatewaytoken.enabled",
|
||||||
|
"hawkbit.server.ddi.security.authentication.gatewaytoken.enabled", Boolean.class, Boolean.FALSE.toString(),
|
||||||
|
TenantConfigurationBooleanValidator.class),
|
||||||
/**
|
/**
|
||||||
* string value which holds the name of the security token key.
|
* string value which holds the name of the security token key.
|
||||||
*/
|
*/
|
||||||
AUTHENTICATION_MODE_GATEWAY_SECURITY_TOKEN_NAME("authentication.gatewaytoken.name", "hawkbit.server.ddi.security.authentication.gatewaytoken.name", String.class, null, TenantConfigurationStringValidator.class),
|
AUTHENTICATION_MODE_GATEWAY_SECURITY_TOKEN_NAME("authentication.gatewaytoken.name",
|
||||||
|
"hawkbit.server.ddi.security.authentication.gatewaytoken.name", String.class, null,
|
||||||
|
TenantConfigurationStringValidator.class),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* string value which holds the actual security-key of the gateway security
|
* string value which holds the actual security-key of the gateway security
|
||||||
* token.
|
* token.
|
||||||
*/
|
*/
|
||||||
AUTHENTICATION_MODE_GATEWAY_SECURITY_TOKEN_KEY("authentication.gatewaytoken.key", "hawkbit.server.ddi.security.authentication.gatewaytoken.key", String.class, null, TenantConfigurationStringValidator.class),
|
AUTHENTICATION_MODE_GATEWAY_SECURITY_TOKEN_KEY("authentication.gatewaytoken.key",
|
||||||
|
"hawkbit.server.ddi.security.authentication.gatewaytoken.key", String.class, null,
|
||||||
|
TenantConfigurationStringValidator.class),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* string value which holds the polling time interval in the format HH:mm:ss
|
* string value which holds the polling time interval in the format HH:mm:ss
|
||||||
*/
|
*/
|
||||||
POLLING_TIME_INTERVAL("pollingTime", "hawkbit.controller.pollingTime", String.class, null, TenantConfigurationPollingDurationValidator.class),
|
POLLING_TIME_INTERVAL("pollingTime", "hawkbit.controller.pollingTime", String.class, null,
|
||||||
|
TenantConfigurationPollingDurationValidator.class),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* string value which holds the polling time interval in the format HH:mm:ss
|
* string value which holds the polling time interval in the format HH:mm:ss
|
||||||
*/
|
*/
|
||||||
POLLING_OVERDUE_TIME_INTERVAL("pollingOverdueTime", "hawkbit.controller.pollingOverdueTime", String.class, null, TenantConfigurationPollingDurationValidator.class);
|
POLLING_OVERDUE_TIME_INTERVAL("pollingOverdueTime", "hawkbit.controller.pollingOverdueTime", String.class, null,
|
||||||
|
TenantConfigurationPollingDurationValidator.class),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* boolean value {@code true} {@code false}.
|
||||||
|
*/
|
||||||
|
ANONYMOUS_DOWNLOAD_MODE_ENABLED("anonymous.download.enabled", "hawkbit.server.download.anonymous.enabled",
|
||||||
|
Boolean.class, Boolean.FALSE.toString(), TenantConfigurationBooleanValidator.class);
|
||||||
|
|
||||||
private final String keyName;
|
private final String keyName;
|
||||||
private final String defaultKeyName;
|
private final String defaultKeyName;
|
||||||
|
|||||||
@@ -25,6 +25,11 @@
|
|||||||
<groupId>org.eclipse.hawkbit</groupId>
|
<groupId>org.eclipse.hawkbit</groupId>
|
||||||
<artifactId>hawkbit-repository</artifactId>
|
<artifactId>hawkbit-repository</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.hawkbit</groupId>
|
||||||
|
<artifactId>hawkbit-core</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.eclipse.hawkbit</groupId>
|
<groupId>org.eclipse.hawkbit</groupId>
|
||||||
|
|||||||
@@ -13,12 +13,14 @@ import java.util.List;
|
|||||||
|
|
||||||
import javax.annotation.PostConstruct;
|
import javax.annotation.PostConstruct;
|
||||||
|
|
||||||
import org.eclipse.hawkbit.dmf.json.model.TenantSecruityToken;
|
import org.eclipse.hawkbit.dmf.json.model.TenantSecurityToken;
|
||||||
import org.eclipse.hawkbit.im.authentication.TenantAwareAuthenticationDetails;
|
import org.eclipse.hawkbit.im.authentication.TenantAwareAuthenticationDetails;
|
||||||
import org.eclipse.hawkbit.repository.ControllerManagement;
|
import org.eclipse.hawkbit.repository.ControllerManagement;
|
||||||
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
|
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
|
||||||
import org.eclipse.hawkbit.security.CoapAnonymousPreAuthenticatedFilter;
|
import org.eclipse.hawkbit.security.CoapAnonymousPreAuthenticatedFilter;
|
||||||
import org.eclipse.hawkbit.security.ControllerPreAuthenticateSecurityTokenFilter;
|
import org.eclipse.hawkbit.security.ControllerPreAuthenticateSecurityTokenFilter;
|
||||||
|
import org.eclipse.hawkbit.security.ControllerPreAuthenticatedAnonymousDownload;
|
||||||
|
import org.eclipse.hawkbit.security.ControllerPreAuthenticatedAnonymousFilter;
|
||||||
import org.eclipse.hawkbit.security.ControllerPreAuthenticatedGatewaySecurityTokenFilter;
|
import org.eclipse.hawkbit.security.ControllerPreAuthenticatedGatewaySecurityTokenFilter;
|
||||||
import org.eclipse.hawkbit.security.ControllerPreAuthenticatedSecurityHeaderFilter;
|
import org.eclipse.hawkbit.security.ControllerPreAuthenticatedSecurityHeaderFilter;
|
||||||
import org.eclipse.hawkbit.security.DdiSecurityProperties;
|
import org.eclipse.hawkbit.security.DdiSecurityProperties;
|
||||||
@@ -90,6 +92,11 @@ public class AmqpControllerAuthentfication {
|
|||||||
tenantConfigurationManagement, controllerManagement, tenantAware, systemSecurityContext);
|
tenantConfigurationManagement, controllerManagement, tenantAware, systemSecurityContext);
|
||||||
filterChain.add(securityTokenFilter);
|
filterChain.add(securityTokenFilter);
|
||||||
|
|
||||||
|
final ControllerPreAuthenticatedAnonymousDownload anonymousDownloadFilter = new ControllerPreAuthenticatedAnonymousDownload(
|
||||||
|
tenantConfigurationManagement, tenantAware, systemSecurityContext);
|
||||||
|
filterChain.add(anonymousDownloadFilter);
|
||||||
|
|
||||||
|
filterChain.add(new ControllerPreAuthenticatedAnonymousFilter(ddiSecruityProperties));
|
||||||
filterChain.add(new CoapAnonymousPreAuthenticatedFilter());
|
filterChain.add(new CoapAnonymousPreAuthenticatedFilter());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,7 +107,7 @@ public class AmqpControllerAuthentfication {
|
|||||||
* the authentication request object
|
* the authentication request object
|
||||||
* @return the authentfication object
|
* @return the authentfication object
|
||||||
*/
|
*/
|
||||||
public Authentication doAuthenticate(final TenantSecruityToken secruityToken) {
|
public Authentication doAuthenticate(final TenantSecurityToken secruityToken) {
|
||||||
PreAuthenticatedAuthenticationToken authentication = new PreAuthenticatedAuthenticationToken(null, null);
|
PreAuthenticatedAuthenticationToken authentication = new PreAuthenticatedAuthenticationToken(null, null);
|
||||||
for (final PreAuthenficationFilter filter : filterChain) {
|
for (final PreAuthenficationFilter filter : filterChain) {
|
||||||
final PreAuthenticatedAuthenticationToken authenticationRest = createAuthentication(filter, secruityToken);
|
final PreAuthenticatedAuthenticationToken authenticationRest = createAuthentication(filter, secruityToken);
|
||||||
@@ -115,7 +122,7 @@ public class AmqpControllerAuthentfication {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static PreAuthenticatedAuthenticationToken createAuthentication(final PreAuthenficationFilter filter,
|
private static PreAuthenticatedAuthenticationToken createAuthentication(final PreAuthenficationFilter filter,
|
||||||
final TenantSecruityToken secruityToken) {
|
final TenantSecurityToken secruityToken) {
|
||||||
|
|
||||||
if (!filter.isEnable(secruityToken)) {
|
if (!filter.isEnable(secruityToken)) {
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ import java.util.Collections;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import org.eclipse.hawkbit.api.ArtifactUrlHandler;
|
||||||
|
import org.eclipse.hawkbit.api.UrlProtocol;
|
||||||
import org.eclipse.hawkbit.dmf.amqp.api.EventTopic;
|
import org.eclipse.hawkbit.dmf.amqp.api.EventTopic;
|
||||||
import org.eclipse.hawkbit.dmf.amqp.api.MessageHeaderKey;
|
import org.eclipse.hawkbit.dmf.amqp.api.MessageHeaderKey;
|
||||||
import org.eclipse.hawkbit.dmf.amqp.api.MessageType;
|
import org.eclipse.hawkbit.dmf.amqp.api.MessageType;
|
||||||
@@ -25,7 +27,6 @@ import org.eclipse.hawkbit.eventbus.EventSubscriber;
|
|||||||
import org.eclipse.hawkbit.eventbus.event.CancelTargetAssignmentEvent;
|
import org.eclipse.hawkbit.eventbus.event.CancelTargetAssignmentEvent;
|
||||||
import org.eclipse.hawkbit.eventbus.event.TargetAssignDistributionSetEvent;
|
import org.eclipse.hawkbit.eventbus.event.TargetAssignDistributionSetEvent;
|
||||||
import org.eclipse.hawkbit.repository.model.LocalArtifact;
|
import org.eclipse.hawkbit.repository.model.LocalArtifact;
|
||||||
import org.eclipse.hawkbit.util.ArtifactUrlHandler;
|
|
||||||
import org.eclipse.hawkbit.util.IpUtil;
|
import org.eclipse.hawkbit.util.IpUtil;
|
||||||
import org.springframework.amqp.core.Message;
|
import org.springframework.amqp.core.Message;
|
||||||
import org.springframework.amqp.core.MessageProperties;
|
import org.springframework.amqp.core.MessageProperties;
|
||||||
@@ -152,12 +153,16 @@ public class AmqpMessageDispatcherService extends BaseAmqpService {
|
|||||||
|
|
||||||
private Artifact convertArtifact(final String targetId, final LocalArtifact localArtifact) {
|
private Artifact convertArtifact(final String targetId, final LocalArtifact localArtifact) {
|
||||||
final Artifact artifact = new Artifact();
|
final Artifact artifact = new Artifact();
|
||||||
|
|
||||||
artifact.getUrls().put(Artifact.UrlProtocol.COAP,
|
artifact.getUrls().put(Artifact.UrlProtocol.COAP,
|
||||||
artifactUrlHandler.getUrl(targetId, localArtifact, Artifact.UrlProtocol.COAP));
|
artifactUrlHandler.getUrl(targetId, localArtifact.getSoftwareModule().getId(),
|
||||||
|
localArtifact.getFilename(), localArtifact.getSha1Hash(), UrlProtocol.COAP));
|
||||||
artifact.getUrls().put(Artifact.UrlProtocol.HTTP,
|
artifact.getUrls().put(Artifact.UrlProtocol.HTTP,
|
||||||
artifactUrlHandler.getUrl(targetId, localArtifact, Artifact.UrlProtocol.HTTP));
|
artifactUrlHandler.getUrl(targetId, localArtifact.getSoftwareModule().getId(),
|
||||||
|
localArtifact.getFilename(), localArtifact.getSha1Hash(), UrlProtocol.HTTP));
|
||||||
artifact.getUrls().put(Artifact.UrlProtocol.HTTPS,
|
artifact.getUrls().put(Artifact.UrlProtocol.HTTPS,
|
||||||
artifactUrlHandler.getUrl(targetId, localArtifact, Artifact.UrlProtocol.HTTPS));
|
artifactUrlHandler.getUrl(targetId, localArtifact.getSoftwareModule().getId(),
|
||||||
|
localArtifact.getFilename(), localArtifact.getSha1Hash(), UrlProtocol.HTTPS));
|
||||||
|
|
||||||
artifact.setFilename(localArtifact.getFilename());
|
artifact.setFilename(localArtifact.getFilename());
|
||||||
artifact.setHashes(new ArtifactHash(localArtifact.getSha1Hash(), null));
|
artifact.setHashes(new ArtifactHash(localArtifact.getSha1Hash(), null));
|
||||||
|
|||||||
@@ -28,7 +28,8 @@ import org.eclipse.hawkbit.dmf.json.model.ActionUpdateStatus;
|
|||||||
import org.eclipse.hawkbit.dmf.json.model.Artifact;
|
import org.eclipse.hawkbit.dmf.json.model.Artifact;
|
||||||
import org.eclipse.hawkbit.dmf.json.model.ArtifactHash;
|
import org.eclipse.hawkbit.dmf.json.model.ArtifactHash;
|
||||||
import org.eclipse.hawkbit.dmf.json.model.DownloadResponse;
|
import org.eclipse.hawkbit.dmf.json.model.DownloadResponse;
|
||||||
import org.eclipse.hawkbit.dmf.json.model.TenantSecruityToken;
|
import org.eclipse.hawkbit.dmf.json.model.TenantSecurityToken;
|
||||||
|
import org.eclipse.hawkbit.dmf.json.model.TenantSecurityToken.FileResource;
|
||||||
import org.eclipse.hawkbit.eventbus.event.TargetAssignDistributionSetEvent;
|
import org.eclipse.hawkbit.eventbus.event.TargetAssignDistributionSetEvent;
|
||||||
import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions;
|
import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions;
|
||||||
import org.eclipse.hawkbit.im.authentication.TenantAwareAuthenticationDetails;
|
import org.eclipse.hawkbit.im.authentication.TenantAwareAuthenticationDetails;
|
||||||
@@ -157,25 +158,28 @@ public class AmqpMessageHandlerService extends BaseAmqpService {
|
|||||||
private Message handleAuthentifiactionMessage(final Message message) {
|
private Message handleAuthentifiactionMessage(final Message message) {
|
||||||
final DownloadResponse authentificationResponse = new DownloadResponse();
|
final DownloadResponse authentificationResponse = new DownloadResponse();
|
||||||
final MessageProperties messageProperties = message.getMessageProperties();
|
final MessageProperties messageProperties = message.getMessageProperties();
|
||||||
final TenantSecruityToken secruityToken = convertMessage(message, TenantSecruityToken.class);
|
final TenantSecurityToken secruityToken = convertMessage(message, TenantSecurityToken.class);
|
||||||
final String sha1 = secruityToken.getSha1();
|
final FileResource fileResource = secruityToken.getFileResource();
|
||||||
try {
|
try {
|
||||||
SecurityContextHolder.getContext().setAuthentication(authenticationManager.doAuthenticate(secruityToken));
|
SecurityContextHolder.getContext().setAuthentication(authenticationManager.doAuthenticate(secruityToken));
|
||||||
final LocalArtifact localArtifact = artifactManagement
|
|
||||||
.findFirstLocalArtifactsBySHA1(secruityToken.getSha1());
|
final LocalArtifact localArtifact = findLocalArtifactByFileResource(fileResource);
|
||||||
|
|
||||||
if (localArtifact == null) {
|
if (localArtifact == null) {
|
||||||
throw new EntityNotFoundException();
|
throw new EntityNotFoundException();
|
||||||
}
|
}
|
||||||
|
|
||||||
// check action for this download purposes, the method will throw an
|
// check action for this download purposes, the method will throw an
|
||||||
// EntityNotFoundException in case the controller is not allowed to
|
// EntityNotFoundException in case the controller is not allowed to
|
||||||
// download this file
|
// download this file because it's not assigned to an action and not
|
||||||
// because it's not assigned to an action and not assigned to this
|
// assigned to this controller. Otherwise no controllerId is set =
|
||||||
// controller.
|
// anonymous download
|
||||||
final Action action = controllerManagement.getActionForDownloadByTargetAndSoftwareModule(
|
if (secruityToken.getControllerId() != null) {
|
||||||
secruityToken.getControllerId(), localArtifact.getSoftwareModule());
|
final Action action = controllerManagement.getActionForDownloadByTargetAndSoftwareModule(
|
||||||
LOG.info("Found action for download authentication request action: {}, sha1: {}", action,
|
secruityToken.getControllerId(), localArtifact.getSoftwareModule());
|
||||||
secruityToken.getSha1());
|
LOG.info("Found action for download authentication request action: {}, resource: {}", action,
|
||||||
|
secruityToken.getFileResource());
|
||||||
|
}
|
||||||
|
|
||||||
final Artifact artifact = convertDbArtifact(artifactManagement.loadLocalArtifactBinary(localArtifact));
|
final Artifact artifact = convertDbArtifact(artifactManagement.loadLocalArtifactBinary(localArtifact));
|
||||||
if (artifact == null) {
|
if (artifact == null) {
|
||||||
@@ -183,7 +187,9 @@ public class AmqpMessageHandlerService extends BaseAmqpService {
|
|||||||
}
|
}
|
||||||
authentificationResponse.setArtifact(artifact);
|
authentificationResponse.setArtifact(artifact);
|
||||||
final String downloadId = UUID.randomUUID().toString();
|
final String downloadId = UUID.randomUUID().toString();
|
||||||
final DownloadArtifactCache downloadCache = new DownloadArtifactCache(DownloadType.BY_SHA1, sha1);
|
// SHA1 key is set, download by SHA1
|
||||||
|
final DownloadArtifactCache downloadCache = new DownloadArtifactCache(DownloadType.BY_SHA1,
|
||||||
|
localArtifact.getSha1Hash());
|
||||||
cache.put(downloadId, downloadCache);
|
cache.put(downloadId, downloadCache);
|
||||||
authentificationResponse
|
authentificationResponse
|
||||||
.setDownloadUrl(UriComponentsBuilder.fromUri(hostnameResolver.resolveHostname().toURI())
|
.setDownloadUrl(UriComponentsBuilder.fromUri(hostnameResolver.resolveHostname().toURI())
|
||||||
@@ -198,7 +204,7 @@ public class AmqpMessageHandlerService extends BaseAmqpService {
|
|||||||
authentificationResponse.setResponseCode(HttpStatus.INTERNAL_SERVER_ERROR.value());
|
authentificationResponse.setResponseCode(HttpStatus.INTERNAL_SERVER_ERROR.value());
|
||||||
authentificationResponse.setMessage("Building download URI failed");
|
authentificationResponse.setMessage("Building download URI failed");
|
||||||
} catch (final EntityNotFoundException e) {
|
} catch (final EntityNotFoundException e) {
|
||||||
final String errorMessage = "Artifact with sha1 " + sha1 + "not found ";
|
final String errorMessage = "Artifact for resource " + fileResource + "not found ";
|
||||||
LOG.warn(errorMessage, e);
|
LOG.warn(errorMessage, e);
|
||||||
authentificationResponse.setResponseCode(HttpStatus.NOT_FOUND.value());
|
authentificationResponse.setResponseCode(HttpStatus.NOT_FOUND.value());
|
||||||
authentificationResponse.setMessage(errorMessage);
|
authentificationResponse.setMessage(errorMessage);
|
||||||
@@ -207,6 +213,21 @@ public class AmqpMessageHandlerService extends BaseAmqpService {
|
|||||||
return getMessageConverter().toMessage(authentificationResponse, messageProperties);
|
return getMessageConverter().toMessage(authentificationResponse, messageProperties);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private LocalArtifact findLocalArtifactByFileResource(final FileResource fileResource) {
|
||||||
|
if (fileResource.getSha1() != null) {
|
||||||
|
return artifactManagement.findFirstLocalArtifactsBySHA1(fileResource.getSha1());
|
||||||
|
} else if (fileResource.getFilename() != null) {
|
||||||
|
return artifactManagement.findLocalArtifactByFilename(fileResource.getFilename()).stream().findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
} else if (fileResource.getSoftwareModuleFilenameResource() != null) {
|
||||||
|
return artifactManagement
|
||||||
|
.findByFilenameAndSoftwareModule(fileResource.getSoftwareModuleFilenameResource().getFilename(),
|
||||||
|
fileResource.getSoftwareModuleFilenameResource().getSoftwareModuleId())
|
||||||
|
.stream().findFirst().orElse(null);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
private static Artifact convertDbArtifact(final DbArtifact dbArtifact) {
|
private static Artifact convertDbArtifact(final DbArtifact dbArtifact) {
|
||||||
final Artifact artifact = new Artifact();
|
final Artifact artifact = new Artifact();
|
||||||
artifact.setSize(dbArtifact.getSize());
|
artifact.setSize(dbArtifact.getSize());
|
||||||
|
|||||||
@@ -1,35 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
|
||||||
*
|
|
||||||
* All rights reserved. This program and the accompanying materials
|
|
||||||
* are made available under the terms of the Eclipse Public License v1.0
|
|
||||||
* which accompanies this distribution, and is available at
|
|
||||||
* http://www.eclipse.org/legal/epl-v10.html
|
|
||||||
*/
|
|
||||||
package org.eclipse.hawkbit.util;
|
|
||||||
|
|
||||||
import org.eclipse.hawkbit.dmf.json.model.Artifact;
|
|
||||||
import org.eclipse.hawkbit.repository.model.LocalArtifact;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Interface declaration of the {@link ArtifactUrlHandler} which generates the
|
|
||||||
* URLs to specific artifacts.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
@FunctionalInterface
|
|
||||||
public interface ArtifactUrlHandler {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a generated URL for a given artifact for a specific protocol.
|
|
||||||
*
|
|
||||||
* @param controllerId
|
|
||||||
* the authentifacted controller id
|
|
||||||
* @param localArtifact
|
|
||||||
* the artifact to retrieve a URL to
|
|
||||||
* @param protocol
|
|
||||||
* the protocol the URL should be generated
|
|
||||||
* @return an URL for the given artifact in a given protocol
|
|
||||||
*/
|
|
||||||
String getUrl(String controllerId, LocalArtifact localArtifact, final Artifact.UrlProtocol protocol);
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -19,12 +19,14 @@ import static org.mockito.Mockito.when;
|
|||||||
import org.eclipse.hawkbit.dmf.amqp.api.MessageHeaderKey;
|
import org.eclipse.hawkbit.dmf.amqp.api.MessageHeaderKey;
|
||||||
import org.eclipse.hawkbit.dmf.amqp.api.MessageType;
|
import org.eclipse.hawkbit.dmf.amqp.api.MessageType;
|
||||||
import org.eclipse.hawkbit.dmf.json.model.DownloadResponse;
|
import org.eclipse.hawkbit.dmf.json.model.DownloadResponse;
|
||||||
import org.eclipse.hawkbit.dmf.json.model.TenantSecruityToken;
|
import org.eclipse.hawkbit.dmf.json.model.TenantSecurityToken;
|
||||||
|
import org.eclipse.hawkbit.dmf.json.model.TenantSecurityToken.FileResource;
|
||||||
import org.eclipse.hawkbit.repository.ArtifactManagement;
|
import org.eclipse.hawkbit.repository.ArtifactManagement;
|
||||||
import org.eclipse.hawkbit.repository.ControllerManagement;
|
import org.eclipse.hawkbit.repository.ControllerManagement;
|
||||||
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
|
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
|
||||||
import org.eclipse.hawkbit.repository.model.TenantConfigurationValue;
|
import org.eclipse.hawkbit.repository.model.TenantConfigurationValue;
|
||||||
import org.eclipse.hawkbit.security.DdiSecurityProperties;
|
import org.eclipse.hawkbit.security.DdiSecurityProperties;
|
||||||
|
import org.eclipse.hawkbit.security.DdiSecurityProperties.Authentication.Anonymous;
|
||||||
import org.eclipse.hawkbit.security.DdiSecurityProperties.Rp;
|
import org.eclipse.hawkbit.security.DdiSecurityProperties.Rp;
|
||||||
import org.eclipse.hawkbit.security.SecurityContextTenantAware;
|
import org.eclipse.hawkbit.security.SecurityContextTenantAware;
|
||||||
import org.eclipse.hawkbit.security.SystemSecurityContext;
|
import org.eclipse.hawkbit.security.SystemSecurityContext;
|
||||||
@@ -79,8 +81,14 @@ public class AmqpControllerAuthenticationTest {
|
|||||||
|
|
||||||
final DdiSecurityProperties secruityProperties = mock(DdiSecurityProperties.class);
|
final DdiSecurityProperties secruityProperties = mock(DdiSecurityProperties.class);
|
||||||
final Rp rp = mock(Rp.class);
|
final Rp rp = mock(Rp.class);
|
||||||
|
final org.eclipse.hawkbit.security.DdiSecurityProperties.Authentication ddiAuthentication = mock(
|
||||||
|
org.eclipse.hawkbit.security.DdiSecurityProperties.Authentication.class);
|
||||||
|
final Anonymous anonymous = mock(Anonymous.class);
|
||||||
when(secruityProperties.getRp()).thenReturn(rp);
|
when(secruityProperties.getRp()).thenReturn(rp);
|
||||||
when(rp.getSslIssuerHashHeader()).thenReturn("X-Ssl-Issuer-Hash-%d");
|
when(rp.getSslIssuerHashHeader()).thenReturn("X-Ssl-Issuer-Hash-%d");
|
||||||
|
when(secruityProperties.getAuthentication()).thenReturn(ddiAuthentication);
|
||||||
|
when(ddiAuthentication.getAnonymous()).thenReturn(anonymous);
|
||||||
|
when(anonymous.isEnabled()).thenReturn(false);
|
||||||
authenticationManager.setSecruityProperties(secruityProperties);
|
authenticationManager.setSecruityProperties(secruityProperties);
|
||||||
|
|
||||||
tenantConfigurationManagement = mock(TenantConfigurationManagement.class);
|
tenantConfigurationManagement = mock(TenantConfigurationManagement.class);
|
||||||
@@ -105,7 +113,8 @@ public class AmqpControllerAuthenticationTest {
|
|||||||
@Test
|
@Test
|
||||||
@Description("Tests authentication manager without principal")
|
@Description("Tests authentication manager without principal")
|
||||||
public void testAuthenticationeBadCredantialsWithoutPricipal() {
|
public void testAuthenticationeBadCredantialsWithoutPricipal() {
|
||||||
final TenantSecruityToken securityToken = new TenantSecruityToken(TENANT, CONTROLLLER_ID, "12345");
|
final TenantSecurityToken securityToken = new TenantSecurityToken(TENANT, CONTROLLLER_ID,
|
||||||
|
FileResource.sha1("12345"));
|
||||||
try {
|
try {
|
||||||
authenticationManager.doAuthenticate(securityToken);
|
authenticationManager.doAuthenticate(securityToken);
|
||||||
fail("BadCredentialsException was excepeted since principal was missing");
|
fail("BadCredentialsException was excepeted since principal was missing");
|
||||||
@@ -118,11 +127,12 @@ public class AmqpControllerAuthenticationTest {
|
|||||||
@Test
|
@Test
|
||||||
@Description("Tests authentication manager without wrong credential")
|
@Description("Tests authentication manager without wrong credential")
|
||||||
public void testAuthenticationBadCredantialsWithWrongCredential() {
|
public void testAuthenticationBadCredantialsWithWrongCredential() {
|
||||||
final TenantSecruityToken securityToken = new TenantSecruityToken(TENANT, CONTROLLLER_ID, "12345");
|
final TenantSecurityToken securityToken = new TenantSecurityToken(TENANT, CONTROLLLER_ID,
|
||||||
|
FileResource.sha1("12345"));
|
||||||
when(tenantConfigurationManagement.getConfigurationValue(
|
when(tenantConfigurationManagement.getConfigurationValue(
|
||||||
eq(TenantConfigurationKey.AUTHENTICATION_MODE_TARGET_SECURITY_TOKEN_ENABLED), eq(Boolean.class)))
|
eq(TenantConfigurationKey.AUTHENTICATION_MODE_TARGET_SECURITY_TOKEN_ENABLED), eq(Boolean.class)))
|
||||||
.thenReturn(CONFIG_VALUE_TRUE);
|
.thenReturn(CONFIG_VALUE_TRUE);
|
||||||
securityToken.getHeaders().put(TenantSecruityToken.AUTHORIZATION_HEADER, "TargetToken 12" + CONTROLLLER_ID);
|
securityToken.getHeaders().put(TenantSecurityToken.AUTHORIZATION_HEADER, "TargetToken 12" + CONTROLLLER_ID);
|
||||||
try {
|
try {
|
||||||
authenticationManager.doAuthenticate(securityToken);
|
authenticationManager.doAuthenticate(securityToken);
|
||||||
fail("BadCredentialsException was excepeted due to wrong credential");
|
fail("BadCredentialsException was excepeted due to wrong credential");
|
||||||
@@ -135,11 +145,12 @@ public class AmqpControllerAuthenticationTest {
|
|||||||
@Test
|
@Test
|
||||||
@Description("Tests authentication successfull")
|
@Description("Tests authentication successfull")
|
||||||
public void testSuccessfullAuthentication() {
|
public void testSuccessfullAuthentication() {
|
||||||
final TenantSecruityToken securityToken = new TenantSecruityToken(TENANT, CONTROLLLER_ID, "12345");
|
final TenantSecurityToken securityToken = new TenantSecurityToken(TENANT, CONTROLLLER_ID,
|
||||||
|
FileResource.sha1("12345"));
|
||||||
when(tenantConfigurationManagement.getConfigurationValue(
|
when(tenantConfigurationManagement.getConfigurationValue(
|
||||||
eq(TenantConfigurationKey.AUTHENTICATION_MODE_TARGET_SECURITY_TOKEN_ENABLED), eq(Boolean.class)))
|
eq(TenantConfigurationKey.AUTHENTICATION_MODE_TARGET_SECURITY_TOKEN_ENABLED), eq(Boolean.class)))
|
||||||
.thenReturn(CONFIG_VALUE_TRUE);
|
.thenReturn(CONFIG_VALUE_TRUE);
|
||||||
securityToken.getHeaders().put(TenantSecruityToken.AUTHORIZATION_HEADER, "TargetToken " + CONTROLLLER_ID);
|
securityToken.getHeaders().put(TenantSecurityToken.AUTHORIZATION_HEADER, "TargetToken " + CONTROLLLER_ID);
|
||||||
final Authentication authentication = authenticationManager.doAuthenticate(securityToken);
|
final Authentication authentication = authenticationManager.doAuthenticate(securityToken);
|
||||||
assertThat(authentication).isNotNull();
|
assertThat(authentication).isNotNull();
|
||||||
}
|
}
|
||||||
@@ -149,7 +160,8 @@ public class AmqpControllerAuthenticationTest {
|
|||||||
public void testAuthenticationMessageBadCredantialsWithoutPricipal() {
|
public void testAuthenticationMessageBadCredantialsWithoutPricipal() {
|
||||||
final MessageProperties messageProperties = createMessageProperties(MessageType.AUTHENTIFICATION);
|
final MessageProperties messageProperties = createMessageProperties(MessageType.AUTHENTIFICATION);
|
||||||
|
|
||||||
final TenantSecruityToken securityToken = new TenantSecruityToken(TENANT, CONTROLLLER_ID, "12345");
|
final TenantSecurityToken securityToken = new TenantSecurityToken(TENANT, CONTROLLLER_ID,
|
||||||
|
FileResource.sha1("12345"));
|
||||||
final Message message = amqpMessageHandlerService.getMessageConverter().toMessage(securityToken,
|
final Message message = amqpMessageHandlerService.getMessageConverter().toMessage(securityToken,
|
||||||
messageProperties);
|
messageProperties);
|
||||||
|
|
||||||
@@ -167,11 +179,12 @@ public class AmqpControllerAuthenticationTest {
|
|||||||
@Description("Tests authentication message without wrong credential")
|
@Description("Tests authentication message without wrong credential")
|
||||||
public void testAuthenticationMessageBadCredantialsWithWrongCredential() {
|
public void testAuthenticationMessageBadCredantialsWithWrongCredential() {
|
||||||
final MessageProperties messageProperties = createMessageProperties(MessageType.AUTHENTIFICATION);
|
final MessageProperties messageProperties = createMessageProperties(MessageType.AUTHENTIFICATION);
|
||||||
final TenantSecruityToken securityToken = new TenantSecruityToken(TENANT, CONTROLLLER_ID, "12345");
|
final TenantSecurityToken securityToken = new TenantSecurityToken(TENANT, CONTROLLLER_ID,
|
||||||
|
FileResource.sha1("12345"));
|
||||||
when(tenantConfigurationManagement.getConfigurationValue(
|
when(tenantConfigurationManagement.getConfigurationValue(
|
||||||
eq(TenantConfigurationKey.AUTHENTICATION_MODE_TARGET_SECURITY_TOKEN_ENABLED), eq(Boolean.class)))
|
eq(TenantConfigurationKey.AUTHENTICATION_MODE_TARGET_SECURITY_TOKEN_ENABLED), eq(Boolean.class)))
|
||||||
.thenReturn(CONFIG_VALUE_TRUE);
|
.thenReturn(CONFIG_VALUE_TRUE);
|
||||||
securityToken.getHeaders().put(TenantSecruityToken.AUTHORIZATION_HEADER, "TargetToken 12" + CONTROLLLER_ID);
|
securityToken.getHeaders().put(TenantSecurityToken.AUTHORIZATION_HEADER, "TargetToken 12" + CONTROLLLER_ID);
|
||||||
final Message message = amqpMessageHandlerService.getMessageConverter().toMessage(securityToken,
|
final Message message = amqpMessageHandlerService.getMessageConverter().toMessage(securityToken,
|
||||||
messageProperties);
|
messageProperties);
|
||||||
|
|
||||||
@@ -189,11 +202,12 @@ public class AmqpControllerAuthenticationTest {
|
|||||||
@Description("Tests authentication message successfull")
|
@Description("Tests authentication message successfull")
|
||||||
public void testSuccessfullMessageAuthentication() {
|
public void testSuccessfullMessageAuthentication() {
|
||||||
final MessageProperties messageProperties = createMessageProperties(MessageType.AUTHENTIFICATION);
|
final MessageProperties messageProperties = createMessageProperties(MessageType.AUTHENTIFICATION);
|
||||||
final TenantSecruityToken securityToken = new TenantSecruityToken(TENANT, CONTROLLLER_ID, "12345");
|
final TenantSecurityToken securityToken = new TenantSecurityToken(TENANT, CONTROLLLER_ID,
|
||||||
|
FileResource.sha1("12345"));
|
||||||
when(tenantConfigurationManagement.getConfigurationValue(
|
when(tenantConfigurationManagement.getConfigurationValue(
|
||||||
eq(TenantConfigurationKey.AUTHENTICATION_MODE_TARGET_SECURITY_TOKEN_ENABLED), eq(Boolean.class)))
|
eq(TenantConfigurationKey.AUTHENTICATION_MODE_TARGET_SECURITY_TOKEN_ENABLED), eq(Boolean.class)))
|
||||||
.thenReturn(CONFIG_VALUE_TRUE);
|
.thenReturn(CONFIG_VALUE_TRUE);
|
||||||
securityToken.getHeaders().put(TenantSecruityToken.AUTHORIZATION_HEADER, "TargetToken " + CONTROLLLER_ID);
|
securityToken.getHeaders().put(TenantSecurityToken.AUTHORIZATION_HEADER, "TargetToken " + CONTROLLLER_ID);
|
||||||
final Message message = amqpMessageHandlerService.getMessageConverter().toMessage(securityToken,
|
final Message message = amqpMessageHandlerService.getMessageConverter().toMessage(securityToken,
|
||||||
messageProperties);
|
messageProperties);
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import static org.junit.Assert.assertFalse;
|
|||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.mockito.Matchers.any;
|
import static org.mockito.Matchers.any;
|
||||||
|
import static org.mockito.Matchers.anyLong;
|
||||||
import static org.mockito.Matchers.anyObject;
|
import static org.mockito.Matchers.anyObject;
|
||||||
import static org.mockito.Matchers.anyString;
|
import static org.mockito.Matchers.anyString;
|
||||||
import static org.mockito.Matchers.eq;
|
import static org.mockito.Matchers.eq;
|
||||||
@@ -25,6 +26,7 @@ import java.util.List;
|
|||||||
|
|
||||||
import org.eclipse.hawkbit.AbstractIntegrationTestWithMongoDB;
|
import org.eclipse.hawkbit.AbstractIntegrationTestWithMongoDB;
|
||||||
import org.eclipse.hawkbit.TestDataUtil;
|
import org.eclipse.hawkbit.TestDataUtil;
|
||||||
|
import org.eclipse.hawkbit.api.ArtifactUrlHandler;
|
||||||
import org.eclipse.hawkbit.artifact.repository.model.DbArtifact;
|
import org.eclipse.hawkbit.artifact.repository.model.DbArtifact;
|
||||||
import org.eclipse.hawkbit.dmf.amqp.api.EventTopic;
|
import org.eclipse.hawkbit.dmf.amqp.api.EventTopic;
|
||||||
import org.eclipse.hawkbit.dmf.amqp.api.MessageHeaderKey;
|
import org.eclipse.hawkbit.dmf.amqp.api.MessageHeaderKey;
|
||||||
@@ -36,7 +38,6 @@ import org.eclipse.hawkbit.repository.model.Artifact;
|
|||||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||||
import org.eclipse.hawkbit.repository.model.LocalArtifact;
|
import org.eclipse.hawkbit.repository.model.LocalArtifact;
|
||||||
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||||
import org.eclipse.hawkbit.util.ArtifactUrlHandler;
|
|
||||||
import org.eclipse.hawkbit.util.IpUtil;
|
import org.eclipse.hawkbit.util.IpUtil;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.mockito.ArgumentCaptor;
|
import org.mockito.ArgumentCaptor;
|
||||||
@@ -77,7 +78,8 @@ public class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTestWit
|
|||||||
amqpMessageDispatcherService.setAmqpSenderService(senderService);
|
amqpMessageDispatcherService.setAmqpSenderService(senderService);
|
||||||
|
|
||||||
final ArtifactUrlHandler artifactUrlHandlerMock = Mockito.mock(ArtifactUrlHandler.class);
|
final ArtifactUrlHandler artifactUrlHandlerMock = Mockito.mock(ArtifactUrlHandler.class);
|
||||||
when(artifactUrlHandlerMock.getUrl(anyString(), any(), anyObject())).thenReturn("http://mockurl");
|
when(artifactUrlHandlerMock.getUrl(anyString(), anyLong(), anyString(), anyString(), anyObject()))
|
||||||
|
.thenReturn("http://mockurl");
|
||||||
|
|
||||||
amqpMessageDispatcherService.setArtifactUrlHandler(artifactUrlHandlerMock);
|
amqpMessageDispatcherService.setArtifactUrlHandler(artifactUrlHandlerMock);
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,8 @@ import org.eclipse.hawkbit.dmf.amqp.api.MessageType;
|
|||||||
import org.eclipse.hawkbit.dmf.json.model.ActionStatus;
|
import org.eclipse.hawkbit.dmf.json.model.ActionStatus;
|
||||||
import org.eclipse.hawkbit.dmf.json.model.ActionUpdateStatus;
|
import org.eclipse.hawkbit.dmf.json.model.ActionUpdateStatus;
|
||||||
import org.eclipse.hawkbit.dmf.json.model.DownloadResponse;
|
import org.eclipse.hawkbit.dmf.json.model.DownloadResponse;
|
||||||
import org.eclipse.hawkbit.dmf.json.model.TenantSecruityToken;
|
import org.eclipse.hawkbit.dmf.json.model.TenantSecurityToken;
|
||||||
|
import org.eclipse.hawkbit.dmf.json.model.TenantSecurityToken.FileResource;
|
||||||
import org.eclipse.hawkbit.eventbus.event.TargetAssignDistributionSetEvent;
|
import org.eclipse.hawkbit.eventbus.event.TargetAssignDistributionSetEvent;
|
||||||
import org.eclipse.hawkbit.repository.ArtifactManagement;
|
import org.eclipse.hawkbit.repository.ArtifactManagement;
|
||||||
import org.eclipse.hawkbit.repository.ControllerManagement;
|
import org.eclipse.hawkbit.repository.ControllerManagement;
|
||||||
@@ -263,7 +264,7 @@ public class AmqpMessageHandlerServiceTest {
|
|||||||
@Description("Tests that an download request is denied for an artifact which does not exists")
|
@Description("Tests that an download request is denied for an artifact which does not exists")
|
||||||
public void authenticationRequestDeniedForArtifactWhichDoesNotExists() {
|
public void authenticationRequestDeniedForArtifactWhichDoesNotExists() {
|
||||||
final MessageProperties messageProperties = createMessageProperties(MessageType.AUTHENTIFICATION);
|
final MessageProperties messageProperties = createMessageProperties(MessageType.AUTHENTIFICATION);
|
||||||
final TenantSecruityToken securityToken = new TenantSecruityToken(TENANT, "123", "12345");
|
final TenantSecurityToken securityToken = new TenantSecurityToken(TENANT, "123", FileResource.sha1("12345"));
|
||||||
final Message message = amqpMessageHandlerService.getMessageConverter().toMessage(securityToken,
|
final Message message = amqpMessageHandlerService.getMessageConverter().toMessage(securityToken,
|
||||||
messageProperties);
|
messageProperties);
|
||||||
|
|
||||||
@@ -282,7 +283,7 @@ public class AmqpMessageHandlerServiceTest {
|
|||||||
@Description("Tests that an download request is denied for an artifact which is not assigned to the requested target")
|
@Description("Tests that an download request is denied for an artifact which is not assigned to the requested target")
|
||||||
public void authenticationRequestDeniedForArtifactWhichIsNotAssignedToTarget() {
|
public void authenticationRequestDeniedForArtifactWhichIsNotAssignedToTarget() {
|
||||||
final MessageProperties messageProperties = createMessageProperties(MessageType.AUTHENTIFICATION);
|
final MessageProperties messageProperties = createMessageProperties(MessageType.AUTHENTIFICATION);
|
||||||
final TenantSecruityToken securityToken = new TenantSecruityToken(TENANT, "123", "12345");
|
final TenantSecurityToken securityToken = new TenantSecurityToken(TENANT, "123", FileResource.sha1("12345"));
|
||||||
final Message message = amqpMessageHandlerService.getMessageConverter().toMessage(securityToken,
|
final Message message = amqpMessageHandlerService.getMessageConverter().toMessage(securityToken,
|
||||||
messageProperties);
|
messageProperties);
|
||||||
|
|
||||||
@@ -306,7 +307,7 @@ public class AmqpMessageHandlerServiceTest {
|
|||||||
@Description("Tests that an download request is allowed for an artifact which exists and assigned to the requested target")
|
@Description("Tests that an download request is allowed for an artifact which exists and assigned to the requested target")
|
||||||
public void authenticationRequestAllowedForArtifactWhichExistsAndAssignedToTarget() throws MalformedURLException {
|
public void authenticationRequestAllowedForArtifactWhichExistsAndAssignedToTarget() throws MalformedURLException {
|
||||||
final MessageProperties messageProperties = createMessageProperties(MessageType.AUTHENTIFICATION);
|
final MessageProperties messageProperties = createMessageProperties(MessageType.AUTHENTIFICATION);
|
||||||
final TenantSecruityToken securityToken = new TenantSecruityToken(TENANT, "123", "12345");
|
final TenantSecurityToken securityToken = new TenantSecurityToken(TENANT, "123", FileResource.sha1("12345"));
|
||||||
final Message message = amqpMessageHandlerService.getMessageConverter().toMessage(securityToken,
|
final Message message = amqpMessageHandlerService.getMessageConverter().toMessage(securityToken,
|
||||||
messageProperties);
|
messageProperties);
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,8 @@ import org.eclipse.hawkbit.AmqpTestConfiguration;
|
|||||||
import org.eclipse.hawkbit.RepositoryApplicationConfiguration;
|
import org.eclipse.hawkbit.RepositoryApplicationConfiguration;
|
||||||
import org.eclipse.hawkbit.TestConfiguration;
|
import org.eclipse.hawkbit.TestConfiguration;
|
||||||
import org.eclipse.hawkbit.TestDataUtil;
|
import org.eclipse.hawkbit.TestDataUtil;
|
||||||
import org.eclipse.hawkbit.dmf.json.model.Artifact;
|
import org.eclipse.hawkbit.api.ArtifactUrlHandler;
|
||||||
|
import org.eclipse.hawkbit.api.UrlProtocol;
|
||||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||||
import org.eclipse.hawkbit.repository.model.LocalArtifact;
|
import org.eclipse.hawkbit.repository.model.LocalArtifact;
|
||||||
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||||
@@ -30,8 +31,7 @@ import ru.yandex.qatools.allure.annotations.Features;
|
|||||||
import ru.yandex.qatools.allure.annotations.Stories;
|
import ru.yandex.qatools.allure.annotations.Stories;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Tests for creating urls to download artifacts.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
@Features("Component Tests - Artifact URL Handler")
|
@Features("Component Tests - Artifact URL Handler")
|
||||||
@Stories("Test to generate the artifact download URL")
|
@Stories("Test to generate the artifact download URL")
|
||||||
@@ -45,6 +45,9 @@ public class PropertyBasedArtifactUrlHandlerTest extends AbstractIntegrationTest
|
|||||||
private TenantAware tenantAware;
|
private TenantAware tenantAware;
|
||||||
private LocalArtifact localArtifact;
|
private LocalArtifact localArtifact;
|
||||||
private final String controllerId = "Test";
|
private final String controllerId = "Test";
|
||||||
|
private String fileName;
|
||||||
|
private Long softwareModuleId;
|
||||||
|
private String sha1Hash;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setup() {
|
public void setup() {
|
||||||
@@ -53,12 +56,18 @@ public class PropertyBasedArtifactUrlHandlerTest extends AbstractIntegrationTest
|
|||||||
final SoftwareModule module = dsA.getModules().iterator().next();
|
final SoftwareModule module = dsA.getModules().iterator().next();
|
||||||
localArtifact = (LocalArtifact) TestDataUtil.generateArtifacts(artifactManagement, module.getId()).stream()
|
localArtifact = (LocalArtifact) TestDataUtil.generateArtifacts(artifactManagement, module.getId()).stream()
|
||||||
.findAny().get();
|
.findAny().get();
|
||||||
|
softwareModuleId = localArtifact.getSoftwareModule().getId();
|
||||||
|
fileName = localArtifact.getFilename();
|
||||||
|
sha1Hash = localArtifact.getSha1Hash();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Description("Tests the generation of http download url.")
|
@Description("Tests the generation of http download url.")
|
||||||
public void testHttpUrl() {
|
public void testHttpUrl() {
|
||||||
final String url = urlHandlerProperties.getUrl(controllerId, localArtifact, Artifact.UrlProtocol.HTTP);
|
|
||||||
|
final String url = urlHandlerProperties.getUrl(controllerId, softwareModuleId, fileName, sha1Hash,
|
||||||
|
UrlProtocol.HTTP);
|
||||||
assertEquals("http is build incorrect",
|
assertEquals("http is build incorrect",
|
||||||
"http://localhost/" + tenantAware.getCurrentTenant() + "/controller/v1/" + controllerId
|
"http://localhost/" + tenantAware.getCurrentTenant() + "/controller/v1/" + controllerId
|
||||||
+ "/softwaremodules/" + localArtifact.getSoftwareModule().getId() + "/artifacts/"
|
+ "/softwaremodules/" + localArtifact.getSoftwareModule().getId() + "/artifacts/"
|
||||||
@@ -69,7 +78,8 @@ public class PropertyBasedArtifactUrlHandlerTest extends AbstractIntegrationTest
|
|||||||
@Test
|
@Test
|
||||||
@Description("Tests the generation of https download url.")
|
@Description("Tests the generation of https download url.")
|
||||||
public void testHttpsUrl() {
|
public void testHttpsUrl() {
|
||||||
final String url = urlHandlerProperties.getUrl(controllerId, localArtifact, Artifact.UrlProtocol.HTTPS);
|
final String url = urlHandlerProperties.getUrl(controllerId, softwareModuleId, fileName, sha1Hash,
|
||||||
|
UrlProtocol.HTTPS);
|
||||||
assertEquals("https is build incorrect",
|
assertEquals("https is build incorrect",
|
||||||
"https://localhost/" + tenantAware.getCurrentTenant() + "/controller/v1/" + controllerId
|
"https://localhost/" + tenantAware.getCurrentTenant() + "/controller/v1/" + controllerId
|
||||||
+ "/softwaremodules/" + localArtifact.getSoftwareModule().getId() + "/artifacts/"
|
+ "/softwaremodules/" + localArtifact.getSoftwareModule().getId() + "/artifacts/"
|
||||||
@@ -80,7 +90,8 @@ public class PropertyBasedArtifactUrlHandlerTest extends AbstractIntegrationTest
|
|||||||
@Test
|
@Test
|
||||||
@Description("Tests the generation of coap download url.")
|
@Description("Tests the generation of coap download url.")
|
||||||
public void testCoapUrl() {
|
public void testCoapUrl() {
|
||||||
final String url = urlHandlerProperties.getUrl(controllerId, localArtifact, Artifact.UrlProtocol.COAP);
|
final String url = urlHandlerProperties.getUrl(controllerId, softwareModuleId, fileName, sha1Hash,
|
||||||
|
UrlProtocol.COAP);
|
||||||
|
|
||||||
assertEquals("coap is build incorrect", "coap://127.0.0.1:5683/fw/" + tenantAware.getCurrentTenant() + "/"
|
assertEquals("coap is build incorrect", "coap://127.0.0.1:5683/fw/" + tenantAware.getCurrentTenant() + "/"
|
||||||
+ controllerId + "/sha1/" + localArtifact.getSha1Hash(), url);
|
+ controllerId + "/sha1/" + localArtifact.getSha1Hash(), url);
|
||||||
|
|||||||
@@ -1,94 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
|
||||||
*
|
|
||||||
* All rights reserved. This program and the accompanying materials
|
|
||||||
* are made available under the terms of the Eclipse Public License v1.0
|
|
||||||
* which accompanies this distribution, and is available at
|
|
||||||
* http://www.eclipse.org/legal/epl-v10.html
|
|
||||||
*/
|
|
||||||
package org.eclipse.hawkbit.dmf.json.model;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.TreeMap;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* JSON representation to authenticate a tenant.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
@JsonInclude(Include.NON_NULL)
|
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
|
||||||
public class TenantSecruityToken {
|
|
||||||
|
|
||||||
public static final String AUTHORIZATION_HEADER = "Authorization";
|
|
||||||
public static final String COAP_AUTHORIZATION_HEADER = "Coap-Authorization";
|
|
||||||
public static final String COAP_TOKEN_VALUE = "CoapToken";
|
|
||||||
|
|
||||||
@JsonProperty
|
|
||||||
private final String tenant;
|
|
||||||
@JsonProperty
|
|
||||||
private final String controllerId;
|
|
||||||
@JsonProperty(required = false)
|
|
||||||
private Map<String, String> headers = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
|
|
||||||
@JsonProperty(required = false)
|
|
||||||
private final String sha1;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor.
|
|
||||||
*
|
|
||||||
* @param tenant
|
|
||||||
* the tenant for the security token
|
|
||||||
* @param controllerId
|
|
||||||
* the ID of the controller for the security token
|
|
||||||
* @param sha1
|
|
||||||
* the sha1 of authentication
|
|
||||||
*/
|
|
||||||
@JsonCreator
|
|
||||||
public TenantSecruityToken(@JsonProperty("tenant") final String tenant,
|
|
||||||
@JsonProperty("controllerId") final String controllerId, @JsonProperty("sha1") final String sha1) {
|
|
||||||
this.tenant = tenant;
|
|
||||||
this.controllerId = controllerId;
|
|
||||||
this.sha1 = sha1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getTenant() {
|
|
||||||
return tenant;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getControllerId() {
|
|
||||||
return controllerId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<String, String> getHeaders() {
|
|
||||||
return headers;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getSha1() {
|
|
||||||
return sha1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets a header value.
|
|
||||||
*
|
|
||||||
* @param name
|
|
||||||
* of header
|
|
||||||
* @return the value
|
|
||||||
*/
|
|
||||||
public String getHeader(final String name) {
|
|
||||||
return headers.get(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setHeaders(final Map<String, String> headers) {
|
|
||||||
this.headers = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
|
|
||||||
this.headers.putAll(headers);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,226 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||||
|
*
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*/
|
||||||
|
package org.eclipse.hawkbit.dmf.json.model;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.TreeMap;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JSON representation to authenticate a tenant.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@JsonInclude(Include.NON_NULL)
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
public class TenantSecurityToken {
|
||||||
|
|
||||||
|
public static final String AUTHORIZATION_HEADER = "Authorization";
|
||||||
|
public static final String COAP_AUTHORIZATION_HEADER = "Coap-Authorization";
|
||||||
|
public static final String COAP_TOKEN_VALUE = "CoapToken";
|
||||||
|
|
||||||
|
@JsonProperty
|
||||||
|
private final String tenant;
|
||||||
|
@JsonProperty
|
||||||
|
private final String controllerId;
|
||||||
|
@JsonProperty(required = false)
|
||||||
|
private Map<String, String> headers = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
|
||||||
|
|
||||||
|
@JsonProperty(required = false)
|
||||||
|
private final FileResource fileResource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param tenant
|
||||||
|
* the tenant for the security token
|
||||||
|
* @param controllerId
|
||||||
|
* the ID of the controller for the security token
|
||||||
|
* @param fileResource
|
||||||
|
* the file to obtain
|
||||||
|
*/
|
||||||
|
@JsonCreator
|
||||||
|
public TenantSecurityToken(@JsonProperty("tenant") final String tenant,
|
||||||
|
@JsonProperty("controllerId") final String controllerId,
|
||||||
|
@JsonProperty("fileResource") final FileResource fileResource) {
|
||||||
|
this.tenant = tenant;
|
||||||
|
this.controllerId = controllerId;
|
||||||
|
this.fileResource = fileResource;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTenant() {
|
||||||
|
return tenant;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getControllerId() {
|
||||||
|
return controllerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, String> getHeaders() {
|
||||||
|
return headers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FileResource getFileResource() {
|
||||||
|
return fileResource;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a header value.
|
||||||
|
*
|
||||||
|
* @param name
|
||||||
|
* of header
|
||||||
|
* @return the value
|
||||||
|
*/
|
||||||
|
public String getHeader(final String name) {
|
||||||
|
return headers.get(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHeaders(final Map<String, String> headers) {
|
||||||
|
this.headers = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
|
||||||
|
this.headers.putAll(headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* File resource descriptor which is used to ask for the resource to
|
||||||
|
* download e.g. The lookup of the file can be different e.g. by SHA1 hash
|
||||||
|
* or by filename.
|
||||||
|
*/
|
||||||
|
@JsonInclude(Include.NON_NULL)
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
public static class FileResource {
|
||||||
|
@JsonProperty(required = false)
|
||||||
|
private String sha1;
|
||||||
|
@JsonProperty(required = false)
|
||||||
|
private String filename;
|
||||||
|
@JsonProperty(required = false)
|
||||||
|
private SoftwareModuleFilenameResource softwareModuleFilenameResource;
|
||||||
|
|
||||||
|
public String getSha1() {
|
||||||
|
return sha1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSha1(final String sha1) {
|
||||||
|
this.sha1 = sha1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFilename() {
|
||||||
|
return filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFilename(final String filename) {
|
||||||
|
this.filename = filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SoftwareModuleFilenameResource getSoftwareModuleFilenameResource() {
|
||||||
|
return softwareModuleFilenameResource;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSoftwareModuleFilenameResource(
|
||||||
|
final SoftwareModuleFilenameResource softwareModuleFilenameResource) {
|
||||||
|
this.softwareModuleFilenameResource = softwareModuleFilenameResource;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* factory method to create a file resource for an SHA1 lookup.
|
||||||
|
*
|
||||||
|
* @param sha1
|
||||||
|
* the SHA1 key of the file to obtain
|
||||||
|
* @return the {@link FileResource} with SHA1 key set
|
||||||
|
*/
|
||||||
|
public static FileResource sha1(final String sha1) {
|
||||||
|
final FileResource resource = new FileResource();
|
||||||
|
resource.sha1 = sha1;
|
||||||
|
return resource;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* factory method to create a file resource for an filename lookup.
|
||||||
|
*
|
||||||
|
* @param filename
|
||||||
|
* the filename of the file to obtain
|
||||||
|
* @return the {@link FileResource} with filename set
|
||||||
|
*/
|
||||||
|
public static FileResource filename(final String filename) {
|
||||||
|
final FileResource resource = new FileResource();
|
||||||
|
resource.filename = filename;
|
||||||
|
return resource;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* factory method to create a file resource for an softwaremodule +
|
||||||
|
* filename lookup, because an filename is not globally unique but
|
||||||
|
* within a softwaremodule.
|
||||||
|
*
|
||||||
|
* @param softwareModuleId
|
||||||
|
* the ID of the software module which contains the artifact
|
||||||
|
* @param filename
|
||||||
|
* the name of file to obtain within the software module
|
||||||
|
* @return the {@link FileResource} with artifactId set
|
||||||
|
*/
|
||||||
|
public static FileResource softwareModuleFilename(final Long softwareModuleId, final String filename) {
|
||||||
|
final FileResource resource = new FileResource();
|
||||||
|
resource.softwareModuleFilenameResource = new SoftwareModuleFilenameResource(softwareModuleId, filename);
|
||||||
|
return resource;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "FileResource [sha1=" + sha1 + ", filename=" + filename + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inner class which holds the pointer to an artifact based on the
|
||||||
|
* softwaremoduleId and the filename.
|
||||||
|
*/
|
||||||
|
@JsonInclude(Include.NON_NULL)
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
public static class SoftwareModuleFilenameResource {
|
||||||
|
@JsonProperty(required = false)
|
||||||
|
private Long softwareModuleId;
|
||||||
|
@JsonProperty(required = false)
|
||||||
|
private String filename;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param softwareModuleId
|
||||||
|
* the ID of the softwaremodule
|
||||||
|
* @param filename
|
||||||
|
* the name of the file of the artifact within the
|
||||||
|
* softwaremodule
|
||||||
|
*/
|
||||||
|
@JsonCreator
|
||||||
|
public SoftwareModuleFilenameResource(@JsonProperty("softwareModuleId") final Long softwareModuleId,
|
||||||
|
@JsonProperty("filename") final String filename) {
|
||||||
|
this.softwareModuleId = softwareModuleId;
|
||||||
|
this.filename = filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getSoftwareModuleId() {
|
||||||
|
return softwareModuleId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFilename() {
|
||||||
|
return filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSoftwareModuleId(final Long softwareModuleId) {
|
||||||
|
this.softwareModuleId = softwareModuleId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFilename(final String filename) {
|
||||||
|
this.filename = filename;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,6 +9,8 @@
|
|||||||
package org.eclipse.hawkbit.security;
|
package org.eclipse.hawkbit.security;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import javax.servlet.FilterChain;
|
import javax.servlet.FilterChain;
|
||||||
@@ -16,14 +18,19 @@ import javax.servlet.ServletException;
|
|||||||
import javax.servlet.ServletRequest;
|
import javax.servlet.ServletRequest;
|
||||||
import javax.servlet.ServletResponse;
|
import javax.servlet.ServletResponse;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
import org.eclipse.hawkbit.dmf.json.model.TenantSecruityToken;
|
import org.eclipse.hawkbit.dmf.json.model.TenantSecurityToken;
|
||||||
|
import org.eclipse.hawkbit.dmf.json.model.TenantSecurityToken.FileResource;
|
||||||
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
|
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
|
||||||
import org.eclipse.hawkbit.tenancy.TenantAware;
|
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.security.core.Authentication;
|
||||||
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
import org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter;
|
import org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter;
|
||||||
|
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken;
|
||||||
import org.springframework.util.AntPathMatcher;
|
import org.springframework.util.AntPathMatcher;
|
||||||
|
|
||||||
import com.google.common.collect.Iterators;
|
import com.google.common.collect.Iterators;
|
||||||
@@ -79,14 +86,6 @@ public abstract class AbstractHttpControllerAuthenticationFilter extends Abstrac
|
|||||||
pathExtractor = new AntPathMatcher();
|
pathExtractor = new AntPathMatcher();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
*
|
|
||||||
* @see org.springframework.security.web.authentication.preauth.
|
|
||||||
* AbstractPreAuthenticatedProcessingFilter
|
|
||||||
* #doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse,
|
|
||||||
* javax.servlet.FilterChain)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain)
|
public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain)
|
||||||
throws IOException, ServletException {
|
throws IOException, ServletException {
|
||||||
@@ -96,7 +95,7 @@ public abstract class AbstractHttpControllerAuthenticationFilter extends Abstrac
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final TenantSecruityToken secruityToken = createTenantSecruityTokenVariables((HttpServletRequest) request);
|
final TenantSecurityToken secruityToken = createTenantSecruityTokenVariables((HttpServletRequest) request);
|
||||||
if (secruityToken == null) {
|
if (secruityToken == null) {
|
||||||
chain.doFilter(request, response);
|
chain.doFilter(request, response);
|
||||||
return;
|
return;
|
||||||
@@ -112,6 +111,18 @@ public abstract class AbstractHttpControllerAuthenticationFilter extends Abstrac
|
|||||||
|
|
||||||
protected abstract PreAuthenficationFilter createControllerAuthenticationFilter();
|
protected abstract PreAuthenficationFilter createControllerAuthenticationFilter();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void successfulAuthentication(final HttpServletRequest request, final HttpServletResponse response,
|
||||||
|
final Authentication authResult) {
|
||||||
|
final Collection<GrantedAuthority> authorities = new ArrayList<>();
|
||||||
|
authorities.addAll(authResult.getAuthorities());
|
||||||
|
authorities.addAll(abstractControllerAuthenticationFilter.getSuccessfulAuthenticationAuthorities());
|
||||||
|
final PreAuthenticatedAuthenticationToken authTokenWithGrantedAuthorities = new PreAuthenticatedAuthenticationToken(
|
||||||
|
authResult.getPrincipal(), authResult.getCredentials(), authorities);
|
||||||
|
authTokenWithGrantedAuthorities.setDetails(authResult.getDetails());
|
||||||
|
super.successfulAuthentication(request, response, authTokenWithGrantedAuthorities);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extracts tenant and controllerId from the request URI as path variables.
|
* Extracts tenant and controllerId from the request URI as path variables.
|
||||||
*
|
*
|
||||||
@@ -121,7 +132,7 @@ public abstract class AbstractHttpControllerAuthenticationFilter extends Abstrac
|
|||||||
* request does not match the pattern and no variables could be
|
* request does not match the pattern and no variables could be
|
||||||
* extracted
|
* extracted
|
||||||
*/
|
*/
|
||||||
protected TenantSecruityToken createTenantSecruityTokenVariables(final HttpServletRequest request) {
|
protected TenantSecurityToken createTenantSecruityTokenVariables(final HttpServletRequest request) {
|
||||||
final String requestURI = request.getRequestURI();
|
final String requestURI = request.getRequestURI();
|
||||||
|
|
||||||
if (pathExtractor.match(request.getContextPath() + CONTROLLER_REQUEST_ANT_PATTERN, requestURI)) {
|
if (pathExtractor.match(request.getContextPath() + CONTROLLER_REQUEST_ANT_PATTERN, requestURI)) {
|
||||||
@@ -153,9 +164,9 @@ public abstract class AbstractHttpControllerAuthenticationFilter extends Abstrac
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private TenantSecruityToken createTenantSecruityTokenVariables(final HttpServletRequest request,
|
private TenantSecurityToken createTenantSecruityTokenVariables(final HttpServletRequest request,
|
||||||
final String tenant, final String controllerId) {
|
final String tenant, final String controllerId) {
|
||||||
final TenantSecruityToken secruityToken = new TenantSecruityToken(tenant, controllerId, "");
|
final TenantSecurityToken secruityToken = new TenantSecurityToken(tenant, controllerId, FileResource.sha1(""));
|
||||||
final UnmodifiableIterator<String> forEnumeration = Iterators.forEnumeration(request.getHeaderNames());
|
final UnmodifiableIterator<String> forEnumeration = Iterators.forEnumeration(request.getHeaderNames());
|
||||||
forEnumeration.forEachRemaining(header -> secruityToken.getHeaders().put(header, request.getHeader(header)));
|
forEnumeration.forEachRemaining(header -> secruityToken.getHeaders().put(header, request.getHeader(header)));
|
||||||
return secruityToken;
|
return secruityToken;
|
||||||
@@ -163,7 +174,7 @@ public abstract class AbstractHttpControllerAuthenticationFilter extends Abstrac
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Object getPreAuthenticatedPrincipal(final HttpServletRequest request) {
|
protected Object getPreAuthenticatedPrincipal(final HttpServletRequest request) {
|
||||||
final TenantSecruityToken secruityToken = createTenantSecruityTokenVariables(request);
|
final TenantSecurityToken secruityToken = createTenantSecruityTokenVariables(request);
|
||||||
if (secruityToken == null) {
|
if (secruityToken == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -172,7 +183,7 @@ public abstract class AbstractHttpControllerAuthenticationFilter extends Abstrac
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Object getPreAuthenticatedCredentials(final HttpServletRequest request) {
|
protected Object getPreAuthenticatedCredentials(final HttpServletRequest request) {
|
||||||
final TenantSecruityToken secruityToken = createTenantSecruityTokenVariables(request);
|
final TenantSecurityToken secruityToken = createTenantSecruityTokenVariables(request);
|
||||||
if (secruityToken == null) {
|
if (secruityToken == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,47 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||||
|
*
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*/
|
||||||
|
package org.eclipse.hawkbit.security;
|
||||||
|
|
||||||
|
import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions;
|
||||||
|
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
|
||||||
|
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An pre-authenticated processing filter which add the
|
||||||
|
* {@link SpringEvalExpressions#CONTROLLER_DOWNLOAD_ROLE_ANONYMOUS} to the
|
||||||
|
* security context in case the anonymous download is allowed through
|
||||||
|
* configuration.
|
||||||
|
*/
|
||||||
|
public class HttpControllerPreAuthenticateAnonymousDownloadFilter extends AbstractHttpControllerAuthenticationFilter {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param tenantConfigurationManagement
|
||||||
|
* the system management service to retrieve configuration
|
||||||
|
* properties
|
||||||
|
* @param tenantAware
|
||||||
|
* the tenant aware service to get configuration for the specific
|
||||||
|
* tenant
|
||||||
|
* @param systemSecurityContext
|
||||||
|
* the system security context
|
||||||
|
*/
|
||||||
|
public HttpControllerPreAuthenticateAnonymousDownloadFilter(
|
||||||
|
final TenantConfigurationManagement tenantConfigurationManagement, final TenantAware tenantAware,
|
||||||
|
final SystemSecurityContext systemSecurityContext) {
|
||||||
|
super(tenantConfigurationManagement, tenantAware, systemSecurityContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected PreAuthenficationFilter createControllerAuthenticationFilter() {
|
||||||
|
return new ControllerPreAuthenticatedAnonymousDownload(tenantConfigurationManagement, tenantAware,
|
||||||
|
systemSecurityContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -321,7 +321,8 @@ public class ArtifactManagement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
boolean artifactIsOnlyUsedByOneSoftwareModule = true;
|
boolean artifactIsOnlyUsedByOneSoftwareModule = true;
|
||||||
for (LocalArtifact lArtifact : localArtifactRepository.findByGridFsFileName(existing.getGridFsFileName())) {
|
for (final LocalArtifact lArtifact : localArtifactRepository
|
||||||
|
.findByGridFsFileName(existing.getGridFsFileName())) {
|
||||||
if (!lArtifact.getSoftwareModule().isDeleted()
|
if (!lArtifact.getSoftwareModule().isDeleted()
|
||||||
&& lArtifact.getSoftwareModule().getId() != existing.getSoftwareModule().getId()) {
|
&& lArtifact.getSoftwareModule().getId() != existing.getSoftwareModule().getId()) {
|
||||||
artifactIsOnlyUsedByOneSoftwareModule = false;
|
artifactIsOnlyUsedByOneSoftwareModule = false;
|
||||||
@@ -403,7 +404,7 @@ public class ArtifactManagement {
|
|||||||
* if file could not be found in store
|
* if file could not be found in store
|
||||||
*/
|
*/
|
||||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_DOWNLOAD_ARTIFACT + SpringEvalExpressions.HAS_AUTH_OR
|
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_DOWNLOAD_ARTIFACT + SpringEvalExpressions.HAS_AUTH_OR
|
||||||
+ SpringEvalExpressions.IS_CONTROLLER)
|
+ SpringEvalExpressions.HAS_CONTROLLER_DOWNLOAD)
|
||||||
public DbArtifact loadLocalArtifactBinary(@NotNull final LocalArtifact artifact) {
|
public DbArtifact loadLocalArtifactBinary(@NotNull final LocalArtifact artifact) {
|
||||||
final DbArtifact result = artifactRepository.getArtifactBySha1(artifact.getGridFsFileName());
|
final DbArtifact result = artifactRepository.getArtifactBySha1(artifact.getGridFsFileName());
|
||||||
if (result == null) {
|
if (result == null) {
|
||||||
|
|||||||
@@ -8,10 +8,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.eclipse.hawkbit.repository.model;
|
package org.eclipse.hawkbit.repository.model;
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
|
|
||||||
import javax.persistence.Basic;
|
|
||||||
import javax.persistence.Column;
|
|
||||||
import javax.persistence.ConstraintMode;
|
import javax.persistence.ConstraintMode;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
import javax.persistence.FetchType;
|
import javax.persistence.FetchType;
|
||||||
@@ -29,63 +25,31 @@ import javax.persistence.Table;
|
|||||||
@IdClass(DsMetadataCompositeKey.class)
|
@IdClass(DsMetadataCompositeKey.class)
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "sp_ds_metadata")
|
@Table(name = "sp_ds_metadata")
|
||||||
public class DistributionSetMetadata implements Serializable {
|
public class DistributionSetMetadata extends MetaData {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
@Id
|
|
||||||
@Column(name = "meta_key", length = 128)
|
|
||||||
private String key;
|
|
||||||
|
|
||||||
@Column(name = "meta_value", length = 4000)
|
|
||||||
@Basic
|
|
||||||
private String value;
|
|
||||||
|
|
||||||
@Id
|
@Id
|
||||||
@ManyToOne(fetch = FetchType.LAZY)
|
@ManyToOne(fetch = FetchType.LAZY)
|
||||||
@JoinColumn(name = "ds_id", foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_metadata_ds"))
|
@JoinColumn(name = "ds_id", foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_metadata_ds"))
|
||||||
private DistributionSet distributionSet;
|
private DistributionSet distributionSet;
|
||||||
|
|
||||||
public DistributionSetMetadata() {
|
public DistributionSetMetadata() {
|
||||||
// Default constructor for JPA.
|
// default public constructor for JPA
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Parameter constructor.
|
|
||||||
*
|
|
||||||
* @param key
|
|
||||||
* @param distributionSet
|
|
||||||
* @param value
|
|
||||||
*/
|
|
||||||
public DistributionSetMetadata(final String key, final DistributionSet distributionSet, final String value) {
|
public DistributionSetMetadata(final String key, final DistributionSet distributionSet, final String value) {
|
||||||
this.key = key;
|
super(key, value);
|
||||||
this.distributionSet = distributionSet;
|
this.distributionSet = distributionSet;
|
||||||
this.value = value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public DsMetadataCompositeKey getId() {
|
public DsMetadataCompositeKey getId() {
|
||||||
return new DsMetadataCompositeKey(distributionSet, key);
|
return new DsMetadataCompositeKey(distributionSet, getKey());
|
||||||
}
|
|
||||||
|
|
||||||
public String getKey() {
|
|
||||||
return key;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setKey(final String key) {
|
|
||||||
this.key = key;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDistributionSet(final DistributionSet distributionSet) {
|
public void setDistributionSet(final DistributionSet distributionSet) {
|
||||||
this.distributionSet = distributionSet;
|
this.distributionSet = distributionSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getValue() {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setValue(final String value) {
|
|
||||||
this.value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DistributionSet getDistributionSet() {
|
public DistributionSet getDistributionSet() {
|
||||||
return distributionSet;
|
return distributionSet;
|
||||||
}
|
}
|
||||||
@@ -93,21 +57,14 @@ public class DistributionSetMetadata implements Serializable {
|
|||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
final int prime = 31;
|
final int prime = 31;
|
||||||
int result = 1;
|
int result = super.hashCode();
|
||||||
result = prime * result + (distributionSet == null ? 0 : distributionSet.hashCode());
|
result = prime * result + ((distributionSet == null) ? 0 : distributionSet.hashCode());
|
||||||
result = prime * result + (key == null ? 0 : key.hashCode());
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(final Object obj) {
|
public boolean equals(final Object obj) {
|
||||||
if (this == obj) {
|
if (!super.equals(obj)) {
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (obj == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!(obj instanceof DistributionSetMetadata)) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
final DistributionSetMetadata other = (DistributionSetMetadata) obj;
|
final DistributionSetMetadata other = (DistributionSetMetadata) obj;
|
||||||
@@ -118,14 +75,6 @@ public class DistributionSetMetadata implements Serializable {
|
|||||||
} else if (!distributionSet.equals(other.distributionSet)) {
|
} else if (!distributionSet.equals(other.distributionSet)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (key == null) {
|
|
||||||
if (other.key != null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else if (!key.equals(other.key)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,98 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||||
|
*
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*/
|
||||||
|
package org.eclipse.hawkbit.repository.model;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import javax.persistence.Basic;
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.MappedSuperclass;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Meta data for entities.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@MappedSuperclass
|
||||||
|
public abstract class MetaData implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@Column(name = "meta_key", length = 128)
|
||||||
|
private String key;
|
||||||
|
|
||||||
|
@Column(name = "meta_value", length = 4000)
|
||||||
|
@Basic
|
||||||
|
private String value;
|
||||||
|
|
||||||
|
public MetaData(final String key, final String value) {
|
||||||
|
super();
|
||||||
|
this.key = key;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MetaData() {
|
||||||
|
// Default constructor needed for JPA entities
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getKey() {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setKey(final String key) {
|
||||||
|
this.key = key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue(final String value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = 1;
|
||||||
|
result = prime * result + ((key == null) ? 0 : key.hashCode());
|
||||||
|
result = prime * result + ((value == null) ? 0 : value.hashCode());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object obj) {
|
||||||
|
if (this == obj) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (obj == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!(this.getClass().isInstance(obj))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
final MetaData other = (MetaData) obj;
|
||||||
|
if (key == null) {
|
||||||
|
if (other.key != null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else if (!key.equals(other.key)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (value == null) {
|
||||||
|
if (other.value != null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else if (!value.equals(other.value)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -8,9 +8,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.eclipse.hawkbit.repository.model;
|
package org.eclipse.hawkbit.repository.model;
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
|
|
||||||
import javax.persistence.Column;
|
|
||||||
import javax.persistence.ConstraintMode;
|
import javax.persistence.ConstraintMode;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
import javax.persistence.FetchType;
|
import javax.persistence.FetchType;
|
||||||
@@ -28,53 +25,25 @@ import javax.persistence.Table;
|
|||||||
@IdClass(SwMetadataCompositeKey.class)
|
@IdClass(SwMetadataCompositeKey.class)
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "sp_sw_metadata")
|
@Table(name = "sp_sw_metadata")
|
||||||
public class SoftwareModuleMetadata implements Serializable {
|
public class SoftwareModuleMetadata extends MetaData {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
@Id
|
|
||||||
@Column(name = "meta_key", length = 128)
|
|
||||||
private String key;
|
|
||||||
|
|
||||||
@Column(name = "meta_value", length = 4000)
|
|
||||||
private String value;
|
|
||||||
|
|
||||||
@Id
|
@Id
|
||||||
@ManyToOne(targetEntity = SoftwareModule.class, fetch = FetchType.LAZY)
|
@ManyToOne(targetEntity = SoftwareModule.class, fetch = FetchType.LAZY)
|
||||||
@JoinColumn(name = "sw_id", foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_metadata_sw"))
|
@JoinColumn(name = "sw_id", foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_metadata_sw"))
|
||||||
private SoftwareModule softwareModule;
|
private SoftwareModule softwareModule;
|
||||||
|
|
||||||
/**
|
|
||||||
* Default constructor for JPA.
|
|
||||||
*/
|
|
||||||
public SoftwareModuleMetadata() {
|
public SoftwareModuleMetadata() {
|
||||||
// default constructor for JPA.
|
// default public constructor for JPA
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Standard constructor.
|
|
||||||
*
|
|
||||||
* @param key
|
|
||||||
* of the meta data element
|
|
||||||
* @param softwareModule
|
|
||||||
* @param value
|
|
||||||
* of the meta data element
|
|
||||||
*/
|
|
||||||
public SoftwareModuleMetadata(final String key, final SoftwareModule softwareModule, final String value) {
|
public SoftwareModuleMetadata(final String key, final SoftwareModule softwareModule, final String value) {
|
||||||
this.key = key;
|
super(key, value);
|
||||||
this.softwareModule = softwareModule;
|
this.softwareModule = softwareModule;
|
||||||
this.value = value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public SwMetadataCompositeKey getId() {
|
public SwMetadataCompositeKey getId() {
|
||||||
return new SwMetadataCompositeKey(softwareModule, key);
|
return new SwMetadataCompositeKey(softwareModule, getKey());
|
||||||
}
|
|
||||||
|
|
||||||
public String getValue() {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setValue(final String value) {
|
|
||||||
this.value = value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public SoftwareModule getSoftwareModule() {
|
public SoftwareModule getSoftwareModule() {
|
||||||
@@ -85,47 +54,20 @@ public class SoftwareModuleMetadata implements Serializable {
|
|||||||
this.softwareModule = softwareModule;
|
this.softwareModule = softwareModule;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getKey() {
|
|
||||||
return key;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setKey(final String key) {
|
|
||||||
this.key = key;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "SoftwareModuleMetadata [key=" + key + ", value=" + value + ", softwareModule=" + softwareModule + "]";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
final int prime = 31;
|
final int prime = 31;
|
||||||
int result = 1;
|
int result = super.hashCode();
|
||||||
result = prime * result + ((key == null) ? 0 : key.hashCode());
|
|
||||||
result = prime * result + ((softwareModule == null) ? 0 : softwareModule.hashCode());
|
result = prime * result + ((softwareModule == null) ? 0 : softwareModule.hashCode());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(final Object obj) {
|
public boolean equals(final Object obj) {
|
||||||
if (this == obj) {
|
if (!super.equals(obj)) {
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (obj == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!(obj instanceof SoftwareModuleMetadata)) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
final SoftwareModuleMetadata other = (SoftwareModuleMetadata) obj;
|
final SoftwareModuleMetadata other = (SoftwareModuleMetadata) obj;
|
||||||
if (key == null) {
|
|
||||||
if (other.key != null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else if (!key.equals(other.key)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (softwareModule == null) {
|
if (softwareModule == null) {
|
||||||
if (other.softwareModule != null) {
|
if (other.softwareModule != null) {
|
||||||
return false;
|
return false;
|
||||||
@@ -135,5 +77,4 @@ public class SoftwareModuleMetadata implements Serializable {
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,9 +14,11 @@ import javax.validation.constraints.NotNull;
|
|||||||
|
|
||||||
import org.springframework.hateoas.ResourceSupport;
|
import org.springframework.hateoas.ResourceSupport;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A list representation with meta data for pagination, e.g. containing the
|
* A list representation with meta data for pagination, e.g. containing the
|
||||||
@@ -31,8 +33,10 @@ import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
|||||||
@JsonInclude(Include.NON_NULL)
|
@JsonInclude(Include.NON_NULL)
|
||||||
public class PagedList<T> extends ResourceSupport {
|
public class PagedList<T> extends ResourceSupport {
|
||||||
|
|
||||||
|
@JsonProperty
|
||||||
private final List<T> content;
|
private final List<T> content;
|
||||||
private final long totalElements;
|
@JsonProperty
|
||||||
|
private final long total;
|
||||||
private final int size;
|
private final int size;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -46,9 +50,10 @@ public class PagedList<T> extends ResourceSupport {
|
|||||||
* @throws NullPointerException
|
* @throws NullPointerException
|
||||||
* in case {@code content} is {@code null}.
|
* in case {@code content} is {@code null}.
|
||||||
*/
|
*/
|
||||||
public PagedList(@NotNull final List<T> content, final long total) {
|
@JsonCreator
|
||||||
|
public PagedList(@JsonProperty("content") @NotNull final List<T> content, @JsonProperty("total") final long total) {
|
||||||
this.size = content.size();
|
this.size = content.size();
|
||||||
this.totalElements = total;
|
this.total = total;
|
||||||
this.content = content;
|
this.content = content;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,7 +68,7 @@ public class PagedList<T> extends ResourceSupport {
|
|||||||
* @return the total amount of elements
|
* @return the total amount of elements
|
||||||
*/
|
*/
|
||||||
public long getTotal() {
|
public long getTotal() {
|
||||||
return totalElements;
|
return total;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<T> getContent() {
|
public List<T> getContent() {
|
||||||
|
|||||||
@@ -25,6 +25,11 @@
|
|||||||
<groupId>org.eclipse.hawkbit</groupId>
|
<groupId>org.eclipse.hawkbit</groupId>
|
||||||
<artifactId>hawkbit-repository</artifactId>
|
<artifactId>hawkbit-repository</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.hawkbit</groupId>
|
||||||
|
<artifactId>hawkbit-core</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.eclipse.hawkbit</groupId>
|
<groupId>org.eclipse.hawkbit</groupId>
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ import java.util.stream.Collectors;
|
|||||||
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import org.eclipse.hawkbit.api.ArtifactUrlHandler;
|
||||||
|
import org.eclipse.hawkbit.api.UrlProtocol;
|
||||||
import org.eclipse.hawkbit.controller.model.Artifact;
|
import org.eclipse.hawkbit.controller.model.Artifact;
|
||||||
import org.eclipse.hawkbit.controller.model.Chunk;
|
import org.eclipse.hawkbit.controller.model.Chunk;
|
||||||
import org.eclipse.hawkbit.controller.model.Config;
|
import org.eclipse.hawkbit.controller.model.Config;
|
||||||
@@ -29,27 +31,29 @@ import org.eclipse.hawkbit.repository.model.LocalArtifact;
|
|||||||
import org.eclipse.hawkbit.repository.model.Target;
|
import org.eclipse.hawkbit.repository.model.Target;
|
||||||
import org.eclipse.hawkbit.rest.resource.model.artifact.ArtifactHash;
|
import org.eclipse.hawkbit.rest.resource.model.artifact.ArtifactHash;
|
||||||
import org.eclipse.hawkbit.tenancy.TenantAware;
|
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.hateoas.Link;
|
||||||
|
|
||||||
import com.google.common.base.Charsets;
|
import com.google.common.base.Charsets;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility class for the Controller API.
|
* Utility class for the Controller API.
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public final class DataConversionHelper {
|
public final class DataConversionHelper {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
ArtifactUrlHandler artifactUrlHandler;
|
||||||
|
|
||||||
// utility class, private constructor.
|
// utility class, private constructor.
|
||||||
private DataConversionHelper() {
|
private DataConversionHelper() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static List<Chunk> createChunks(final String targetid, final Action uAction, final TenantAware tenantAware) {
|
static List<Chunk> createChunks(final String targetid, final Action uAction,
|
||||||
return uAction.getDistributionSet()
|
final ArtifactUrlHandler artifactUrlHandler) {
|
||||||
.getModules().stream().map(module -> new Chunk(mapChunkLegacyKeys(module.getType().getKey()),
|
return uAction.getDistributionSet().getModules().stream()
|
||||||
module.getVersion(), module.getName(), createArtifacts(targetid, module, tenantAware)))
|
.map(module -> new Chunk(mapChunkLegacyKeys(module.getType().getKey()), module.getVersion(),
|
||||||
|
module.getName(), createArtifacts(targetid, module, artifactUrlHandler)))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -72,23 +76,25 @@ public final class DataConversionHelper {
|
|||||||
* of the target
|
* of the target
|
||||||
* @param module
|
* @param module
|
||||||
* the software module
|
* the software module
|
||||||
* @param tenantAware
|
|
||||||
* of the tenant
|
|
||||||
* @return a list of artifacts or a empty list. Cannot be <null>.
|
* @return a list of artifacts or a empty list. Cannot be <null>.
|
||||||
*/
|
*/
|
||||||
public static List<Artifact> createArtifacts(final String targetid,
|
public static List<Artifact> createArtifacts(final String targetid,
|
||||||
final org.eclipse.hawkbit.repository.model.SoftwareModule module, final TenantAware tenantAware) {
|
final org.eclipse.hawkbit.repository.model.SoftwareModule module,
|
||||||
|
final ArtifactUrlHandler artifactUrlHandler) {
|
||||||
final List<Artifact> files = new ArrayList<>();
|
final List<Artifact> files = new ArrayList<>();
|
||||||
module.getLocalArtifacts().forEach(artifact -> {
|
module.getLocalArtifacts().forEach(artifact -> {
|
||||||
final Artifact file = new Artifact();
|
final Artifact file = new Artifact();
|
||||||
file.setHashes(new ArtifactHash(artifact.getSha1Hash(), artifact.getMd5Hash()));
|
file.setHashes(new ArtifactHash(artifact.getSha1Hash(), artifact.getMd5Hash()));
|
||||||
file.setFilename(artifact.getFilename());
|
file.setFilename(artifact.getFilename());
|
||||||
file.setSize(artifact.getSize());
|
file.setSize(artifact.getSize());
|
||||||
|
final String linkHttp = artifactUrlHandler.getUrl(targetid, artifact.getSoftwareModule().getId(),
|
||||||
file.add(linkTo(methodOn(RootController.class, tenantAware.getCurrentTenant()).downloadArtifact(targetid,
|
artifact.getFilename(), artifact.getSha1Hash(), UrlProtocol.HTTP);
|
||||||
artifact.getSoftwareModule().getId(), artifact.getFilename(), null, null)).withRel("download"));
|
final String linkHttps = artifactUrlHandler.getUrl(targetid, artifact.getSoftwareModule().getId(),
|
||||||
file.add(linkTo(methodOn(RootController.class, tenantAware.getCurrentTenant()).downloadArtifactMd5(targetid,
|
artifact.getFilename(), artifact.getSha1Hash(), UrlProtocol.HTTPS);
|
||||||
artifact.getSoftwareModule().getId(), artifact.getFilename(), null, null)).withRel("md5sum"));
|
file.add(new Link(linkHttps).withRel("download"));
|
||||||
|
file.add(new Link(linkHttps + ControllerConstants.ARTIFACT_MD5_DWNL_SUFFIX).withRel("md5sum"));
|
||||||
|
file.add(new Link(linkHttp).withRel("download-http"));
|
||||||
|
file.add(new Link(linkHttp + ControllerConstants.ARTIFACT_MD5_DWNL_SUFFIX).withRel("md5sum-http"));
|
||||||
|
|
||||||
files.add(file);
|
files.add(file);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import javax.servlet.http.HttpServletRequest;
|
|||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
|
|
||||||
|
import org.eclipse.hawkbit.api.ArtifactUrlHandler;
|
||||||
import org.eclipse.hawkbit.artifact.repository.model.DbArtifact;
|
import org.eclipse.hawkbit.artifact.repository.model.DbArtifact;
|
||||||
import org.eclipse.hawkbit.cache.CacheWriteNotify;
|
import org.eclipse.hawkbit.cache.CacheWriteNotify;
|
||||||
import org.eclipse.hawkbit.controller.model.ActionFeedback;
|
import org.eclipse.hawkbit.controller.model.ActionFeedback;
|
||||||
@@ -84,11 +85,14 @@ public class RootController {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private CacheWriteNotify cacheWriteNotify;
|
private CacheWriteNotify cacheWriteNotify;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private HawkbitSecurityProperties securityProperties;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private TenantAware tenantAware;
|
private TenantAware tenantAware;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private HawkbitSecurityProperties securityProperties;
|
private ArtifactUrlHandler artifactUrlHandler;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns all artifacts of a given software module and target.
|
* Returns all artifacts of a given software module and target.
|
||||||
@@ -114,7 +118,7 @@ public class RootController {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ResponseEntity<>(DataConversionHelper.createArtifacts(targetid, softwareModule, tenantAware),
|
return new ResponseEntity<>(DataConversionHelper.createArtifacts(targetid, softwareModule, artifactUrlHandler),
|
||||||
HttpStatus.OK);
|
HttpStatus.OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -303,7 +307,7 @@ public class RootController {
|
|||||||
|
|
||||||
if (!action.isCancelingOrCanceled()) {
|
if (!action.isCancelingOrCanceled()) {
|
||||||
|
|
||||||
final List<Chunk> chunks = DataConversionHelper.createChunks(targetid, action, tenantAware);
|
final List<Chunk> chunks = DataConversionHelper.createChunks(targetid, action, artifactUrlHandler);
|
||||||
|
|
||||||
final HandlingType handlingType = action.isForce() ? HandlingType.FORCED : HandlingType.ATTEMPT;
|
final HandlingType handlingType = action.isForce() ? HandlingType.FORCED : HandlingType.ATTEMPT;
|
||||||
|
|
||||||
|
|||||||
@@ -170,15 +170,27 @@ public class DeploymentBaseTest extends AbstractIntegrationTestWithMongoDB {
|
|||||||
jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[0].hashes.sha1",
|
jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[0].hashes.sha1",
|
||||||
equalTo(artifact.getSha1Hash())))
|
equalTo(artifact.getSha1Hash())))
|
||||||
.andExpect(jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[0]._links.download.href",
|
.andExpect(jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[0]._links.download.href",
|
||||||
equalTo("http://localhost/" + tenantAware.getCurrentTenant()
|
equalTo("https://localhost/" + tenantAware.getCurrentTenant()
|
||||||
+ "/controller/v1/4712/softwaremodules/"
|
+ "/controller/v1/4712/softwaremodules/"
|
||||||
+ findDistributionSetByAction.findFirstModuleByType(osType).getId()
|
+ findDistributionSetByAction.findFirstModuleByType(osType).getId()
|
||||||
+ "/artifacts/test1")))
|
+ "/artifacts/test1")))
|
||||||
.andExpect(jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[0]._links.md5sum.href",
|
.andExpect(jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[0]._links.md5sum.href",
|
||||||
|
equalTo("https://localhost/" + tenantAware.getCurrentTenant()
|
||||||
|
+ "/controller/v1/4712/softwaremodules/"
|
||||||
|
+ findDistributionSetByAction.findFirstModuleByType(osType).getId()
|
||||||
|
+ "/artifacts/test1.MD5SUM")))
|
||||||
|
|
||||||
|
.andExpect(jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[0]._links.download-http.href",
|
||||||
|
equalTo("http://localhost/" + tenantAware.getCurrentTenant()
|
||||||
|
+ "/controller/v1/4712/softwaremodules/"
|
||||||
|
+ findDistributionSetByAction.findFirstModuleByType(osType).getId()
|
||||||
|
+ "/artifacts/test1")))
|
||||||
|
.andExpect(jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[0]._links.md5sum-http.href",
|
||||||
equalTo("http://localhost/" + tenantAware.getCurrentTenant()
|
equalTo("http://localhost/" + tenantAware.getCurrentTenant()
|
||||||
+ "/controller/v1/4712/softwaremodules/"
|
+ "/controller/v1/4712/softwaremodules/"
|
||||||
+ findDistributionSetByAction.findFirstModuleByType(osType).getId()
|
+ findDistributionSetByAction.findFirstModuleByType(osType).getId()
|
||||||
+ "/artifacts/test1.MD5SUM")))
|
+ "/artifacts/test1.MD5SUM")))
|
||||||
|
|
||||||
.andExpect(jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[1].size", equalTo(5 * 1024)))
|
.andExpect(jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[1].size", equalTo(5 * 1024)))
|
||||||
.andExpect(jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[1].filename",
|
.andExpect(jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[1].filename",
|
||||||
equalTo("test1.signature")))
|
equalTo("test1.signature")))
|
||||||
@@ -188,11 +200,21 @@ public class DeploymentBaseTest extends AbstractIntegrationTestWithMongoDB {
|
|||||||
jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[1].hashes.sha1",
|
jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[1].hashes.sha1",
|
||||||
equalTo(artifactSignature.getSha1Hash())))
|
equalTo(artifactSignature.getSha1Hash())))
|
||||||
.andExpect(jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[1]._links.download.href",
|
.andExpect(jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[1]._links.download.href",
|
||||||
equalTo("http://localhost/" + tenantAware.getCurrentTenant()
|
equalTo("https://localhost/" + tenantAware.getCurrentTenant()
|
||||||
+ "/controller/v1/4712/softwaremodules/"
|
+ "/controller/v1/4712/softwaremodules/"
|
||||||
+ findDistributionSetByAction.findFirstModuleByType(osType).getId()
|
+ findDistributionSetByAction.findFirstModuleByType(osType).getId()
|
||||||
+ "/artifacts/test1.signature")))
|
+ "/artifacts/test1.signature")))
|
||||||
.andExpect(jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[1]._links.md5sum.href",
|
.andExpect(jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[1]._links.md5sum.href",
|
||||||
|
equalTo("https://localhost/" + tenantAware.getCurrentTenant()
|
||||||
|
+ "/controller/v1/4712/softwaremodules/"
|
||||||
|
+ findDistributionSetByAction.findFirstModuleByType(osType).getId()
|
||||||
|
+ "/artifacts/test1.signature.MD5SUM")))
|
||||||
|
.andExpect(jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[1]._links.download-http.href",
|
||||||
|
equalTo("http://localhost/" + tenantAware.getCurrentTenant()
|
||||||
|
+ "/controller/v1/4712/softwaremodules/"
|
||||||
|
+ findDistributionSetByAction.findFirstModuleByType(osType).getId()
|
||||||
|
+ "/artifacts/test1.signature")))
|
||||||
|
.andExpect(jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[1]._links.md5sum-http.href",
|
||||||
equalTo("http://localhost/" + tenantAware.getCurrentTenant()
|
equalTo("http://localhost/" + tenantAware.getCurrentTenant()
|
||||||
+ "/controller/v1/4712/softwaremodules/"
|
+ "/controller/v1/4712/softwaremodules/"
|
||||||
+ findDistributionSetByAction.findFirstModuleByType(osType).getId()
|
+ findDistributionSetByAction.findFirstModuleByType(osType).getId()
|
||||||
@@ -293,12 +315,12 @@ public class DeploymentBaseTest extends AbstractIntegrationTestWithMongoDB {
|
|||||||
jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[0].hashes.sha1",
|
jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[0].hashes.sha1",
|
||||||
equalTo(artifact.getSha1Hash())))
|
equalTo(artifact.getSha1Hash())))
|
||||||
.andExpect(jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[0]._links.download.href",
|
.andExpect(jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[0]._links.download.href",
|
||||||
equalTo("http://localhost/" + tenantAware.getCurrentTenant()
|
equalTo("https://localhost/" + tenantAware.getCurrentTenant()
|
||||||
+ "/controller/v1/4712/softwaremodules/"
|
+ "/controller/v1/4712/softwaremodules/"
|
||||||
+ findDistributionSetByAction.findFirstModuleByType(osType).getId()
|
+ findDistributionSetByAction.findFirstModuleByType(osType).getId()
|
||||||
+ "/artifacts/test1")))
|
+ "/artifacts/test1")))
|
||||||
.andExpect(jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[0]._links.md5sum.href",
|
.andExpect(jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[0]._links.md5sum.href",
|
||||||
equalTo("http://localhost/" + tenantAware.getCurrentTenant()
|
equalTo("https://localhost/" + tenantAware.getCurrentTenant()
|
||||||
+ "/controller/v1/4712/softwaremodules/"
|
+ "/controller/v1/4712/softwaremodules/"
|
||||||
+ findDistributionSetByAction.findFirstModuleByType(osType).getId()
|
+ findDistributionSetByAction.findFirstModuleByType(osType).getId()
|
||||||
+ "/artifacts/test1.MD5SUM")))
|
+ "/artifacts/test1.MD5SUM")))
|
||||||
@@ -311,11 +333,21 @@ public class DeploymentBaseTest extends AbstractIntegrationTestWithMongoDB {
|
|||||||
jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[1].hashes.sha1",
|
jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[1].hashes.sha1",
|
||||||
equalTo(artifactSignature.getSha1Hash())))
|
equalTo(artifactSignature.getSha1Hash())))
|
||||||
.andExpect(jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[1]._links.download.href",
|
.andExpect(jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[1]._links.download.href",
|
||||||
equalTo("http://localhost/" + tenantAware.getCurrentTenant()
|
equalTo("https://localhost/" + tenantAware.getCurrentTenant()
|
||||||
+ "/controller/v1/4712/softwaremodules/"
|
+ "/controller/v1/4712/softwaremodules/"
|
||||||
+ findDistributionSetByAction.findFirstModuleByType(osType).getId()
|
+ findDistributionSetByAction.findFirstModuleByType(osType).getId()
|
||||||
+ "/artifacts/test1.signature")))
|
+ "/artifacts/test1.signature")))
|
||||||
.andExpect(jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[1]._links.md5sum.href",
|
.andExpect(jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[1]._links.md5sum.href",
|
||||||
|
equalTo("https://localhost/" + tenantAware.getCurrentTenant()
|
||||||
|
+ "/controller/v1/4712/softwaremodules/"
|
||||||
|
+ findDistributionSetByAction.findFirstModuleByType(osType).getId()
|
||||||
|
+ "/artifacts/test1.signature.MD5SUM")))
|
||||||
|
.andExpect(jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[1]._links.download-http.href",
|
||||||
|
equalTo("http://localhost/" + tenantAware.getCurrentTenant()
|
||||||
|
+ "/controller/v1/4712/softwaremodules/"
|
||||||
|
+ findDistributionSetByAction.findFirstModuleByType(osType).getId()
|
||||||
|
+ "/artifacts/test1.signature")))
|
||||||
|
.andExpect(jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[1]._links.md5sum-http.href",
|
||||||
equalTo("http://localhost/" + tenantAware.getCurrentTenant()
|
equalTo("http://localhost/" + tenantAware.getCurrentTenant()
|
||||||
+ "/controller/v1/4712/softwaremodules/"
|
+ "/controller/v1/4712/softwaremodules/"
|
||||||
+ findDistributionSetByAction.findFirstModuleByType(osType).getId()
|
+ findDistributionSetByAction.findFirstModuleByType(osType).getId()
|
||||||
@@ -409,15 +441,25 @@ public class DeploymentBaseTest extends AbstractIntegrationTestWithMongoDB {
|
|||||||
.andExpect(jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[0].filename", equalTo("test1")))
|
.andExpect(jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[0].filename", equalTo("test1")))
|
||||||
.andExpect(jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[0].hashes.md5",
|
.andExpect(jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[0].hashes.md5",
|
||||||
equalTo(artifact.getMd5Hash())))
|
equalTo(artifact.getMd5Hash())))
|
||||||
.andExpect(
|
.andExpect(jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[0].hashes.sha1",
|
||||||
jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[0].hashes.sha1",
|
equalTo(artifact.getSha1Hash())))
|
||||||
equalTo(artifact.getSha1Hash())))
|
|
||||||
.andExpect(jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[0]._links.download.href",
|
.andExpect(jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[0]._links.download.href",
|
||||||
equalTo("http://localhost/" + tenantAware.getCurrentTenant()
|
equalTo("https://localhost/" + tenantAware.getCurrentTenant()
|
||||||
+ "/controller/v1/4712/softwaremodules/"
|
+ "/controller/v1/4712/softwaremodules/"
|
||||||
+ findDistributionSetByAction.findFirstModuleByType(osType).getId()
|
+ findDistributionSetByAction.findFirstModuleByType(osType).getId()
|
||||||
+ "/artifacts/test1")))
|
+ "/artifacts/test1")))
|
||||||
.andExpect(jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[0]._links.md5sum.href",
|
.andExpect(jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[0]._links.md5sum.href",
|
||||||
|
equalTo("https://localhost/" + tenantAware.getCurrentTenant()
|
||||||
|
+ "/controller/v1/4712/softwaremodules/"
|
||||||
|
+ findDistributionSetByAction.findFirstModuleByType(osType).getId()
|
||||||
|
+ "/artifacts/test1.MD5SUM")))
|
||||||
|
.andExpect(jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[0]._links.download-http.href",
|
||||||
|
equalTo("http://localhost/" + tenantAware.getCurrentTenant()
|
||||||
|
+ "/controller/v1/4712/softwaremodules/"
|
||||||
|
+ findDistributionSetByAction.findFirstModuleByType(osType).getId()
|
||||||
|
+ "/artifacts/test1")))
|
||||||
|
.andExpect(jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[0]._links.md5sum-http.href",
|
||||||
equalTo("http://localhost/" + tenantAware.getCurrentTenant()
|
equalTo("http://localhost/" + tenantAware.getCurrentTenant()
|
||||||
+ "/controller/v1/4712/softwaremodules/"
|
+ "/controller/v1/4712/softwaremodules/"
|
||||||
+ findDistributionSetByAction.findFirstModuleByType(osType).getId()
|
+ findDistributionSetByAction.findFirstModuleByType(osType).getId()
|
||||||
@@ -431,15 +473,27 @@ public class DeploymentBaseTest extends AbstractIntegrationTestWithMongoDB {
|
|||||||
jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[1].hashes.sha1",
|
jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[1].hashes.sha1",
|
||||||
equalTo(artifactSignature.getSha1Hash())))
|
equalTo(artifactSignature.getSha1Hash())))
|
||||||
.andExpect(jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[1]._links.download.href",
|
.andExpect(jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[1]._links.download.href",
|
||||||
equalTo("http://localhost/" + tenantAware.getCurrentTenant()
|
equalTo("https://localhost/" + tenantAware.getCurrentTenant()
|
||||||
+ "/controller/v1/4712/softwaremodules/"
|
+ "/controller/v1/4712/softwaremodules/"
|
||||||
+ findDistributionSetByAction.findFirstModuleByType(osType).getId()
|
+ findDistributionSetByAction.findFirstModuleByType(osType).getId()
|
||||||
+ "/artifacts/test1.signature")))
|
+ "/artifacts/test1.signature")))
|
||||||
.andExpect(jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[1]._links.md5sum.href",
|
.andExpect(jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[1]._links.md5sum.href",
|
||||||
|
equalTo("https://localhost/" + tenantAware.getCurrentTenant()
|
||||||
|
+ "/controller/v1/4712/softwaremodules/"
|
||||||
|
+ findDistributionSetByAction.findFirstModuleByType(osType).getId()
|
||||||
|
+ "/artifacts/test1.signature.MD5SUM")))
|
||||||
|
|
||||||
|
.andExpect(jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[1]._links.download-http.href",
|
||||||
|
equalTo("http://localhost/" + tenantAware.getCurrentTenant()
|
||||||
|
+ "/controller/v1/4712/softwaremodules/"
|
||||||
|
+ findDistributionSetByAction.findFirstModuleByType(osType).getId()
|
||||||
|
+ "/artifacts/test1.signature")))
|
||||||
|
.andExpect(jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[1]._links.md5sum-http.href",
|
||||||
equalTo("http://localhost/" + tenantAware.getCurrentTenant()
|
equalTo("http://localhost/" + tenantAware.getCurrentTenant()
|
||||||
+ "/controller/v1/4712/softwaremodules/"
|
+ "/controller/v1/4712/softwaremodules/"
|
||||||
+ findDistributionSetByAction.findFirstModuleByType(osType).getId()
|
+ findDistributionSetByAction.findFirstModuleByType(osType).getId()
|
||||||
+ "/artifacts/test1.signature.MD5SUM")))
|
+ "/artifacts/test1.signature.MD5SUM")))
|
||||||
|
|
||||||
.andExpect(jsonPath("$deployment.chunks[?(@.part==bApp)][0].version",
|
.andExpect(jsonPath("$deployment.chunks[?(@.part==bApp)][0].version",
|
||||||
equalTo(ds.findFirstModuleByType(appType).getVersion())))
|
equalTo(ds.findFirstModuleByType(appType).getVersion())))
|
||||||
.andExpect(jsonPath("$deployment.chunks[?(@.part==bApp)][0].name",
|
.andExpect(jsonPath("$deployment.chunks[?(@.part==bApp)][0].name",
|
||||||
|
|||||||
@@ -182,6 +182,12 @@ public final class SpPermission {
|
|||||||
*/
|
*/
|
||||||
public static final String CONTROLLER_ROLE_ANONYMOUS = "ROLE_CONTROLLER_ANONYMOUS";
|
public static final String CONTROLLER_ROLE_ANONYMOUS = "ROLE_CONTROLLER_ANONYMOUS";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The role which contains in the spring security context in case an
|
||||||
|
* controller is authenticated to download artifacts.
|
||||||
|
*/
|
||||||
|
public static final String CONTROLLER_DOWNLOAD_ROLE = "ROLE_CONTROLLER_DOWNLOAD";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The role which contains the spring security context in case the
|
* The role which contains the spring security context in case the
|
||||||
* system is executing code which is necessary to be privileged.
|
* system is executing code which is necessary to be privileged.
|
||||||
@@ -275,8 +281,16 @@ public final class SpPermission {
|
|||||||
* context contains the anoynmous role or the controller specific role
|
* context contains the anoynmous role or the controller specific role
|
||||||
* {@link SpPermission#CONTROLLER_ROLE}.
|
* {@link SpPermission#CONTROLLER_ROLE}.
|
||||||
*/
|
*/
|
||||||
public static final String IS_CONTROLLER = "hasAnyRole('" + CONTROLLER_ROLE_ANONYMOUS + "', '"
|
public static final String IS_CONTROLLER = "hasAnyRole('" + CONTROLLER_ROLE_ANONYMOUS + "', '" + CONTROLLER_ROLE
|
||||||
+ CONTROLLER_ROLE + "')";
|
+ "')";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Spring security eval hasAuthority expression to check if the spring
|
||||||
|
* context contains the role to allow controllers to download specific
|
||||||
|
* role {@link SpPermission#CONTROLLER_DOWNLOAD_ROLE}.
|
||||||
|
*/
|
||||||
|
public static final String HAS_CONTROLLER_DOWNLOAD = HAS_AUTH_PREFIX + CONTROLLER_DOWNLOAD_ROLE
|
||||||
|
+ HAS_AUTH_SUFFIX;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Spring security eval hasAnyRole expression to check if the spring
|
* Spring security eval hasAnyRole expression to check if the spring
|
||||||
|
|||||||
@@ -35,7 +35,32 @@
|
|||||||
<groupId>org.springframework.security</groupId>
|
<groupId>org.springframework.security</groupId>
|
||||||
<artifactId>spring-security-web</artifactId>
|
<artifactId>spring-security-web</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- TEST -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.easytesting</groupId>
|
||||||
|
<artifactId>fest-assert-core</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.easytesting</groupId>
|
||||||
|
<artifactId>fest-assert</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.mockito</groupId>
|
||||||
|
<artifactId>mockito-core</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>ru.yandex.qatools.allure</groupId>
|
||||||
|
<artifactId>allure-junit-adaptor</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.eclipse.hawkbit.security;
|
package org.eclipse.hawkbit.security;
|
||||||
|
|
||||||
import org.eclipse.hawkbit.dmf.json.model.TenantSecruityToken;
|
import org.eclipse.hawkbit.dmf.json.model.TenantSecurityToken;
|
||||||
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
|
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
|
||||||
import org.eclipse.hawkbit.tenancy.TenantAware;
|
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||||
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationKey;
|
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationKey;
|
||||||
@@ -42,15 +42,15 @@ public abstract class AbstractControllerAuthenticationFilter implements PreAuthe
|
|||||||
protected abstract TenantConfigurationKey getTenantConfigurationKey();
|
protected abstract TenantConfigurationKey getTenantConfigurationKey();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isEnable(final TenantSecruityToken secruityToken) {
|
public boolean isEnable(final TenantSecurityToken secruityToken) {
|
||||||
return tenantAware.runAsTenant(secruityToken.getTenant(), configurationKeyTenantRunner);
|
return tenantAware.runAsTenant(secruityToken.getTenant(), configurationKeyTenantRunner);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public abstract HeaderAuthentication getPreAuthenticatedPrincipal(TenantSecruityToken secruityToken);
|
public abstract HeaderAuthentication getPreAuthenticatedPrincipal(TenantSecurityToken secruityToken);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public abstract HeaderAuthentication getPreAuthenticatedCredentials(TenantSecruityToken secruityToken);
|
public abstract HeaderAuthentication getPreAuthenticatedCredentials(TenantSecurityToken secruityToken);
|
||||||
|
|
||||||
private final class SecurityConfigurationKeyTenantRunner implements TenantAware.TenantRunner<Boolean> {
|
private final class SecurityConfigurationKeyTenantRunner implements TenantAware.TenantRunner<Boolean> {
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.eclipse.hawkbit.security;
|
package org.eclipse.hawkbit.security;
|
||||||
|
|
||||||
import org.eclipse.hawkbit.dmf.json.model.TenantSecruityToken;
|
import org.eclipse.hawkbit.dmf.json.model.TenantSecurityToken;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A Filter for device which download via coap.
|
* A Filter for device which download via coap.
|
||||||
@@ -19,19 +19,19 @@ import org.eclipse.hawkbit.dmf.json.model.TenantSecruityToken;
|
|||||||
public class CoapAnonymousPreAuthenticatedFilter implements PreAuthenficationFilter {
|
public class CoapAnonymousPreAuthenticatedFilter implements PreAuthenficationFilter {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HeaderAuthentication getPreAuthenticatedPrincipal(final TenantSecruityToken secruityToken) {
|
public HeaderAuthentication getPreAuthenticatedPrincipal(final TenantSecurityToken secruityToken) {
|
||||||
return new HeaderAuthentication(secruityToken.getControllerId(), TenantSecruityToken.COAP_TOKEN_VALUE);
|
return new HeaderAuthentication(secruityToken.getControllerId(), TenantSecurityToken.COAP_TOKEN_VALUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HeaderAuthentication getPreAuthenticatedCredentials(final TenantSecruityToken secruityToken) {
|
public HeaderAuthentication getPreAuthenticatedCredentials(final TenantSecurityToken secruityToken) {
|
||||||
return new HeaderAuthentication(secruityToken.getControllerId(), TenantSecruityToken.COAP_TOKEN_VALUE);
|
return new HeaderAuthentication(secruityToken.getControllerId(), TenantSecurityToken.COAP_TOKEN_VALUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isEnable(final TenantSecruityToken secruityToken) {
|
public boolean isEnable(final TenantSecurityToken secruityToken) {
|
||||||
final String authHeader = secruityToken.getHeader(TenantSecruityToken.COAP_AUTHORIZATION_HEADER);
|
final String authHeader = secruityToken.getHeader(TenantSecurityToken.COAP_AUTHORIZATION_HEADER);
|
||||||
return TenantSecruityToken.COAP_TOKEN_VALUE.equals(authHeader);
|
return TenantSecurityToken.COAP_TOKEN_VALUE.equals(authHeader);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.eclipse.hawkbit.security;
|
package org.eclipse.hawkbit.security;
|
||||||
|
|
||||||
import org.eclipse.hawkbit.dmf.json.model.TenantSecruityToken;
|
import org.eclipse.hawkbit.dmf.json.model.TenantSecurityToken;
|
||||||
import org.eclipse.hawkbit.im.authentication.SpPermission;
|
import org.eclipse.hawkbit.im.authentication.SpPermission;
|
||||||
import org.eclipse.hawkbit.im.authentication.TenantAwareAuthenticationDetails;
|
import org.eclipse.hawkbit.im.authentication.TenantAwareAuthenticationDetails;
|
||||||
import org.eclipse.hawkbit.repository.ControllerManagement;
|
import org.eclipse.hawkbit.repository.ControllerManagement;
|
||||||
@@ -67,8 +67,8 @@ public class ControllerPreAuthenticateSecurityTokenFilter extends AbstractContro
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HeaderAuthentication getPreAuthenticatedPrincipal(final TenantSecruityToken secruityToken) {
|
public HeaderAuthentication getPreAuthenticatedPrincipal(final TenantSecurityToken secruityToken) {
|
||||||
final String authHeader = secruityToken.getHeader(TenantSecruityToken.AUTHORIZATION_HEADER);
|
final String authHeader = secruityToken.getHeader(TenantSecurityToken.AUTHORIZATION_HEADER);
|
||||||
if ((authHeader != null) && authHeader.startsWith(TARGET_SECURITY_TOKEN_AUTH_SCHEME)) {
|
if ((authHeader != null) && authHeader.startsWith(TARGET_SECURITY_TOKEN_AUTH_SCHEME)) {
|
||||||
LOGGER.debug("found authorization header with scheme {} using target security token for authentication",
|
LOGGER.debug("found authorization header with scheme {} using target security token for authentication",
|
||||||
TARGET_SECURITY_TOKEN_AUTH_SCHEME);
|
TARGET_SECURITY_TOKEN_AUTH_SCHEME);
|
||||||
@@ -81,7 +81,7 @@ public class ControllerPreAuthenticateSecurityTokenFilter extends AbstractContro
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HeaderAuthentication getPreAuthenticatedCredentials(final TenantSecruityToken secruityToken) {
|
public HeaderAuthentication getPreAuthenticatedCredentials(final TenantSecurityToken secruityToken) {
|
||||||
final String securityToken = tenantAware.runAsTenant(secruityToken.getTenant(),
|
final String securityToken = tenantAware.runAsTenant(secruityToken.getTenant(),
|
||||||
new GetSecurityTokenTenantRunner(secruityToken.getTenant(), secruityToken.getControllerId()));
|
new GetSecurityTokenTenantRunner(secruityToken.getTenant(), secruityToken.getControllerId()));
|
||||||
return new HeaderAuthentication(secruityToken.getControllerId(), securityToken);
|
return new HeaderAuthentication(secruityToken.getControllerId(), securityToken);
|
||||||
|
|||||||
@@ -0,0 +1,69 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||||
|
*
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*/
|
||||||
|
package org.eclipse.hawkbit.security;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import org.eclipse.hawkbit.dmf.json.model.TenantSecurityToken;
|
||||||
|
import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions;
|
||||||
|
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
|
||||||
|
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||||
|
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationKey;
|
||||||
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
|
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An pre-authenticated processing filter which add the
|
||||||
|
* {@link SpringEvalExpressions#CONTROLLER_DOWNLOAD_ROLE_ANONYMOUS} to the
|
||||||
|
* security context in case the anonymous download is allowed through
|
||||||
|
* configuration.
|
||||||
|
*/
|
||||||
|
public class ControllerPreAuthenticatedAnonymousDownload extends AbstractControllerAuthenticationFilter {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param tenantConfigurationManagement
|
||||||
|
* the tenant management service to retrieve configuration
|
||||||
|
* properties
|
||||||
|
* @param tenantAware
|
||||||
|
* the tenant aware service to get configuration for the specific
|
||||||
|
* tenant
|
||||||
|
* @param systemSecurityContext
|
||||||
|
* the system security context to get access to tenant
|
||||||
|
* configuration
|
||||||
|
*/
|
||||||
|
public ControllerPreAuthenticatedAnonymousDownload(
|
||||||
|
final TenantConfigurationManagement tenantConfigurationManagement, final TenantAware tenantAware,
|
||||||
|
final SystemSecurityContext systemSecurityContext) {
|
||||||
|
super(tenantConfigurationManagement, tenantAware, systemSecurityContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HeaderAuthentication getPreAuthenticatedPrincipal(final TenantSecurityToken secruityToken) {
|
||||||
|
return new HeaderAuthentication(secruityToken.getControllerId(), secruityToken.getControllerId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HeaderAuthentication getPreAuthenticatedCredentials(final TenantSecurityToken secruityToken) {
|
||||||
|
return new HeaderAuthentication(secruityToken.getControllerId(), secruityToken.getControllerId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected TenantConfigurationKey getTenantConfigurationKey() {
|
||||||
|
return TenantConfigurationKey.ANONYMOUS_DOWNLOAD_MODE_ENABLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<GrantedAuthority> getSuccessfulAuthenticationAuthorities() {
|
||||||
|
return Lists.newArrayList(new SimpleGrantedAuthority(SpringEvalExpressions.CONTROLLER_DOWNLOAD_ROLE));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||||
|
*
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*/
|
||||||
|
package org.eclipse.hawkbit.security;
|
||||||
|
|
||||||
|
import org.eclipse.hawkbit.dmf.json.model.TenantSecurityToken;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An anonymous controller filter which is only enabled in case of anonymous
|
||||||
|
* access is granted. This should only be for development purposes.
|
||||||
|
*
|
||||||
|
* @see DdiSecurityProperties
|
||||||
|
*/
|
||||||
|
public class ControllerPreAuthenticatedAnonymousFilter implements PreAuthenficationFilter {
|
||||||
|
|
||||||
|
private final DdiSecurityProperties ddiSecurityConfiguration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ddiSecurityConfiguration
|
||||||
|
* the security configuration which holds the configuration if
|
||||||
|
* anonymous is enabled or not
|
||||||
|
*/
|
||||||
|
public ControllerPreAuthenticatedAnonymousFilter(final DdiSecurityProperties ddiSecurityConfiguration) {
|
||||||
|
this.ddiSecurityConfiguration = ddiSecurityConfiguration;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HeaderAuthentication getPreAuthenticatedPrincipal(final TenantSecurityToken secruityToken) {
|
||||||
|
return new HeaderAuthentication(secruityToken.getControllerId(), secruityToken.getControllerId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HeaderAuthentication getPreAuthenticatedCredentials(final TenantSecurityToken secruityToken) {
|
||||||
|
return new HeaderAuthentication(secruityToken.getControllerId(), secruityToken.getControllerId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEnable(final TenantSecurityToken secruityToken) {
|
||||||
|
return ddiSecurityConfiguration.getAuthentication().getAnonymous().isEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.eclipse.hawkbit.security;
|
package org.eclipse.hawkbit.security;
|
||||||
|
|
||||||
import org.eclipse.hawkbit.dmf.json.model.TenantSecruityToken;
|
import org.eclipse.hawkbit.dmf.json.model.TenantSecurityToken;
|
||||||
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
|
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
|
||||||
import org.eclipse.hawkbit.tenancy.TenantAware;
|
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||||
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationKey;
|
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationKey;
|
||||||
@@ -56,8 +56,8 @@ public class ControllerPreAuthenticatedGatewaySecurityTokenFilter extends Abstra
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HeaderAuthentication getPreAuthenticatedPrincipal(final TenantSecruityToken secruityToken) {
|
public HeaderAuthentication getPreAuthenticatedPrincipal(final TenantSecurityToken secruityToken) {
|
||||||
final String authHeader = secruityToken.getHeader(TenantSecruityToken.AUTHORIZATION_HEADER);
|
final String authHeader = secruityToken.getHeader(TenantSecurityToken.AUTHORIZATION_HEADER);
|
||||||
if ((authHeader != null) && authHeader.startsWith(GATEWAY_SECURITY_TOKEN_AUTH_SCHEME)) {
|
if ((authHeader != null) && authHeader.startsWith(GATEWAY_SECURITY_TOKEN_AUTH_SCHEME)) {
|
||||||
LOGGER.debug("found authorization header with scheme {} using target security token for authentication",
|
LOGGER.debug("found authorization header with scheme {} using target security token for authentication",
|
||||||
GATEWAY_SECURITY_TOKEN_AUTH_SCHEME);
|
GATEWAY_SECURITY_TOKEN_AUTH_SCHEME);
|
||||||
@@ -71,7 +71,7 @@ public class ControllerPreAuthenticatedGatewaySecurityTokenFilter extends Abstra
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HeaderAuthentication getPreAuthenticatedCredentials(final TenantSecruityToken secruityToken) {
|
public HeaderAuthentication getPreAuthenticatedCredentials(final TenantSecurityToken secruityToken) {
|
||||||
final String gatewayToken = tenantAware.runAsTenant(secruityToken.getTenant(),
|
final String gatewayToken = tenantAware.runAsTenant(secruityToken.getTenant(),
|
||||||
gatewaySecurityTokenKeyConfigRunner);
|
gatewaySecurityTokenKeyConfigRunner);
|
||||||
return new HeaderAuthentication(secruityToken.getControllerId(), gatewayToken);
|
return new HeaderAuthentication(secruityToken.getControllerId(), gatewayToken);
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.eclipse.hawkbit.security;
|
package org.eclipse.hawkbit.security;
|
||||||
|
|
||||||
import org.eclipse.hawkbit.dmf.json.model.TenantSecruityToken;
|
import org.eclipse.hawkbit.dmf.json.model.TenantSecurityToken;
|
||||||
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
|
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
|
||||||
import org.eclipse.hawkbit.tenancy.TenantAware;
|
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||||
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationKey;
|
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationKey;
|
||||||
@@ -18,7 +18,7 @@ import org.slf4j.LoggerFactory;
|
|||||||
/**
|
/**
|
||||||
* An pre-authenticated processing filter which extracts the principal from a
|
* An pre-authenticated processing filter which extracts the principal from a
|
||||||
* request URI and the credential from a request header in a the
|
* request URI and the credential from a request header in a the
|
||||||
* {@link TenantSecruityToken}.
|
* {@link TenantSecurityToken}.
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
@@ -75,7 +75,7 @@ public class ControllerPreAuthenticatedSecurityHeaderFilter extends AbstractCont
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HeaderAuthentication getPreAuthenticatedPrincipal(final TenantSecruityToken secruityToken) {
|
public HeaderAuthentication getPreAuthenticatedPrincipal(final TenantSecurityToken secruityToken) {
|
||||||
// retrieve the common name header and the authority name header from
|
// retrieve the common name header and the authority name header from
|
||||||
// the http request and
|
// the http request and
|
||||||
// combine them together
|
// combine them together
|
||||||
@@ -97,7 +97,7 @@ public class ControllerPreAuthenticatedSecurityHeaderFilter extends AbstractCont
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HeaderAuthentication getPreAuthenticatedCredentials(final TenantSecruityToken secruityToken) {
|
public HeaderAuthentication getPreAuthenticatedCredentials(final TenantSecurityToken secruityToken) {
|
||||||
final String authorityNameConfigurationValue = tenantAware.runAsTenant(secruityToken.getTenant(),
|
final String authorityNameConfigurationValue = tenantAware.runAsTenant(secruityToken.getTenant(),
|
||||||
sslIssuerNameConfigTenantRunner);
|
sslIssuerNameConfigTenantRunner);
|
||||||
String controllerId = secruityToken.getControllerId();
|
String controllerId = secruityToken.getControllerId();
|
||||||
@@ -117,7 +117,7 @@ public class ControllerPreAuthenticatedSecurityHeaderFilter extends AbstractCont
|
|||||||
* It's ok if we find the the hash in any the trusted CA chain to accept
|
* It's ok if we find the the hash in any the trusted CA chain to accept
|
||||||
* this request for this tenant.
|
* this request for this tenant.
|
||||||
*/
|
*/
|
||||||
private String getIssuerHashHeader(final TenantSecruityToken secruityToken, final String knownIssuerHash) {
|
private String getIssuerHashHeader(final TenantSecurityToken secruityToken, final String knownIssuerHash) {
|
||||||
// iterate over the headers until we get a null header.
|
// iterate over the headers until we get a null header.
|
||||||
int iHeader = 1;
|
int iHeader = 1;
|
||||||
String foundHash;
|
String foundHash;
|
||||||
|
|||||||
@@ -109,6 +109,7 @@ public class PreAuthTokenSourceTrustAuthenticationProvider implements Authentica
|
|||||||
if (successAuthentication) {
|
if (successAuthentication) {
|
||||||
final Collection<GrantedAuthority> controllerAuthorities = new ArrayList<>();
|
final Collection<GrantedAuthority> controllerAuthorities = new ArrayList<>();
|
||||||
controllerAuthorities.add(new SimpleGrantedAuthority(SpringEvalExpressions.CONTROLLER_ROLE));
|
controllerAuthorities.add(new SimpleGrantedAuthority(SpringEvalExpressions.CONTROLLER_ROLE));
|
||||||
|
controllerAuthorities.add(new SimpleGrantedAuthority(SpringEvalExpressions.CONTROLLER_DOWNLOAD_ROLE));
|
||||||
final PreAuthenticatedAuthenticationToken successToken = new PreAuthenticatedAuthenticationToken(principal,
|
final PreAuthenticatedAuthenticationToken successToken = new PreAuthenticatedAuthenticationToken(principal,
|
||||||
credentials, controllerAuthorities);
|
credentials, controllerAuthorities);
|
||||||
successToken.setDetails(tokenDetails);
|
successToken.setDetails(tokenDetails);
|
||||||
|
|||||||
@@ -8,7 +8,12 @@
|
|||||||
*/
|
*/
|
||||||
package org.eclipse.hawkbit.security;
|
package org.eclipse.hawkbit.security;
|
||||||
|
|
||||||
import org.eclipse.hawkbit.dmf.json.model.TenantSecruityToken;
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
import org.eclipse.hawkbit.dmf.json.model.TenantSecurityToken;
|
||||||
|
import org.springframework.security.core.Authentication;
|
||||||
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface for Pre Authenfication.
|
* Interface for Pre Authenfication.
|
||||||
@@ -25,7 +30,7 @@ public interface PreAuthenficationFilter {
|
|||||||
* the secruity info
|
* the secruity info
|
||||||
* @return <true> is enabled <false> diabled
|
* @return <true> is enabled <false> diabled
|
||||||
*/
|
*/
|
||||||
boolean isEnable(TenantSecruityToken secruityToken);
|
boolean isEnable(TenantSecurityToken secruityToken);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extract the principal information from the current secruityToken.
|
* Extract the principal information from the current secruityToken.
|
||||||
@@ -34,7 +39,7 @@ public interface PreAuthenficationFilter {
|
|||||||
* the secruityToken
|
* the secruityToken
|
||||||
* @return the extracted tenant and controller id
|
* @return the extracted tenant and controller id
|
||||||
*/
|
*/
|
||||||
HeaderAuthentication getPreAuthenticatedPrincipal(TenantSecruityToken secruityToken);
|
HeaderAuthentication getPreAuthenticatedPrincipal(TenantSecurityToken secruityToken);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extract the principal credentials from the current secruityToken.
|
* Extract the principal credentials from the current secruityToken.
|
||||||
@@ -43,6 +48,18 @@ public interface PreAuthenficationFilter {
|
|||||||
* the secruityToken
|
* the secruityToken
|
||||||
* @return the extracted tenant and controller id
|
* @return the extracted tenant and controller id
|
||||||
*/
|
*/
|
||||||
HeaderAuthentication getPreAuthenticatedCredentials(TenantSecruityToken secruityToken);
|
HeaderAuthentication getPreAuthenticatedCredentials(TenantSecurityToken secruityToken);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows to add additional authorities to the successful authenticated
|
||||||
|
* token.
|
||||||
|
*
|
||||||
|
* @return the authorities granted to the principal, or an empty collection
|
||||||
|
* if the token has not been authenticated. Never null.
|
||||||
|
* @see Authentication#getAuthorities()
|
||||||
|
*/
|
||||||
|
default Collection<GrantedAuthority> getSuccessfulAuthenticationAuthorities() {
|
||||||
|
return Collections.emptyList();
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,61 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||||
|
*
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*/
|
||||||
|
package org.eclipse.hawkbit.security;
|
||||||
|
|
||||||
|
import static org.fest.assertions.Assertions.assertThat;
|
||||||
|
|
||||||
|
import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions;
|
||||||
|
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
|
||||||
|
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.runners.MockitoJUnitRunner;
|
||||||
|
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||||
|
|
||||||
|
import ru.yandex.qatools.allure.annotations.Features;
|
||||||
|
import ru.yandex.qatools.allure.annotations.Stories;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Michael Hirsch
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Features("Unit Tests - Security")
|
||||||
|
@Stories("Exclude path aware shallow ETag filter")
|
||||||
|
@RunWith(MockitoJUnitRunner.class)
|
||||||
|
public class ControllerPreAuthenticatedAnonymousDownloadTest {
|
||||||
|
|
||||||
|
private ControllerPreAuthenticatedAnonymousDownload underTest;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private TenantConfigurationManagement tenantConfigurationManagementMock;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private TenantAware tenantAwareMock;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void before() {
|
||||||
|
underTest = new ControllerPreAuthenticatedAnonymousDownload(tenantConfigurationManagementMock, tenantAwareMock,
|
||||||
|
new SystemSecurityContext(tenantAwareMock));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void useCorrectTenantConfiguationKey() {
|
||||||
|
assertThat(underTest.getTenantConfigurationKey()).as("Should be using the correct tenant configuration key")
|
||||||
|
.isEqualTo(underTest.getTenantConfigurationKey());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void successfulAuthenticationAdditionalAuthoritiesForDownload() {
|
||||||
|
assertThat(underTest.getSuccessfulAuthenticationAuthorities())
|
||||||
|
.as("Additional authorities should be containing the download anonymous role")
|
||||||
|
.contains(new SimpleGrantedAuthority(SpringEvalExpressions.CONTROLLER_DOWNLOAD_ROLE));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -215,13 +215,15 @@ public class UploadLayout extends VerticalLayout {
|
|||||||
hasDirectory = Boolean.TRUE;
|
hasDirectory = Boolean.TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean isDirectory(final Html5File file) {
|
private StreamVariable createStreamVariable(final Html5File file) {
|
||||||
if (Strings.isNullOrEmpty(file.getType()) && file.getFileSize() % 4096 == 0) {
|
return new UploadHandler(file.getFileName(), file.getFileSize(), UploadLayout.this, uploadInfoWindow,
|
||||||
return true;
|
spInfo.getMaxArtifactFileSize(), null, file.getType());
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isDirectory(final Html5File file) {
|
||||||
|
return Strings.isNullOrEmpty(file.getType()) && file.getFileSize() % 4096 == 0;
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void displayCompositeMessage() {
|
private void displayCompositeMessage() {
|
||||||
@@ -282,11 +284,6 @@ public class UploadLayout extends VerticalLayout {
|
|||||||
discardBtn.addClickListener(event -> discardUploadData(event));
|
discardBtn.addClickListener(event -> discardUploadData(event));
|
||||||
}
|
}
|
||||||
|
|
||||||
private StreamVariable createStreamVariable(final Html5File file) {
|
|
||||||
return new UploadHandler(file.getFileName(), file.getFileSize(), this, uploadInfoWindow,
|
|
||||||
spInfo.getMaxArtifactFileSize(), null, file.getType());
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean checkForDuplicate(final String filename) {
|
boolean checkForDuplicate(final String filename) {
|
||||||
final Boolean isDuplicate = checkIfFileIsDuplicate(filename);
|
final Boolean isDuplicate = checkIfFileIsDuplicate(filename);
|
||||||
if (isDuplicate) {
|
if (isDuplicate) {
|
||||||
@@ -349,17 +346,17 @@ public class UploadLayout extends VerticalLayout {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Boolean validate(DragAndDropEvent event) {
|
Boolean validate(final DragAndDropEvent event) {
|
||||||
// check if drop is valid.If valid ,check if software module is
|
// check if drop is valid.If valid ,check if software module is
|
||||||
// selected.
|
// selected.
|
||||||
if(!isFilesDropped(event)){
|
if (!isFilesDropped(event)) {
|
||||||
uiNotification.displayValidationError(i18n.get("message.action.not.allowed"));
|
uiNotification.displayValidationError(i18n.get("message.action.not.allowed"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return checkIfSoftwareModuleIsSelected();
|
return checkIfSoftwareModuleIsSelected();
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isFilesDropped(DragAndDropEvent event) {
|
private boolean isFilesDropped(final DragAndDropEvent event) {
|
||||||
if (event.getTransferable() instanceof WrapperTransferable) {
|
if (event.getTransferable() instanceof WrapperTransferable) {
|
||||||
final Html5File[] files = ((WrapperTransferable) event.getTransferable()).getFiles();
|
final Html5File[] files = ((WrapperTransferable) event.getTransferable()).getFiles();
|
||||||
// other components can also be wrapped in WrapperTransferable , so
|
// other components can also be wrapped in WrapperTransferable , so
|
||||||
@@ -448,7 +445,7 @@ public class UploadLayout extends VerticalLayout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private String getDuplicateFileValidationMessage() {
|
private String getDuplicateFileValidationMessage() {
|
||||||
StringBuilder message = new StringBuilder();
|
final StringBuilder message = new StringBuilder();
|
||||||
if (!duplicateFileNamesList.isEmpty()) {
|
if (!duplicateFileNamesList.isEmpty()) {
|
||||||
final String fileNames = StringUtils.collectionToCommaDelimitedString(duplicateFileNamesList);
|
final String fileNames = StringUtils.collectionToCommaDelimitedString(duplicateFileNamesList);
|
||||||
if (duplicateFileNamesList.size() == 1) {
|
if (duplicateFileNamesList.size() == 1) {
|
||||||
@@ -655,8 +652,7 @@ public class UploadLayout extends VerticalLayout {
|
|||||||
return uiNotification;
|
return uiNotification;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setHasDirectory(final Boolean hasDirectory) {
|
||||||
public void setHasDirectory(Boolean hasDirectory) {
|
|
||||||
this.hasDirectory = hasDirectory;
|
this.hasDirectory = hasDirectory;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -196,18 +196,25 @@ public abstract class AbstractTagToken<T extends BaseEntity> implements Serializ
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
private void updateTokenStyle(final Object tokenId, final Button button) {
|
||||||
|
final String color = getColor(tokenId);
|
||||||
|
button.setCaption("<span style=\"color:" + color + " !important;\">" + FontAwesome.CIRCLE.getHtml()
|
||||||
|
+ "</span>" + " " + getItemNameProperty(tokenId).getValue().toString().concat(" ×"));
|
||||||
|
button.setCaptionAsHtml(true);
|
||||||
|
}
|
||||||
|
|
||||||
private void updateTokenStyle(final Object tokenId, final Button button) {
|
private void onTokenSearch(final Object tokenId) {
|
||||||
final String color = getColor(tokenId);
|
assignTag(getItemNameProperty(tokenId).getValue().toString());
|
||||||
button.setCaption("<span style=\"color:" + color + " !important;\">" + FontAwesome.CIRCLE.getHtml() + "</span>"
|
removeTagAssignedFromCombo((Long) tokenId);
|
||||||
+ " " + getItemNameProperty(tokenId).getValue().toString().concat(" ×"));
|
}
|
||||||
button.setCaptionAsHtml(true);
|
|
||||||
}
|
private void tokenClick(final Object tokenId) {
|
||||||
|
final Item item = tokenField.getContainerDataSource().addItem(tokenId);
|
||||||
|
item.getItemProperty("name").setValue(tagDetails.get(tokenId).getName());
|
||||||
|
item.getItemProperty(COLOR_PROPERTY).setValue(tagDetails.get(tokenId).getColor());
|
||||||
|
unassignTag(tagDetails.get(tokenId).getName());
|
||||||
|
}
|
||||||
|
|
||||||
private void onTokenSearch(final Object tokenId) {
|
|
||||||
assignTag(getItemNameProperty(tokenId).getValue().toString());
|
|
||||||
removeTagAssignedFromCombo((Long) tokenId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Property getItemNameProperty(final Object tokenId) {
|
private Property getItemNameProperty(final Object tokenId) {
|
||||||
@@ -229,13 +236,6 @@ public abstract class AbstractTagToken<T extends BaseEntity> implements Serializ
|
|||||||
return (String) item.getItemProperty("name").getValue();
|
return (String) item.getItemProperty("name").getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void tokenClick(final Object tokenId) {
|
|
||||||
final Item item = tokenField.getContainerDataSource().addItem(tokenId);
|
|
||||||
item.getItemProperty("name").setValue(tagDetails.get(tokenId).getName());
|
|
||||||
item.getItemProperty(COLOR_PROPERTY).setValue(tagDetails.get(tokenId).getColor());
|
|
||||||
unassignTag(tagDetails.get(tokenId).getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void removePreviouslyAddedTokens() {
|
protected void removePreviouslyAddedTokens() {
|
||||||
tokensAdded.keySet().forEach(previouslyAddedToken -> tokenField.removeToken(previouslyAddedToken));
|
tokensAdded.keySet().forEach(previouslyAddedToken -> tokenField.removeToken(previouslyAddedToken));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,14 +63,10 @@ import com.vaadin.ui.Upload.SucceededListener;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Bulk target upload handler.
|
* Bulk target upload handler.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public class BulkUploadHandler extends CustomComponent
|
public class BulkUploadHandler extends CustomComponent
|
||||||
implements SucceededListener, FailedListener, Receiver, StartedListener {
|
implements SucceededListener, FailedListener, Receiver, StartedListener {
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
private static final long serialVersionUID = -1273494705754674501L;
|
private static final long serialVersionUID = -1273494705754674501L;
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(BulkUploadHandler.class);
|
private static final Logger LOG = LoggerFactory.getLogger(BulkUploadHandler.class);
|
||||||
|
|
||||||
@@ -149,12 +145,6 @@ public class BulkUploadHandler extends CustomComponent
|
|||||||
setCompositionRoot(horizontalLayout);
|
setCompositionRoot(horizontalLayout);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
*
|
|
||||||
* @see com.vaadin.ui.Upload.Receiver#receiveUpload(java.lang.String,
|
|
||||||
* java.lang.String)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public OutputStream receiveUpload(final String filename, final String mimeType) {
|
public OutputStream receiveUpload(final String filename, final String mimeType) {
|
||||||
try {
|
try {
|
||||||
@@ -170,25 +160,11 @@ public class BulkUploadHandler extends CustomComponent
|
|||||||
return new NullOutputStream();
|
return new NullOutputStream();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
*
|
|
||||||
* @see
|
|
||||||
* com.vaadin.ui.Upload.FailedListener#uploadFailed(com.vaadin.ui.Upload.
|
|
||||||
* FailedEvent)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void uploadFailed(final FailedEvent event) {
|
public void uploadFailed(final FailedEvent event) {
|
||||||
LOG.info("Upload failed for file :{} due to {}", event.getFilename(), event.getReason());
|
LOG.info("Upload failed for file :{} due to {}", event.getFilename(), event.getReason());
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
*
|
|
||||||
* @see
|
|
||||||
* com.vaadin.ui.Upload.SucceededListener#uploadSucceeded(com.vaadin.ui.
|
|
||||||
* Upload.SucceededEvent)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void uploadSucceeded(final SucceededEvent event) {
|
public void uploadSucceeded(final SucceededEvent event) {
|
||||||
executor.execute(new UploadAsync(event));
|
executor.execute(new UploadAsync(event));
|
||||||
@@ -252,6 +228,61 @@ public class BulkUploadHandler extends CustomComponent
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private double getTotalNumberOfLines() {
|
||||||
|
|
||||||
|
double totalFileSize = 0;
|
||||||
|
try (InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream(tempFile),
|
||||||
|
Charset.defaultCharset())) {
|
||||||
|
try (BufferedReader readerForSize = new BufferedReader(inputStreamReader)) {
|
||||||
|
totalFileSize = readerForSize.lines().count();
|
||||||
|
}
|
||||||
|
} catch (final FileNotFoundException e) {
|
||||||
|
LOG.error("Error reading file {}", tempFile.getName(), e);
|
||||||
|
} catch (final IOException e) {
|
||||||
|
LOG.error("Error while closing reader of file {}", tempFile.getName(), e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return totalFileSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void resetCounts() {
|
||||||
|
successfullTargetCount = 0;
|
||||||
|
failedTargetCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void deleteFile() {
|
||||||
|
if (tempFile.exists()) {
|
||||||
|
final boolean isDeleted = tempFile.delete();
|
||||||
|
if (!isDeleted) {
|
||||||
|
LOG.info("File {} was not deleted !", tempFile.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tempFile = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void readEachLine(final String line, final double innerCounter, final double totalFileSize) {
|
||||||
|
final String csvDelimiter = ",";
|
||||||
|
final String[] targets = line.split(csvDelimiter);
|
||||||
|
if (targets.length == 2) {
|
||||||
|
final String controllerId = targets[0];
|
||||||
|
final String targetName = targets[1];
|
||||||
|
addNewTarget(controllerId, targetName);
|
||||||
|
} else {
|
||||||
|
failedTargetCount++;
|
||||||
|
}
|
||||||
|
final float current = managementUIState.getTargetTableFilters().getBulkUpload()
|
||||||
|
.getProgressBarCurrentValue();
|
||||||
|
final float next = (float) (innerCounter / totalFileSize);
|
||||||
|
if (Math.abs(next - 0.1) < 0.00001 || current - next >= 0 || next - current >= 0.05
|
||||||
|
|| Math.abs(next - 1) < 0.00001) {
|
||||||
|
managementUIState.getTargetTableFilters().getBulkUpload().setProgressBarCurrentValue(next);
|
||||||
|
managementUIState.getTargetTableFilters().getBulkUpload()
|
||||||
|
.setSucessfulUploadCount(successfullTargetCount);
|
||||||
|
managementUIState.getTargetTableFilters().getBulkUpload().setFailedUploadCount(failedTargetCount);
|
||||||
|
eventBus.publish(this, new TargetTableEvent(TargetComponentEvent.BULK_TARGET_CREATED));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void doAssignments() {
|
private void doAssignments() {
|
||||||
final StringBuilder errorMessage = new StringBuilder();
|
final StringBuilder errorMessage = new StringBuilder();
|
||||||
String dsAssignmentFailedMsg = null;
|
String dsAssignmentFailedMsg = null;
|
||||||
@@ -267,6 +298,41 @@ public class BulkUploadHandler extends CustomComponent
|
|||||||
displayValidationMessage(errorMessage, dsAssignmentFailedMsg, tagAssignmentFailedMsg);
|
displayValidationMessage(errorMessage, dsAssignmentFailedMsg, tagAssignmentFailedMsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String saveAllAssignments() {
|
||||||
|
final ActionType actionType = ActionType.FORCED;
|
||||||
|
final long forcedTimeStamp = new Date().getTime();
|
||||||
|
final TargetBulkUpload targetBulkUpload = managementUIState.getTargetTableFilters().getBulkUpload();
|
||||||
|
final List<String> targetsList = targetBulkUpload.getTargetsCreated();
|
||||||
|
final DistributionSetIdName dsSelected = (DistributionSetIdName) comboBox.getValue();
|
||||||
|
if (distributionSetManagement.findDistributionSetById(dsSelected.getId()) == null) {
|
||||||
|
return i18n.get("message.bulk.upload.assignment.failed");
|
||||||
|
}
|
||||||
|
deploymentManagement.assignDistributionSet(targetBulkUpload.getDsNameAndVersion().getId(), actionType,
|
||||||
|
forcedTimeStamp, targetsList.toArray(new String[targetsList.size()]));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String tagAssignment() {
|
||||||
|
final Map<Long, TagData> tokensSelected = targetBulkTokenTags.getTokensAdded();
|
||||||
|
final List<String> deletedTags = new ArrayList<>();
|
||||||
|
for (final TagData tagData : tokensSelected.values()) {
|
||||||
|
if (tagManagement.findTargetTagById(tagData.getId()) == null) {
|
||||||
|
deletedTags.add(tagData.getName());
|
||||||
|
} else {
|
||||||
|
targetManagement.toggleTagAssignment(
|
||||||
|
managementUIState.getTargetTableFilters().getBulkUpload().getTargetsCreated(),
|
||||||
|
tagData.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (deletedTags.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (deletedTags.size() == 1) {
|
||||||
|
return i18n.get("message.bulk.upload.tag.assignment.failed", deletedTags.get(0));
|
||||||
|
}
|
||||||
|
return i18n.get("message.bulk.upload.tag.assignments.failed");
|
||||||
|
}
|
||||||
|
|
||||||
private boolean ifTagsSelected() {
|
private boolean ifTagsSelected() {
|
||||||
return targetBulkTokenTags.getTokenField().getValue() != null;
|
return targetBulkTokenTags.getTokenField().getValue() != null;
|
||||||
}
|
}
|
||||||
@@ -307,59 +373,6 @@ public class BulkUploadHandler extends CustomComponent
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private double getTotalNumberOfLines() {
|
|
||||||
|
|
||||||
double totalFileSize = 0;
|
|
||||||
try (InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream(tempFile),
|
|
||||||
Charset.defaultCharset())) {
|
|
||||||
try (BufferedReader readerForSize = new BufferedReader(inputStreamReader)) {
|
|
||||||
totalFileSize = readerForSize.lines().count();
|
|
||||||
}
|
|
||||||
} catch (final FileNotFoundException e) {
|
|
||||||
LOG.error("Error reading file {}", tempFile.getName(), e);
|
|
||||||
} catch (final IOException e) {
|
|
||||||
LOG.error("Error while closing reader of file {}", tempFile.getName(), e);
|
|
||||||
}
|
|
||||||
|
|
||||||
return totalFileSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void resetCounts() {
|
|
||||||
successfullTargetCount = 0;
|
|
||||||
failedTargetCount = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void deleteFile() {
|
|
||||||
if (tempFile.exists()) {
|
|
||||||
final boolean isDeleted = tempFile.delete();
|
|
||||||
if (!isDeleted) {
|
|
||||||
LOG.info("File {} was not deleted !", tempFile.getName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tempFile = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void readEachLine(final String line, final double innerCounter, final double totalFileSize) {
|
|
||||||
final String csvDelimiter = ",";
|
|
||||||
final String[] targets = line.split(csvDelimiter);
|
|
||||||
if (targets.length == 2) {
|
|
||||||
final String controllerId = targets[0];
|
|
||||||
final String targetName = targets[1];
|
|
||||||
addNewTarget(controllerId, targetName);
|
|
||||||
} else {
|
|
||||||
failedTargetCount++;
|
|
||||||
}
|
|
||||||
final float current = managementUIState.getTargetTableFilters().getBulkUpload().getProgressBarCurrentValue();
|
|
||||||
final float next = (float) (innerCounter / totalFileSize);
|
|
||||||
if (Math.abs(next - 0.1) < 0.00001 || current - next >= 0 || next - current >= 0.05
|
|
||||||
|| Math.abs(next - 1) < 0.00001) {
|
|
||||||
managementUIState.getTargetTableFilters().getBulkUpload().setProgressBarCurrentValue(next);
|
|
||||||
managementUIState.getTargetTableFilters().getBulkUpload().setSucessfulUploadCount(successfullTargetCount);
|
|
||||||
managementUIState.getTargetTableFilters().getBulkUpload().setFailedUploadCount(failedTargetCount);
|
|
||||||
eventBus.publish(this, new TargetTableEvent(TargetComponentEvent.BULK_TARGET_CREATED));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addNewTarget(final String controllerId, final String name) {
|
private void addNewTarget(final String controllerId, final String name) {
|
||||||
final String newControllerId = HawkbitCommonUtil.trimAndNullIfEmpty(controllerId);
|
final String newControllerId = HawkbitCommonUtil.trimAndNullIfEmpty(controllerId);
|
||||||
if (mandatoryCheck(newControllerId) && duplicateCheck(newControllerId)) {
|
if (mandatoryCheck(newControllerId) && duplicateCheck(newControllerId)) {
|
||||||
@@ -405,43 +418,6 @@ public class BulkUploadHandler extends CustomComponent
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String saveAllAssignments() {
|
|
||||||
final ActionType actionType = ActionType.FORCED;
|
|
||||||
final long forcedTimeStamp = new Date().getTime();
|
|
||||||
final TargetBulkUpload targetBulkUpload = managementUIState.getTargetTableFilters().getBulkUpload();
|
|
||||||
final List<String> targetsList = targetBulkUpload.getTargetsCreated();
|
|
||||||
final DistributionSetIdName dsSelected = (DistributionSetIdName) comboBox.getValue();
|
|
||||||
if (distributionSetManagement.findDistributionSetById(dsSelected.getId()) == null) {
|
|
||||||
return i18n.get("message.bulk.upload.assignment.failed");
|
|
||||||
} else {
|
|
||||||
deploymentManagement.assignDistributionSet(targetBulkUpload.getDsNameAndVersion().getId(), actionType,
|
|
||||||
forcedTimeStamp, targetsList.toArray(new String[targetsList.size()]));
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private String tagAssignment() {
|
|
||||||
final Map<Long, TagData> tokensSelected = targetBulkTokenTags.getTokensAdded();
|
|
||||||
final List<String> deletedTags = new ArrayList<>();
|
|
||||||
for (final TagData tagData : tokensSelected.values()) {
|
|
||||||
if (tagManagement.findTargetTagById(tagData.getId()) == null) {
|
|
||||||
deletedTags.add(tagData.getName());
|
|
||||||
} else {
|
|
||||||
targetManagement.toggleTagAssignment(
|
|
||||||
managementUIState.getTargetTableFilters().getBulkUpload().getTargetsCreated(),
|
|
||||||
tagData.getName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!deletedTags.isEmpty()) {
|
|
||||||
if (deletedTags.size() == 1) {
|
|
||||||
return i18n.get("message.bulk.upload.tag.assignment.failed", deletedTags.get(0));
|
|
||||||
} else {
|
|
||||||
return i18n.get("message.bulk.upload.tag.assignments.failed");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class NullOutputStream extends OutputStream {
|
private static class NullOutputStream extends OutputStream {
|
||||||
/**
|
/**
|
||||||
* null output stream.
|
* null output stream.
|
||||||
@@ -462,13 +438,6 @@ public class BulkUploadHandler extends CustomComponent
|
|||||||
return upload;
|
return upload;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
*
|
|
||||||
* @see
|
|
||||||
* com.vaadin.ui.Upload.StartedListener#uploadStarted(com.vaadin.ui.Upload
|
|
||||||
* .StartedEvent)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void uploadStarted(final StartedEvent event) {
|
public void uploadStarted(final StartedEvent event) {
|
||||||
if (!event.getFilename().endsWith(".csv")) {
|
if (!event.getFilename().endsWith(".csv")) {
|
||||||
|
|||||||
@@ -356,7 +356,6 @@ public class RolloutListGrid extends AbstractGrid {
|
|||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void getUpdateMenuItem(final ContextMenu context, final Long rolloutId) {
|
private void getUpdateMenuItem(final ContextMenu context, final Long rolloutId) {
|
||||||
// Add 'Update' option only if user has update permission
|
// Add 'Update' option only if user has update permission
|
||||||
if (!permissionChecker.hasRolloutUpdatePermission()) {
|
if (!permissionChecker.hasRolloutUpdatePermission()) {
|
||||||
@@ -366,17 +365,6 @@ public class RolloutListGrid extends AbstractGrid {
|
|||||||
cancelItem.setData(new ContextMenuData(rolloutId, ACTION.UPDATE));
|
cancelItem.setData(new ContextMenuData(rolloutId, ACTION.UPDATE));
|
||||||
}
|
}
|
||||||
|
|
||||||
private String convertRolloutStatusToString(final RolloutStatus value) {
|
|
||||||
final StatusFontIcon statusFontIcon = statusIconMap.get(value);
|
|
||||||
if (statusFontIcon == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
final String codePoint = statusFontIcon.getFontIcon() != null
|
|
||||||
? Integer.toString(statusFontIcon.getFontIcon().getCodepoint()) : null;
|
|
||||||
return HawkbitCommonUtil.getStatusLabelDetailsInString(codePoint, statusFontIcon.getStyle(),
|
|
||||||
SPUIComponetIdProvider.ROLLOUT_STATUS_LABEL_ID);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void menuItemClicked(final ContextMenuItemClickEvent event) {
|
private void menuItemClicked(final ContextMenuItemClickEvent event) {
|
||||||
final ContextMenuItem item = (ContextMenuItem) event.getSource();
|
final ContextMenuItem item = (ContextMenuItem) event.getSource();
|
||||||
final ContextMenuData contextMenuData = (ContextMenuData) item.getData();
|
final ContextMenuData contextMenuData = (ContextMenuData) item.getData();
|
||||||
@@ -537,6 +525,13 @@ public class RolloutListGrid extends AbstractGrid {
|
|||||||
public Class<String> getPresentationType() {
|
public Class<String> getPresentationType() {
|
||||||
return String.class;
|
return String.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String convertRolloutStatusToString(final RolloutStatus value) {
|
||||||
|
final StatusFontIcon statusFontIcon = statusIconMap.get(value);
|
||||||
|
final String codePoint = HawkbitCommonUtil.getCodePoint(statusFontIcon);
|
||||||
|
return HawkbitCommonUtil.getStatusLabelDetailsInString(codePoint, statusFontIcon.getStyle(),
|
||||||
|
SPUIComponetIdProvider.ROLLOUT_STATUS_LABEL_ID);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -549,14 +544,16 @@ public class RolloutListGrid extends AbstractGrid {
|
|||||||
private static final long serialVersionUID = -5794528427855153924L;
|
private static final long serialVersionUID = -5794528427855153924L;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TotalTargetCountStatus convertToModel(final String value, final Class<? extends TotalTargetCountStatus> targetType,
|
public TotalTargetCountStatus convertToModel(final String value,
|
||||||
final Locale locale) throws com.vaadin.data.util.converter.Converter.ConversionException {
|
final Class<? extends TotalTargetCountStatus> targetType, final Locale locale)
|
||||||
|
throws com.vaadin.data.util.converter.Converter.ConversionException {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String convertToPresentation(final TotalTargetCountStatus value, final Class<? extends String> targetType,
|
public String convertToPresentation(final TotalTargetCountStatus value,
|
||||||
final Locale locale) throws com.vaadin.data.util.converter.Converter.ConversionException {
|
final Class<? extends String> targetType, final Locale locale)
|
||||||
|
throws com.vaadin.data.util.converter.Converter.ConversionException {
|
||||||
return DistributionBarHelper.getDistributionBarAsHTMLString(value.getStatusTotalCountMap());
|
return DistributionBarHelper.getDistributionBarAsHTMLString(value.getStatusTotalCountMap());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -217,7 +217,7 @@ public class RolloutGroupListGrid extends AbstractGrid {
|
|||||||
createRolloutGroupStatusToFontMap();
|
createRolloutGroupStatusToFontMap();
|
||||||
getColumn(SPUILabelDefinitions.VAR_STATUS).setRenderer(new HtmlLabelRenderer(),
|
getColumn(SPUILabelDefinitions.VAR_STATUS).setRenderer(new HtmlLabelRenderer(),
|
||||||
new RolloutGroupStatusConverter());
|
new RolloutGroupStatusConverter());
|
||||||
|
|
||||||
getColumn(SPUILabelDefinitions.VAR_TOTAL_TARGETS_COUNT_STATUS).setRenderer(new HtmlRenderer(),
|
getColumn(SPUILabelDefinitions.VAR_TOTAL_TARGETS_COUNT_STATUS).setRenderer(new HtmlRenderer(),
|
||||||
new TotalTargetCountStatusConverter());
|
new TotalTargetCountStatusConverter());
|
||||||
if (permissionChecker.hasRolloutTargetsReadPermission()) {
|
if (permissionChecker.hasRolloutTargetsReadPermission()) {
|
||||||
@@ -250,18 +250,6 @@ public class RolloutGroupListGrid extends AbstractGrid {
|
|||||||
eventBus.publish(this, RolloutEvent.SHOW_ROLLOUT_GROUP_TARGETS);
|
eventBus.publish(this, RolloutEvent.SHOW_ROLLOUT_GROUP_TARGETS);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String convertRolloutGroupStatusToString(final RolloutGroupStatus value) {
|
|
||||||
final StatusFontIcon statusFontIcon = statusIconMap.get(value);
|
|
||||||
if (statusFontIcon == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
final String codePoint = statusFontIcon.getFontIcon() != null
|
|
||||||
? Integer.toString(statusFontIcon.getFontIcon().getCodepoint()) : null;
|
|
||||||
return HawkbitCommonUtil.getStatusLabelDetailsInString(codePoint, statusFontIcon.getStyle(),
|
|
||||||
SPUIComponetIdProvider.ROLLOUT_GROUP_STATUS_LABEL_ID);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private void createRolloutGroupStatusToFontMap() {
|
private void createRolloutGroupStatusToFontMap() {
|
||||||
statusIconMap.put(RolloutGroupStatus.FINISHED,
|
statusIconMap.put(RolloutGroupStatus.FINISHED,
|
||||||
new StatusFontIcon(FontAwesome.CHECK_CIRCLE, SPUIStyleDefinitions.STATUS_ICON_GREEN));
|
new StatusFontIcon(FontAwesome.CHECK_CIRCLE, SPUIStyleDefinitions.STATUS_ICON_GREEN));
|
||||||
@@ -316,14 +304,16 @@ public class RolloutGroupListGrid extends AbstractGrid {
|
|||||||
private static final long serialVersionUID = -9205943894818450807L;
|
private static final long serialVersionUID = -9205943894818450807L;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TotalTargetCountStatus convertToModel(final String value, final Class<? extends TotalTargetCountStatus> targetType,
|
public TotalTargetCountStatus convertToModel(final String value,
|
||||||
final Locale locale) throws com.vaadin.data.util.converter.Converter.ConversionException {
|
final Class<? extends TotalTargetCountStatus> targetType, final Locale locale)
|
||||||
|
throws com.vaadin.data.util.converter.Converter.ConversionException {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String convertToPresentation(final TotalTargetCountStatus value, final Class<? extends String> targetType,
|
public String convertToPresentation(final TotalTargetCountStatus value,
|
||||||
final Locale locale) throws com.vaadin.data.util.converter.Converter.ConversionException {
|
final Class<? extends String> targetType, final Locale locale)
|
||||||
|
throws com.vaadin.data.util.converter.Converter.ConversionException {
|
||||||
return DistributionBarHelper.getDistributionBarAsHTMLString(value.getStatusTotalCountMap());
|
return DistributionBarHelper.getDistributionBarAsHTMLString(value.getStatusTotalCountMap());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -369,5 +359,13 @@ public class RolloutGroupListGrid extends AbstractGrid {
|
|||||||
return String.class;
|
return String.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String convertRolloutGroupStatusToString(final RolloutGroupStatus value) {
|
||||||
|
final StatusFontIcon statusFontIcon = statusIconMap.get(value);
|
||||||
|
final String codePoint = HawkbitCommonUtil.getCodePoint(statusFontIcon);
|
||||||
|
return HawkbitCommonUtil.getStatusLabelDetailsInString(codePoint, statusFontIcon.getStyle(),
|
||||||
|
SPUIComponetIdProvider.ROLLOUT_GROUP_STATUS_LABEL_ID);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -196,11 +196,9 @@ public class RolloutGroupTargetsListGrid extends AbstractGrid {
|
|||||||
public String convertToPresentation(final Status status, final Class<? extends String> targetType,
|
public String convertToPresentation(final Status status, final Class<? extends String> targetType,
|
||||||
final Locale locale) {
|
final Locale locale) {
|
||||||
if (status == null) {
|
if (status == null) {
|
||||||
// Actions are not created for targets when
|
// Actions are not created for targets when rollout's status is
|
||||||
// rollout's status
|
// READY and when duplicate assignment is done. In these cases
|
||||||
// is READY and when duplicate assignment is done.
|
// display a appropriate status with description
|
||||||
// In these cases display a appropriate status with
|
|
||||||
// description
|
|
||||||
return getStatus();
|
return getStatus();
|
||||||
}
|
}
|
||||||
return processActionStatus(status);
|
return processActionStatus(status);
|
||||||
@@ -216,16 +214,27 @@ public class RolloutGroupTargetsListGrid extends AbstractGrid {
|
|||||||
return String.class;
|
return String.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
private String processActionStatus(final Status status) {
|
||||||
|
final StatusFontIcon statusFontIcon = statusIconMap.get(status);
|
||||||
private String processActionStatus(final Status status) {
|
final String codePoint = HawkbitCommonUtil.getCodePoint(statusFontIcon);
|
||||||
final StatusFontIcon statusFontIcon = statusIconMap.get(status);
|
return HawkbitCommonUtil.getStatusLabelDetailsInString(codePoint, statusFontIcon.getStyle(), null);
|
||||||
if (statusFontIcon == null) {
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
final String codePoint = statusFontIcon.getFontIcon() != null
|
|
||||||
? Integer.toString(statusFontIcon.getFontIcon().getCodepoint()) : null;
|
private String getStatus() {
|
||||||
return HawkbitCommonUtil.getStatusLabelDetailsInString(codePoint, statusFontIcon.getStyle(), null);
|
final RolloutGroup rolloutGroup = rolloutUIState.getRolloutGroup().isPresent()
|
||||||
|
? rolloutUIState.getRolloutGroup().get() : null;
|
||||||
|
if (rolloutGroup != null && rolloutGroup.getStatus() == RolloutGroupStatus.READY) {
|
||||||
|
return HawkbitCommonUtil.getStatusLabelDetailsInString(
|
||||||
|
Integer.toString(FontAwesome.DOT_CIRCLE_O.getCodepoint()), "statusIconLightBlue", null);
|
||||||
|
}
|
||||||
|
if (rolloutGroup != null && rolloutGroup.getStatus() == RolloutGroupStatus.FINISHED) {
|
||||||
|
return HawkbitCommonUtil.getStatusLabelDetailsInString(
|
||||||
|
Integer.toString(FontAwesome.MINUS_CIRCLE.getCodepoint()), "statusIconBlue", null);
|
||||||
|
}
|
||||||
|
return HawkbitCommonUtil.getStatusLabelDetailsInString(
|
||||||
|
Integer.toString(FontAwesome.QUESTION_CIRCLE.getCodepoint()), "statusIconBlue", null);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createRolloutStatusToFontMap() {
|
private void createRolloutStatusToFontMap() {
|
||||||
@@ -249,21 +258,6 @@ public class RolloutGroupTargetsListGrid extends AbstractGrid {
|
|||||||
new StatusFontIcon(FontAwesome.EXCLAMATION_CIRCLE, SPUIStyleDefinitions.STATUS_ICON_RED));
|
new StatusFontIcon(FontAwesome.EXCLAMATION_CIRCLE, SPUIStyleDefinitions.STATUS_ICON_RED));
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getStatus() {
|
|
||||||
final RolloutGroup rolloutGroup = rolloutUIState.getRolloutGroup().isPresent()
|
|
||||||
? rolloutUIState.getRolloutGroup().get() : null;
|
|
||||||
if (rolloutGroup != null && rolloutGroup.getStatus() == RolloutGroupStatus.READY) {
|
|
||||||
return HawkbitCommonUtil.getStatusLabelDetailsInString(
|
|
||||||
Integer.toString(FontAwesome.DOT_CIRCLE_O.getCodepoint()), "statusIconLightBlue", null);
|
|
||||||
} else if (rolloutGroup != null && rolloutGroup.getStatus() == RolloutGroupStatus.FINISHED) {
|
|
||||||
return HawkbitCommonUtil.getStatusLabelDetailsInString(
|
|
||||||
Integer.toString(FontAwesome.MINUS_CIRCLE.getCodepoint()), "statusIconBlue", null);
|
|
||||||
} else {
|
|
||||||
return HawkbitCommonUtil.getStatusLabelDetailsInString(
|
|
||||||
Integer.toString(FontAwesome.QUESTION_CIRCLE.getCodepoint()), "statusIconBlue", null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getDescription(final CellReference cell) {
|
private String getDescription(final CellReference cell) {
|
||||||
if (!SPUILabelDefinitions.VAR_STATUS.equals(cell.getPropertyId())) {
|
if (!SPUILabelDefinitions.VAR_STATUS.equals(cell.getPropertyId())) {
|
||||||
return null;
|
return null;
|
||||||
@@ -274,7 +268,6 @@ public class RolloutGroupTargetsListGrid extends AbstractGrid {
|
|||||||
}
|
}
|
||||||
return cell.getProperty().getValue().toString().toLowerCase();
|
return cell.getProperty().getValue().toString().toLowerCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private String getDescriptionWhenNoAction() {
|
private String getDescriptionWhenNoAction() {
|
||||||
final RolloutGroup rolloutGroup = rolloutUIState.getRolloutGroup().isPresent()
|
final RolloutGroup rolloutGroup = rolloutUIState.getRolloutGroup().isPresent()
|
||||||
|
|||||||
@@ -30,9 +30,6 @@ import com.vaadin.ui.VerticalLayout;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* View to configure the authentication mode.
|
* View to configure the authentication mode.
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
@SpringComponent
|
@SpringComponent
|
||||||
@ViewScope
|
@ViewScope
|
||||||
|
|||||||
@@ -14,8 +14,8 @@ import java.util.List;
|
|||||||
import com.vaadin.ui.CustomComponent;
|
import com.vaadin.ui.CustomComponent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* base class for all configuration views. This class implements the logic for
|
* Base class for all configuration views. This class implements the logic for
|
||||||
* the handling of the
|
* the handling of the configurations in a consistent way.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public abstract class BaseConfigurationView extends CustomComponent implements ConfigurationGroup {
|
public abstract class BaseConfigurationView extends CustomComponent implements ConfigurationGroup {
|
||||||
|
|||||||
@@ -11,9 +11,8 @@ package org.eclipse.hawkbit.ui.tenantconfiguration;
|
|||||||
import com.vaadin.ui.Component;
|
import com.vaadin.ui.Component;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Interface that all system configurations have to implement to save and undo
|
||||||
*
|
* their customized changes.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public interface ConfigurationGroup extends Component, ConfigurationItem {
|
public interface ConfigurationGroup extends Component, ConfigurationItem {
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ package org.eclipse.hawkbit.ui.tenantconfiguration;
|
|||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* represents an configurationItem, which can be modified by the user
|
* Represents an configurationItem, which can be modified by the user
|
||||||
*/
|
*/
|
||||||
public interface ConfigurationItem {
|
public interface ConfigurationItem {
|
||||||
|
|
||||||
|
|||||||
@@ -33,9 +33,6 @@ import com.vaadin.ui.VerticalLayout;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Default DistributionSet Panel.
|
* Default DistributionSet Panel.
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
@SpringComponent
|
@SpringComponent
|
||||||
@ViewScope
|
@ViewScope
|
||||||
|
|||||||
@@ -0,0 +1,119 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||||
|
*
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*/
|
||||||
|
package org.eclipse.hawkbit.ui.tenantconfiguration;
|
||||||
|
|
||||||
|
import javax.annotation.PostConstruct;
|
||||||
|
|
||||||
|
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
|
||||||
|
import org.eclipse.hawkbit.repository.model.TenantConfigurationValue;
|
||||||
|
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationKey;
|
||||||
|
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
|
||||||
|
import org.eclipse.hawkbit.ui.utils.I18N;
|
||||||
|
import org.eclipse.hawkbit.ui.utils.SPUIComponetIdProvider;
|
||||||
|
import org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
|
import com.vaadin.spring.annotation.SpringComponent;
|
||||||
|
import com.vaadin.spring.annotation.ViewScope;
|
||||||
|
import com.vaadin.ui.Alignment;
|
||||||
|
import com.vaadin.ui.CheckBox;
|
||||||
|
import com.vaadin.ui.GridLayout;
|
||||||
|
import com.vaadin.ui.Label;
|
||||||
|
import com.vaadin.ui.Panel;
|
||||||
|
import com.vaadin.ui.VerticalLayout;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* View to enable anonymous download.
|
||||||
|
*/
|
||||||
|
@SpringComponent
|
||||||
|
@ViewScope
|
||||||
|
public class DownloadAnonymousConfigurationView extends BaseConfigurationView
|
||||||
|
implements ConfigurationItem.ConfigurationItemChangeListener {
|
||||||
|
|
||||||
|
private static final String DIST_CHECKBOX_STYLE = "dist-checkbox-style";
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private I18N i18n;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private transient TenantConfigurationManagement tenantConfigurationManagement;
|
||||||
|
|
||||||
|
boolean anonymousDownloadEnabled;
|
||||||
|
|
||||||
|
private CheckBox downloadAnonymousCheckBox;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize Default Download Anonymous layout.
|
||||||
|
*/
|
||||||
|
@PostConstruct
|
||||||
|
public void init() {
|
||||||
|
|
||||||
|
final TenantConfigurationValue<Boolean> value = tenantConfigurationManagement
|
||||||
|
.getConfigurationValue(TenantConfigurationKey.ANONYMOUS_DOWNLOAD_MODE_ENABLED, Boolean.class);
|
||||||
|
anonymousDownloadEnabled = value.getValue();
|
||||||
|
|
||||||
|
final Panel rootPanel = new Panel();
|
||||||
|
rootPanel.setSizeFull();
|
||||||
|
rootPanel.addStyleName("config-panel");
|
||||||
|
|
||||||
|
final VerticalLayout vLayout = new VerticalLayout();
|
||||||
|
vLayout.setMargin(true);
|
||||||
|
vLayout.setSizeFull();
|
||||||
|
|
||||||
|
final Label headerDisSetType = new Label(i18n.get("enonymous.download.title"));
|
||||||
|
headerDisSetType.addStyleName("config-panel-header");
|
||||||
|
vLayout.addComponent(headerDisSetType);
|
||||||
|
|
||||||
|
final GridLayout gridLayout = new GridLayout(2, 1);
|
||||||
|
gridLayout.setSpacing(true);
|
||||||
|
gridLayout.setImmediate(true);
|
||||||
|
gridLayout.setColumnExpandRatio(1, 1.0F);
|
||||||
|
gridLayout.setSizeFull();
|
||||||
|
|
||||||
|
downloadAnonymousCheckBox = SPUIComponentProvider.getCheckBox("", DIST_CHECKBOX_STYLE, null, false, "");
|
||||||
|
downloadAnonymousCheckBox.setValue(anonymousDownloadEnabled);
|
||||||
|
downloadAnonymousCheckBox.addValueChangeListener(event -> configurationHasChanged());
|
||||||
|
downloadAnonymousCheckBox.setId(SPUIComponetIdProvider.SYSTEM_CONFIGURATION_ANONYMOUS_DOWNLOAD_CHECKBOX);
|
||||||
|
|
||||||
|
gridLayout.addComponent(downloadAnonymousCheckBox);
|
||||||
|
|
||||||
|
final Label configurationLabel = SPUIComponentProvider.getLabel(i18n.get("enonymous.download.label"),
|
||||||
|
SPUILabelDefinitions.SP_LABEL_SIMPLE);
|
||||||
|
gridLayout.addComponent(configurationLabel);
|
||||||
|
gridLayout.setComponentAlignment(configurationLabel, Alignment.MIDDLE_LEFT);
|
||||||
|
|
||||||
|
vLayout.addComponent(gridLayout);
|
||||||
|
|
||||||
|
rootPanel.setContent(vLayout);
|
||||||
|
setCompositionRoot(rootPanel);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void configurationHasChanged() {
|
||||||
|
anonymousDownloadEnabled = downloadAnonymousCheckBox.getValue();
|
||||||
|
notifyConfigurationChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void save() {
|
||||||
|
tenantConfigurationManagement.addOrUpdateConfiguration(TenantConfigurationKey.ANONYMOUS_DOWNLOAD_MODE_ENABLED,
|
||||||
|
downloadAnonymousCheckBox.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void undo() {
|
||||||
|
final TenantConfigurationValue<Boolean> value = tenantConfigurationManagement
|
||||||
|
.getConfigurationValue(TenantConfigurationKey.ANONYMOUS_DOWNLOAD_MODE_ENABLED, Boolean.class);
|
||||||
|
anonymousDownloadEnabled = value.getValue();
|
||||||
|
downloadAnonymousCheckBox.setValue(anonymousDownloadEnabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -29,8 +29,6 @@ import com.vaadin.ui.VerticalLayout;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* View to configure the polling interval and the overdue time.
|
* View to configure the polling interval and the overdue time.
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
@SpringComponent
|
@SpringComponent
|
||||||
@ViewScope
|
@ViewScope
|
||||||
|
|||||||
@@ -38,9 +38,6 @@ import com.vaadin.ui.VerticalLayout;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Main UI for the system configuration view.
|
* Main UI for the system configuration view.
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
@SpringView(name = TenantConfigurationDashboardView.VIEW_NAME, ui = HawkbitUI.class)
|
@SpringView(name = TenantConfigurationDashboardView.VIEW_NAME, ui = HawkbitUI.class)
|
||||||
@ViewScope
|
@ViewScope
|
||||||
@@ -58,6 +55,9 @@ public class TenantConfigurationDashboardView extends CustomComponent implements
|
|||||||
@Autowired
|
@Autowired
|
||||||
private PollingConfigurationView pollingConfigurationView;
|
private PollingConfigurationView pollingConfigurationView;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private DownloadAnonymousConfigurationView downloadAnonymousConfigurationView;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private I18N i18n;
|
private I18N i18n;
|
||||||
|
|
||||||
@@ -73,13 +73,14 @@ public class TenantConfigurationDashboardView extends CustomComponent implements
|
|||||||
private final List<ConfigurationGroup> configurationViews = new ArrayList<>();
|
private final List<ConfigurationGroup> configurationViews = new ArrayList<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* init method adds all Configuration Views to the list of Views.
|
* Init method adds all Configuration Views to the list of Views.
|
||||||
*/
|
*/
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
public void init() {
|
public void init() {
|
||||||
configurationViews.add(defaultDistributionSetTypeLayout);
|
configurationViews.add(defaultDistributionSetTypeLayout);
|
||||||
configurationViews.add(authenticationConfigurationView);
|
configurationViews.add(authenticationConfigurationView);
|
||||||
configurationViews.add(pollingConfigurationView);
|
configurationViews.add(pollingConfigurationView);
|
||||||
|
configurationViews.add(downloadAnonymousConfigurationView);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -154,13 +155,6 @@ public class TenantConfigurationDashboardView extends CustomComponent implements
|
|||||||
undoConfigurationBtn.setEnabled(false);
|
undoConfigurationBtn.setEnabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
*
|
|
||||||
* @see
|
|
||||||
* org.eclipse.hawkbit.server.ui.tenantconfiguration.ConfigurationGroup.
|
|
||||||
* ConfigurationGroupChangeListener #configurationChanged()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void configurationHasChanged() {
|
public void configurationHasChanged() {
|
||||||
saveConfigurationBtn.setEnabled(true);
|
saveConfigurationBtn.setEnabled(true);
|
||||||
|
|||||||
@@ -21,9 +21,6 @@ import com.vaadin.server.Resource;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Menu item for system configuration view.
|
* Menu item for system configuration view.
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
@Order(700)
|
@Order(700)
|
||||||
|
|||||||
@@ -26,16 +26,13 @@ import com.vaadin.ui.VerticalLayout;
|
|||||||
import com.vaadin.ui.themes.ValoTheme;
|
import com.vaadin.ui.themes.ValoTheme;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* This class represents the UI item for the certificate authenticated by an
|
||||||
*
|
* reverse proxy in the authentication configuration view.
|
||||||
*/
|
*/
|
||||||
@SpringComponent
|
@SpringComponent
|
||||||
@ViewScope
|
@ViewScope
|
||||||
public class CertificateAuthenticationConfigurationItem extends AbstractAuthenticationTenantConfigurationItem {
|
public class CertificateAuthenticationConfigurationItem extends AbstractAuthenticationTenantConfigurationItem {
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
@@ -59,7 +56,7 @@ public class CertificateAuthenticationConfigurationItem extends AbstractAuthenti
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* init mehotd called by spring.
|
* Init mehotd called by spring.
|
||||||
*/
|
*/
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
public void init() {
|
public void init() {
|
||||||
@@ -94,12 +91,6 @@ public class CertificateAuthenticationConfigurationItem extends AbstractAuthenti
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
*
|
|
||||||
* @see org.eclipse.hawkbit.server.ui.tenantconfiguration.
|
|
||||||
* TenantConfigurationItem# configEnable()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void configEnable() {
|
public void configEnable() {
|
||||||
if (!configurationEnabled) {
|
if (!configurationEnabled) {
|
||||||
@@ -110,12 +101,6 @@ public class CertificateAuthenticationConfigurationItem extends AbstractAuthenti
|
|||||||
setDetailVisible(true);
|
setDetailVisible(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
*
|
|
||||||
* @see org.eclipse.hawkbit.server.ui.tenantconfiguration.
|
|
||||||
* TenantConfigurationItem# configDisable()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void configDisable() {
|
public void configDisable() {
|
||||||
if (configurationEnabled) {
|
if (configurationEnabled) {
|
||||||
@@ -125,11 +110,6 @@ public class CertificateAuthenticationConfigurationItem extends AbstractAuthenti
|
|||||||
setDetailVisible(false);
|
setDetailVisible(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
*
|
|
||||||
* @see hawkbit.server.ui.tenantconfiguration.TenantConfigurationItem#save()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void save() {
|
public void save() {
|
||||||
if (configurationEnabledChange) {
|
if (configurationEnabledChange) {
|
||||||
@@ -142,11 +122,6 @@ public class CertificateAuthenticationConfigurationItem extends AbstractAuthenti
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
*
|
|
||||||
* @see hawkbit.server.ui.tenantconfiguration.TenantConfigurationItem#undo()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void undo() {
|
public void undo() {
|
||||||
configurationEnabledChange = false;
|
configurationEnabledChange = false;
|
||||||
|
|||||||
@@ -30,16 +30,13 @@ import com.vaadin.ui.VerticalLayout;
|
|||||||
import com.vaadin.ui.themes.ValoTheme;
|
import com.vaadin.ui.themes.ValoTheme;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* This class represents the UI item for the gateway security token section in
|
||||||
*
|
* the authentication configuration view.
|
||||||
*/
|
*/
|
||||||
@SpringComponent
|
@SpringComponent
|
||||||
@ViewScope
|
@ViewScope
|
||||||
public class GatewaySecurityTokenAuthenticationConfigurationItem extends AbstractAuthenticationTenantConfigurationItem {
|
public class GatewaySecurityTokenAuthenticationConfigurationItem extends AbstractAuthenticationTenantConfigurationItem {
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
@@ -70,7 +67,7 @@ public class GatewaySecurityTokenAuthenticationConfigurationItem extends Abstrac
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* init mehotd called by spring.
|
* Init mehotd called by spring.
|
||||||
*/
|
*/
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
public void init() {
|
public void init() {
|
||||||
@@ -135,12 +132,6 @@ public class GatewaySecurityTokenAuthenticationConfigurationItem extends Abstrac
|
|||||||
notifyConfigurationChanged();
|
notifyConfigurationChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
*
|
|
||||||
* @see org.eclipse.hawkbit.server.ui.tenantconfiguration.
|
|
||||||
* TenantConfigurationItem# configEnable()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void configEnable() {
|
public void configEnable() {
|
||||||
if (!configurationEnabled) {
|
if (!configurationEnabled) {
|
||||||
|
|||||||
@@ -19,17 +19,13 @@ import com.vaadin.spring.annotation.SpringComponent;
|
|||||||
import com.vaadin.spring.annotation.ViewScope;
|
import com.vaadin.spring.annotation.ViewScope;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* This class represents the UI item for the target security token section in
|
||||||
*
|
* the authentication configuration view.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
@SpringComponent
|
@SpringComponent
|
||||||
@ViewScope
|
@ViewScope
|
||||||
public class TargetSecurityTokenAuthenticationConfigurationItem extends AbstractAuthenticationTenantConfigurationItem {
|
public class TargetSecurityTokenAuthenticationConfigurationItem extends AbstractAuthenticationTenantConfigurationItem {
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
@@ -49,7 +45,7 @@ public class TargetSecurityTokenAuthenticationConfigurationItem extends Abstract
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* init mehotd called by spring.
|
* Init mehotd called by spring.
|
||||||
*/
|
*/
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
public void init() {
|
public void init() {
|
||||||
@@ -57,12 +53,6 @@ public class TargetSecurityTokenAuthenticationConfigurationItem extends Abstract
|
|||||||
configurationEnabled = isConfigEnabled();
|
configurationEnabled = isConfigEnabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
*
|
|
||||||
* @see org.eclipse.hawkbit.server.ui.tenantconfiguration.
|
|
||||||
* TenantConfigurationItem# configEnable()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void configEnable() {
|
public void configEnable() {
|
||||||
if (!configurationEnabled) {
|
if (!configurationEnabled) {
|
||||||
@@ -71,12 +61,6 @@ public class TargetSecurityTokenAuthenticationConfigurationItem extends Abstract
|
|||||||
configurationEnabled = true;
|
configurationEnabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
*
|
|
||||||
* @see org.eclipse.hawkbit.server.ui.tenantconfiguration.
|
|
||||||
* TenantConfigurationItem# configDisable()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void configDisable() {
|
public void configDisable() {
|
||||||
if (configurationEnabled) {
|
if (configurationEnabled) {
|
||||||
|
|||||||
@@ -14,8 +14,6 @@ import java.util.List;
|
|||||||
|
|
||||||
import org.eclipse.hawkbit.ui.tenantconfiguration.ConfigurationItem;
|
import org.eclipse.hawkbit.ui.tenantconfiguration.ConfigurationItem;
|
||||||
|
|
||||||
import com.vaadin.data.Property.ValueChangeEvent;
|
|
||||||
import com.vaadin.data.Property.ValueChangeListener;
|
|
||||||
import com.vaadin.ui.Alignment;
|
import com.vaadin.ui.Alignment;
|
||||||
import com.vaadin.ui.CheckBox;
|
import com.vaadin.ui.CheckBox;
|
||||||
import com.vaadin.ui.GridLayout;
|
import com.vaadin.ui.GridLayout;
|
||||||
@@ -50,8 +48,8 @@ public class DurationConfigField extends GridLayout implements ConfigurationItem
|
|||||||
this.addComponent(durationField, 1, 0);
|
this.addComponent(durationField, 1, 0);
|
||||||
this.setComponentAlignment(durationField, Alignment.MIDDLE_LEFT);
|
this.setComponentAlignment(durationField, Alignment.MIDDLE_LEFT);
|
||||||
|
|
||||||
checkBox.addValueChangeListener(event->checkBoxChange());
|
checkBox.addValueChangeListener(event -> checkBoxChange());
|
||||||
durationField.addValueChangeListener(event->notifyConfigurationChanged());
|
durationField.addValueChangeListener(event -> notifyConfigurationChanged());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkBoxChange() {
|
private void checkBoxChange() {
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ import org.eclipse.hawkbit.repository.model.TargetInfo.PollStatus;
|
|||||||
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
|
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
|
||||||
import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus;
|
import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus;
|
||||||
import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus.Status;
|
import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus.Status;
|
||||||
|
import org.eclipse.hawkbit.ui.rollout.StatusFontIcon;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.security.core.userdetails.UserDetails;
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
@@ -89,8 +90,6 @@ public final class HawkbitCommonUtil {
|
|||||||
private static final String COUNT_STYLE = " countStyle = document.createElement('style'); ";
|
private static final String COUNT_STYLE = " countStyle = document.createElement('style'); ";
|
||||||
private static final String COUNT_STYLE_ID = " countStyle.id=\"sp-drag-count\"; ";
|
private static final String COUNT_STYLE_ID = " countStyle.id=\"sp-drag-count\"; ";
|
||||||
private static final String APPEND_CHILD = " document.head.appendChild(countStyle);";
|
private static final String APPEND_CHILD = " document.head.appendChild(countStyle);";
|
||||||
private static final String HEADER_VERSION = "header.version";
|
|
||||||
private static final String HEADER_NAME = "header.name";
|
|
||||||
private static final String SM_HIGHLIGHT_CREATE_SCRIPT = "smHighlight = document.createElement('style'); smHighlight.id=\"sm-table-highlight\"; document.head.appendChild(smHighlight); ";
|
private static final String SM_HIGHLIGHT_CREATE_SCRIPT = "smHighlight = document.createElement('style'); smHighlight.id=\"sm-table-highlight\"; document.head.appendChild(smHighlight); ";
|
||||||
private static final String SM_HIGHLIGHT_REMOVE_SCRIPT = "var y = document.getElementById('sm-table-highlight'); if(y) { document.head.removeChild(y); } ";
|
private static final String SM_HIGHLIGHT_REMOVE_SCRIPT = "var y = document.getElementById('sm-table-highlight'); if(y) { document.head.removeChild(y); } ";
|
||||||
private static final String SM_HIGHLIGHT_RESET_SCRIPT = SM_HIGHLIGHT_REMOVE_SCRIPT + SM_HIGHLIGHT_CREATE_SCRIPT
|
private static final String SM_HIGHLIGHT_RESET_SCRIPT = SM_HIGHLIGHT_REMOVE_SCRIPT + SM_HIGHLIGHT_CREATE_SCRIPT
|
||||||
@@ -1279,4 +1278,19 @@ public final class HawkbitCommonUtil {
|
|||||||
return val.toString();
|
return val.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Receive the code point of a given StatusFontIcon.
|
||||||
|
*
|
||||||
|
* @param statusFontIcon
|
||||||
|
* the status font icon
|
||||||
|
* @return the code point of the StatusFontIcon
|
||||||
|
*/
|
||||||
|
public static String getCodePoint(final StatusFontIcon statusFontIcon) {
|
||||||
|
if (statusFontIcon == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return statusFontIcon.getFontIcon() != null ? Integer.toString(statusFontIcon.getFontIcon().getCodepoint())
|
||||||
|
: null;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -501,6 +501,11 @@ public final class SPUIComponetIdProvider {
|
|||||||
*/
|
*/
|
||||||
public static final String SYSTEM_CONFIGURATION_CANCEL = "system.configuration.cancel";
|
public static final String SYSTEM_CONFIGURATION_CANCEL = "system.configuration.cancel";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Id of the anonymous download checkbox.
|
||||||
|
*/
|
||||||
|
public static final String SYSTEM_CONFIGURATION_ANONYMOUS_DOWNLOAD_CHECKBOX = "system.configuration.anonymous.download.checkbox";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Id of maximize/minimize icon of table - Software module table.
|
* Id of maximize/minimize icon of table - Software module table.
|
||||||
*/
|
*/
|
||||||
@@ -827,7 +832,7 @@ public final class SPUIComponetIdProvider {
|
|||||||
* Rollout status label id.
|
* Rollout status label id.
|
||||||
*/
|
*/
|
||||||
public static final String ROLLOUT_STATUS_LABEL_ID = "rollout.status.id";
|
public static final String ROLLOUT_STATUS_LABEL_ID = "rollout.status.id";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rollout group status label id.
|
* Rollout group status label id.
|
||||||
*/
|
*/
|
||||||
@@ -867,12 +872,12 @@ public final class SPUIComponetIdProvider {
|
|||||||
* Rollout group targets count message label.
|
* Rollout group targets count message label.
|
||||||
*/
|
*/
|
||||||
public static final String ROLLOUT_GROUP_TARGET_LABEL = "rollout.group.target.label";
|
public static final String ROLLOUT_GROUP_TARGET_LABEL = "rollout.group.target.label";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Action confirmation popup id.
|
* Action confirmation popup id.
|
||||||
*/
|
*/
|
||||||
public static final String CONFIRMATION_POPUP_ID = "action.confirmation.popup.id";
|
public static final String CONFIRMATION_POPUP_ID = "action.confirmation.popup.id";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validation status icon .
|
* Validation status icon .
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -401,6 +401,8 @@ configuration.polling.title=Polling Configuration
|
|||||||
configuration.polling.time=Polling Time
|
configuration.polling.time=Polling Time
|
||||||
configuration.polling.overduetime=Polling Overdue Time
|
configuration.polling.overduetime=Polling Overdue Time
|
||||||
configuration.polling.custom.value=use a custom value
|
configuration.polling.custom.value=use a custom value
|
||||||
|
enonymous.download.title=Anonymous download
|
||||||
|
enonymous.download.label=Allow anonymous download. If you enable this option the download server will accept anonymous download requests.
|
||||||
|
|
||||||
#Calendar
|
#Calendar
|
||||||
calendar.year=year
|
calendar.year=year
|
||||||
|
|||||||
@@ -389,6 +389,8 @@ configuration.defaultdistributionset.select.label=Wahl des default Distribution
|
|||||||
configuration.savebutton.tooltip=Konfigurationen speichern
|
configuration.savebutton.tooltip=Konfigurationen speichern
|
||||||
configuration.cancellbutton.tooltip=Konfigurationen zur<75>cksetzen
|
configuration.cancellbutton.tooltip=Konfigurationen zur<75>cksetzen
|
||||||
configuration.authentication.title=Authentifikationseinstellungen
|
configuration.authentication.title=Authentifikationseinstellungen
|
||||||
|
enonymous.download.title=Anonymes herunterladen
|
||||||
|
enonymous.download.label=Erlaube anonymes herunterladen. When diese option aktivert ist, wird der download server anonyme download anfragen erlauben.
|
||||||
#Calendar
|
#Calendar
|
||||||
calendar.year=Jahr
|
calendar.year=Jahr
|
||||||
calendar.years=Jahre
|
calendar.years=Jahre
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user