Merge branch 'dev' into 'web-socket-feature'
This commit is contained in:
commit
873ef54e13
73 changed files with 1783 additions and 620 deletions
|
@ -1,17 +1,61 @@
|
||||||
code_quality:
|
#Trying to set up the CI, probably won't work
|
||||||
image: docker:stable
|
image: gradle:jdk13
|
||||||
variables:
|
|
||||||
DOCKER_DRIVER: overlay2
|
stages:
|
||||||
allow_failure: true
|
- build
|
||||||
|
- test
|
||||||
|
- code_quality
|
||||||
|
- deploy
|
||||||
|
|
||||||
|
#Sets up the docker
|
||||||
|
smarthut_deploy:
|
||||||
|
stage: deploy
|
||||||
|
image: docker:latest
|
||||||
services:
|
services:
|
||||||
- docker:stable-dind
|
- docker:dind
|
||||||
|
variables:
|
||||||
|
DOCKER_DRIVER: overlay
|
||||||
|
before_script:
|
||||||
|
- docker version
|
||||||
|
- docker info
|
||||||
|
- docker login -u smarthutsm -p $CI_DOCKER_PASS #GiovanniRoberto
|
||||||
script:
|
script:
|
||||||
- export SP_VERSION=$(echo "$CI_SERVER_VERSION" | sed 's/^\([0-9]*\)\.\([0-9]*\).*/\1-\2-stable/')
|
- "docker build -t smarthutsm/smarthut:${CI_COMMIT_BRANCH} --pull ."
|
||||||
- docker run
|
- "docker push smarthutsm/smarthut:${CI_COMMIT_BRANCH}"
|
||||||
--env SOURCE_CODE="$PWD"
|
after_script:
|
||||||
--volume "$PWD":/code
|
- docker logout
|
||||||
--volume /var/run/docker.sock:/var/run/docker.sock
|
|
||||||
"registry.gitlab.com/gitlab-org/security-products/codequality:$SP_VERSION" /code
|
|
||||||
|
#base checks for the code
|
||||||
|
build:
|
||||||
|
stage: build
|
||||||
|
script:
|
||||||
|
- gradle clean
|
||||||
|
- gradle assemble
|
||||||
artifacts:
|
artifacts:
|
||||||
|
paths:
|
||||||
|
- build/libs/*.jar
|
||||||
|
expire_in: 1 week
|
||||||
|
|
||||||
|
#Runs the various tests and creates a report on the test coverage
|
||||||
|
test:
|
||||||
|
stage: test
|
||||||
|
script:
|
||||||
|
- gradle test
|
||||||
|
artifacts:
|
||||||
|
paths:
|
||||||
|
- build/test-results/test/TEST-*.xml
|
||||||
reports:
|
reports:
|
||||||
codequality: gl-code-quality-report.json
|
junit: build/test-results/test/TEST-*.xml
|
||||||
|
|
||||||
|
#Runs a quality check on the code and creates a report on the codes
|
||||||
|
code_quality:
|
||||||
|
stage: code_quality
|
||||||
|
script:
|
||||||
|
- gradle cpdCheck
|
||||||
|
artifacts:
|
||||||
|
paths:
|
||||||
|
- build/reports/cpd/cpdCheck.xml
|
||||||
|
#create a report on the quality of the code
|
||||||
|
expose_as: 'Code Quality Report'
|
||||||
|
allow_failure: true
|
||||||
|
|
8
Dockerfile
Normal file
8
Dockerfile
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
FROM openjdk:13-jdk-alpine
|
||||||
|
ENV DB_URL ""
|
||||||
|
ENV DB_USER ""
|
||||||
|
ENV DB_PASS ""
|
||||||
|
ARG JAR_FILE=build/libs/smarthut*.jar
|
||||||
|
COPY ${JAR_FILE} app.jar
|
||||||
|
EXPOSE 8080
|
||||||
|
ENTRYPOINT ["java","-jar","/app.jar"]
|
24
build.gradle
24
build.gradle
|
@ -1,37 +1,49 @@
|
||||||
plugins {
|
plugins {
|
||||||
id 'org.springframework.boot' version '2.2.4.RELEASE'
|
id 'org.springframework.boot' version '2.2.4.RELEASE'
|
||||||
id 'io.spring.dependency-management' version '1.0.9.RELEASE'
|
id 'io.spring.dependency-management' version '1.0.9.RELEASE'
|
||||||
|
id "de.aaschmid.cpd" version "3.1"
|
||||||
id 'java'
|
id 'java'
|
||||||
}
|
}
|
||||||
|
|
||||||
group = 'ch.usi.inf.sa4.sanmarinoes.'
|
group = 'ch.usi.inf.sa4.sanmarinoes'
|
||||||
version = '0.0.1-SNAPSHOT'
|
version = '0.0.1-SNAPSHOT'
|
||||||
sourceCompatibility = "11"
|
sourceCompatibility = '11'
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
jcenter()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile 'org.hibernate.javax.persistence:hibernate-jpa-2.1-api:1.0.0.Final'
|
compile 'org.hibernate.javax.persistence:hibernate-jpa-2.1-api:1.0.0.Final'
|
||||||
|
compile "org.springframework.boot:spring-boot-starter-websocket"
|
||||||
|
|
||||||
implementation 'org.springframework.boot:spring-boot-starter'
|
implementation 'org.springframework.boot:spring-boot-starter'
|
||||||
|
|
||||||
|
implementation 'com.sun.mail:javax.mail:1.6.2'
|
||||||
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 '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"
|
implementation 'com.google.code.gson:gson'
|
||||||
compile group: 'io.springfox', name: 'springfox-swagger-ui', version: '2.9.2'
|
compile 'io.springfox:springfox-swagger2:2.9.2'
|
||||||
|
compile 'io.springfox:springfox-swagger-ui:2.9.2'
|
||||||
|
compile 'org.springframework.boot:spring-boot-configuration-processor'
|
||||||
|
|
||||||
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'
|
||||||
}
|
}
|
||||||
implementation 'com.google.code.gson:gson'
|
|
||||||
testImplementation('org.springframework.boot:spring-boot-starter-test') {
|
testImplementation('org.springframework.boot:spring-boot-starter-test') {
|
||||||
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
|
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
testImplementation 'org.springframework.security:spring-security-test'
|
||||||
|
testImplementation 'com.h2database:h2:1.4.200'
|
||||||
|
|
||||||
|
// Fixes https://stackoverflow.com/a/60455550
|
||||||
|
testImplementation group: 'org.apache.httpcomponents', name: 'httpclient', version: '4.5.11'
|
||||||
}
|
}
|
||||||
|
|
||||||
test {
|
test {
|
||||||
|
|
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
Binary file not shown.
3
gradle/wrapper/gradle-wrapper.properties
vendored
3
gradle/wrapper/gradle-wrapper.properties
vendored
|
@ -1,6 +1,5 @@
|
||||||
#Thu Feb 20 21:04:58 CET 2020
|
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
|
distributionUrl=https\://services.gradle.org/distributions/gradle-6.2.2-bin.zip
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.0.1-all.zip
|
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
package ch.usi.inf.sa4.sanmarinoes.smarthut.config;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.servlet.*;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add CORS headers to each response in order to please the frontend requests, coming from a
|
||||||
|
* different host for now (thanks to the difference in ports). Andrea would you please stop
|
||||||
|
* complaining now
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class CORSFilter implements Filter {
|
||||||
|
|
||||||
|
static void setCORSHeaders(HttpServletResponse response) {
|
||||||
|
response.setHeader("Access-Control-Allow-Origin", "*");
|
||||||
|
response.setHeader("Access-Control-Allow-Methods", "HEAD, PUT, POST, GET, OPTIONS, DELETE");
|
||||||
|
response.setHeader("Access-Control-Max-Age", "3600");
|
||||||
|
response.setHeader(
|
||||||
|
"Access-Control-Allow-Headers",
|
||||||
|
String.join(
|
||||||
|
",",
|
||||||
|
List.of(
|
||||||
|
"Access-Control-Allow-Headers",
|
||||||
|
"Origin",
|
||||||
|
"Accept",
|
||||||
|
"X-Requested-With",
|
||||||
|
"Authorization",
|
||||||
|
"Content-Type",
|
||||||
|
"Access-Control-Request-Method",
|
||||||
|
"Access-Control-Request-Headers")));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
|
||||||
|
throws IOException, ServletException {
|
||||||
|
final HttpServletResponse response = (HttpServletResponse) res;
|
||||||
|
|
||||||
|
setCORSHeaders(response);
|
||||||
|
|
||||||
|
chain.doFilter(req, res);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(FilterConfig filterConfig) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void destroy() {}
|
||||||
|
}
|
|
@ -0,0 +1,92 @@
|
||||||
|
package ch.usi.inf.sa4.sanmarinoes.smarthut.config;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class to interface with `email.*` properties in application.properties. This properties are used
|
||||||
|
* for generating the email to send on password reset or registration
|
||||||
|
*
|
||||||
|
* @see ch.usi.inf.sa4.sanmarinoes.smarthut.controller.UserAccountController
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
@Validated
|
||||||
|
@EnableConfigurationProperties
|
||||||
|
@ConfigurationProperties(prefix = "email")
|
||||||
|
public class EmailConfigurationService {
|
||||||
|
|
||||||
|
/** The email subject for a registration email */
|
||||||
|
@NotNull private String registrationSubject;
|
||||||
|
|
||||||
|
/** The text in the email body preceding the confirmation URL for a registration email */
|
||||||
|
@NotNull private String registration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The URL to follow for registration email confirmation. Has to end with the start of a query
|
||||||
|
* parameter
|
||||||
|
*/
|
||||||
|
@NotNull private String registrationPath;
|
||||||
|
|
||||||
|
/** The email subject for a reset password email */
|
||||||
|
@NotNull private String resetPasswordSubject;
|
||||||
|
|
||||||
|
/** The text in the email body preceding the confirmation URL for a reset password email */
|
||||||
|
@NotNull private String resetPassword;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The URL to follow for password reset email confirmation. Has to end with the start of a query
|
||||||
|
* parameter
|
||||||
|
*/
|
||||||
|
@NotNull private String resetPasswordPath;
|
||||||
|
|
||||||
|
public String getRegistrationSubject() {
|
||||||
|
return registrationSubject;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRegistrationSubject(String registrationSubject) {
|
||||||
|
this.registrationSubject = registrationSubject;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRegistration() {
|
||||||
|
return registration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRegistration(String registration) {
|
||||||
|
this.registration = registration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRegistrationPath() {
|
||||||
|
return registrationPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRegistrationPath(String registrationPath) {
|
||||||
|
this.registrationPath = registrationPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getResetPasswordSubject() {
|
||||||
|
return resetPasswordSubject;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setResetPasswordSubject(String resetPasswordSubject) {
|
||||||
|
this.resetPasswordSubject = resetPasswordSubject;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getResetPassword() {
|
||||||
|
return resetPassword;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setResetPassword(String resetPassword) {
|
||||||
|
this.resetPassword = resetPassword;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getResetPasswordPath() {
|
||||||
|
return resetPasswordPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setResetPasswordPath(String resetPasswordPath) {
|
||||||
|
this.resetPasswordPath = resetPasswordPath;
|
||||||
|
}
|
||||||
|
}
|
|
@ -23,6 +23,7 @@ public class GsonConfig {
|
||||||
private Gson gson() {
|
private Gson gson() {
|
||||||
final GsonBuilder builder = new GsonBuilder();
|
final GsonBuilder builder = new GsonBuilder();
|
||||||
builder.registerTypeAdapter(Json.class, new SpringfoxJsonToGsonAdapter());
|
builder.registerTypeAdapter(Json.class, new SpringfoxJsonToGsonAdapter());
|
||||||
|
builder.addSerializationExclusionStrategy(new AnnotationExclusionStrategy());
|
||||||
return builder.create();
|
return builder.create();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,3 +35,16 @@ class SpringfoxJsonToGsonAdapter implements JsonSerializer<Json> {
|
||||||
return JsonParser.parseString(json.value());
|
return JsonParser.parseString(json.value());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** GSON exclusion strategy to exclude attributes with @GsonExclude */
|
||||||
|
class AnnotationExclusionStrategy implements ExclusionStrategy {
|
||||||
|
@Override
|
||||||
|
public boolean shouldSkipField(FieldAttributes f) {
|
||||||
|
return f.getAnnotation(GsonExclude.class) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean shouldSkipClass(Class<?> clazz) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
package ch.usi.inf.sa4.sanmarinoes.smarthut.config;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(ElementType.FIELD)
|
||||||
|
public @interface GsonExclude {}
|
|
@ -16,6 +16,10 @@ public class JWTAuthenticationEntryPoint implements AuthenticationEntryPoint {
|
||||||
HttpServletResponse response,
|
HttpServletResponse response,
|
||||||
AuthenticationException authException)
|
AuthenticationException authException)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");
|
if (!"OPTIONS".equals(request.getMethod())) {
|
||||||
|
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");
|
||||||
|
} else {
|
||||||
|
CORSFilter.setCORSHeaders(response);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package ch.usi.inf.sa4.sanmarinoes.smarthut.config;
|
package ch.usi.inf.sa4.sanmarinoes.smarthut.config;
|
||||||
|
|
||||||
import static springfox.documentation.builders.PathSelectors.regex;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
@ -8,11 +7,11 @@ import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.ComponentScan;
|
import org.springframework.context.annotation.ComponentScan;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import springfox.documentation.builders.ApiInfoBuilder;
|
import springfox.documentation.builders.ApiInfoBuilder;
|
||||||
|
import springfox.documentation.builders.PathSelectors;
|
||||||
import springfox.documentation.builders.RequestHandlerSelectors;
|
import springfox.documentation.builders.RequestHandlerSelectors;
|
||||||
import springfox.documentation.service.ApiInfo;
|
import springfox.documentation.service.*;
|
||||||
import springfox.documentation.service.ApiKey;
|
|
||||||
import springfox.documentation.service.SecurityScheme;
|
|
||||||
import springfox.documentation.spi.DocumentationType;
|
import springfox.documentation.spi.DocumentationType;
|
||||||
|
import springfox.documentation.spi.service.contexts.SecurityContext;
|
||||||
import springfox.documentation.spring.web.plugins.Docket;
|
import springfox.documentation.spring.web.plugins.Docket;
|
||||||
import springfox.documentation.swagger2.annotations.EnableSwagger2;
|
import springfox.documentation.swagger2.annotations.EnableSwagger2;
|
||||||
|
|
||||||
|
@ -38,7 +37,8 @@ public class SpringFoxConfig {
|
||||||
.paths(paths()::test)
|
.paths(paths()::test)
|
||||||
.build()
|
.build()
|
||||||
.apiInfo(apiInfo())
|
.apiInfo(apiInfo())
|
||||||
.securitySchemes(securitySchemes());
|
.securitySchemes(securitySchemes())
|
||||||
|
.securityContexts(List.of(securityContext()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -50,14 +50,32 @@ public class SpringFoxConfig {
|
||||||
return List.of(new ApiKey("Bearer", "Authorization", "header"));
|
return List.of(new ApiKey("Bearer", "Authorization", "header"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private SecurityContext securityContext() {
|
||||||
* Return a Java functional API predicate for regex matches
|
return SecurityContext.builder()
|
||||||
*
|
.securityReferences(defaultAuth())
|
||||||
* @param regex the regex to match on
|
.forPaths(authenticatedPaths()::test)
|
||||||
* @return a Java functional API predicate
|
.build();
|
||||||
*/
|
}
|
||||||
private Predicate<String> regexPredicate(final String regex) {
|
|
||||||
return regex(regex)::apply;
|
private List<SecurityReference> defaultAuth() {
|
||||||
|
final AuthorizationScope authorizationScope =
|
||||||
|
new AuthorizationScope("global", "accessEverything");
|
||||||
|
return List.of(
|
||||||
|
new SecurityReference("Bearer", new AuthorizationScope[] {authorizationScope}));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Predicate<String> authenticatedPaths() {
|
||||||
|
return ((Predicate<String>) PathSelectors.regex("/auth/update")::apply)
|
||||||
|
.or(PathSelectors.regex("/room.*")::apply)
|
||||||
|
.or(PathSelectors.regex("/device.*")::apply)
|
||||||
|
.or(PathSelectors.regex("/buttonDimmer.*")::apply)
|
||||||
|
.or(PathSelectors.regex("/dimmableLight.*")::apply)
|
||||||
|
.or(PathSelectors.regex("/knobDimmer.*")::apply)
|
||||||
|
.or(PathSelectors.regex("/regularLight.*")::apply)
|
||||||
|
.or(PathSelectors.regex("/sensor.*")::apply)
|
||||||
|
.or(PathSelectors.regex("/smartPlug.*")::apply)
|
||||||
|
.or(PathSelectors.regex("/switch.*")::apply)
|
||||||
|
.or(PathSelectors.regex("/motionSensor.*")::apply);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -67,9 +85,7 @@ 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.*")
|
return PathSelectors.any()::apply;
|
||||||
.or(regexPredicate("/room.*"))
|
|
||||||
.or(regexPredicate("/register.*"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -52,10 +52,11 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||||
.authorizeRequests()
|
.authorizeRequests()
|
||||||
.antMatchers(
|
.antMatchers(
|
||||||
"/auth/login",
|
"/auth/login",
|
||||||
"/auth/register",
|
|
||||||
"/swagger-ui.html",
|
"/swagger-ui.html",
|
||||||
"/register",
|
"/register",
|
||||||
"/register/confirm-account",
|
"/register/confirm-account",
|
||||||
|
"/register/init-reset-password",
|
||||||
|
"/register/reset-password",
|
||||||
"/v2/api-docs",
|
"/v2/api-docs",
|
||||||
"/webjars/**",
|
"/webjars/**",
|
||||||
"/swagger-resources/**",
|
"/swagger-resources/**",
|
||||||
|
|
|
@ -4,6 +4,8 @@ import ch.usi.inf.sa4.sanmarinoes.smarthut.config.JWTTokenUtil;
|
||||||
import ch.usi.inf.sa4.sanmarinoes.smarthut.dto.JWTRequest;
|
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.error.UnauthorizedException;
|
||||||
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.error.UserNotFoundException;
|
||||||
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.*;
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.*;
|
||||||
import io.swagger.annotations.Authorization;
|
import io.swagger.annotations.Authorization;
|
||||||
import java.security.Principal;
|
import java.security.Principal;
|
||||||
|
@ -17,7 +19,6 @@ import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@CrossOrigin
|
|
||||||
@RequestMapping("/auth")
|
@RequestMapping("/auth")
|
||||||
public class AuthenticationController {
|
public class AuthenticationController {
|
||||||
|
|
||||||
|
@ -35,8 +36,7 @@ public class AuthenticationController {
|
||||||
AuthenticationManager authenticationManager,
|
AuthenticationManager authenticationManager,
|
||||||
UserRepository userRepository,
|
UserRepository userRepository,
|
||||||
JWTTokenUtil jwtTokenUtil,
|
JWTTokenUtil jwtTokenUtil,
|
||||||
JWTUserDetailsService userDetailsService,
|
JWTUserDetailsService userDetailsService) {
|
||||||
UserRepository users) {
|
|
||||||
this.authenticationManager = authenticationManager;
|
this.authenticationManager = authenticationManager;
|
||||||
this.userRepository = userRepository;
|
this.userRepository = userRepository;
|
||||||
this.jwtTokenUtil = jwtTokenUtil;
|
this.jwtTokenUtil = jwtTokenUtil;
|
||||||
|
@ -44,10 +44,30 @@ public class AuthenticationController {
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/login")
|
@PostMapping("/login")
|
||||||
public JWTResponse login(@RequestBody JWTRequest authenticationRequest) throws Exception {
|
public JWTResponse login(@Valid @RequestBody JWTRequest authenticationRequest)
|
||||||
authenticate(authenticationRequest.getUsername(), authenticationRequest.getPassword());
|
throws UnauthorizedException, UserNotFoundException {
|
||||||
final UserDetails userDetails =
|
final UserDetails userDetails;
|
||||||
userDetailsService.loadUserByUsername(authenticationRequest.getUsername());
|
if (authenticationRequest.getUsernameOrEmail().contains("@")) {
|
||||||
|
// usernameOrEmail contains an email, so fetch the corresponding username
|
||||||
|
final User user =
|
||||||
|
userRepository.findByEmailIgnoreCase(
|
||||||
|
authenticationRequest.getUsernameOrEmail());
|
||||||
|
if (user == null) {
|
||||||
|
throw new UserNotFoundException();
|
||||||
|
}
|
||||||
|
|
||||||
|
authenticate(user.getUsername(), authenticationRequest.getPassword());
|
||||||
|
userDetails = userDetailsService.loadUserByUsername(user.getUsername());
|
||||||
|
} else {
|
||||||
|
// usernameOrEmail contains a username, authenticate with that then
|
||||||
|
authenticate(
|
||||||
|
authenticationRequest.getUsernameOrEmail(),
|
||||||
|
authenticationRequest.getPassword());
|
||||||
|
userDetails =
|
||||||
|
userDetailsService.loadUserByUsername(
|
||||||
|
authenticationRequest.getUsernameOrEmail());
|
||||||
|
}
|
||||||
|
|
||||||
final String token = jwtTokenUtil.generateToken(userDetails);
|
final String token = jwtTokenUtil.generateToken(userDetails);
|
||||||
return new JWTResponse(token);
|
return new JWTResponse(token);
|
||||||
}
|
}
|
||||||
|
@ -67,16 +87,14 @@ public class AuthenticationController {
|
||||||
return userRepository.save(oldUser);
|
return userRepository.save(oldUser);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void authenticate(String username, String password) throws Exception {
|
private void authenticate(String username, String password) throws UnauthorizedException {
|
||||||
try {
|
try {
|
||||||
authenticationManager.authenticate(
|
authenticationManager.authenticate(
|
||||||
new UsernamePasswordAuthenticationToken(username, password));
|
new UsernamePasswordAuthenticationToken(username, password));
|
||||||
} catch (DisabledException e) {
|
} catch (DisabledException e) {
|
||||||
e.printStackTrace();
|
throw new UnauthorizedException(true);
|
||||||
throw new Exception("USER_DISABLED", e);
|
|
||||||
} catch (BadCredentialsException e) {
|
} catch (BadCredentialsException e) {
|
||||||
e.printStackTrace();
|
throw new UnauthorizedException(false);
|
||||||
throw new Exception("INVALID_CREDENTIALS", e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,11 +2,12 @@ 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.dto.ButtonDimmerDimRequest;
|
||||||
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.ButtonDimmer;
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.dto.GenericDeviceSaveReguest;
|
||||||
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.ButtonDimmerRepository;
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.error.NotFoundException;
|
||||||
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.*;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Set;
|
||||||
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;
|
||||||
|
@ -15,37 +16,77 @@ import org.springframework.web.bind.annotation.*;
|
||||||
@RestController
|
@RestController
|
||||||
@EnableAutoConfiguration
|
@EnableAutoConfiguration
|
||||||
@RequestMapping("/buttonDimmer")
|
@RequestMapping("/buttonDimmer")
|
||||||
public class ButtonDimmerController {
|
public class ButtonDimmerController
|
||||||
@Autowired private ButtonDimmerRepository buttonDimmerService;
|
extends InputDeviceConnectionController<ButtonDimmer, DimmableLight> {
|
||||||
|
private ButtonDimmerRepository buttonDimmerRepository;
|
||||||
|
private DimmableLightRepository dimmableLightRepository;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
protected ButtonDimmerController(
|
||||||
|
ButtonDimmerRepository inputRepository, DimmableLightRepository outputRepository) {
|
||||||
|
super(
|
||||||
|
inputRepository,
|
||||||
|
outputRepository,
|
||||||
|
DimmableLight.BUTTON_DIMMER_DIMMABLE_LIGHT_CONNECTOR);
|
||||||
|
this.buttonDimmerRepository = inputRepository;
|
||||||
|
this.dimmableLightRepository = outputRepository;
|
||||||
|
}
|
||||||
|
|
||||||
@GetMapping
|
@GetMapping
|
||||||
public List<ButtonDimmer> findAll() {
|
public List<ButtonDimmer> findAll() {
|
||||||
return toList(buttonDimmerService.findAll());
|
return toList(buttonDimmerRepository.findAll());
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/{id}")
|
@GetMapping("/{id}")
|
||||||
public Optional<ButtonDimmer> findById(@PathVariable("id") long id) {
|
public ButtonDimmer findById(@PathVariable("id") long id) throws NotFoundException {
|
||||||
return buttonDimmerService.findById(id);
|
return buttonDimmerRepository.findById(id).orElseThrow(NotFoundException::new);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping
|
@PostMapping
|
||||||
public ButtonDimmer create(@Valid @RequestBody final ButtonDimmerSaveRequest bd) {
|
public ButtonDimmer create(@Valid @RequestBody final GenericDeviceSaveReguest bd) {
|
||||||
ButtonDimmer newBD = new ButtonDimmer();
|
ButtonDimmer newBD = new ButtonDimmer();
|
||||||
newBD.setLights(bd.getLights());
|
|
||||||
newBD.setId(bd.getId());
|
|
||||||
newBD.setName(bd.getName());
|
newBD.setName(bd.getName());
|
||||||
newBD.setRoomId(bd.getRoomId());
|
newBD.setRoomId(bd.getRoomId());
|
||||||
|
|
||||||
return buttonDimmerService.save(newBD);
|
return buttonDimmerRepository.save(newBD);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PutMapping
|
@PutMapping("/dim")
|
||||||
public ButtonDimmer update(@Valid @RequestBody ButtonDimmerSaveRequest bd) {
|
public Set<DimmableLight> dim(@Valid @RequestBody final ButtonDimmerDimRequest bd)
|
||||||
return this.create(bd);
|
throws NotFoundException {
|
||||||
|
final ButtonDimmer buttonDimmer =
|
||||||
|
buttonDimmerRepository.findById(bd.getId()).orElseThrow(NotFoundException::new);
|
||||||
|
|
||||||
|
switch (bd.getDimType()) {
|
||||||
|
case UP:
|
||||||
|
buttonDimmer.increaseIntensity();
|
||||||
|
break;
|
||||||
|
case DOWN:
|
||||||
|
buttonDimmer.decreaseIntensity();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
dimmableLightRepository.saveAll(buttonDimmer.getOutputs());
|
||||||
|
|
||||||
|
return buttonDimmer.getOutputs();
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/{id}/lights")
|
||||||
|
public Set<? extends OutputDevice> addLight(
|
||||||
|
@PathVariable("id") long inputId, @RequestParam("lightId") Long lightId)
|
||||||
|
throws NotFoundException {
|
||||||
|
return addOutput(inputId, lightId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@DeleteMapping("/{id}/lights")
|
||||||
|
public Set<? extends OutputDevice> removeLight(
|
||||||
|
@PathVariable("id") long inputId, @RequestParam("lightId") Long lightId)
|
||||||
|
throws NotFoundException {
|
||||||
|
return removeOutput(inputId, lightId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@DeleteMapping("/{id}")
|
@DeleteMapping("/{id}")
|
||||||
public void delete(@PathVariable("id") long id) {
|
public void delete(@PathVariable("id") long id) {
|
||||||
buttonDimmerService.deleteById(id);
|
buttonDimmerRepository.deleteById(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
package ch.usi.inf.sa4.sanmarinoes.smarthut.controller;
|
||||||
|
|
||||||
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.dto.DeviceSaveRequest;
|
||||||
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.error.BadDataException;
|
||||||
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.error.NotFoundException;
|
||||||
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.Device;
|
||||||
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.DeviceRepository;
|
||||||
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.RoomRepository;
|
||||||
|
import javax.validation.Valid;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||||
|
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
|
||||||
|
@EnableAutoConfiguration
|
||||||
|
@RequestMapping("/device")
|
||||||
|
public class DeviceController {
|
||||||
|
|
||||||
|
@Autowired private DeviceRepository<Device> deviceRepository;
|
||||||
|
@Autowired private RoomRepository roomRepository;
|
||||||
|
|
||||||
|
@PutMapping
|
||||||
|
public Device update(@Valid @RequestBody DeviceSaveRequest deviceSaveRequest)
|
||||||
|
throws NotFoundException, BadDataException {
|
||||||
|
final Device d =
|
||||||
|
deviceRepository
|
||||||
|
.findById(deviceSaveRequest.getId())
|
||||||
|
.orElseThrow(NotFoundException::new);
|
||||||
|
|
||||||
|
// check if roomId is valid
|
||||||
|
roomRepository
|
||||||
|
.findById(deviceSaveRequest.getRoomId())
|
||||||
|
.orElseThrow(() -> new BadDataException("roomId is not a valid room id"));
|
||||||
|
|
||||||
|
d.setRoomId(deviceSaveRequest.getRoomId());
|
||||||
|
d.setName(deviceSaveRequest.getName());
|
||||||
|
|
||||||
|
deviceRepository.save(d);
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,10 +3,10 @@ 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.dto.DimmableLightSaveRequest;
|
||||||
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.error.NotFoundException;
|
||||||
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;
|
||||||
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;
|
||||||
|
@ -25,24 +25,28 @@ public class DimmableLightController {
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/{id}")
|
@GetMapping("/{id}")
|
||||||
public Optional<DimmableLight> findById(@PathVariable("id") long id) {
|
public DimmableLight findById(@PathVariable("id") long id) throws NotFoundException {
|
||||||
return dimmableLightService.findById(id);
|
return dimmableLightService.findById(id).orElseThrow(NotFoundException::new);
|
||||||
|
}
|
||||||
|
|
||||||
|
private DimmableLight save(DimmableLight initial, DimmableLightSaveRequest dl) {
|
||||||
|
initial.setIntensity(dl.getIntensity());
|
||||||
|
initial.setName(dl.getName());
|
||||||
|
initial.setRoomId(dl.getRoomId());
|
||||||
|
|
||||||
|
return dimmableLightService.save(initial);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping
|
@PostMapping
|
||||||
public DimmableLight create(@Valid @RequestBody DimmableLightSaveRequest dl) {
|
public DimmableLight create(@Valid @RequestBody DimmableLightSaveRequest dl) {
|
||||||
DimmableLight newDL = new DimmableLight();
|
return save(new DimmableLight(), dl);
|
||||||
newDL.setIntensity(dl.getIntensity());
|
|
||||||
newDL.setId(dl.getId());
|
|
||||||
newDL.setName(dl.getName());
|
|
||||||
newDL.setRoomId(dl.getRoomId());
|
|
||||||
|
|
||||||
return dimmableLightService.save(newDL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@PutMapping
|
@PutMapping
|
||||||
public DimmableLight update(@Valid @RequestBody DimmableLightSaveRequest dl) {
|
public DimmableLight update(@Valid @RequestBody DimmableLightSaveRequest sp)
|
||||||
return this.create(dl);
|
throws NotFoundException {
|
||||||
|
return save(
|
||||||
|
dimmableLightService.findById(sp.getId()).orElseThrow(NotFoundException::new), sp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@DeleteMapping("/{id}")
|
@DeleteMapping("/{id}")
|
||||||
|
|
|
@ -0,0 +1,92 @@
|
||||||
|
package ch.usi.inf.sa4.sanmarinoes.smarthut.controller;
|
||||||
|
|
||||||
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.error.NotFoundException;
|
||||||
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.*;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An abstract controller for an input device that has output connected to it. Aids to create the
|
||||||
|
* output add and output remove route
|
||||||
|
*
|
||||||
|
* @param <I> the type of device this controller is for
|
||||||
|
* @param <O> the output device attached to I
|
||||||
|
*/
|
||||||
|
public abstract class InputDeviceConnectionController<
|
||||||
|
I extends InputDevice, O extends OutputDevice> {
|
||||||
|
|
||||||
|
private class IOPair {
|
||||||
|
private final I input;
|
||||||
|
private final O output;
|
||||||
|
|
||||||
|
private IOPair(I input, O output) {
|
||||||
|
this.input = input;
|
||||||
|
this.output = output;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private DeviceRepository<I> inputRepository;
|
||||||
|
|
||||||
|
private DeviceRepository<O> outputReposiory;
|
||||||
|
|
||||||
|
private Connector<I, O> connector;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contstructs the controller by requiring essential object for the controller implementation
|
||||||
|
*
|
||||||
|
* @param inputRepository the input device repository
|
||||||
|
* @param outputRepository the output device repository
|
||||||
|
* @param connector a appropriate Connector instance for the I and O tyoes.
|
||||||
|
*/
|
||||||
|
protected InputDeviceConnectionController(
|
||||||
|
DeviceRepository<I> inputRepository,
|
||||||
|
DeviceRepository<O> outputRepository,
|
||||||
|
Connector<I, O> connector) {
|
||||||
|
this.inputRepository = inputRepository;
|
||||||
|
this.outputReposiory = outputRepository;
|
||||||
|
this.connector = connector;
|
||||||
|
}
|
||||||
|
|
||||||
|
private IOPair checkConnectionIDs(Long inputId, Long outputId) throws NotFoundException {
|
||||||
|
final I input =
|
||||||
|
inputRepository
|
||||||
|
.findById(inputId)
|
||||||
|
.orElseThrow(() -> new NotFoundException("input device"));
|
||||||
|
final O output =
|
||||||
|
outputReposiory
|
||||||
|
.findById(outputId)
|
||||||
|
.orElseThrow(() -> new NotFoundException("output device"));
|
||||||
|
return new IOPair(input, output);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements the output device connection creation (add) route
|
||||||
|
*
|
||||||
|
* @param inputId input device id
|
||||||
|
* @param outputId output device id
|
||||||
|
* @return the list of output devices attached to the input device of id inputId
|
||||||
|
* @throws NotFoundException if inputId or outputId are not valid
|
||||||
|
*/
|
||||||
|
protected Set<? extends OutputDevice> addOutput(Long inputId, Long outputId)
|
||||||
|
throws NotFoundException {
|
||||||
|
final IOPair pair = checkConnectionIDs(inputId, outputId);
|
||||||
|
connector.connect(pair.input, pair.output, true);
|
||||||
|
outputReposiory.save(pair.output);
|
||||||
|
return pair.input.getOutputs();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements the output device connection destruction (remove) route
|
||||||
|
*
|
||||||
|
* @param inputId input device id
|
||||||
|
* @param outputId output device id
|
||||||
|
* @return the list of output devices attached to the input device of id inputId
|
||||||
|
* @throws NotFoundException if inputId or outputId are not valid
|
||||||
|
*/
|
||||||
|
protected Set<? extends OutputDevice> removeOutput(Long inputId, Long outputId)
|
||||||
|
throws NotFoundException {
|
||||||
|
final IOPair pair = checkConnectionIDs(inputId, outputId);
|
||||||
|
connector.connect(pair.input, pair.output, false);
|
||||||
|
outputReposiory.save(pair.output);
|
||||||
|
return pair.input.getOutputs();
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,11 +2,12 @@ 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.dto.GenericDeviceSaveReguest;
|
||||||
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.KnobDimmer;
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.dto.KnobDimmerDimRequest;
|
||||||
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.KnobDimmerRepository;
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.error.NotFoundException;
|
||||||
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.*;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Set;
|
||||||
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;
|
||||||
|
@ -15,38 +16,70 @@ import org.springframework.web.bind.annotation.*;
|
||||||
@RestController
|
@RestController
|
||||||
@EnableAutoConfiguration
|
@EnableAutoConfiguration
|
||||||
@RequestMapping("/knobDimmer")
|
@RequestMapping("/knobDimmer")
|
||||||
public class KnobDimmerController {
|
public class KnobDimmerController
|
||||||
|
extends InputDeviceConnectionController<KnobDimmer, DimmableLight> {
|
||||||
|
|
||||||
@Autowired private KnobDimmerRepository knobDimmerService;
|
@Autowired private KnobDimmerRepository knobDimmerRepository;
|
||||||
|
@Autowired private DimmableLightRepository dimmableLightRepository;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
protected KnobDimmerController(
|
||||||
|
KnobDimmerRepository inputRepository, DimmableLightRepository outputRepository) {
|
||||||
|
super(
|
||||||
|
inputRepository,
|
||||||
|
outputRepository,
|
||||||
|
DimmableLight.KNOB_DIMMER_DIMMABLE_LIGHT_CONNECTOR);
|
||||||
|
this.knobDimmerRepository = inputRepository;
|
||||||
|
this.dimmableLightRepository = outputRepository;
|
||||||
|
}
|
||||||
|
|
||||||
@GetMapping
|
@GetMapping
|
||||||
public List<KnobDimmer> findAll() {
|
public List<KnobDimmer> findAll() {
|
||||||
return toList(knobDimmerService.findAll());
|
return toList(knobDimmerRepository.findAll());
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/{id}")
|
@GetMapping("/{id}")
|
||||||
public Optional<KnobDimmer> findById(@PathVariable("id") long id) {
|
public KnobDimmer findById(@PathVariable("id") long id) throws NotFoundException {
|
||||||
return knobDimmerService.findById(id);
|
return knobDimmerRepository.findById(id).orElseThrow(NotFoundException::new);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping
|
@PostMapping
|
||||||
public KnobDimmer create(@Valid @RequestBody KnobDimmerSaveRequest kd) {
|
public KnobDimmer create(@Valid @RequestBody GenericDeviceSaveReguest kd) {
|
||||||
KnobDimmer newKD = new KnobDimmer();
|
KnobDimmer newKD = new KnobDimmer();
|
||||||
newKD.setLights(kd.getLights());
|
|
||||||
newKD.setId(kd.getId());
|
|
||||||
newKD.setName(kd.getName());
|
newKD.setName(kd.getName());
|
||||||
newKD.setRoomId(kd.getRoomId());
|
newKD.setRoomId(kd.getRoomId());
|
||||||
|
|
||||||
return knobDimmerService.save(newKD);
|
return knobDimmerRepository.save(newKD);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PutMapping
|
@PutMapping("/dimTo")
|
||||||
public KnobDimmer update(@Valid @RequestBody KnobDimmerSaveRequest kd) {
|
public Set<DimmableLight> dimTo(@Valid @RequestBody final KnobDimmerDimRequest bd)
|
||||||
return this.create(kd);
|
throws NotFoundException {
|
||||||
|
final KnobDimmer dimmer =
|
||||||
|
knobDimmerRepository.findById(bd.getId()).orElseThrow(NotFoundException::new);
|
||||||
|
|
||||||
|
dimmer.setLightIntensity(bd.getIntensity());
|
||||||
|
dimmableLightRepository.saveAll(dimmer.getOutputs());
|
||||||
|
|
||||||
|
return dimmer.getOutputs();
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/{id}/lights")
|
||||||
|
public Set<? extends OutputDevice> addLight(
|
||||||
|
@PathVariable("id") long inputId, @RequestParam("lightId") Long lightId)
|
||||||
|
throws NotFoundException {
|
||||||
|
return addOutput(inputId, lightId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@DeleteMapping("/{id}/lights")
|
||||||
|
public Set<? extends OutputDevice> removeLight(
|
||||||
|
@PathVariable("id") long inputId, @RequestParam("lightId") Long lightId)
|
||||||
|
throws NotFoundException {
|
||||||
|
return removeOutput(inputId, lightId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@DeleteMapping("/{id}")
|
@DeleteMapping("/{id}")
|
||||||
public void delete(@PathVariable("id") long id) {
|
public void delete(@PathVariable("id") long id) {
|
||||||
knobDimmerService.deleteById(id);
|
knobDimmerRepository.deleteById(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,11 +2,11 @@ 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.dto.GenericDeviceSaveReguest;
|
||||||
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.error.NotFoundException;
|
||||||
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;
|
||||||
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;
|
||||||
|
@ -25,26 +25,19 @@ public class MotionSensorController {
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/{id}")
|
@GetMapping("/{id}")
|
||||||
public Optional<MotionSensor> findById(@PathVariable("id") long id) {
|
public MotionSensor findById(@PathVariable("id") long id) throws NotFoundException {
|
||||||
return motionSensorService.findById(id);
|
return motionSensorService.findById(id).orElseThrow(NotFoundException::new);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping
|
@PostMapping
|
||||||
public MotionSensor create(@Valid @RequestBody MotionSensorSaveRequest ms) {
|
public MotionSensor create(@Valid @RequestBody GenericDeviceSaveReguest ms) {
|
||||||
MotionSensor newMS = new MotionSensor();
|
MotionSensor newMS = new MotionSensor();
|
||||||
newMS.setDetected(ms.isDetected());
|
|
||||||
newMS.setId(ms.getId());
|
|
||||||
newMS.setName(ms.getName());
|
newMS.setName(ms.getName());
|
||||||
newMS.setRoomId(ms.getRoomId());
|
newMS.setRoomId(ms.getRoomId());
|
||||||
|
|
||||||
return motionSensorService.save(newMS);
|
return motionSensorService.save(newMS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PutMapping
|
|
||||||
public MotionSensor update(@Valid @RequestBody MotionSensorSaveRequest ms) {
|
|
||||||
return this.create(ms);
|
|
||||||
}
|
|
||||||
|
|
||||||
@DeleteMapping("/{id}")
|
@DeleteMapping("/{id}")
|
||||||
public void delete(@PathVariable("id") long id) {
|
public void delete(@PathVariable("id") long id) {
|
||||||
motionSensorService.deleteById(id);
|
motionSensorService.deleteById(id);
|
||||||
|
|
|
@ -3,10 +3,10 @@ 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.dto.RegularLightSaveRequest;
|
||||||
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.error.NotFoundException;
|
||||||
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;
|
||||||
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;
|
||||||
|
@ -32,14 +32,11 @@ public class RegularLightController {
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/{id}")
|
@GetMapping("/{id}")
|
||||||
public Optional<RegularLight> findById(@PathVariable("id") long id) {
|
public RegularLight findById(@PathVariable("id") long id) throws NotFoundException {
|
||||||
return regularLightService.findById(id);
|
return regularLightService.findById(id).orElseThrow(NotFoundException::new);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping
|
private RegularLight save(RegularLight newRL, RegularLightSaveRequest rl) {
|
||||||
public RegularLight create(@Valid @RequestBody RegularLightSaveRequest rl) {
|
|
||||||
RegularLight newRL = new RegularLight();
|
|
||||||
newRL.setId(rl.getId());
|
|
||||||
newRL.setName(rl.getName());
|
newRL.setName(rl.getName());
|
||||||
newRL.setRoomId(rl.getRoomId());
|
newRL.setRoomId(rl.getRoomId());
|
||||||
newRL.setOn(rl.isOn());
|
newRL.setOn(rl.isOn());
|
||||||
|
@ -47,9 +44,16 @@ public class RegularLightController {
|
||||||
return regularLightService.save(newRL);
|
return regularLightService.save(newRL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PostMapping
|
||||||
|
public RegularLight create(@Valid @RequestBody RegularLightSaveRequest rl) {
|
||||||
|
return save(new RegularLight(), rl);
|
||||||
|
}
|
||||||
|
|
||||||
@PutMapping
|
@PutMapping
|
||||||
public RegularLight update(@Valid @RequestBody RegularLightSaveRequest rl) {
|
public RegularLight update(@Valid @RequestBody RegularLightSaveRequest rl)
|
||||||
return this.create(rl);
|
throws NotFoundException {
|
||||||
|
return save(
|
||||||
|
regularLightService.findById(rl.getId()).orElseThrow(NotFoundException::new), rl);
|
||||||
}
|
}
|
||||||
|
|
||||||
@DeleteMapping("/{id}")
|
@DeleteMapping("/{id}")
|
||||||
|
|
|
@ -3,13 +3,13 @@ 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.RoomSaveRequest;
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.dto.RoomSaveRequest;
|
||||||
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.error.NotFoundException;
|
||||||
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.*;
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.*;
|
||||||
import java.security.Principal;
|
import java.security.Principal;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
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.*;
|
import org.springframework.boot.autoconfigure.*;
|
||||||
import org.springframework.security.core.userdetails.UserDetails;
|
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
|
@ -29,26 +29,27 @@ public class RoomController {
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/{id}")
|
@GetMapping("/{id}")
|
||||||
public @ResponseBody Optional<Room> findById(@PathVariable("id") long id) {
|
public @ResponseBody Room findById(@PathVariable("id") long id) throws NotFoundException {
|
||||||
return roomRepository.findById(id);
|
return roomRepository.findById(id).orElseThrow(NotFoundException::new);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Room save(final RoomSaveRequest r, final Principal principal, boolean setWhenNull) {
|
private Room save(final RoomSaveRequest r, final Principal principal, boolean setWhenNull) {
|
||||||
Room newRoom = new Room();
|
Room newRoom = new Room();
|
||||||
|
|
||||||
final String username = ((UserDetails) principal).getUsername();
|
final String username = principal.getName();
|
||||||
final Long userId = userRepository.findByUsername(username).getId();
|
final Long userId = userRepository.findByUsername(username).getId();
|
||||||
final String img = r.getImage();
|
final String img = r.getImage();
|
||||||
final String icon = r.getIcon();
|
final Room.Icon icon = r.getIcon();
|
||||||
|
|
||||||
newRoom.setUserId(userId);
|
newRoom.setUserId(userId);
|
||||||
|
newRoom.setName(r.getName());
|
||||||
if (img != null) {
|
if (img != null) {
|
||||||
newRoom.setImage(img.getBytes());
|
newRoom.setImage(img);
|
||||||
} else if (setWhenNull) {
|
} else if (setWhenNull) {
|
||||||
newRoom.setImage(null);
|
newRoom.setImage(null);
|
||||||
}
|
}
|
||||||
if (icon != null) {
|
if (icon != null) {
|
||||||
newRoom.setIcon(icon.getBytes());
|
newRoom.setIcon(icon);
|
||||||
} else if (setWhenNull) {
|
} else if (setWhenNull) {
|
||||||
newRoom.setIcon(null);
|
newRoom.setIcon(null);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,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.dto.SensorSaveRequest;
|
||||||
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.error.NotFoundException;
|
||||||
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;
|
||||||
|
@ -24,27 +25,20 @@ public class SensorController {
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/{id}")
|
@GetMapping("/{id}")
|
||||||
public Optional<Sensor> findById(@PathVariable("id") long id) {
|
public Sensor findById(@PathVariable("id") long id) throws NotFoundException {
|
||||||
return sensorRepository.findById(id);
|
return sensorRepository.findById(id).orElseThrow(NotFoundException::new);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping
|
@PostMapping
|
||||||
public Sensor create(@Valid @RequestBody SensorSaveRequest s) {
|
public Sensor create(@Valid @RequestBody SensorSaveRequest s) {
|
||||||
Sensor newSensor = new Sensor();
|
Sensor newSensor = new Sensor();
|
||||||
newSensor.setSensor(s.getSensor());
|
newSensor.setSensor(s.getSensor());
|
||||||
newSensor.setValue(s.getValue());
|
|
||||||
newSensor.setId(s.getId());
|
|
||||||
newSensor.setName(s.getName());
|
newSensor.setName(s.getName());
|
||||||
newSensor.setRoomId(s.getRoomId());
|
newSensor.setRoomId(s.getRoomId());
|
||||||
|
|
||||||
return sensorRepository.save(newSensor);
|
return sensorRepository.save(newSensor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PutMapping
|
|
||||||
public Sensor update(@Valid @RequestBody SensorSaveRequest s) {
|
|
||||||
return this.create(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
@DeleteMapping("/{id}")
|
@DeleteMapping("/{id}")
|
||||||
public void deleteById(@PathVariable("id") long id) {
|
public void deleteById(@PathVariable("id") long id) {
|
||||||
sensorRepository.deleteById(id);
|
sensorRepository.deleteById(id);
|
||||||
|
|
|
@ -3,6 +3,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.dto.SmartPlugSaveRequest;
|
||||||
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.error.NotFoundException;
|
||||||
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;
|
||||||
|
@ -24,13 +25,11 @@ public class SmartPlugController {
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/{id}")
|
@GetMapping("/{id}")
|
||||||
public Optional<SmartPlug> findById(@PathVariable("id") long id) {
|
public SmartPlug findById(@PathVariable("id") long id) throws NotFoundException {
|
||||||
return smartPlugRepository.findById(id);
|
return smartPlugRepository.findById(id).orElseThrow(NotFoundException::new);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping
|
private SmartPlug save(SmartPlug newSP, SmartPlugSaveRequest sp) {
|
||||||
public SmartPlug create(@Valid @RequestBody SmartPlugSaveRequest sp) {
|
|
||||||
SmartPlug newSP = new SmartPlug();
|
|
||||||
newSP.setOn(sp.isOn());
|
newSP.setOn(sp.isOn());
|
||||||
newSP.setId(sp.getId());
|
newSP.setId(sp.getId());
|
||||||
newSP.setName(sp.getName());
|
newSP.setName(sp.getName());
|
||||||
|
@ -39,9 +38,15 @@ public class SmartPlugController {
|
||||||
return smartPlugRepository.save(newSP);
|
return smartPlugRepository.save(newSP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PostMapping
|
||||||
|
public SmartPlug create(@Valid @RequestBody SmartPlugSaveRequest sp) {
|
||||||
|
return save(new SmartPlug(), sp);
|
||||||
|
}
|
||||||
|
|
||||||
@PutMapping
|
@PutMapping
|
||||||
public SmartPlug update(@Valid @RequestBody SmartPlugSaveRequest sp) {
|
public SmartPlug update(@Valid @RequestBody SmartPlugSaveRequest sp) throws NotFoundException {
|
||||||
return this.create(sp);
|
return save(
|
||||||
|
smartPlugRepository.findById(sp.getId()).orElseThrow(NotFoundException::new), sp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@DeleteMapping("/{id}")
|
@DeleteMapping("/{id}")
|
||||||
|
|
|
@ -2,7 +2,9 @@ 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.dto.GenericDeviceSaveReguest;
|
||||||
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.dto.SwitchOperationRequest;
|
||||||
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.error.NotFoundException;
|
||||||
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;
|
||||||
|
@ -14,9 +16,24 @@ import org.springframework.web.bind.annotation.*;
|
||||||
@RestController
|
@RestController
|
||||||
@EnableAutoConfiguration
|
@EnableAutoConfiguration
|
||||||
@RequestMapping("/switch")
|
@RequestMapping("/switch")
|
||||||
public class SwitchController {
|
public class SwitchController extends InputDeviceConnectionController<Switch, Switchable> {
|
||||||
|
|
||||||
@Autowired private SwitchRepository switchRepository;
|
private SwitchRepository switchRepository;
|
||||||
|
private SwitchableRepository<Switchable> switchableRepository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contstructs the controller by requiring essential object for the controller implementation
|
||||||
|
*
|
||||||
|
* @param inputRepository the input device repository
|
||||||
|
* @param outputRepository the output device repository
|
||||||
|
*/
|
||||||
|
@Autowired
|
||||||
|
protected SwitchController(
|
||||||
|
SwitchRepository inputRepository, SwitchableRepository<Switchable> outputRepository) {
|
||||||
|
super(inputRepository, outputRepository, Switchable.SWITCH_SWITCHABLE_CONNECTOR);
|
||||||
|
this.switchRepository = inputRepository;
|
||||||
|
this.switchableRepository = outputRepository;
|
||||||
|
}
|
||||||
|
|
||||||
@GetMapping
|
@GetMapping
|
||||||
public List<Switch> findAll() {
|
public List<Switch> findAll() {
|
||||||
|
@ -24,24 +41,53 @@ public class SwitchController {
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/{id}")
|
@GetMapping("/{id}")
|
||||||
public Optional<Switch> findById(@PathVariable("id") long id) {
|
public Switch findById(@PathVariable("id") long id) throws NotFoundException {
|
||||||
return switchRepository.findById(id);
|
return switchRepository.findById(id).orElseThrow(NotFoundException::new);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping
|
@PostMapping
|
||||||
public Switch create(@Valid @RequestBody SwitchSaveRequest s) {
|
public Switch create(@Valid @RequestBody GenericDeviceSaveReguest s) {
|
||||||
Switch newSwitch = new Switch();
|
Switch newSwitch = new Switch();
|
||||||
newSwitch.setId(s.getId());
|
|
||||||
newSwitch.setName(s.getName());
|
newSwitch.setName(s.getName());
|
||||||
newSwitch.setRoomId(s.getRoomId());
|
newSwitch.setRoomId(s.getRoomId());
|
||||||
newSwitch.setOn(s.isOn());
|
|
||||||
|
|
||||||
return switchRepository.save(newSwitch);
|
return switchRepository.save(newSwitch);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PutMapping
|
@PutMapping("/operate")
|
||||||
public Switch update(@Valid @RequestBody SwitchSaveRequest s) {
|
public Set<Switchable> operate(@Valid @RequestBody final SwitchOperationRequest sr)
|
||||||
return this.create(s);
|
throws NotFoundException {
|
||||||
|
final Switch s = switchRepository.findById(sr.getId()).orElseThrow(NotFoundException::new);
|
||||||
|
|
||||||
|
switch (sr.getType()) {
|
||||||
|
case ON:
|
||||||
|
s.setOn(true);
|
||||||
|
break;
|
||||||
|
case OFF:
|
||||||
|
s.setOn(false);
|
||||||
|
break;
|
||||||
|
case TOGGLE:
|
||||||
|
s.toggle();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switchableRepository.saveAll(s.getOutputs());
|
||||||
|
|
||||||
|
return s.getOutputs();
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/{id}/lights")
|
||||||
|
public Set<? extends OutputDevice> addSwitchable(
|
||||||
|
@PathVariable("id") long inputId, @RequestParam("switchableId") Long switchableId)
|
||||||
|
throws NotFoundException {
|
||||||
|
return addOutput(inputId, switchableId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@DeleteMapping("/{id}/lights")
|
||||||
|
public Set<? extends OutputDevice> removeSwitchable(
|
||||||
|
@PathVariable("id") long inputId, @RequestParam("switchableId") Long switchableId)
|
||||||
|
throws NotFoundException {
|
||||||
|
return removeOutput(inputId, switchableId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@DeleteMapping("/{id}")
|
@DeleteMapping("/{id}")
|
||||||
|
|
|
@ -1,9 +1,13 @@
|
||||||
package ch.usi.inf.sa4.sanmarinoes.smarthut.controller;
|
package ch.usi.inf.sa4.sanmarinoes.smarthut.controller;
|
||||||
|
|
||||||
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.config.EmailConfigurationService;
|
||||||
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.dto.InitPasswordResetRequest;
|
||||||
import ch.usi.inf.sa4.sanmarinoes.smarthut.dto.OkResponse;
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.dto.OkResponse;
|
||||||
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.dto.PasswordResetRequest;
|
||||||
import ch.usi.inf.sa4.sanmarinoes.smarthut.dto.UserRegistrationRequest;
|
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.DuplicateRegistrationException;
|
||||||
import ch.usi.inf.sa4.sanmarinoes.smarthut.error.EmailTokenNotFoundException;
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.error.EmailTokenNotFoundException;
|
||||||
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.error.UserNotFoundException;
|
||||||
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.ConfirmationToken;
|
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.ConfirmationTokenRepository;
|
||||||
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.User;
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.User;
|
||||||
|
@ -11,30 +15,66 @@ import ch.usi.inf.sa4.sanmarinoes.smarthut.models.UserRepository;
|
||||||
import ch.usi.inf.sa4.sanmarinoes.smarthut.service.EmailSenderService;
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.service.EmailSenderService;
|
||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
import javax.validation.constraints.NotNull;
|
import javax.validation.constraints.NotNull;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||||
import org.springframework.mail.SimpleMailMessage;
|
import org.springframework.mail.SimpleMailMessage;
|
||||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.*;
|
||||||
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;
|
|
||||||
|
|
||||||
|
/** Unauthenticated set of endpoints to handle registration and password reset */
|
||||||
@RestController
|
@RestController
|
||||||
@EnableAutoConfiguration
|
@EnableAutoConfiguration
|
||||||
@RequestMapping("/register")
|
@RequestMapping("/register")
|
||||||
public class UserAccountController {
|
public class UserAccountController {
|
||||||
|
|
||||||
@Autowired private UserRepository userRepository;
|
private final UserRepository userRepository;
|
||||||
|
|
||||||
@Autowired private ConfirmationTokenRepository confirmationTokenRepository;
|
private final ConfirmationTokenRepository confirmationTokenRepository;
|
||||||
|
|
||||||
@Autowired private EmailSenderService emailSenderService;
|
private final EmailSenderService emailSenderService;
|
||||||
|
|
||||||
@Autowired private BCryptPasswordEncoder encoder;
|
private final BCryptPasswordEncoder encoder;
|
||||||
|
|
||||||
|
private final EmailConfigurationService emailConfig;
|
||||||
|
|
||||||
|
public UserAccountController(
|
||||||
|
UserRepository userRepository,
|
||||||
|
ConfirmationTokenRepository confirmationTokenRepository,
|
||||||
|
EmailSenderService emailSenderService,
|
||||||
|
BCryptPasswordEncoder encoder,
|
||||||
|
EmailConfigurationService emailConfig) {
|
||||||
|
this.userRepository = userRepository;
|
||||||
|
this.confirmationTokenRepository = confirmationTokenRepository;
|
||||||
|
this.emailSenderService = emailSenderService;
|
||||||
|
this.encoder = encoder;
|
||||||
|
this.emailConfig = emailConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sendEmail(String email, ConfirmationToken token, boolean isRegistration) {
|
||||||
|
SimpleMailMessage mailMessage = new SimpleMailMessage();
|
||||||
|
mailMessage.setTo(email);
|
||||||
|
mailMessage.setSubject(
|
||||||
|
isRegistration
|
||||||
|
? emailConfig.getRegistrationSubject()
|
||||||
|
: emailConfig.getResetPasswordSubject());
|
||||||
|
mailMessage.setFrom("smarthut.sm@gmail.com");
|
||||||
|
mailMessage.setText(
|
||||||
|
(isRegistration ? emailConfig.getRegistration() : emailConfig.getResetPassword())
|
||||||
|
+ " "
|
||||||
|
+ (isRegistration
|
||||||
|
? emailConfig.getRegistrationPath()
|
||||||
|
: emailConfig.getResetPasswordPath())
|
||||||
|
+ token.getConfirmationToken());
|
||||||
|
|
||||||
|
emailSenderService.sendEmail(mailMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unauthenticated endpoint to call to send a password reset email
|
||||||
|
*
|
||||||
|
* @param registrationData registration data of the new user
|
||||||
|
* @return success
|
||||||
|
* @throws DuplicateRegistrationException if a user exists with same email or username
|
||||||
|
*/
|
||||||
@PostMapping
|
@PostMapping
|
||||||
public OkResponse registerUser(@Valid @RequestBody UserRegistrationRequest registrationData)
|
public OkResponse registerUser(@Valid @RequestBody UserRegistrationRequest registrationData)
|
||||||
throws DuplicateRegistrationException {
|
throws DuplicateRegistrationException {
|
||||||
|
@ -60,35 +100,101 @@ public class UserAccountController {
|
||||||
toSave.setEmail(registrationData.getEmail());
|
toSave.setEmail(registrationData.getEmail());
|
||||||
userRepository.save(toSave);
|
userRepository.save(toSave);
|
||||||
|
|
||||||
ConfirmationToken confirmationToken = new ConfirmationToken(toSave);
|
ConfirmationToken token;
|
||||||
|
do {
|
||||||
|
token = new ConfirmationToken(toSave);
|
||||||
|
} while (confirmationTokenRepository.findByConfirmationToken(
|
||||||
|
token.getConfirmationToken())
|
||||||
|
!= null);
|
||||||
|
|
||||||
confirmationTokenRepository.save(confirmationToken);
|
confirmationTokenRepository.save(token);
|
||||||
|
|
||||||
SimpleMailMessage mailMessage = new SimpleMailMessage();
|
sendEmail(toSave.getEmail(), token, true);
|
||||||
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();
|
return new OkResponse();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unauthenticated endpoint to call to send a password reset email
|
||||||
|
*
|
||||||
|
* @param resetRequest a JSON object containing the email of the user to reset
|
||||||
|
* @return success
|
||||||
|
* @throws UserNotFoundException if given email does not belong to any user
|
||||||
|
*/
|
||||||
|
@PostMapping("/init-reset-password")
|
||||||
|
public OkResponse initResetPassword(@Valid @RequestBody InitPasswordResetRequest resetRequest)
|
||||||
|
throws UserNotFoundException {
|
||||||
|
final User toReset = userRepository.findByEmailIgnoreCase(resetRequest.getEmail());
|
||||||
|
|
||||||
|
// Check if an User with the same email already exists
|
||||||
|
if (toReset == null) {
|
||||||
|
throw new UserNotFoundException();
|
||||||
|
}
|
||||||
|
|
||||||
|
ConfirmationToken token;
|
||||||
|
do {
|
||||||
|
token = new ConfirmationToken(toReset);
|
||||||
|
token.setResetPassword(true);
|
||||||
|
} while (confirmationTokenRepository.findByConfirmationToken(token.getConfirmationToken())
|
||||||
|
!= null);
|
||||||
|
|
||||||
|
// Delete existing email password reset tokens
|
||||||
|
confirmationTokenRepository.deleteByUserAndResetPassword(toReset, true);
|
||||||
|
|
||||||
|
// Save new token
|
||||||
|
confirmationTokenRepository.save(token);
|
||||||
|
|
||||||
|
sendEmail(toReset.getEmail(), token, false);
|
||||||
|
|
||||||
|
return new OkResponse();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unauthenticated endpoint to call with token sent by email to reset password
|
||||||
|
*
|
||||||
|
* @param resetRequest the token given via email and the new password
|
||||||
|
* @return success
|
||||||
|
* @throws EmailTokenNotFoundException if given token is not a valid token for password reset
|
||||||
|
*/
|
||||||
|
@PutMapping("/reset-password")
|
||||||
|
public OkResponse resetPassword(@Valid @RequestBody PasswordResetRequest resetRequest)
|
||||||
|
throws EmailTokenNotFoundException {
|
||||||
|
final ConfirmationToken token =
|
||||||
|
confirmationTokenRepository.findByConfirmationToken(
|
||||||
|
resetRequest.getConfirmationToken());
|
||||||
|
|
||||||
|
if (token == null || !token.getResetPassword()) {
|
||||||
|
throw new EmailTokenNotFoundException();
|
||||||
|
}
|
||||||
|
|
||||||
|
final User user = token.getUser();
|
||||||
|
user.setPassword(encoder.encode(resetRequest.getPassword()));
|
||||||
|
userRepository.save(user);
|
||||||
|
|
||||||
|
// Delete token to prevent further password changes
|
||||||
|
confirmationTokenRepository.delete(token);
|
||||||
|
|
||||||
|
return new OkResponse();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unauthenticated endpoint to call with token sent by email to enable user
|
||||||
|
*
|
||||||
|
* @param confirmationToken the token given via email
|
||||||
|
* @return success
|
||||||
|
* @throws EmailTokenNotFoundException if given token is not a valid token for email
|
||||||
|
* confirmation
|
||||||
|
*/
|
||||||
@GetMapping(value = "/confirm-account")
|
@GetMapping(value = "/confirm-account")
|
||||||
public OkResponse confirmUserAccount(@RequestParam("token") @NotNull String confirmationToken)
|
public OkResponse confirmUserAccount(@RequestParam("token") @NotNull String confirmationToken)
|
||||||
throws EmailTokenNotFoundException {
|
throws EmailTokenNotFoundException {
|
||||||
final ConfirmationToken token =
|
final ConfirmationToken token =
|
||||||
confirmationTokenRepository.findByConfirmationToken(confirmationToken);
|
confirmationTokenRepository.findByConfirmationToken(confirmationToken);
|
||||||
|
|
||||||
if (token != null) {
|
if (token != null && !token.getResetPassword()) {
|
||||||
final User user = userRepository.findByEmailIgnoreCase(token.getUser().getEmail());
|
token.getUser().setEnabled(true);
|
||||||
user.setEnabled(true);
|
userRepository.save(token.getUser());
|
||||||
userRepository.save(user);
|
|
||||||
// TODO: redirect to frontend
|
// TODO: redirect to frontend
|
||||||
return new OkResponse();
|
return new OkResponse();
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
package ch.usi.inf.sa4.sanmarinoes.smarthut.controller;
|
|
||||||
|
|
||||||
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.*;
|
|
||||||
import java.util.*;
|
|
||||||
import org.springframework.boot.autoconfigure.*;
|
|
||||||
import org.springframework.web.bind.annotation.*;
|
|
||||||
|
|
||||||
@RestController
|
|
||||||
@EnableAutoConfiguration
|
|
||||||
// @Mapping("/light")
|
|
||||||
public class WelcomeController {
|
|
||||||
|
|
||||||
@GetMapping
|
|
||||||
List<Device> testDevices() {
|
|
||||||
return Arrays.asList(
|
|
||||||
new KnobDimmer(),
|
|
||||||
new RegularLight(),
|
|
||||||
new MotionSensor(),
|
|
||||||
new Sensor(),
|
|
||||||
new SmartPlug(),
|
|
||||||
new Switch());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
package ch.usi.inf.sa4.sanmarinoes.smarthut.dto;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
|
/** A 'dim' event from a button dimmer. */
|
||||||
|
public class ButtonDimmerDimRequest {
|
||||||
|
|
||||||
|
/** The device id */
|
||||||
|
@NotNull private Long id;
|
||||||
|
|
||||||
|
public enum DimType {
|
||||||
|
UP,
|
||||||
|
DOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Whether the dim is up or down */
|
||||||
|
@NotNull private DimType dimType;
|
||||||
|
|
||||||
|
public DimType getDimType() {
|
||||||
|
return dimType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDimType(DimType dimType) {
|
||||||
|
this.dimType = dimType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,67 +0,0 @@
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,11 +1,9 @@
|
||||||
package ch.usi.inf.sa4.sanmarinoes.smarthut.dto;
|
package ch.usi.inf.sa4.sanmarinoes.smarthut.dto;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotEmpty;
|
||||||
import javax.validation.constraints.NotNull;
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
public class SwitchSaveRequest {
|
public class DeviceSaveRequest {
|
||||||
/** The state of this switch */
|
|
||||||
private boolean on;
|
|
||||||
|
|
||||||
/** Device identifier */
|
/** Device identifier */
|
||||||
private long id;
|
private long id;
|
||||||
|
|
||||||
|
@ -16,37 +14,29 @@ public class SwitchSaveRequest {
|
||||||
@NotNull private Long roomId;
|
@NotNull private Long roomId;
|
||||||
|
|
||||||
/** The name of the device as assigned by the user (e.g. 'Master bedroom light') */
|
/** The name of the device as assigned by the user (e.g. 'Master bedroom light') */
|
||||||
@NotNull private String name;
|
@NotNull @NotEmpty private String name;
|
||||||
|
|
||||||
public void setId(long id) {
|
|
||||||
this.id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRoomId(Long roomId) {
|
|
||||||
this.roomId = roomId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setName(String name) {
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getId() {
|
public long getId() {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setId(long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
public Long getRoomId() {
|
public Long getRoomId() {
|
||||||
return roomId;
|
return roomId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setRoomId(Long roomId) {
|
||||||
|
this.roomId = roomId;
|
||||||
|
}
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isOn() {
|
public void setName(String name) {
|
||||||
return on;
|
this.name = name;
|
||||||
}
|
|
||||||
|
|
||||||
public void setOn(boolean on) {
|
|
||||||
this.on = on;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,24 +1,20 @@
|
||||||
package ch.usi.inf.sa4.sanmarinoes.smarthut.dto;
|
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.Max;
|
||||||
import javax.validation.constraints.Min;
|
import javax.validation.constraints.Min;
|
||||||
import javax.validation.constraints.NotNull;
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
public class DimmableLightSaveRequest {
|
public class DimmableLightSaveRequest {
|
||||||
|
|
||||||
|
/** Device id (used only for update requests) */
|
||||||
|
private Long id;
|
||||||
|
|
||||||
/** The light intensity value. Goes from 0 (off) to 100 (on) */
|
/** The light intensity value. Goes from 0 (off) to 100 (on) */
|
||||||
@NotNull
|
@NotNull
|
||||||
@Min(1)
|
@Min(1)
|
||||||
@Max(100)
|
@Max(100)
|
||||||
private Integer intensity = 0;
|
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
|
* The room this device belongs in, as a foreign key id. To use when updating and inserting from
|
||||||
* a REST call.
|
* a REST call.
|
||||||
|
@ -28,14 +24,6 @@ public class DimmableLightSaveRequest {
|
||||||
/** The name of the device as assigned by the user (e.g. 'Master bedroom light') */
|
/** The name of the device as assigned by the user (e.g. 'Master bedroom light') */
|
||||||
@NotNull private String name;
|
@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) {
|
public void setRoomId(Long roomId) {
|
||||||
this.roomId = roomId;
|
this.roomId = roomId;
|
||||||
}
|
}
|
||||||
|
@ -44,14 +32,6 @@ public class DimmableLightSaveRequest {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Room getRoom() {
|
|
||||||
return room;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Long getRoomId() {
|
public Long getRoomId() {
|
||||||
return roomId;
|
return roomId;
|
||||||
}
|
}
|
||||||
|
@ -64,10 +44,15 @@ public class DimmableLightSaveRequest {
|
||||||
return intensity;
|
return intensity;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setIntensity(Integer intensity) throws IllegalArgumentException {
|
public void setIntensity(Integer intensity) {
|
||||||
if (intensity < 0 || intensity > 100) {
|
|
||||||
throw new IllegalArgumentException("The intensity level can't go below 0 or above 100");
|
|
||||||
}
|
|
||||||
this.intensity = intensity;
|
this.intensity = intensity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,12 +2,7 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut.dto;
|
||||||
|
|
||||||
import javax.validation.constraints.NotNull;
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
public class MotionSensorSaveRequest {
|
public class GenericDeviceSaveReguest {
|
||||||
private boolean detected;
|
|
||||||
|
|
||||||
/** Device identifier */
|
|
||||||
private long id;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The room this device belongs in, as a foreign key id. To use when updating and inserting from
|
* The room this device belongs in, as a foreign key id. To use when updating and inserting from
|
||||||
* a REST call.
|
* a REST call.
|
||||||
|
@ -17,10 +12,6 @@ public class MotionSensorSaveRequest {
|
||||||
/** The name of the device as assigned by the user (e.g. 'Master bedroom light') */
|
/** The name of the device as assigned by the user (e.g. 'Master bedroom light') */
|
||||||
@NotNull private String name;
|
@NotNull private String name;
|
||||||
|
|
||||||
public void setId(long id) {
|
|
||||||
this.id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRoomId(Long roomId) {
|
public void setRoomId(Long roomId) {
|
||||||
this.roomId = roomId;
|
this.roomId = roomId;
|
||||||
}
|
}
|
||||||
|
@ -29,10 +20,6 @@ public class MotionSensorSaveRequest {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Long getRoomId() {
|
public Long getRoomId() {
|
||||||
return roomId;
|
return roomId;
|
||||||
}
|
}
|
||||||
|
@ -40,12 +27,4 @@ public class MotionSensorSaveRequest {
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isDetected() {
|
|
||||||
return detected;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDetected(boolean detected) {
|
|
||||||
this.detected = detected;
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
package ch.usi.inf.sa4.sanmarinoes.smarthut.dto;
|
||||||
|
|
||||||
|
import javax.validation.constraints.Email;
|
||||||
|
import javax.validation.constraints.NotEmpty;
|
||||||
|
import javax.validation.constraints.Pattern;
|
||||||
|
|
||||||
|
/** DTO for password reset request */
|
||||||
|
public class InitPasswordResetRequest {
|
||||||
|
/**
|
||||||
|
* The user's email (validated according to criteria used in <code>>input type="email"<>
|
||||||
|
* </code>, technically not RFC 5322 compliant
|
||||||
|
*/
|
||||||
|
@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 getEmail() {
|
||||||
|
return email;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEmail(String email) {
|
||||||
|
this.email = email;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,15 +1,17 @@
|
||||||
package ch.usi.inf.sa4.sanmarinoes.smarthut.dto;
|
package ch.usi.inf.sa4.sanmarinoes.smarthut.dto;
|
||||||
|
|
||||||
public class JWTRequest {
|
import javax.validation.constraints.NotNull;
|
||||||
private String username;
|
|
||||||
private String password;
|
|
||||||
|
|
||||||
public String getUsername() {
|
public class JWTRequest {
|
||||||
return this.username;
|
@NotNull private String usernameOrEmail;
|
||||||
|
@NotNull private String password;
|
||||||
|
|
||||||
|
public String getUsernameOrEmail() {
|
||||||
|
return this.usernameOrEmail;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setUsername(String username) {
|
public void setUsernameOrEmail(String usernameOrEmail) {
|
||||||
this.username = username;
|
this.usernameOrEmail = usernameOrEmail;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getPassword() {
|
public String getPassword() {
|
||||||
|
@ -19,4 +21,16 @@ public class JWTRequest {
|
||||||
public void setPassword(String password) {
|
public void setPassword(String password) {
|
||||||
this.password = password;
|
this.password = password;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "JWTRequest{"
|
||||||
|
+ "usernameOrEmail='"
|
||||||
|
+ usernameOrEmail
|
||||||
|
+ '\''
|
||||||
|
+ ", password='"
|
||||||
|
+ password
|
||||||
|
+ '\''
|
||||||
|
+ '}';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
package ch.usi.inf.sa4.sanmarinoes.smarthut.dto;
|
||||||
|
|
||||||
|
import javax.validation.constraints.Max;
|
||||||
|
import javax.validation.constraints.Min;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
|
public class KnobDimmerDimRequest {
|
||||||
|
|
||||||
|
/** The device id */
|
||||||
|
@NotNull private Long id;
|
||||||
|
|
||||||
|
/** The absolute intensity value */
|
||||||
|
@NotNull
|
||||||
|
@Min(0)
|
||||||
|
@Max(100)
|
||||||
|
private Integer intensity;
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getIntensity() {
|
||||||
|
return intensity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIntensity(Integer intensity) {
|
||||||
|
this.intensity = intensity;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,55 +0,0 @@
|
||||||
package ch.usi.inf.sa4.sanmarinoes.smarthut.dto;
|
|
||||||
|
|
||||||
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.DimmableLight;
|
|
||||||
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, 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 setRoomId(Long roomId) {
|
|
||||||
this.roomId = roomId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setName(String name) {
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
package ch.usi.inf.sa4.sanmarinoes.smarthut.dto;
|
||||||
|
|
||||||
|
import javax.validation.constraints.*;
|
||||||
|
|
||||||
|
/** DTO for password reset request */
|
||||||
|
public class PasswordResetRequest {
|
||||||
|
|
||||||
|
@NotNull private String confirmationToken;
|
||||||
|
|
||||||
|
/** 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;
|
||||||
|
|
||||||
|
public String getConfirmationToken() {
|
||||||
|
return confirmationToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConfirmationToken(String confirmationToken) {
|
||||||
|
this.confirmationToken = confirmationToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPassword() {
|
||||||
|
return password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPassword(String password) {
|
||||||
|
this.password = password;
|
||||||
|
}
|
||||||
|
}
|
|
@ -18,10 +18,6 @@ public class RegularLightSaveRequest {
|
||||||
/** The name of the device as assigned by the user (e.g. 'Master bedroom light') */
|
/** The name of the device as assigned by the user (e.g. 'Master bedroom light') */
|
||||||
@NotNull private String name;
|
@NotNull private String name;
|
||||||
|
|
||||||
public void setId(long id) {
|
|
||||||
this.id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRoomId(Long roomId) {
|
public void setRoomId(Long roomId) {
|
||||||
this.roomId = roomId;
|
this.roomId = roomId;
|
||||||
}
|
}
|
||||||
|
@ -49,4 +45,8 @@ public class RegularLightSaveRequest {
|
||||||
public void setOn(boolean on) {
|
public void setOn(boolean on) {
|
||||||
this.on = on;
|
this.on = on;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setId(long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,19 @@
|
||||||
package ch.usi.inf.sa4.sanmarinoes.smarthut.dto;
|
package ch.usi.inf.sa4.sanmarinoes.smarthut.dto;
|
||||||
|
|
||||||
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.Room;
|
||||||
import javax.persistence.Lob;
|
import javax.persistence.Lob;
|
||||||
import javax.validation.constraints.NotNull;
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
public class RoomSaveRequest {
|
public class RoomSaveRequest {
|
||||||
|
|
||||||
|
@NotNull private Room.Icon icon;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Icon and image are to be given as byte[]. In order to get an encoded string from it, the
|
* Image is to be given as byte[]. In order to get an encoded string from it, the
|
||||||
* Base64.getEncoder().encodeToString(byte[] content) should be used. For further information:
|
* Base64.getEncoder().encodeToString(byte[] content) should be used. For further information:
|
||||||
* https://www.baeldung.com/java-base64-image-string
|
* https://www.baeldung.com/java-base64-image-string
|
||||||
* https://docs.oracle.com/javase/8/docs/api/java/util/Base64.html
|
* https://docs.oracle.com/javase/8/docs/api/java/util/Base64.html
|
||||||
*/
|
*/
|
||||||
@Lob private String icon;
|
|
||||||
|
|
||||||
@Lob private String image;
|
@Lob private String image;
|
||||||
|
|
||||||
/** The user given name of this room (e.g. 'Master bedroom') */
|
/** The user given name of this room (e.g. 'Master bedroom') */
|
||||||
|
@ -25,11 +27,11 @@ public class RoomSaveRequest {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getIcon() {
|
public Room.Icon getIcon() {
|
||||||
return icon;
|
return icon;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setIcon(String icon) {
|
public void setIcon(Room.Icon icon) {
|
||||||
this.icon = icon;
|
this.icon = icon;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,17 +23,11 @@ public class SensorSaveRequest {
|
||||||
LIGHT
|
LIGHT
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The value of this sensor according to its sensor type */
|
|
||||||
private int value;
|
|
||||||
|
|
||||||
/** The type of this sensor */
|
/** The type of this sensor */
|
||||||
@NotNull
|
@NotNull
|
||||||
@Enumerated(value = EnumType.STRING)
|
@Enumerated(value = EnumType.STRING)
|
||||||
private Sensor.SensorType sensor;
|
private Sensor.SensorType sensor;
|
||||||
|
|
||||||
/** Device identifier */
|
|
||||||
private long id;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The room this device belongs in, as a foreign key id. To use when updating and inserting from
|
* The room this device belongs in, as a foreign key id. To use when updating and inserting from
|
||||||
* a REST call.
|
* a REST call.
|
||||||
|
@ -43,10 +37,6 @@ public class SensorSaveRequest {
|
||||||
/** The name of the device as assigned by the user (e.g. 'Master bedroom light') */
|
/** The name of the device as assigned by the user (e.g. 'Master bedroom light') */
|
||||||
@NotNull private String name;
|
@NotNull private String name;
|
||||||
|
|
||||||
public void setId(long id) {
|
|
||||||
this.id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRoomId(Long roomId) {
|
public void setRoomId(Long roomId) {
|
||||||
this.roomId = roomId;
|
this.roomId = roomId;
|
||||||
}
|
}
|
||||||
|
@ -55,10 +45,6 @@ public class SensorSaveRequest {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Long getRoomId() {
|
public Long getRoomId() {
|
||||||
return roomId;
|
return roomId;
|
||||||
}
|
}
|
||||||
|
@ -74,12 +60,4 @@ public class SensorSaveRequest {
|
||||||
public void setSensor(Sensor.SensorType sensor) {
|
public void setSensor(Sensor.SensorType sensor) {
|
||||||
this.sensor = sensor;
|
this.sensor = sensor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getValue() {
|
|
||||||
return this.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setValue(int newValue) {
|
|
||||||
this.value = newValue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,10 +18,6 @@ public class SmartPlugSaveRequest {
|
||||||
/** The name of the device as assigned by the user (e.g. 'Master bedroom light') */
|
/** The name of the device as assigned by the user (e.g. 'Master bedroom light') */
|
||||||
@NotNull private String name;
|
@NotNull private String name;
|
||||||
|
|
||||||
public void setId(long id) {
|
|
||||||
this.id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRoomId(Long roomId) {
|
public void setRoomId(Long roomId) {
|
||||||
this.roomId = roomId;
|
this.roomId = roomId;
|
||||||
}
|
}
|
||||||
|
@ -49,4 +45,8 @@ public class SmartPlugSaveRequest {
|
||||||
public void setOn(boolean on) {
|
public void setOn(boolean on) {
|
||||||
this.on = on;
|
this.on = on;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setId(long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
package ch.usi.inf.sa4.sanmarinoes.smarthut.dto;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
|
/** An on/off/toggle operation on a switch */
|
||||||
|
public class SwitchOperationRequest {
|
||||||
|
|
||||||
|
/** The device id */
|
||||||
|
@NotNull private Long id;
|
||||||
|
|
||||||
|
public enum OperationType {
|
||||||
|
ON,
|
||||||
|
OFF,
|
||||||
|
TOGGLE
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The type of switch operation */
|
||||||
|
@NotNull private SwitchOperationRequest.OperationType type;
|
||||||
|
|
||||||
|
public OperationType getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setType(OperationType type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,6 +12,9 @@ public class UserRegistrationRequest {
|
||||||
/** The full name of the user */
|
/** The full name of the user */
|
||||||
@NotNull
|
@NotNull
|
||||||
@NotEmpty(message = "Please provide a username")
|
@NotEmpty(message = "Please provide a username")
|
||||||
|
@Pattern(
|
||||||
|
regexp = "[A-Za-z0-9_\\-]+",
|
||||||
|
message = "Username can contain only letters, numbers, '_' and '-'")
|
||||||
private String username;
|
private String username;
|
||||||
|
|
||||||
/** A properly salted way to store the password */
|
/** A properly salted way to store the password */
|
||||||
|
|
|
@ -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 BadDataException extends Exception {
|
||||||
|
public BadDataException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package ch.usi.inf.sa4.sanmarinoes.smarthut.error;
|
||||||
|
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||||
|
|
||||||
|
@ResponseStatus(code = HttpStatus.NOT_FOUND)
|
||||||
|
public class NotFoundException extends Exception {
|
||||||
|
public NotFoundException() {
|
||||||
|
super("Not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
public NotFoundException(String what) {
|
||||||
|
super(what + " not found");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package ch.usi.inf.sa4.sanmarinoes.smarthut.error;
|
||||||
|
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||||
|
|
||||||
|
@ResponseStatus(code = HttpStatus.UNAUTHORIZED)
|
||||||
|
public class UnauthorizedException extends Exception {
|
||||||
|
private final boolean isUserDisabled;
|
||||||
|
|
||||||
|
public UnauthorizedException(boolean isDisabled) {
|
||||||
|
super("Access denied: " + (isDisabled ? "user is disabled" : "wrong credentials"));
|
||||||
|
this.isUserDisabled = isDisabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isUserDisabled() {
|
||||||
|
return isUserDisabled;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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 UserNotFoundException extends Exception {
|
||||||
|
public UserNotFoundException() {
|
||||||
|
super("No user found with given email");
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,9 +1,6 @@
|
||||||
package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
|
package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
|
||||||
|
|
||||||
|
|
||||||
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,60 +8,25 @@ import javax.persistence.OneToMany;
|
||||||
*/
|
*/
|
||||||
@Entity
|
@Entity
|
||||||
public class ButtonDimmer extends Dimmer {
|
public class ButtonDimmer extends Dimmer {
|
||||||
|
|
||||||
|
/** The delta amount to apply to a increase or decrease intensity */
|
||||||
|
private static final int DIM_INCREMENT = 10;
|
||||||
|
|
||||||
public ButtonDimmer() {
|
public ButtonDimmer() {
|
||||||
super("button-dimmer");
|
super("button-dimmer");
|
||||||
}
|
}
|
||||||
|
|
||||||
@OneToMany(mappedBy = "dimmer")
|
/** Increases the current intensity level of the dimmable light by DIM_INCREMENT */
|
||||||
private Set<DimmableLight> lights;
|
|
||||||
|
|
||||||
/** Increases the current intensity level of the dimmable light by 1 */
|
|
||||||
public void increaseIntensity() {
|
public void increaseIntensity() {
|
||||||
for (DimmableLight dl : lights) {
|
for (DimmableLight dl : getOutputs()) {
|
||||||
dl.setIntensity(dl.getIntensity() + 1);
|
dl.setIntensity(dl.getIntensity() + DIM_INCREMENT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Decreases the current intensity level of the dimmable light by 1 */
|
/** Decreases the current intensity level of the dimmable light by DIM_INCREMENT */
|
||||||
public void decreaseIntensity() {
|
public void decreaseIntensity() {
|
||||||
for (DimmableLight dl : lights) {
|
for (DimmableLight dl : getOutputs()) {
|
||||||
dl.setIntensity(dl.getIntensity() - 1);
|
dl.setIntensity(dl.getIntensity() - DIM_INCREMENT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ public class ConfirmationToken {
|
||||||
@Column(name = "id", updatable = false, nullable = false)
|
@Column(name = "id", updatable = false, nullable = false)
|
||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
@Column(name = "confirmation_token")
|
@Column(name = "confirmation_token", unique = true)
|
||||||
private String confirmationToken;
|
private String confirmationToken;
|
||||||
|
|
||||||
@Temporal(TemporalType.TIMESTAMP)
|
@Temporal(TemporalType.TIMESTAMP)
|
||||||
|
@ -31,10 +31,14 @@ public class ConfirmationToken {
|
||||||
@JoinColumn(nullable = false, name = "user_id")
|
@JoinColumn(nullable = false, name = "user_id")
|
||||||
private User user;
|
private User user;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private Boolean resetPassword;
|
||||||
|
|
||||||
public ConfirmationToken(User user) {
|
public ConfirmationToken(User user) {
|
||||||
this.user = user;
|
this.user = user;
|
||||||
createdDate = new Date();
|
createdDate = new Date();
|
||||||
confirmationToken = UUID.randomUUID().toString();
|
confirmationToken = UUID.randomUUID().toString();
|
||||||
|
resetPassword = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Constructor for hibernate reflective stuff things whatever */
|
/** Constructor for hibernate reflective stuff things whatever */
|
||||||
|
@ -71,4 +75,12 @@ public class ConfirmationToken {
|
||||||
public void setUser(User user) {
|
public void setUser(User user) {
|
||||||
this.user = user;
|
this.user = user;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Boolean getResetPassword() {
|
||||||
|
return resetPassword;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setResetPassword(Boolean resetPassword) {
|
||||||
|
this.resetPassword = resetPassword;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
|
package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
|
||||||
|
|
||||||
|
import javax.transaction.Transactional;
|
||||||
import org.springframework.data.repository.CrudRepository;
|
import org.springframework.data.repository.CrudRepository;
|
||||||
|
|
||||||
public interface ConfirmationTokenRepository extends CrudRepository<ConfirmationToken, String> {
|
public interface ConfirmationTokenRepository extends CrudRepository<ConfirmationToken, String> {
|
||||||
ConfirmationToken findByConfirmationToken(String confirmationToken);
|
ConfirmationToken findByConfirmationToken(String confirmationToken);
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
void deleteByUserAndResetPassword(User user, boolean resetPassword);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A rule on how to connect an input device type to an output device type
|
||||||
|
*
|
||||||
|
* @param <I> the input device type
|
||||||
|
* @param <O> the output device type
|
||||||
|
*/
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface Connector<I extends InputDevice, O extends OutputDevice> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Connects or disconnects input to output
|
||||||
|
*
|
||||||
|
* @param input the input device
|
||||||
|
* @param output the output device
|
||||||
|
* @param connect true if connection, false if disconnection
|
||||||
|
*/
|
||||||
|
void connect(I input, O output, boolean connect);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Produces a basic implementation of a connector, assuming there is a OneToMany relationship
|
||||||
|
* between J and K
|
||||||
|
*
|
||||||
|
* @param outputsGetter the getter method of the set of outputs on the input class
|
||||||
|
* @param inputSetter the setter method for the input id on the output class
|
||||||
|
* @param <J> the input device type
|
||||||
|
* @param <K> the output device type
|
||||||
|
* @return a Connector implementation for the pair of types J and K
|
||||||
|
*/
|
||||||
|
static <J extends InputDevice, K extends OutputDevice> Connector<J, K> basic(
|
||||||
|
Function<J, Set<? super K>> outputsGetter, BiConsumer<K, Long> inputSetter) {
|
||||||
|
return (i, o, connect) -> {
|
||||||
|
if (connect) {
|
||||||
|
outputsGetter.apply(i).add(o);
|
||||||
|
} else {
|
||||||
|
outputsGetter.apply(i).remove(o);
|
||||||
|
}
|
||||||
|
|
||||||
|
inputSetter.accept(o, connect ? i.getId() : null);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,9 @@
|
||||||
package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
|
package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
|
||||||
|
|
||||||
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.config.GsonExclude;
|
||||||
import javax.persistence.Column;
|
import javax.persistence.Column;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.JoinColumn;
|
||||||
import javax.persistence.ManyToOne;
|
import javax.persistence.ManyToOne;
|
||||||
import javax.validation.constraints.Max;
|
import javax.validation.constraints.Max;
|
||||||
import javax.validation.constraints.Min;
|
import javax.validation.constraints.Min;
|
||||||
|
@ -9,18 +11,31 @@ import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
/** Represent a dimmable light */
|
/** Represent a dimmable light */
|
||||||
@Entity
|
@Entity
|
||||||
public class DimmableLight extends Light {
|
public class DimmableLight extends Switchable {
|
||||||
|
|
||||||
|
public static final Connector<ButtonDimmer, DimmableLight>
|
||||||
|
BUTTON_DIMMER_DIMMABLE_LIGHT_CONNECTOR =
|
||||||
|
Connector.basic(ButtonDimmer::getOutputs, DimmableLight::setDimmerId);
|
||||||
|
|
||||||
|
public static final Connector<KnobDimmer, DimmableLight> KNOB_DIMMER_DIMMABLE_LIGHT_CONNECTOR =
|
||||||
|
Connector.basic(KnobDimmer::getOutputs, DimmableLight::setDimmerId);
|
||||||
|
|
||||||
public DimmableLight() {
|
public DimmableLight() {
|
||||||
super("light");
|
super("light");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ManyToOne private Dimmer dimmer;
|
@ManyToOne
|
||||||
|
@GsonExclude
|
||||||
|
@JoinColumn(name = "dimmer_id", updatable = false, insertable = false)
|
||||||
|
private Dimmer dimmer;
|
||||||
|
|
||||||
|
@Column(name = "dimmer_id")
|
||||||
|
private Long dimmerId;
|
||||||
|
|
||||||
/** The light intensity value. Goes from 0 (off) to 100 (on) */
|
/** The light intensity value. Goes from 0 (off) to 100 (on) */
|
||||||
@NotNull
|
@NotNull
|
||||||
@Column(nullable = false)
|
@Column(nullable = false)
|
||||||
@Min(1)
|
@Min(0)
|
||||||
@Max(100)
|
@Max(100)
|
||||||
private Integer intensity = 0;
|
private Integer intensity = 0;
|
||||||
|
|
||||||
|
@ -28,10 +43,41 @@ public class DimmableLight extends Light {
|
||||||
return intensity;
|
return intensity;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setIntensity(Integer intensity) throws IllegalArgumentException {
|
/**
|
||||||
if (intensity < 0 || intensity > 100) {
|
* Sets the intensity to a certain level. Out of bound values are corrected to the respective
|
||||||
throw new IllegalArgumentException("The intensity level can't go below 0 or above 100");
|
* extremums. An intensity level of 0 turns the light off, but keeps the old intensity level
|
||||||
|
* stored.
|
||||||
|
*
|
||||||
|
* @param intensity the intensity level (may be out of bounds)
|
||||||
|
*/
|
||||||
|
public void setIntensity(Integer intensity) {
|
||||||
|
if (intensity <= 0) {
|
||||||
|
this.intensity = 0;
|
||||||
|
} else if (intensity > 100) {
|
||||||
|
this.intensity = 100;
|
||||||
|
} else {
|
||||||
|
this.intensity = intensity;
|
||||||
}
|
}
|
||||||
this.intensity = intensity;
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isOn() {
|
||||||
|
return intensity != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setOn(boolean on) {
|
||||||
|
intensity = on ? 100 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDimmerId(Long dimmerId) {
|
||||||
|
this.dimmerId = dimmerId;
|
||||||
|
super.setSwitchId(null);
|
||||||
|
};
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setSwitchId(Long switchId) {
|
||||||
|
super.setSwitchId(switchId);
|
||||||
|
this.dimmerId = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
|
package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
|
||||||
|
|
||||||
public interface DimmableLightRepository extends DeviceRepository<DimmableLight> {}
|
public interface DimmableLightRepository extends SwitchableRepository<DimmableLight> {}
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
|
package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
import javax.persistence.Inheritance;
|
import javax.persistence.Inheritance;
|
||||||
import javax.persistence.InheritanceType;
|
import javax.persistence.InheritanceType;
|
||||||
|
import javax.persistence.OneToMany;
|
||||||
|
|
||||||
/** Represents a generic dimmer input device */
|
/** Represents a generic dimmer input device */
|
||||||
@Entity
|
@Entity
|
||||||
|
@ -11,4 +13,17 @@ public abstract class Dimmer extends InputDevice {
|
||||||
public Dimmer(String kind) {
|
public Dimmer(String kind) {
|
||||||
super(kind);
|
super(kind);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OneToMany(mappedBy = "dimmer")
|
||||||
|
private Set<DimmableLight> lights;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the lights connected to this dimmer
|
||||||
|
*
|
||||||
|
* @return duh
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Set<DimmableLight> getOutputs() {
|
||||||
|
return this.lights;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,22 @@
|
||||||
package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
|
package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Inheritance;
|
||||||
|
import javax.persistence.InheritanceType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A generic abstraction for an input device, i.e. something that captures input either from the
|
* A generic abstraction for an input device, i.e. something that captures input either from the
|
||||||
* environment (sensor) or the user (switch / dimmer).
|
* environment (sensor) or the user (switch / dimmer).
|
||||||
*/
|
*/
|
||||||
@Entity
|
@Entity
|
||||||
|
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
|
||||||
public abstract class InputDevice extends Device {
|
public abstract class InputDevice extends Device {
|
||||||
public InputDevice(String kind) {
|
public InputDevice(String kind) {
|
||||||
super(kind, FlowType.INPUT);
|
super(kind, FlowType.INPUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Set<? extends OutputDevice> getOutputs() {
|
||||||
|
return Set.of();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ public class JWTUserDetailsService implements UserDetailsService {
|
||||||
@Override
|
@Override
|
||||||
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
|
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
|
||||||
User toReturn = repository.findByUsername(username);
|
User toReturn = repository.findByUsername(username);
|
||||||
if (toReturn != null) {
|
if (toReturn != null && toReturn.getEnabled()) {
|
||||||
return new org.springframework.security.core.userdetails.User(
|
return new org.springframework.security.core.userdetails.User(
|
||||||
toReturn.getUsername(), toReturn.getPassword(), Set.of());
|
toReturn.getUsername(), toReturn.getPassword(), Set.of());
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
|
package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
|
||||||
|
|
||||||
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
|
||||||
|
@ -10,62 +8,19 @@ import javax.persistence.OneToMany;
|
||||||
*/
|
*/
|
||||||
@Entity
|
@Entity
|
||||||
public class KnobDimmer extends Dimmer {
|
public class KnobDimmer extends Dimmer {
|
||||||
|
|
||||||
public KnobDimmer() {
|
public KnobDimmer() {
|
||||||
super("knob-dimmer");
|
super("knob-dimmer");
|
||||||
}
|
}
|
||||||
|
|
||||||
@OneToMany(mappedBy = "dimmer")
|
|
||||||
private Set<DimmableLight> lights;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Increases or decreases the current intensity level by 5, moving between absolute multiples of
|
* Sets absolutely the intensity level of all lights connected
|
||||||
* 5 between 0 and 100, of all dimmable lights mapped to this knob
|
|
||||||
*
|
*
|
||||||
* @param inc The direction the knob is turned with
|
* @param intensity the intensity (must be from 0 to 100)
|
||||||
*/
|
*/
|
||||||
public void modifyIntensity(boolean inc) {
|
public void setLightIntensity(int intensity) {
|
||||||
|
for (DimmableLight dl : getOutputs()) {
|
||||||
for (DimmableLight dl : lights) {
|
dl.setIntensity(intensity);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,31 +0,0 @@
|
||||||
package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
|
|
||||||
|
|
||||||
import javax.persistence.Column;
|
|
||||||
import javax.persistence.Entity;
|
|
||||||
import javax.persistence.Inheritance;
|
|
||||||
import javax.persistence.InheritanceType;
|
|
||||||
import javax.validation.constraints.NotNull;
|
|
||||||
|
|
||||||
/** Represents a generic light */
|
|
||||||
@Entity
|
|
||||||
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
|
|
||||||
public abstract class Light extends OutputDevice {
|
|
||||||
|
|
||||||
/** Whether the light is on or not */
|
|
||||||
@Column(name = "light_on", nullable = false)
|
|
||||||
@NotNull
|
|
||||||
boolean on;
|
|
||||||
|
|
||||||
protected Light(String kind) {
|
|
||||||
super(kind);
|
|
||||||
this.on = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isOn() {
|
|
||||||
return on;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setOn(boolean on) {
|
|
||||||
this.on = on;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,8 +1,6 @@
|
||||||
package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
|
package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
|
||||||
|
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.*;
|
||||||
import javax.persistence.Inheritance;
|
|
||||||
import javax.persistence.InheritanceType;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a generic output device, i.e. something that causes some behaviour (light, smartPlugs,
|
* Represents a generic output device, i.e. something that causes some behaviour (light, smartPlugs,
|
||||||
|
|
|
@ -1,11 +1,30 @@
|
||||||
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;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
/** Represents a standard non-dimmable light */
|
/** Represents a standard non-dimmable light */
|
||||||
@Entity
|
@Entity
|
||||||
public class RegularLight extends Light {
|
public class RegularLight extends Switchable {
|
||||||
|
|
||||||
|
/** Whether the light is on or not */
|
||||||
|
@Column(name = "light_on", nullable = false)
|
||||||
|
@NotNull
|
||||||
|
boolean on;
|
||||||
|
|
||||||
public RegularLight() {
|
public RegularLight() {
|
||||||
super("regular-light");
|
super("regular-light");
|
||||||
|
this.on = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isOn() {
|
||||||
|
return on;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setOn(boolean on) {
|
||||||
|
this.on = on;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
|
package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
|
||||||
|
|
||||||
public interface RegularLightRepository extends DeviceRepository<RegularLight> {}
|
public interface RegularLightRepository extends SwitchableRepository<RegularLight> {}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
|
package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
import javax.persistence.*;
|
import javax.persistence.*;
|
||||||
import javax.validation.constraints.NotNull;
|
import javax.validation.constraints.NotNull;
|
||||||
|
@ -8,25 +9,124 @@ import javax.validation.constraints.NotNull;
|
||||||
@Entity
|
@Entity
|
||||||
public class Room {
|
public class Room {
|
||||||
|
|
||||||
|
/** A collection of Semantic UI icons */
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public enum Icon {
|
||||||
|
@SerializedName("home")
|
||||||
|
HOME("home"),
|
||||||
|
@SerializedName("coffee")
|
||||||
|
COFFEE("coffee"),
|
||||||
|
@SerializedName("beer")
|
||||||
|
BEER("beer"),
|
||||||
|
@SerializedName("glass martini")
|
||||||
|
GLASS_MARTINI("glass martini"),
|
||||||
|
@SerializedName("film")
|
||||||
|
FILM("film"),
|
||||||
|
@SerializedName("video")
|
||||||
|
VIDEO("video"),
|
||||||
|
@SerializedName("music")
|
||||||
|
MUSIC("music"),
|
||||||
|
@SerializedName("headphones")
|
||||||
|
HEADPHONES("headphones"),
|
||||||
|
@SerializedName("fax")
|
||||||
|
FAX("fax"),
|
||||||
|
@SerializedName("phone")
|
||||||
|
PHONE("phone"),
|
||||||
|
@SerializedName("laptop")
|
||||||
|
LAPTOP("laptop"),
|
||||||
|
@SerializedName("bath")
|
||||||
|
BATH("bath"),
|
||||||
|
@SerializedName("shower")
|
||||||
|
SHOWER("shower"),
|
||||||
|
@SerializedName("bed")
|
||||||
|
BED("bed"),
|
||||||
|
@SerializedName("child")
|
||||||
|
CHILD("child"),
|
||||||
|
@SerializedName("warehouse")
|
||||||
|
WAREHOUSE("warehouse"),
|
||||||
|
@SerializedName("car")
|
||||||
|
CAR("car"),
|
||||||
|
@SerializedName("bicycle")
|
||||||
|
BICYCLE("bicycle"),
|
||||||
|
@SerializedName("motorcycle")
|
||||||
|
MOTORCYCLE("motorcycle"),
|
||||||
|
@SerializedName("archive")
|
||||||
|
ARCHIVE("archive"),
|
||||||
|
@SerializedName("boxes")
|
||||||
|
BOXES("boxes"),
|
||||||
|
@SerializedName("cubes")
|
||||||
|
CUBES("cubes"),
|
||||||
|
@SerializedName("chess")
|
||||||
|
CHESS("chess"),
|
||||||
|
@SerializedName("gamepad")
|
||||||
|
GAMEPAD("gamepad"),
|
||||||
|
@SerializedName("futbol")
|
||||||
|
FUTBOL("futbol"),
|
||||||
|
@SerializedName("table tennis")
|
||||||
|
TABLE_TENNIS("table tennis"),
|
||||||
|
@SerializedName("server")
|
||||||
|
SERVER("server"),
|
||||||
|
@SerializedName("tv")
|
||||||
|
TV("tv"),
|
||||||
|
@SerializedName("heart")
|
||||||
|
HEART("heart"),
|
||||||
|
@SerializedName("camera")
|
||||||
|
CAMERA("camera"),
|
||||||
|
@SerializedName("trophy")
|
||||||
|
TROPHY("trophy"),
|
||||||
|
@SerializedName("wrench")
|
||||||
|
WRENCH("wrench"),
|
||||||
|
@SerializedName("image")
|
||||||
|
IMAGE("image"),
|
||||||
|
@SerializedName("book")
|
||||||
|
BOOK("book"),
|
||||||
|
@SerializedName("university")
|
||||||
|
UNIVERSITY("university"),
|
||||||
|
@SerializedName("medkit")
|
||||||
|
MEDKIT("medkit"),
|
||||||
|
@SerializedName("paw")
|
||||||
|
PAW("paw"),
|
||||||
|
@SerializedName("tree")
|
||||||
|
TREE("tree"),
|
||||||
|
@SerializedName("utensils")
|
||||||
|
UTENSILS("utensils"),
|
||||||
|
@SerializedName("male")
|
||||||
|
MALE("male"),
|
||||||
|
@SerializedName("female")
|
||||||
|
FEMALE("female"),
|
||||||
|
@SerializedName("life ring outline")
|
||||||
|
LIFE_RING_OUTLINE("life ring outline");
|
||||||
|
|
||||||
|
private String iconName;
|
||||||
|
|
||||||
|
Icon(String s) {
|
||||||
|
this.iconName = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return iconName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@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)
|
@ApiModelProperty(hidden = true)
|
||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
|
/** The room icon, out of a set of Semantic UI icons */
|
||||||
|
@Column private Icon icon;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Icon and image are to be given as byte[]. In order to get an encoded string from it, the
|
* Image is to be given as byte[]. In order to get an encoded string from it, the
|
||||||
* Base64.getEncoder().encodeToString(byte[] content) should be used. For further information:
|
* Base64.getEncoder().encodeToString(byte[] content) should be used. For further information:
|
||||||
* https://www.baeldung.com/java-base64-image-string
|
* https://www.baeldung.com/java-base64-image-string
|
||||||
* https://docs.oracle.com/javase/8/docs/api/java/util/Base64.html
|
* https://docs.oracle.com/javase/8/docs/api/java/util/Base64.html
|
||||||
*/
|
*/
|
||||||
@Lob
|
|
||||||
@Column(name = "icon", columnDefinition = "TEXT")
|
|
||||||
private byte[] icon;
|
|
||||||
|
|
||||||
@Lob
|
@Lob
|
||||||
@Column(name = "image", columnDefinition = "TEXT")
|
@Column(name = "image", columnDefinition = "TEXT")
|
||||||
private byte[] image;
|
private String image;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User that owns the house this room is in as a foreign key id. To use when updating and
|
* User that owns the house this room is in as a foreign key id. To use when updating and
|
||||||
|
@ -65,19 +165,19 @@ public class Room {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] getIcon() {
|
public Icon getIcon() {
|
||||||
return icon;
|
return icon;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setIcon(byte[] icon) {
|
public void setIcon(Icon icon) {
|
||||||
this.icon = icon;
|
this.icon = icon;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] getImage() {
|
public String getImage() {
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setImage(byte[] image) {
|
public void setImage(String image) {
|
||||||
this.image = image;
|
this.image = image;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,8 @@ public class Sensor extends InputDevice {
|
||||||
|
|
||||||
public void setSensor(SensorType sensor) {
|
public void setSensor(SensorType sensor) {
|
||||||
this.sensor = sensor;
|
this.sensor = sensor;
|
||||||
|
|
||||||
|
// TODO: setup hook for sockets live update
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getValue() {
|
public int getValue() {
|
||||||
|
|
|
@ -6,17 +6,19 @@ import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
/** A smart plug that can be turned either on or off */
|
/** A smart plug that can be turned either on or off */
|
||||||
@Entity
|
@Entity
|
||||||
public class SmartPlug extends OutputDevice {
|
public class SmartPlug extends Switchable {
|
||||||
|
|
||||||
/** Whether the smart plug is on */
|
/** Whether the smart plug is on */
|
||||||
@Column(name = "smart_plug_on", nullable = false)
|
@Column(name = "smart_plug_on", nullable = false)
|
||||||
@NotNull
|
@NotNull
|
||||||
private boolean on;
|
private boolean on;
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean isOn() {
|
public boolean isOn() {
|
||||||
return on;
|
return on;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void setOn(boolean on) {
|
public void setOn(boolean on) {
|
||||||
this.on = on;
|
this.on = on;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
|
package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
|
||||||
|
|
||||||
public interface SmartPlugRepository extends DeviceRepository<SmartPlug> {}
|
public interface SmartPlugRepository extends SwitchableRepository<SmartPlug> {}
|
||||||
|
|
|
@ -1,12 +1,18 @@
|
||||||
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.Column;
|
import javax.persistence.Column;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.OneToMany;
|
||||||
|
|
||||||
/** A switch input device */
|
/** A switch input device */
|
||||||
@Entity
|
@Entity
|
||||||
public class Switch extends InputDevice {
|
public class Switch extends InputDevice {
|
||||||
|
|
||||||
|
@OneToMany(mappedBy = "switchDevice")
|
||||||
|
private Set<Switchable> switchables = new HashSet<>();
|
||||||
|
|
||||||
/** The state of this switch */
|
/** The state of this switch */
|
||||||
@Column(nullable = false, name = "switch_on")
|
@Column(nullable = false, name = "switch_on")
|
||||||
private boolean on;
|
private boolean on;
|
||||||
|
@ -22,6 +28,15 @@ public class Switch extends InputDevice {
|
||||||
*/
|
*/
|
||||||
public void setOn(boolean state) {
|
public void setOn(boolean state) {
|
||||||
on = state;
|
on = state;
|
||||||
|
|
||||||
|
for (final Switchable s : switchables) {
|
||||||
|
s.setOn(on);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Toggle between on and off state */
|
||||||
|
public void toggle() {
|
||||||
|
setOn(!isOn());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -32,4 +47,8 @@ public class Switch extends InputDevice {
|
||||||
public boolean isOn() {
|
public boolean isOn() {
|
||||||
return on;
|
return on;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Set<Switchable> getOutputs() {
|
||||||
|
return switchables;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
|
||||||
|
|
||||||
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.config.GsonExclude;
|
||||||
|
import javax.persistence.*;
|
||||||
|
|
||||||
|
/** A device that can be turned either on or off */
|
||||||
|
@Entity
|
||||||
|
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
|
||||||
|
public abstract class Switchable extends OutputDevice {
|
||||||
|
|
||||||
|
public static final Connector<Switch, Switchable> SWITCH_SWITCHABLE_CONNECTOR =
|
||||||
|
Connector.basic(Switch::getOutputs, Switchable::setSwitchId);
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
@GsonExclude
|
||||||
|
@JoinColumn(name = "switch_id", updatable = false, insertable = false)
|
||||||
|
private Switch switchDevice;
|
||||||
|
|
||||||
|
@Column(name = "switch_id")
|
||||||
|
private Long switchId;
|
||||||
|
|
||||||
|
protected Switchable(String kind) {
|
||||||
|
super(kind);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the device is on (true) or not (false)
|
||||||
|
*
|
||||||
|
* @return whether the device is on (true) or not (false)
|
||||||
|
*/
|
||||||
|
public abstract boolean isOn();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the on status of the device
|
||||||
|
*
|
||||||
|
* @param on the new on status: true for on, false for off
|
||||||
|
*/
|
||||||
|
public abstract void setOn(boolean on);
|
||||||
|
|
||||||
|
public Long getSwitchId() {
|
||||||
|
return switchId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSwitchId(Long switchId) {
|
||||||
|
this.switchId = switchId;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SwitchableRepository acts as a superclass for the other repositories so to mirror in the database
|
||||||
|
* the class inheritance present among the various switchable devices.
|
||||||
|
*/
|
||||||
|
public interface SwitchableRepository<T extends Switchable> extends DeviceRepository<T> {}
|
|
@ -2,11 +2,6 @@ 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.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")
|
||||||
|
@ -19,25 +14,15 @@ public class User {
|
||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
/** The full name of the user */
|
/** The full name of the user */
|
||||||
@NotNull
|
|
||||||
@Column(nullable = false)
|
@Column(nullable = false)
|
||||||
@NotEmpty(message = "Please provide a full name")
|
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
/** The full username of the user */
|
/** The full username of the user */
|
||||||
@NotNull
|
|
||||||
@Column(nullable = false, unique = true)
|
@Column(nullable = false, unique = true)
|
||||||
@NotEmpty(message = "Please provide a username")
|
|
||||||
private String username;
|
private String username;
|
||||||
|
|
||||||
/** A properly salted way to store the password */
|
/** A properly salted way to store the password */
|
||||||
@NotNull
|
|
||||||
@Column(nullable = false)
|
@Column(nullable = false)
|
||||||
@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;
|
private String password;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -45,10 +30,6 @@ public class User {
|
||||||
* </code>, technically not RFC 5322 compliant
|
* </code>, technically not RFC 5322 compliant
|
||||||
*/
|
*/
|
||||||
@Column(nullable = false, unique = true)
|
@Column(nullable = false, unique = true)
|
||||||
@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;
|
private String email;
|
||||||
|
|
||||||
@Column(nullable = false)
|
@Column(nullable = false)
|
||||||
|
|
|
@ -22,4 +22,12 @@ spring.mail.properties.mail.smtp.starttls.required=true
|
||||||
spring.mail.properties.mail.smtp.auth=true
|
spring.mail.properties.mail.smtp.auth=true
|
||||||
spring.mail.properties.mail.smtp.connectiontimeout=5000
|
spring.mail.properties.mail.smtp.connectiontimeout=5000
|
||||||
spring.mail.properties.mail.smtp.timeout=5000
|
spring.mail.properties.mail.smtp.timeout=5000
|
||||||
spring.mail.properties.mail.smtp.writetimeout=5000
|
spring.mail.properties.mail.smtp.writetimeout=5000
|
||||||
|
|
||||||
|
email.registrationSubject=Complete your SmartHut.sm registration
|
||||||
|
email.registration=To confirm your registration, please click here:
|
||||||
|
email.registrationPath=http://localhost:8080/register/confirm-account?token=
|
||||||
|
|
||||||
|
email.resetpasswordSubject=SmartHut.sm password reset
|
||||||
|
email.resetpassword=To reset your password, please click here:
|
||||||
|
email.resetpasswordPath=http://localhost:3000/password-reset?token=
|
|
@ -0,0 +1,233 @@
|
||||||
|
package ch.usi.inf.sa4.sanmarinoes.smarthut;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.dto.JWTRequest;
|
||||||
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.dto.JWTResponse;
|
||||||
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.dto.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.UnauthorizedException;
|
||||||
|
import com.google.gson.JsonArray;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import java.util.Map;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
import org.springframework.boot.test.web.client.TestRestTemplate;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
|
||||||
|
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
|
||||||
|
@AutoConfigureMockMvc
|
||||||
|
public class AuthenticationTests extends SmartHutTest {
|
||||||
|
|
||||||
|
@Autowired private TestRestTemplate restTemplate;
|
||||||
|
|
||||||
|
private UserRegistrationRequest getDisabledUser() {
|
||||||
|
final UserRegistrationRequest disabledUser = new UserRegistrationRequest();
|
||||||
|
disabledUser.setName("Disabled User");
|
||||||
|
disabledUser.setEmail("disabled@example.com");
|
||||||
|
disabledUser.setUsername("disabled");
|
||||||
|
disabledUser.setPassword("password");
|
||||||
|
return disabledUser;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final UserRegistrationRequest enabledUser = new UserRegistrationRequest();
|
||||||
|
|
||||||
|
static {
|
||||||
|
enabledUser.setName("Enabled User");
|
||||||
|
enabledUser.setEmail("enabled@example.com");
|
||||||
|
enabledUser.setUsername("enabled");
|
||||||
|
enabledUser.setPassword("password");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setUp() {
|
||||||
|
final ResponseEntity<OkResponse> res =
|
||||||
|
this.restTemplate.postForEntity(
|
||||||
|
this.url("/register"), getDisabledUser(), OkResponse.class);
|
||||||
|
assertThat(res.getStatusCode().equals(HttpStatus.OK));
|
||||||
|
|
||||||
|
final ResponseEntity<OkResponse> res2 =
|
||||||
|
this.restTemplate.postForEntity(
|
||||||
|
this.url("/register"), enabledUser, OkResponse.class);
|
||||||
|
assertThat(res2.getStatusCode().equals(HttpStatus.OK));
|
||||||
|
|
||||||
|
// TODO: email confirmation for enabledUser
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void registrationShouldReturnBadRequestWithIncorrectFields() {
|
||||||
|
final Map<String, Object> badJSON = Map.of("luciano", "goretti", "danilo", "malusa");
|
||||||
|
|
||||||
|
assertThat(
|
||||||
|
this.restTemplate
|
||||||
|
.postForEntity(url("/register"), badJSON, JWTResponse.class)
|
||||||
|
.getStatusCode()
|
||||||
|
.equals(HttpStatus.BAD_REQUEST));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void registrationShouldReturnBadRequestWithShortPassword() {
|
||||||
|
final UserRegistrationRequest request = new UserRegistrationRequest();
|
||||||
|
request.setName("Mario Goretti");
|
||||||
|
request.setEmail("test@example.com");
|
||||||
|
request.setUsername("mgo");
|
||||||
|
request.setPassword("passw");
|
||||||
|
|
||||||
|
final ResponseEntity<JsonObject> res =
|
||||||
|
this.restTemplate.postForEntity(url("/register"), request, JsonObject.class);
|
||||||
|
assertThat(res.getStatusCode().equals(HttpStatus.BAD_REQUEST));
|
||||||
|
assertThat(res.getBody() != null);
|
||||||
|
|
||||||
|
final JsonArray errors = res.getBody().getAsJsonArray("errors");
|
||||||
|
assertThat(errors.size() == 1);
|
||||||
|
assertThat(errors.get(0).getAsJsonObject().get("field").getAsString().equals("password"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void registrationShouldReturnBadRequestWithWrongEmail() {
|
||||||
|
final UserRegistrationRequest request = new UserRegistrationRequest();
|
||||||
|
request.setName("Mario Goretti");
|
||||||
|
request.setEmail("test@example");
|
||||||
|
request.setUsername("mgo");
|
||||||
|
request.setPassword("password");
|
||||||
|
|
||||||
|
final ResponseEntity<JsonObject> res =
|
||||||
|
this.restTemplate.postForEntity(url("/register"), request, JsonObject.class);
|
||||||
|
assertThat(res.getStatusCode().equals(HttpStatus.BAD_REQUEST));
|
||||||
|
assertThat(res.getBody() != null);
|
||||||
|
|
||||||
|
final JsonArray errors = res.getBody().getAsJsonArray("errors");
|
||||||
|
assertThat(errors.size() == 1);
|
||||||
|
assertThat(errors.get(0).getAsJsonObject().get("field").getAsString().equals("email"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void registrationShouldReturnBadRequestWithNoName() {
|
||||||
|
final UserRegistrationRequest request = new UserRegistrationRequest();
|
||||||
|
request.setEmail("test@example.com");
|
||||||
|
request.setUsername("mgo");
|
||||||
|
request.setPassword("password");
|
||||||
|
|
||||||
|
final ResponseEntity<JsonObject> res =
|
||||||
|
this.restTemplate.postForEntity(url("/register"), request, JsonObject.class);
|
||||||
|
assertThat(res.getStatusCode().equals(HttpStatus.BAD_REQUEST));
|
||||||
|
assertThat(res.getBody() != null);
|
||||||
|
|
||||||
|
final JsonArray errors = res.getBody().getAsJsonArray("errors");
|
||||||
|
assertThat(errors.size() == 1);
|
||||||
|
assertThat(errors.get(0).getAsJsonObject().get("field").getAsString().equals("name"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void registrationShouldReturnBadRequestWithNoUsername() {
|
||||||
|
final UserRegistrationRequest request = new UserRegistrationRequest();
|
||||||
|
request.setName("Mario Goretti");
|
||||||
|
request.setEmail("test@example.com");
|
||||||
|
request.setPassword("password");
|
||||||
|
|
||||||
|
final ResponseEntity<JsonObject> res =
|
||||||
|
this.restTemplate.postForEntity(url("/register"), request, JsonObject.class);
|
||||||
|
assertThat(res.getStatusCode().equals(HttpStatus.BAD_REQUEST));
|
||||||
|
assertThat(res.getBody() != null);
|
||||||
|
|
||||||
|
final JsonArray errors = res.getBody().getAsJsonArray("errors");
|
||||||
|
assertThat(errors.size() == 1);
|
||||||
|
assertThat(errors.get(0).getAsJsonObject().get("field").getAsString().equals("username"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void registrationShouldReturnBadRequestWithDuplicateData() {
|
||||||
|
{
|
||||||
|
final ResponseEntity<DuplicateRegistrationException> res =
|
||||||
|
this.restTemplate.postForEntity(
|
||||||
|
url("/register"),
|
||||||
|
getDisabledUser(),
|
||||||
|
DuplicateRegistrationException.class);
|
||||||
|
assertThat(res.getStatusCode().equals(HttpStatus.BAD_REQUEST));
|
||||||
|
assertThat(res.getBody() != null);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
final UserRegistrationRequest disabledUserDifferentMail = getDisabledUser();
|
||||||
|
enabledUser.setEmail("another@example.com");
|
||||||
|
|
||||||
|
final ResponseEntity<DuplicateRegistrationException> res =
|
||||||
|
this.restTemplate.postForEntity(
|
||||||
|
url("/register"),
|
||||||
|
disabledUserDifferentMail,
|
||||||
|
DuplicateRegistrationException.class);
|
||||||
|
assertThat(res.getStatusCode().equals(HttpStatus.BAD_REQUEST));
|
||||||
|
assertThat(res.getBody() != null);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
final UserRegistrationRequest disabledUserDifferentUsername = getDisabledUser();
|
||||||
|
enabledUser.setUsername("another");
|
||||||
|
|
||||||
|
final ResponseEntity<DuplicateRegistrationException> res =
|
||||||
|
this.restTemplate.postForEntity(
|
||||||
|
url("/register"),
|
||||||
|
disabledUserDifferentUsername,
|
||||||
|
DuplicateRegistrationException.class);
|
||||||
|
assertThat(res.getStatusCode().equals(HttpStatus.BAD_REQUEST));
|
||||||
|
assertThat(res.getBody() != null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void registrationShouldReturnOkWithCorrectData() {
|
||||||
|
final UserRegistrationRequest request = new UserRegistrationRequest();
|
||||||
|
request.setName("Registration Test");
|
||||||
|
request.setUsername("smarthut");
|
||||||
|
request.setEmail("smarthut.sm@example.com");
|
||||||
|
request.setPassword("password");
|
||||||
|
|
||||||
|
final ResponseEntity<OkResponse> res =
|
||||||
|
this.restTemplate.postForEntity(url("/register"), request, OkResponse.class);
|
||||||
|
assertThat(res.getStatusCode().equals(HttpStatus.OK));
|
||||||
|
assertThat(res.getBody() != null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void loginShouldReturnBadRequestWithIncorrectFields() {
|
||||||
|
final Map<String, Object> badJSON = Map.of("badkey", 3, "password", "ciaomamma");
|
||||||
|
|
||||||
|
assertThat(
|
||||||
|
this.restTemplate
|
||||||
|
.postForEntity(url("/auth/login"), badJSON, JWTResponse.class)
|
||||||
|
.getStatusCode()
|
||||||
|
.equals(HttpStatus.BAD_REQUEST));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void loginShouldReturnUnauthorizedWithNonExistantUser() {
|
||||||
|
final JWTRequest request = new JWTRequest();
|
||||||
|
request.setUsernameOrEmail("roberto");
|
||||||
|
request.setPassword("ciaomamma");
|
||||||
|
|
||||||
|
final ResponseEntity<UnauthorizedException> res =
|
||||||
|
this.restTemplate.postForEntity(
|
||||||
|
url("/auth/login"), request, UnauthorizedException.class);
|
||||||
|
assertThat(res.getStatusCode().equals(HttpStatus.UNAUTHORIZED));
|
||||||
|
assertThat(res.getBody() != null);
|
||||||
|
assertThat(!res.getBody().isUserDisabled());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void loginShouldReturnUnauthorizedWithDisabledUser() {
|
||||||
|
final JWTRequest request = new JWTRequest();
|
||||||
|
request.setUsernameOrEmail("disabled");
|
||||||
|
request.setPassword("password");
|
||||||
|
|
||||||
|
final ResponseEntity<UnauthorizedException> res =
|
||||||
|
this.restTemplate.postForEntity(
|
||||||
|
url("/auth/login"), request, UnauthorizedException.class);
|
||||||
|
assertThat(res.getStatusCode().equals(HttpStatus.UNAUTHORIZED));
|
||||||
|
assertThat(res.getBody() != null);
|
||||||
|
assertThat(res.getBody().isUserDisabled());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
package ch.usi.inf.sa4.sanmarinoes.smarthut;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
|
||||||
|
public abstract class SmartHutTest {
|
||||||
|
private boolean setupDone = false;
|
||||||
|
|
||||||
|
protected final String getBaseURL() {
|
||||||
|
return "http://localhost:2000/";
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final String url(final String url) {
|
||||||
|
return getBaseURL() + url;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void setUp() {}
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setUpHack() {
|
||||||
|
if (!setupDone) {
|
||||||
|
setUp();
|
||||||
|
setupDone = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,11 +1,26 @@
|
||||||
package ch.usi.inf.sa4.sanmarinoes.smarthut;
|
package ch.usi.inf.sa4.sanmarinoes.smarthut;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
|
||||||
|
|
||||||
@SpringBootTest
|
import org.junit.jupiter.api.Test;
|
||||||
class SmarthutApplicationTests {
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
import org.springframework.boot.test.web.client.TestRestTemplate;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
|
||||||
|
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
|
||||||
|
@AutoConfigureMockMvc
|
||||||
|
public class SmarthutApplicationTests extends SmartHutTest {
|
||||||
|
|
||||||
|
@Autowired private TestRestTemplate restTemplate;
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void contextLoads() {}
|
public void anonymousGreetingShouldNotBeAuthorized() throws Exception {
|
||||||
|
assertThat(
|
||||||
|
this.restTemplate
|
||||||
|
.getForEntity(getBaseURL(), Void.class)
|
||||||
|
.getStatusCode()
|
||||||
|
.equals(HttpStatus.UNAUTHORIZED));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
35
src/test/resources/application.properties
Normal file
35
src/test/resources/application.properties
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
spring.http.converters.preferred-json-mapper=gson
|
||||||
|
spring.datasource.driver-class-name=org.h2.Driver
|
||||||
|
spring.datasource.url=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1
|
||||||
|
spring.datasource.username=sa
|
||||||
|
spring.datasource.password=sa
|
||||||
|
|
||||||
|
# Hibernate properties
|
||||||
|
spring.jpa.show-sql=true
|
||||||
|
spring.jpa.hibernate.ddl-auto=update
|
||||||
|
spring.jpa.hibernate.naming.implicit-strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyJpaCompliantImpl
|
||||||
|
spring.jpa.properties.hibernate.format_sql=true
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
server.port = 2000
|
||||||
|
|
||||||
|
email.registrationSubject=Complete your SmartHut.sm registration
|
||||||
|
email.registration=To confirm your registration, please click here:
|
||||||
|
email.registrationPath=http://localhost:8080/register/confirm-account?token=
|
||||||
|
|
||||||
|
email.resetpasswordSubject=SmartHut.sm password reset
|
||||||
|
email.resetpassword=To reset your password, please click here:
|
||||||
|
email.resetpasswordPath=http://localhost:3000/password-reset?token=
|
Loading…
Reference in a new issue