Skip to content
Snippets Groups Projects
Commit 64aad3c7 authored by Ondřej Trojan's avatar Ondřej Trojan
Browse files

Merge branch 'security' into 'master'

Security

See merge request trojaond/5d-backend!1
parents a5f3cd30 43ddd3ac
No related branches found
No related tags found
No related merge requests found
Showing
with 381 additions and 65 deletions
FROM openjdk:12-alpine
VOLUME /tpm
ARG JAR_FILE=target/5d-projection.jar
ARG JAR_FILE=target/5d-backend.jar
COPY ${JAR_FILE} app.jar
EXPOSE 8080
ENTRYPOINT ["java","-Djava.com.museum.projection.security.egd=file:/dev/./urandom","-jar","/app.jar"]
......
......@@ -2,14 +2,31 @@
This repository uses
Spring Boot
(MySQL)
(postgres)
## Getting started
### Using docker
First generate .jar file as is shown in Dockerfile. Then run as follows:
Spring boot requires running postgres db. For initial start run as stated below
```docker run --name 5d-postgres-manual -e POSTGRES_PASSWORD=password -d -p 5432:5432 postgres:alpine```
Then just start with
```docker start 5d-postgres-manual```
For the first time, you need to create a database. Connect to running container with
```docker exec -it 5d-postgres-manual bash```
and in container connecto to postgres
```psql -U postgres```
and run SQL command
```CREATE DATABASE projection;```
Then generate .jar file as is shown in Dockerfile. Then run as follows:
```
docker build -t spring .
&& docker run
......@@ -19,7 +36,9 @@ docker build -t spring .
spring
```
### Running VLC Instances
The server application requires running instances of VLC with RC interface. Such application is available at
https://gitlab.fel.cvut.cz/trojaond/5d.git
\ No newline at end of file
https://gitlab.fel.cvut.cz/trojaond/5d.git
......@@ -21,15 +21,15 @@
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
......@@ -39,10 +39,51 @@
<optional>true</optional>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>28.1-jre</version>
</dependency>
<!-- JDBC-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
</dependency>
<!-- END JDBC-->
<!-- JWT-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.10.7</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.10.7</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.10.7</version>
<scope>runtime</scope>
</dependency>
<!-- JWT - END-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
......
Manifest-Version: 1.0
Main-Class: com.museum.projection.Application
......@@ -19,9 +19,3 @@ public class Application {
}
//@Configuration
//@EnableScheduling
//@ConditionalOnProperty(name = "scheduling.enabled", matchIfMissing = true)
//class SchedulingConfiguration {
//
//}
\ No newline at end of file
package com.museum.projection.vlc;
package com.museum.projection.clients;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
......
package com.museum.projection.vlc;
package com.museum.projection.clients;
import java.util.List;
......
package com.museum.projection.vlc;
package com.museum.projection.clients;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
......
package com.museum.projection.config;
import com.google.common.net.HttpHeaders;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
@Configuration
@ConfigurationProperties(prefix = "5d.security.jwt")
public class JwtConfig {
private String secretKey;
private String tokenPrefix;
private Integer tokenExpirationAfterDays;
public JwtConfig() {
}
public String getSecretKey() {
return secretKey;
}
public void setSecretKey(String secretKey) {
this.secretKey = secretKey;
}
public String getTokenPrefix() {
return tokenPrefix;
}
public void setTokenPrefix(String tokenPrefix) {
this.tokenPrefix = tokenPrefix;
}
public Integer getTokenExpirationAfterDays() {
return tokenExpirationAfterDays;
}
public void setTokenExpirationAfterDays(Integer tokenExpirationAfterDays) {
this.tokenExpirationAfterDays = tokenExpirationAfterDays;
}
public String getAuthorizationHeader() {
return HttpHeaders.AUTHORIZATION;
}
}
package com.museum.projection.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
@Configuration
public class PasswordConfig {
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(10);
}
}
package com.museum.projection.vlc;
package com.museum.projection.config;
import com.museum.projection.config.CustomConfig;
import com.museum.projection.clients.DummyClient;
import com.museum.projection.clients.RemoteClient;
import com.museum.projection.clients.VlcClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
......
package com.museum.projection.controller;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api")
public class ApiController {
@GetMapping("/")
public String fakeLogin() {
return "Api";
}
}
package com.museum.projection.controller;
import com.museum.projection.models.ControlEntity;
import com.museum.projection.model.ControlEntity;
import com.museum.projection.service.ControlService;
import com.museum.projection.service.ResponseService;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
@Controller
@RequestMapping("/control")
public class MainController {
@RestController
@RequestMapping("/api/vlc")
public class ApliVlcController {
@Resource()
public ResponseService responseService;
@Resource
public ControlService controlService;
@GetMapping()
public String Index(@RequestParam(name = "name", required = false, defaultValue = "World") String name, Model model) {
model.addAttribute("name", responseService.changeName(name));
return "index";
}
@GetMapping("/main")
public String main(@RequestParam(name = "name", required = false, defaultValue = "World") String name, Model model) {
model.addAttribute("name", responseService.changeName(name));
return "main";
}
@PostMapping(value = "/play", produces = "application/json")
public ResponseEntity play() {
controlService.play();
......@@ -61,15 +44,16 @@ public class MainController {
"Video set to pause", HttpStatus.OK);
}
@PostMapping(value = "/shutdown", produces = "application/json")
public ResponseEntity shutdown(@RequestParam String clientId) {
@RequestMapping(value = "/shutdown/{id}", produces = "application/json", method = RequestMethod.POST)
@ResponseBody
public ResponseEntity shutdown(@PathVariable("id") String clientId) {
controlService.shutdownById(clientId);
return new ResponseEntity<>(
"Client "+clientId+ " set to shutdown", HttpStatus.OK);
"Client " + clientId + " set to shutdown", HttpStatus.OK);
}
@GetMapping("/")
@GetMapping("/test")
public List<String> get() {
return List.of("Hello", "edited", "s");
}
......
package com.museum.projection.controller;
import com.museum.projection.service.ResponseService;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.security.Principal;
@Controller
public class PageController {
@Resource()
public ResponseService responseService;
@GetMapping
public String Index(Principal principal, Model model) {
if(principal != null) {
model.addAttribute("name",principal.getName());
return "main";
}
return "index";
}
@GetMapping("/signin")
public String Login() {
return "login";
}
}
package com.museum.projection.dao;
import com.museum.projection.security.ApplicationUser;
import java.util.Optional;
public interface ApplicationUserDao {
Optional<ApplicationUser> selectApplicationUserByUsername(String username);
}
package com.museum.projection.dao;
import com.google.common.collect.Lists;
import com.museum.projection.security.ApplicationUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Optional;
import static com.museum.projection.security.ApplicationUserRole.*;
@Repository("fake")
public class FakeApplicationUserDaoService implements ApplicationUserDao {
private final PasswordEncoder passwordEncoder;
@Autowired
public FakeApplicationUserDaoService(PasswordEncoder passwordEncoder) {
this.passwordEncoder = passwordEncoder;
}
@Override
public Optional<ApplicationUser> selectApplicationUserByUsername(String username) {
return getApplicationUsers()
.stream()
.filter(applicationUser -> username.equals(applicationUser.getUsername()))
.findFirst();
}
private List<ApplicationUser> getApplicationUsers() {
List<ApplicationUser> applicationUsers = Lists.newArrayList(
new ApplicationUser(
STUDENT.getGrantedAuthorities(),
passwordEncoder.encode("password"),
"annasmith",
true,
true,
true,
true
),
new ApplicationUser(
ADMIN.getGrantedAuthorities(),
passwordEncoder.encode("nimda"),
"admin",
true,
true,
true,
true
),
new ApplicationUser(
ADMINTRAINEE.getGrantedAuthorities(),
passwordEncoder.encode("tom"),
"tom",
true,
true,
true,
true
)
);
return applicationUsers;
}
}
package com.museum.projection.dao;
import com.museum.projection.model.Account;
import com.museum.projection.security.ApplicationUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
import java.util.stream.Collectors;
import static com.museum.projection.security.ApplicationUserRole.*;
@Repository("postgres")
public class PostgresApplicationUserDaoService implements ApplicationUserDao {
private final PasswordEncoder passwordEncoder;
private final JdbcTemplate jdbcTemplate;
@Autowired
public PostgresApplicationUserDaoService(PasswordEncoder passwordEncoder, JdbcTemplate jdbcTemplate) {
this.passwordEncoder = passwordEncoder;
this.jdbcTemplate = jdbcTemplate;
}
@Override
public Optional<ApplicationUser> selectApplicationUserByUsername(String username) {
return getApplicationUsers()
.stream()
.filter(applicationUser -> username.equals(applicationUser.getUsername()))
.findFirst();
}
private List<ApplicationUser> getApplicationUsers() {
List<ApplicationUser> applicationUsers = getAccounts().stream().map(x -> new ApplicationUser(
ADMIN.getGrantedAuthorities(),
x.getPassword(),
x.getUsername(),
true,
true,
true,
true)).collect(Collectors.toList());
return applicationUsers;
}
private List<Account> getAccounts() {
final String sql = "SELECT id, username, password FROM account";
List<Account> accounts = jdbcTemplate.query(sql, (resultSet, i) -> {
UUID id = UUID.fromString(resultSet.getString("id"));
String name = resultSet.getString("username");
String password = resultSet.getString("password");
return new Account(id, name, password);
});
return accounts;
}
}
\ No newline at end of file
package com.museum.projection.datasource;
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class PostgresDatasource {
@Bean
@ConfigurationProperties("app.datasource")
public HikariDataSource hikariDataSource(){
return DataSourceBuilder
.create()
.type(HikariDataSource.class)
.build();
}
}
package com.museum.projection.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import javax.validation.constraints.NotBlank;
import java.util.UUID;
public class Account {
private final UUID id;
@NotBlank
private final String username;
@NotBlank
private final String password;
public Account(@JsonProperty("id") UUID id, @JsonProperty("username") String username, @JsonProperty("password") String password) {
this.id = id;
this.username = username;
this.password = password;
}
public UUID getId() {
return id;
}
public String getUsername() {
return username;
}
public String getPassword() {
return password;
}
}
package com.museum.projection.models;
package com.museum.projection.model;
import com.fasterxml.jackson.annotation.JsonProperty;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment