Merge branch 'dev' into 'device-unification'

# Conflicts:
#   src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/config/SpringFoxConfig.java
#   src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/ButtonDimmerController.java
#   src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/DimmableLightController.java
#   src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/KnobDimmerController.java
#   src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/MotionSensorController.java
#   src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/RegularLightController.java
#   src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/SensorController.java
#   src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/SmartPlugController.java
#   src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/SwitchController.java
#   src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/User.java
This commit is contained in:
Claudio Maggioni 2020-03-02 21:48:02 +01:00
commit 5ae97da8a7
36 changed files with 1133 additions and 83 deletions

View File

@ -18,6 +18,7 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter' implementation 'org.springframework.boot:spring-boot-starter'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-security' implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-mail'
implementation 'io.jsonwebtoken:jjwt:0.9.1' implementation 'io.jsonwebtoken:jjwt:0.9.1'
implementation 'org.springframework.security:spring-security-web' implementation 'org.springframework.security:spring-security-web'
implementation 'org.postgresql:postgresql' implementation 'org.postgresql:postgresql'

View File

@ -0,0 +1,23 @@
package ch.usi.inf.sa4.sanmarinoes.smarthut.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
@Service("emailSenderService")
public class EmailSenderService {
private JavaMailSender javaMailSender;
@Autowired
public EmailSenderService(JavaMailSender javaMailSender) {
this.javaMailSender = javaMailSender;
}
@Async
public void sendEmail(SimpleMailMessage email) {
javaMailSender.send(email);
}
}

View File

