diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..981aeb8
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+/out
\ No newline at end of file
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..ab1f416
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,10 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Ignored default folder with query files
+/queries/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
+# Editor-based HTTP Client requests
+/httpRequests/
diff --git a/.idea/artifacts/NTO_2025_Backend_Team_Task_jar.xml b/.idea/artifacts/NTO_2025_Backend_Team_Task_jar.xml
new file mode 100644
index 0000000..fee9c5a
--- /dev/null
+++ b/.idea/artifacts/NTO_2025_Backend_Team_Task_jar.xml
@@ -0,0 +1,91 @@
+
+
+ $PROJECT_DIR$/out/artifacts/NTO_2025_Backend_Team_Task_jar
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
new file mode 100644
index 0000000..7c70b4f
--- /dev/null
+++ b/.idea/compiler.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/encodings.xml b/.idea/encodings.xml
new file mode 100644
index 0000000..63e9001
--- /dev/null
+++ b/.idea/encodings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml
new file mode 100644
index 0000000..712ab9d
--- /dev/null
+++ b/.idea/jarRepositories.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..9dc782b
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 93eee07..018a1b2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -58,4 +58,12 @@
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
\ No newline at end of file
diff --git a/src/main/java/com/example/nto/controller/BookingController.java b/src/main/java/com/example/nto/controller/BookingController.java
index a4ed8b1..1ce9439 100644
--- a/src/main/java/com/example/nto/controller/BookingController.java
+++ b/src/main/java/com/example/nto/controller/BookingController.java
@@ -20,16 +20,16 @@ public class BookingController {
private final BookingService bookingService;
- @GetMapping("/{code}/booking")
+ @GetMapping("/{code}/{password}/booking")
@ResponseStatus(code = HttpStatus.OK)
- public Map> getByDate(@PathVariable String code) {
- return bookingService.getFreePlace(code);
+ public Map> getByDate(@PathVariable String code, @PathVariable String password) {
+ return bookingService.getFreePlace(code, password);
}
- @PostMapping("/{code}/book")
+ @PostMapping("/{code}/{password}/book")
@ResponseStatus(code = HttpStatus.CREATED)
- public void create(@PathVariable String code, @RequestBody BookingCreateDto bookingCreateDto) {
- bookingService.create(code, bookingCreateDto);
+ public void create(@PathVariable String code, @RequestBody BookingCreateDto bookingCreateDto, @PathVariable String password) {
+ bookingService.create(code, password, bookingCreateDto);
}
}
diff --git a/src/main/java/com/example/nto/controller/EmployeeController.java b/src/main/java/com/example/nto/controller/EmployeeController.java
index 7f73702..e9e8f0e 100644
--- a/src/main/java/com/example/nto/controller/EmployeeController.java
+++ b/src/main/java/com/example/nto/controller/EmployeeController.java
@@ -14,16 +14,16 @@ public class EmployeeController {
private final EmployeeService employeeService;
- @GetMapping("/{code}/auth")
- @ResponseStatus(code = HttpStatus.OK)
- public void login(@PathVariable String code) {
- employeeService.auth(code);
- }
-
@GetMapping("/{code}/info")
@ResponseStatus(code = HttpStatus.OK)
- public EmployeeDto getByCode(@PathVariable String code) {
- return employeeService.getByCode(code);
+ public EmployeeDto getByCode(@PathVariable String login) {
+ return employeeService.getByCode(login);
+ }
+
+ @GetMapping("/login/{username}/{password}")
+ @ResponseStatus(code = HttpStatus.OK)
+ public EmployeeDto login(@PathVariable String username, @PathVariable String password){
+ return employeeService.auth(username, password);
}
}
diff --git a/src/main/java/com/example/nto/controller/dto/EmployeeCreateDto.java b/src/main/java/com/example/nto/controller/dto/EmployeeCreateDto.java
new file mode 100644
index 0000000..ec7a585
--- /dev/null
+++ b/src/main/java/com/example/nto/controller/dto/EmployeeCreateDto.java
@@ -0,0 +1,18 @@
+package com.example.nto.controller.dto;
+
+import jakarta.validation.constraints.NotNull;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class EmployeeCreateDto {
+ @NotNull
+ private String username;
+ @NotNull
+ private String 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..710da9f 100644
--- a/src/main/java/com/example/nto/controller/dto/EmployeeDto.java
+++ b/src/main/java/com/example/nto/controller/dto/EmployeeDto.java
@@ -9,6 +9,7 @@ import lombok.NoArgsConstructor;
import java.time.LocalDate;
import java.util.Map;
+import java.util.Optional;
import java.util.TreeMap;
@Data
@@ -28,4 +29,13 @@ public class EmployeeDto {
return new EmployeeDto(employee.getName(), employee.getPhotoUrl(), dtoTreeMap);
}
+
+ public static EmployeeDto toDtoOpt(Optional employee) {
+ Map dtoTreeMap = new TreeMap<>();
+ for (Booking booking : employee.get().getBookingList()) {
+ dtoTreeMap.put(booking.getDate(), PlaceDto.toDto(booking.getPlace()));
+ }
+
+ return new EmployeeDto(employee.get().getName(), employee.get().getPhotoUrl(), dtoTreeMap);
+ }
}
diff --git a/src/main/java/com/example/nto/entity/Employee.java b/src/main/java/com/example/nto/entity/Employee.java
index e854a92..26ebe38 100644
--- a/src/main/java/com/example/nto/entity/Employee.java
+++ b/src/main/java/com/example/nto/entity/Employee.java
@@ -6,7 +6,9 @@ import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
+import java.util.Collection;
import java.util.List;
+import java.util.Set;
@Data
@Entity
@@ -23,6 +25,12 @@ public class Employee {
@Column(name = "name")
private String name;
+ @Column(name = "username")
+ private String username;
+
+ @Column(name = "password")
+ private String password;
+
@Column(name = "code")
private String code;
@@ -31,4 +39,7 @@ public class Employee {
@OneToMany(mappedBy = "employee", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private List bookingList;
+
+ @ManyToMany
+ private Set roles;
}
diff --git a/src/main/java/com/example/nto/entity/Role.java b/src/main/java/com/example/nto/entity/Role.java
new file mode 100644
index 0000000..75fa41d
--- /dev/null
+++ b/src/main/java/com/example/nto/entity/Role.java
@@ -0,0 +1,21 @@
+package com.example.nto.entity;
+
+import jakarta.persistence.*;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Entity
+@NoArgsConstructor
+@AllArgsConstructor
+@Data
+public class Role {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private long id;
+
+ @Column(name = "role")
+ private String role;
+
+}
diff --git a/src/main/java/com/example/nto/exception/EmployeeAlreadyExists.java b/src/main/java/com/example/nto/exception/EmployeeAlreadyExists.java
new file mode 100644
index 0000000..7d64107
--- /dev/null
+++ b/src/main/java/com/example/nto/exception/EmployeeAlreadyExists.java
@@ -0,0 +1,7 @@
+package com.example.nto.exception;
+
+public class EmployeeAlreadyExists extends RuntimeException {
+ public EmployeeAlreadyExists(String message) {
+ super(message);
+ }
+}
diff --git a/src/main/java/com/example/nto/exception/InvalidPassword.java b/src/main/java/com/example/nto/exception/InvalidPassword.java
new file mode 100644
index 0000000..352a305
--- /dev/null
+++ b/src/main/java/com/example/nto/exception/InvalidPassword.java
@@ -0,0 +1,7 @@
+package com.example.nto.exception;
+
+public class InvalidPassword extends RuntimeException {
+ public InvalidPassword(String message) {
+ super(message);
+ }
+}
diff --git a/src/main/java/com/example/nto/exception/InvalidUsername.java b/src/main/java/com/example/nto/exception/InvalidUsername.java
new file mode 100644
index 0000000..72772e5
--- /dev/null
+++ b/src/main/java/com/example/nto/exception/InvalidUsername.java
@@ -0,0 +1,7 @@
+package com.example.nto.exception;
+
+public class InvalidUsername extends RuntimeException {
+ public InvalidUsername(String message) {
+ super(message);
+ }
+}
diff --git a/src/main/java/com/example/nto/repository/EmployeeRepository.java b/src/main/java/com/example/nto/repository/EmployeeRepository.java
index d845a04..968e56f 100644
--- a/src/main/java/com/example/nto/repository/EmployeeRepository.java
+++ b/src/main/java/com/example/nto/repository/EmployeeRepository.java
@@ -3,10 +3,14 @@ package com.example.nto.repository;
import com.example.nto.entity.Employee;
import org.springframework.data.jpa.repository.EntityGraph;
import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+import java.util.List;
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/repository/PlaceRepository.java b/src/main/java/com/example/nto/repository/PlaceRepository.java
index e7b84c9..5c67b85 100644
--- a/src/main/java/com/example/nto/repository/PlaceRepository.java
+++ b/src/main/java/com/example/nto/repository/PlaceRepository.java
@@ -1,7 +1,10 @@
package com.example.nto.repository;
import com.example.nto.entity.Place;
+import jdk.jfr.Registered;
import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+@Repository
public interface PlaceRepository extends JpaRepository {
}
diff --git a/src/main/java/com/example/nto/service/BookingService.java b/src/main/java/com/example/nto/service/BookingService.java
index 64e6ac6..37cd9f0 100644
--- a/src/main/java/com/example/nto/service/BookingService.java
+++ b/src/main/java/com/example/nto/service/BookingService.java
@@ -9,7 +9,7 @@ import java.util.List;
import java.util.Map;
public interface BookingService {
- Map> getFreePlace(String code);
+ Map> getFreePlace(String code, String password);
- Booking create(String code, BookingCreateDto bookingCreateDto);
+ Booking create(String code, String password, BookingCreateDto bookingCreateDto);
}
diff --git a/src/main/java/com/example/nto/service/EmployeeService.java b/src/main/java/com/example/nto/service/EmployeeService.java
index 83144af..2a0994f 100644
--- a/src/main/java/com/example/nto/service/EmployeeService.java
+++ b/src/main/java/com/example/nto/service/EmployeeService.java
@@ -1,9 +1,11 @@
package com.example.nto.service;
import com.example.nto.controller.dto.EmployeeDto;
+import com.example.nto.exception.InvalidPassword;
public interface EmployeeService {
EmployeeDto getByCode(String code);
- void auth(String code);
+ EmployeeDto auth(String username, String password) throws InvalidPassword;
+
}
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..957d6e5 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 code, String password) {
+ employeeService.auth(code, password);
List allPlaces = placeRepository.findAll();
@@ -72,14 +72,15 @@ public class BookingServiceImpl implements BookingService {
@Override
@Transactional
- public Booking create(String code, BookingCreateDto bookingCreateDto) {
+ public Booking create(String code, String password, BookingCreateDto bookingCreateDto) {
+ employeeService.auth(code, password);
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)
+ Employee employee = employeeRepository.findByUsername(code)
.orElseThrow(() -> new EmployeeNotFoundException("Employee with " + code + " code not found!"));
long placeId = bookingCreateDto.getPlaceId();
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..1ccec1e 100644
--- a/src/main/java/com/example/nto/service/impl/EmployeeServiceImpl.java
+++ b/src/main/java/com/example/nto/service/impl/EmployeeServiceImpl.java
@@ -1,13 +1,22 @@
package com.example.nto.service.impl;
import com.example.nto.controller.dto.EmployeeDto;
+import com.example.nto.entity.Employee;
import com.example.nto.exception.EmployeeNotFoundException;
+import com.example.nto.exception.InvalidPassword;
+import com.example.nto.exception.InvalidUsername;
import com.example.nto.repository.EmployeeRepository;
import com.example.nto.service.EmployeeService;
+
import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
+import java.util.Optional;
+
+
+@Slf4j
@Service
@RequiredArgsConstructor
public class EmployeeServiceImpl implements EmployeeService {
@@ -21,11 +30,20 @@ public class EmployeeServiceImpl implements EmployeeService {
.orElseThrow(() -> new EmployeeNotFoundException("Employee with " + code + " 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 EmployeeDto auth(String username, String password) throws InvalidPassword {
+ Optional employee = employeeRepository.findByUsername(username);
+ if(employee.isEmpty()){
+ throw new InvalidUsername("Invalid Username");
}
+
+
+ if(!employee.get().getPassword().equals(password)){
+ throw new InvalidPassword("Wrong password: " + password);
+ }
+ return EmployeeDto.toDtoOpt(employee);
}
}
diff --git a/src/main/java/com/example/nto/utils/PasswordValidator.java b/src/main/java/com/example/nto/utils/PasswordValidator.java
new file mode 100644
index 0000000..a490119
--- /dev/null
+++ b/src/main/java/com/example/nto/utils/PasswordValidator.java
@@ -0,0 +1,16 @@
+package com.example.nto.utils;
+
+import java.util.regex.Pattern;
+
+public class PasswordValidator {
+ public static boolean validate(String password){
+ Pattern p = Pattern.compile("*[%?()*^$#@!/.,><|';:]*");
+ if(password.length() < 8){
+ return false;
+ }
+ if(!p.matcher(password).matches()){
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/src/main/resources/META-INF/MANIFEST.MF b/src/main/resources/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..929f41e
--- /dev/null
+++ b/src/main/resources/META-INF/MANIFEST.MF
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Main-Class: com.example.nto.App
+
diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml
index 8b68191..a2a2d7a 100644
--- a/src/main/resources/application.yml
+++ b/src/main/resources/application.yml
@@ -1,4 +1,6 @@
spring:
+ profiles:
+ active: "dev"
datasource:
url: jdbc:h2:mem:testdb
@@ -18,5 +20,8 @@ spring:
enabled: true
change-log: classpath:db.changelog/db.changelog-master.xml
+server:
+ port : 49179
+
booking:
days-ahead: 3
\ 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..1017f74 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,6 +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..d2015e1 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;code;photo_url;password;username
+Ivanov Ivan;1111;https://catalog-cdn.detmir.st/media/2fe02057f9915e72a378795d32c79ea9.jpeg;bac12345;ivan
+Petrov Petr;2222;https://catalog-cdn.detmir.st/media/2fe02057f9915e72a378795d32c79ea9.jpeg;bac12345;petr
+Kozlov Oleg;3333;https://catalog-cdn.detmir.st/media/2fe02057f9915e72a378795d32c79ea9.jpeg;bac12345;oleg
+Smirnova Anna;4444;https://catalog-cdn.udetmir.st/media/2fe02057f9915e72a378795d32c79ea9.jpeg;bac12345;anna
\ No newline at end of file