From c6a769c1b8f61fb754b7e399e665943a160024b7 Mon Sep 17 00:00:00 2001 From: tommi27 Date: Thu, 27 Feb 2020 17:24:08 +0100 Subject: [PATCH 1/8] updated button and knob dimmers --- .../smarthut/models/ButtonDimmer.java | 43 ++++++++++++++++ .../smarthut/models/KnobDimmer.java | 50 +++++++++++++++++++ 2 files changed, 93 insertions(+) diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/ButtonDimmer.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/ButtonDimmer.java index e666c3e..e44e990 100644 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/ButtonDimmer.java +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/ButtonDimmer.java @@ -1,6 +1,9 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut.models; +import java.util.HashSet; +import java.util.Set; 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 @@ -8,7 +11,47 @@ import javax.persistence.Entity; */ @Entity public class ButtonDimmer extends Dimmer { + @OneToMany(mappedBy = "") + private Set lights = new HashSet(); + public ButtonDimmer() { super("button-dimmer"); } + + /** Increases the current intensity level of the dimmable light by 1 */ + public void increaseIntensity() { + for (DimmableLight dl : lights) { + dl.setIntensity(dl.getIntensity() + 1); + } + } + + /** Decreases the current intensity level of the dimmable light by 1 */ + public void decreaseIntensity() { + for (DimmableLight dl : lights) { + dl.setIntensity(dl.getIntensity() - 1); + } + } + + /** + * Adds a DimmableLight to this set of DimmableLights + * + * @param dl The DimmableLight to be added + */ + public void addLight(DimmableLight dl) { + lights.add(dl); + } + + /** + * Removes the given DimmableLight + * + * @param dl The DimmableLight to be removed + */ + public void removeLight(DimmableLight dl) { + lights.remove(dl); + } + + /** Clears this set */ + public void clearSet() { + lights.clear(); + } } diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/KnobDimmer.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/KnobDimmer.java index 80d59ab..e34ef76 100644 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/KnobDimmer.java +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/KnobDimmer.java @@ -1,6 +1,9 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut.models; +import java.util.HashSet; +import java.util.Set; import javax.persistence.Entity; +import javax.persistence.OneToMany; /** * Represents a dimmer able to set absolute intensity values (i.e. knowing the absolute intensity @@ -8,7 +11,54 @@ import javax.persistence.Entity; */ @Entity public class KnobDimmer extends Dimmer { + @OneToMany(mappedBy = "") + private Set lights = new HashSet(); + public KnobDimmer() { super("knob-dimmer"); } + + /** + * Increases or decreases the current intensity level by 5, moving between absolute multiples of + * 5 between 0 and 100, of all dimmable lights mapped to this knob + * + * @param inc The direction the knob is turned with + */ + public void modifyIntensity(boolean inc) { + + for (DimmableLight dl : lights) { + int remainder = dl.getIntensity() / 5; + + if (inc) { + dl.setIntensity(dl.getIntensity() - remainder); + dl.setIntensity((dl.getIntensity() + 5) % 105); + } else { + dl.setIntensity(dl.getIntensity() + (5 - remainder)); + dl.setIntensity((dl.getIntensity() - 5) % 105); + } + } + } + + /** + * Adds a DimmableLight to this set of DimmableLights + * + * @param dl The DimmableLight to be added + */ + public void addLight(DimmableLight dl) { + lights.add(dl); + } + + /** + * Removes the given DimmableLight + * + * @param dl The DimmableLight to be removed + */ + public void removeLight(DimmableLight dl) { + lights.remove(dl); + } + + /** Clears this set */ + public void clearSet() { + lights.clear(); + } } From 01ccf6d968b09228d5c6341587f290976ca0199c Mon Sep 17 00:00:00 2001 From: tommi27 Date: Fri, 28 Feb 2020 15:28:55 +0100 Subject: [PATCH 2/8] wip --- .idea/codeStyles/codeStyleConfig.xml | 5 +++++ .idea/misc.xml | 2 +- .../smarthut/models/ButtonDimmer.java | 2 +- .../smarthut/models/KnobDimmer.java | 2 +- .../sanmarinoes/smarthut/models/Switch.java | 18 ++++++++++++++++++ 5 files changed, 26 insertions(+), 3 deletions(-) create mode 100644 .idea/codeStyles/codeStyleConfig.xml diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000..a55e7a1 --- /dev/null +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index 7c6191b..c2c3244 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,7 +1,7 @@ - + \ No newline at end of file diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/ButtonDimmer.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/ButtonDimmer.java index e44e990..23a69f8 100644 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/ButtonDimmer.java +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/ButtonDimmer.java @@ -11,7 +11,7 @@ import javax.persistence.OneToMany; */ @Entity public class ButtonDimmer extends Dimmer { - @OneToMany(mappedBy = "") + @OneToMany(mappedBy = "button_dimmer") private Set lights = new HashSet(); public ButtonDimmer() { diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/KnobDimmer.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/KnobDimmer.java index e34ef76..5c5c603 100644 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/KnobDimmer.java +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/KnobDimmer.java @@ -11,7 +11,7 @@ import javax.persistence.OneToMany; */ @Entity public class KnobDimmer extends Dimmer { - @OneToMany(mappedBy = "") + @OneToMany(mappedBy = "knob_dimmer") private Set lights = new HashSet(); public KnobDimmer() { diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/Switch.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/Switch.java index fbf1eed..cdc6a35 100644 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/Switch.java +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/Switch.java @@ -1,11 +1,29 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut.models; +import javax.persistence.Column; import javax.persistence.Entity; /** A switch input device TODO: define switch behaviour (push button vs on/off state) */ @Entity public class Switch extends InputDevice { + + /** The state of this switch */ + @Column private boolean switchState = false; + public Switch() { super("switch"); } + + /** + * Setter method for Switch + * + * @param state The state to be set + */ + void setState(boolean state) { + switchState = state; + } + + boolean getState() { + return switchState; + } } From 11d3679fdb4d4ff2af13495b143a4b3ef27679c9 Mon Sep 17 00:00:00 2001 From: Claudio Maggioni Date: Fri, 28 Feb 2020 16:57:32 +0100 Subject: [PATCH 3/8] Fix to email constraint --- .gitignore | 2 ++ .idea/misc.xml | 2 +- .../inf/sa4/sanmarinoes/smarthut/models/User.java | 12 ++++++------ 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/.gitignore b/.gitignore index 69ca520..1375525 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ +.idea/misc.xml + **/.DS_Store # Compiled class file diff --git a/.idea/misc.xml b/.idea/misc.xml index 7c6191b..241f098 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,7 +1,7 @@ - + \ No newline at end of file diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/User.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/User.java index e4ce24e..7909fe8 100644 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/User.java +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/User.java @@ -2,11 +2,7 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut.models; import java.util.Set; import javax.persistence.*; -import javax.validation.constraints.Email; -import javax.validation.constraints.Min; -import javax.validation.constraints.NotEmpty; -import javax.validation.constraints.NotNull; -import javax.validation.constraints.Pattern; +import javax.validation.constraints.*; /** A user of the Smarthut application */ @Entity(name = "smarthutuser") @@ -33,7 +29,11 @@ public class User { @NotNull @Column(nullable = false) @NotEmpty(message = "Please provide a password") - @Min(value = 6, message = "Your password should be at least 6 characters long") + @Size( + min = 6, + max = 255, + message = + "Your password should be at least 6 characters long and at most 255 chars long") private String password; /** From 5d1549cfa20b7d50b7f27f915d1169ace5253c70 Mon Sep 17 00:00:00 2001 From: tommi27 Date: Fri, 28 Feb 2020 17:06:42 +0100 Subject: [PATCH 4/8] room controller updated --- .../smarthut/controller/RoomController.java | 40 +++++++++++------ .../smarthut/dto/RoomSaveRequest.java | 43 +++++++++++++++++++ .../sanmarinoes/smarthut/models/Device.java | 2 +- .../sanmarinoes/smarthut/models/Switch.java | 14 ++++-- .../sa4/sanmarinoes/smarthut/models/User.java | 2 +- 5 files changed, 81 insertions(+), 20 deletions(-) create mode 100644 src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/dto/RoomSaveRequest.java diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/RoomController.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/RoomController.java index 9ff6e2e..a25e4b5 100644 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/RoomController.java +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/RoomController.java @@ -1,11 +1,12 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut.controller; +import ch.usi.inf.sa4.sanmarinoes.smarthut.dto.RoomSaveRequest; import ch.usi.inf.sa4.sanmarinoes.smarthut.models.*; +import java.security.Principal; import java.util.*; import javax.validation.Valid; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.*; -import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.web.bind.annotation.*; @@ -28,27 +29,38 @@ public class RoomController { return roomRepository.findById(id); } - @PostMapping - public Room save(@Valid @RequestBody Room r) { - final Object principal = - SecurityContextHolder.getContext().getAuthentication().getPrincipal(); - - if (!(principal instanceof UserDetails)) { - throw new IllegalStateException("User is not logged in"); - } + private Room save(final RoomSaveRequest r, final Principal principal, boolean setWhenNull) { + Room newRoom = new Room(); final String username = ((UserDetails) principal).getUsername(); final Long userId = userRepository.findByUsername(username).getId(); + final String img = r.getImage(); + final String icon = r.getIcon(); - r.setUserId(userId); - r.setUser(null); + newRoom.setUserId(userId); + newRoom.setUser(null); + if (img != null) { + newRoom.setImage(img.getBytes()); + } else if (setWhenNull) { + newRoom.setImage(null); + } + if (icon != null) { + newRoom.setIcon(icon.getBytes()); + } else if (setWhenNull) { + newRoom.setIcon(null); + } - return roomRepository.save(r); + return roomRepository.save(newRoom); + } + + @PostMapping + public Room create(@Valid @RequestBody RoomSaveRequest r, final Principal principal) { + return this.save(r, principal, true); } @PutMapping - public Room update(@Valid @RequestBody Room r) { - return roomRepository.save(r); + public Room update(@Valid @RequestBody RoomSaveRequest r, final Principal principal) { + return this.save(r, principal, false); } @DeleteMapping("/{id}") diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/dto/RoomSaveRequest.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/dto/RoomSaveRequest.java new file mode 100644 index 0000000..f813b1c --- /dev/null +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/dto/RoomSaveRequest.java @@ -0,0 +1,43 @@ +package ch.usi.inf.sa4.sanmarinoes.smarthut.dto; + +import javax.persistence.Lob; +import javax.validation.constraints.NotNull; + +public class RoomSaveRequest { + /** + * Icon and image are 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: + * https://www.baeldung.com/java-base64-image-string + * https://docs.oracle.com/javase/8/docs/api/java/util/Base64.html + */ + @Lob private String icon; + + @Lob private String image; + + /** The user given name of this room (e.g. 'Master bedroom') */ + @NotNull private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getIcon() { + return icon; + } + + public void setIcon(String icon) { + this.icon = icon; + } + + public String getImage() { + return image; + } + + public void setImage(String image) { + this.image = image; + } +} diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/Device.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/Device.java index 834104d..0d5d959 100644 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/Device.java +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/Device.java @@ -21,7 +21,7 @@ public abstract class Device { /** Device identifier */ @Id @GeneratedValue(strategy = GenerationType.AUTO) - @Column(name = "id", updatable = false, nullable = false) + @Column(name = "id", updatable = false, nullable = false, unique = true) private long id; /** The room this device belongs in */ diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/Switch.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/Switch.java index cdc6a35..6f0eb99 100644 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/Switch.java +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/Switch.java @@ -8,22 +8,28 @@ import javax.persistence.Entity; public class Switch extends InputDevice { /** The state of this switch */ - @Column private boolean switchState = false; + @Column(nullable = false, name = "switch_on") + private boolean on; public Switch() { super("switch"); } /** - * Setter method for Switch + * Setter method for this Switch * * @param state The state to be set */ void setState(boolean state) { - switchState = state; + on = state; } + /** + * Getter method for this Switch + * + * @return This Switch on state + */ boolean getState() { - return switchState; + return on; } } diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/User.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/User.java index e4ce24e..a3b9202 100644 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/User.java +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/User.java @@ -40,7 +40,7 @@ public class User { * The user's email (validated according to criteria used in >input type="email"<> * , technically not RFC 5322 compliant */ - @Column(nullable = false) + @Column(nullable = false, unique = true) @NotNull @NotEmpty(message = "Please provide an email") @Email(message = "Please provide a valid email address") From 6be9c80c6ea8a5cbe591d43ba3a9589d68c65052 Mon Sep 17 00:00:00 2001 From: Claudio Maggioni Date: Sun, 1 Mar 2020 12:15:43 +0100 Subject: [PATCH 5/8] Work on Swagger integration --- build.gradle | 3 ++ .../smarthut/config/GsonConfig.java | 36 +++++++++++++++++++ .../smarthut/config/SpringFoxConfig.java | 25 +++++++++++++ .../smarthut/config/WebSecurityConfig.java | 14 +++++--- .../controller/AuthenticationController.java | 24 +++++++++---- .../sanmarinoes/smarthut/models/Device.java | 11 ++++-- .../sa4/sanmarinoes/smarthut/models/Room.java | 4 +++ .../sa4/sanmarinoes/smarthut/models/User.java | 3 ++ 8 files changed, 107 insertions(+), 13 deletions(-) create mode 100644 src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/config/GsonConfig.java create mode 100644 src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/config/SpringFoxConfig.java diff --git a/build.gradle b/build.gradle index ea7614f..728859b 100644 --- a/build.gradle +++ b/build.gradle @@ -10,6 +10,7 @@ sourceCompatibility = "11" repositories { mavenCentral() + jcenter() } dependencies { @@ -20,6 +21,8 @@ dependencies { implementation 'io.jsonwebtoken:jjwt:0.9.1' implementation 'org.springframework.security:spring-security-web' implementation 'org.postgresql:postgresql' + compile "io.springfox:springfox-swagger2:2.9.2" + compile group: 'io.springfox', name: 'springfox-swagger-ui', version: '2.9.2' implementation('org.springframework.boot:spring-boot-starter-web') { exclude group: 'org.springframework.boot', module: 'spring-boot-starter-json' diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/config/GsonConfig.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/config/GsonConfig.java new file mode 100644 index 0000000..3a2ab37 --- /dev/null +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/config/GsonConfig.java @@ -0,0 +1,36 @@ +package ch.usi.inf.sa4.sanmarinoes.smarthut.config; + +import com.google.gson.*; +import java.lang.reflect.Type; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.converter.json.GsonHttpMessageConverter; +import springfox.documentation.spring.web.json.Json; + +/** + * Spring configuration in order to register the GSON type adapter needed to avoid serializing twice + * Springfox Swagger JSON output (see: https://stackoverflow.com/a/30220562) + */ +@Configuration +public class GsonConfig { + @Bean + public GsonHttpMessageConverter gsonHttpMessageConverter() { + GsonHttpMessageConverter converter = new GsonHttpMessageConverter(); + converter.setGson(gson()); + return converter; + } + + private Gson gson() { + final GsonBuilder builder = new GsonBuilder(); + builder.registerTypeAdapter(Json.class, new SpringfoxJsonToGsonAdapter()); + return builder.create(); + } +} + +/** GSON type adapter needed to avoid serializing twice Springfox Swagger JSON output */ +class SpringfoxJsonToGsonAdapter implements JsonSerializer { + @Override + public JsonElement serialize(Json json, Type type, JsonSerializationContext context) { + return JsonParser.parseString(json.value()); + } +} diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/config/SpringFoxConfig.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/config/SpringFoxConfig.java new file mode 100644 index 0000000..ad88e75 --- /dev/null +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/config/SpringFoxConfig.java @@ -0,0 +1,25 @@ +package ch.usi.inf.sa4.sanmarinoes.smarthut.config; + +import ch.usi.inf.sa4.sanmarinoes.smarthut.controller.AuthenticationController; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import springfox.documentation.builders.PathSelectors; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spring.web.plugins.Docket; +import springfox.documentation.swagger2.annotations.EnableSwagger2; + +@Configuration +@EnableSwagger2 +@ComponentScan(basePackageClasses = {AuthenticationController.class}) +public class SpringFoxConfig { + @Bean + public Docket api() { + return new Docket(DocumentationType.SWAGGER_2) + .select() + .apis(RequestHandlerSelectors.any()) + .paths(PathSelectors.any()) + .build(); + } +} diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/config/WebSecurityConfig.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/config/WebSecurityConfig.java index a8bcb1d..bb548f0 100644 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/config/WebSecurityConfig.java +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/config/WebSecurityConfig.java @@ -50,13 +50,17 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter { .disable() // dont authenticate this particular request .authorizeRequests() - .antMatchers("/auth/login") + .antMatchers( + "/auth/login", + "/auth/register", + "/swagger-ui.html", + "/v2/api-docs", + "/webjars/**", + "/swagger-resources/**", + "/csrf") .permitAll() - .antMatchers("/auth/register") - .permitAll() - . // all other requests need to be authenticated - anyRequest() + .anyRequest() .authenticated() .and() . diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/AuthenticationController.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/AuthenticationController.java index ed82692..0ba000e 100644 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/AuthenticationController.java +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/AuthenticationController.java @@ -7,7 +7,6 @@ import ch.usi.inf.sa4.sanmarinoes.smarthut.dto.UserUpdateRequest; import ch.usi.inf.sa4.sanmarinoes.smarthut.models.*; import java.security.Principal; import javax.validation.Valid; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.DisabledException; @@ -21,18 +20,31 @@ import org.springframework.web.bind.annotation.*; @RequestMapping("/auth") public class AuthenticationController { - @Autowired private AuthenticationManager authenticationManager; + private final AuthenticationManager authenticationManager; - @Autowired private UserRepository userRepository; + private final UserRepository userRepository; - @Autowired private JWTTokenUtil jwtTokenUtil; + private final JWTTokenUtil jwtTokenUtil; - @Autowired private JWTUserDetailsService userDetailsService; + private final JWTUserDetailsService userDetailsService; - @Autowired private UserRepository users; + private final UserRepository users; private BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(); + public AuthenticationController( + AuthenticationManager authenticationManager, + UserRepository userRepository, + JWTTokenUtil jwtTokenUtil, + JWTUserDetailsService userDetailsService, + UserRepository users) { + this.authenticationManager = authenticationManager; + this.userRepository = userRepository; + this.jwtTokenUtil = jwtTokenUtil; + this.userDetailsService = userDetailsService; + this.users = users; + } + @PostMapping("/login") public JWTResponse login(@RequestBody JWTRequest authenticationRequest) throws Exception { authenticate(authenticationRequest.getUsername(), authenticationRequest.getPassword()); diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/Device.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/Device.java index 834104d..63ce4d2 100644 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/Device.java +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/Device.java @@ -1,6 +1,7 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut.models; import com.google.gson.annotations.SerializedName; +import io.swagger.annotations.ApiModelProperty; import javax.persistence.*; import javax.validation.constraints.NotNull; @@ -22,11 +23,13 @@ public abstract class Device { @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "id", updatable = false, nullable = false) + @ApiModelProperty(hidden = true) private long id; /** The room this device belongs in */ @ManyToOne @JoinColumn(name = "room_id", nullable = false, updatable = false, insertable = false) + @ApiModelProperty(hidden = true) private Room room; /** @@ -46,13 +49,17 @@ public abstract class Device { * The name for the category of this particular device (e.g 'dimmer'). Not stored in the * database but set thanks to constructors */ - @Transient private final String kind; + @ApiModelProperty(hidden = true) + @Transient + private final String kind; /** * The way this device behaves in the automation flow. Not stored in the database but set thanks * to constructors */ - @Transient private final FlowType flowType; + @ApiModelProperty(hidden = true) + @Transient + private final FlowType flowType; public long getId() { return id; diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/Room.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/Room.java index c0fae3f..4a82ab2 100644 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/Room.java +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/Room.java @@ -1,5 +1,6 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut.models; +import io.swagger.annotations.ApiModelProperty; import java.util.Set; import javax.persistence.*; import javax.validation.constraints.NotNull; @@ -11,6 +12,7 @@ public class Room { @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "id", updatable = false, nullable = false) + @ApiModelProperty(hidden = true) private Long id; /** @@ -41,12 +43,14 @@ public class Room { private String name; /** Collection of devices present in this room */ + @ApiModelProperty(hidden = true) @OneToMany(mappedBy = "room") private Set devices; /** User that owns the house this room is in */ @ManyToOne @JoinColumn(name = "user_id", nullable = false, updatable = false, insertable = false) + @ApiModelProperty(hidden = true) private User user; public Long getId() { diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/User.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/User.java index 7909fe8..8c6798b 100644 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/User.java +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/User.java @@ -1,5 +1,6 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut.models; +import io.swagger.annotations.ApiModelProperty; import java.util.Set; import javax.persistence.*; import javax.validation.constraints.*; @@ -11,6 +12,7 @@ public class User { @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "id", updatable = false, nullable = false) + @ApiModelProperty(hidden = true) private Long id; /** The full name of the user */ @@ -49,6 +51,7 @@ public class User { /** All rooms in the user's house */ @OneToMany(mappedBy = "user") + @ApiModelProperty(hidden = true) private Set rooms; public Long getId() { From 0257a9a89c57d8deb5e4388467c301f163cb8cc2 Mon Sep 17 00:00:00 2001 From: Claudio Maggioni Date: Sun, 1 Mar 2020 13:38:51 +0100 Subject: [PATCH 6/8] Idea misc.xml removed --- .idea/misc.xml | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 .idea/misc.xml diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index 241f098..0000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file From b294144a2289ff0af58e7975f574543550461218 Mon Sep 17 00:00:00 2001 From: Claudio Maggioni Date: Sun, 1 Mar 2020 13:46:15 +0100 Subject: [PATCH 7/8] Idea configuration removed so not to cause complaining for the SDK different installations between team members --- .gitignore | 2 +- .idea/.name | 1 - .idea/jarRepositories.xml | 20 -------------------- .idea/vcs.xml | 6 ------ 4 files changed, 1 insertion(+), 28 deletions(-) delete mode 100644 .idea/.name delete mode 100644 .idea/jarRepositories.xml delete mode 100644 .idea/vcs.xml diff --git a/.gitignore b/.gitignore index 1375525..1b1a367 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ -.idea/misc.xml +.idea/** **/.DS_Store diff --git a/.idea/.name b/.idea/.name deleted file mode 100644 index 03128f2..0000000 --- a/.idea/.name +++ /dev/null @@ -1 +0,0 @@ -smarthut \ No newline at end of file diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml deleted file mode 100644 index fdc392f..0000000 --- a/.idea/jarRepositories.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 35eb1dd..0000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file From 6ce90e61cb7b108c16e240e1d867bb9ecd93bee6 Mon Sep 17 00:00:00 2001 From: Claudio Maggioni Date: Sun, 1 Mar 2020 15:13:37 +0100 Subject: [PATCH 8/8] Swagger configuration --- .../smarthut/config/SpringFoxConfig.java | 60 +++++++++++++++++-- .../controller/AuthenticationController.java | 14 +++-- .../smarthut/models/ButtonDimmer.java | 43 ------------- .../smarthut/models/KnobDimmer.java | 50 ---------------- 4 files changed, 65 insertions(+), 102 deletions(-) diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/config/SpringFoxConfig.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/config/SpringFoxConfig.java index ad88e75..743d119 100644 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/config/SpringFoxConfig.java +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/config/SpringFoxConfig.java @@ -1,25 +1,77 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut.config; -import ch.usi.inf.sa4.sanmarinoes.smarthut.controller.AuthenticationController; +import static springfox.documentation.builders.PathSelectors.regex; + +import java.util.List; +import java.util.function.Predicate; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; -import springfox.documentation.builders.PathSelectors; +import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.service.ApiInfo; +import springfox.documentation.service.ApiKey; +import springfox.documentation.service.SecurityScheme; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger2.annotations.EnableSwagger2; +/** + * This class configures the automated REST documentation tool Swagger for this project. The + * documentation can be seen by going to http://localhost:8080/swaggeer-ui.html + */ @Configuration @EnableSwagger2 -@ComponentScan(basePackageClasses = {AuthenticationController.class}) +@ComponentScan("ch.usi.inf.sa4.sanmarinoes.smarthut") public class SpringFoxConfig { + + /** + * Main definition of Springfox / swagger configuration + * + * @return a Docket object containing the swagger configuration + */ @Bean public Docket api() { return new Docket(DocumentationType.SWAGGER_2) .select() .apis(RequestHandlerSelectors.any()) - .paths(PathSelectors.any()) + .paths(paths()::test) + .build() + .apiInfo(apiInfo()) + .securitySchemes(securitySchemes()); + } + + /** + * Configures the documentation about the smarthut authentication system + * + * @return a list of springfox authentication configurations + */ + private static List securitySchemes() { + return List.of(new ApiKey("Bearer", "Authorization", "header")); + } + + /** + * Configures the paths the documentation must be generated for. Add a path here only when the + * spec has been totally defined. + * + * @return A predicate that tests whether a path must be included or not + */ + private Predicate paths() { + return regex("/auth.*")::apply; + } + + /** + * Returns the metadata about the smarthut project + * + * @return metadata about smarthut + */ + private ApiInfo apiInfo() { + return new ApiInfoBuilder() + .title("SmartHut.sm API") + .description("Backend API for the SanMariones version of the SA4 SmartHut project") + .termsOfServiceUrl("https://www.youtube.com/watch?v=9KxTcDsy9Gs") + .license("WTFPL") + .version("dev branch") .build(); } } diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/AuthenticationController.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/AuthenticationController.java index 0ba000e..e4c575e 100644 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/AuthenticationController.java +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/AuthenticationController.java @@ -5,6 +5,7 @@ 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.UserUpdateRequest; import ch.usi.inf.sa4.sanmarinoes.smarthut.models.*; +import io.swagger.annotations.Authorization; import java.security.Principal; import javax.validation.Valid; import org.springframework.security.authentication.AuthenticationManager; @@ -61,15 +62,18 @@ public class AuthenticationController { return user; } + @Authorization(value = "Bearer") @PatchMapping("/update") - public User update(@Valid @RequestBody final UserUpdateRequest u, final Principal principal) { + public User update( + @Valid @RequestBody final UserUpdateRequest userData, final Principal principal) { final User oldUser = userRepository.findByUsername(principal.getName()); - if (u.getName() != null) oldUser.setName(u.getName()); - if (u.getEmail() != null) { - oldUser.setEmail(u.getEmail()); + if (userData.getName() != null) oldUser.setName(userData.getName()); + if (userData.getEmail() != null) { + oldUser.setEmail(userData.getEmail()); // TODO: handle email verification } - if (u.getPassword() != null) oldUser.setPassword(encoder.encode(u.getPassword())); + if (userData.getPassword() != null) + oldUser.setPassword(encoder.encode(userData.getPassword())); return userRepository.save(oldUser); } diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/ButtonDimmer.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/ButtonDimmer.java index 23a69f8..e666c3e 100644 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/ButtonDimmer.java +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/ButtonDimmer.java @@ -1,9 +1,6 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut.models; -import java.util.HashSet; -import java.util.Set; 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 @@ -11,47 +8,7 @@ import javax.persistence.OneToMany; */ @Entity public class ButtonDimmer extends Dimmer { - @OneToMany(mappedBy = "button_dimmer") - private Set lights = new HashSet(); - public ButtonDimmer() { super("button-dimmer"); } - - /** Increases the current intensity level of the dimmable light by 1 */ - public void increaseIntensity() { - for (DimmableLight dl : lights) { - dl.setIntensity(dl.getIntensity() + 1); - } - } - - /** Decreases the current intensity level of the dimmable light by 1 */ - public void decreaseIntensity() { - for (DimmableLight dl : lights) { - dl.setIntensity(dl.getIntensity() - 1); - } - } - - /** - * Adds a DimmableLight to this set of DimmableLights - * - * @param dl The DimmableLight to be added - */ - public void addLight(DimmableLight dl) { - lights.add(dl); - } - - /** - * Removes the given DimmableLight - * - * @param dl The DimmableLight to be removed - */ - public void removeLight(DimmableLight dl) { - lights.remove(dl); - } - - /** Clears this set */ - public void clearSet() { - lights.clear(); - } } diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/KnobDimmer.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/KnobDimmer.java index 5c5c603..80d59ab 100644 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/KnobDimmer.java +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/KnobDimmer.java @@ -1,9 +1,6 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut.models; -import java.util.HashSet; -import java.util.Set; import javax.persistence.Entity; -import javax.persistence.OneToMany; /** * Represents a dimmer able to set absolute intensity values (i.e. knowing the absolute intensity @@ -11,54 +8,7 @@ import javax.persistence.OneToMany; */ @Entity public class KnobDimmer extends Dimmer { - @OneToMany(mappedBy = "knob_dimmer") - private Set lights = new HashSet(); - public KnobDimmer() { super("knob-dimmer"); } - - /** - * Increases or decreases the current intensity level by 5, moving between absolute multiples of - * 5 between 0 and 100, of all dimmable lights mapped to this knob - * - * @param inc The direction the knob is turned with - */ - public void modifyIntensity(boolean inc) { - - for (DimmableLight dl : lights) { - int remainder = dl.getIntensity() / 5; - - if (inc) { - dl.setIntensity(dl.getIntensity() - remainder); - dl.setIntensity((dl.getIntensity() + 5) % 105); - } else { - dl.setIntensity(dl.getIntensity() + (5 - remainder)); - dl.setIntensity((dl.getIntensity() - 5) % 105); - } - } - } - - /** - * Adds a DimmableLight to this set of DimmableLights - * - * @param dl The DimmableLight to be added - */ - public void addLight(DimmableLight dl) { - lights.add(dl); - } - - /** - * Removes the given DimmableLight - * - * @param dl The DimmableLight to be removed - */ - public void removeLight(DimmableLight dl) { - lights.remove(dl); - } - - /** Clears this set */ - public void clearSet() { - lights.clear(); - } }