@ -67,7 +67,9 @@ public class SpringFoxConfig {
* @return A predicate that tests whether a path must be included or not * @return A predicate that tests whether a path must be included or not
*/ */
private Predicate<String> paths() { private Predicate<String> paths() {
return regexPredicate("/auth.*").or(regexPredicate("/room.*")); return regexPredicate("/auth.*")
.or(regexPredicate("/room.*"))
.or(regexPredicate("/register.*"));
} }
/** /**

View File

@ -54,6 +54,8 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
"/auth/login", "/auth/login",
"/auth/register", "/auth/register",
"/swagger-ui.html", "/swagger-ui.html",
"/register",
"/register/confirm-account",
"/v2/api-docs", "/v2/api-docs",
"/webjars/**", "/webjars/**",
"/swagger-resources/**", "/swagger-resources/**",

View File

@ -29,8 +29,6 @@ public class AuthenticationController {
private final JWTUserDetailsService userDetailsService; private final JWTUserDetailsService userDetailsService;
private final UserRepository users;
private BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(); private BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
public AuthenticationController( public AuthenticationController(
@ -43,7 +41,6 @@ public class AuthenticationController {
this.userRepository = userRepository; this.userRepository = userRepository;
this.jwtTokenUtil = jwtTokenUtil; this.jwtTokenUtil = jwtTokenUtil;
this.userDetailsService = userDetailsService; this.userDetailsService = userDetailsService;
this.users = users;
} }
@PostMapping("/login") @PostMapping("/login")
@ -55,13 +52,6 @@ public class AuthenticationController {
return new JWTResponse(token); return new JWTResponse(token);
} }
@PostMapping("/register")
public User register(@Valid @RequestBody User user) {
user.setPassword(encoder.encode(user.getPassword()));
users.save(user);
return user;
}
@Authorization(value = "Bearer") @Authorization(value = "Bearer")
@PatchMapping("/update") @PatchMapping("/update")
public User update( public User update(

View File

@ -2,6 +2,7 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut.controller;
import static ch.usi.inf.sa4.sanmarinoes.smarthut.utils.Utils.toList; import static ch.usi.inf.sa4.sanmarinoes.smarthut.utils.Utils.toList;
import ch.usi.inf.sa4.sanmarinoes.smarthut.dto.ButtonDimmerSaveRequest;
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.ButtonDimmer; import ch.usi.inf.sa4.sanmarinoes.smarthut.models.ButtonDimmer;
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.ButtonDimmerRepository; import ch.usi.inf.sa4.sanmarinoes.smarthut.models.ButtonDimmerRepository;
import java.util.List; import java.util.List;
@ -9,14 +10,7 @@ import java.util.Optional;
import javax.validation.Valid; import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.*;
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.RestController;
@RestController @RestController
@EnableAutoConfiguration @EnableAutoConfiguration
@ -35,13 +29,20 @@ public class ButtonDimmerController {
} }
@PostMapping @PostMapping
public ButtonDimmer save(@Valid @RequestBody ButtonDimmer bd) { public ButtonDimmer create(@Valid @RequestBody final ButtonDimmerSaveRequest bd) {
return buttonDimmerService.save(bd); ButtonDimmer newBD = new ButtonDimmer();
newBD.setLights(bd.getLights());
newBD.setId(bd.getId());
newBD.setName(bd.getName());
newBD.setRoom(bd.getRoom());
newBD.setRoomId(bd.getRoomId());
return buttonDimmerService.save(newBD);
} }
@PutMapping @PutMapping
public ButtonDimmer update(@Valid @RequestBody ButtonDimmer bd) { public ButtonDimmer update(@Valid @RequestBody ButtonDimmerSaveRequest bd) {
return buttonDimmerService.save(bd); return this.create(bd);
} }
@DeleteMapping("/{id}") @DeleteMapping("/{id}")

View File

@ -2,6 +2,7 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut.controller;
import static ch.usi.inf.sa4.sanmarinoes.smarthut.utils.Utils.toList; import static ch.usi.inf.sa4.sanmarinoes.smarthut.utils.Utils.toList;
import ch.usi.inf.sa4.sanmarinoes.smarthut.dto.DimmableLightSaveRequest;
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.DimmableLight; import ch.usi.inf.sa4.sanmarinoes.smarthut.models.DimmableLight;
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.DimmableLightRepository; import ch.usi.inf.sa4.sanmarinoes.smarthut.models.DimmableLightRepository;
import java.util.List; import java.util.List;
@ -9,14 +10,7 @@ import java.util.Optional;
import javax.validation.Valid; import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.*;
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.RestController;
@RestController @RestController
@EnableAutoConfiguration @EnableAutoConfiguration
@ -36,13 +30,20 @@ public class DimmableLightController {
} }
@PostMapping @PostMapping
public DimmableLight save(@Valid @RequestBody DimmableLight dl) { public DimmableLight create(@Valid @RequestBody DimmableLightSaveRequest dl) {
return dimmableLightService.save(dl); DimmableLight newDL = new DimmableLight();
newDL.setIntensity(dl.getIntensity());
newDL.setId(dl.getId());
newDL.setName(dl.getName());
newDL.setRoom(dl.getRoom());
newDL.setRoomId(dl.getRoomId());
return dimmableLightService.save(newDL);
} }
@PutMapping @PutMapping
public DimmableLight update(@Valid @RequestBody DimmableLight dl) { public DimmableLight update(@Valid @RequestBody DimmableLightSaveRequest dl) {
return dimmableLightService.save(dl); return this.create(dl);
} }
@DeleteMapping("/{id}") @DeleteMapping("/{id}")

View File

@ -2,6 +2,7 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut.controller;
import static ch.usi.inf.sa4.sanmarinoes.smarthut.utils.Utils.toList; import static ch.usi.inf.sa4.sanmarinoes.smarthut.utils.Utils.toList;
import ch.usi.inf.sa4.sanmarinoes.smarthut.dto.KnobDimmerSaveRequest;
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.KnobDimmer; import ch.usi.inf.sa4.sanmarinoes.smarthut.models.KnobDimmer;
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.KnobDimmerRepository; import ch.usi.inf.sa4.sanmarinoes.smarthut.models.KnobDimmerRepository;
import java.util.List; import java.util.List;
@ -9,14 +10,7 @@ import java.util.Optional;
import javax.validation.Valid; import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.*;
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.RestController;
@RestController @RestController
@EnableAutoConfiguration @EnableAutoConfiguration
@ -36,13 +30,20 @@ public class KnobDimmerController {
} }
@PostMapping @PostMapping
public KnobDimmer save(@Valid @RequestBody KnobDimmer kd) { public KnobDimmer create(@Valid @RequestBody KnobDimmerSaveRequest kd) {
return knobDimmerService.save(kd); KnobDimmer newKD = new KnobDimmer();
newKD.setLights(kd.getLights());
newKD.setId(kd.getId());
newKD.setName(kd.getName());
newKD.setRoom(kd.getRoom());
newKD.setRoomId(kd.getRoomId());
return knobDimmerService.save(newKD);
} }
@PutMapping @PutMapping
public KnobDimmer update(@Valid @RequestBody KnobDimmer kd) { public KnobDimmer update(@Valid @RequestBody KnobDimmerSaveRequest kd) {
return knobDimmerService.save(kd); return this.create(kd);
} }
@DeleteMapping("/{id}") @DeleteMapping("/{id}")

View File

@ -2,6 +2,7 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut.controller;
import static ch.usi.inf.sa4.sanmarinoes.smarthut.utils.Utils.toList; import static ch.usi.inf.sa4.sanmarinoes.smarthut.utils.Utils.toList;
import ch.usi.inf.sa4.sanmarinoes.smarthut.dto.MotionSensorSaveRequest;
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.MotionSensor; 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.models.MotionSensorRepository;
import java.util.List; import java.util.List;
@ -9,14 +10,7 @@ import java.util.Optional;
import javax.validation.Valid; import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.*;
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.RestController;
@RestController @RestController
@EnableAutoConfiguration @EnableAutoConfiguration
@ -36,13 +30,20 @@ public class MotionSensorController {
} }
@PostMapping @PostMapping
public MotionSensor save(@Valid @RequestBody MotionSensor ms) { public MotionSensor create(@Valid @RequestBody MotionSensorSaveRequest ms) {
return motionSensorService.save(ms); MotionSensor newMS = new MotionSensor();
newMS.setDetected(ms.isDetected());
newMS.setId(ms.getId());
newMS.setName(ms.getName());
newMS.setRoom(ms.getRoom());
newMS.setRoomId(ms.getRoomId());
return motionSensorService.save(newMS);
} }
@PutMapping @PutMapping
public MotionSensor update(@Valid @RequestBody MotionSensor ms) { public MotionSensor update(@Valid @RequestBody MotionSensorSaveRequest ms) {
return motionSensorService.save(ms); return this.create(ms);
} }
@DeleteMapping("/{id}") @DeleteMapping("/{id}")

View File

@ -2,6 +2,7 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut.controller;
import static ch.usi.inf.sa4.sanmarinoes.smarthut.utils.Utils.toList; import static ch.usi.inf.sa4.sanmarinoes.smarthut.utils.Utils.toList;
import ch.usi.inf.sa4.sanmarinoes.smarthut.dto.RegularLightSaveRequest;
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.RegularLight; import ch.usi.inf.sa4.sanmarinoes.smarthut.models.RegularLight;
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.RegularLightRepository; import ch.usi.inf.sa4.sanmarinoes.smarthut.models.RegularLightRepository;
import java.util.List; import java.util.List;
@ -36,13 +37,20 @@ public class RegularLightController {
} }
@PostMapping @PostMapping
public RegularLight save(@Valid @RequestBody RegularLight rl) { public RegularLight create(@Valid @RequestBody RegularLightSaveRequest rl) {
return regularLightService.save(rl); RegularLight newRL = new RegularLight();
newRL.setId(rl.getId());
newRL.setName(rl.getName());
newRL.setRoom(rl.getRoom());
newRL.setRoomId(rl.getRoomId());
newRL.setOn(rl.isOn());
return regularLightService.save(newRL);
} }
@PutMapping @PutMapping
public RegularLight update(@Valid @RequestBody RegularLight rl) { public RegularLight update(@Valid @RequestBody RegularLightSaveRequest rl) {
return regularLightService.save(rl); return this.create(rl);
} }
@DeleteMapping("/{id}") @DeleteMapping("/{id}")

View File

@ -2,6 +2,7 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut.controller;
import static ch.usi.inf.sa4.sanmarinoes.smarthut.utils.Utils.toList; import static ch.usi.inf.sa4.sanmarinoes.smarthut.utils.Utils.toList;
import ch.usi.inf.sa4.sanmarinoes.smarthut.dto.SensorSaveRequest;
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.*; import ch.usi.inf.sa4.sanmarinoes.smarthut.models.*;
import java.util.*; import java.util.*;
import java.util.List; import java.util.List;
@ -28,13 +29,21 @@ public class SensorController {
} }
@PostMapping @PostMapping
public Sensor save(@Valid @RequestBody Sensor s) { public Sensor create(@Valid @RequestBody SensorSaveRequest s) {
return sensorRepository.save(s); Sensor newSensor = new Sensor();
newSensor.setSensor(s.getSensor());
newSensor.setValue(s.getValue());
newSensor.setId(s.getId());
newSensor.setName(s.getName());
newSensor.setRoom(s.getRoom());
newSensor.setRoomId(s.getRoomId());
return sensorRepository.save(newSensor);
} }
@PutMapping @PutMapping
public Sensor update(@Valid @RequestBody Sensor s) { public Sensor update(@Valid @RequestBody SensorSaveRequest s) {
return sensorRepository.save(s); return this.create(s);
} }
@DeleteMapping("/{id}") @DeleteMapping("/{id}")

View File

@ -2,6 +2,7 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut.controller;
import static ch.usi.inf.sa4.sanmarinoes.smarthut.utils.Utils.toList; import static ch.usi.inf.sa4.sanmarinoes.smarthut.utils.Utils.toList;
import ch.usi.inf.sa4.sanmarinoes.smarthut.dto.SmartPlugSaveRequest;
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.*; import ch.usi.inf.sa4.sanmarinoes.smarthut.models.*;
import java.util.*; import java.util.*;
import java.util.List; import java.util.List;
@ -28,13 +29,20 @@ public class SmartPlugController {
} }
@PostMapping @PostMapping
public SmartPlug save(@Valid @RequestBody SmartPlug sp) { public SmartPlug create(@Valid @RequestBody SmartPlugSaveRequest sp) {
return smartPlugRepository.save(sp); SmartPlug newSP = new SmartPlug();
newSP.setOn(sp.isOn());
newSP.setId(sp.getId());
newSP.setName(sp.getName());
newSP.setRoom(sp.getRoom());
newSP.setRoomId(sp.getRoomId());
return smartPlugRepository.save(newSP);
} }
@PutMapping @PutMapping
public SmartPlug update(@Valid @RequestBody SmartPlug sp) { public SmartPlug update(@Valid @RequestBody SmartPlugSaveRequest sp) {
return smartPlugRepository.save(sp); return this.create(sp);
} }
@DeleteMapping("/{id}") @DeleteMapping("/{id}")

View File

@ -2,6 +2,7 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut.controller;
import static ch.usi.inf.sa4.sanmarinoes.smarthut.utils.Utils.toList; import static ch.usi.inf.sa4.sanmarinoes.smarthut.utils.Utils.toList;
import ch.usi.inf.sa4.sanmarinoes.smarthut.dto.SwitchSaveRequest;
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.*; import ch.usi.inf.sa4.sanmarinoes.smarthut.models.*;
import java.util.*; import java.util.*;
import java.util.List; import java.util.List;
@ -28,13 +29,20 @@ public class SwitchController {
} }
@PostMapping @PostMapping
public Switch save(@Valid @RequestBody Switch s) { public Switch create(@Valid @RequestBody SwitchSaveRequest s) {
return switchRepository.save(s); Switch newSwitch = new Switch();
newSwitch.setId(s.getId());
newSwitch.setName(s.getName());
newSwitch.setRoom(s.getRoom());
newSwitch.setRoomId(s.getRoomId());
newSwitch.setOn(s.isOn());
return switchRepository.save(newSwitch);
} }
@PutMapping @PutMapping
public Switch update(@Valid @RequestBody Switch s) { public Switch update(@Valid @RequestBody SwitchSaveRequest s) {
return switchRepository.save(s); return this.create(s);
} }
@DeleteMapping("/{id}") @DeleteMapping("/{id}")

View File

@ -0,0 +1,98 @@
package ch.usi.inf.sa4.sanmarinoes.smarthut.controller;
import ch.usi.inf.sa4.sanmarinoes.smarthut.dto.OkResponse;
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.EmailTokenNotFoundException;
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.ConfirmationToken;
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.ConfirmationTokenRepository;
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.User;
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.UserRepository;
import ch.usi.inf.sa4.sanmarinoes.smarthut.service.EmailSenderService;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@EnableAutoConfiguration
@RequestMapping("/register")
public class UserAccountController {
@Autowired private UserRepository userRepository;
@Autowired private ConfirmationTokenRepository confirmationTokenRepository;
@Autowired private EmailSenderService emailSenderService;
@Autowired private BCryptPasswordEncoder encoder;
@PostMapping
public OkResponse registerUser(@Valid @RequestBody UserRegistrationRequest registrationData)
throws DuplicateRegistrationException {
final User existingEmailUser =
userRepository.findByEmailIgnoreCase(registrationData.getEmail());
final User existingUsernameUser =
userRepository.findByUsername(registrationData.getUsername());
// Check if an User with the same email already exists
if (existingEmailUser != null || existingUsernameUser != null) {
throw new DuplicateRegistrationException();
} else {
final User toSave = new User();
// disable the user (it will be enabled on email confiration)
toSave.setEnabled(false);
// encode user's password
toSave.setPassword(encoder.encode(registrationData.getPassword()));
// set other fields
toSave.setName(registrationData.getName());
toSave.setUsername(registrationData.getUsername());
toSave.setEmail(registrationData.getEmail());
userRepository.save(toSave);
ConfirmationToken confirmationToken = new ConfirmationToken(toSave);
confirmationTokenRepository.save(confirmationToken);
SimpleMailMessage mailMessage = new SimpleMailMessage();
mailMessage.setTo(registrationData.getEmail());
mailMessage.setSubject("Complete Registration!");
mailMessage.setFrom("smarthut.sm@gmail.com");
mailMessage.setText(
"To confirm your account, please click here : "
+ "http://localhost:8080/register/confirm-account?token="
+ confirmationToken.getConfirmationToken());
emailSenderService.sendEmail(mailMessage);
return new OkResponse();
}
}
@GetMapping(value = "/confirm-account")
public OkResponse confirmUserAccount(@RequestParam("token") @NotNull String confirmationToken)
throws EmailTokenNotFoundException {
final ConfirmationToken token =
confirmationTokenRepository.findByConfirmationToken(confirmationToken);
if (token != null) {
final User user = userRepository.findByEmailIgnoreCase(token.getUser().getEmail());
user.setEnabled(true);
userRepository.save(user);
// TODO: redirect to frontend
return new OkResponse();
} else {
throw new EmailTokenNotFoundException();
}
}
}

View File

@ -0,0 +1,67 @@
package ch.usi.inf.sa4.sanmarinoes.smarthut.dto;
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.DimmableLight;
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.Room;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.*;
import javax.validation.constraints.NotNull;
public class ButtonDimmerSaveRequest {
@Lob private Set<DimmableLight> lights = new HashSet<DimmableLight>();
/** Device identifier */
private long id;
/** The room this device belongs in */
private Room room;
/**
* The room this device belongs in, as a foreign key id. To use when updating and inserting from
* a REST call.
*/
@NotNull private Long roomId;
/** The name of the device as assigned by the user (e.g. 'Master bedroom light') */
@NotNull private String name;
public Set<DimmableLight> getLights() {
return this.lights;
}
public void setLights(Set<DimmableLight> newLights) {
this.lights = newLights;
}
public void setId(long id) {
this.id = id;
}
public void setRoom(Room room) {
this.room = room;
}
public void setRoomId(Long roomId) {
this.roomId = roomId;
}
public void setName(String name) {
this.name = name;
}
public long getId() {
return id;
}
public Room getRoom() {
return room;
}
public Long getRoomId() {
return roomId;
}
public String getName() {
return name;
}
}

