diff --git a/module09/src/test/java/ru/sberbank/edu/AppTest.java b/module09/src/test/java/ru/sberbank/edu/AppTest.java
deleted file mode 100644
index 895d735c..00000000
--- a/module09/src/test/java/ru/sberbank/edu/AppTest.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package ru.sberbank.edu;
-
-import junit.framework.Test;
-import junit.framework.TestCase;
-import junit.framework.TestSuite;
-
-/**
- * Unit test for simple App.
- */
-public class AppTest
- extends TestCase
-{
- /**
- * Create the test case
- *
- * @param testName name of the test case
- */
- public AppTest( String testName )
- {
- super( testName );
- }
-
- /**
- * @return the suite of tests being tested
- */
- public static Test suite()
- {
- return new TestSuite( AppTest.class );
- }
-
- /**
- * Rigourous Test :-)
- */
- public void testApp()
- {
- assertTrue( true );
- }
-}
diff --git a/module13/.gitignore b/module13/.gitignore
new file mode 100644
index 00000000..5ff6309b
--- /dev/null
+++ b/module13/.gitignore
@@ -0,0 +1,38 @@
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### IntelliJ IDEA ###
+.idea/modules.xml
+.idea/jarRepositories.xml
+.idea/compiler.xml
+.idea/libraries/
+*.iws
+*.iml
+*.ipr
+
+### Eclipse ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/
+
+### Mac OS ###
+.DS_Store
\ No newline at end of file
diff --git a/module13/README.md b/module13/README.md
new file mode 100644
index 00000000..8c663473
--- /dev/null
+++ b/module13/README.md
@@ -0,0 +1,9 @@
+# Module 13. Docker
+
+### Требования:
+Доработать ДЗ 12, добавить возможность запускать приложение в контейнере.
+
+## Критерии приемки:
+
+1. Для запуска приложения использовать Docker (docker-compose.yml).
+2. В качестве бд использовать PostgreSQL (предпочтение) или любую другую бд.
\ No newline at end of file
diff --git a/module13/docker-compose.yml b/module13/docker-compose.yml
new file mode 100644
index 00000000..de348b7d
--- /dev/null
+++ b/module13/docker-compose.yml
@@ -0,0 +1,27 @@
+version: '3.8'
+
+services:
+ app:
+ build: .
+ ports:
+ - "8080:8080"
+ environment:
+ - SPRING_DATASOURCE_URL=jdbc:postgresql://db:5432/postgres
+ - SPRING_DATASOURCE_USERNAME=postgres
+ - SPRING_DATASOURCE_PASSWORD=mypassword
+ depends_on:
+ - db
+
+ db:
+ image: postgres:latest
+ environment:
+ - POSTGRES_DB=postgres
+ - POSTGRES_USER=postgres
+ - POSTGRES_PASSWORD=mypassword
+ ports:
+ - "5432:5432"
+ volumes:
+ - postgres_data:/var/lib/postgresql/data
+
+volumes:
+ postgres_data:
\ No newline at end of file
diff --git a/module13/dockerfile b/module13/dockerfile
new file mode 100644
index 00000000..838255fe
--- /dev/null
+++ b/module13/dockerfile
@@ -0,0 +1,4 @@
+FROM openjdk:17-slim
+COPY target/module13-0.0.1-SNAPSHOT.jar app.jar
+EXPOSE 8080
+ENTRYPOINT ["java", "-jar", "/app.jar"]
\ No newline at end of file
diff --git a/module13/pom.xml b/module13/pom.xml
new file mode 100644
index 00000000..fc1a80c0
--- /dev/null
+++ b/module13/pom.xml
@@ -0,0 +1,65 @@
+
+
+ 4.0.0
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 3.2.0
+
+
+ ru.edu
+ module13
+ 0.0.1-SNAPSHOT
+ module13
+ module13
+
+ 17
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-security
+
+
+
+ org.postgresql
+ postgresql
+ runtime
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ org.springframework.security
+ spring-security-test
+ test
+
+
+ org.projectlombok
+ lombok
+ RELEASE
+ compile
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/module13/src/main/java/ru/edu/module13/Application.java b/module13/src/main/java/ru/edu/module13/Application.java
new file mode 100644
index 00000000..106b56b5
--- /dev/null
+++ b/module13/src/main/java/ru/edu/module13/Application.java
@@ -0,0 +1,13 @@
+package ru.edu.module13;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+}
diff --git a/module13/src/main/java/ru/edu/module13/config/SecurityConfig.java b/module13/src/main/java/ru/edu/module13/config/SecurityConfig.java
new file mode 100644
index 00000000..f3a98e80
--- /dev/null
+++ b/module13/src/main/java/ru/edu/module13/config/SecurityConfig.java
@@ -0,0 +1,60 @@
+package ru.edu.module13.config;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.HttpMethod;
+import org.springframework.security.config.Customizer;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.security.web.SecurityFilterChain;
+import ru.edu.module13.entity.Auth;
+import ru.edu.module13.repository.AuthRepository;
+
+import java.util.stream.Collectors;
+
+@Configuration
+@EnableWebSecurity
+public class SecurityConfig {
+ @Autowired
+ private AuthRepository authRepository;
+
+ @Bean
+ public UserDetailsService userDetailsService() {
+ return username -> {
+ Auth auth = authRepository.findByUsername(username);
+ if (auth == null) {
+ throw new UsernameNotFoundException("Пользователь " + username + " не найден.");
+ }
+ return new org.springframework.security.core.userdetails.User(
+ auth.getUsername(),
+ auth.getPassword(),
+ auth.getRoles().stream()
+ .map(role -> new SimpleGrantedAuthority(role.getName()))
+ .collect(Collectors.toList()));
+ };
+ }
+
+ @Bean
+ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
+ http
+ .csrf((csrf) -> csrf.disable())
+ .authorizeHttpRequests((authorize) -> authorize
+ .requestMatchers(HttpMethod.GET).hasAuthority("ROLE_USER")
+ .requestMatchers(HttpMethod.POST).hasAuthority("ROLE_ADMIN")
+ .anyRequest().authenticated())
+ .httpBasic(Customizer.withDefaults());
+
+ return http.build();
+ }
+
+ @Bean
+ public PasswordEncoder passwordEncoder() {
+ return new BCryptPasswordEncoder();
+ }
+}
diff --git a/module13/src/main/java/ru/edu/module13/controller/UsersRestController.java b/module13/src/main/java/ru/edu/module13/controller/UsersRestController.java
new file mode 100644
index 00000000..11ed15ca
--- /dev/null
+++ b/module13/src/main/java/ru/edu/module13/controller/UsersRestController.java
@@ -0,0 +1,49 @@
+package ru.edu.module13.controller;
+
+import org.springframework.web.bind.annotation.*;
+import ru.edu.module13.entity.MyUser;
+import ru.edu.module13.repository.MyUserRepository;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@RestController
+@RequestMapping("/users")
+public class UsersRestController {
+ private MyUserRepository myUserRepository;
+ public UsersRestController(MyUserRepository myUserRepository) {
+ this.myUserRepository = myUserRepository;
+ }
+
+ @GetMapping
+ public List getUsers() {
+ return myUserRepository.findAll();
+ }
+ @PostMapping
+ public MyUser createUser(@RequestBody MyUser user) {
+ return myUserRepository.save(user);
+ }
+ @PutMapping("/{id}")
+ public MyUser updateUser(@PathVariable Long id, @RequestBody MyUser myUserDetails) {
+ MyUser myUser = myUserRepository.findById(id).orElseThrow(() -> new RuntimeException("User not found with id " + id));
+
+ myUser.setName(myUserDetails.getName());
+ myUser.setAge(myUserDetails.getAge());
+ return myUserRepository.save(myUser);
+ }
+ @DeleteMapping("/{id}")
+ public Map deleteUser(@PathVariable Long id) {
+ MyUser myUser = myUserRepository.findById(id).orElseThrow(() -> new RuntimeException("User not found with id " + id));
+
+ myUserRepository.delete(myUser);
+ Map response = new HashMap<>();
+ response.put("deleted", Boolean.TRUE);
+ return response;
+ }
+ @GetMapping("/{id}")
+ public MyUser getUserById(@PathVariable Long id) {
+ return myUserRepository.findById(id).orElseThrow(() -> new RuntimeException("User not found with id " + id));
+ }
+
+}
diff --git a/module13/src/main/java/ru/edu/module13/entity/Auth.java b/module13/src/main/java/ru/edu/module13/entity/Auth.java
new file mode 100644
index 00000000..4496f45c
--- /dev/null
+++ b/module13/src/main/java/ru/edu/module13/entity/Auth.java
@@ -0,0 +1,36 @@
+package ru.edu.module13.entity;
+
+import jakarta.persistence.*;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+import java.util.HashSet;
+import java.util.Set;
+
+@Entity
+@Table(name = "auth")
+@Getter
+@Setter
+@NoArgsConstructor
+@AllArgsConstructor
+public class Auth {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private Long id;
+
+ private String username;
+ private String password;
+
+ @ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
+ @JoinTable(
+ name = "auth_roles",
+ joinColumns = @JoinColumn(name = "auth_id"),
+ inverseJoinColumns = @JoinColumn(name = "role_id")
+ )
+ private Set roles = new HashSet<>();
+
+
+}
diff --git a/module13/src/main/java/ru/edu/module13/entity/MyUser.java b/module13/src/main/java/ru/edu/module13/entity/MyUser.java
new file mode 100644
index 00000000..c9ab9022
--- /dev/null
+++ b/module13/src/main/java/ru/edu/module13/entity/MyUser.java
@@ -0,0 +1,21 @@
+package ru.edu.module13.entity;
+import jakarta.persistence.*;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+@Entity
+@Getter
+@Setter
+@NoArgsConstructor
+@AllArgsConstructor
+public class MyUser {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private Long id;
+
+ private String name;
+ private Integer age;
+}
\ No newline at end of file
diff --git a/module13/src/main/java/ru/edu/module13/entity/Role.java b/module13/src/main/java/ru/edu/module13/entity/Role.java
new file mode 100644
index 00000000..b33402b8
--- /dev/null
+++ b/module13/src/main/java/ru/edu/module13/entity/Role.java
@@ -0,0 +1,23 @@
+package ru.edu.module13.entity;
+import jakarta.persistence.*;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+@Entity
+@Table(name = "roles")
+@Getter
+@Setter
+@NoArgsConstructor
+@AllArgsConstructor
+public class Role {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private Long id;
+
+ private String name;
+
+
+}
diff --git a/module13/src/main/java/ru/edu/module13/repository/AuthRepository.java b/module13/src/main/java/ru/edu/module13/repository/AuthRepository.java
new file mode 100644
index 00000000..80cd756a
--- /dev/null
+++ b/module13/src/main/java/ru/edu/module13/repository/AuthRepository.java
@@ -0,0 +1,10 @@
+package ru.edu.module13.repository;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+import ru.edu.module13.entity.Auth;
+
+@Repository
+public interface AuthRepository extends JpaRepository {
+ Auth findByUsername(String username);
+}
\ No newline at end of file
diff --git a/module13/src/main/java/ru/edu/module13/repository/MyUserRepository.java b/module13/src/main/java/ru/edu/module13/repository/MyUserRepository.java
new file mode 100644
index 00000000..4cd17489
--- /dev/null
+++ b/module13/src/main/java/ru/edu/module13/repository/MyUserRepository.java
@@ -0,0 +1,10 @@
+package ru.edu.module13.repository;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+import ru.edu.module13.entity.MyUser;
+
+@Repository
+public interface MyUserRepository extends JpaRepository {
+
+}
diff --git a/module13/src/main/java/ru/edu/module13/repository/RoleRepository.java b/module13/src/main/java/ru/edu/module13/repository/RoleRepository.java
new file mode 100644
index 00000000..6346bd00
--- /dev/null
+++ b/module13/src/main/java/ru/edu/module13/repository/RoleRepository.java
@@ -0,0 +1,10 @@
+package ru.edu.module13.repository;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+import ru.edu.module13.entity.Role;
+
+@Repository
+public interface RoleRepository extends JpaRepository {
+ Role findByName(String name);
+}
diff --git a/module13/src/main/resources/application.yaml b/module13/src/main/resources/application.yaml
new file mode 100644
index 00000000..eea6b4e6
--- /dev/null
+++ b/module13/src/main/resources/application.yaml
@@ -0,0 +1,25 @@
+logging:
+ level:
+ root: WARN
+
+server:
+ port: 8080
+ address: 0.0.0.0
+
+spring:
+ datasource:
+ url: jdbc:postgresql://localhost:5432/postgres
+ driverClassName: org.postgresql.Driver
+ username: postgres
+ password: mypassword
+ jpa:
+ defer-datasource-initialization: true
+ hibernate:
+ ddl-auto: create-drop
+ properties:
+ hibernate:
+ show_sql: true
+ format_sql: true
+ sql:
+ init:
+ mode: always
diff --git a/module13/src/main/resources/data.sql b/module13/src/main/resources/data.sql
new file mode 100644
index 00000000..ccab0b85
--- /dev/null
+++ b/module13/src/main/resources/data.sql
@@ -0,0 +1,6 @@
+INSERT INTO roles (name) VALUES ('ROLE_ADMIN');
+INSERT INTO roles (name) VALUES ('ROLE_USER');
+INSERT INTO auth (username, password) VALUES ('admin', '$2a$10$rnxHUAo/gTfmUm2Rmf7lfeyIwMKcVOiU9cdnGWIrFDXivSGOsCvde');
+INSERT INTO auth_roles (auth_id, role_id) SELECT (SELECT id FROM auth WHERE username = 'admin'), (SELECT id FROM roles WHERE name = 'ROLE_ADMIN');
+INSERT INTO auth (username, password) VALUES ('user', '$2a$10$rnxHUAo/gTfmUm2Rmf7lfeyIwMKcVOiU9cdnGWIrFDXivSGOsCvde');
+INSERT INTO auth_roles (auth_id, role_id) SELECT (SELECT id FROM auth WHERE username = 'user'), (SELECT id FROM roles WHERE name = 'ROLE_USER');
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 0b768ddf..da2e5414 100644
--- a/pom.xml
+++ b/pom.xml
@@ -16,7 +16,9 @@
module08
module09
module10
+ module11
module12
+ module13
pom