From 29c44d684f7a74c26df2e975cc82f58e62343706 Mon Sep 17 00:00:00 2001 From: Samsung Date: Tue, 24 Feb 2026 20:22:31 +0300 Subject: [PATCH 1/5] create jar file --- pom.xml | 18 ++++++++++++++++++ src/main/resources/application.properties | 1 + 2 files changed, 19 insertions(+) create mode 100644 src/main/resources/application.properties diff --git a/pom.xml b/pom.xml index 93eee07..e965168 100644 --- a/pom.xml +++ b/pom.xml @@ -58,4 +58,22 @@ + + + + org.springframework.boot + spring-boot-maven-plugin + + + + org.projectlombok + lombok + + + + + + + + \ No newline at end of file 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 -- 2.47.1 From 712dad45f7bc7e5b3bdecc4f5ec065167917e1aa Mon Sep 17 00:00:00 2001 From: Samsung Date: Wed, 25 Feb 2026 14:29:55 +0300 Subject: [PATCH 2/5] checkpoint1 --- pom.xml | 4 ++ .../example/nto/config/WebSecurityConfig.java | 33 ++++++++++++++++ .../nto/controller/EmployeeController.java | 17 ++++++--- .../controller/dto/EmployeeRegisterDto.java | 16 ++++++++ .../java/com/example/nto/entity/Employee.java | 11 +++++- .../EmployeeAlreadyExistsException.java | 7 ++++ .../PasswordNotCorrectException.java | 7 ++++ .../handler/GlobalExceptionHandler.java | 15 ++++++-- .../nto/repository/EmployeeRepository.java | 2 +- .../example/nto/service/EmployeeService.java | 7 +++- .../nto/service/impl/BookingServiceImpl.java | 10 ++--- .../nto/service/impl/EmployeeServiceImpl.java | 38 ++++++++++++++++--- .../1/0/2025-11-05--0001-employee.xml | 6 ++- .../csv/2025-11-05--0001-employee-data.csv | 10 ++--- 14 files changed, 152 insertions(+), 31 deletions(-) create mode 100644 src/main/java/com/example/nto/config/WebSecurityConfig.java create mode 100644 src/main/java/com/example/nto/controller/dto/EmployeeRegisterDto.java create mode 100644 src/main/java/com/example/nto/exception/EmployeeAlreadyExistsException.java create mode 100644 src/main/java/com/example/nto/exception/PasswordNotCorrectException.java diff --git a/pom.xml b/pom.xml index e965168..2d5d992 100644 --- a/pom.xml +++ b/pom.xml @@ -56,6 +56,10 @@ springdoc-openapi-starter-webmvc-ui 2.8.8 + + org.springframework.boot + spring-boot-starter-security + 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..508d772 --- /dev/null +++ b/src/main/java/com/example/nto/config/WebSecurityConfig.java @@ -0,0 +1,33 @@ +package com.example.nto.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.authentication.AuthenticationManager; +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; + +@Configuration +@EnableWebSecurity +public class WebSecurityConfig { + + @Bean + public PasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } + + + @Bean + public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { + http + .csrf(csrf -> csrf.disable()) + .authorizeHttpRequests((authorize) -> authorize + .requestMatchers("/h2-console").permitAll() + .requestMatchers("/register").permitAll() + .anyRequest().authenticated() + ); + return http.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..8f7d364 100644 --- a/src/main/java/com/example/nto/controller/EmployeeController.java +++ b/src/main/java/com/example/nto/controller/EmployeeController.java @@ -2,6 +2,7 @@ package com.example.nto.controller; import com.example.nto.controller.dto.EmployeeDto; +import com.example.nto.controller.dto.EmployeeRegisterDto; import com.example.nto.service.EmployeeService; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; @@ -14,16 +15,20 @@ public class EmployeeController { private final EmployeeService employeeService; - @GetMapping("/{code}/auth") + @GetMapping("/{username}/auth") @ResponseStatus(code = HttpStatus.OK) - public void login(@PathVariable String code) { - employeeService.auth(code); + public void login(@PathVariable String username) { + employeeService.auth(username); } - @GetMapping("/{code}/info") + @GetMapping("/{username}/info") @ResponseStatus(code = HttpStatus.OK) - public EmployeeDto getByCode(@PathVariable String code) { - return employeeService.getByCode(code); + public EmployeeDto getByCode(@PathVariable String username) { + return employeeService.getByUsername(username); } + @GetMapping("/register") + @ResponseStatus(code = HttpStatus.CREATED) + public void register(EmployeeRegisterDto employeeRegisterDto) {employeeService.register(employeeRegisterDto);} + } 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..9dbfbb4 --- /dev/null +++ b/src/main/java/com/example/nto/controller/dto/EmployeeRegisterDto.java @@ -0,0 +1,16 @@ +package com.example.nto.controller.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class EmployeeRegisterDto { + private String name; + 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..67be86c 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 @@ -23,12 +26,16 @@ public class Employee { @Column(name = "name") private String name; - @Column(name = "code") - private String code; + @Column(name = "username") + private String username; + + @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; + } 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/PasswordNotCorrectException.java b/src/main/java/com/example/nto/exception/PasswordNotCorrectException.java new file mode 100644 index 0000000..97b00d2 --- /dev/null +++ b/src/main/java/com/example/nto/exception/PasswordNotCorrectException.java @@ -0,0 +1,7 @@ +package com.example.nto.exception; + +public class PasswordNotCorrectException extends RuntimeException { + public PasswordNotCorrectException(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..f95660e 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(PasswordNotCorrectException.class) + public ResponseEntity handlePasswordNotCorrectException(PasswordNotCorrectException 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/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..5f221a7 100644 --- a/src/main/java/com/example/nto/service/EmployeeService.java +++ b/src/main/java/com/example/nto/service/EmployeeService.java @@ -1,9 +1,12 @@ package com.example.nto.service; import com.example.nto.controller.dto.EmployeeDto; +import com.example.nto.controller.dto.EmployeeRegisterDto; public interface EmployeeService { - EmployeeDto getByCode(String code); + EmployeeDto getByUsername(String username); - void auth(String code); + void auth(String username); + + void register(EmployeeRegisterDto employeeRegisterDto); } 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..7ad558d 100644 --- a/src/main/java/com/example/nto/service/impl/BookingServiceImpl.java +++ b/src/main/java/com/example/nto/service/impl/BookingServiceImpl.java @@ -37,8 +37,8 @@ public class BookingServiceImpl implements BookingService { @Override @Transactional(readOnly = true) - public Map> getFreePlace(String code) { - employeeService.auth(code); + public Map> getFreePlace(String username) { + employeeService.auth(username); List allPlaces = placeRepository.findAll(); @@ -72,15 +72,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/EmployeeServiceImpl.java b/src/main/java/com/example/nto/service/impl/EmployeeServiceImpl.java index 3085dc2..4e045ff 100644 --- a/src/main/java/com/example/nto/service/impl/EmployeeServiceImpl.java +++ b/src/main/java/com/example/nto/service/impl/EmployeeServiceImpl.java @@ -1,10 +1,15 @@ package com.example.nto.service.impl; import com.example.nto.controller.dto.EmployeeDto; +import com.example.nto.controller.dto.EmployeeRegisterDto; +import com.example.nto.entity.Employee; +import com.example.nto.exception.EmployeeAlreadyExistsException; import com.example.nto.exception.EmployeeNotFoundException; +import com.example.nto.exception.PasswordNotCorrectException; import com.example.nto.repository.EmployeeRepository; import com.example.nto.service.EmployeeService; import lombok.RequiredArgsConstructor; +import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -13,19 +18,40 @@ import org.springframework.transaction.annotation.Transactional; public class EmployeeServiceImpl implements EmployeeService { private final EmployeeRepository employeeRepository; + private 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 EmployeeDto getByUsername(String username) { + return employeeRepository.findByUsername(username).map(EmployeeDto::toDto) + .orElseThrow(() -> new EmployeeNotFoundException("Employee with " + username + " code not found!")); } @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 auth(String username) { + if (employeeRepository.findByUsername(username).isEmpty()) { + throw new EmployeeNotFoundException("Employee with " + username + " username not found!"); } } + + @Override + public void register(EmployeeRegisterDto employeeRegisterDto) { + if (employeeRepository.findByUsername(employeeRegisterDto.getUsername()).isPresent()){ + throw new EmployeeAlreadyExistsException("Employee with " + employeeRegisterDto.getUsername() + " username already exist"); + }; + + Employee employee = new Employee(); + + if (passwordEncoder.encode(employee.getPassword()).length() < 8) { + throw new PasswordNotCorrectException("The password is too short!!!"); + } + + employee.setName(employeeRegisterDto.getName()); + employee.setUsername(employeeRegisterDto.getUsername()); + employee.setPassword(passwordEncoder.encode(employeeRegisterDto.getPassword())); + + employeeRepository.save(employee); + } + } 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/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 -- 2.47.1 From f5f797a9cf1a753f3b89dbfbb917f6b96c025226 Mon Sep 17 00:00:00 2001 From: Samsung Date: Wed, 25 Feb 2026 19:02:30 +0300 Subject: [PATCH 3/5] checkpoint1 2.0 --- src/main/java/com/example/nto/App.java | 3 +- .../example/nto/config/WebSecurityConfig.java | 68 ++++++++++--------- .../nto/controller/EmployeeController.java | 16 ++--- .../nto/controller/dto/EmployeeDto.java | 4 +- .../controller/dto/EmployeeRegisterDto.java | 7 +- .../java/com/example/nto/entity/Employee.java | 9 +-- .../PasswordNotCorrectException.java | 7 -- .../handler/GlobalExceptionHandler.java | 5 -- .../example/nto/service/EmployeeService.java | 5 +- .../nto/service/impl/BookingServiceImpl.java | 4 +- .../nto/service/impl/EmployeeServiceImpl.java | 28 ++------ .../1/0/2026-25-02--0004-authority.xml | 26 +++++++ .../data/2026-25-02--0004-authority-data.xml | 14 ++++ .../csv/2026-25-02--0004-authority-data.csv | 3 + 14 files changed, 110 insertions(+), 89 deletions(-) delete mode 100644 src/main/java/com/example/nto/exception/PasswordNotCorrectException.java create mode 100644 src/main/resources/db.changelog/1/0/2026-25-02--0004-authority.xml create mode 100644 src/main/resources/db.changelog/data/2026-25-02--0004-authority-data.xml create mode 100644 src/main/resources/db.changelog/data/csv/2026-25-02--0004-authority-data.csv diff --git a/src/main/java/com/example/nto/App.java b/src/main/java/com/example/nto/App.java index d4add94..b22ec6c 100644 --- a/src/main/java/com/example/nto/App.java +++ b/src/main/java/com/example/nto/App.java @@ -2,8 +2,9 @@ package com.example.nto; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration; -@SpringBootApplication +@SpringBootApplication(exclude = { SecurityAutoConfiguration.class }) public class App { public static void main(String[] args) { SpringApplication.run(App.class, args); diff --git a/src/main/java/com/example/nto/config/WebSecurityConfig.java b/src/main/java/com/example/nto/config/WebSecurityConfig.java index 508d772..0bd9ecd 100644 --- a/src/main/java/com/example/nto/config/WebSecurityConfig.java +++ b/src/main/java/com/example/nto/config/WebSecurityConfig.java @@ -1,33 +1,35 @@ -package com.example.nto.config; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.security.authentication.AuthenticationManager; -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; - -@Configuration -@EnableWebSecurity -public class WebSecurityConfig { - - @Bean - public PasswordEncoder passwordEncoder() { - return new BCryptPasswordEncoder(); - } - - - @Bean - public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { - http - .csrf(csrf -> csrf.disable()) - .authorizeHttpRequests((authorize) -> authorize - .requestMatchers("/h2-console").permitAll() - .requestMatchers("/register").permitAll() - .anyRequest().authenticated() - ); - return http.build(); - } -} +//package com.example.nto.controller.config; +// +//import org.springframework.context.annotation.Bean; +//import org.springframework.context.annotation.Configuration; +//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; +// +//@Configuration +//@EnableWebSecurity +//public class WebSecurityConfig { +// @Bean +// public PasswordEncoder passwordEncoder() { +// return new BCryptPasswordEncoder(); +// } +// +// @Bean +// public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { +// http +// .csrf(csrf -> csrf.disable()) +// .authorizeHttpRequests((authorize) -> authorize +// .requestMatchers("/h2-console").permitAll() +// .requestMatchers("/index.html").permitAll() +// .requestMatchers("/register").permitAll() +// .anyRequest().authenticated() +// ); +// +// return http.build(); +// } +// +// +// +//} diff --git a/src/main/java/com/example/nto/controller/EmployeeController.java b/src/main/java/com/example/nto/controller/EmployeeController.java index 8f7d364..6d7d57c 100644 --- a/src/main/java/com/example/nto/controller/EmployeeController.java +++ b/src/main/java/com/example/nto/controller/EmployeeController.java @@ -3,6 +3,7 @@ package com.example.nto.controller; import com.example.nto.controller.dto.EmployeeDto; import com.example.nto.controller.dto.EmployeeRegisterDto; +import com.example.nto.entity.Employee; import com.example.nto.service.EmployeeService; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; @@ -15,20 +16,17 @@ public class EmployeeController { private final EmployeeService employeeService; - @GetMapping("/{username}/auth") - @ResponseStatus(code = HttpStatus.OK) - public void login(@PathVariable String username) { - employeeService.auth(username); - } - @GetMapping("/{username}/info") @ResponseStatus(code = HttpStatus.OK) - public EmployeeDto getByCode(@PathVariable String username) { + public EmployeeDto getByUsername(@PathVariable String username) { return employeeService.getByUsername(username); } - @GetMapping("/register") + @PostMapping("/register") @ResponseStatus(code = HttpStatus.CREATED) - public void register(EmployeeRegisterDto employeeRegisterDto) {employeeService.register(employeeRegisterDto);} + public Employee registerEmployee(EmployeeRegisterDto employeeRegisterDto) { + return employeeService.register(employeeRegisterDto); + } + } 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 index 9dbfbb4..44b461f 100644 --- a/src/main/java/com/example/nto/controller/dto/EmployeeRegisterDto.java +++ b/src/main/java/com/example/nto/controller/dto/EmployeeRegisterDto.java @@ -1,16 +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 name; 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 67be86c..4b27334 100644 --- a/src/main/java/com/example/nto/entity/Employee.java +++ b/src/main/java/com/example/nto/entity/Employee.java @@ -17,15 +17,12 @@ 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; @@ -38,4 +35,8 @@ public class Employee { @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/PasswordNotCorrectException.java b/src/main/java/com/example/nto/exception/PasswordNotCorrectException.java deleted file mode 100644 index 97b00d2..0000000 --- a/src/main/java/com/example/nto/exception/PasswordNotCorrectException.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.example.nto.exception; - -public class PasswordNotCorrectException extends RuntimeException { - public PasswordNotCorrectException(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 f95660e..89860b5 100644 --- a/src/main/java/com/example/nto/exception/handler/GlobalExceptionHandler.java +++ b/src/main/java/com/example/nto/exception/handler/GlobalExceptionHandler.java @@ -28,11 +28,6 @@ public class GlobalExceptionHandler { return new ResponseEntity<>(e.getMessage(), HttpStatus.CONFLICT); } - @ExceptionHandler(PasswordNotCorrectException.class) - public ResponseEntity handlePasswordNotCorrectException(PasswordNotCorrectException 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/service/EmployeeService.java b/src/main/java/com/example/nto/service/EmployeeService.java index 5f221a7..084cda2 100644 --- a/src/main/java/com/example/nto/service/EmployeeService.java +++ b/src/main/java/com/example/nto/service/EmployeeService.java @@ -2,11 +2,10 @@ package com.example.nto.service; import com.example.nto.controller.dto.EmployeeDto; import com.example.nto.controller.dto.EmployeeRegisterDto; +import com.example.nto.entity.Employee; public interface EmployeeService { EmployeeDto getByUsername(String username); - void auth(String username); - - void register(EmployeeRegisterDto employeeRegisterDto); + Employee register(EmployeeRegisterDto employeeRegisterDto); } 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 7ad558d..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,15 +30,13 @@ 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; @Override @Transactional(readOnly = true) - public Map> getFreePlace(String username) { - employeeService.auth(username); + public Map> getFreePlace(String code) { List allPlaces = placeRepository.findAll(); 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 4e045ff..e73ef9d 100644 --- a/src/main/java/com/example/nto/service/impl/EmployeeServiceImpl.java +++ b/src/main/java/com/example/nto/service/impl/EmployeeServiceImpl.java @@ -5,7 +5,6 @@ import com.example.nto.controller.dto.EmployeeRegisterDto; import com.example.nto.entity.Employee; import com.example.nto.exception.EmployeeAlreadyExistsException; import com.example.nto.exception.EmployeeNotFoundException; -import com.example.nto.exception.PasswordNotCorrectException; import com.example.nto.repository.EmployeeRepository; import com.example.nto.service.EmployeeService; import lombok.RequiredArgsConstructor; @@ -18,7 +17,7 @@ import org.springframework.transaction.annotation.Transactional; public class EmployeeServiceImpl implements EmployeeService { private final EmployeeRepository employeeRepository; - private PasswordEncoder passwordEncoder; + @Override @Transactional(readOnly = true) @@ -28,30 +27,17 @@ public class EmployeeServiceImpl implements EmployeeService { } @Override - @Transactional(readOnly = true) - public void auth(String username) { - if (employeeRepository.findByUsername(username).isEmpty()) { - throw new EmployeeNotFoundException("Employee with " + username + " username not found!"); + public Employee register(EmployeeRegisterDto employeeRegisterDto) { + if (employeeRepository.findByUsername(employeeRegisterDto.getUsername()).isPresent()) { + throw new EmployeeAlreadyExistsException("Employee with " + employeeRegisterDto.getUsername() + " username"); } - } - - @Override - public void register(EmployeeRegisterDto employeeRegisterDto) { - if (employeeRepository.findByUsername(employeeRegisterDto.getUsername()).isPresent()){ - throw new EmployeeAlreadyExistsException("Employee with " + employeeRegisterDto.getUsername() + " username already exist"); - }; Employee employee = new Employee(); - - if (passwordEncoder.encode(employee.getPassword()).length() < 8) { - throw new PasswordNotCorrectException("The password is too short!!!"); - } - - employee.setName(employeeRegisterDto.getName()); employee.setUsername(employeeRegisterDto.getUsername()); - employee.setPassword(passwordEncoder.encode(employeeRegisterDto.getPassword())); + employee.setPassword(employeeRegisterDto.getPassword()); - employeeRepository.save(employee); + return employeeRepository.save(employee); } + } 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/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 -- 2.47.1 From 3f7e768a5e518991b0bce663bbabaa9006712f94 Mon Sep 17 00:00:00 2001 From: Samsung Date: Thu, 26 Feb 2026 14:40:08 +0300 Subject: [PATCH 4/5] checkpoint3 --- src/main/java/com/example/nto/App.java | 3 +- .../example/nto/config/WebSecurityConfig.java | 75 ++++++++++--------- .../nto/controller/EmployeeController.java | 24 +++--- .../java/com/example/nto/entity/Employee.java | 2 +- .../exception/NoSuchUsernameException.java | 7 ++ .../handler/GlobalExceptionHandler.java | 5 ++ .../example/nto/filter/BaseAuthFilter.java | 36 +++++++++ .../example/nto/service/EmployeeService.java | 6 +- .../impl/CustomUserDetailsServiceImpl.java | 23 ++++++ .../nto/service/impl/EmployeeServiceImpl.java | 28 +++---- 10 files changed, 140 insertions(+), 69 deletions(-) create mode 100644 src/main/java/com/example/nto/exception/NoSuchUsernameException.java create mode 100644 src/main/java/com/example/nto/filter/BaseAuthFilter.java create mode 100644 src/main/java/com/example/nto/service/impl/CustomUserDetailsServiceImpl.java diff --git a/src/main/java/com/example/nto/App.java b/src/main/java/com/example/nto/App.java index b22ec6c..d4add94 100644 --- a/src/main/java/com/example/nto/App.java +++ b/src/main/java/com/example/nto/App.java @@ -2,9 +2,8 @@ package com.example.nto; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration; -@SpringBootApplication(exclude = { SecurityAutoConfiguration.class }) +@SpringBootApplication public class App { public static void main(String[] args) { SpringApplication.run(App.class, args); diff --git a/src/main/java/com/example/nto/config/WebSecurityConfig.java b/src/main/java/com/example/nto/config/WebSecurityConfig.java index 0bd9ecd..ae47ed2 100644 --- a/src/main/java/com/example/nto/config/WebSecurityConfig.java +++ b/src/main/java/com/example/nto/config/WebSecurityConfig.java @@ -1,35 +1,40 @@ -//package com.example.nto.controller.config; -// -//import org.springframework.context.annotation.Bean; -//import org.springframework.context.annotation.Configuration; -//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; -// -//@Configuration -//@EnableWebSecurity -//public class WebSecurityConfig { -// @Bean -// public PasswordEncoder passwordEncoder() { -// return new BCryptPasswordEncoder(); -// } -// -// @Bean -// public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { -// http -// .csrf(csrf -> csrf.disable()) -// .authorizeHttpRequests((authorize) -> authorize -// .requestMatchers("/h2-console").permitAll() -// .requestMatchers("/index.html").permitAll() -// .requestMatchers("/register").permitAll() -// .anyRequest().authenticated() -// ); -// -// return http.build(); -// } -// -// -// -//} +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 6d7d57c..ab9a7d5 100644 --- a/src/main/java/com/example/nto/controller/EmployeeController.java +++ b/src/main/java/com/example/nto/controller/EmployeeController.java @@ -1,14 +1,21 @@ package com.example.nto.controller; - import com.example.nto.controller.dto.EmployeeDto; -import com.example.nto.controller.dto.EmployeeRegisterDto; 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 @@ -16,17 +23,14 @@ public class EmployeeController { private final EmployeeService employeeService; - @GetMapping("/{username}/info") - @ResponseStatus(code = HttpStatus.OK) - public EmployeeDto getByUsername(@PathVariable String username) { - return employeeService.getByUsername(username); + @GetMapping("/login") + public Employee login(Authentication auth) { + return employeeService.getByUsername((auth.getDeclaringClass()).getName()); } @PostMapping("/register") - @ResponseStatus(code = HttpStatus.CREATED) - public Employee registerEmployee(EmployeeRegisterDto employeeRegisterDto) { - return employeeService.register(employeeRegisterDto); + public void register(@RequestBody Map body) { + employeeService.register(body.get("login"), body.get("password")); } - } diff --git a/src/main/java/com/example/nto/entity/Employee.java b/src/main/java/com/example/nto/entity/Employee.java index 4b27334..9465ad7 100644 --- a/src/main/java/com/example/nto/entity/Employee.java +++ b/src/main/java/com/example/nto/entity/Employee.java @@ -17,7 +17,7 @@ import java.util.List; @NoArgsConstructor @AllArgsConstructor @Table(name = "employee") -public class Employee implements UserDetails{ +public class Employee implements UserDetails { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) 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 89860b5..c0ef676 100644 --- a/src/main/java/com/example/nto/exception/handler/GlobalExceptionHandler.java +++ b/src/main/java/com/example/nto/exception/handler/GlobalExceptionHandler.java @@ -28,6 +28,11 @@ public class GlobalExceptionHandler { 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/service/EmployeeService.java b/src/main/java/com/example/nto/service/EmployeeService.java index 084cda2..6367440 100644 --- a/src/main/java/com/example/nto/service/EmployeeService.java +++ b/src/main/java/com/example/nto/service/EmployeeService.java @@ -1,11 +1,9 @@ package com.example.nto.service; -import com.example.nto.controller.dto.EmployeeDto; -import com.example.nto.controller.dto.EmployeeRegisterDto; import com.example.nto.entity.Employee; public interface EmployeeService { - EmployeeDto getByUsername(String username); + Employee getByUsername(String username); - Employee register(EmployeeRegisterDto employeeRegisterDto); + void register(String login, String password); } 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 e73ef9d..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,43 +1,37 @@ package com.example.nto.service.impl; -import com.example.nto.controller.dto.EmployeeDto; -import com.example.nto.controller.dto.EmployeeRegisterDto; import com.example.nto.entity.Employee; import com.example.nto.exception.EmployeeAlreadyExistsException; -import com.example.nto.exception.EmployeeNotFoundException; +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 getByUsername(String username) { - return employeeRepository.findByUsername(username).map(EmployeeDto::toDto) - .orElseThrow(() -> new EmployeeNotFoundException("Employee with " + username + " code not found!")); + public Employee getByUsername(String username) { + return employeeRepository.findByUsername(username).orElseThrow(() -> new NoSuchUsernameException("No employee with " + username + " username!!!")); } @Override - public Employee register(EmployeeRegisterDto employeeRegisterDto) { - if (employeeRepository.findByUsername(employeeRegisterDto.getUsername()).isPresent()) { - throw new EmployeeAlreadyExistsException("Employee with " + employeeRegisterDto.getUsername() + " username"); + 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(employeeRegisterDto.getUsername()); - employee.setPassword(employeeRegisterDto.getPassword()); - - return employeeRepository.save(employee); + employee.setUsername(login); + employee.setPassword(passwordEncoder.encode(password)); } - - } -- 2.47.1 From 37f65952cf953c5b3acb0e65dccb838cf76058ac Mon Sep 17 00:00:00 2001 From: student-g-gaydaenko Date: Thu, 26 Feb 2026 11:46:56 +0000 Subject: [PATCH 5/5] =?UTF-8?q?=D0=9E=D0=B1=D0=BD=D0=BE=D0=B2=D0=B8=D1=82?= =?UTF-8?q?=D1=8C=20README.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 98 ++----------------------------------------------------- 1 file changed, 2 insertions(+), 96 deletions(-) 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 -- 2.47.1