View File

@ -0,0 +1,73 @@
package ch.usi.inf.sa4.sanmarinoes.smarthut.dto;
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.Room;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
public class DimmableLightSaveRequest {
/** The light intensity value. Goes from 0 (off) to 100 (on) */
@NotNull
@Min(1)
@Max(100)
private Integer intensity = 0;
/** Device identifier */
private long id;
/** The room this device belongs in */
private Room room;
/**
* The room this device belongs in, as a foreign key id. To use when updating and inserting from
* a REST call.
*/
@NotNull private Long roomId;
/** The name of the device as assigned by the user (e.g. 'Master bedroom light') */
@NotNull private String name;
public void setId(long id) {
this.id = id;
}
public void setRoom(Room room) {
this.room = room;
}
public void setRoomId(Long roomId) {
this.roomId = roomId;
}
public void setName(String name) {
this.name = name;
}
public long getId() {
return id;
}
public Room getRoom() {
return room;
}
public Long getRoomId() {
return roomId;
}
public String getName() {
return name;
}
public Integer getIntensity() {
return intensity;
}
public void setIntensity(Integer intensity) throws IllegalArgumentException {
if (intensity < 0 || intensity > 100) {
throw new IllegalArgumentException("The intensity level can't go below 0 or above 100");
}
this.intensity = intensity;
}
}

