Reviewed GET /scene?hostId= and GET /scene/{sceneId}/apply?hostId=

This commit is contained in:
Claudio Maggioni (maggicl) 2020-05-04 17:11:59 +02:00
parent c24598cc6a
commit a278a9f7b3
4 changed files with 72 additions and 37 deletions

View file

@ -6,20 +6,13 @@ import ch.usi.inf.sa4.sanmarinoes.smarthut.dto.SceneSaveRequest;
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.SceneService;
import ch.usi.inf.sa4.sanmarinoes.smarthut.utils.Utils;
import java.security.Principal;
import java.util.List;
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
@RestController
@EnableAutoConfiguration
@ -27,21 +20,20 @@ import org.springframework.web.bind.annotation.RestController;
public class SceneController {
@Autowired private SceneRepository sceneRepository;
@Autowired private UserRepository userRepository;
@Autowired private SceneService sceneService;
@Autowired private UserRepository userService;
@Autowired private StateRepository<State<?>> stateService;
@Autowired private StateRepository<State<?>> stateRepository;
@GetMapping
public List<Scene> findAll(Principal principal) {
return toList(sceneRepository.findByUsername(principal.getName()));
}
@GetMapping("/{id}")
public @ResponseBody Scene findById(@PathVariable("id") long id, Principal principal)
public List<Scene> findAll(
Principal principal, @RequestParam(value = "hostId", required = false) Long hostId)
throws NotFoundException {
return sceneRepository
.findByIdAndUsername(id, principal.getName())
.orElseThrow(NotFoundException::new);
if (hostId == null) {
return toList(sceneRepository.findByUsername(principal.getName()));
} else {
Utils.returnIfGuest(userRepository, null, hostId, principal);
return sceneRepository.findByHostId(hostId);
}
}
@PostMapping
@ -49,7 +41,7 @@ public class SceneController {
@Valid @RequestBody SceneSaveRequest s, final Principal principal) {
final String username = principal.getName();
final Long userId = userService.findByUsername(username).getId();
final Long userId = userRepository.findByUsername(username).getId();
final Scene newScene = new Scene();
@ -62,14 +54,27 @@ public class SceneController {
}
@PostMapping("/{id}/apply")
public @ResponseBody List<Device> apply(@PathVariable("id") long id, final Principal principal)
public @ResponseBody List<Device> apply(
@PathVariable("id") long id,
final Principal principal,
@RequestParam(value = "hostId", required = false) Long hostId)
throws NotFoundException {
final Scene newScene =
if (hostId == null) {
return sceneService.apply(
sceneRepository
.findByIdAndUsername(id, principal.getName())
.orElseThrow(NotFoundException::new);
return sceneService.apply(newScene, principal.getName(), false);
.orElseThrow(NotFoundException::new),
principal.getName(),
false);
} else {
Utils.returnIfGuest(userRepository, null, hostId, principal);
return sceneService.applyAsGuest(
sceneRepository
.findByIdAndUserId(id, hostId)
.orElseThrow(NotFoundException::new),
principal.getName(),
hostId);
}
}
@PostMapping("/{id}/copyFrom/{copyId}")
@ -112,7 +117,7 @@ public class SceneController {
@DeleteMapping("/{id}")
public void deleteById(@PathVariable("id") long id) {
stateService.deleteAllBySceneId(id);
stateRepository.deleteAllBySceneId(id);
sceneRepository.deleteById(id);
}
@ -122,7 +127,7 @@ public class SceneController {
*/
@GetMapping(path = "/{sceneId}/states")
public List<State<?>> getDevices(@PathVariable("sceneId") long sceneId) {
Iterable<State<?>> states = stateService.findBySceneId(sceneId);
Iterable<State<?>> states = stateRepository.findBySceneId(sceneId);
return toList(states);
}
}

View file

@ -19,4 +19,9 @@ public interface SceneRepository extends CrudRepository<Scene, Long> {
@Query("SELECT s FROM Scene s JOIN s.user u WHERE u.username = ?1")
List<Scene> findByUsername(String username);
@Query("SELECT s FROM Scene s JOIN s.user u WHERE u.id = ?1 AND s.guestAccessEnabled = true")
List<Scene> findByHostId(Long hostId);
Optional<Scene> findByIdAndUserId(Long id, Long userId);
}

View file

@ -128,7 +128,13 @@ public class DeviceService {
final User host = userRepository.findById(hostId).orElseThrow(NotFoundException::new);
if (!host.getGuests().contains(currentUser)) throw new NotFoundException();
renameIfDuplicate(device, host.getUsername());
device = deviceRepository.save(device);
propagateUpdateAsGuest(device, host, currentUser);
return device;
}
private void propagateUpdateAsGuest(Device device, User host, User guest) {
final Set<User> guests = Set.copyOf(host.getGuests());
// We're telling the host that a guest has modified a device. Therefore, fromGuest becomes
@ -138,15 +144,22 @@ public class DeviceService {
// We're telling all guests that a higher entity has issued a device update. Therefore,
// fromHost becomes true.
for (final User guest : guests) {
if (guest.equals(currentUser)) {
for (final User aGuest : guests) {
if (aGuest.equals(guest)) {
continue;
}
// enqueue all device updates for all other guests
endpoint.queueDeviceUpdate(device, guest, false, host.getId(), false);
endpoint.queueDeviceUpdate(device, aGuest, false, host.getId(), false);
}
}
return device;
List<Device> saveAllAsGuestSceneApplication(
List<Device> devices, String guestUsername, Long hostId) {
final User guest = userRepository.findByUsername(guestUsername);
final User host = userRepository.findById(hostId).orElseThrow(IllegalStateException::new);
deviceRepository.saveAll(devices);
devices.forEach(d -> this.propagateUpdateAsGuest(d, host, guest));
return devices;
}
/**

View file

@ -13,18 +13,30 @@ public class SceneService {
@Autowired private DeviceService deviceService;
@Autowired private StateRepository<State<?>> stateRepository;
public List<Device> apply(Scene newScene, String username, boolean fromTrigger) {
private List<Device> copyStatesToDevices(Scene fromScene) {
final List<Device> updated = new ArrayList<>();
for (final State<?> s : newScene.getStates()) {
for (final State<?> s : fromScene.getStates()) {
s.apply();
updated.add(s.getDevice());
}
deviceService.saveAllAsOwner(updated, username, true, fromTrigger);
deviceService.populateComputedFields(updated);
return updated;
}
public List<Device> apply(Scene newScene, String username, boolean fromTrigger) {
List<Device> updated = copyStatesToDevices(newScene);
deviceService.saveAllAsOwner(updated, username, true, fromTrigger);
return updated;
}
public List<Device> applyAsGuest(Scene newScene, String username, Long hostId) {
List<Device> updated = copyStatesToDevices(newScene);
deviceService.saveAllAsGuestSceneApplication(updated, username, hostId);
return updated;
}
public List<State<?>> copyStates(Scene to, Scene from) {
final ArrayList<State<?>> states = new ArrayList<>();
for (final State<?> s : from.getStates()) {