Files
jambotron/src/main/java/com/jambotronGroup/jambotron/controllers/ProjectController.java
T
2026-05-05 23:10:05 +03:00

209 lines
8.8 KiB
Java

package com.jambotronGroup.jambotron.controllers;
import com.jambotronGroup.jambotron.model.Project;
import com.jambotronGroup.jambotron.model.ProjectStatus;
import com.jambotronGroup.jambotron.model.User;
import com.jambotronGroup.jambotron.projects.ContainerStatus;
import com.jambotronGroup.jambotron.projects.ProjectCreateRequest;
import com.jambotronGroup.jambotron.projects.ProjectDetailResponse;
import com.jambotronGroup.jambotron.projects.ProjectService;
import com.jambotronGroup.jambotron.repository.UserRepository;
import com.jambotronGroup.jambotron.security.AuthenticationFacade;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.UUID;
@RestController
@RequestMapping("/api")
@RequiredArgsConstructor
public class ProjectController {
private static final Logger _logger = LoggerFactory.getLogger(ProjectController.class);
private final ProjectService projectService;
private final UserRepository userRepository;
private final AuthenticationFacade authenticationFacade;
//-------------------- Просмотр и Dashboard ----------------------------
/**
* Получение списка проектов текущего пользователя (Dashboard)[cite: 2, 3].
*/
@GetMapping("/user/projects")
public ResponseEntity<List<Project>> getUserProjects() {
try {
User user = getCurrentUser();
List<Project> projects = projectService.findAllByOwnerId(user.getId());
if (projects.isEmpty()) {
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
return new ResponseEntity<>(projects, HttpStatus.OK);
} catch (Exception e) {
_logger.error("Error fetching user projects", e);
return new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
/**
* Детали проекта (Project + Config). Доступно владельцу или админу.
*/
@GetMapping("/user/projects/{id}/details")
public ResponseEntity<ProjectDetailResponse> getProjectDetails(@PathVariable UUID id) {
try {
User user = getCurrentUser();
boolean isAdmin = checkIfAdmin(user);
// Метод сервиса сам проверит права владельца, если isAdmin = false
ProjectDetailResponse details = projectService.getProjectDetailsSecure(
id,
user.getId(),
isAdmin
);
return new ResponseEntity<>(details, HttpStatus.OK);
} catch (AccessDeniedException e) {
return new ResponseEntity<>(HttpStatus.FORBIDDEN);
} catch (Exception e) {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
}
//-------------------- Управление Жизненным Циклом (User & Admin) ----------------------------
/**
* Деплой проекта (Docker Compose Up). Доступно владельцу или админу[cite: 1, 4].
*/
@PostMapping("/user/projects/{id}/deploy")
public ResponseEntity<String> deployProject(@PathVariable UUID id) {
// Получаем текущего пользователя (твой метод)
User user = getCurrentUser();
// Используем метод сервиса findById, а не репозиторий напрямую!
Project project = projectService.findById(id);
// Выполняем проверку безопасности (через String.valueOf, как мы выяснили)
if (checkIfAdmin(user) ||
String.valueOf(project.getUser().getId()).equals(String.valueOf(user.getId()))) {
// ВАЖНО: В твоем сервисе метод называется deployProject(Project project)
projectService.deployProject(project);
return ResponseEntity.ok("Процесс созидания запущен...");
}
return ResponseEntity.status(403).body("Access Denied");
}
/**
* Остановка проекта (Docker Compose Down). Доступно владельцу или админу[cite: 1, 4].
*/
@PostMapping("/user/projects/{id}/stop")
public ResponseEntity<String> stopProject(@PathVariable UUID id) {
User user = getCurrentUser();
Project project = projectService.findById(id);
if (!checkIfAdmin(user) && !project.getUser().getId().equals(String.valueOf(user.getId()))) {
return new ResponseEntity<>("Access Denied", HttpStatus.FORBIDDEN);
}
projectService.stopProject(project);
project.setStatus(ProjectStatus.STOPPED);
projectService.save(project);
return ResponseEntity.ok("Project stopped: " + project.getName());
}
/**
* Удаление проекта (Очистка Docker + Файлы + БД). Доступно владельцу или админу[cite: 1, 2].
*/
@DeleteMapping("/user/projects/{id}")
public ResponseEntity<String> deleteProject(@PathVariable UUID id) {
User user = getCurrentUser();
Project project = projectService.findById(id);
// Безопасная проверка владельца (уже ставшая стандартом для нашего "сосуда")
if (checkIfAdmin(user) ||
String.valueOf(project.getUser().getId()).equals(String.valueOf(user.getId()))) {
_logger.info("Начато полное удаление проекта: {}", id);
projectService.deleteProject(id); // Вызов того самого метода из ProjectService_2.java
return ResponseEntity.ok("Проект полностью удален из системы");
}
return ResponseEntity.status(403).body("Access Denied");
}
//-------------------- Администрирование PaaS ----------------------------
/**
* Список всех проектов системы для глобального мониторинга[cite: 2].
*/
@GetMapping("/admin/projects/all")
public ResponseEntity<List<Project>> getAllProjectsForAdmin() {
User user = getCurrentUser();
if (!checkIfAdmin(user)) {
return new ResponseEntity<>(HttpStatus.FORBIDDEN);
}
List<Project> allProjects = projectService.findAllProjectsForAdmin();
return new ResponseEntity<>(allProjects, HttpStatus.OK);
}
//-------------------- Создание и Конфигурация ----------------------------
@PostMapping("/user/projects")
public ResponseEntity<Project> create(@Valid @RequestBody ProjectCreateRequest request) {
User user = getCurrentUser();
Project newProject = projectService.createProject(request.name(), request.rawComposeContent(), user);
return ResponseEntity.status(HttpStatus.CREATED).body(newProject);
}
@PutMapping("/user/projects/{id}/config")
public ResponseEntity<String> updateConfig(@PathVariable UUID id, @RequestBody String newContent) {
User user = getCurrentUser();
Project project = projectService.findById(id);
if (!checkIfAdmin(user) && !project.getUser().getId().equals(String.valueOf(user.getId()))) {
return new ResponseEntity<>("Access Denied", HttpStatus.FORBIDDEN);
}
projectService.updateProjectConfig(id, newContent);
return ResponseEntity.ok("Configuration updated.");
}
//-------------------- Вспомогательные методы ----------------------------
private User getCurrentUser() {
return userRepository.findById(authenticationFacade.getUserDetails().getId())
.orElseThrow(() -> new RuntimeException("Current user not found"));
}
private boolean checkIfAdmin(User user) {
return user.getRoles() != null && (user.getRoles().equals("ADMIN") || user.getRoles().equals("ROLE_ADMIN"));
}
@GetMapping("/user/projects/{id}/containers")
public ResponseEntity<List<ContainerStatus>> getContainers(@PathVariable UUID id) {
User user = getCurrentUser();
Project project = projectService.findById(id);
// Применяем нашу "золотую формулу" сравнения ID
if (checkIfAdmin(user) ||
String.valueOf(project.getUser().getId()).equals(String.valueOf(user.getId()))) {
return ResponseEntity.ok(projectService.getProjectContainers(id));
}
return ResponseEntity.status(403).build();
}
}