View File

@ -0,0 +1,67 @@
package ch.usi.inf.sa4.sanmarinoes.smarthut.dto;
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.DimmableLight;
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.Room;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Lob;
import javax.validation.constraints.NotNull;
public class KnobDimmerSaveRequest {
@Lob private Set<DimmableLight> lights = new HashSet<DimmableLight>();
/** Device identifier */
private long id;
/** The room this device belongs in */
private Room room;
/**
* The room this device belongs in, as a foreign key id. To use when updating and inserting from
* a REST call.
*/
@NotNull private Long roomId;
/** The name of the device as assigned by the user (e.g. 'Master bedroom light') */
@NotNull private String name;
public void setId(long id) {
this.id = id;
}
public void setRoom(Room room) {
this.room = room;
}
public void setRoomId(Long roomId) {
this.roomId = roomId;
}
public void setName(String name) {
this.name = name;
}
public long getId() {
return id;
}
public Room getRoom() {
return room;
}
public Long getRoomId() {
return roomId;
}
public String getName() {
return name;
}
public void setLights(Set<DimmableLight> lights) {
this.lights = lights;
}
public Set<DimmableLight> getLights() {
return lights;
}
}

View File

@ -0,0 +1,63 @@
package ch.usi.inf.sa4.sanmarinoes.smarthut.dto;
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.Room;
import javax.validation.constraints.NotNull;
public class MotionSensorSaveRequest {
private boolean detected;
/** Device identifier */
private long id;
/** The room this device belongs in */
private Room room;
/**
* The room this device belongs in, as a foreign key id. To use when updating and inserting from
* a REST call.
*/
@NotNull private Long roomId;
/** The name of the device as assigned by the user (e.g. 'Master bedroom light') */
@NotNull private String name;
public void setId(long id) {
this.id = id;
}
public void setRoom(Room room) {
this.room = room;
}
public void setRoomId(Long roomId) {
this.roomId = roomId;
}
public void setName(String name) {
this.name = name;
}
public long getId() {
return id;
}
public Room getRoom() {
return room;
}
public Long getRoomId() {
return roomId;
}
public String getName() {
return name;
}
public boolean isDetected() {
return detected;
}
public void setDetected(boolean detected) {
this.detected = detected;
}
}

