fixes+icripted passwords lol
This commit is contained in:
parent
c0eef0a2c5
commit
0137ba0bb2
@ -2,10 +2,14 @@ package com.example.nto;
|
|||||||
|
|
||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||||
|
|
||||||
@SpringBootApplication
|
@SpringBootApplication
|
||||||
public class App {
|
public class App {
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
SpringApplication.run(App.class, args);
|
SpringApplication.run(App.class, args);
|
||||||
|
System.out.println(new BCryptPasswordEncoder().encode("password000"));
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,57 +1,63 @@
|
|||||||
package com.example.nto.config;
|
package com.example.nto.config;
|
||||||
|
|
||||||
import com.example.nto.entity.Employee;
|
import com.example.nto.entity.Employee;
|
||||||
import com.example.nto.service.EmployeeService;
|
import com.example.nto.repository.EmployeeRepository;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
|
||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
import org.springframework.security.core.userdetails.User;
|
||||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
|
||||||
import org.springframework.security.crypto.password.NoOpPasswordEncoder; // Для незашифрованных паролей
|
|
||||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
|
||||||
import org.springframework.security.core.userdetails.UserDetails;
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||||
|
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||||
|
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
|
||||||
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@EnableWebSecurity
|
public class SecurityConfig {
|
||||||
public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
|
||||||
|
|
||||||
@Autowired
|
private final EmployeeRepository employeeRepository;
|
||||||
private EmployeeService employeeService;
|
|
||||||
|
|
||||||
@Override
|
public SecurityConfig(EmployeeRepository employeeRepository) {
|
||||||
protected void configure(HttpSecurity http) throws Exception {
|
this.employeeRepository = employeeRepository;
|
||||||
http
|
|
||||||
.csrf().disable() // Отключ CSRF
|
|
||||||
.authorizeRequests()
|
|
||||||
.antMatchers("/api/auth").permitAll() // Разрешаем доступ к /auth
|
|
||||||
.anyRequest().authenticated() // Все запросы требуют аутентификации
|
|
||||||
.and()
|
|
||||||
.httpBasic(); // Включаем базу
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Bean
|
||||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
public BCryptPasswordEncoder passwordEncoder() {
|
||||||
auth.userDetailsService(userDetailsService()).passwordEncoder(NoOpPasswordEncoder.getInstance());
|
return new BCryptPasswordEncoder();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public UserDetailsService userDetailsService() {
|
public UserDetailsService userDetailsService() {
|
||||||
return username -> {
|
return username -> {
|
||||||
Optional<Employee> employee = employeeService.findByLogin(username);
|
Optional<Employee> employee = Optional.ofNullable(employeeRepository.findByLogin(username));
|
||||||
if (employee.isPresent()) {
|
if (employee.isEmpty()) {
|
||||||
Employee emp = employee.get();
|
throw new RuntimeException("User not found");
|
||||||
return org.springframework.security.core.userdetails.User.withUsername(emp.getLogin())
|
|
||||||
.password(emp.getPassword())
|
|
||||||
.roles(emp.getRole())
|
|
||||||
.build();
|
|
||||||
} else {
|
|
||||||
throw new UsernameNotFoundException("User not found with login: " + username);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Employee emp = employee.get();
|
||||||
|
return User.builder()
|
||||||
|
.username(emp.getLogin())
|
||||||
|
.password(emp.getPassword()) // Пароль должен быть в BCrypt
|
||||||
|
.roles(emp.getRole().toUpperCase()) // Spring Security требует `ROLE_XXX`
|
||||||
|
.build();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
||||||
|
http
|
||||||
|
.authorizeRequests()
|
||||||
|
.antMatchers("/api/auth").permitAll()
|
||||||
|
.antMatchers("/api/workers").hasRole("ADMIN") // Только админ может смотреть всех сотрудников
|
||||||
|
.antMatchers("/api/{login}/block").hasRole("ADMIN") // Только админ может блокировать
|
||||||
|
.anyRequest().authenticated() // Остальные запросы доступны всем авторизованным пользователям
|
||||||
|
.and()
|
||||||
|
.httpBasic()
|
||||||
|
.and()
|
||||||
|
.csrf().disable();
|
||||||
|
|
||||||
|
return http.build();
|
||||||
|
}
|
||||||
}
|
}
|
@ -2,18 +2,14 @@ package com.example.nto.controller;
|
|||||||
|
|
||||||
import com.example.nto.entity.Employee;
|
import com.example.nto.entity.Employee;
|
||||||
import com.example.nto.service.EmployeeService;
|
import com.example.nto.service.EmployeeService;
|
||||||
import org.springframework.http.HttpStatus;
|
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/api") // база
|
@RequestMapping("/api")
|
||||||
public class EmployeeController {
|
public class EmployeeController {
|
||||||
|
|
||||||
private final EmployeeService employeeService;
|
private final EmployeeService employeeService;
|
||||||
@ -22,66 +18,53 @@ public class EmployeeController {
|
|||||||
this.employeeService = employeeService;
|
this.employeeService = employeeService;
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/auth") // Проверка аутентификации
|
// Аутентификация
|
||||||
public ResponseEntity<?> authenticate(@RequestHeader("Authorization") String authHeader) {
|
@GetMapping("/auth")
|
||||||
// Проверяем заголовок
|
public ResponseEntity<String> authenticate(@RequestHeader("Authorization") String authHeader) {
|
||||||
if (authHeader == null || !authHeader.startsWith("Basic ")) {
|
|
||||||
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Missing or invalid Authorization header");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Получение логина и пароля
|
|
||||||
String[] credentials = new String(java.util.Base64.getDecoder().decode(authHeader.substring(6))).split(":");
|
String[] credentials = new String(java.util.Base64.getDecoder().decode(authHeader.substring(6))).split(":");
|
||||||
|
|
||||||
String login = credentials[0];
|
String login = credentials[0];
|
||||||
String password = credentials.length > 1 ? credentials[1] : "";
|
String password = credentials.length > 1 ? credentials[1] : "";
|
||||||
|
|
||||||
Optional<Employee> employee = employeeService.findByLogin(login);
|
if (employeeService.authenticate(login, password)) {
|
||||||
|
|
||||||
if (employee.isPresent() && employee.get().getPassword().equals(password)) {
|
|
||||||
return ResponseEntity.ok("Authenticated successfully");
|
return ResponseEntity.ok("Authenticated successfully");
|
||||||
}
|
}
|
||||||
|
return ResponseEntity.status(401).body("Invalid login or password");
|
||||||
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Invalid login or password");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@PreAuthorize("isAuthenticated()") // Убедитесь, что пользователь аутентифицирован
|
// Получение информации о пользователе
|
||||||
@GetMapping("/{login}/info") // Получение информации о сотруднике
|
@PreAuthorize("isAuthenticated()")
|
||||||
public ResponseEntity<?> getInfo(@PathVariable String login) {
|
@GetMapping("/{login}/info")
|
||||||
|
public ResponseEntity<?> getUserInfo(@PathVariable String login) {
|
||||||
Optional<Employee> employee = employeeService.findByLogin(login);
|
Optional<Employee> employee = employeeService.findByLogin(login);
|
||||||
if (employee.isPresent()) {
|
if (employee.isPresent()) {
|
||||||
return ResponseEntity.ok(employee.get());
|
return ResponseEntity.ok(employee.get());
|
||||||
} else {
|
|
||||||
return ResponseEntity.status(HttpStatus.NOT_FOUND).body("Employee not found");
|
|
||||||
}
|
}
|
||||||
|
return ResponseEntity.status(404).body("User not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
@PreAuthorize("isAuthenticated()") // Убедитесь, что пользователь аутентифицирован
|
// Получение списка всех сотрудников (только для администратора)
|
||||||
@PatchMapping("/{login}/open") // Открыть дверь
|
@PreAuthorize("hasRole('ADMIN')")
|
||||||
public ResponseEntity<?> openDoor(@PathVariable String login, @RequestBody Map<String, Long> payload) {
|
|
||||||
Long code = payload.get("value");
|
|
||||||
|
|
||||||
if (code != null) {
|
|
||||||
Optional<Employee> employee = employeeService.findByLogin(login);
|
|
||||||
if (!employee.isPresent()) {
|
|
||||||
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("Invalid login");
|
|
||||||
}
|
|
||||||
if (employeeService.validateCode(login, code)) {
|
|
||||||
return ResponseEntity.ok("Door opened");
|
|
||||||
} else {
|
|
||||||
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("Invalid code");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("Invalid payload");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@PreAuthorize("hasRole('admin')")
|
|
||||||
@GetMapping("/workers")
|
@GetMapping("/workers")
|
||||||
public ResponseEntity<List<Employee>> getAllWorkers() {
|
public ResponseEntity<?> getAllWorkers() {
|
||||||
String currentUserName = SecurityContextHolder.getContext().getAuthentication().getName();
|
return ResponseEntity.ok(employeeService.findAll());
|
||||||
// Логируем информацию о текущем пользователе
|
}
|
||||||
System.out.println("Current user: " + currentUserName);
|
|
||||||
List<Employee> allEmployees = employeeService.findAll();
|
// Блокировка/разблокировка пользователя (только для администратора)
|
||||||
return ResponseEntity.ok(allEmployees);
|
@PreAuthorize("hasRole('ADMIN')")
|
||||||
|
@PatchMapping("/{login}/block")
|
||||||
|
public ResponseEntity<String> toggleBlockStatus(@PathVariable String login) {
|
||||||
|
employeeService.toggleBlockStatus(login);
|
||||||
|
return ResponseEntity.ok("User " + login + " status changed");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Открытие двери, если сотрудник не заблокирован
|
||||||
|
@PreAuthorize("isAuthenticated()")
|
||||||
|
@PatchMapping("/{login}/open")
|
||||||
|
public ResponseEntity<String> openDoor(@PathVariable String login, @RequestBody Long code) {
|
||||||
|
Optional<Employee> employee = employeeService.findByLogin(login);
|
||||||
|
if (employee.isPresent() && !employee.get().isBlocked() && employeeService.validateCode(login, code)) {
|
||||||
|
return ResponseEntity.ok("Door opened");
|
||||||
|
}
|
||||||
|
return ResponseEntity.status(403).body("Access denied");
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,7 +1,10 @@
|
|||||||
|
|
||||||
package com.example.nto.entity;
|
package com.example.nto.entity;
|
||||||
|
|
||||||
import javax.persistence.*;
|
import javax.persistence.*;
|
||||||
import lombok.*;
|
import lombok.*;
|
||||||
|
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@ -15,7 +18,9 @@ public class Employee {
|
|||||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
private long id;
|
private long id;
|
||||||
|
|
||||||
|
@Column(unique = true, nullable = false)
|
||||||
private String login;
|
private String login;
|
||||||
|
|
||||||
private String name;
|
private String name;
|
||||||
private String photo;
|
private String photo;
|
||||||
private String position;
|
private String position;
|
||||||
@ -24,11 +29,14 @@ public class Employee {
|
|||||||
private LocalDateTime lastVisit;
|
private LocalDateTime lastVisit;
|
||||||
|
|
||||||
private String password;
|
private String password;
|
||||||
|
|
||||||
private String role;
|
private String role;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private String status = "works"; // Новый статус: 'works' или 'blocked'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public boolean isBlocked() {
|
||||||
|
return "blocked".equals(status);
|
||||||
|
}
|
||||||
}
|
}
|
@ -11,5 +11,7 @@ public interface CodeRepository extends JpaRepository<Code, Long> {
|
|||||||
|
|
||||||
// Метод для поиска кодов по логину
|
// Метод для поиска кодов по логину
|
||||||
@Query("SELECT c.value FROM Code c WHERE c.employee.login = :login")
|
@Query("SELECT c.value FROM Code c WHERE c.employee.login = :login")
|
||||||
List<Long> findCodesByLogin(@Param("login") String login);
|
static List<Long> findCodesByLogin(@Param("login") String login) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
@ -9,4 +9,6 @@ public interface EmployeeService {
|
|||||||
List<Employee> findAll();
|
List<Employee> findAll();
|
||||||
Optional<Employee> findByLogin(String login);
|
Optional<Employee> findByLogin(String login);
|
||||||
boolean validateCode(String login, long code);
|
boolean validateCode(String login, long code);
|
||||||
|
boolean authenticate(String login, String rawPassword);
|
||||||
|
void toggleBlockStatus(String login);
|
||||||
}
|
}
|
@ -1,9 +1,10 @@
|
|||||||
package com.example.nto.service.impl;
|
package com.example.nto.service.impl;
|
||||||
|
|
||||||
import com.example.nto.entity.Employee;
|
import com.example.nto.entity.Employee;
|
||||||
import com.example.nto.repository.CodeRepository; // Импортируйте нужный репозиторий
|
import com.example.nto.repository.CodeRepository;
|
||||||
import com.example.nto.repository.EmployeeRepository;
|
import com.example.nto.repository.EmployeeRepository;
|
||||||
import com.example.nto.service.EmployeeService;
|
import com.example.nto.service.EmployeeService;
|
||||||
|
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -13,12 +14,10 @@ import java.util.Optional;
|
|||||||
public class EmployeeServiceImpl implements EmployeeService {
|
public class EmployeeServiceImpl implements EmployeeService {
|
||||||
|
|
||||||
private final EmployeeRepository employeeRepository;
|
private final EmployeeRepository employeeRepository;
|
||||||
private final CodeRepository codeRepository; // Добавьте CodeRepository как зависимость
|
private final BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
|
||||||
|
|
||||||
// Конструктор с внедрением
|
public EmployeeServiceImpl(EmployeeRepository employeeRepository) {
|
||||||
public EmployeeServiceImpl(EmployeeRepository employeeRepository, CodeRepository codeRepository) {
|
|
||||||
this.employeeRepository = employeeRepository;
|
this.employeeRepository = employeeRepository;
|
||||||
this.codeRepository = codeRepository; // Инициируем код репозиторий
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -33,8 +32,8 @@ public class EmployeeServiceImpl implements EmployeeService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean validateCode(String login, long code) {
|
public boolean validateCode(String login, long code) {
|
||||||
// Получаем все коды для данного логина
|
|
||||||
List<Long> validCodes = codeRepository.findCodesByLogin(login); // Теперь вызывается из объекта
|
List<Long> validCodes = CodeRepository.findCodesByLogin(login); // Теперь вызывается из объекта
|
||||||
|
|
||||||
// Проверяем, если переданный код присутствует в списке
|
// Проверяем, если переданный код присутствует в списке
|
||||||
boolean isValid = validCodes.contains(code);
|
boolean isValid = validCodes.contains(code);
|
||||||
@ -45,4 +44,20 @@ public class EmployeeServiceImpl implements EmployeeService {
|
|||||||
|
|
||||||
return isValid;
|
return isValid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean authenticate(String login, String rawPassword) {
|
||||||
|
Optional<Employee> employee = findByLogin(login);
|
||||||
|
if (employee.isPresent() && !employee.get().isBlocked()) {
|
||||||
|
return passwordEncoder.matches(rawPassword, employee.get().getPassword());
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void toggleBlockStatus(String login) {
|
||||||
|
Optional<Employee> employee = findByLogin(login);
|
||||||
|
employee.ifPresent(emp -> {
|
||||||
|
emp.setStatus(emp.isBlocked() ? "works" : "blocked");
|
||||||
|
employeeRepository.save(emp);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,26 +1,28 @@
|
|||||||
-- Создание таблицы employee
|
-- Создание таблицы employee
|
||||||
CREATE TABLE IF NOT EXISTS employee (
|
CREATE TABLE IF NOT EXISTS employee (
|
||||||
id INT PRIMARY KEY,
|
id INT PRIMARY KEY AUTO_INCREMENT,
|
||||||
login VARCHAR(255),
|
login VARCHAR(255) UNIQUE NOT NULL,
|
||||||
name VARCHAR(255),
|
name VARCHAR(255) NOT NULL,
|
||||||
photo VARCHAR(255),
|
photo VARCHAR(255),
|
||||||
position VARCHAR(255),
|
position VARCHAR(255),
|
||||||
last_visit TIMESTAMP,
|
last_visit TIMESTAMP,
|
||||||
password VARCHAR(255),
|
password VARCHAR(255) NOT NULL, -- Зашифрованный пароль
|
||||||
role VARCHAR(50)
|
role VARCHAR(50) NOT NULL,
|
||||||
|
status VARCHAR(20) DEFAULT 'works' -- Новый статус
|
||||||
);
|
);
|
||||||
|
|
||||||
-- Вставка данных в таблицу employee
|
-- Вставка данных в таблицу employee
|
||||||
INSERT INTO employee (id, login, name, photo, position, last_visit, password, role) //add
|
INSERT INTO employee (id, login, name, photo, position, last_visit, password, role, status)
|
||||||
VALUES
|
VALUES
|
||||||
(1, 'pivanov', 'Иванов Петр Федорович', 'https://funnyducks.ru/upload/iblock/0cd/0cdeb7ec3ed6fddda0f90fccee05557d.jpg', 'Разработчик', '2024-02-12T08:30', 'password123', 'admin'),
|
(1, 'pivanov', 'Иванов Петр Федорович', 'https://funnyducks.ru/upload/iblock/0cd/0cdeb7ec3ed6fddda0f90fccee05557d.jpg', 'Разработчик', '2024-02-12T08:30', '$2a$10$LRykcZHYR0tb72biv9aqp./icK7ReK57gRFDd74kiF02ZoZqQtnEm', 'ADMIN','works'),
|
||||||
(2, 'ipetrov', 'Петров Иван Константинович', 'https://funnyducks.ru/upload/iblock/0cd/0cdeb7ec3ed6fddda0f90fccee05557d.jpg', 'Аналитик', '2024-02-13T08:35', 'password456', 'user'),
|
(2, 'ipetrov', 'Петров Иван Константинович', 'https://funnyducks.ru/upload/iblock/0cd/0cdeb7ec3ed6fddda0f90fccee05557d.jpg', 'Аналитик', '2024-02-13T08:35', '$2a$10$rscyLIftEqucmDbSzBHZbO5DUOyICzkYXzQ4stJfbSN.Ao9R4kfQe', 'USER', 'works'),
|
||||||
(3, 'asemenov', 'Семенов Анатолий Анатольевич', 'https://funnyducks.ru/upload/iblock/0cd/0cdeb7ec3ed6fddda0f90fccee05557d.jpg', 'Разработчик', '2024-02-13T08:31', 'password789', 'user'),
|
(3, 'asemenov', 'Семенов Анатолий Анатольевич', 'https://funnyducks.ru/upload/iblock/0cd/0cdeb7ec3ed6fddda0f90fccee05557d.jpg', 'Разработчик', '2024-02-13T08:31', '$2a$10$o/g9lV7iDi.WhwztohTcfuIEhHHWUo5xlR0Vvdy2xaaI3RNwfbqzO', 'USER', 'works'),
|
||||||
(4, 'afedorov', 'Федоров Александр Сергеевич', 'https://funnyducks.ru/upload/iblock/0cd/0cdeb7ec3ed6fddda0f90fccee05557d.jpg', 'Тестировщик', '2024-02-12T08:36', 'password000', 'user');
|
(4, 'afedorov', 'Федоров Александр Сергеевич', 'https://funnyducks.ru/upload/iblock/0cd/0cdeb7ec3ed6fddda0f90fccee05557d.jpg', 'Тестировщик', '2024-02-12T08:36', '$2a$10$s33LR8PuMLQJQY85.zusceJVJLUn8mwEEwAsAUzQIaiwnjeKjt.km', 'USER', 'works');
|
||||||
|
|
||||||
-- Создание таблицы code
|
-- Создание таблицы code
|
||||||
CREATE TABLE IF NOT EXISTS code (
|
CREATE TABLE IF NOT EXISTS code (
|
||||||
value BIGINT
|
value BIGINT,
|
||||||
|
employee_id INT
|
||||||
);
|
);
|
||||||
|
|
||||||
-- Вставка данных в таблицу code
|
-- Вставка данных в таблицу code
|
||||||
|
Loading…
x
Reference in New Issue
Block a user