Skip to content

Commit

Permalink
v1
Browse files Browse the repository at this point in the history
  • Loading branch information
ChabVlad committed Sep 19, 2024
1 parent ea2f942 commit 9a7eda3
Show file tree
Hide file tree
Showing 17 changed files with 309 additions and 10 deletions.
6 changes: 6 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,12 @@
<scope>runtime</scope>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
<version>3.3.3</version>
</dependency>

<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
Expand Down
41 changes: 41 additions & 0 deletions src/main/java/project/bookstore/config/SecurityConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package project.bookstore.config;

import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
@EnableMethodSecurity
@RequiredArgsConstructor
public class SecurityConfig {
private final UserDetailsService userDetailsService;

@Bean
public PasswordEncoder getPasswordEncoder() {
return new BCryptPasswordEncoder();
}

@Bean
public SecurityFilterChain getSecurityFilterChain(HttpSecurity http) throws Exception {
return http
.cors(AbstractHttpConfigurer::disable)
.csrf(AbstractHttpConfigurer::disable)
.authorizeHttpRequests(
auth -> auth
.requestMatchers("/auth/**", "/swagger-ui/**", "/v3/api-docs/**")
.permitAll()
.anyRequest()
.authenticated()
)
.userDetailsService(userDetailsService)
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Pageable;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
Expand All @@ -23,6 +24,7 @@
@Tag(name = "Book controller", description = "endpoints for managing library")
@RequiredArgsConstructor
@RestController
//@PreAuthorize("hasAnyRole('ROLE_ADMIN', 'ROLE_USER')")
@RequestMapping("/books")
public class BookController {
private final BookService bookService;
Expand All @@ -45,6 +47,7 @@ public BookDto getBookById(@PathVariable Long id) {
}

@PostMapping
@PreAuthorize("has_role('ROLE_ADMIN')")
@Operation(
summary = "Create new book",
description = "Create new book and add to db")
Expand Down
27 changes: 27 additions & 0 deletions src/main/java/project/bookstore/model/Role.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package project.bookstore.model;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import org.springframework.security.core.GrantedAuthority;

@Entity
@Table(name = "roles")
public class Role implements GrantedAuthority {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true, nullable = false)
@Enumerated(EnumType.STRING)
private RoleName role;

@Override
public String getAuthority() {
return role.name();
}
}
6 changes: 6 additions & 0 deletions src/main/java/project/bookstore/model/RoleName.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package project.bookstore.model;

public enum RoleName {
USER,
ADMIN
}
33 changes: 27 additions & 6 deletions src/main/java/project/bookstore/model/User.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,51 @@
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.JoinTable;
import jakarta.persistence.ManyToMany;
import jakarta.persistence.Table;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import lombok.Getter;
import lombok.Setter;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

@Entity
@Table(name = "users")
@Getter
@Setter
public class User {
public class User implements UserDetails {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column(unique = true, nullable = false)
private String email;

@Column(nullable = false)
private String password;

@Column(nullable = false)
private String firstName;

@Column(nullable = false)
private String lastName;

private String shippingAddress;
@Column(nullable = false)
@ManyToMany
@JoinTable(
name = "users_roles",
joinColumns = @JoinColumn(name = "user_id"),
inverseJoinColumns = @JoinColumn(name = "role_id")
)
private Set<Role> roles = new HashSet<>();

@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return getRoles();
}

@Override
public String getUsername() {
return getEmail();
}
}
7 changes: 7 additions & 0 deletions src/main/java/project/bookstore/repository/role/RoleRepo.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package project.bookstore.repository.role;

import org.springframework.data.jpa.repository.JpaRepository;
import project.bookstore.model.Role;

public interface RoleRepo extends JpaRepository<Role, Integer> {
}
3 changes: 3 additions & 0 deletions src/main/java/project/bookstore/repository/user/UserRepo.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@
import org.springframework.stereotype.Repository;
import project.bookstore.model.User;

import java.util.Optional;

@Repository
public interface UserRepo extends JpaRepository<User, Integer> {
Boolean existsUserByEmail(String email);
Optional<User> findByEmail(String email);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package project.bookstore.security;

import lombok.RequiredArgsConstructor;
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 project.bookstore.repository.user.UserRepo;

@Service
@RequiredArgsConstructor
public class CustomUserDetailsService implements UserDetailsService {
private final UserRepo userRepo;

@Override
public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
return userRepo.findByEmail(email)
.orElseThrow(() -> new UsernameNotFoundException("Can't find user by email: " + email));
}
}
2 changes: 1 addition & 1 deletion src/main/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ spring.application.name=BookStore
spring.datasource.url=jdbc:mysql://localhost/book_store?serverTimezone=UTC
spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=pass
spring.datasource.password=!Vladius080197

spring.jpa.hibernate.ddl-auto=validate
spring.jpa.show-sql=true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ databaseChangeLog:
author: vlad
changes:
- createTable:
- tableName: books
- columns:
tableName: books
columns:
- column:
name: id
type: bigint
Expand Down
21 changes: 21 additions & 0 deletions src/main/resources/db/changelog/changes/03_create_roles_table.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
databaseChangeLog:
- changeSet:
id: create_roles_table
author: vlad
changes:
- createTable:
tableName: roles
columns:
- column:
name: id
type: bigint
autoIncrement: true
constraints:
primaryKey: true
nullable: false
- column:
name: role
type: varchar(255)
constraints:
unique: true
nullable: false
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
databaseChangeLog:
- changeSet:
id: create_users_roles_table
author: vlad
changes:
- createTable:
tableName: users_roles
columns:
- column:
name: user_id
type: bigint
constraints:
primaryKey: true
nullable: false
foreignKeyName: fk_users_id
references: users(id)
- column:
name: role_id
type: bigint
constraints:
primaryKey: true
nullable: false
foreignKeyName: fk_roles_id
references: roles(id)
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
databaseChangeLog:
- changeSet:
id: add_role_id_to_users
author: vlad
changes:
- addColumn:
tableName: users
columns:
- column:
name: role_id
type: bigint
constraints:
nullable: false
98 changes: 98 additions & 0 deletions src/main/resources/db/changelog/changes/06_insert_users_to_db.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
databaseChangeLog:
- changeSet:
id: 1
author: vlad
changes:
- insert:
tableName: roles
columns:
- column:
name: id
valueNumeric: 1
- column:
name: role
value: ROLE_USER
- insert:
tableName: roles
columns:
- column:
name: id
valueNumeric: 2
- column:
name: role
value: ROLE_ADMIN

- changeSet:
id: 2
author: vlad
changes:
- insert:
tableName: users
columns:
- column:
name: id
valueNumeric: 1
- column:
name: email
value: [email protected]
- column:
name: password
value: encodedPassword1
- column:
name: first_name
value: John
- column:
name: last_name
value: Doe
- column:
name: shipping_address
value: 123 Main St, City, Country
- column:
name: role_id
valueNumeric: 1
- insert:
tableName: users
columns:
- column:
name: id
valueNumeric: 2
- column:
name: email
value: [email protected]
- column:
name: password
value: encodedPassword2
- column:
name: first_name
value: Admin
- column:
name: last_name
value: User
- column:
name: shipping_address
value: 456 Admin St, City, Country
- column:
name: role_id
valueNumeric: 2
- changeSet:
id: 3
author: vlad
changes:
- insert:
tableName: users_roles
columns:
- column:
name: user_id
valueNumeric: 1
- column:
name: role_id
valueNumeric: 1
- insert:
tableName: users_roles
columns:
- column:
name: user_id
valueNumeric: 2
- column:
name: role_id
valueNumeric: 2
Loading

0 comments on commit 9a7eda3

Please sign in to comment.