View File

@ -0,0 +1,6 @@
package ch.usi.inf.sa4.sanmarinoes.smarthut.dto;
/** A dummy DTO to return when there is no data to return */
public class OkResponse {
private boolean success = true;
}

View File

@ -0,0 +1,64 @@
package ch.usi.inf.sa4.sanmarinoes.smarthut.dto;
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.Room;
import javax.validation.constraints.NotNull;
public class RegularLightSaveRequest {
/** The state of this switch */
private boolean on;
/** Device identifier */
private long id;
/** The room this device belongs in */
private Room room;
/**
* The room this device belongs in, as a foreign key id. To use when updating and inserting from
* a REST call.
*/
@NotNull private Long roomId;
/** The name of the device as assigned by the user (e.g. 'Master bedroom light') */
@NotNull private String name;
public void setId(long id) {
this.id = id;
}
public void setRoom(Room room) {
this.room = room;
}
public void setRoomId(Long roomId) {
this.roomId = roomId;
}
public void setName(String name) {
this.name = name;
}
public long getId() {
return id;
}
public Room getRoom() {
return room;
}
public Long getRoomId() {
return roomId;
}
public String getName() {
return name;
}
public boolean isOn() {
return on;
}
public void setOn(boolean on) {
this.on = on;
}
}

View File

