create jar file #2

Open
student-g-gaydaenko wants to merge 5 commits from Kristall-org/NTO-2026-Backend-TeamTask-Template:main into main
14 changed files with 152 additions and 31 deletions
Showing only changes of commit 712dad45f7 - Show all commits

View File

@ -56,6 +56,10 @@
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.8.8</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
</dependencies>
<build>

View File

@ -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();
}
}

View File

@ -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);}
}

View File

@ -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;
}

View File

@ -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<Booking> bookingList;
}

View File

@ -0,0 +1,7 @@
package com.example.nto.exception;
public class EmployeeAlreadyExistsException extends RuntimeException {
public EmployeeAlreadyExistsException(String message) {
super(message);
}
}

View File

@ -0,0 +1,7 @@
package com.example.nto.exception;
public class PasswordNotCorrectException extends RuntimeException {
public PasswordNotCorrectException(String message) {
super(message);
}
}

View File

@ -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<String> handleEmployeeAlreadyExistsException(EmployeeAlreadyExistsException e) {
return new ResponseEntity<>(e.getMessage(), HttpStatus.CONFLICT);
}
@ExceptionHandler(PasswordNotCorrectException.class)
public ResponseEntity<String> handlePasswordNotCorrectException(PasswordNotCorrectException e) {
return new ResponseEntity<>(e.getMessage(), HttpStatus.CONFLICT);
}
@ExceptionHandler(Exception.class)
public ResponseEntity<String> handleGenericException(Exception e) {
return new ResponseEntity<>(e.getMessage(), HttpStatus.BAD_REQUEST);
}
}

View File

@ -8,5 +8,5 @@ import java.util.Optional;
public interface EmployeeRepository extends JpaRepository<Employee, Long> {
@EntityGraph(attributePaths = {"bookingList", "bookingList.place"})
Optional<Employee> findByCode(String code);
Optional<Employee> findByUsername(String username);
}

View File

@ -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);
}

View File

@ -37,8 +37,8 @@ public class BookingServiceImpl implements BookingService {
@Override
@Transactional(readOnly = true)
public Map<LocalDate, List<PlaceDto>> getFreePlace(String code) {
employeeService.auth(code);
public Map<LocalDate, List<PlaceDto>> getFreePlace(String username) {
employeeService.auth(username);
List<Place> 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)

View File

@ -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);
}
}

View File

@ -21,10 +21,14 @@
<constraints nullable="false"/>
</column>
<column name="code" type="VARCHAR(100)">
<column name="username" type="VARCHAR(100)">
<constraints nullable="false" unique="true"/>
</column>
<column name="password" type="VARCHAR(50)">
<constraints nullable="false"/>
</column>
<column name="photo_url" type="VARCHAR(100)"/>
</createTable>
</changeSet>

View File

@ -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
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
1 name code username password photo_url
2 Ivanov Ivan 1111 iivanov YWRtaW4= https://catalog-cdn.detmir.st/media/2fe02057f9915e72a378795d32c79ea9.jpeg
3 Petrov Petr 2222 ppetrov YWRtaW4= https://catalog-cdn.detmir.st/media/2fe02057f9915e72a378795d32c79ea9.jpeg
4 Kozlov Oleg 3333 okozlov YWRtaW4= https://catalog-cdn.detmir.st/media/2fe02057f9915e72a378795d32c79ea9.jpeg
5 Smirnova Anna 4444 asmirnova YWRtaW4= https://catalog-cdn.detmir.st/media/2fe02057f9915e72a378795d32c79ea9.jpeg