security
This commit is contained in:
1 parent
2064ed5abc
commit
9efd7b3fb4
33 files changed
+595
-91
No files matched your search
+4
-2
@@ -7,7 +7,7 @@ plugins {
|
|||||||
|
|
||||||
group = 'site.easy-startup'
|
group = 'site.easy-startup'
|
||||||
version = '0.0.1-SNAPSHOT'
|
version = '0.0.1-SNAPSHOT'
|
||||||
sourceCompatibility = "16"
|
sourceCompatibility = "17"
|
||||||
|
|
||||||
configurations {
|
configurations {
|
||||||
compileOnly {
|
compileOnly {
|
||||||
@@ -20,6 +20,8 @@ repositories {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
implementation 'com.auth0:java-jwt:4.0.0'
|
||||||
|
implementation 'com.google.code.gson:gson:2.9.1'
|
||||||
implementation 'org.modelmapper:modelmapper:3.1.0'
|
implementation 'org.modelmapper:modelmapper:3.1.0'
|
||||||
implementation 'org.springframework.boot:spring-boot-starter-validation'
|
implementation 'org.springframework.boot:spring-boot-starter-validation'
|
||||||
implementation 'com.google.guava:guava:31.1-jre'
|
implementation 'com.google.guava:guava:31.1-jre'
|
||||||
@@ -43,4 +45,4 @@ dependencies {
|
|||||||
tasks.named('test') {
|
tasks.named('test') {
|
||||||
useJUnitPlatform()
|
useJUnitPlatform()
|
||||||
}
|
}
|
||||||
targetCompatibility = JavaVersion.VERSION_16
|
targetCompatibility = JavaVersion.VERSION_17
|
||||||
@@ -4,7 +4,6 @@ import org.springframework.boot.SpringApplication;
|
|||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
@RestController
|
|
||||||
@SpringBootApplication
|
@SpringBootApplication
|
||||||
public class EasyStartupApplication {
|
public class EasyStartupApplication {
|
||||||
|
|
||||||
|
|||||||
@@ -1,50 +1,50 @@
|
|||||||
package site.easystartup.web.auth.config;
|
//package site.easystartup.web.auth.config;
|
||||||
|
//
|
||||||
import lombok.RequiredArgsConstructor;
|
//import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
//import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.context.annotation.Configuration;
|
//import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
//import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
//import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
//import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
//import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
//import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
|
//
|
||||||
import javax.sql.DataSource;
|
//import javax.sql.DataSource;
|
||||||
|
//
|
||||||
@Configuration
|
//@Configuration
|
||||||
@EnableWebSecurity
|
//@EnableWebSecurity
|
||||||
@RequiredArgsConstructor(onConstructor_ = @Autowired)
|
//@RequiredArgsConstructor(onConstructor_ = @Autowired)
|
||||||
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
//public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||||
private final DataSource dataSource;
|
// private final DataSource dataSource;
|
||||||
|
//
|
||||||
private final PasswordEncoder passwordEncoder;
|
// private final PasswordEncoder passwordEncoder;
|
||||||
|
//
|
||||||
@Override
|
// @Override
|
||||||
protected void configure(HttpSecurity http) throws Exception {
|
// protected void configure(HttpSecurity http) throws Exception {
|
||||||
http
|
// http
|
||||||
.authorizeRequests()
|
// .authorizeRequests()
|
||||||
.antMatchers("/", "/home", "/registration").permitAll()
|
// .antMatchers("/", "/home", "/registration").permitAll()
|
||||||
.anyRequest().authenticated()
|
// .anyRequest().authenticated()
|
||||||
.and()
|
// .and()
|
||||||
.formLogin()
|
// .formLogin()
|
||||||
.loginPage("/login")
|
// .loginPage("/login")
|
||||||
.permitAll()
|
// .permitAll()
|
||||||
.and()
|
// .and()
|
||||||
.logout()
|
// .logout()
|
||||||
.permitAll()
|
// .permitAll()
|
||||||
.and()
|
// .and()
|
||||||
.rememberMe().userDetailsService(this.userDetailsService())
|
// .rememberMe().userDetailsService(this.userDetailsService())
|
||||||
.rememberMeServices(null)
|
// .rememberMeServices(null)
|
||||||
.tokenValiditySeconds(86400)
|
// .tokenValiditySeconds(86400)
|
||||||
.useSecureCookie(true);
|
// .useSecureCookie(true);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
@Override
|
// @Override
|
||||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
// protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||||
auth.jdbcAuthentication()
|
// auth.jdbcAuthentication()
|
||||||
.dataSource(dataSource)
|
// .dataSource(dataSource)
|
||||||
.passwordEncoder(passwordEncoder)
|
// .passwordEncoder(passwordEncoder)
|
||||||
.usersByUsernameQuery("SELECT username, password, active FROM usr WHERE username = ?;")
|
// .usersByUsernameQuery("SELECT username, password, active FROM usr WHERE username = ?;")
|
||||||
.authoritiesByUsernameQuery("SELECT u.username, ur.roles FROM usr u INNER JOIN user_role ur ON u.id = ur.user_id WHERE username = ?;");
|
// .authoritiesByUsernameQuery("SELECT u.username, ur.roles FROM usr u INNER JOIN user_role ur ON u.id = ur.user_id WHERE username = ?;");
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
package site.easystartup.web.auth.controller;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.modelmapper.ModelMapper;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.security.authentication.AuthenticationManager;
|
||||||
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||||
|
import org.springframework.security.core.Authentication;
|
||||||
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
|
import org.springframework.util.ObjectUtils;
|
||||||
|
import org.springframework.validation.BindingResult;
|
||||||
|
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.RestController;
|
||||||
|
import site.easystartup.web.domain.model.User;
|
||||||
|
import site.easystartup.web.domain.request.LoginRequest;
|
||||||
|
import site.easystartup.web.domain.request.SignupRequest;
|
||||||
|
import site.easystartup.web.domain.response.MessageResponse;
|
||||||
|
import site.easystartup.web.domain.response.SuccessAuthenticationResponse;
|
||||||
|
import site.easystartup.web.domain.validation.ResponseErrorValidation;
|
||||||
|
import site.easystartup.web.project.dto.UserDto;
|
||||||
|
import site.easystartup.web.security.JWTUtil;
|
||||||
|
import site.easystartup.web.security.SecurityConstants;
|
||||||
|
import site.easystartup.web.service.AuthService;
|
||||||
|
import site.easystartup.web.service.UserService;
|
||||||
|
|
||||||
|
import javax.validation.Valid;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/auth")
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class AuthController {
|
||||||
|
private final JWTUtil jwtUtil;
|
||||||
|
private final UserService userService;
|
||||||
|
private final AuthService authService;
|
||||||
|
private final AuthenticationManager authenticationManager;
|
||||||
|
private final ResponseErrorValidation responseErrorValidation;
|
||||||
|
private final ModelMapper modelMapper;
|
||||||
|
|
||||||
|
@PostMapping("/signup")
|
||||||
|
public ResponseEntity<Object> registration(@Valid @RequestBody SignupRequest signupRequest,
|
||||||
|
BindingResult bindingResult) {
|
||||||
|
ResponseEntity<Object> errors = responseErrorValidation.mapValidationService(bindingResult);
|
||||||
|
if (!ObjectUtils.isEmpty(errors)) return errors;
|
||||||
|
|
||||||
|
authService.createUser(signupRequest);
|
||||||
|
|
||||||
|
return ResponseEntity.ok(new MessageResponse("Account registered successfully!"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/login")
|
||||||
|
public ResponseEntity<Object> authentication(@Valid @RequestBody LoginRequest loginRequest,
|
||||||
|
BindingResult bindingResult) {
|
||||||
|
ResponseEntity<Object> errors = responseErrorValidation.mapValidationService(bindingResult);
|
||||||
|
if (!ObjectUtils.isEmpty(errors)) return errors;
|
||||||
|
|
||||||
|
Authentication authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(
|
||||||
|
loginRequest.getUsername(),
|
||||||
|
loginRequest.getPassword()
|
||||||
|
));
|
||||||
|
|
||||||
|
SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||||
|
|
||||||
|
String jwt = SecurityConstants.TOKEN_PREFIX + jwtUtil.generateToken(loginRequest.getUsername());
|
||||||
|
User user = userService.getUserByUsername(loginRequest.getUsername());
|
||||||
|
SuccessAuthenticationResponse response = new SuccessAuthenticationResponse(jwt, modelMapper.map(user, UserDto.class));
|
||||||
|
return ResponseEntity.ok().body(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package site.easystartup.web.domain.annotation;
|
||||||
|
|
||||||
|
import site.easystartup.web.domain.validation.PasswordMatchesValidator;
|
||||||
|
|
||||||
|
import javax.validation.Constraint;
|
||||||
|
import javax.validation.Payload;
|
||||||
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
|
@Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE})
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Constraint(validatedBy = PasswordMatchesValidator.class)
|
||||||
|
@Documented
|
||||||
|
public @interface PasswordMatches {
|
||||||
|
String message() default "Password do not match";
|
||||||
|
|
||||||
|
Class<?>[] groups() default{};
|
||||||
|
|
||||||
|
Class<? extends Payload>[] payload() default {};
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package site.easystartup.web.domain.exception;
|
||||||
|
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||||
|
|
||||||
|
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||||
|
public class UserExistException extends RuntimeException {
|
||||||
|
public UserExistException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,11 @@
|
|||||||
package site.easystartup.web.domain.model;
|
package site.easystartup.web.domain.model;
|
||||||
|
|
||||||
public enum Role {
|
public enum Role {
|
||||||
USER, PREMIUM, MODER, ADMIN;
|
USER("USER"), PREMIUM("PREMIUM"), MODER("MODER"), ADMIN("ADMIN");
|
||||||
|
|
||||||
|
private String role;
|
||||||
|
|
||||||
|
Role(String role) {
|
||||||
|
this.role = role;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -2,12 +2,13 @@ package site.easystartup.web.domain.model;
|
|||||||
|
|
||||||
import lombok.*;
|
import lombok.*;
|
||||||
import org.hibernate.Hibernate;
|
import org.hibernate.Hibernate;
|
||||||
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
|
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
import site.easystartup.web.project.domain.model.Participant;
|
import site.easystartup.web.project.domain.model.Participant;
|
||||||
|
|
||||||
import javax.persistence.*;
|
import javax.persistence.*;
|
||||||
import java.util.List;
|
import java.util.*;
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
@@ -15,7 +16,7 @@ import java.util.Set;
|
|||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "usr")
|
@Table(name = "usr")
|
||||||
public class User {
|
public class User implements UserDetails {
|
||||||
@Id
|
@Id
|
||||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||||
@Column(name = "user_id")
|
@Column(name = "user_id")
|
||||||
@@ -75,4 +76,31 @@ public class User {
|
|||||||
if (roles.contains(Role.PREMIUM) || roles.contains(Role.ADMIN)) return true;
|
if (roles.contains(Role.PREMIUM) || roles.contains(Role.ADMIN)) return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<? extends GrantedAuthority> getAuthorities() {
|
||||||
|
Collection<GrantedAuthority> authorities = new ArrayList<>();
|
||||||
|
getRoles().forEach(role -> authorities.add(new SimpleGrantedAuthority(role.name())));
|
||||||
|
return authorities;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAccountNonExpired() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAccountNonLocked() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isCredentialsNonExpired() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEnabled() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package site.easystartup.web.domain.request;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import javax.validation.constraints.Email;
|
||||||
|
import javax.validation.constraints.NotEmpty;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class LoginRequest {
|
||||||
|
@NotEmpty(message = "Username cannot be empty")
|
||||||
|
private String username;
|
||||||
|
@NotEmpty(message = "Password cannot be empty")
|
||||||
|
private String password;
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package site.easystartup.web.domain.request;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import site.easystartup.web.domain.annotation.PasswordMatches;
|
||||||
|
import site.easystartup.web.domain.model.Role;
|
||||||
|
|
||||||
|
import javax.validation.constraints.Email;
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
|
import javax.validation.constraints.NotEmpty;
|
||||||
|
import javax.validation.constraints.Size;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@PasswordMatches
|
||||||
|
public class SignupRequest {
|
||||||
|
@NotEmpty
|
||||||
|
@Size(min = 3, max = 30, message = "Username should be no less 3 and no more 30 signs")
|
||||||
|
private String username;
|
||||||
|
|
||||||
|
@Email(message = "It should have email format")
|
||||||
|
@NotBlank(message = "Email is required")
|
||||||
|
private String email;
|
||||||
|
|
||||||
|
@NotEmpty(message = "Password is required")
|
||||||
|
@Size(min = 6, max = 30, message = "Password should be no less 6 and no more 30 signs")
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
private String confirmPassword;
|
||||||
|
|
||||||
|
private Set<String> roles;
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package site.easystartup.web.domain.response;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
public class InvalidLoginResponse {
|
||||||
|
private String username;
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
public InvalidLoginResponse() {
|
||||||
|
this.username = "Invalid username";
|
||||||
|
this.password = "Invalid password";
|
||||||
|
}
|
||||||
|
}
|
||||||
+2
-2
@@ -3,10 +3,10 @@ package site.easystartup.web.domain.response;
|
|||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class ResponseMessage {
|
public class MessageResponse {
|
||||||
private String message;
|
private String message;
|
||||||
|
|
||||||
public ResponseMessage(String message) {
|
public MessageResponse(String message) {
|
||||||
this.message = message;
|
this.message = message;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package site.easystartup.web.domain.response;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
import site.easystartup.web.project.dto.UserDto;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class SuccessAuthenticationResponse {
|
||||||
|
private String jwt;
|
||||||
|
private UserDto userDto;
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package site.easystartup.web.domain.validation;
|
||||||
|
|
||||||
|
import site.easystartup.web.domain.annotation.PasswordMatches;
|
||||||
|
import site.easystartup.web.domain.request.SignupRequest;
|
||||||
|
|
||||||
|
import javax.validation.ConstraintValidator;
|
||||||
|
import javax.validation.ConstraintValidatorContext;
|
||||||
|
|
||||||
|
public class PasswordMatchesValidator implements ConstraintValidator<PasswordMatches, Object> {
|
||||||
|
@Override
|
||||||
|
public void initialize(PasswordMatches constraintAnnotation) {
|
||||||
|
ConstraintValidator.super.initialize(constraintAnnotation);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isValid(Object o, ConstraintValidatorContext constraintValidatorContext) {
|
||||||
|
SignupRequest signupRequest = (SignupRequest) o;
|
||||||
|
|
||||||
|
return signupRequest.getPassword().equals(signupRequest.getConfirmPassword());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,17 +6,13 @@ import org.modelmapper.ModelMapper;
|
|||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.security.access.annotation.Secured;
|
import org.springframework.security.access.annotation.Secured;
|
||||||
import org.springframework.stereotype.Controller;
|
|
||||||
import org.springframework.ui.Model;
|
|
||||||
import org.springframework.util.ObjectUtils;
|
import org.springframework.util.ObjectUtils;
|
||||||
import org.springframework.validation.BindingResult;
|
import org.springframework.validation.BindingResult;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import site.easystartup.web.domain.model.User;
|
import site.easystartup.web.domain.model.User;
|
||||||
import site.easystartup.web.domain.response.ResponseMessage;
|
import site.easystartup.web.domain.response.MessageResponse;
|
||||||
import site.easystartup.web.domain.validation.ResponseErrorValidation;
|
import site.easystartup.web.domain.validation.ResponseErrorValidation;
|
||||||
import site.easystartup.web.forum.domain.model.Discussion;
|
|
||||||
import site.easystartup.web.forum.domain.model.DiscussionMessage;
|
import site.easystartup.web.forum.domain.model.DiscussionMessage;
|
||||||
import site.easystartup.web.forum.domain.model.DiscussionStatus;
|
|
||||||
import site.easystartup.web.forum.domain.model.Topic;
|
import site.easystartup.web.forum.domain.model.Topic;
|
||||||
import site.easystartup.web.forum.domain.request.DiscussionMessageRequest;
|
import site.easystartup.web.forum.domain.request.DiscussionMessageRequest;
|
||||||
import site.easystartup.web.forum.domain.request.DiscussionRequest;
|
import site.easystartup.web.forum.domain.request.DiscussionRequest;
|
||||||
@@ -25,10 +21,7 @@ import site.easystartup.web.forum.dto.DiscussionDto;
|
|||||||
import site.easystartup.web.forum.dto.DiscussionMessageDto;
|
import site.easystartup.web.forum.dto.DiscussionMessageDto;
|
||||||
import site.easystartup.web.forum.dto.TopicDto;
|
import site.easystartup.web.forum.dto.TopicDto;
|
||||||
import site.easystartup.web.forum.service.ForumService;
|
import site.easystartup.web.forum.service.ForumService;
|
||||||
import site.easystartup.web.forum.repo.TopicRepo;
|
|
||||||
import site.easystartup.web.project.domain.model.Project;
|
|
||||||
import site.easystartup.web.project.domain.requst.ProjectRequest;
|
import site.easystartup.web.project.domain.requst.ProjectRequest;
|
||||||
import site.easystartup.web.project.dto.ProjectDto;
|
|
||||||
import site.easystartup.web.service.UserService;
|
import site.easystartup.web.service.UserService;
|
||||||
|
|
||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
@@ -151,9 +144,9 @@ public class ForumController {
|
|||||||
DiscussionMessage message = forumService.getDiscussionMessageById(message_id);
|
DiscussionMessage message = forumService.getDiscussionMessageById(message_id);
|
||||||
User user = userService.getUserByPrincipal(principal);
|
User user = userService.getUserByPrincipal(principal);
|
||||||
if(!(message.getSender().equals(user.getUsername()) || user.isModer()))
|
if(!(message.getSender().equals(user.getUsername()) || user.isModer()))
|
||||||
return ResponseEntity.ok(new ResponseMessage("No permissions!"));
|
return ResponseEntity.ok(new MessageResponse("No permissions!"));
|
||||||
forumService.deleteDiscussionMessage(message_id, user);
|
forumService.deleteDiscussionMessage(message_id, user);
|
||||||
return ResponseEntity.ok(new ResponseMessage("Message was deleted!"));
|
return ResponseEntity.ok(new MessageResponse("Message was deleted!"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import org.springframework.web.bind.annotation.*;
|
|||||||
import site.easystartup.web.project.domain.model.Project;
|
import site.easystartup.web.project.domain.model.Project;
|
||||||
import site.easystartup.web.project.domain.requst.ParticipantRequest;
|
import site.easystartup.web.project.domain.requst.ParticipantRequest;
|
||||||
import site.easystartup.web.project.domain.requst.ProjectRequest;
|
import site.easystartup.web.project.domain.requst.ProjectRequest;
|
||||||
import site.easystartup.web.domain.response.ResponseMessage;
|
import site.easystartup.web.domain.response.MessageResponse;
|
||||||
import site.easystartup.web.domain.validation.ResponseErrorValidation;
|
import site.easystartup.web.domain.validation.ResponseErrorValidation;
|
||||||
import site.easystartup.web.project.dto.ParticipantDto;
|
import site.easystartup.web.project.dto.ParticipantDto;
|
||||||
import site.easystartup.web.project.dto.ProjectDto;
|
import site.easystartup.web.project.dto.ProjectDto;
|
||||||
@@ -55,7 +55,7 @@ public class ProjectController {
|
|||||||
public ResponseEntity<Object> deleteProject(@PathVariable("projectId") Long projectId,
|
public ResponseEntity<Object> deleteProject(@PathVariable("projectId") Long projectId,
|
||||||
Principal principal) {
|
Principal principal) {
|
||||||
projectService.deleteProject(projectId, principal);
|
projectService.deleteProject(projectId, principal);
|
||||||
return ResponseEntity.ok(new ResponseMessage("Project was deleted!"));
|
return ResponseEntity.ok(new MessageResponse("Project was deleted!"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/{projectId}")
|
@GetMapping("/{projectId}")
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ public class Project {
|
|||||||
private int commercialStatus;
|
private int commercialStatus;
|
||||||
|
|
||||||
@ManyToMany
|
@ManyToMany
|
||||||
@JoinTable(
|
@JoinTable(name = "project_tag",
|
||||||
joinColumns = @JoinColumn(name = "project_id"),
|
joinColumns = @JoinColumn(name = "project_id"),
|
||||||
inverseJoinColumns = @JoinColumn(name = "tag_id")
|
inverseJoinColumns = @JoinColumn(name = "tag_id")
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,23 +1,25 @@
|
|||||||
package site.easystartup.web.project.dto;
|
package site.easystartup.web.project.dto;
|
||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
import site.easystartup.web.domain.model.Role;
|
import site.easystartup.web.domain.model.Role;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
public class UserDto implements Serializable {
|
public class UserDto implements Serializable {
|
||||||
private final long id;
|
private long id;
|
||||||
private final String username;
|
private String username;
|
||||||
private final String password;
|
private String password;
|
||||||
private final boolean active;
|
private boolean active;
|
||||||
private final String full_name;
|
private String full_name;
|
||||||
private final String status;
|
private String status;
|
||||||
private final String iconPath;
|
private String iconPath;
|
||||||
private final String email;
|
private String email;
|
||||||
private final Set<String> tags;
|
private Set<String> tags;
|
||||||
private final Set<String> professions;
|
private Set<String> professions;
|
||||||
private final Set<Long> projects;
|
private Set<Long> projects;
|
||||||
private final Set<Role> roles;
|
private Set<Role> roles;
|
||||||
}
|
}
|
||||||
@@ -11,6 +11,6 @@ import java.util.LinkedHashSet;
|
|||||||
|
|
||||||
@Repository
|
@Repository
|
||||||
public interface ParticipantRepo extends JpaRepository<Participant, Long> {
|
public interface ParticipantRepo extends JpaRepository<Participant, Long> {
|
||||||
@Query ("SELECT Project FROM Participant WHERE nameOfPosition = :nameOfPosition")
|
@Query ("SELECT p FROM Participant p WHERE p.nameOfPosition = :nameOfPosition")
|
||||||
LinkedHashSet<Project> findAllByNameOfPosition(@Param("nameOfPosition") String name);
|
LinkedHashSet<Project> findAllByNameOfPosition(@Param("nameOfPosition") String name);
|
||||||
}
|
}
|
||||||
@@ -6,6 +6,7 @@ import org.springframework.data.repository.query.Param;
|
|||||||
import org.springframework.stereotype.Repository;
|
import org.springframework.stereotype.Repository;
|
||||||
import site.easystartup.web.domain.model.User;
|
import site.easystartup.web.domain.model.User;
|
||||||
import site.easystartup.web.project.domain.model.Project;
|
import site.easystartup.web.project.domain.model.Project;
|
||||||
|
import site.easystartup.web.project.domain.model.Tag;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -13,9 +14,7 @@ import java.util.List;
|
|||||||
public interface ProjectRepo extends JpaRepository<Project, Long> {
|
public interface ProjectRepo extends JpaRepository<Project, Long> {
|
||||||
|
|
||||||
List<Project> findAllByOwnerOrderByCreatedDate(User owner);
|
List<Project> findAllByOwnerOrderByCreatedDate(User owner);
|
||||||
|
List<Project> findAllByTechnology(Tag tag);
|
||||||
@Query("SELECT p from Project p WHERE p.technology LIKE %:technology%")
|
|
||||||
List<Project> findAllByTechnology(@Param("technology") String tech);
|
|
||||||
|
|
||||||
List<Project> findAllByCommercialStatusOrderByCreatedDateAsc(int commercialStatus);
|
List<Project> findAllByCommercialStatusOrderByCreatedDateAsc(int commercialStatus);
|
||||||
|
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ public class ProjectService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public List<Project> getAllProjectsWithTechnology(String technology) {
|
public List<Project> getAllProjectsWithTechnology(String technology) {
|
||||||
return projectRepo.findAllByTechnology(technology.trim());
|
return projectRepo.findAllByTechnology(tagService.getTechnologyByName(technology.trim()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Project> getAllProjectsForCurrentUser(Principal principal) {
|
public List<Project> getAllProjectsForCurrentUser(Principal principal) {
|
||||||
|
|||||||
@@ -31,4 +31,8 @@ public class TagService {
|
|||||||
});
|
});
|
||||||
return tags;
|
return tags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Tag getTechnologyByName(String tag) {
|
||||||
|
return tagRepo.findTagByTagNameIgnoreCase(tag).orElseThrow(() -> new RuntimeException("Technolohy not found"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -3,6 +3,10 @@ package site.easystartup.web.repo;
|
|||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
import site.easystartup.web.domain.model.User;
|
import site.easystartup.web.domain.model.User;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
public interface UserRepo extends JpaRepository<User, Long> {
|
public interface UserRepo extends JpaRepository<User, Long> {
|
||||||
User findByUsername(String username);
|
User findByUsername(String username);
|
||||||
|
|
||||||
|
Optional<User> findUserByUsername(String username);
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package site.easystartup.web.security;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import org.springframework.security.core.AuthenticationException;
|
||||||
|
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import site.easystartup.web.domain.response.InvalidLoginResponse;
|
||||||
|
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
|
@Component
|
||||||
|
public class JWTAuthenticationEntryPoint implements AuthenticationEntryPoint {
|
||||||
|
@Override
|
||||||
|
public void commence(HttpServletRequest request,
|
||||||
|
HttpServletResponse response,
|
||||||
|
AuthenticationException authException) throws IOException, ServletException {
|
||||||
|
InvalidLoginResponse invalidLoginResponse = new InvalidLoginResponse();
|
||||||
|
String jsonLoginResponse = new Gson().toJson(invalidLoginResponse);
|
||||||
|
response.setContentType(SecurityConstants.HEADER_STRING);
|
||||||
|
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
|
||||||
|
response.getWriter().println(jsonLoginResponse);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
package site.easystartup.web.security;
|
||||||
|
|
||||||
|
import com.auth0.jwt.exceptions.JWTVerificationException;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||||
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
import org.springframework.web.filter.OncePerRequestFilter;
|
||||||
|
import site.easystartup.web.service.CustomUserDetailService;
|
||||||
|
|
||||||
|
import javax.servlet.FilterChain;
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class JWTFilter extends OncePerRequestFilter {
|
||||||
|
private final JWTUtil jwtUtil;
|
||||||
|
private final CustomUserDetailService userDetailService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doFilterInternal(HttpServletRequest request,
|
||||||
|
HttpServletResponse response,
|
||||||
|
FilterChain filterChain) throws ServletException, IOException {
|
||||||
|
String header = request.getHeader(SecurityConstants.HEADER_STRING);
|
||||||
|
|
||||||
|
if (StringUtils.hasText(header) && header.startsWith(SecurityConstants.TOKEN_PREFIX)) {
|
||||||
|
String jwt = header.split(" ")[1];
|
||||||
|
|
||||||
|
if (jwt.isEmpty()) {
|
||||||
|
response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Invalid JWT token in Bearer Header");
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
String email = jwtUtil.validateTokenAndRetrieveClaim(jwt);
|
||||||
|
UserDetails userDetails = userDetailService.loadUserByUsername(email);
|
||||||
|
|
||||||
|
UsernamePasswordAuthenticationToken authenticationToken =
|
||||||
|
new UsernamePasswordAuthenticationToken(userDetails,
|
||||||
|
userDetails.getPassword(),
|
||||||
|
userDetails.getAuthorities());
|
||||||
|
|
||||||
|
if (SecurityContextHolder.getContext().getAuthentication() == null) {
|
||||||
|
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
|
||||||
|
}
|
||||||
|
} catch (JWTVerificationException ex) {
|
||||||
|
response.sendError(HttpServletResponse.SC_BAD_REQUEST, " Invalid JWT token");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
filterChain.doFilter(request, response);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package site.easystartup.web.security;
|
||||||
|
|
||||||
|
import com.auth0.jwt.JWT;
|
||||||
|
import com.auth0.jwt.JWTVerifier;
|
||||||
|
import com.auth0.jwt.algorithms.Algorithm;
|
||||||
|
import com.auth0.jwt.exceptions.JWTVerificationException;
|
||||||
|
import com.auth0.jwt.interfaces.DecodedJWT;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
|
import java.util.Date;
|
||||||
|
@Component
|
||||||
|
public class JWTUtil {
|
||||||
|
public String generateToken(String username) {
|
||||||
|
|
||||||
|
Date expirationDate = Date.from(ZonedDateTime.now().plusDays(30).toInstant());
|
||||||
|
|
||||||
|
return JWT.create()
|
||||||
|
.withSubject("User details")
|
||||||
|
.withClaim("username", username)
|
||||||
|
.withIssuedAt(Date.from(ZonedDateTime.now().toInstant()))
|
||||||
|
.withIssuer("site.easystartup")
|
||||||
|
.withExpiresAt(expirationDate)
|
||||||
|
.sign(Algorithm.HMAC256(SecurityConstants.SECRET));
|
||||||
|
}
|
||||||
|
|
||||||
|
public String validateTokenAndRetrieveClaim(String token) throws JWTVerificationException {
|
||||||
|
JWTVerifier verifier = JWT.require(Algorithm.HMAC256(SecurityConstants.SECRET))
|
||||||
|
.withSubject("User details")
|
||||||
|
.withIssuer("site.easystartup")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
DecodedJWT decodedJWT = verifier.verify(token);
|
||||||
|
return decodedJWT.getClaim("username").asString();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
package site.easystartup.web.security;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.security.authentication.AuthenticationManager;
|
||||||
|
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||||
|
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
|
||||||
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
|
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||||
|
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||||
|
import org.springframework.security.config.http.SessionCreationPolicy;
|
||||||
|
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||||
|
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||||
|
import site.easystartup.web.service.CustomUserDetailService;
|
||||||
|
|
||||||
|
@EnableWebSecurity
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@EnableGlobalMethodSecurity(
|
||||||
|
securedEnabled = true,
|
||||||
|
jsr250Enabled = true,
|
||||||
|
prePostEnabled = true
|
||||||
|
)
|
||||||
|
public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
||||||
|
|
||||||
|
private final CustomUserDetailService customUserDetailService;
|
||||||
|
private final JWTAuthenticationEntryPoint jwtAuthenticationEntryPoint;
|
||||||
|
private final JWTFilter jwtFilter;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||||
|
auth.userDetailsService(customUserDetailService).passwordEncoder(bCryptPasswordEncoder());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configure(HttpSecurity http) throws Exception {
|
||||||
|
http.cors().and().csrf().disable()
|
||||||
|
.exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint)
|
||||||
|
.and()
|
||||||
|
.sessionManagement()
|
||||||
|
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
|
||||||
|
.and()
|
||||||
|
.authorizeRequests()
|
||||||
|
.antMatchers(SecurityConstants.SIGN_UP_URLS).permitAll()
|
||||||
|
// .antMatchers("/").permitAll();
|
||||||
|
.anyRequest().authenticated();
|
||||||
|
|
||||||
|
http.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@Override
|
||||||
|
public AuthenticationManager authenticationManagerBean() throws Exception {
|
||||||
|
return super.authenticationManagerBean();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
BCryptPasswordEncoder bCryptPasswordEncoder() {
|
||||||
|
return new BCryptPasswordEncoder();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package site.easystartup.web.security;
|
||||||
|
|
||||||
|
public class SecurityConstants {
|
||||||
|
public static final String SIGN_UP_URLS = "/api/auth/*";
|
||||||
|
|
||||||
|
public static final String SECRET = "SecretKeyGenJWT";
|
||||||
|
public static final String TOKEN_PREFIX = "Bearer ";
|
||||||
|
public static final String HEADER_STRING = "Authorization";
|
||||||
|
public static final String CONTENT_TYPE = "application/json";
|
||||||
|
// public static final long EXPIRATION_TIME = 600_000_000; //10min
|
||||||
|
public static final long EXPIRATION_TIME = Long.MAX_VALUE;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
package site.easystartup.web.service;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import site.easystartup.web.domain.exception.UserExistException;
|
||||||
|
import site.easystartup.web.domain.model.Role;
|
||||||
|
import site.easystartup.web.domain.model.User;
|
||||||
|
import site.easystartup.web.domain.request.SignupRequest;
|
||||||
|
import site.easystartup.web.repo.UserRepo;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class AuthService {
|
||||||
|
private final UserRepo userRepo;
|
||||||
|
private final PasswordEncoder passwordEncoder;
|
||||||
|
|
||||||
|
public User createUser(SignupRequest signupRequest) {
|
||||||
|
if (userRepo.findUserByUsername(signupRequest.getUsername()).isPresent()) {
|
||||||
|
throw new UserExistException("An account with this username already exists.");
|
||||||
|
}
|
||||||
|
|
||||||
|
User user = new User();
|
||||||
|
user.setEmail(signupRequest.getEmail());
|
||||||
|
user.setUsername(signupRequest.getUsername());
|
||||||
|
user.setPassword(passwordEncoder.encode(signupRequest.getPassword()));
|
||||||
|
Set<Role> roles = new HashSet<>();
|
||||||
|
signupRequest.getRoles().forEach(role -> roles.add(Role.valueOf(role)));
|
||||||
|
user.setRoles(roles);
|
||||||
|
|
||||||
|
return userRepo.save(user);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package site.easystartup.web.service;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||||
|
|
||||||
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||||
|
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import site.easystartup.web.domain.model.User;
|
||||||
|
import site.easystartup.web.repo.UserRepo;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class CustomUserDetailService implements UserDetailsService {
|
||||||
|
private final UserRepo userRepo;
|
||||||
|
@Override
|
||||||
|
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
|
||||||
|
User user = userRepo.findUserByUsername(username)
|
||||||
|
.orElseThrow(() -> new UsernameNotFoundException("User not found"));
|
||||||
|
|
||||||
|
Collection<SimpleGrantedAuthority> authorities = new ArrayList<>();
|
||||||
|
user.getRoles().forEach(role -> {
|
||||||
|
authorities.add(new SimpleGrantedAuthority(role.name()));
|
||||||
|
});
|
||||||
|
|
||||||
|
return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), authorities);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserDetails loadUserById(Long userId) {
|
||||||
|
User user = userRepo.findById(userId)
|
||||||
|
.orElseThrow(() -> new UsernameNotFoundException("User not found"));
|
||||||
|
return user;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -22,4 +22,8 @@ public class UserService {
|
|||||||
public User getUserById(Long userId) {
|
public User getUserById(Long userId) {
|
||||||
return userRepo.findById(userId).orElseThrow(() -> new UsernameNotFoundException("User not found"));
|
return userRepo.findById(userId).orElseThrow(() -> new UsernameNotFoundException("User not found"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public User getUserByUsername(String username) {
|
||||||
|
return userRepo.findUserByUsername(username).orElseThrow(() -> new UsernameNotFoundException("User not found"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,11 +1,12 @@
|
|||||||
package site.easystartup.web.storage.service;
|
package site.easystartup.web.storage.service;
|
||||||
|
|
||||||
import org.springframework.core.io.Resource;
|
import org.springframework.core.io.Resource;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
@Service
|
||||||
public interface StorageService {
|
public interface StorageService {
|
||||||
void init();
|
void init();
|
||||||
void save(MultipartFile file);
|
void save(MultipartFile file);
|
||||||
|
|||||||
@@ -9,3 +9,4 @@ spring.datasource.url=jdbc:postgresql://localhost:5432/testdb
|
|||||||
spring.datasource.username=postgres
|
spring.datasource.username=postgres
|
||||||
spring.datasource.password=root
|
spring.datasource.password=root
|
||||||
|
|
||||||
|
spring.security.filter.order=10
|
||||||
Reference in new issue
Block a user