@ -0,0 +1,97 @@
package ch.usi.inf.sa4.sanmarinoes.smarthut.dto;
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.Room;
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.Sensor;
import com.google.gson.annotations.SerializedName;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.validation.constraints.NotNull;
public class SensorSaveRequest {
/** Type of sensor, i.e. of the thing the sensor measures. */
public enum SensorType {
/** A sensor that measures temperature in degrees celsius */
@SerializedName("TEMPERATURE")
TEMPERATURE,
/** A sensor that measures relative humidity in percentage points */
@SerializedName("HUMIDITY")
HUMIDITY,
/** A sensor that measures light in degrees */
@SerializedName("LIGHT")
LIGHT
}
/** The value of this sensor according to its sensor type */
private int value;
/** The type of this sensor */
@NotNull
@Enumerated(value = EnumType.STRING)
private Sensor.SensorType sensor;
/** Device identifier */
private long id;
/** The room this device belongs in */
private Room room;
/**
* The room this device belongs in, as a foreign key id. To use when updating and inserting from
* a REST call.
*/
@NotNull private Long roomId;
/** The name of the device as assigned by the user (e.g. 'Master bedroom light') */
@NotNull private String name;
public void setId(long id) {
this.id = id;
}
public void setRoom(Room room) {
this.room = room;
}
public void setRoomId(Long roomId) {
this.roomId = roomId;
}
public void setName(String name) {
this.name = name;
}
public long getId() {
return id;
}
public Room getRoom() {
return room;
}
public Long getRoomId() {
return roomId;
}
public String getName() {
return name;
}
public Sensor.SensorType getSensor() {
return sensor;
}
public void setSensor(Sensor.SensorType sensor) {
this.sensor = sensor;
}
public int getValue() {
return this.value;
}
public void setValue(int newValue) {
this.value = newValue;
}
}

View File

@ -0,0 +1,64 @@
package ch.usi.inf.sa4.sanmarinoes.smarthut.dto;
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.Room;
import javax.validation.constraints.NotNull;
public class SmartPlugSaveRequest {
/** Whether the smart plug is on */
@NotNull private boolean on;
/** Device identifier */
private long id;
/** The room this device belongs in */
private Room room;
/**
* The room this device belongs in, as a foreign key id. To use when updating and inserting from
* a REST call.
*/
@NotNull private Long roomId;
/** The name of the device as assigned by the user (e.g. 'Master bedroom light') */
@NotNull private String name;
public void setId(long id) {
this.id = id;
}
public void setRoom(Room room) {
this.room = room;
}
public void setRoomId(Long roomId) {
this.roomId = roomId;
}
public void setName(String name) {
this.name = name;
}
public long getId() {
return id;
}
public Room getRoom() {
return room;
}
public Long getRoomId() {
return roomId;
}
public String getName() {
return name;
}
public boolean isOn() {
return on;
}
public void setOn(boolean on) {
this.on = on;
}
}

View File

@ -0,0 +1,64 @@
package ch.usi.inf.sa4.sanmarinoes.smarthut.dto;
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.Room;
import javax.validation.constraints.NotNull;
public class SwitchSaveRequest {
/** The state of this switch */
private boolean on;
/** Device identifier */
private long id;
/** The room this device belongs in */
private Room room;
/**
* The room this device belongs in, as a foreign key id. To use when updating and inserting from
* a REST call.
*/
@NotNull private Long roomId;
/** The name of the device as assigned by the user (e.g. 'Master bedroom light') */
@NotNull private String name;
public void setId(long id) {
this.id = id;
}
public void setRoom(Room room) {
this.room = room;
}
public void setRoomId(Long roomId) {
this.roomId = roomId;
}
public void setName(String name) {
this.name = name;
}
public long getId() {
return id;
}
public Room getRoom() {
return room;
}
public Long getRoomId() {
return roomId;
}
public String getName() {
return name;
}
public boolean isOn() {
return on;
}
public void setOn(boolean on) {
this.on = on;
}
}

View File

@ -0,0 +1,67 @@
package ch.usi.inf.sa4.sanmarinoes.smarthut.dto;
import javax.validation.constraints.*;
public class UserRegistrationRequest {
/** The full name of the user */
@NotNull
@NotEmpty(message = "Please provide a full name")
private String name;
/** The full name of the user */
@NotNull
@NotEmpty(message = "Please provide a username")
private String username;
/** A properly salted way to store the password */
@NotNull
@NotEmpty(message = "Please provide a password")
@Size(
min = 6,
max = 255,
message = "Your password should be at least 6 characters long and up to 255 chars long")
private String password;
/**
* The user's email (validated according to criteria used in <code>&gt;input type="email"&lt;>
* </code>, technically not RFC 5322 compliant
*/
@NotNull
@NotEmpty(message = "Please provide an email")
@Email(message = "Please provide a valid email address")
@Pattern(regexp = ".+@.+\\..+", message = "Please provide a valid email address")
private String email;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}

