209 lines
8.8 KiB
Java
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();
|
|
}
|
|
} |