Merge branch 'dev' into 'model-update'
# Conflicts: # src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/ButtonDimmer.java # src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/KnobDimmer.java
This commit is contained in:
commit
529adb0d83
21 changed files with 507 additions and 44 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -1,4 +1,4 @@
|
||||||
.idea/misc.xml
|
.idea/**
|
||||||
|
|
||||||
**/.DS_Store
|
**/.DS_Store
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ sourceCompatibility = "11"
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
|
jcenter()
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
@ -17,9 +18,12 @@ 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'
|
||||||
|
compile "io.springfox:springfox-swagger2:2.9.2"
|
||||||
|
compile group: 'io.springfox', name: 'springfox-swagger-ui', version: '2.9.2'
|
||||||
|
|
||||||
implementation('org.springframework.boot:spring-boot-starter-web') {
|
implementation('org.springframework.boot:spring-boot-starter-web') {
|
||||||
exclude group: 'org.springframework.boot', module: 'spring-boot-starter-json'
|
exclude group: 'org.springframework.boot', module: 'spring-boot-starter-json'
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
package ch.usi.inf.sa4.sanmarinoes.smarthut.config;
|
||||||
|
|
||||||
|
import com.google.gson.*;
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.http.converter.json.GsonHttpMessageConverter;
|
||||||
|
import springfox.documentation.spring.web.json.Json;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Spring configuration in order to register the GSON type adapter needed to avoid serializing twice
|
||||||
|
* Springfox Swagger JSON output (see: https://stackoverflow.com/a/30220562)
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
public class GsonConfig {
|
||||||
|
@Bean
|
||||||
|
public GsonHttpMessageConverter gsonHttpMessageConverter() {
|
||||||
|
GsonHttpMessageConverter converter = new GsonHttpMessageConverter();
|
||||||
|
converter.setGson(gson());
|
||||||
|
return converter;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Gson gson() {
|
||||||
|
final GsonBuilder builder = new GsonBuilder();
|
||||||
|
builder.registerTypeAdapter(Json.class, new SpringfoxJsonToGsonAdapter());
|
||||||
|
return builder.create();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** GSON type adapter needed to avoid serializing twice Springfox Swagger JSON output */
|
||||||
|
class SpringfoxJsonToGsonAdapter implements JsonSerializer<Json> {
|
||||||
|
@Override
|
||||||
|
public JsonElement serialize(Json json, Type type, JsonSerializationContext context) {
|
||||||
|
return JsonParser.parseString(json.value());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,77 @@
|
||||||
|
package ch.usi.inf.sa4.sanmarinoes.smarthut.config;
|
||||||
|
|
||||||
|
import static springfox.documentation.builders.PathSelectors.regex;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.ComponentScan;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import springfox.documentation.builders.ApiInfoBuilder;
|
||||||
|
import springfox.documentation.builders.RequestHandlerSelectors;
|
||||||
|
import springfox.documentation.service.ApiInfo;
|
||||||
|
import springfox.documentation.service.ApiKey;
|
||||||
|
import springfox.documentation.service.SecurityScheme;
|
||||||
|
import springfox.documentation.spi.DocumentationType;
|
||||||
|
import springfox.documentation.spring.web.plugins.Docket;
|
||||||
|
import springfox.documentation.swagger2.annotations.EnableSwagger2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class configures the automated REST documentation tool Swagger for this project. The
|
||||||
|
* documentation can be seen by going to http://localhost:8080/swaggeer-ui.html
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
@EnableSwagger2
|
||||||
|
@ComponentScan("ch.usi.inf.sa4.sanmarinoes.smarthut")
|
||||||
|
public class SpringFoxConfig {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main definition of Springfox / swagger configuration
|
||||||
|
*
|
||||||
|
* @return a Docket object containing the swagger configuration
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public Docket api() {
|
||||||
|
return new Docket(DocumentationType.SWAGGER_2)
|
||||||
|
.select()
|
||||||
|
.apis(RequestHandlerSelectors.any())
|
||||||
|
.paths(paths()::test)
|
||||||
|
.build()
|
||||||
|
.apiInfo(apiInfo())
|
||||||
|
.securitySchemes(securitySchemes());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures the documentation about the smarthut authentication system
|
||||||
|
*
|
||||||
|
* @return a list of springfox authentication configurations
|
||||||
|
*/
|
||||||
|
private static List<? extends SecurityScheme> securitySchemes() {
|
||||||
|
return List.of(new ApiKey("Bearer", "Authorization", "header"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures the paths the documentation must be generated for. Add a path here only when the
|
||||||
|
* spec has been totally defined.
|
||||||
|
*
|
||||||
|
* @return A predicate that tests whether a path must be included or not
|
||||||
|
*/
|
||||||
|
private Predicate<String> paths() {
|
||||||
|
return ((Predicate<String>) regex("/auth.*")::apply).or(regex("/register.*")::apply);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the metadata about the smarthut project
|
||||||
|
*
|
||||||
|
* @return metadata about smarthut
|
||||||
|
*/
|
||||||
|
private ApiInfo apiInfo() {
|
||||||
|
return new ApiInfoBuilder()
|
||||||
|
.title("SmartHut.sm API")
|
||||||
|
.description("Backend API for the SanMariones version of the SA4 SmartHut project")
|
||||||
|
.termsOfServiceUrl("https://www.youtube.com/watch?v=9KxTcDsy9Gs")
|
||||||
|
.license("WTFPL")
|
||||||
|
.version("dev branch")
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
|
@ -50,13 +50,19 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||||
.disable()
|
.disable()
|
||||||
// dont authenticate this particular request
|
// dont authenticate this particular request
|
||||||
.authorizeRequests()
|
.authorizeRequests()
|
||||||
.antMatchers("/auth/login")
|
.antMatchers(
|
||||||
|
"/auth/login",
|
||||||
|
"/auth/register",
|
||||||
|
"/swagger-ui.html",
|
||||||
|
"/register",
|
||||||
|
"/register/confirm-account",
|
||||||
|
"/v2/api-docs",
|
||||||
|
"/webjars/**",
|
||||||
|
"/swagger-resources/**",
|
||||||
|
"/csrf")
|
||||||
.permitAll()
|
.permitAll()
|
||||||
.antMatchers("/auth/register")
|
|
||||||
.permitAll()
|
|
||||||
.
|
|
||||||
// all other requests need to be authenticated
|
// all other requests need to be authenticated
|
||||||
anyRequest()
|
.anyRequest()
|
||||||
.authenticated()
|
.authenticated()
|
||||||
.and()
|
.and()
|
||||||
.
|
.
|
||||||
|
|
|
@ -5,9 +5,9 @@ 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.JWTResponse;
|
||||||
import ch.usi.inf.sa4.sanmarinoes.smarthut.dto.UserUpdateRequest;
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.dto.UserUpdateRequest;
|
||||||
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.*;
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.*;
|
||||||
|
import io.swagger.annotations.Authorization;
|
||||||
import java.security.Principal;
|
import java.security.Principal;
|
||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.security.authentication.AuthenticationManager;
|
import org.springframework.security.authentication.AuthenticationManager;
|
||||||
import org.springframework.security.authentication.BadCredentialsException;
|
import org.springframework.security.authentication.BadCredentialsException;
|
||||||
import org.springframework.security.authentication.DisabledException;
|
import org.springframework.security.authentication.DisabledException;
|
||||||
|
@ -21,18 +21,28 @@ import org.springframework.web.bind.annotation.*;
|
||||||
@RequestMapping("/auth")
|
@RequestMapping("/auth")
|
||||||
public class AuthenticationController {
|
public class AuthenticationController {
|
||||||
|
|
||||||
@Autowired private AuthenticationManager authenticationManager;
|
private final AuthenticationManager authenticationManager;
|
||||||
|
|
||||||
@Autowired private UserRepository userRepository;
|
private final UserRepository userRepository;
|
||||||
|
|
||||||
@Autowired private JWTTokenUtil jwtTokenUtil;
|
private final JWTTokenUtil jwtTokenUtil;
|
||||||
|
|
||||||
@Autowired private JWTUserDetailsService userDetailsService;
|
private final JWTUserDetailsService userDetailsService;
|
||||||
|
|
||||||
@Autowired private UserRepository users;
|
|
||||||
|
|
||||||
private BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
|
private BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
|
||||||
|
|
||||||
|
public AuthenticationController(
|
||||||
|
AuthenticationManager authenticationManager,
|
||||||
|
UserRepository userRepository,
|
||||||
|
JWTTokenUtil jwtTokenUtil,
|
||||||
|
JWTUserDetailsService userDetailsService,
|
||||||
|
UserRepository users) {
|
||||||
|
this.authenticationManager = authenticationManager;
|
||||||
|
this.userRepository = userRepository;
|
||||||
|
this.jwtTokenUtil = jwtTokenUtil;
|
||||||
|
this.userDetailsService = userDetailsService;
|
||||||
|
}
|
||||||
|
|
||||||
@PostMapping("/login")
|
@PostMapping("/login")
|
||||||
public JWTResponse login(@RequestBody JWTRequest authenticationRequest) throws Exception {
|
public JWTResponse login(@RequestBody JWTRequest authenticationRequest) throws Exception {
|
||||||
authenticate(authenticationRequest.getUsername(), authenticationRequest.getPassword());
|
authenticate(authenticationRequest.getUsername(), authenticationRequest.getPassword());
|
||||||
|
@ -42,22 +52,18 @@ public class AuthenticationController {
|
||||||
return new JWTResponse(token);
|
return new JWTResponse(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/register")
|
@Authorization(value = "Bearer")
|
||||||
public User register(@Valid @RequestBody User user) {
|
|
||||||
user.setPassword(encoder.encode(user.getPassword()));
|
|
||||||
users.save(user);
|
|
||||||
return user;
|
|
||||||
}
|
|
||||||
|
|
||||||
@PatchMapping("/update")
|
@PatchMapping("/update")
|
||||||
public User update(@Valid @RequestBody final UserUpdateRequest u, final Principal principal) {
|
public User update(
|
||||||
|
@Valid @RequestBody final UserUpdateRequest userData, final Principal principal) {
|
||||||
final User oldUser = userRepository.findByUsername(principal.getName());
|
final User oldUser = userRepository.findByUsername(principal.getName());
|
||||||
if (u.getName() != null) oldUser.setName(u.getName());
|
if (userData.getName() != null) oldUser.setName(userData.getName());
|
||||||
if (u.getEmail() != null) {
|
if (userData.getEmail() != null) {
|
||||||
oldUser.setEmail(u.getEmail());
|
oldUser.setEmail(userData.getEmail());
|
||||||
// TODO: handle email verification
|
// TODO: handle email verification
|
||||||
}
|
}
|
||||||
if (u.getPassword() != null) oldUser.setPassword(encoder.encode(u.getPassword()));
|
if (userData.getPassword() != null)
|
||||||
|
oldUser.setPassword(encoder.encode(userData.getPassword()));
|
||||||
return userRepository.save(oldUser);
|
return userRepository.save(oldUser);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
|
@ -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>>input type="email"<>
|
||||||
|
* </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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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");
|
||||||
|
}
|
||||||
|
}
|
|
@ -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");
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,9 +1,6 @@
|
||||||
package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
|
package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
|
||||||
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
import javax.persistence.OneToMany;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a dimmer that can only instruct an increase or decrease of intensity (i.e. like a
|
* Represents a dimmer that can only instruct an increase or decrease of intensity (i.e. like a
|
||||||
|
@ -11,9 +8,6 @@ import javax.persistence.OneToMany;
|
||||||
*/
|
*/
|
||||||
@Entity
|
@Entity
|
||||||
public class ButtonDimmer extends Dimmer {
|
public class ButtonDimmer extends Dimmer {
|
||||||
@OneToMany(mappedBy = "button_dimmer")
|
|
||||||
private Set<DimmableLight> lights = new HashSet<DimmableLight>();
|
|
||||||
|
|
||||||
public ButtonDimmer() {
|
public ButtonDimmer() {
|
||||||
super("button-dimmer");
|
super("button-dimmer");
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
|
package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
|
||||||
|
|
||||||
import com.google.gson.annotations.SerializedName;
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
import javax.persistence.*;
|
import javax.persistence.*;
|
||||||
import javax.validation.constraints.NotNull;
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
|
@ -22,11 +23,13 @@ public abstract class Device {
|
||||||
@Id
|
@Id
|
||||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||||
@Column(name = "id", updatable = false, nullable = false, unique = true)
|
@Column(name = "id", updatable = false, nullable = false, unique = true)
|
||||||
|
@ApiModelProperty(hidden = true)
|
||||||
private long id;
|
private long id;
|
||||||
|
|
||||||
/** The room this device belongs in */
|
/** The room this device belongs in */
|
||||||
@ManyToOne
|
@ManyToOne
|
||||||
@JoinColumn(name = "room_id", nullable = false, updatable = false, insertable = false)
|
@JoinColumn(name = "room_id", nullable = false, updatable = false, insertable = false)
|
||||||
|
@ApiModelProperty(hidden = true)
|
||||||
private Room room;
|
private Room room;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -46,13 +49,17 @@ public abstract class Device {
|
||||||
* The name for the category of this particular device (e.g 'dimmer'). Not stored in the
|
* The name for the category of this particular device (e.g 'dimmer'). Not stored in the
|
||||||
* database but set thanks to constructors
|
* database but set thanks to constructors
|
||||||
*/
|
*/
|
||||||
@Transient private final String kind;
|
@ApiModelProperty(hidden = true)
|
||||||
|
@Transient
|
||||||
|
private final String kind;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The way this device behaves in the automation flow. Not stored in the database but set thanks
|
* The way this device behaves in the automation flow. Not stored in the database but set thanks
|
||||||
* to constructors
|
* to constructors
|
||||||
*/
|
*/
|
||||||
@Transient private final FlowType flowType;
|
@ApiModelProperty(hidden = true)
|
||||||
|
@Transient
|
||||||
|
private final FlowType flowType;
|
||||||
|
|
||||||
public long getId() {
|
public long getId() {
|
||||||
return id;
|
return id;
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
|
package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
|
||||||
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
import javax.persistence.OneToMany;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a dimmer able to set absolute intensity values (i.e. knowing the absolute intensity
|
* Represents a dimmer able to set absolute intensity values (i.e. knowing the absolute intensity
|
||||||
|
@ -11,9 +8,6 @@ import javax.persistence.OneToMany;
|
||||||
*/
|
*/
|
||||||
@Entity
|
@Entity
|
||||||
public class KnobDimmer extends Dimmer {
|
public class KnobDimmer extends Dimmer {
|
||||||
@OneToMany(mappedBy = "knob_dimmer")
|
|
||||||
private Set<DimmableLight> lights = new HashSet<DimmableLight>();
|
|
||||||
|
|
||||||
public KnobDimmer() {
|
public KnobDimmer() {
|
||||||
super("knob-dimmer");
|
super("knob-dimmer");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
|
package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import javax.persistence.*;
|
import javax.persistence.*;
|
||||||
import javax.validation.constraints.NotNull;
|
import javax.validation.constraints.NotNull;
|
||||||
|
@ -11,6 +12,7 @@ public class Room {
|
||||||
@Id
|
@Id
|
||||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||||
@Column(name = "id", updatable = false, nullable = false)
|
@Column(name = "id", updatable = false, nullable = false)
|
||||||
|
@ApiModelProperty(hidden = true)
|
||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -41,12 +43,14 @@ public class Room {
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
/** Collection of devices present in this room */
|
/** Collection of devices present in this room */
|
||||||
|
@ApiModelProperty(hidden = true)
|
||||||
@OneToMany(mappedBy = "room")
|
@OneToMany(mappedBy = "room")
|
||||||
private Set<Device> devices;
|
private Set<Device> devices;
|
||||||
|
|
||||||
/** User that owns the house this room is in */
|
/** User that owns the house this room is in */
|
||||||
@ManyToOne
|
@ManyToOne
|
||||||
@JoinColumn(name = "user_id", nullable = false, updatable = false, insertable = false)
|
@JoinColumn(name = "user_id", nullable = false, updatable = false, insertable = false)
|
||||||
|
@ApiModelProperty(hidden = true)
|
||||||
private User user;
|
private User user;
|
||||||
|
|
||||||
public Long getId() {
|
public Long getId() {
|
||||||
|
|
|
@ -1,8 +1,13 @@
|
||||||
package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
|
package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
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")
|
||||||
|
@ -11,6 +16,7 @@ public class User {
|
||||||
@Id
|
@Id
|
||||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||||
@Column(name = "id", updatable = false, nullable = false)
|
@Column(name = "id", updatable = false, nullable = false)
|
||||||
|
@ApiModelProperty(hidden = true)
|
||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
/** The full name of the user */
|
/** The full name of the user */
|
||||||
|
@ -32,8 +38,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;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -49,8 +54,13 @@ public class User {
|
||||||
|
|
||||||
/** All rooms in the user's house */
|
/** All rooms in the user's house */
|
||||||
@OneToMany(mappedBy = "user")
|
@OneToMany(mappedBy = "user")
|
||||||
|
@ApiModelProperty(hidden = true)
|
||||||
private Set<Room> rooms;
|
private Set<Room> rooms;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
@ApiModelProperty(hidden = true)
|
||||||
|
private Boolean isEnabled = false;
|
||||||
|
|
||||||
public Long getId() {
|
public Long getId() {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
@ -95,6 +105,14 @@ public class User {
|
||||||
return rooms;
|
return rooms;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Boolean getEnabled() {
|
||||||
|
return isEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEnabled(Boolean enabled) {
|
||||||
|
isEnabled = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "User{"
|
return "User{"
|
||||||
|
@ -103,11 +121,17 @@ public class User {
|
||||||
+ ", name='"
|
+ ", name='"
|
||||||
+ name
|
+ name
|
||||||
+ '\''
|
+ '\''
|
||||||
|
+ ", username='"
|
||||||
|
+ username
|
||||||
|
+ '\''
|
||||||
+ ", password='"
|
+ ", password='"
|
||||||
+ password
|
+ password
|
||||||
+ '\''
|
+ '\''
|
||||||
+ ", email='"
|
+ ", email='"
|
||||||
+ email
|
+ email
|
||||||
+ "\'}";
|
+ '\''
|
||||||
|
+ ", isEnabled="
|
||||||
|
+ isEnabled
|
||||||
|
+ '}';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,3 +11,15 @@ spring.jpa.hibernate.naming.implicit-strategy=org.hibernate.boot.model.naming.Im
|
||||||
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
|
Loading…
Reference in a new issue