View File

@ -0,0 +1,11 @@
package ch.usi.inf.sa4.sanmarinoes.smarthut.error;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;
@ResponseStatus(code = HttpStatus.BAD_REQUEST)
public class DuplicateRegistrationException extends Exception {
public DuplicateRegistrationException() {
super("Email or username already belonging to another user");
}
}

View File

@ -0,0 +1,11 @@
package ch.usi.inf.sa4.sanmarinoes.smarthut.error;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;
@ResponseStatus(code = HttpStatus.BAD_REQUEST)
public class EmailTokenNotFoundException extends Exception {
public EmailTokenNotFoundException() {
super("Email verification token not found in DB");
}
}

View File

@ -11,4 +11,54 @@ public class ButtonDimmer extends Dimmer {
public ButtonDimmer() { public ButtonDimmer() {
super("button-dimmer"); super("button-dimmer");
} }
/** Increases the current intensity level of the dimmable light by 1 */
public void increaseIntensity() {
for (DimmableLight dl : lights) {
dl.setIntensity(dl.getIntensity() + 1);
}
}
/** Decreases the current intensity level of the dimmable light by 1 */
public void decreaseIntensity() {
for (DimmableLight dl : lights) {
dl.setIntensity(dl.getIntensity() - 1);
}
}
/**
* Adds a DimmableLight to this set of DimmableLights
*
* @param dl The DimmableLight to be added
*/
public void addLight(DimmableLight dl) {
lights.add(dl);
}
/**
* Removes the given DimmableLight
*
* @param dl The DimmableLight to be removed
*/
public void removeLight(DimmableLight dl) {
lights.remove(dl);
}
/** Clears this set */
public void clearSet() {
lights.clear();
}
/**
* Get the lights
*
* @return duh
*/
public Set<DimmableLight> getLights() {
return this.lights;
}
public void setLights(Set<DimmableLight> newLights) {
this.lights = newLights;
}
} }

View File

@ -0,0 +1,74 @@
package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
import java.util.Date;
import java.util.UUID;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
@Entity
public class ConfirmationToken {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id", updatable = false, nullable = false)
private Long id;
@Column(name = "confirmation_token")
private String confirmationToken;
@Temporal(TemporalType.TIMESTAMP)
private Date createdDate;
@OneToOne(targetEntity = User.class, fetch = FetchType.EAGER)
@JoinColumn(nullable = false, name = "user_id")
private User user;
public ConfirmationToken(User user) {
this.user = user;
createdDate = new Date();
confirmationToken = UUID.randomUUID().toString();
}
/** Constructor for hibernate reflective stuff things whatever */
public ConfirmationToken() {}
public Long getId() {
return id;
}
public String getConfirmationToken() {
return confirmationToken;
}
public Date getCreatedDate() {
return createdDate;
}
public User getUser() {
return user;
}
public void setId(Long id) {
this.id = id;
}
public void setConfirmationToken(String confirmationToken) {
this.confirmationToken = confirmationToken;
}
public void setCreatedDate(Date createdDate) {
this.createdDate = createdDate;
}
public void setUser(User user) {
this.user = user;
}
}

View File

@ -0,0 +1,7 @@
package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
import org.springframework.data.repository.CrudRepository;
public interface ConfirmationTokenRepository extends CrudRepository<ConfirmationToken, String> {
ConfirmationToken findByConfirmationToken(String confirmationToken);
}

View File

@ -11,4 +11,56 @@ public class KnobDimmer extends Dimmer {
public KnobDimmer() { public KnobDimmer() {
super("knob-dimmer"); super("knob-dimmer");
} }
/**
* Increases or decreases the current intensity level by 5, moving between absolute multiples of
* 5 between 0 and 100, of all dimmable lights mapped to this knob
*
* @param inc The direction the knob is turned with
*/
public void modifyIntensity(boolean inc) {
for (DimmableLight dl : lights) {
int remainder = dl.getIntensity() / 5;
if (inc) {
dl.setIntensity(dl.getIntensity() - remainder);
dl.setIntensity((dl.getIntensity() + 5) % 105);
} else {
dl.setIntensity(dl.getIntensity() + (5 - remainder));
dl.setIntensity((dl.getIntensity() - 5) % 105);
}
}
}
/**
* Adds a DimmableLight to this set of DimmableLights
*
* @param dl The DimmableLight to be added
*/
public void addLight(DimmableLight dl) {
lights.add(dl);
}
/**
* Removes the given DimmableLight
*
* @param dl The DimmableLight to be removed
*/
public void removeLight(DimmableLight dl) {
lights.remove(dl);
}
/** Clears this set */
public void clearSet() {
lights.clear();
}
public void setLights(Set<DimmableLight> lights) {
this.lights = lights;
}
public Set<DimmableLight> getLights() {
return lights;
}
} }

View File

