From d34a304763d47896a9307f712dd3afa5cbde6b76 Mon Sep 17 00:00:00 2001 From: vladp Date: Thu, 11 Dec 2025 13:00:01 +0700 Subject: [PATCH 1/3] add logout request,delete old controller --- .../nocopy/controller/ApiController.java | 5 +- .../nocopy/controller/AuthController.java | 37 ------------ .../ru/soune/nocopy/dto/LogOutAnswer.java | 7 +-- .../ru/soune/nocopy/dto/LogoutRequest.java | 19 +++++++ .../java/ru/soune/nocopy/dto/MessageCode.java | 2 + .../nocopy/handler/LogoutRequestHandler.java | 56 +++++++++++++++++++ 6 files changed, 83 insertions(+), 43 deletions(-) delete mode 100644 src/main/java/ru/soune/nocopy/controller/AuthController.java create mode 100644 src/main/java/ru/soune/nocopy/dto/LogoutRequest.java create mode 100644 src/main/java/ru/soune/nocopy/handler/LogoutRequestHandler.java diff --git a/src/main/java/ru/soune/nocopy/controller/ApiController.java b/src/main/java/ru/soune/nocopy/controller/ApiController.java index 460ad8b..0e4e641 100644 --- a/src/main/java/ru/soune/nocopy/controller/ApiController.java +++ b/src/main/java/ru/soune/nocopy/controller/ApiController.java @@ -15,6 +15,7 @@ import ru.soune.nocopy.dto.RegAnswer; import ru.soune.nocopy.exception.NotValidFieldException; import ru.soune.nocopy.exception.ValidationException; import ru.soune.nocopy.handler.LoginRequestHandler; +import ru.soune.nocopy.handler.LogoutRequestHandler; import ru.soune.nocopy.handler.RegRequestHandler; import ru.soune.nocopy.handler.RequestHandler; @@ -36,9 +37,11 @@ public class ApiController { public void init() { RegRequestHandler regHandler = applicationContext.getBean(RegRequestHandler.class); LoginRequestHandler loginHandler = applicationContext.getBean(LoginRequestHandler.class); + LogoutRequestHandler logoutHandler = applicationContext.getBean(LogoutRequestHandler.class); - handlers.put(20002, regHandler); handlers.put(20001, loginHandler); + handlers.put(20002, regHandler); + handlers.put(20003, logoutHandler); } @PostMapping("/v{version}/data") diff --git a/src/main/java/ru/soune/nocopy/controller/AuthController.java b/src/main/java/ru/soune/nocopy/controller/AuthController.java deleted file mode 100644 index d9ba3d3..0000000 --- a/src/main/java/ru/soune/nocopy/controller/AuthController.java +++ /dev/null @@ -1,37 +0,0 @@ -package ru.soune.nocopy.controller; - -import lombok.RequiredArgsConstructor; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; -import ru.soune.nocopy.entity.AuthToken; -import ru.soune.nocopy.exception.TokenNotFoundException; -import ru.soune.nocopy.repository.AuthTokenRepository; -import ru.soune.nocopy.service.AuthService; - -import java.util.Map; -import java.util.Optional; - -@RestController -@RequestMapping("v1/api/auth") -@RequiredArgsConstructor -public class AuthController { - - private final AuthService authService; - - private final AuthTokenRepository authTokenRepository; - - @PostMapping("/logout") - public ResponseEntity logout(@RequestHeader("Authorization") String tokenHeader) { - String token = tokenHeader.replace("Bearer ", ""); - - Optional opToken = authTokenRepository.findByToken(token); - - if (opToken.isEmpty()) { - throw new TokenNotFoundException("Token not found"); - } - - authService.logout(token); - - return ResponseEntity.ok(Map.of("success", true)); - } -} diff --git a/src/main/java/ru/soune/nocopy/dto/LogOutAnswer.java b/src/main/java/ru/soune/nocopy/dto/LogOutAnswer.java index fbb7e21..f483363 100644 --- a/src/main/java/ru/soune/nocopy/dto/LogOutAnswer.java +++ b/src/main/java/ru/soune/nocopy/dto/LogOutAnswer.java @@ -4,14 +4,11 @@ import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; -import java.util.List; -import java.util.Map; - @Data @AllArgsConstructor @NoArgsConstructor public class LogOutAnswer { - private String Token; + private String token; - private List> fieldErrors; + private String email; } diff --git a/src/main/java/ru/soune/nocopy/dto/LogoutRequest.java b/src/main/java/ru/soune/nocopy/dto/LogoutRequest.java new file mode 100644 index 0000000..33a43e4 --- /dev/null +++ b/src/main/java/ru/soune/nocopy/dto/LogoutRequest.java @@ -0,0 +1,19 @@ +package ru.soune.nocopy.dto; + +import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Size; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class LogoutRequest { + @NotBlank(message = "error.not.blank") @Email(message = "error.not.email") @Size(max = 128) + private String email; + + @NotBlank(message = "error.not.blank") + private String token; +} diff --git a/src/main/java/ru/soune/nocopy/dto/MessageCode.java b/src/main/java/ru/soune/nocopy/dto/MessageCode.java index e5fd6e4..6ec7505 100644 --- a/src/main/java/ru/soune/nocopy/dto/MessageCode.java +++ b/src/main/java/ru/soune/nocopy/dto/MessageCode.java @@ -8,6 +8,8 @@ public enum MessageCode { MSG_ID_NOT_FOUND(4, "Message id not found"), AUTH_EMAIL_NOT_FOUND(4, "Email not found"), + AUTH_EMAIL_OR_TOKEN_NOT_FOUND(4, "Email or Token not found "), + AUTH_TOKEN_MISMATCH(4, "Token mismatch"), AUTH_PASSWORD_NOT_MATCHES(2, "Password does not match"); private final Integer code; diff --git a/src/main/java/ru/soune/nocopy/handler/LogoutRequestHandler.java b/src/main/java/ru/soune/nocopy/handler/LogoutRequestHandler.java new file mode 100644 index 0000000..3e0ef89 --- /dev/null +++ b/src/main/java/ru/soune/nocopy/handler/LogoutRequestHandler.java @@ -0,0 +1,56 @@ +package ru.soune.nocopy.handler; + +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; +import ru.soune.nocopy.dto.*; +import ru.soune.nocopy.entity.AuthToken; +import ru.soune.nocopy.entity.User; +import ru.soune.nocopy.exception.NotValidFieldException; +import ru.soune.nocopy.repository.AuthTokenRepository; +import ru.soune.nocopy.repository.UserRepository; +import ru.soune.nocopy.service.AuthService; + +import java.util.Objects; +import java.util.Optional; + +@Component +@RequiredArgsConstructor +public class LogoutRequestHandler implements RequestHandler { + + private final AuthService authService; + + private final AuthTokenRepository authTokenRepository; + + private final ObjectMapper objectMapper; + + private final UserRepository userRepository; + + @Override + public BaseResponse handle(BaseRequest request) { + LogoutRequest logoutRequest = objectMapper.convertValue(request.getMessageBody(), LogoutRequest.class); + + Optional opToken = authTokenRepository.findByToken(logoutRequest.getToken()); + Optional user = userRepository.findByEmail(logoutRequest.getEmail()); + + if (opToken.isEmpty() || user.isEmpty()) { + throw new NotValidFieldException("User with email or token not found", + new BaseResponse(request.getMsgId(), MessageCode.AUTH_EMAIL_OR_TOKEN_NOT_FOUND.getCode(), + MessageCode.AUTH_EMAIL_OR_TOKEN_NOT_FOUND.getDescription(), + new LogoutRequest(logoutRequest.getEmail(), logoutRequest.getToken()))); + } + + if (!Objects.equals(opToken.get().getUser().getId(), user.get().getId())) { + throw new NotValidFieldException("User token mismatch with user", + new BaseResponse(request.getMsgId(), MessageCode.AUTH_TOKEN_MISMATCH.getCode(), + MessageCode.AUTH_TOKEN_MISMATCH.getDescription(), + new LogoutRequest(logoutRequest.getEmail(), logoutRequest.getToken()))); + } + + + authService.logout(logoutRequest.getToken()); + + return new BaseResponse(request.getMsgId(), MessageCode.SUCCESS.getCode(), MessageCode.SUCCESS.getDescription(), + new LogOutAnswer(logoutRequest.getEmail(), logoutRequest.getToken())); + } +} From 651b92cb59aae38f91cf6650e783cd158cceb210 Mon Sep 17 00:00:00 2001 From: vladp Date: Wed, 17 Dec 2025 15:40:38 +0700 Subject: [PATCH 2/3] fix job --- infrastructure/jenkins/deploy.groovy | 77 +++++++++++++++++++++++----- 1 file changed, 65 insertions(+), 12 deletions(-) diff --git a/infrastructure/jenkins/deploy.groovy b/infrastructure/jenkins/deploy.groovy index f19a80c..43b39ff 100644 --- a/infrastructure/jenkins/deploy.groovy +++ b/infrastructure/jenkins/deploy.groovy @@ -54,15 +54,26 @@ pipeline { echo 'Step 1: Checking current state...' # Смотрим что запущено - docker ps --filter 'name=postgres|app-backend' --format 'table {{.Names}}\\t{{.Status}}\\t{{.Ports}}' + docker ps --filter 'name=postgres|app-backend' --format 'table {{.Names}}\\t{{.Image}}\\t{{.Status}}\\t{{.Ports}}' - echo 'Step 2: Stopping only application (keeping DB)...' + echo 'Step 2: Force cleanup old application...' - # Останавливаем только приложение, БД оставляем работать + # Принудительно удаляем старый контейнер и образ docker stop app-backend 2>/dev/null || echo 'App not running' docker rm app-backend 2>/dev/null || echo 'App not found' + docker rmi app-backend:latest 2>/dev/null || echo 'Image not found' - # Проверяем что БД работает, если нет - запускаем + # Удаляем все образы app-backend + docker images --filter 'reference=app-backend*' -q | xargs -r docker rmi 2>/dev/null || echo 'No images to remove' + + echo 'Step 3: Verify copied files...' + echo 'Files in directory:' + ls -la + echo '' + echo 'Checking Java sources:' + find . -name '*.java' | head -2 + + echo 'Step 4: Check if PostgreSQL is running...' if ! docker ps | grep -q postgres; then echo 'Starting PostgreSQL...' docker-compose up -d db @@ -71,13 +82,37 @@ pipeline { echo 'PostgreSQL already running' fi - echo 'Step 3: Building new application image...' - docker build --no-cache -t app-backend:latest . + echo 'Step 5: Build application with forced rebuild...' + echo 'Checking Dockerfile exists:' + ls -la Dockerfile 2>/dev/null || echo 'Dockerfile not found, creating simple one' - echo 'Step 4: Starting application...' + # Если нет Dockerfile, создаем простой + if [ ! -f Dockerfile ]; then + echo 'Creating simple Dockerfile...' + cat > Dockerfile << 'EOF' +FROM eclipse-temurin:21-jre +WORKDIR /app +COPY . /app/ +CMD ["java", "-jar", "app.jar"] +EOF + fi + + # Собираем с подробным выводом + echo 'Building Docker image...' + docker build --no-cache --progress=plain -t app-backend:latest . 2>&1 | tail -50 + + echo 'Step 6: Verify new image...' + echo 'Current app-backend images:' + docker images | grep app-backend + + echo 'Image creation time:' + docker inspect app-backend:latest --format='{{.Created}}' 2>/dev/null || echo 'Cannot inspect image' + + echo 'Step 7: Starting application with alias...' docker run -d \\ --name app-backend \\ --network app-network \\ + --network-alias app \\ -p 80:8080 \\ -e POSTGRES_DB=no_copy_ \\ -e POSTGRES_USER=postgres \\ @@ -87,17 +122,35 @@ pipeline { --restart unless-stopped \\ app-backend:latest - echo 'Step 5: Checking deployment...' + echo 'Step 8: Checking deployment...' sleep 10 echo 'Containers status:' - docker ps --filter 'name=postgres|app-backend' --format 'table {{.Names}}\\t{{.Status}}\\t{{.Ports}}' + docker ps --filter 'name=postgres|app-backend' --format 'table {{.Names}}\\t{{.Image}}\\t{{.Status}}\\t{{.CreatedAt}}' - echo 'Application logs (last 5 lines):' - docker logs --tail=5 app-backend 2>/dev/null || echo 'Logs not available yet' + echo 'Checking image inside container:' + docker exec app-backend ls -la /app/ 2>/dev/null || echo 'Cannot check container files' + echo 'Application logs (last 10 lines):' + docker logs --tail=10 app-backend 2>/dev/null || echo 'Logs not available yet' + + echo 'Step 9: Health check...' if docker ps | grep -q app-backend; then - echo 'Deployment successful' + echo 'Container is running' + echo 'Testing application health...' + for i in {1..5}; do + if curl -s -f http://localhost:80/health > /dev/null 2>&1; then + echo 'Health check passed' + echo 'Deployment successful' + echo 'Application URL: http://${params.SERVER}:80' + exit 0 + fi + echo 'Waiting for application to start... attempt ' \$i + sleep 5 + done + + echo 'Health check failed, but container is running' + echo 'Application might be starting slowly' echo 'Application URL: http://${params.SERVER}:80' else echo 'Application failed to start' From f3266ee0e5841ec8c7f05fda938d71ab7ae97b92 Mon Sep 17 00:00:00 2001 From: vladp Date: Thu, 18 Dec 2025 17:50:06 +0700 Subject: [PATCH 3/3] NCBACK-13 --- src/main/java/ru/soune/nocopy/controller/ApiController.java | 2 +- src/main/java/ru/soune/nocopy/dto/LogOutAnswer.java | 2 -- src/main/java/ru/soune/nocopy/handler/LogoutRequestHandler.java | 2 +- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/main/java/ru/soune/nocopy/controller/ApiController.java b/src/main/java/ru/soune/nocopy/controller/ApiController.java index 0e4e641..5c8c457 100644 --- a/src/main/java/ru/soune/nocopy/controller/ApiController.java +++ b/src/main/java/ru/soune/nocopy/controller/ApiController.java @@ -41,7 +41,7 @@ public class ApiController { handlers.put(20001, loginHandler); handlers.put(20002, regHandler); - handlers.put(20003, logoutHandler); + handlers.put(20006, logoutHandler); } @PostMapping("/v{version}/data") diff --git a/src/main/java/ru/soune/nocopy/dto/LogOutAnswer.java b/src/main/java/ru/soune/nocopy/dto/LogOutAnswer.java index f483363..009f5f5 100644 --- a/src/main/java/ru/soune/nocopy/dto/LogOutAnswer.java +++ b/src/main/java/ru/soune/nocopy/dto/LogOutAnswer.java @@ -8,7 +8,5 @@ import lombok.NoArgsConstructor; @AllArgsConstructor @NoArgsConstructor public class LogOutAnswer { - private String token; - private String email; } diff --git a/src/main/java/ru/soune/nocopy/handler/LogoutRequestHandler.java b/src/main/java/ru/soune/nocopy/handler/LogoutRequestHandler.java index 3e0ef89..44fa253 100644 --- a/src/main/java/ru/soune/nocopy/handler/LogoutRequestHandler.java +++ b/src/main/java/ru/soune/nocopy/handler/LogoutRequestHandler.java @@ -51,6 +51,6 @@ public class LogoutRequestHandler implements RequestHandler { authService.logout(logoutRequest.getToken()); return new BaseResponse(request.getMsgId(), MessageCode.SUCCESS.getCode(), MessageCode.SUCCESS.getDescription(), - new LogOutAnswer(logoutRequest.getEmail(), logoutRequest.getToken())); + new LogOutAnswer(logoutRequest.getEmail())); } }