diff --git a/README.md b/README.md index 0c57e64..3b03632 100644 --- a/README.md +++ b/README.md @@ -1,96 +1,2 @@ -# НТО 2025. II отборочный этап. Командные задания — Backend Решение -## 📖 Предыстория - -В компании S есть возможность бронирования мест в пространствах, предназначенных под общее использование (open-space). На данный момент для бронирования места используются различные способы бронирования, разработанные в каждом офисе индивидуально. -Администрации компании S требуется мобильное приложение, как для рядовых сотрудников, так и для администрации с возможностью просмотра забронированных мест. - -## 📑 Технологический стек - -- Java 17 -- Spring Boot -- H2 -- Liquibase - - -## 🛠️ Техническое задание - -Требуется разработать серверное приложение на Java с использованием Spring Boot, которое работает на основе протокола HTTP и взаимодействует с клиентами благодаря RESTful API. - -Для хранения данных о сотрудниках и их посещениях должна использоваться реляционная база данных (H2). Схема БД должна создаваться liquibase-скриптами. ID-поля всех сущностей, сохраняемых в базе, должны выдаваться на уровне БД. Стратегия генерации ID - автоинкремент (1, 2, 3, 4…) - -Сотрудникам не нужно регистрироваться, все данные в базе должны быть предзаполнены liquibase-скриптами при запуске серверного приложения. Данные для предзаполнения таблиц представлены ниже. - -Картинки для аватаров пользователей не должны храниться в БД. Должны быть сохранены лишь URL-адреса на ресурсы, откуда в последующем мобильное приложение загрузит соответствующее изображение. - -Сервер разрабатывается на основе предоставляемой заготовки проекта. Версии зависимостей и сами зависимости изменяться не должны. - - -## 📂 Правила работы с проектом-заготовкой - -В предоставленном проекте необходимо изучить, но никак не модифицировать, не перемещать и не удалять следующие файлы: -- `pom.xml` -- `application.yml` -- все файлы из `db.changelog` - -Кроме описанных выше файлов, в проекте уже созданы основные классы-сущности и добавлены пустые классы всех слоев. В этих классах необходимо будет написать программный код и добавить аннотации для реализации описанного задания. Наименования классов и прочий код уже написанный в предоставляемом проекте **изменять/удалять не нужно, необходимо их доработать**. Добавлять свои дополнительные классы в проект можно. - -Создание таблиц в БД и предзаполнение их требуемыми данными уже реализовано в заготовке при помощи liquibase. В одной из сущностей добавлены аннотации для реализации связи “один ко многим”, обратите внимание, что в проекте потребуется еще связь данного типа. - - -## 🌐 Где необходимо разместить сервер - -Серверное приложение должно быть разработано и протестировано локально (**не требуется** размещать сервер удаленно и осуществлять его функционирование 24/7). - - -## 📋 Технические требования к серверу и его ответам клиенту - -Для конфигурирования Вашего сервера (его хоста/IP адреса) используйте константы из файла `Constants.kt`. - -| **Тип запроса** | **Путь** | **Описание** | **Параметры/Тело** | **Ответы** | -|-----------------|-----------------------|---------------------------|--------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| **GET** | `api//auth` | Проверка авторизации | `` - код для входа | `400` - что-то пошло не так
`401` - кода не существует
`200` - данный код существует - можно пользоваться приложением | -| **GET** | `api//info` | Получение информации о пользователе | `` - код для входа | `400` - что-то пошло не так
`401` - кода не существует
`200` - ОК
{
"name":"Иванов Петр Федорович",
"photoUrl":"",
"booking":{
"2025-01-05": {"id":1,"place":"102"},
"2025-01-06": {"id":2,"place":"209.13"},
"2025-01-09": {"id":3,"place":"Зона 51. 50"}
}
}
| -| **GET** | `api//booking` | Получение доступных для бронирования мест | `` - код для входа | `400` - что-то пошло не так
`401` - кода не существует
`200` - ОК
{
"2025-01-05": [{"id": 1, "place": "102"},{"id": 2, "place": "209.13"}],
"2025-01-06": [{"id": 3, "place": "Зона 51. 50"}],
"2025-01-07": [{"id": 1, "place": "102"},{"id": 2, "place": "209.13"}],
"2025-01-08": [{"id": 2, "place": "209.13"}]
}
**Список дат ограничен текущим + 3 днями** (ответ от сервера содержит 4 дня со свободными местами для каждого) -| **POST** | `api//book` | Создание нового бронирования | `` - код для входа
Тело:
{
“date”: “2025-01-05”,
“placeId”: 1
}
|`400` - что-то пошло не так
`401` - кода не существует
`409` - уже забронировано
`201` - бронирование успешно создано - - -## 📊 Пример данных - -Таблица сотрудников: - -| **id** | **name** | **code** | **photo_url** | -|--------|-----------|---------------------------------|---------------------------------------------------------------------------------------------| -| 1 | Ivanov Ivan | 1111 | https://catalog-cdn.detmir.st/media/2fe02057f9915e72a378795d32c79ea9.jpeg | -| 2 | Petrov Petr | 2222 | https://catalog-cdn.detmir.st/media/2fe02057f9915e72a378795d32c79ea9.jpeg | -| 3 | Kozlov Oleg | 3333 | https://catalog-cdn.detmir.st/media/2fe02057f9915e72a378795d32c79ea9.jpeg | -| 4 | Smirnova Anna | 4444 | https://catalog-cdn.detmir.st/media/2fe02057f9915e72a378795d32c79ea9.jpeg | - - -Таблица мест для бронирования: - -| **id** | **place_name** | -|--------|-----------------| -| 1 | K-19 | -| 2 | M-16 | -| 3 | T-1 | - - -Таблица бронирований: - -| **id** | **date** | **place_id** | **employee_id** | -|--------|-----------|--------------|------------------| -| 1 | 2025-11-08 | 1 | 1 | -| 2 | 2025-11-10 | 2 | 2 | - - -# 📝 Решение - -Работу необходимо осуществлять в предоставленном проекте-заготовке (шаблоне). -Когда завершите разработку, создайте пулреквест и запустите workflow в учебной системе. - - -## ✅ Особенности оценивания - -При тестировании сервера на него поочередно отправляются команды, описанные в API и ожидаются определенные корректные ответы. -Сервер и приложение тестируются независимо. - +username: user +password: 123456789 \ No newline at end of file diff --git a/pom.xml b/pom.xml index 93eee07..2d5d992 100644 --- a/pom.xml +++ b/pom.xml @@ -56,6 +56,28 @@ springdoc-openapi-starter-webmvc-ui 2.8.8 + + org.springframework.boot + spring-boot-starter-security + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + org.projectlombok + lombok + + + + + + + + \ No newline at end of file diff --git a/src/main/java/com/example/nto/config/WebSecurityConfig.java b/src/main/java/com/example/nto/config/WebSecurityConfig.java new file mode 100644 index 0000000..ae47ed2 --- /dev/null +++ b/src/main/java/com/example/nto/config/WebSecurityConfig.java @@ -0,0 +1,40 @@ +package com.example.nto.config; + +import com.example.nto.filter.BaseAuthFilter; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +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.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.web.SecurityFilterChain; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; + +@Configuration +@EnableWebSecurity +public class WebSecurityConfig { + @Bean + public PasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } + + @Bean + public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { + return + http + .csrf(csrf -> csrf.disable()) + .authorizeHttpRequests((authorize) -> authorize + .requestMatchers("/h2-console").permitAll() + .requestMatchers("/register").permitAll() + .anyRequest().authenticated()). + addFilterBefore(new BaseAuthFilter(), UsernamePasswordAuthenticationFilter.class). + httpBasic(Customizer.withDefaults()) + .build(); + + + } + + + +} diff --git a/src/main/java/com/example/nto/controller/EmployeeController.java b/src/main/java/com/example/nto/controller/EmployeeController.java index 7f73702..ab9a7d5 100644 --- a/src/main/java/com/example/nto/controller/EmployeeController.java +++ b/src/main/java/com/example/nto/controller/EmployeeController.java @@ -1,12 +1,21 @@ package com.example.nto.controller; - import com.example.nto.controller.dto.EmployeeDto; +import com.example.nto.entity.Employee; import com.example.nto.service.EmployeeService; import lombok.RequiredArgsConstructor; +import org.apache.tomcat.util.net.openssl.ciphers.Authentication; import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.security.core.context.SecurityContext; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.web.server.authorization.AuthorizationContext; import org.springframework.web.bind.annotation.*; +import java.util.Map; + +import static com.example.nto.controller.dto.EmployeeDto.toDto; + @RestController @RequestMapping("api") @RequiredArgsConstructor @@ -14,16 +23,14 @@ public class EmployeeController { private final EmployeeService employeeService; - @GetMapping("/{code}/auth") - @ResponseStatus(code = HttpStatus.OK) - public void login(@PathVariable String code) { - employeeService.auth(code); + @GetMapping("/login") + public Employee login(Authentication auth) { + return employeeService.getByUsername((auth.getDeclaringClass()).getName()); } - @GetMapping("/{code}/info") - @ResponseStatus(code = HttpStatus.OK) - public EmployeeDto getByCode(@PathVariable String code) { - return employeeService.getByCode(code); + @PostMapping("/register") + public void register(@RequestBody Map body) { + employeeService.register(body.get("login"), body.get("password")); } } diff --git a/src/main/java/com/example/nto/controller/dto/EmployeeDto.java b/src/main/java/com/example/nto/controller/dto/EmployeeDto.java index 3c87566..b5a5c24 100644 --- a/src/main/java/com/example/nto/controller/dto/EmployeeDto.java +++ b/src/main/java/com/example/nto/controller/dto/EmployeeDto.java @@ -16,7 +16,7 @@ import java.util.TreeMap; @NoArgsConstructor @AllArgsConstructor public class EmployeeDto { - private String name; + private String username; private String photoUrl; private Map booking; @@ -26,6 +26,6 @@ public class EmployeeDto { dtoTreeMap.put(booking.getDate(), PlaceDto.toDto(booking.getPlace())); } - return new EmployeeDto(employee.getName(), employee.getPhotoUrl(), dtoTreeMap); + return new EmployeeDto(employee.getUsername(), employee.getPhotoUrl(), dtoTreeMap); } } diff --git a/src/main/java/com/example/nto/controller/dto/EmployeeRegisterDto.java b/src/main/java/com/example/nto/controller/dto/EmployeeRegisterDto.java new file mode 100644 index 0000000..44b461f --- /dev/null +++ b/src/main/java/com/example/nto/controller/dto/EmployeeRegisterDto.java @@ -0,0 +1,21 @@ +package com.example.nto.controller.dto; + +import com.example.nto.entity.Booking; +import com.example.nto.entity.Employee; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.time.LocalDate; +import java.util.Map; +import java.util.TreeMap; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class EmployeeRegisterDto { + private String username; + private String password; +} diff --git a/src/main/java/com/example/nto/entity/Employee.java b/src/main/java/com/example/nto/entity/Employee.java index e854a92..9465ad7 100644 --- a/src/main/java/com/example/nto/entity/Employee.java +++ b/src/main/java/com/example/nto/entity/Employee.java @@ -5,7 +5,10 @@ import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; +import java.util.Collection; import java.util.List; @Data @@ -14,21 +17,26 @@ import java.util.List; @NoArgsConstructor @AllArgsConstructor @Table(name = "employee") -public class Employee { +public class Employee implements UserDetails { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private long id; - @Column(name = "name") - private String name; + @Column(name = "username") + private String username; - @Column(name = "code") - private String code; + @Column(name = "password") + private String password; @Column(name = "photo_url") private String photoUrl; @OneToMany(mappedBy = "employee", cascade = CascadeType.ALL, fetch = FetchType.LAZY) private List bookingList; + + @Override + public Collection getAuthorities() { + return List.of(); + } } diff --git a/src/main/java/com/example/nto/exception/EmployeeAlreadyExistsException.java b/src/main/java/com/example/nto/exception/EmployeeAlreadyExistsException.java new file mode 100644 index 0000000..2c8c98f --- /dev/null +++ b/src/main/java/com/example/nto/exception/EmployeeAlreadyExistsException.java @@ -0,0 +1,7 @@ +package com.example.nto.exception; + +public class EmployeeAlreadyExistsException extends RuntimeException { + public EmployeeAlreadyExistsException(String message) { + super(message); + } +} diff --git a/src/main/java/com/example/nto/exception/NoSuchUsernameException.java b/src/main/java/com/example/nto/exception/NoSuchUsernameException.java new file mode 100644 index 0000000..c6ca91f --- /dev/null +++ b/src/main/java/com/example/nto/exception/NoSuchUsernameException.java @@ -0,0 +1,7 @@ +package com.example.nto.exception; + +public class NoSuchUsernameException extends RuntimeException { + public NoSuchUsernameException(String message) { + super(message); + } +} diff --git a/src/main/java/com/example/nto/exception/handler/GlobalExceptionHandler.java b/src/main/java/com/example/nto/exception/handler/GlobalExceptionHandler.java index 234a158..c0ef676 100644 --- a/src/main/java/com/example/nto/exception/handler/GlobalExceptionHandler.java +++ b/src/main/java/com/example/nto/exception/handler/GlobalExceptionHandler.java @@ -1,8 +1,6 @@ package com.example.nto.exception.handler; -import com.example.nto.exception.BookingAlreadyExistsException; -import com.example.nto.exception.EmployeeNotFoundException; -import com.example.nto.exception.PlaceNotFoundException; +import com.example.nto.exception.*; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ControllerAdvice; @@ -25,8 +23,19 @@ public class GlobalExceptionHandler { return new ResponseEntity<>(e.getMessage(), HttpStatus.BAD_REQUEST); } + @ExceptionHandler(EmployeeAlreadyExistsException.class) + public ResponseEntity handleEmployeeAlreadyExistsException(EmployeeAlreadyExistsException e) { + return new ResponseEntity<>(e.getMessage(), HttpStatus.CONFLICT); + } + + @ExceptionHandler(NoSuchUsernameException.class) + public ResponseEntity handleNoSuchUsernameException(NoSuchUsernameException e) { + return new ResponseEntity<>(e.getMessage(), HttpStatus.CONFLICT); + } + @ExceptionHandler(Exception.class) public ResponseEntity handleGenericException(Exception e) { return new ResponseEntity<>(e.getMessage(), HttpStatus.BAD_REQUEST); } + } diff --git a/src/main/java/com/example/nto/filter/BaseAuthFilter.java b/src/main/java/com/example/nto/filter/BaseAuthFilter.java new file mode 100644 index 0000000..02d0166 --- /dev/null +++ b/src/main/java/com/example/nto/filter/BaseAuthFilter.java @@ -0,0 +1,36 @@ +package com.example.nto.filter; + +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.web.filter.OncePerRequestFilter; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Base64; + +public class BaseAuthFilter extends OncePerRequestFilter { + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { + String header = request.getHeader("Authorisation"); + if (header != null && header.startsWith("Base")) { + try { + String base64Token = header.substring(5); + byte[] decoded = Base64.getDecoder().decode(base64Token); + String credentials = new String(decoded, StandardCharsets.UTF_8); + String[] values = credentials.split(" ", 2); + String username = values[0]; + String password = values[1]; + + UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(username, password, new ArrayList<>()); + SecurityContextHolder.getContext().setAuthentication(auth); + } catch (Exception e) { + filterChain.doFilter(request, response); + } + } + } +} diff --git a/src/main/java/com/example/nto/repository/EmployeeRepository.java b/src/main/java/com/example/nto/repository/EmployeeRepository.java index d845a04..0378807 100644 --- a/src/main/java/com/example/nto/repository/EmployeeRepository.java +++ b/src/main/java/com/example/nto/repository/EmployeeRepository.java @@ -8,5 +8,5 @@ import java.util.Optional; public interface EmployeeRepository extends JpaRepository { @EntityGraph(attributePaths = {"bookingList", "bookingList.place"}) - Optional findByCode(String code); + Optional findByUsername(String username); } diff --git a/src/main/java/com/example/nto/service/EmployeeService.java b/src/main/java/com/example/nto/service/EmployeeService.java index 83144af..6367440 100644 --- a/src/main/java/com/example/nto/service/EmployeeService.java +++ b/src/main/java/com/example/nto/service/EmployeeService.java @@ -1,9 +1,9 @@ package com.example.nto.service; -import com.example.nto.controller.dto.EmployeeDto; +import com.example.nto.entity.Employee; public interface EmployeeService { - EmployeeDto getByCode(String code); + Employee getByUsername(String username); - void auth(String code); + void register(String login, String password); } diff --git a/src/main/java/com/example/nto/service/impl/BookingServiceImpl.java b/src/main/java/com/example/nto/service/impl/BookingServiceImpl.java index ffc4f86..dea29f5 100644 --- a/src/main/java/com/example/nto/service/impl/BookingServiceImpl.java +++ b/src/main/java/com/example/nto/service/impl/BookingServiceImpl.java @@ -30,7 +30,6 @@ public class BookingServiceImpl implements BookingService { private final BookingRepository bookingRepository; private final EmployeeRepository employeeRepository; private final PlaceRepository placeRepository; - private final EmployeeService employeeService; @Value("${booking.days-ahead}") private int daysAhead; @@ -38,7 +37,6 @@ public class BookingServiceImpl implements BookingService { @Override @Transactional(readOnly = true) public Map> getFreePlace(String code) { - employeeService.auth(code); List allPlaces = placeRepository.findAll(); @@ -72,15 +70,15 @@ public class BookingServiceImpl implements BookingService { @Override @Transactional - public Booking create(String code, BookingCreateDto bookingCreateDto) { + public Booking create(String username, BookingCreateDto bookingCreateDto) { LocalDate date = bookingCreateDto.getDate(); LocalDate today = LocalDate.now(ZoneId.systemDefault()); if (date.isBefore(today) || date.isAfter(today.plusDays(daysAhead))) { throw new IllegalArgumentException("Date is out of booking window"); } - Employee employee = employeeRepository.findByCode(code) - .orElseThrow(() -> new EmployeeNotFoundException("Employee with " + code + " code not found!")); + Employee employee = employeeRepository.findByUsername(username) + .orElseThrow(() -> new EmployeeNotFoundException("Employee with " + username + " code not found!")); long placeId = bookingCreateDto.getPlaceId(); Place place = placeRepository.findById(placeId) diff --git a/src/main/java/com/example/nto/service/impl/CustomUserDetailsServiceImpl.java b/src/main/java/com/example/nto/service/impl/CustomUserDetailsServiceImpl.java new file mode 100644 index 0000000..b577749 --- /dev/null +++ b/src/main/java/com/example/nto/service/impl/CustomUserDetailsServiceImpl.java @@ -0,0 +1,23 @@ +package com.example.nto.service.impl; + +import com.example.nto.entity.Employee; +import com.example.nto.exception.NoSuchUsernameException; +import com.example.nto.repository.EmployeeRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; + +import java.util.ArrayList; + +public class CustomUserDetailsServiceImpl implements UserDetailsService { + @Autowired private EmployeeRepository employeeRepository; + @Override + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { + Employee employee = employeeRepository.findByUsername(username).orElseThrow(() -> new NoSuchUsernameException("No employee with " + username + " username!!!")); + + return new org.springframework.security.core.userdetails.User(employee.getUsername(), + employee.getPassword(), + new ArrayList<>()); + } +} diff --git a/src/main/java/com/example/nto/service/impl/EmployeeServiceImpl.java b/src/main/java/com/example/nto/service/impl/EmployeeServiceImpl.java index 3085dc2..aec9e6e 100644 --- a/src/main/java/com/example/nto/service/impl/EmployeeServiceImpl.java +++ b/src/main/java/com/example/nto/service/impl/EmployeeServiceImpl.java @@ -1,31 +1,37 @@ package com.example.nto.service.impl; -import com.example.nto.controller.dto.EmployeeDto; -import com.example.nto.exception.EmployeeNotFoundException; +import com.example.nto.entity.Employee; +import com.example.nto.exception.EmployeeAlreadyExistsException; +import com.example.nto.exception.NoSuchUsernameException; import com.example.nto.repository.EmployeeRepository; import com.example.nto.service.EmployeeService; import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; @Service @RequiredArgsConstructor public class EmployeeServiceImpl implements EmployeeService { + @Autowired private final EmployeeRepository employeeRepository; + private final PasswordEncoder passwordEncoder; + @Override - @Transactional(readOnly = true) - public EmployeeDto getByCode(String code) { - return employeeRepository.findByCode(code).map(EmployeeDto::toDto) - .orElseThrow(() -> new EmployeeNotFoundException("Employee with " + code + " code not found!")); + public Employee getByUsername(String username) { + return employeeRepository.findByUsername(username).orElseThrow(() -> new NoSuchUsernameException("No employee with " + username + " username!!!")); } @Override - @Transactional(readOnly = true) - public void auth(String code) { - if (employeeRepository.findByCode(code).isEmpty()) { - throw new EmployeeNotFoundException("Employee with " + code + " code not found!"); + public void register(String login, String password) { + if (employeeRepository.findByUsername(login).isPresent()){ + throw new EmployeeAlreadyExistsException("Username is already exists"); } + + Employee employee = new Employee(); + employee.setUsername(login); + employee.setPassword(passwordEncoder.encode(password)); } } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties new file mode 100644 index 0000000..3680552 --- /dev/null +++ b/src/main/resources/application.properties @@ -0,0 +1 @@ +server.port=49155 \ No newline at end of file diff --git a/src/main/resources/db.changelog/1/0/2025-11-05--0001-employee.xml b/src/main/resources/db.changelog/1/0/2025-11-05--0001-employee.xml index d1f92f8..bc84754 100644 --- a/src/main/resources/db.changelog/1/0/2025-11-05--0001-employee.xml +++ b/src/main/resources/db.changelog/1/0/2025-11-05--0001-employee.xml @@ -21,10 +21,14 @@ - + + + + + diff --git a/src/main/resources/db.changelog/1/0/2026-25-02--0004-authority.xml b/src/main/resources/db.changelog/1/0/2026-25-02--0004-authority.xml new file mode 100644 index 0000000..fed641a --- /dev/null +++ b/src/main/resources/db.changelog/1/0/2026-25-02--0004-authority.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/db.changelog/data/2026-25-02--0004-authority-data.xml b/src/main/resources/db.changelog/data/2026-25-02--0004-authority-data.xml new file mode 100644 index 0000000..4d64e90 --- /dev/null +++ b/src/main/resources/db.changelog/data/2026-25-02--0004-authority-data.xml @@ -0,0 +1,14 @@ + + + + + + + \ No newline at end of file diff --git a/src/main/resources/db.changelog/data/csv/2025-11-05--0001-employee-data.csv b/src/main/resources/db.changelog/data/csv/2025-11-05--0001-employee-data.csv index 87ddc6b..e3b3fe8 100644 --- a/src/main/resources/db.changelog/data/csv/2025-11-05--0001-employee-data.csv +++ b/src/main/resources/db.changelog/data/csv/2025-11-05--0001-employee-data.csv @@ -1,5 +1,5 @@ -name;code;photo_url -Ivanov Ivan;1111;https://catalog-cdn.detmir.st/media/2fe02057f9915e72a378795d32c79ea9.jpeg -Petrov Petr;2222;https://catalog-cdn.detmir.st/media/2fe02057f9915e72a378795d32c79ea9.jpeg -Kozlov Oleg;3333;https://catalog-cdn.detmir.st/media/2fe02057f9915e72a378795d32c79ea9.jpeg -Smirnova Anna;4444;https://catalog-cdn.detmir.st/media/2fe02057f9915e72a378795d32c79ea9.jpeg \ No newline at end of file +name;username;password;photo_url +Ivanov Ivan;iivanov;YWRtaW4=;https://catalog-cdn.detmir.st/media/2fe02057f9915e72a378795d32c79ea9.jpeg +Petrov Petr;ppetrov;YWRtaW4=;https://catalog-cdn.detmir.st/media/2fe02057f9915e72a378795d32c79ea9.jpeg +Kozlov Oleg;okozlov;YWRtaW4=;https://catalog-cdn.detmir.st/media/2fe02057f9915e72a378795d32c79ea9.jpeg +Smirnova Anna;asmirnova;YWRtaW4=;https://catalog-cdn.detmir.st/media/2fe02057f9915e72a378795d32c79ea9.jpeg \ No newline at end of file diff --git a/src/main/resources/db.changelog/data/csv/2026-25-02--0004-authority-data.csv b/src/main/resources/db.changelog/data/csv/2026-25-02--0004-authority-data.csv new file mode 100644 index 0000000..6005ef8 --- /dev/null +++ b/src/main/resources/db.changelog/data/csv/2026-25-02--0004-authority-data.csv @@ -0,0 +1,3 @@ +authority +ROLE_USER +ROLE_ROOM \ No newline at end of file