@ -1,10 +1,23 @@
package ch.usi.inf.sa4.sanmarinoes.smarthut.models; package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
import javax.persistence.Column;
import javax.persistence.Entity; import javax.persistence.Entity;
/** Represents a motion sensor device */ /** Represents a motion sensor device */
@Entity @Entity
public class MotionSensor extends InputDevice { public class MotionSensor extends InputDevice {
@Column(nullable = false)
private boolean detected;
public boolean isDetected() {
return detected;
}
public void setDetected(boolean detected) {
this.detected = detected;
}
public MotionSensor() { public MotionSensor() {
super("motion-sensor"); super("motion-sensor");
} }

View File

@ -26,6 +26,10 @@ public class Sensor extends InputDevice {
LIGHT LIGHT
} }
/** The value of this sensor according to its sensor type */
@Column(nullable = false)
private int value;
/** The type of this sensor */ /** The type of this sensor */
@Column(nullable = false) @Column(nullable = false)
@NotNull @NotNull
@ -40,6 +44,14 @@ public class Sensor extends InputDevice {
this.sensor = sensor; this.sensor = sensor;
} }
public int getValue() {
return this.value;
}
public void setValue(int newValue) {
this.value = newValue;
}
public Sensor() { public Sensor() {
super("sensor"); super("sensor");
} }

View File

@ -3,7 +3,7 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
import javax.persistence.Column; import javax.persistence.Column;
import javax.persistence.Entity; import javax.persistence.Entity;
/** A switch input device TODO: define switch behaviour (push button vs on/off state) */ /** A switch input device */
@Entity @Entity
public class Switch extends InputDevice { public class Switch extends InputDevice {
@ -20,7 +20,7 @@ public class Switch extends InputDevice {
* *
* @param state The state to be set * @param state The state to be set
*/ */
void setState(boolean state) { public void setOn(boolean state) {
on = state; on = state;
} }
@ -29,7 +29,7 @@ public class Switch extends InputDevice {
* *
* @return This Switch on state * @return This Switch on state
*/ */
boolean getState() { public boolean isOn() {
return on; return on;
} }
} }

View File

@ -2,7 +2,11 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
import javax.persistence.*; import javax.persistence.*;
import javax.validation.constraints.*; import javax.validation.constraints.Email;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
/** A user of the Smarthut application */ /** A user of the Smarthut application */
@Entity(name = "smarthutuser") @Entity(name = "smarthutuser")
@ -33,8 +37,7 @@ public class User {
@Size( @Size(
min = 6, min = 6,
max = 255, max = 255,
message = message = "Your password should be at least 6 characters long and up to 255 chars long")
"Your password should be at least 6 characters long and at most 255 chars long")
private String password; private String password;
/** /**
@ -48,6 +51,10 @@ public class User {
@Pattern(regexp = ".+@.+\\..+", message = "Please provide a valid email address") @Pattern(regexp = ".+@.+\\..+", message = "Please provide a valid email address")
private String email; private String email;
@Column(nullable = false)
@ApiModelProperty(hidden = true)
private Boolean isEnabled = false;
public Long getId() { public Long getId() {
return id; return id;
} }
@ -88,6 +95,14 @@ public class User {
this.password = password; this.password = password;
} }
public Boolean getEnabled() {
return isEnabled;
}
public void setEnabled(Boolean enabled) {
isEnabled = enabled;
}
@Override @Override
public String toString() { public String toString() {
return "User{" return "User{"
@ -96,11 +111,17 @@ public class User {
+ ", name='" + ", name='"
+ name + name
+ '\'' + '\''
+ ", username='"
+ username
+ '\''
+ ", password='" + ", password='"
+ password + password
+ '\'' + '\''
+ ", email='" + ", email='"
+ email + email
+ "\'}"; + '\''
+ ", isEnabled="
+ isEnabled
+ '}';
} }
} }

View File

@ -5,4 +5,6 @@ import org.springframework.data.repository.CrudRepository;
public interface UserRepository extends CrudRepository<User, Long> { public interface UserRepository extends CrudRepository<User, Long> {
User findByUsername(String username); User findByUsername(String username);
User findByEmailIgnoreCase(String email);
} }

View File

@ -10,4 +10,16 @@ spring.jpa.hibernate.ddl-auto=update
spring.jpa.hibernate.naming.implicit-strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyJpaCompliantImpl spring.jpa.hibernate.naming.implicit-strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyJpaCompliantImpl
spring.jpa.properties.hibernate.format_sql=true spring.jpa.properties.hibernate.format_sql=true
jwt.secret=thiskeymustbeverylongorthethingcomplainssoiamjustgoingtowritehereabunchofgarbageciaomamma jwt.secret=thiskeymustbeverylongorthethingcomplainssoiamjustgoingtowritehereabunchofgarbageciaomamma
spring.mail.test-connection=true
spring.mail.host=smtp.gmail.com
spring.mail.port=587
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.username=smarthut.sm@gmail.com
spring.mail.password=dcadvbagqfkwbfts
spring.mail.properties.mail.smtp.starttls.required=true
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.connectiontimeout=5000
spring.mail.properties.mail.smtp.timeout=5000
spring.mail.properties.mail.smtp.writetimeout=5000