diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/SceneController.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/SceneController.java index a11b40e..2eeaaef 100644 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/SceneController.java +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/SceneController.java @@ -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> stateService; + @Autowired private StateRepository> stateRepository; @GetMapping - public List findAll(Principal principal) { - return toList(sceneRepository.findByUsername(principal.getName())); - } - - @GetMapping("/{id}") - public @ResponseBody Scene findById(@PathVariable("id") long id, Principal principal) + public List 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 apply(@PathVariable("id") long id, final Principal principal) + public @ResponseBody List apply( + @PathVariable("id") long id, + final Principal principal, + @RequestParam(value = "hostId", required = false) Long hostId) throws NotFoundException { - final Scene newScene = - sceneRepository - .findByIdAndUsername(id, principal.getName()) - .orElseThrow(NotFoundException::new); - - return sceneService.apply(newScene, principal.getName(), false); + if (hostId == null) { + return sceneService.apply( + sceneRepository + .findByIdAndUsername(id, principal.getName()) + .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> getDevices(@PathVariable("sceneId") long sceneId) { - Iterable> states = stateService.findBySceneId(sceneId); + Iterable> states = stateRepository.findBySceneId(sceneId); return toList(states); } } diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/SceneRepository.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/SceneRepository.java index a4aa68c..028f292 100644 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/SceneRepository.java +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/SceneRepository.java @@ -19,4 +19,9 @@ public interface SceneRepository extends CrudRepository { @Query("SELECT s FROM Scene s JOIN s.user u WHERE u.username = ?1") List findByUsername(String username); + + @Query("SELECT s FROM Scene s JOIN s.user u WHERE u.id = ?1 AND s.guestAccessEnabled = true") + List findByHostId(Long hostId); + + Optional findByIdAndUserId(Long id, Long userId); } diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/service/DeviceService.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/service/DeviceService.java index 789b53a..d2b02a6 100644 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/service/DeviceService.java +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/service/DeviceService.java @@ -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 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 saveAllAsGuestSceneApplication( + List 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; } /** diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/service/SceneService.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/service/SceneService.java index 72abf08..3c91277 100644 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/service/SceneService.java +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/service/SceneService.java @@ -13,18 +13,30 @@ public class SceneService { @Autowired private DeviceService deviceService; @Autowired private StateRepository> stateRepository; - public List apply(Scene newScene, String username, boolean fromTrigger) { + private List copyStatesToDevices(Scene fromScene) { final List 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 apply(Scene newScene, String username, boolean fromTrigger) { + List updated = copyStatesToDevices(newScene); + deviceService.saveAllAsOwner(updated, username, true, fromTrigger); + return updated; + } + + public List applyAsGuest(Scene newScene, String username, Long hostId) { + List updated = copyStatesToDevices(newScene); + deviceService.saveAllAsGuestSceneApplication(updated, username, hostId); + return updated; + } + public List> copyStates(Scene to, Scene from) { final ArrayList> states = new ArrayList<>(); for (final State s : from.getStates()) {