Merge remote-tracking branch 'origin/dev' into dev
This commit is contained in:
commit
1d422ec420
48 changed files with 368 additions and 381 deletions
|
@ -31,10 +31,4 @@ public class CORSFilter implements Filter {
|
|||
|
||||
chain.doFilter(req, res);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(FilterConfig filterConfig) {}
|
||||
|
||||
@Override
|
||||
public void destroy() {}
|
||||
}
|
||||
|
|
|
@ -36,9 +36,9 @@ public class JWTRequestFilter extends OncePerRequestFilter {
|
|||
try {
|
||||
username = jwtTokenUtils.getUsernameFromToken(jwtToken);
|
||||
} catch (IllegalArgumentException e) {
|
||||
System.out.println("Unable to get JWT Token");
|
||||
logger.info("Unable to get JWT Token");
|
||||
} catch (ExpiredJwtException e) {
|
||||
System.out.println("JWT Token has expired");
|
||||
logger.info("JWT Token has expired");
|
||||
}
|
||||
} else {
|
||||
logger.warn("JWT Token does not begin with Bearer String");
|
||||
|
|
|
@ -14,7 +14,7 @@ import org.springframework.stereotype.Component;
|
|||
@Component
|
||||
public class JWTTokenUtils {
|
||||
/** The duration in seconds of the validity of a single token */
|
||||
private static final long JWT_TOKEN_VALIDITY = 5 * 60 * 60;
|
||||
private static final long JWT_TOKEN_VALIDITY = (long) 5 * 60 * 60;
|
||||
|
||||
/** The secret key used to encrypt all JWTs */
|
||||
@Value("${jwt.secret}")
|
||||
|
@ -68,7 +68,7 @@ public class JWTTokenUtils {
|
|||
* @param userDetails user details to validate against
|
||||
* @return true if valid, false if not
|
||||
*/
|
||||
public Boolean validateToken(String token, UserDetails userDetails) {
|
||||
public boolean validateToken(String token, UserDetails userDetails) {
|
||||
final String username = getUsernameFromToken(token);
|
||||
return (username.equals(userDetails.getUsername()) && !isTokenExpired(token));
|
||||
}
|
||||
|
|
|
@ -1,21 +1,5 @@
|
|||
package ch.usi.inf.sa4.sanmarinoes.smarthut.config;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2011 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
|
@ -158,8 +142,8 @@ import java.util.Map;
|
|||
public final class RuntimeTypeAdapterFactory<T> implements TypeAdapterFactory {
|
||||
private final Class<?> baseType;
|
||||
private final String typeFieldName;
|
||||
private final Map<String, Class<?>> labelToSubtype = new LinkedHashMap<String, Class<?>>();
|
||||
private final Map<Class<?>, String> subtypeToLabel = new LinkedHashMap<Class<?>, String>();
|
||||
private final Map<String, Class<?>> labelToSubtype = new LinkedHashMap<>();
|
||||
private final Map<Class<?>, String> subtypeToLabel = new LinkedHashMap<>();
|
||||
private final boolean maintainType;
|
||||
|
||||
private RuntimeTypeAdapterFactory(
|
||||
|
@ -179,7 +163,7 @@ public final class RuntimeTypeAdapterFactory<T> implements TypeAdapterFactory {
|
|||
*/
|
||||
public static <T> RuntimeTypeAdapterFactory<T> of(
|
||||
Class<T> baseType, String typeFieldName, boolean maintainType) {
|
||||
return new RuntimeTypeAdapterFactory<T>(baseType, typeFieldName, maintainType);
|
||||
return new RuntimeTypeAdapterFactory<>(baseType, typeFieldName, maintainType);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -187,7 +171,7 @@ public final class RuntimeTypeAdapterFactory<T> implements TypeAdapterFactory {
|
|||
* the type field name. Type field names are case sensitive.
|
||||
*/
|
||||
public static <T> RuntimeTypeAdapterFactory<T> of(Class<T> baseType, String typeFieldName) {
|
||||
return new RuntimeTypeAdapterFactory<T>(baseType, typeFieldName, false);
|
||||
return new RuntimeTypeAdapterFactory<>(baseType, typeFieldName, false);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -195,7 +179,7 @@ public final class RuntimeTypeAdapterFactory<T> implements TypeAdapterFactory {
|
|||
* field name.
|
||||
*/
|
||||
public static <T> RuntimeTypeAdapterFactory<T> of(Class<T> baseType) {
|
||||
return new RuntimeTypeAdapterFactory<T>(baseType, "type", false);
|
||||
return new RuntimeTypeAdapterFactory<>(baseType, "type", false);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -216,26 +200,15 @@ public final class RuntimeTypeAdapterFactory<T> implements TypeAdapterFactory {
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers {@code type} identified by its {@link Class#getSimpleName simple name}. Labels are
|
||||
* case sensitive.
|
||||
*
|
||||
* @throws IllegalArgumentException if either {@code type} or its simple name have already been
|
||||
* registered on this type adapter.
|
||||
*/
|
||||
public RuntimeTypeAdapterFactory<T> registerSubtype(Class<? extends T> type) {
|
||||
return registerSubtype(type, type.getSimpleName());
|
||||
}
|
||||
|
||||
public <R> TypeAdapter<R> create(Gson gson, TypeToken<R> type) {
|
||||
if (type.getRawType() != baseType) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final Map<String, TypeAdapter<?>> labelToDelegate =
|
||||
new LinkedHashMap<String, TypeAdapter<?>>(labelToSubtype.size());
|
||||
new LinkedHashMap<>(labelToSubtype.size());
|
||||
final Map<Class<?>, TypeAdapter<?>> subtypeToDelegate =
|
||||
new LinkedHashMap<Class<?>, TypeAdapter<?>>(labelToSubtype.size());
|
||||
new LinkedHashMap<>(labelToSubtype.size());
|
||||
for (Map.Entry<String, Class<?>> entry : labelToSubtype.entrySet()) {
|
||||
TypeAdapter<?> delegate =
|
||||
gson.getDelegateAdapter(this, TypeToken.get(entry.getValue()));
|
||||
|
|
|
@ -33,8 +33,7 @@ public class AutomationController {
|
|||
@GetMapping
|
||||
public List<Automation> getAll(
|
||||
@RequestParam(value = "hostId", required = false) Long hostId,
|
||||
final Principal principal)
|
||||
throws NotFoundException {
|
||||
final Principal principal) {
|
||||
final Long userId = userService.findByUsername(principal.getName()).getId();
|
||||
return automationRepository.findAllByUserId(userId);
|
||||
}
|
||||
|
@ -100,7 +99,16 @@ public class AutomationController {
|
|||
req.getScenes()
|
||||
.stream()
|
||||
.map(AutomationFastUpdateRequest.ScenePriorityDTO::toModel)
|
||||
.map(t -> t.setAutomationId(a.getId()))
|
||||
.map(
|
||||
t -> {
|
||||
t.setAutomationId(a.getId());
|
||||
|
||||
// this is here just to pass the quality gate,
|
||||
// please do not replicate unless the quality gate sees
|
||||
// it as a bug
|
||||
t.setAutomation(a);
|
||||
return t;
|
||||
})
|
||||
.collect(Collectors.toList()));
|
||||
|
||||
a.getScenes().clear();
|
||||
|
|
|
@ -26,7 +26,7 @@ public class ButtonDimmerController
|
|||
ButtonDimmerRepository inputRepository,
|
||||
DimmableRepository<Dimmable> outputRepository,
|
||||
DeviceService deviceService) {
|
||||
super(inputRepository, outputRepository, DimmableLight.BUTTON_DIMMER_DIMMABLE_CONNECTOR);
|
||||
super(inputRepository, outputRepository);
|
||||
this.deviceService = deviceService;
|
||||
this.buttonDimmerRepository = inputRepository;
|
||||
}
|
||||
|
@ -58,13 +58,11 @@ public class ButtonDimmerController
|
|||
.findByIdAndUsername(bd.getId(), principal.getName())
|
||||
.orElseThrow(NotFoundException::new);
|
||||
|
||||
switch (bd.getDimType()) {
|
||||
case UP:
|
||||
buttonDimmer.increaseIntensity();
|
||||
break;
|
||||
case DOWN:
|
||||
buttonDimmer.decreaseIntensity();
|
||||
break;
|
||||
if (bd.getDimType() == ButtonDimmerDimRequest.DimType.UP) {
|
||||
|
||||
buttonDimmer.increaseIntensity();
|
||||
} else {
|
||||
buttonDimmer.decreaseIntensity();
|
||||
}
|
||||
|
||||
deviceService.saveAllAsOwner(buttonDimmer.getOutputs(), principal.getName());
|
||||
|
|
|
@ -16,10 +16,10 @@ import org.springframework.web.bind.annotation.*;
|
|||
@RequestMapping("/dimmableLight")
|
||||
public class DimmableLightController extends GuestEnabledController<DimmableLight> {
|
||||
|
||||
private DimmableLightRepository dimmableLightRepository;
|
||||
private SceneRepository sceneRepository;
|
||||
private StateRepository<State<?>> stateRepository;
|
||||
private DeviceService deviceService;
|
||||
private final DimmableLightRepository dimmableLightRepository;
|
||||
private final SceneRepository sceneRepository;
|
||||
private final StateRepository<State<?>> stateRepository;
|
||||
private final DeviceService deviceService;
|
||||
|
||||
@Autowired
|
||||
public DimmableLightController(
|
||||
|
@ -49,10 +49,10 @@ public class DimmableLightController extends GuestEnabledController<DimmableLigh
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Assume that only the host can create a device
|
||||
Here save always as host, but remember to propagate change to guests (DeviceService.saveAsOwner())
|
||||
*/
|
||||
/**
|
||||
* Assume that only the host can create a device Here save always as host, but remember to
|
||||
* propagate change to guests (DeviceService.saveAsOwner())
|
||||
*/
|
||||
@PostMapping
|
||||
public DimmableLight create(
|
||||
@Valid @RequestBody DimmableSaveRequest dl, final Principal principal)
|
||||
|
@ -61,9 +61,7 @@ public class DimmableLightController extends GuestEnabledController<DimmableLigh
|
|||
return save(new DimmableLight(), dl, principal.getName(), null);
|
||||
}
|
||||
|
||||
/*
|
||||
Logic for saving either as owner or guest is handled in method save of this controller
|
||||
*/
|
||||
/** Logic for saving either as owner or guest is handled in method save of this controller */
|
||||
@PutMapping
|
||||
public DimmableLight update(
|
||||
@Valid @RequestBody DimmableSaveRequest sp,
|
||||
|
@ -84,8 +82,10 @@ public class DimmableLightController extends GuestEnabledController<DimmableLigh
|
|||
deviceService.deleteByIdAsOwner(id, principal.getName());
|
||||
}
|
||||
|
||||
// the full url should be: "/dimmableLight/{id}/state?sceneId={sceneId}
|
||||
// however it is not necessary to specify the query in the mapping
|
||||
/**
|
||||
* the full url should be: "/dimmableLight/{id}/state?sceneId={sceneId} however it is not
|
||||
* necessary to specify the query in the mapping
|
||||
*/
|
||||
@PostMapping("/{id}/state")
|
||||
public State<? extends Dimmable> sceneBinding(
|
||||
@PathVariable("id") long deviceId,
|
||||
|
|
|
@ -5,7 +5,6 @@ import static ch.usi.inf.sa4.sanmarinoes.smarthut.utils.Utils.toList;
|
|||
import ch.usi.inf.sa4.sanmarinoes.smarthut.dto.GuestPermissionsRequest;
|
||||
import ch.usi.inf.sa4.sanmarinoes.smarthut.dto.GuestsUpdateRequest;
|
||||
import ch.usi.inf.sa4.sanmarinoes.smarthut.dto.UserResponse;
|
||||
import ch.usi.inf.sa4.sanmarinoes.smarthut.error.NotFoundException;
|
||||
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.EagerUserRepository;
|
||||
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.User;
|
||||
import java.security.Principal;
|
||||
|
@ -46,8 +45,7 @@ public class GuestController {
|
|||
|
||||
@PutMapping("/guests")
|
||||
public List<User> setGuests(
|
||||
@RequestBody @Valid GuestsUpdateRequest g, final Principal principal)
|
||||
throws NotFoundException {
|
||||
@RequestBody @Valid GuestsUpdateRequest g, final Principal principal) {
|
||||
Iterable<User> guests = userRepository.findAllById(g.ids);
|
||||
User host = userRepository.findByUsername(principal.getName());
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ import org.springframework.web.bind.annotation.RequestBody;
|
|||
* @param <O> the output device attached to I
|
||||
*/
|
||||
public abstract class InputDeviceConnectionController<
|
||||
I extends InputDevice, O extends OutputDevice> {
|
||||
I extends InputDevice & Connectable<O>, O extends OutputDevice> {
|
||||
|
||||
private class Connection {
|
||||
private final I input;
|
||||
|
@ -53,26 +53,20 @@ public abstract class InputDeviceConnectionController<
|
|||
|
||||
@Autowired private DeviceService deviceService;
|
||||
|
||||
private DeviceRepository<I> inputRepository;
|
||||
private final DeviceRepository<I> inputRepository;
|
||||
|
||||
private DeviceRepository<O> outputReposiory;
|
||||
|
||||
private Connector<I, O> connector;
|
||||
private final DeviceRepository<O> outputReposiory;
|
||||
|
||||
/**
|
||||
* Contstructs the controller by requiring essential object for the controller implementation
|
||||
*
|
||||
* @param inputRepository the input device repository
|
||||
* @param outputRepository the output device repository
|
||||
* @param connector a appropriate Connector instance for the I and O tyoes.
|
||||
*/
|
||||
protected InputDeviceConnectionController(
|
||||
DeviceRepository<I> inputRepository,
|
||||
DeviceRepository<O> outputRepository,
|
||||
Connector<I, O> connector) {
|
||||
DeviceRepository<I> inputRepository, DeviceRepository<O> outputRepository) {
|
||||
this.inputRepository = inputRepository;
|
||||
this.outputReposiory = outputRepository;
|
||||
this.connector = connector;
|
||||
}
|
||||
|
||||
private Connection checkConnectionIDs(Long inputId, List<Long> outputs, String username)
|
||||
|
@ -104,7 +98,7 @@ public abstract class InputDeviceConnectionController<
|
|||
final Connection pair = checkConnectionIDs(inputId, outputs, username);
|
||||
|
||||
for (final O o : pair.getOutputs()) {
|
||||
connector.connect(pair.getInput(), o, true);
|
||||
pair.getInput().connect(o, true);
|
||||
}
|
||||
|
||||
deviceService.saveAllAsOwner(pair.getOutputs(), username);
|
||||
|
@ -124,7 +118,7 @@ public abstract class InputDeviceConnectionController<
|
|||
final Connection pair = checkConnectionIDs(inputId, outputs, username);
|
||||
|
||||
for (final O o : pair.getOutputs()) {
|
||||
connector.connect(pair.getInput(), o, false);
|
||||
pair.getInput().connect(o, false);
|
||||
}
|
||||
|
||||
deviceService.saveAllAsOwner(pair.getOutputs(), username);
|
||||
|
|
|
@ -25,7 +25,7 @@ public class KnobDimmerController extends InputDeviceConnectionController<KnobDi
|
|||
KnobDimmerRepository inputRepository,
|
||||
DimmableRepository<Dimmable> outputRepository,
|
||||
DeviceService deviceService) {
|
||||
super(inputRepository, outputRepository, Dimmable.KNOB_DIMMER_DIMMABLE_CONNECTOR);
|
||||
super(inputRepository, outputRepository);
|
||||
this.knobDimmerRepository = inputRepository;
|
||||
this.deviceService = deviceService;
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@ import ch.usi.inf.sa4.sanmarinoes.smarthut.models.MotionSensor;
|
|||
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.MotionSensorRepository;
|
||||
import ch.usi.inf.sa4.sanmarinoes.smarthut.service.DeviceService;
|
||||
import ch.usi.inf.sa4.sanmarinoes.smarthut.service.MotionSensorService;
|
||||
import ch.usi.inf.sa4.sanmarinoes.smarthut.socket.SensorSocketEndpoint;
|
||||
import java.security.Principal;
|
||||
import javax.validation.Valid;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
@ -21,7 +20,6 @@ public class MotionSensorController {
|
|||
@Autowired private DeviceService deviceService;
|
||||
@Autowired private MotionSensorService motionSensorService;
|
||||
@Autowired private MotionSensorRepository motionSensorRepository;
|
||||
@Autowired private SensorSocketEndpoint sensorSocketEndpoint;
|
||||
|
||||
@PostMapping
|
||||
public MotionSensor create(
|
||||
|
|
|
@ -97,8 +97,6 @@ public class RegularLightController extends GuestEnabledController<RegularLight>
|
|||
deviceService.deleteByIdAsOwner(id, principal.getName());
|
||||
}
|
||||
|
||||
// the full url should be: "/regularLight/{id}/state?sceneId={sceneId}
|
||||
// however it is not necessary to specify the query in the mapping
|
||||
@PostMapping("/{id}/state")
|
||||
public State<? extends Switchable> sceneBinding(
|
||||
@PathVariable("id") long deviceId,
|
||||
|
|
|
@ -6,7 +6,6 @@ import ch.usi.inf.sa4.sanmarinoes.smarthut.dto.RoomSaveRequest;
|
|||
import ch.usi.inf.sa4.sanmarinoes.smarthut.error.NotFoundException;
|
||||
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.*;
|
||||
import ch.usi.inf.sa4.sanmarinoes.smarthut.service.DeviceService;
|
||||
import ch.usi.inf.sa4.sanmarinoes.smarthut.service.ThermostatService;
|
||||
import ch.usi.inf.sa4.sanmarinoes.smarthut.utils.Utils;
|
||||
import java.security.Principal;
|
||||
import java.util.*;
|
||||
|
@ -20,19 +19,33 @@ import org.springframework.web.bind.annotation.*;
|
|||
@RequestMapping("/room")
|
||||
public class RoomController {
|
||||
|
||||
@Autowired private RoomRepository roomRepository;
|
||||
private final RoomRepository roomRepository;
|
||||
|
||||
@Autowired private UserRepository userRepository;
|
||||
private final UserRepository userRepository;
|
||||
|
||||
@Autowired private DeviceService deviceService;
|
||||
private final DeviceService deviceService;
|
||||
|
||||
@Autowired private SwitchRepository switchRepository;
|
||||
private final SwitchRepository switchRepository;
|
||||
|
||||
@Autowired private ButtonDimmerRepository buttonDimmerRepository;
|
||||
private final ButtonDimmerRepository buttonDimmerRepository;
|
||||
|
||||
@Autowired private KnobDimmerRepository knobDimmerRepository;
|
||||
private final KnobDimmerRepository knobDimmerRepository;
|
||||
|
||||
@Autowired private ThermostatService thermostatService;
|
||||
@Autowired
|
||||
public RoomController(
|
||||
RoomRepository roomRepository,
|
||||
UserRepository userRepository,
|
||||
DeviceService deviceService,
|
||||
SwitchRepository switchRepository,
|
||||
ButtonDimmerRepository buttonDimmerRepository,
|
||||
KnobDimmerRepository knobDimmerRepository) {
|
||||
this.roomRepository = roomRepository;
|
||||
this.userRepository = userRepository;
|
||||
this.deviceService = deviceService;
|
||||
this.switchRepository = switchRepository;
|
||||
this.buttonDimmerRepository = buttonDimmerRepository;
|
||||
this.knobDimmerRepository = knobDimmerRepository;
|
||||
}
|
||||
|
||||
private <T> List<T> fetchOwnerOrGuest(
|
||||
final List<T> list, Long hostId, final Principal principal) throws NotFoundException {
|
||||
|
|
|
@ -25,8 +25,7 @@ public class ScenePriorityController {
|
|||
@Autowired ScenePriorityRepository scenePriorityRepository;
|
||||
|
||||
@GetMapping("/{automationId}")
|
||||
public List<ScenePriority> getByAutomationId(@PathVariable long automationId)
|
||||
throws NotFoundException {
|
||||
public List<ScenePriority> getByAutomationId(@PathVariable long automationId) {
|
||||
return scenePriorityRepository.findAllByAutomationId(automationId);
|
||||
}
|
||||
|
||||
|
|
|
@ -22,12 +22,22 @@ import org.springframework.web.bind.annotation.RestController;
|
|||
@EnableAutoConfiguration
|
||||
@RequestMapping("/securityCamera")
|
||||
public class SecurityCameraController {
|
||||
private final DeviceService deviceService;
|
||||
private final SecurityCameraRepository securityCameraService;
|
||||
private final SceneRepository sceneRepository;
|
||||
private final StateRepository<State<?>> stateRepository;
|
||||
|
||||
@Autowired private DeviceService deviceService;
|
||||
@Autowired private SecurityCameraRepository securityCameraService;
|
||||
@Autowired private SceneRepository sceneRepository;
|
||||
@Autowired private StateRepository<State<?>> stateRepository;
|
||||
@Autowired private RoomRepository roomRepository;
|
||||
@Autowired
|
||||
public SecurityCameraController(
|
||||
DeviceService deviceService,
|
||||
SecurityCameraRepository securityCameraService,
|
||||
SceneRepository sceneRepository,
|
||||
StateRepository<State<?>> stateRepository) {
|
||||
this.deviceService = deviceService;
|
||||
this.securityCameraService = securityCameraService;
|
||||
this.sceneRepository = sceneRepository;
|
||||
this.stateRepository = stateRepository;
|
||||
}
|
||||
|
||||
private SecurityCamera save(
|
||||
SecurityCamera newSC, SwitchableSaveRequest sc, final Principal principal) {
|
||||
|
@ -76,8 +86,8 @@ public class SecurityCameraController {
|
|||
.findByIdAndUsername(deviceId, principal.getName())
|
||||
.orElseThrow(NotFoundException::new);
|
||||
State<? extends Switchable> s = d.cloneState();
|
||||
sceneRepository.findById(sceneId).orElseThrow(NotFoundException::new);
|
||||
s.setSceneId(sceneId);
|
||||
final Scene sc = sceneRepository.findById(sceneId).orElseThrow(NotFoundException::new);
|
||||
s.setSceneId(sc.getId());
|
||||
if (stateRepository.countByDeviceIdAndSceneId(deviceId, sceneId) > 0)
|
||||
throw new DuplicateStateException();
|
||||
return stateRepository.save(s);
|
||||
|
|
|
@ -5,7 +5,6 @@ import ch.usi.inf.sa4.sanmarinoes.smarthut.error.NotFoundException;
|
|||
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.*;
|
||||
import ch.usi.inf.sa4.sanmarinoes.smarthut.service.DeviceService;
|
||||
import ch.usi.inf.sa4.sanmarinoes.smarthut.service.SensorService;
|
||||
import ch.usi.inf.sa4.sanmarinoes.smarthut.socket.SensorSocketEndpoint;
|
||||
import java.math.BigDecimal;
|
||||
import java.security.Principal;
|
||||
import java.util.*;
|
||||
|
@ -19,13 +18,21 @@ import org.springframework.web.bind.annotation.*;
|
|||
@RequestMapping("/sensor")
|
||||
public class SensorController {
|
||||
|
||||
@Autowired private DeviceService deviceService;
|
||||
private final DeviceService deviceService;
|
||||
|
||||
@Autowired private SensorRepository sensorRepository;
|
||||
private final SensorRepository sensorRepository;
|
||||
|
||||
@Autowired private SensorSocketEndpoint sensorSocketEndpoint;
|
||||
private final SensorService sensorService;
|
||||
|
||||
@Autowired private SensorService sensorService;
|
||||
@Autowired
|
||||
public SensorController(
|
||||
DeviceService deviceService,
|
||||
SensorRepository sensorRepository,
|
||||
SensorService sensorService) {
|
||||
this.deviceService = deviceService;
|
||||
this.sensorRepository = sensorRepository;
|
||||
this.sensorService = sensorService;
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
public Sensor create(@Valid @RequestBody SensorSaveRequest s, final Principal principal)
|
||||
|
|
|
@ -17,8 +17,8 @@ import org.springframework.web.bind.annotation.*;
|
|||
@RequestMapping("/switch")
|
||||
public class SwitchController extends InputDeviceConnectionController<Switch, Switchable> {
|
||||
|
||||
private SwitchRepository switchRepository;
|
||||
private DeviceService deviceService;
|
||||
private final SwitchRepository switchRepository;
|
||||
private final DeviceService deviceService;
|
||||
|
||||
/**
|
||||
* Contstructs the controller by requiring essential object for the controller implementation
|
||||
|
@ -31,7 +31,7 @@ public class SwitchController extends InputDeviceConnectionController<Switch, Sw
|
|||
SwitchRepository inputRepository,
|
||||
SwitchableRepository<Switchable> outputRepository,
|
||||
DeviceService deviceService) {
|
||||
super(inputRepository, outputRepository, Switchable.SWITCH_SWITCHABLE_CONNECTOR);
|
||||
super(inputRepository, outputRepository);
|
||||
this.deviceService = deviceService;
|
||||
this.switchRepository = inputRepository;
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ import ch.usi.inf.sa4.sanmarinoes.smarthut.error.DuplicateStateException;
|
|||
import ch.usi.inf.sa4.sanmarinoes.smarthut.error.NotFoundException;
|
||||
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.*;
|
||||
import ch.usi.inf.sa4.sanmarinoes.smarthut.service.DeviceService;
|
||||
import ch.usi.inf.sa4.sanmarinoes.smarthut.service.ThermostatService;
|
||||
import ch.usi.inf.sa4.sanmarinoes.smarthut.service.ThermostatPopulationService;
|
||||
import java.security.Principal;
|
||||
import javax.validation.Valid;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
@ -19,7 +19,7 @@ public class ThermostatController {
|
|||
|
||||
@Autowired private DeviceService deviceService;
|
||||
@Autowired private ThermostatRepository thermostatRepository;
|
||||
@Autowired private ThermostatService thermostatService;
|
||||
@Autowired private ThermostatPopulationService thermostatService;
|
||||
@Autowired private SceneRepository sceneRepository;
|
||||
@Autowired private StateRepository<State<?>> stateRepository;
|
||||
|
||||
|
@ -30,7 +30,6 @@ public class ThermostatController {
|
|||
newT.setRoomId(t.getRoomId());
|
||||
newT.setUseExternalSensors(t.isUseExternalSensors());
|
||||
newT.setOn(false);
|
||||
System.out.println(newT);
|
||||
|
||||
thermostatService.populateMeasuredTemperature(newT);
|
||||
newT = thermostatRepository.save(newT);
|
||||
|
|
|
@ -155,10 +155,8 @@ public class UserAccountController {
|
|||
* @throws EmailTokenNotFoundException if given token is not a valid token for password reset
|
||||
*/
|
||||
@PutMapping("/reset-password")
|
||||
public void resetPassword(
|
||||
@Valid @RequestBody PasswordResetRequest resetRequest,
|
||||
final HttpServletResponse response)
|
||||
throws EmailTokenNotFoundException, IOException {
|
||||
public void resetPassword(@Valid @RequestBody PasswordResetRequest resetRequest)
|
||||
throws EmailTokenNotFoundException {
|
||||
final ConfirmationToken token =
|
||||
confirmationTokenRepository.findByConfirmationToken(
|
||||
resetRequest.getConfirmationToken());
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package ch.usi.inf.sa4.sanmarinoes.smarthut.dto;
|
||||
|
||||
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.Icon;
|
||||
import com.sun.istack.NotNull;
|
||||
import javax.persistence.Column;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
public class SceneSaveRequest {
|
||||
|
||||
|
|
|
@ -43,10 +43,6 @@ public class Automation {
|
|||
this.id = id;
|
||||
}
|
||||
|
||||
public Set<Trigger<?>> getStates() {
|
||||
return triggers;
|
||||
}
|
||||
|
||||
public Set<ScenePriority> getScenes() {
|
||||
return scenes;
|
||||
}
|
||||
|
|
|
@ -53,7 +53,7 @@ public class ConfirmationToken {
|
|||
}
|
||||
|
||||
public Date getCreatedDate() {
|
||||
return createdDate;
|
||||
return (Date) createdDate.clone();
|
||||
}
|
||||
|
||||
public User getUser() {
|
||||
|
@ -69,7 +69,7 @@ public class ConfirmationToken {
|
|||
}
|
||||
|
||||
public void setCreatedDate(Date createdDate) {
|
||||
this.createdDate = createdDate;
|
||||
this.createdDate = (Date) createdDate.clone();
|
||||
}
|
||||
|
||||
public void setUser(User user) {
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
|
||||
|
||||
public interface Connectable<O extends OutputDevice> {
|
||||
void connect(O output, boolean connect);
|
||||
}
|
|
@ -1,47 +0,0 @@
|
|||
package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* A rule on how to connect an input device type to an output device type
|
||||
*
|
||||
* @param <I> the input device type
|
||||
* @param <O> the output device type
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface Connector<I extends InputDevice, O extends OutputDevice> {
|
||||
|
||||
/**
|
||||
* Connects or disconnects input to output
|
||||
*
|
||||
* @param input the input device
|
||||
* @param output the output device
|
||||
* @param connect true if connection, false if disconnection
|
||||
*/
|
||||
void connect(I input, O output, boolean connect);
|
||||
|
||||
/**
|
||||
* Produces a basic implementation of a connector, assuming there is a ManyToMany relationship
|
||||
* between J and K
|
||||
*
|
||||
* @param outputsGetter the getter method of the set of outputs on the input class
|
||||
* @param inputsGetter the getter method of the set of outputs on the input class
|
||||
* @param <J> the input device type
|
||||
* @param <K> the output device type
|
||||
* @return a Connector implementation for the pair of types J and K
|
||||
*/
|
||||
static <J extends InputDevice, K extends OutputDevice> Connector<J, K> basic(
|
||||
Function<J, Set<? super K>> outputsGetter, Function<K, Set<? super J>> inputsGetter) {
|
||||
return (i, o, connect) -> {
|
||||
if (connect) {
|
||||
outputsGetter.apply(i).add(o);
|
||||
inputsGetter.apply(o).add(i);
|
||||
} else {
|
||||
outputsGetter.apply(i).remove(o);
|
||||
inputsGetter.apply(o).remove(i);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
|
@ -3,8 +3,8 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
|
|||
import javax.persistence.Entity;
|
||||
|
||||
/**
|
||||
* Represents a curtain. The intensity represents how much the curtains are opened,
|
||||
* 0 is completely closed 100 is completely open
|
||||
* Represents a curtain. The intensity represents how much the curtains are opened, 0 is completely
|
||||
* closed 100 is completely open
|
||||
*/
|
||||
@Entity
|
||||
public class Curtains extends Dimmable {
|
||||
|
|
|
@ -4,7 +4,6 @@ import ch.usi.inf.sa4.sanmarinoes.smarthut.config.GsonExclude;
|
|||
import ch.usi.inf.sa4.sanmarinoes.smarthut.config.SocketGsonExclude;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import javax.persistence.*;
|
||||
|
||||
|
@ -38,7 +37,7 @@ public abstract class Device {
|
|||
@OneToMany(mappedBy = "device", orphanRemoval = true)
|
||||
@GsonExclude
|
||||
@SocketGsonExclude
|
||||
private Set<Trigger<? extends Device>> triggers = new HashSet<>();
|
||||
private Set<Trigger<? extends Device>> triggers;
|
||||
|
||||
/**
|
||||
* The room this device belongs in, as a foreign key id. To use when updating and inserting from
|
||||
|
@ -66,7 +65,7 @@ public abstract class Device {
|
|||
@OneToMany(mappedBy = "device", orphanRemoval = true)
|
||||
@GsonExclude
|
||||
@SocketGsonExclude
|
||||
private Set<State<?>> states = new HashSet<>();
|
||||
private Set<State<?>> states;
|
||||
|
||||
@Transient @GsonExclude private Long fromHostId = null;
|
||||
|
||||
|
@ -74,28 +73,9 @@ public abstract class Device {
|
|||
|
||||
@Transient @GsonExclude private boolean deleted = false;
|
||||
|
||||
public Long getFromHostId() {
|
||||
return fromHostId;
|
||||
}
|
||||
|
||||
public void setFromHostId(Long fromHostId) {
|
||||
this.fromHostId = fromHostId;
|
||||
}
|
||||
|
||||
public boolean isDeleted() {
|
||||
return deleted;
|
||||
}
|
||||
|
||||
public void setDeleted(boolean deleted) {
|
||||
this.deleted = deleted;
|
||||
}
|
||||
|
||||
public boolean isFromGuest() {
|
||||
return fromGuest;
|
||||
}
|
||||
|
||||
public void setFromGuest(boolean fromGuest) {
|
||||
this.fromGuest = fromGuest;
|
||||
public Device(String kind, FlowType flowType) {
|
||||
this.kind = kind;
|
||||
this.flowType = flowType;
|
||||
}
|
||||
|
||||
public long getId() {
|
||||
|
@ -106,12 +86,20 @@ public abstract class Device {
|
|||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
public Room getRoom() {
|
||||
return room;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
public void setRoom(Room room) {
|
||||
this.room = room;
|
||||
}
|
||||
|
||||
public Set<Trigger<? extends Device>> getTriggers() {
|
||||
return triggers;
|
||||
}
|
||||
|
||||
public void setTriggers(Set<Trigger<? extends Device>> triggers) {
|
||||
this.triggers = triggers;
|
||||
}
|
||||
|
||||
public Long getRoomId() {
|
||||
|
@ -122,8 +110,51 @@ public abstract class Device {
|
|||
this.roomId = roomId;
|
||||
}
|
||||
|
||||
public Device(String kind, FlowType flowType) {
|
||||
this.kind = kind;
|
||||
this.flowType = flowType;
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getKind() {
|
||||
return kind;
|
||||
}
|
||||
|
||||
public FlowType getFlowType() {
|
||||
return flowType;
|
||||
}
|
||||
|
||||
public Set<State<?>> getStates() {
|
||||
return states;
|
||||
}
|
||||
|
||||
public void setStates(Set<State<?>> states) {
|
||||
this.states = states;
|
||||
}
|
||||
|
||||
public Long getFromHostId() {
|
||||
return fromHostId;
|
||||
}
|
||||
|
||||
public void setFromHostId(Long fromHostId) {
|
||||
this.fromHostId = fromHostId;
|
||||
}
|
||||
|
||||
public boolean isFromGuest() {
|
||||
return fromGuest;
|
||||
}
|
||||
|
||||
public void setFromGuest(boolean fromGuest) {
|
||||
this.fromGuest = fromGuest;
|
||||
}
|
||||
|
||||
public boolean isDeleted() {
|
||||
return deleted;
|
||||
}
|
||||
|
||||
public void setDeleted(boolean deleted) {
|
||||
this.deleted = deleted;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,12 +12,6 @@ import javax.validation.constraints.NotNull;
|
|||
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
|
||||
public class Dimmable extends Switchable implements RangeTriggerable {
|
||||
|
||||
public static final Connector<KnobDimmer, Dimmable> KNOB_DIMMER_DIMMABLE_CONNECTOR =
|
||||
Connector.basic(KnobDimmer::getOutputs, Dimmable::getDimmers);
|
||||
|
||||
public static final Connector<ButtonDimmer, Dimmable> BUTTON_DIMMER_DIMMABLE_CONNECTOR =
|
||||
Connector.basic(ButtonDimmer::getOutputs, Dimmable::getDimmers);
|
||||
|
||||
protected Dimmable(String kind) {
|
||||
super(kind);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
|
||||
|
||||
public interface DimmableRepository<T extends Dimmable> extends SwitchableRepository<T> {
|
||||
}
|
||||
public interface DimmableRepository<T extends Dimmable> extends SwitchableRepository<T> {}
|
||||
|
|
|
@ -9,7 +9,7 @@ import javax.persistence.*;
|
|||
/** Represents a generic dimmer input device */
|
||||
@Entity
|
||||
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
|
||||
public abstract class Dimmer extends InputDevice {
|
||||
public abstract class Dimmer extends InputDevice implements Connectable<Dimmable> {
|
||||
public Dimmer(String kind) {
|
||||
super(kind);
|
||||
}
|
||||
|
@ -37,4 +37,14 @@ public abstract class Dimmer extends InputDevice {
|
|||
public void addDimmable(Dimmable dimmable) {
|
||||
dimmables.add(dimmable);
|
||||
}
|
||||
|
||||
public void connect(Dimmable output, boolean connect) {
|
||||
if (connect) {
|
||||
output.getDimmers().add(this);
|
||||
getOutputs().add(output);
|
||||
} else {
|
||||
output.getDimmers().remove(this);
|
||||
getOutputs().remove(output);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
|
|||
import com.google.gson.annotations.SerializedName;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@Entity
|
||||
public class RangeTrigger<D extends Device & RangeTriggerable> extends Trigger<D> {
|
||||
|
@ -46,7 +45,6 @@ public class RangeTrigger<D extends Device & RangeTriggerable> extends Trigger<D
|
|||
@Column(nullable = false)
|
||||
private Operator operator;
|
||||
|
||||
@NotNull
|
||||
@Column(nullable = false)
|
||||
private double range;
|
||||
|
||||
|
|
|
@ -99,4 +99,12 @@ public class Room {
|
|||
public String toString() {
|
||||
return "Room{" + "id=" + id + ", name='" + name + "\'}";
|
||||
}
|
||||
|
||||
public User getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
public void setUser(User user) {
|
||||
this.user = user;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,7 +28,6 @@ public class ScenePriority {
|
|||
private Automation automation;
|
||||
|
||||
@Column(name = "automation_id", nullable = false)
|
||||
@NotNull
|
||||
private Long automationId;
|
||||
|
||||
@NotNull
|
||||
|
@ -42,9 +41,12 @@ public class ScenePriority {
|
|||
private Scene scene;
|
||||
|
||||
@Column(name = "scene_id", nullable = false, updatable = false)
|
||||
@NotNull
|
||||
private Long sceneId;
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public Integer getPriority() {
|
||||
return priority;
|
||||
}
|
||||
|
@ -53,21 +55,16 @@ public class ScenePriority {
|
|||
this.priority = priority;
|
||||
}
|
||||
|
||||
public Automation getAutomation() {
|
||||
return automation;
|
||||
}
|
||||
|
||||
public void setAutomation(Automation automation) {
|
||||
this.automation = automation;
|
||||
}
|
||||
|
||||
public Long getAutomationId() {
|
||||
return automationId;
|
||||
}
|
||||
|
||||
public ScenePriority setAutomationId(Long automationId) {
|
||||
public void setAutomationId(Long automationId) {
|
||||
this.automationId = automationId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public void setAutomation(Automation automation) {
|
||||
this.automation = automation;
|
||||
}
|
||||
|
||||
public Scene getScene() {
|
||||
|
@ -88,10 +85,14 @@ public class ScenePriority {
|
|||
|
||||
@PreRemove
|
||||
public void preRemove() {
|
||||
this.setAutomation(null);
|
||||
this.setAutomationId(null);
|
||||
this.automation = null;
|
||||
this.automationId = null;
|
||||
|
||||
this.setScene(null);
|
||||
this.setSceneId(null);
|
||||
this.scene = null;
|
||||
this.sceneId = null;
|
||||
}
|
||||
|
||||
public Automation getAutomation() {
|
||||
return automation;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ import javax.persistence.*;
|
|||
|
||||
/** A switch input device */
|
||||
@Entity
|
||||
public class Switch extends InputDevice implements BooleanTriggerable {
|
||||
public class Switch extends InputDevice implements BooleanTriggerable, Connectable<Switchable> {
|
||||
|
||||
@ManyToMany(
|
||||
cascade = {
|
||||
|
@ -60,10 +60,21 @@ public class Switch extends InputDevice implements BooleanTriggerable {
|
|||
return on;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Switchable> getOutputs() {
|
||||
return switchables;
|
||||
}
|
||||
|
||||
public void connect(Switchable output, boolean connect) {
|
||||
if (connect) {
|
||||
output.getSwitches().add(this);
|
||||
getOutputs().add(output);
|
||||
} else {
|
||||
output.getSwitches().remove(this);
|
||||
getOutputs().remove(output);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean readTriggerState() {
|
||||
return on;
|
||||
|
|
|
@ -11,9 +11,6 @@ import javax.persistence.*;
|
|||
@Inheritance(strategy = InheritanceType.JOINED)
|
||||
public abstract class Switchable extends OutputDevice {
|
||||
|
||||
public static final Connector<Switch, Switchable> SWITCH_SWITCHABLE_CONNECTOR =
|
||||
Connector.basic(Switch::getOutputs, Switchable::getSwitches);
|
||||
|
||||
@ManyToMany(
|
||||
mappedBy = "switchables",
|
||||
cascade = {
|
||||
|
|
|
@ -24,7 +24,6 @@ public interface ThermostatRepository extends DeviceRepository<Thermostat> {
|
|||
* @param thermostatRoomId room ID of the thermostat
|
||||
* @return an optional big decimal, empty if none found
|
||||
*/
|
||||
@Query(
|
||||
"SELECT AVG(s.value) FROM Sensor s JOIN s.room r WHERE s.sensor = ?2 AND r.id = ?1")
|
||||
@Query("SELECT AVG(s.value) FROM Sensor s JOIN s.room r WHERE s.sensor = ?2 AND r.id = ?1")
|
||||
Optional<BigDecimal> getAverageTemperature(Long thermostatRoomId, Sensor.SensorType sensorType);
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
|
|||
import ch.usi.inf.sa4.sanmarinoes.smarthut.config.GsonExclude;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import javax.persistence.*;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@Entity
|
||||
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
|
||||
|
@ -45,7 +44,6 @@ public abstract class Trigger<D extends Device> {
|
|||
private Automation automation;
|
||||
|
||||
@Column(name = "automation_id", nullable = false)
|
||||
@NotNull
|
||||
private Long automationId;
|
||||
|
||||
public long getId() {
|
||||
|
|
|
@ -8,7 +8,7 @@ import org.springframework.stereotype.Component;
|
|||
@Component
|
||||
public class DevicePopulationService {
|
||||
|
||||
@Autowired private ThermostatService thermostatService;
|
||||
@Autowired private ThermostatPopulationService thermostatService;
|
||||
|
||||
public void populateComputedFields(Iterable<Device> devices) {
|
||||
for (Device d : devices) {
|
||||
|
|
|
@ -13,9 +13,19 @@ import org.springframework.stereotype.Component;
|
|||
@Component
|
||||
public class DevicePropagationService {
|
||||
|
||||
@Autowired private SensorSocketEndpoint endpoint;
|
||||
@Autowired private EagerUserRepository userRepository;
|
||||
@Autowired private DeviceRepository<Device> deviceRepository;
|
||||
private final SensorSocketEndpoint endpoint;
|
||||
private final EagerUserRepository userRepository;
|
||||
private final DeviceRepository<Device> deviceRepository;
|
||||
|
||||
@Autowired
|
||||
public DevicePropagationService(
|
||||
SensorSocketEndpoint endpoint,
|
||||
EagerUserRepository userRepository,
|
||||
DeviceRepository<Device> deviceRepository) {
|
||||
this.endpoint = endpoint;
|
||||
this.userRepository = userRepository;
|
||||
this.deviceRepository = deviceRepository;
|
||||
}
|
||||
|
||||
void propagateUpdateAsGuest(Device device, User host, User guest) {
|
||||
final Set<User> guests = Set.copyOf(host.getGuests());
|
||||
|
|
|
@ -75,7 +75,7 @@ public class DeviceService {
|
|||
sceneRepository
|
||||
.findById(t.getSceneId())
|
||||
.orElseThrow(IllegalStateException::new))
|
||||
.forEach((s) -> sceneService.apply(s, username, true));
|
||||
.forEach(s -> sceneService.apply(s, username, true));
|
||||
}
|
||||
|
||||
public List<Device> findAll(Long hostId, String username) throws NotFoundException {
|
||||
|
@ -123,7 +123,7 @@ public class DeviceService {
|
|||
List<T> toReturn =
|
||||
devicePropagationService.saveAllAsOwner(devices, username, fromScene, fromTrigger);
|
||||
if (!fromScene) {
|
||||
toReturn.forEach((d) -> this.triggerTriggers(d, username));
|
||||
toReturn.forEach(d -> this.triggerTriggers(d, username));
|
||||
}
|
||||
return toReturn;
|
||||
}
|
||||
|
@ -170,6 +170,10 @@ public class DeviceService {
|
|||
|
||||
devicePopulationService.populateComputedFields(devices);
|
||||
|
||||
return filterOutCamerasIfNeeded(host, devices);
|
||||
}
|
||||
|
||||
private List<Device> filterOutCamerasIfNeeded(User host, Iterable<Device> devices) {
|
||||
if (host != null && !host.isCameraEnabled()) {
|
||||
return StreamSupport.stream(devices.spliterator(), true)
|
||||
.filter(d -> !(d instanceof SecurityCamera))
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
package ch.usi.inf.sa4.sanmarinoes.smarthut.service;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.User;
|
||||
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.UserRepository;
|
||||
import java.util.Set;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.core.*;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
|
@ -16,7 +15,7 @@ public class JWTUserDetailsService implements UserDetailsService {
|
|||
@Autowired private UserRepository repository;
|
||||
|
||||
@Override
|
||||
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
|
||||
public UserDetails loadUserByUsername(String username) {
|
||||
User toReturn = repository.findByUsername(username);
|
||||
if (toReturn != null && toReturn.getEnabled()) {
|
||||
return new org.springframework.security.core.userdetails.User(
|
||||
|
|
|
@ -3,16 +3,23 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut.service;
|
|||
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class SceneService {
|
||||
|
||||
@Autowired private DeviceRepository<Device> deviceRepository;
|
||||
@Autowired private DevicePopulationService devicePopulationService;
|
||||
@Autowired private DevicePropagationService devicePropagationService;
|
||||
@Autowired private StateRepository<State<?>> stateRepository;
|
||||
private final DevicePopulationService devicePopulationService;
|
||||
private final DevicePropagationService devicePropagationService;
|
||||
private final StateRepository<State<?>> stateRepository;
|
||||
|
||||
public SceneService(
|
||||
DevicePopulationService devicePopulationService,
|
||||
DevicePropagationService devicePropagationService,
|
||||
StateRepository<State<?>> stateRepository) {
|
||||
this.devicePopulationService = devicePopulationService;
|
||||
this.devicePropagationService = devicePropagationService;
|
||||
this.stateRepository = stateRepository;
|
||||
}
|
||||
|
||||
private List<Device> copyStatesToDevices(Scene fromScene) {
|
||||
final List<Device> updated = new ArrayList<>(fromScene.getStates().size());
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
package ch.usi.inf.sa4.sanmarinoes.smarthut.service;
|
||||
|
||||
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.Sensor;
|
||||
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.Thermostat;
|
||||
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.ThermostatRepository;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Optional;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class ThermostatPopulationService {
|
||||
|
||||
@Autowired private ThermostatRepository thermostatRepository;
|
||||
|
||||
private BigDecimal measureTemperature(final Thermostat thermostat) {
|
||||
Optional<BigDecimal> average;
|
||||
|
||||
if (thermostat.isUseExternalSensors()) {
|
||||
average =
|
||||
thermostatRepository.getAverageTemperature(
|
||||
thermostat.getRoomId(), Sensor.SensorType.TEMPERATURE);
|
||||
|
||||
} else {
|
||||
return thermostat.getInternalSensorTemperature();
|
||||
}
|
||||
|
||||
return average.orElse(null);
|
||||
}
|
||||
|
||||
public void populateMeasuredTemperature(Thermostat thermostat) {
|
||||
thermostat.setMeasuredTemperature(measureTemperature(thermostat));
|
||||
}
|
||||
}
|
|
@ -16,7 +16,9 @@ public class ThermostatService {
|
|||
|
||||
@Autowired private SensorSocketEndpoint endpoint;
|
||||
|
||||
@Autowired private DevicePropagationService deviceService;
|
||||
@Autowired private DeviceService deviceService;
|
||||
|
||||
@Autowired private ThermostatPopulationService thermostatPopulationService;
|
||||
|
||||
@Autowired private ThermostatRepository thermostatRepository;
|
||||
|
||||
|
@ -41,12 +43,12 @@ public class ThermostatService {
|
|||
|
||||
public List<Thermostat> findAll(String username) {
|
||||
Iterable<Thermostat> all = thermostatRepository.findAllByUsername(username);
|
||||
all.forEach(this::populateMeasuredTemperature);
|
||||
all.forEach(thermostatPopulationService::populateMeasuredTemperature);
|
||||
return Utils.toList(all);
|
||||
}
|
||||
|
||||
public void computeState(Thermostat t) {
|
||||
populateMeasuredTemperature(t);
|
||||
thermostatPopulationService.populateMeasuredTemperature(t);
|
||||
t.computeState();
|
||||
}
|
||||
|
||||
|
@ -67,26 +69,9 @@ public class ThermostatService {
|
|||
|
||||
if (t.isPresent()) {
|
||||
Thermostat u = t.get();
|
||||
populateMeasuredTemperature(u);
|
||||
thermostatPopulationService.populateMeasuredTemperature(u);
|
||||
t = Optional.of(u);
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
private BigDecimal measureTemperature(final Thermostat thermostat) {
|
||||
Optional<BigDecimal> average;
|
||||
|
||||
if (thermostat.isUseExternalSensors()) {
|
||||
average = thermostatRepository.getAverageTemperature(thermostat.getRoomId(), Sensor.SensorType.TEMPERATURE);
|
||||
|
||||
} else {
|
||||
return thermostat.getInternalSensorTemperature();
|
||||
}
|
||||
|
||||
return average.orElse(null);
|
||||
}
|
||||
|
||||
public void populateMeasuredTemperature(Thermostat thermostat) {
|
||||
thermostat.setMeasuredTemperature(measureTemperature(thermostat));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,8 +42,8 @@ public class SensorSocketConfig extends ServerEndpointConfig.Configurator {
|
|||
public <T> T getEndpointInstance(Class<T> endpointClass) throws InstantiationException {
|
||||
try {
|
||||
@SuppressWarnings("unchecked")
|
||||
final T instance = (T) this.instance;
|
||||
return instance;
|
||||
final T thaInstance = (T) this.instance;
|
||||
return thaInstance;
|
||||
} catch (ClassCastException e) {
|
||||
final var e2 =
|
||||
new InstantiationException("Cannot cast SensorSocketEndpoint to desired type");
|
||||
|
|
|
@ -13,6 +13,8 @@ import com.google.gson.Gson;
|
|||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import javax.websocket.*;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
|
@ -20,6 +22,8 @@ import org.springframework.stereotype.Component;
|
|||
@Component
|
||||
public class SensorSocketEndpoint extends Endpoint {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(SensorSocketEndpoint.class);
|
||||
|
||||
private final Gson gson = GsonConfig.socketGson();
|
||||
|
||||
@Autowired private DevicePopulationService deviceService;
|
||||
|
@ -98,7 +102,7 @@ public class SensorSocketEndpoint extends Endpoint {
|
|||
authorizedClients.remove(u, s);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
logger.warn(e.getLocalizedMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -118,7 +122,8 @@ public class SensorSocketEndpoint extends Endpoint {
|
|||
} else {
|
||||
try {
|
||||
session.close();
|
||||
} catch (IOException ignored) {
|
||||
} catch (IOException e) {
|
||||
logger.warn(e.getLocalizedMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -128,8 +133,8 @@ public class SensorSocketEndpoint extends Endpoint {
|
|||
|
||||
try {
|
||||
username = jwtTokenUtils.getUsernameFromToken(protocolString);
|
||||
} catch (Throwable ignored) {
|
||||
System.out.println("Token format not valid");
|
||||
} catch (Exception ignored) {
|
||||
logger.info("Token format not valid");
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,6 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||
import ch.usi.inf.sa4.sanmarinoes.smarthut.dto.JWTRequest;
|
||||
import ch.usi.inf.sa4.sanmarinoes.smarthut.dto.JWTResponse;
|
||||
import ch.usi.inf.sa4.sanmarinoes.smarthut.dto.UserRegistrationRequest;
|
||||
import ch.usi.inf.sa4.sanmarinoes.smarthut.error.DuplicateRegistrationException;
|
||||
import ch.usi.inf.sa4.sanmarinoes.smarthut.error.UnauthorizedException;
|
||||
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.ConfirmationTokenRepository;
|
||||
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.UserRepository;
|
||||
|
@ -44,7 +43,7 @@ public class AuthenticationTests extends SmartHutTest {
|
|||
final ResponseEntity<Object> res =
|
||||
this.restTemplate.postForEntity(
|
||||
this.url("/register"), getDisabledUser(), Object.class);
|
||||
assertThat(res.getStatusCode().equals(HttpStatus.OK));
|
||||
assertThat(res.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
|
||||
registerTestUser(restTemplate, userRepository, tokenRepository);
|
||||
}
|
||||
|
@ -54,10 +53,11 @@ public class AuthenticationTests extends SmartHutTest {
|
|||
final Map<String, Object> badJSON = Map.of("luciano", "goretti", "danilo", "malusa");
|
||||
|
||||
assertThat(
|
||||
this.restTemplate
|
||||
.postForEntity(url("/register"), badJSON, JWTResponse.class)
|
||||
.getStatusCode()
|
||||
.equals(HttpStatus.BAD_REQUEST));
|
||||
this.restTemplate
|
||||
.postForEntity(url("/register"), badJSON, JWTResponse.class)
|
||||
.getStatusCode()
|
||||
.equals(HttpStatus.BAD_REQUEST))
|
||||
.isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -70,12 +70,15 @@ public class AuthenticationTests extends SmartHutTest {
|
|||
|
||||
final ResponseEntity<JsonObject> res =
|
||||
this.restTemplate.postForEntity(url("/register"), request, JsonObject.class);
|
||||
assertThat(res.getStatusCode().equals(HttpStatus.BAD_REQUEST));
|
||||
assertThat(res.getBody() != null);
|
||||
assertThat(res.getStatusCode().equals(HttpStatus.BAD_REQUEST)).isTrue();
|
||||
assertThat(res.getBody()).isNotNull();
|
||||
|
||||
final JsonArray errors = res.getBody().getAsJsonArray("errors");
|
||||
assertThat(errors.size() == 1);
|
||||
assertThat(errors.get(0).getAsJsonObject().get("field").getAsString().equals("password"));
|
||||
assertThat(errors)
|
||||
.allSatisfy(
|
||||
e ->
|
||||
assertThat(e.getAsJsonObject().get("field").getAsString())
|
||||
.isEqualTo("password"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -88,12 +91,15 @@ public class AuthenticationTests extends SmartHutTest {
|
|||
|
||||
final ResponseEntity<JsonObject> res =
|
||||
this.restTemplate.postForEntity(url("/register"), request, JsonObject.class);
|
||||
assertThat(res.getStatusCode().equals(HttpStatus.BAD_REQUEST));
|
||||
assertThat(res.getBody() != null);
|
||||
assertThat(res.getStatusCode().equals(HttpStatus.BAD_REQUEST)).isTrue();
|
||||
assertThat(res.getBody()).isNotNull();
|
||||
|
||||
final JsonArray errors = res.getBody().getAsJsonArray("errors");
|
||||
assertThat(errors.size() == 1);
|
||||
assertThat(errors.get(0).getAsJsonObject().get("field").getAsString().equals("email"));
|
||||
assertThat(errors)
|
||||
.allSatisfy(
|
||||
e ->
|
||||
assertThat(e.getAsJsonObject().get("field").getAsString())
|
||||
.isEqualTo("email"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -105,12 +111,15 @@ public class AuthenticationTests extends SmartHutTest {
|
|||
|
||||
final ResponseEntity<JsonObject> res =
|
||||
this.restTemplate.postForEntity(url("/register"), request, JsonObject.class);
|
||||
assertThat(res.getStatusCode().equals(HttpStatus.BAD_REQUEST));
|
||||
assertThat(res.getBody() != null);
|
||||
assertThat(res.getStatusCode().equals(HttpStatus.BAD_REQUEST)).isTrue();
|
||||
assertThat(res.getBody() != null).isTrue();
|
||||
|
||||
final JsonArray errors = res.getBody().getAsJsonArray("errors");
|
||||
assertThat(errors.size() == 1);
|
||||
assertThat(errors.get(0).getAsJsonObject().get("field").getAsString().equals("name"));
|
||||
assertThat(errors)
|
||||
.allSatisfy(
|
||||
e ->
|
||||
assertThat(e.getAsJsonObject().get("field").getAsString())
|
||||
.isEqualTo("name"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -122,51 +131,15 @@ public class AuthenticationTests extends SmartHutTest {
|
|||
|
||||
final ResponseEntity<JsonObject> res =
|
||||
this.restTemplate.postForEntity(url("/register"), request, JsonObject.class);
|
||||
assertThat(res.getStatusCode().equals(HttpStatus.BAD_REQUEST));
|
||||
assertThat(res.getBody() != null);
|
||||
assertThat(res.getStatusCode().equals(HttpStatus.BAD_REQUEST)).isTrue();
|
||||
assertThat(res.getBody() != null).isTrue();
|
||||
|
||||
final JsonArray errors = res.getBody().getAsJsonArray("errors");
|
||||
assertThat(errors.size() == 1);
|
||||
assertThat(errors.get(0).getAsJsonObject().get("field").getAsString().equals("username"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void registrationShouldReturnBadRequestWithDuplicateData() {
|
||||
{
|
||||
final ResponseEntity<DuplicateRegistrationException> res =
|
||||
this.restTemplate.postForEntity(
|
||||
url("/register"),
|
||||
getDisabledUser(),
|
||||
DuplicateRegistrationException.class);
|
||||
assertThat(res.getStatusCode().equals(HttpStatus.BAD_REQUEST));
|
||||
assertThat(res.getBody() != null);
|
||||
}
|
||||
|
||||
{
|
||||
final UserRegistrationRequest disabledUserDifferentMail = getDisabledUser();
|
||||
enabledUser.setEmail("another@example.com");
|
||||
|
||||
final ResponseEntity<DuplicateRegistrationException> res =
|
||||
this.restTemplate.postForEntity(
|
||||
url("/register"),
|
||||
disabledUserDifferentMail,
|
||||
DuplicateRegistrationException.class);
|
||||
assertThat(res.getStatusCode().equals(HttpStatus.BAD_REQUEST));
|
||||
assertThat(res.getBody() != null);
|
||||
}
|
||||
|
||||
{
|
||||
final UserRegistrationRequest disabledUserDifferentUsername = getDisabledUser();
|
||||
enabledUser.setUsername("another");
|
||||
|
||||
final ResponseEntity<DuplicateRegistrationException> res =
|
||||
this.restTemplate.postForEntity(
|
||||
url("/register"),
|
||||
disabledUserDifferentUsername,
|
||||
DuplicateRegistrationException.class);
|
||||
assertThat(res.getStatusCode().equals(HttpStatus.BAD_REQUEST));
|
||||
assertThat(res.getBody() != null);
|
||||
}
|
||||
assertThat(errors)
|
||||
.allSatisfy(
|
||||
j ->
|
||||
assertThat(j.getAsJsonObject().get("field").getAsString())
|
||||
.isEqualTo("username"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -179,8 +152,7 @@ public class AuthenticationTests extends SmartHutTest {
|
|||
|
||||
final ResponseEntity<Object> res =
|
||||
this.restTemplate.postForEntity(url("/register"), request, Object.class);
|
||||
assertThat(res.getStatusCode().equals(HttpStatus.OK));
|
||||
assertThat(res.getBody() != null);
|
||||
assertThat(res.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -188,10 +160,11 @@ public class AuthenticationTests extends SmartHutTest {
|
|||
final Map<String, Object> badJSON = Map.of("badkey", 3, "password", "ciaomamma");
|
||||
|
||||
assertThat(
|
||||
this.restTemplate
|
||||
.postForEntity(url("/auth/login"), badJSON, JWTResponse.class)
|
||||
.getStatusCode()
|
||||
.equals(HttpStatus.BAD_REQUEST));
|
||||
this.restTemplate
|
||||
.postForEntity(url("/auth/login"), badJSON, JWTResponse.class)
|
||||
.getStatusCode()
|
||||
.equals(HttpStatus.BAD_REQUEST))
|
||||
.isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -203,9 +176,9 @@ public class AuthenticationTests extends SmartHutTest {
|
|||
final ResponseEntity<UnauthorizedException> res =
|
||||
this.restTemplate.postForEntity(
|
||||
url("/auth/login"), request, UnauthorizedException.class);
|
||||
assertThat(res.getStatusCode().equals(HttpStatus.UNAUTHORIZED));
|
||||
assertThat(res.getBody() != null);
|
||||
assertThat(!res.getBody().isUserDisabled());
|
||||
assertThat(res.getStatusCode().equals(HttpStatus.UNAUTHORIZED)).isTrue();
|
||||
assertThat(res.getBody() != null).isTrue();
|
||||
assertThat(!res.getBody().isUserDisabled()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -217,22 +190,7 @@ public class AuthenticationTests extends SmartHutTest {
|
|||
final ResponseEntity<UnauthorizedException> res =
|
||||
this.restTemplate.postForEntity(
|
||||
url("/auth/login"), request, UnauthorizedException.class);
|
||||
assertThat(res.getStatusCode().equals(HttpStatus.UNAUTHORIZED));
|
||||
assertThat(res.getBody() != null);
|
||||
assertThat(res.getBody().isUserDisabled());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loginShouldReturnTokenWithEnabledUser() {
|
||||
final JWTRequest request = new JWTRequest();
|
||||
request.setUsernameOrEmail("enabled");
|
||||
request.setPassword("password");
|
||||
|
||||
final ResponseEntity<JWTResponse> res =
|
||||
this.restTemplate.postForEntity(url("/auth/login"), request, JWTResponse.class);
|
||||
assertThat(res.getStatusCode().equals(HttpStatus.OK));
|
||||
assertThat(res.getBody() != null);
|
||||
assertThat(res.getBody().getToken() != null);
|
||||
assertThat(!res.getBody().getToken().isEmpty());
|
||||
assertThat(res.getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED);
|
||||
assertThat(res.getBody()).isNotNull();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ import org.springframework.http.ResponseEntity;
|
|||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
|
||||
public abstract class SmartHutTest {
|
||||
private boolean setupDone = false;
|
||||
private static boolean setupDone = false;
|
||||
|
||||
protected final String getBaseURL() {
|
||||
return "http://localhost:2000/";
|
||||
|
@ -41,7 +41,7 @@ public abstract class SmartHutTest {
|
|||
final ConfirmationTokenRepository tokenRepository) {
|
||||
final ResponseEntity<Object> res2 =
|
||||
restTemplate.postForEntity(this.url("/register"), enabledUser, Object.class);
|
||||
assertThat(res2.getStatusCode().equals(HttpStatus.OK));
|
||||
assertThat(res2.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
|
||||
final User persistedEnabledUser = userRepository.findByUsername("enabled");
|
||||
final ConfirmationToken token = tokenRepository.findByUser(persistedEnabledUser);
|
||||
|
@ -54,8 +54,9 @@ public abstract class SmartHutTest {
|
|||
.toBodilessEntity()
|
||||
.block();
|
||||
|
||||
assertThat(res3.getStatusCode().is2xxSuccessful());
|
||||
assertThat(userRepository.findByUsername("enabled").getEnabled());
|
||||
assertThat(res3).isNotNull();
|
||||
assertThat(res3.getStatusCode()).isEqualTo(HttpStatus.FOUND);
|
||||
assertThat(userRepository.findByUsername("enabled").getEnabled()).isTrue();
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
|
|
|
@ -16,11 +16,8 @@ public class SmarthutApplicationTests extends SmartHutTest {
|
|||
@Autowired private TestRestTemplate restTemplate;
|
||||
|
||||
@Test
|
||||
public void anonymousGreetingShouldNotBeAuthorized() throws Exception {
|
||||
assertThat(
|
||||
this.restTemplate
|
||||
.getForEntity(getBaseURL(), Void.class)
|
||||
.getStatusCode()
|
||||
.equals(HttpStatus.UNAUTHORIZED));
|
||||
public void anonymousGreetingShouldNotBeAuthorized() {
|
||||
assertThat(this.restTemplate.getForEntity(getBaseURL(), Void.class).getStatusCode())
|
||||
.isEqualTo(HttpStatus.UNAUTHORIZED);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue