remake init data
json dump
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
package com.jambotronGroup.jambotron.DTOs;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.jambotronGroup.jambotron.model.ERole;
|
||||
import com.jambotronGroup.jambotron.model.Role;
|
||||
|
||||
public class RoleDto {
|
||||
@JsonIgnore
|
||||
private Long id;
|
||||
private ERole name;
|
||||
|
||||
public RoleDto() {
|
||||
}
|
||||
|
||||
public RoleDto(Long id, ERole name) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public ERole getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(ERole name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
// Mapping helpers
|
||||
public static RoleDto fromEntity(Role role) {
|
||||
if (role == null) return null;
|
||||
return new RoleDto(role.getId(), role.getName());
|
||||
}
|
||||
|
||||
public Role toEntity() {
|
||||
Role role = new Role();
|
||||
role.setId(this.id);
|
||||
role.setName(this.name);
|
||||
return role;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
package com.jambotronGroup.jambotron.DTOs;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.jambotronGroup.jambotron.model.Tutorial;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
|
||||
public class TutorialDto {
|
||||
@JsonIgnore
|
||||
private Long id;
|
||||
private String title;
|
||||
private String description;
|
||||
private Boolean published;
|
||||
|
||||
private boolean tobepublished;
|
||||
|
||||
private Long userID;
|
||||
|
||||
private java.sql.Timestamp created;
|
||||
|
||||
private java.sql.Timestamp modified;
|
||||
|
||||
private String titleimage;
|
||||
|
||||
private String body;
|
||||
|
||||
public TutorialDto() {
|
||||
}
|
||||
|
||||
public TutorialDto(Long id, String title, String description, Boolean published, boolean tobepublished, Long userID, Timestamp created, Timestamp modified, String titleimage, String body) {
|
||||
this.id = id;
|
||||
this.title = title;
|
||||
this.description = description;
|
||||
this.published = published;
|
||||
this.tobepublished = tobepublished;
|
||||
this.userID = userID;
|
||||
this.created = created;
|
||||
this.modified = modified;
|
||||
this.titleimage = titleimage;
|
||||
this.body = body;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public Boolean getPublished() {
|
||||
return published;
|
||||
}
|
||||
|
||||
public void setPublished(Boolean published) {
|
||||
this.published = published;
|
||||
}
|
||||
|
||||
public boolean isTobepublished() {
|
||||
return tobepublished;
|
||||
}
|
||||
public void setTobepublished(boolean tobepublished) {
|
||||
this.tobepublished = tobepublished;
|
||||
}
|
||||
public Long getUserID() {
|
||||
return userID;
|
||||
}
|
||||
public void setUserID(Long userID) {
|
||||
this.userID = userID;
|
||||
}
|
||||
public Timestamp getCreated() {
|
||||
return created;
|
||||
}
|
||||
public void setCreated(Timestamp created) {
|
||||
this.created = created;
|
||||
}
|
||||
public Timestamp getModified() {
|
||||
return modified;
|
||||
}
|
||||
public void setModified(Timestamp modified) {
|
||||
this.modified = modified;
|
||||
}
|
||||
public String getTitleimage() {
|
||||
return titleimage;
|
||||
}
|
||||
public void setTitleimage(String titleimage) {
|
||||
this.titleimage = titleimage;
|
||||
}
|
||||
public String getBody() {
|
||||
return body;
|
||||
}
|
||||
public void setBody(String body) {
|
||||
this.body = body;
|
||||
}
|
||||
|
||||
// Mapping helpers
|
||||
public static TutorialDto fromEntity(Tutorial tutorial) {
|
||||
if (tutorial == null) return null;
|
||||
return new TutorialDto(
|
||||
tutorial.getId(),
|
||||
tutorial.getTitle(),
|
||||
tutorial.getDescription(),
|
||||
tutorial.isPublished(),
|
||||
tutorial.isTobepublished(),
|
||||
tutorial.getUser().getId(),
|
||||
tutorial.getCreated(),
|
||||
tutorial.getModified(),
|
||||
tutorial.getTitleimage(),
|
||||
tutorial.getBody()
|
||||
);
|
||||
}
|
||||
|
||||
public Tutorial toEntity() {
|
||||
Tutorial tutorial = new Tutorial();
|
||||
tutorial.setId(this.id);
|
||||
tutorial.setTitle(this.title);
|
||||
tutorial.setDescription(this.description);
|
||||
if (this.published != null) {
|
||||
tutorial.setPublished(this.published);
|
||||
}
|
||||
tutorial.setCreated(this.created);
|
||||
tutorial.setModified(this.modified);
|
||||
tutorial.setTobepublished(this.tobepublished);
|
||||
tutorial.setTitleimage(this.titleimage);
|
||||
tutorial.setBody(this.body);
|
||||
|
||||
return tutorial;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
package com.jambotronGroup.jambotron.DTOs;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.jambotronGroup.jambotron.model.User;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class UserDto {
|
||||
@JsonIgnore
|
||||
private Long id;
|
||||
private String username;
|
||||
private String email;
|
||||
|
||||
private String password; // typically you don't expose password in DTOs
|
||||
|
||||
private Set<RoleDto> roles; // typically you don't expose password in DTOs
|
||||
|
||||
|
||||
public UserDto() {
|
||||
}
|
||||
|
||||
public UserDto(Long id, String username, String email, String password, Set<RoleDto> roles) {
|
||||
this.id = id;
|
||||
this.username = username;
|
||||
this.email = email;
|
||||
this.password = password;
|
||||
this.roles = roles;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public String getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
public void setEmail(String email) {
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
public Set<RoleDto> getRoles() {
|
||||
return roles;
|
||||
}
|
||||
|
||||
public void setRoles(Set<RoleDto> roles) {
|
||||
this.roles = roles;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
// Mapping helpers
|
||||
public static UserDto fromEntity(User user) {
|
||||
if (user == null) return null;
|
||||
return new UserDto(
|
||||
user.getId(),
|
||||
user.getUsername(),
|
||||
user.getEmail(),
|
||||
user.getPassword(),
|
||||
user.getRoles() == null ? null :
|
||||
user.getRoles().stream()
|
||||
.filter(Objects::nonNull)
|
||||
.map(RoleDto::fromEntity)
|
||||
.collect(Collectors.toSet())
|
||||
);
|
||||
}
|
||||
|
||||
public User toEntity() {
|
||||
User user = new User();
|
||||
user.setId(this.id);
|
||||
user.setUsername(this.username);
|
||||
user.setEmail(this.email);
|
||||
user.setPassword(this.password); // Assuming password is already hashed
|
||||
if (this.roles != null) {
|
||||
user.setRoles(this.roles.stream()
|
||||
.filter(Objects::nonNull)
|
||||
.map(RoleDto::toEntity)
|
||||
.collect(Collectors.toSet()));
|
||||
}
|
||||
return user;
|
||||
}
|
||||
}
|
||||
@@ -2,9 +2,11 @@ package com.jambotronGroup.jambotron;
|
||||
|
||||
|
||||
import com.jambotronGroup.jambotron.fileUpload.FilesStorageService;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.CommandLineRunner;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
@@ -14,6 +16,9 @@ public class JambotronApplication implements CommandLineRunner {
|
||||
@Resource
|
||||
FilesStorageService storageService;
|
||||
|
||||
// @Autowired
|
||||
// UserExportService userExportService;
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(JambotronApplication.class);
|
||||
public static void main(String[] args) {
|
||||
|
||||
@@ -29,6 +34,14 @@ public class JambotronApplication implements CommandLineRunner {
|
||||
public void run(String... arg) throws Exception {
|
||||
// storageService.deleteAll();
|
||||
storageService.init();
|
||||
|
||||
// try {
|
||||
// userExportService.exportAllRolesToJson();
|
||||
// userExportService.exportAllUsersToJson();
|
||||
//
|
||||
// } catch (Exception e) {
|
||||
// logger.error("Error exporting users or roles to JSON", e);
|
||||
// }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,347 @@
|
||||
package com.jambotronGroup.jambotron.controllers;
|
||||
|
||||
import com.jambotronGroup.jambotron.jsonDump.JsonDumpService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.io.FileSystemResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static java.util.stream.Collectors.toList;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/admin/json-dump")
|
||||
@PreAuthorize("hasRole('ADMIN')")
|
||||
public class JsonDumpController {
|
||||
|
||||
private static final Logger _logger = LoggerFactory.getLogger(JsonDumpController.class);
|
||||
|
||||
@Autowired
|
||||
private JsonDumpService _jsonDumpService;
|
||||
|
||||
// ==================== EXPORT ENDPOINTS ====================
|
||||
|
||||
@PostMapping("/export/all")
|
||||
public ResponseEntity<Map<String, Object>> exportAll() {
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
try {
|
||||
_jsonDumpService.exportAllRolesToJson();
|
||||
_jsonDumpService.exportAllUsersToJson();
|
||||
_jsonDumpService.exportAllTutorialsToJson();
|
||||
|
||||
response.put("success", true);
|
||||
response.put("message", "All entities exported successfully");
|
||||
response.put("timestamp", LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
|
||||
|
||||
_logger.info("Manual export of all entities completed successfully");
|
||||
return ResponseEntity.ok(response);
|
||||
|
||||
} catch (Exception e) {
|
||||
_logger.error("Failed to export all entities", e);
|
||||
response.put("success", false);
|
||||
response.put("message", "Export failed: " + e.getMessage());
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping("/export/users")
|
||||
public ResponseEntity<Map<String, Object>> exportUsers() {
|
||||
return performExport(() -> _jsonDumpService.exportAllUsersToJson(), "users");
|
||||
}
|
||||
|
||||
@PostMapping("/export/tutorials")
|
||||
public ResponseEntity<Map<String, Object>> exportTutorials() {
|
||||
return performExport(() -> _jsonDumpService.exportAllTutorialsToJson(), "tutorials");
|
||||
}
|
||||
|
||||
@PostMapping("/export/roles")
|
||||
public ResponseEntity<Map<String, Object>> exportRoles() {
|
||||
return performExport(() -> _jsonDumpService.exportAllRolesToJson(), "roles");
|
||||
}
|
||||
|
||||
// ==================== IMPORT ENDPOINTS ====================
|
||||
|
||||
@PostMapping("/import/users")
|
||||
public ResponseEntity<Map<String, Object>> importUsers() {
|
||||
return performImport(() -> _jsonDumpService.importUsers(), "users");
|
||||
}
|
||||
|
||||
@PostMapping("/import/tutorials")
|
||||
public ResponseEntity<Map<String, Object>> importTutorials() {
|
||||
return performImport(() -> _jsonDumpService.importTutorials(), "tutorials");
|
||||
}
|
||||
|
||||
@PostMapping("/import/roles")
|
||||
public ResponseEntity<Map<String, Object>> importRoles() {
|
||||
return performImport(() -> _jsonDumpService.importRoles(), "roles");
|
||||
}
|
||||
|
||||
@PostMapping("/import/users/file")
|
||||
public ResponseEntity<Map<String, Object>> importUsersFromFile(@RequestParam("file") MultipartFile file) {
|
||||
return importFromFile(file, (path) -> _jsonDumpService.importUsers(path), "users");
|
||||
}
|
||||
|
||||
@PostMapping("/import/tutorials/file")
|
||||
public ResponseEntity<Map<String, Object>> importTutorialsFromFile(@RequestParam("file") MultipartFile file) {
|
||||
return importFromFile(file, (path) -> _jsonDumpService.importTutorials(path), "tutorials");
|
||||
}
|
||||
|
||||
// ==================== ARCHIVE MANAGEMENT ====================
|
||||
|
||||
@PostMapping("/archives/archive-old-files")
|
||||
public ResponseEntity<Map<String, Object>> archiveOldFiles() {
|
||||
return performArchiveOldFiles(() -> _jsonDumpService.archiveOldFiles());
|
||||
}
|
||||
@GetMapping("/archives")
|
||||
public ResponseEntity<Map<String, Object>> getArchivedFiles() {
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
try {
|
||||
List<String> archivedFiles = _jsonDumpService.getArchivedFiles();
|
||||
response.put("success", true);
|
||||
response.put("archives", archivedFiles);
|
||||
response.put("count", archivedFiles.size());
|
||||
|
||||
return ResponseEntity.ok(response);
|
||||
|
||||
} catch (IOException e) {
|
||||
_logger.error("Failed to list archived files", e);
|
||||
response.put("success", false);
|
||||
response.put("message", "Failed to list archives: " + e.getMessage());
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping("/archives/{fileName}/extract")
|
||||
public ResponseEntity<Map<String, Object>> extractArchive(@PathVariable String fileName) {
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
try {
|
||||
|
||||
_jsonDumpService.extractArchivedFile(fileName);
|
||||
|
||||
response.put("success", true);
|
||||
response.put("message", "Archive extracted successfully");
|
||||
response.put("fileName", fileName);
|
||||
//response.put("targetDirectory", targetDir.toAbsolutePath().toString());
|
||||
|
||||
_logger.info("Archive {} extracted successfully", fileName);
|
||||
return ResponseEntity.ok(response);
|
||||
|
||||
} catch (Exception e) {
|
||||
_logger.error("Failed to extract archive: {}", fileName, e);
|
||||
response.put("success", false);
|
||||
response.put("message", "Failed to extract archive: " + e.getMessage());
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping("/archives/{fileName}/download")
|
||||
public ResponseEntity<Resource> downloadArchive(@PathVariable String fileName) {
|
||||
try {
|
||||
|
||||
|
||||
Resource resource = _jsonDumpService.getArchivedFileResource(fileName);
|
||||
|
||||
return ResponseEntity.ok()
|
||||
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + fileName + "\"")
|
||||
.contentType(MediaType.APPLICATION_OCTET_STREAM)
|
||||
.contentLength(Files.size(resource.getFile().toPath()))
|
||||
.body(resource);
|
||||
|
||||
} catch (IOException e) {
|
||||
_logger.error("Failed to download archive: {}", fileName, e);
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== FILE MANAGEMENT ====================
|
||||
|
||||
@GetMapping("/files")
|
||||
public ResponseEntity<Map<String, Object>> listFiles() {
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
try {
|
||||
|
||||
List<Map<String, Object>> files = _jsonDumpService.getJsonDumpInfo();
|
||||
|
||||
response.put("success", true);
|
||||
response.put("files", files);
|
||||
response.put("count", files.size());
|
||||
|
||||
return ResponseEntity.ok(response);
|
||||
|
||||
} catch (IOException e) {
|
||||
_logger.error("Failed to list files", e);
|
||||
response.put("success", false);
|
||||
response.put("message", "Failed to list files: " + e.getMessage());
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping("/files/{fileName}/download")
|
||||
public ResponseEntity<Resource> downloadFile(@PathVariable String fileName) {
|
||||
try {
|
||||
|
||||
Resource resource = _jsonDumpService.getJsonDumpResource(fileName);
|
||||
|
||||
return ResponseEntity.ok()
|
||||
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + fileName + "\"")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.contentLength(Files.size(resource.getFile().toPath()))
|
||||
.body(resource);
|
||||
|
||||
} catch (IOException e) {
|
||||
_logger.error("Failed to download file: {}", fileName, e);
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
|
||||
}
|
||||
}
|
||||
|
||||
@DeleteMapping("/files/{fileName}")
|
||||
public ResponseEntity<Map<String, Object>> deleteFile(@PathVariable String fileName) {
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
try {
|
||||
response = _jsonDumpService.deleteJsonDumpFile(fileName);
|
||||
_logger.info("File {} deleted successfully", fileName);
|
||||
return ResponseEntity.ok(response);
|
||||
|
||||
} catch (IOException e) {
|
||||
_logger.error("Failed to delete file: {}", fileName, e);
|
||||
response.put("success", false);
|
||||
response.put("message", "Failed to delete file: " + e.getMessage());
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== UTILITY METHODS ====================
|
||||
|
||||
private ResponseEntity<Map<String, Object>> performExport(ExportOperation operation, String entityType) {
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
try {
|
||||
operation.execute();
|
||||
response.put("success", true);
|
||||
response.put("message", entityType + " exported successfully");
|
||||
response.put("timestamp", LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
|
||||
|
||||
_logger.info("Manual export of {} completed successfully", entityType);
|
||||
return ResponseEntity.ok(response);
|
||||
|
||||
} catch (Exception e) {
|
||||
_logger.error("Failed to export {}", entityType, e);
|
||||
response.put("success", false);
|
||||
response.put("message", "Export failed: " + e.getMessage());
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
|
||||
}
|
||||
}
|
||||
|
||||
private ResponseEntity<Map<String, Object>> performImport(ImportOperation operation, String entityType) {
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
try {
|
||||
operation.execute();
|
||||
response.put("success", true);
|
||||
response.put("message", entityType + " imported successfully");
|
||||
response.put("timestamp", LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
|
||||
|
||||
_logger.info("Manual import of {} completed successfully", entityType);
|
||||
return ResponseEntity.ok(response);
|
||||
|
||||
} catch (Exception e) {
|
||||
_logger.error("Failed to import {}", entityType, e);
|
||||
response.put("success", false);
|
||||
response.put("message", "Import failed: " + e.getMessage());
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
|
||||
}
|
||||
}
|
||||
|
||||
private ResponseEntity<Map<String, Object>> importFromFile(MultipartFile file, FileImportOperation operation, String entityType) {
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
try {
|
||||
if (file.isEmpty() || !file.getOriginalFilename().endsWith(".json")) {
|
||||
response.put("success", false);
|
||||
response.put("message", "Please upload a valid JSON file");
|
||||
return ResponseEntity.badRequest().body(response);
|
||||
}
|
||||
|
||||
// Save uploaded file temporarily
|
||||
Path tempFile = Files.createTempFile("import_", ".json");
|
||||
file.transferTo(tempFile.toFile());
|
||||
|
||||
try {
|
||||
operation.execute(tempFile);
|
||||
response.put("success", true);
|
||||
response.put("message", entityType + " imported successfully from uploaded file");
|
||||
response.put("fileName", file.getOriginalFilename());
|
||||
response.put("timestamp", LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
|
||||
|
||||
_logger.info("Manual import of {} from file {} completed successfully", entityType, file.getOriginalFilename());
|
||||
return ResponseEntity.ok(response);
|
||||
|
||||
} finally {
|
||||
// Clean up temp file
|
||||
Files.deleteIfExists(tempFile);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
_logger.error("Failed to import {} from file", entityType, e);
|
||||
response.put("success", false);
|
||||
response.put("message", "Import failed: " + e.getMessage());
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
|
||||
}
|
||||
}
|
||||
|
||||
private ResponseEntity<Map<String, Object>> performArchiveOldFiles(ArchiveOperation operation) {
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
try {
|
||||
operation.execute();
|
||||
response.put("success", true);
|
||||
response.put("message", "Archive old files successfully");
|
||||
response.put("timestamp", LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
|
||||
|
||||
_logger.info("Archive old files successfully");
|
||||
return ResponseEntity.ok(response);
|
||||
|
||||
} catch (Exception e) {
|
||||
_logger.error("Failed Archive old files.", e);
|
||||
response.put("success", false);
|
||||
response.put("message", "Failed Archive old files: " + e.getMessage());
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@FunctionalInterface
|
||||
private interface ArchiveOperation {
|
||||
void execute() throws Exception;
|
||||
}
|
||||
|
||||
// Functional interfaces for operations
|
||||
@FunctionalInterface
|
||||
private interface ExportOperation {
|
||||
void execute() throws Exception;
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
private interface ImportOperation {
|
||||
void execute() throws Exception;
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
private interface FileImportOperation {
|
||||
void execute(Path filePath) throws Exception;
|
||||
}
|
||||
}
|
||||
@@ -42,6 +42,7 @@ public class FilesStorageServiceImpl implements FilesStorageService {
|
||||
private final Path root = Paths.get("/jambotron_data/uploads/user-images/");
|
||||
private final Path rootPublic = Paths.get("/jambotron_data/uploads/public-images/");
|
||||
|
||||
// private final Path rootInitData = Pa
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.jambotronGroup.jambotron.initData;
|
||||
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
//@ConditionalOnProperty(name = "app.init.data.enabled", havingValue = "true", matchIfMissing = true)
|
||||
public class InitDataConfiguration {
|
||||
|
||||
@Autowired
|
||||
private InitDataService _initDataService;
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
|
||||
_initDataService.importData();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
package com.jambotronGroup.jambotron.initData;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.jambotronGroup.jambotron.DTOs.RoleDto;
|
||||
import com.jambotronGroup.jambotron.DTOs.UserDto;
|
||||
import com.jambotronGroup.jambotron.model.ERole;
|
||||
import com.jambotronGroup.jambotron.model.Role;
|
||||
import com.jambotronGroup.jambotron.model.User;
|
||||
import com.jambotronGroup.jambotron.repository.RoleRepository;
|
||||
import com.jambotronGroup.jambotron.repository.UserRepository;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
@Primary
|
||||
public class InitDataService {
|
||||
|
||||
private static final Logger _logger = LoggerFactory.getLogger(InitDataService.class);
|
||||
|
||||
private ObjectMapper _mapper;
|
||||
|
||||
@Autowired
|
||||
private ResourceLoader _resources;
|
||||
@Autowired
|
||||
private RoleRepository _roleRepository;
|
||||
|
||||
@Autowired
|
||||
private UserRepository _userRepository;
|
||||
|
||||
public InitDataService(){
|
||||
_mapper = new ObjectMapper();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void importRoles(Path jsonFile) throws Exception {
|
||||
_logger.info("Importing roles from {}", jsonFile.toAbsolutePath());
|
||||
List<RoleDto> items = readList(jsonFile, new TypeReference<List<RoleDto>>() {});
|
||||
for (RoleDto dto : items) {
|
||||
Role roleEntity = dto.toEntity();
|
||||
// If a role with same name exists, reuse its ID to upsert
|
||||
// _roleRepository.findByName(entity.getName())
|
||||
// .ifPresent(existing -> entity.setId(existing.getId()));
|
||||
|
||||
if(!_roleRepository.existsByName(roleEntity.getName())) {
|
||||
_roleRepository.save(roleEntity);
|
||||
_logger.info("Saving new role: {}", roleEntity.getName());
|
||||
} else {
|
||||
_logger.info("Role {} already exists, SKIPPING import", roleEntity.getName());
|
||||
}
|
||||
}
|
||||
_logger.info("Imported {} roles", items.stream()
|
||||
.map(RoleDto::getName).toList()
|
||||
.stream().map(ERole::toString).collect(Collectors.joining(", ")));
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void importUsers(Path jsonFile) throws Exception {
|
||||
_logger.info("Importing users from {}", jsonFile.toAbsolutePath());
|
||||
// Preload roles map by name for quick lookup
|
||||
Map<ERole, Role> rolesByName = _roleRepository.findAll().stream()
|
||||
.collect(Collectors.toMap(Role::getName, r -> r));
|
||||
|
||||
List<UserDto> items = readList(jsonFile, new TypeReference<List<UserDto>>() {});
|
||||
for (UserDto dto : items) {
|
||||
User user = new User();
|
||||
if (dto.getId() != null) user.setId(dto.getId());
|
||||
user.setUsername(dto.getUsername());
|
||||
user.setEmail(dto.getEmail());
|
||||
// Expecting already-hashed values; do not import plain text secrets
|
||||
user.setPassword(dto.getPassword());
|
||||
|
||||
// Resolve roles by enum name
|
||||
Set<Role> roles = new HashSet<>();
|
||||
if (dto.getRoles() != null) {
|
||||
for (RoleDto roleDto : dto.getRoles()) {
|
||||
ERole erole = ERole.valueOf(roleDto.getName().name());
|
||||
Role role = rolesByName.get(erole);
|
||||
if (role == null) {
|
||||
// Optionally create missing roles on the fly
|
||||
role = new Role();
|
||||
role.setName(erole);
|
||||
role = _roleRepository.save(role);
|
||||
rolesByName.put(erole, role);
|
||||
}
|
||||
roles.add(role);
|
||||
}
|
||||
}
|
||||
user.setRoles(roles);
|
||||
|
||||
if(!_userRepository.existsByUsername(user.getUsername())) {
|
||||
_userRepository.save(user);
|
||||
|
||||
_logger.info("Imported user: {} with roles: {}", user.getUsername(), user.getRoles().stream()
|
||||
.map(Role::getName).collect(Collectors.toList()).stream().map(ERole::toString)
|
||||
.collect(Collectors.joining(", ")));
|
||||
} else {
|
||||
_logger.warn("User with username {} already exists, SKIPPING import", user.getUsername());
|
||||
_logger.info("Imported user: {} with roles: {}", user.getUsername(), user.getRoles().stream()
|
||||
.map(Role::getName).collect(Collectors.toList()).stream().map(ERole::toString)
|
||||
.collect(Collectors.joining(", ")));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected <T> List<T> readList(Path file, TypeReference<List<T>> type) throws Exception {
|
||||
String json = Files.readString(file);
|
||||
return _mapper.readValue(json, type);
|
||||
}
|
||||
|
||||
public void importData() {
|
||||
try {
|
||||
Resource resource = _resources.getResource("classpath:import/roles.json");
|
||||
if (resource.exists()) {
|
||||
|
||||
importRoles(resource.getFile().toPath());
|
||||
} else {
|
||||
|
||||
_logger.warn("Roles import file not found: {}", resource.getFilename());
|
||||
}
|
||||
|
||||
resource = _resources.getResource("classpath:import/users.json");
|
||||
if (resource.exists()) {
|
||||
importUsers(resource.getFile().toPath());
|
||||
} else {
|
||||
|
||||
_logger.warn("Users import file not found: {}", resource.getFilename());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
_logger.error("Error importing data", e);
|
||||
throw new RuntimeException("Failed to import data", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,456 @@
|
||||
package com.jambotronGroup.jambotron.jsonDump;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.jambotronGroup.jambotron.DTOs.TutorialDto;
|
||||
import com.jambotronGroup.jambotron.DTOs.UserDto;
|
||||
import com.jambotronGroup.jambotron.controllers.AuthController;
|
||||
import com.jambotronGroup.jambotron.initData.InitDataService;
|
||||
import com.jambotronGroup.jambotron.model.ERole;
|
||||
import com.jambotronGroup.jambotron.model.Role;
|
||||
import com.jambotronGroup.jambotron.model.Tutorial;
|
||||
import com.jambotronGroup.jambotron.model.User;
|
||||
import com.jambotronGroup.jambotron.repository.RoleRepository;
|
||||
import com.jambotronGroup.jambotron.repository.TutorialRepository;
|
||||
import com.jambotronGroup.jambotron.repository.UserRepository;
|
||||
import jakarta.persistence.EntityManager;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.attribute.FileTime;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
@Service
|
||||
public class JsonDumpService extends InitDataService {
|
||||
|
||||
private static final Logger _logger = LoggerFactory.getLogger(JsonDumpService.class);
|
||||
private final Path _root = Paths.get("/jambotron_data/jsonDump/");
|
||||
private final Path _archivePath = _root.resolve("archive");
|
||||
|
||||
private final Path _extractedPath = _root.resolve("extracted");
|
||||
|
||||
private final ObjectMapper _mapper;
|
||||
|
||||
@Autowired
|
||||
private final UserRepository _userRepository;
|
||||
|
||||
@Autowired
|
||||
private final RoleRepository _roleRepository;
|
||||
|
||||
@Autowired
|
||||
private final TutorialRepository _tutorialRepository;
|
||||
|
||||
@Value("${app.json.dump.cleanup.enabled:true}")
|
||||
private boolean _cleanupEnabled;
|
||||
|
||||
@Value("${app.json.dump.cleanup.retention.weeks:4}")
|
||||
private int _retentionWeeks;
|
||||
|
||||
@Value("${app.json.dump.archive.enabled:true}")
|
||||
private boolean _archiveEnabled;
|
||||
|
||||
public JsonDumpService(ObjectMapper mapper, UserRepository userRepository, RoleRepository roleRepository, TutorialRepository tutorialRepository) {
|
||||
_mapper = mapper;
|
||||
_userRepository = userRepository;
|
||||
_roleRepository = roleRepository;
|
||||
_tutorialRepository = tutorialRepository;
|
||||
}
|
||||
|
||||
private static String getFileNameWithTimestamp(String prefix) {
|
||||
String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd_HH-mm-ss"));
|
||||
return String.format("%s_%s.json", prefix, timestamp);
|
||||
}
|
||||
|
||||
private void exportToJson(List<?> entities, String entitiesName) throws Exception {
|
||||
|
||||
// Create filename with timestamp
|
||||
String fileNameWithTimestamp = JsonDumpService.getFileNameWithTimestamp(entitiesName);
|
||||
|
||||
// Ensure export directory exists
|
||||
Files.createDirectories(_root);
|
||||
|
||||
// Write entities to JSON file
|
||||
Path filePath = _root.resolve(fileNameWithTimestamp);
|
||||
_mapper.writerWithDefaultPrettyPrinter().writeValue(filePath.toFile(), entities);
|
||||
|
||||
_logger.info("Exported {} to {}", entitiesName, filePath.toAbsolutePath());
|
||||
}
|
||||
|
||||
public void exportAllTutorialsToJson() throws Exception {
|
||||
List<Tutorial> tutorials = _tutorialRepository.findAll();
|
||||
|
||||
List<TutorialDto> tutorialDtos = tutorials.stream().map(
|
||||
TutorialDto::fromEntity
|
||||
).toList();
|
||||
exportToJson(tutorialDtos, "tutorials");
|
||||
}
|
||||
|
||||
public void exportAllRolesToJson() throws Exception {
|
||||
List<Role> roles = _roleRepository.findAll();
|
||||
|
||||
exportToJson(roles, "roles");
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void exportAllUsersToJson() throws Exception {
|
||||
List<User> users = _userRepository.findAll();
|
||||
|
||||
List<UserDto> userDtos = users.stream().map(
|
||||
user-> UserDto.fromEntity(user)
|
||||
).toList();
|
||||
|
||||
exportToJson(userDtos, "users");
|
||||
}
|
||||
|
||||
private Optional<Path> getLatestJsonFile(String prefix) throws IOException {
|
||||
Optional<Path> latestFile = Files.list(_root)
|
||||
.filter(p -> p.getFileName().toString().matches(prefix + "_.*\\.json"))
|
||||
.max(Comparator.comparing(p -> p.toFile().lastModified()));
|
||||
return latestFile.isPresent() ? latestFile : Optional.empty();
|
||||
}
|
||||
|
||||
public void importRoles() throws Exception {
|
||||
_logger.info("Importing roles from latest JSON file in {}", _root.toAbsolutePath());
|
||||
|
||||
Path jsonFile = getLatestJsonFile("roles").get();
|
||||
|
||||
if (!Files.exists(jsonFile)) {
|
||||
throw new IllegalArgumentException("Roles JSON file not found: " + jsonFile.toAbsolutePath());
|
||||
}
|
||||
importRoles(jsonFile);
|
||||
}
|
||||
|
||||
public void importUsers() throws Exception {
|
||||
_logger.info("Importing users from latest JSON file in {}", _root.toAbsolutePath());
|
||||
|
||||
Path jsonFile = getLatestJsonFile("users").get();
|
||||
|
||||
if (!Files.exists(jsonFile)) {
|
||||
throw new IllegalArgumentException("Users JSON file not found: " + jsonFile.toAbsolutePath());
|
||||
}
|
||||
importUsers(jsonFile);
|
||||
}
|
||||
|
||||
public void importTutorials() throws Exception {
|
||||
_logger.info("Importing tutorials from latest JSON file in {}", _root.toAbsolutePath());
|
||||
|
||||
Path jsonFile = getLatestJsonFile("tutorials").get();
|
||||
|
||||
if (!Files.exists(jsonFile)) {
|
||||
throw new IllegalArgumentException("Tutorials JSON file not found: " + jsonFile.toAbsolutePath());
|
||||
}
|
||||
importTutorials(jsonFile);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void importTutorials(Path jsonFile) throws Exception {
|
||||
Map<Long, User> usersById = _userRepository.findAll().stream()
|
||||
.collect(Collectors.toMap(User::getId, u -> u));
|
||||
List<TutorialDto> items = super.readList(jsonFile, new TypeReference<List<TutorialDto>>() {});
|
||||
|
||||
for (TutorialDto dto : items) {
|
||||
Tutorial t = new Tutorial();
|
||||
t.setId(dto.getId());
|
||||
t.setTitle(dto.getTitle());
|
||||
t.setDescription(dto.getDescription());
|
||||
t.setPublished(dto.getPublished());
|
||||
t.setTobepublished(dto.isTobepublished());
|
||||
t.setCreated(dto.getCreated());
|
||||
t.setModified(dto.getModified());
|
||||
t.setTitleimage(dto.getTitleimage());
|
||||
t.setBody(dto.getBody());
|
||||
|
||||
if (!usersById.containsKey(dto.getUserID())) {
|
||||
_logger.warn(String.format("Missing or unknown userId [%s] for tutorial: [%s]", dto.getUserID(), dto.getTitle()));
|
||||
Optional<User> admin = _userRepository.findAll()
|
||||
.stream().filter(
|
||||
user -> user.getRoles()
|
||||
.stream().anyMatch(
|
||||
role -> role.getName().equals(ERole.ROLE_ADMIN)
|
||||
)
|
||||
).findFirst();
|
||||
if (admin.isPresent()) {
|
||||
_logger.info("Assigning tutorial [%s] to admin user [%s]".formatted(dto.getTitle(), admin.get().getUsername()));
|
||||
t.setUser(admin.get());
|
||||
} else {
|
||||
throw new IllegalArgumentException("Missing user with ROLE_ADMIN to assign tutorial: " + dto.getTitle());
|
||||
}
|
||||
}
|
||||
User user = usersById.get(dto.getUserID());
|
||||
//user = _entityManager.merge(user); // Ensure user is managed by EntityManager
|
||||
//user.setRoles(null); // because we don't want to load roles to user object
|
||||
t.setUser(user);
|
||||
|
||||
if(_tutorialRepository.findByUserIdAndTitle(t.getUser().getId(), t.getTitle()).size()> 0) {
|
||||
_logger.warn("Tutorial with title [{}] already exists for user [{}], SKIPPING import", t.getTitle(), t.getUser().getUsername());
|
||||
continue;
|
||||
}
|
||||
_tutorialRepository.saveAndFlush(t);
|
||||
//_tutorialRepository.save(t);
|
||||
_logger.info("Imported tutorial: {} with user: {}", t.getTitle(), t.getUser().getUsername());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Scheduled(cron = "${app.json.dump.schedule.cron:0 0 2 * * SUN}") // Configurable schedule, default: Sunday 2 AM
|
||||
public void exportEntities() {
|
||||
try {
|
||||
_logger.info("--------------Starting weekly entity export...-------------------");
|
||||
|
||||
exportAllRolesToJson();
|
||||
exportAllUsersToJson();
|
||||
exportAllTutorialsToJson();
|
||||
|
||||
_logger.info("--------------Weekly entity export completed successfully.--------");
|
||||
|
||||
|
||||
// Optional: Clean up old exports (configurable)
|
||||
if (_cleanupEnabled) {
|
||||
if( _archiveEnabled) {
|
||||
archiveOldFiles(_retentionWeeks);
|
||||
} else {
|
||||
cleanupOldFiles();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
_logger.error("Failed to export entities", e);
|
||||
|
||||
}
|
||||
}
|
||||
public void cleanupOldFiles() throws IOException {
|
||||
Path exportDir = _root;
|
||||
if (!Files.exists(exportDir)) return;
|
||||
|
||||
LocalDateTime cutoffDate = LocalDateTime.now().minusWeeks(_retentionWeeks);
|
||||
|
||||
Files.list(exportDir)
|
||||
.filter(path -> path.toString().endsWith(".json"))
|
||||
.filter(path -> {
|
||||
try {
|
||||
FileTime lastModified = Files.getLastModifiedTime(path);
|
||||
return lastModified.toInstant().isBefore(cutoffDate.atZone(ZoneId.systemDefault()).toInstant());
|
||||
} catch (IOException e) {
|
||||
return false;
|
||||
}
|
||||
})
|
||||
.forEach(path -> {
|
||||
try {
|
||||
Files.delete(path);
|
||||
_logger.info("Deleted old export file: {}", path);
|
||||
|
||||
} catch (IOException e) {
|
||||
_logger.warn("Failed to delete old export file: {}", path, e);
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public void archiveOldFiles() throws IOException {
|
||||
this.archiveOldFiles(0);
|
||||
}
|
||||
|
||||
private void archiveOldFiles(int retentionWeeks) throws IOException {
|
||||
Path exportDir = _root;
|
||||
Path archiveDir = _archivePath;
|
||||
|
||||
if (!Files.exists(exportDir)) return;
|
||||
|
||||
// Create archive directory if it doesn't exist
|
||||
Files.createDirectories(archiveDir);
|
||||
|
||||
LocalDateTime cutoffDate = LocalDateTime.now().minusWeeks(retentionWeeks);
|
||||
|
||||
Files.list(exportDir)
|
||||
.filter(path -> path.toString().endsWith(".json"))
|
||||
//.filter(path -> path.getFileName().toString().startsWith("entities_"))
|
||||
.filter(path -> {
|
||||
try {
|
||||
FileTime lastModified = Files.getLastModifiedTime(path);
|
||||
return lastModified.toInstant().isBefore(cutoffDate.atZone(ZoneId.systemDefault()).toInstant());
|
||||
} catch (IOException e) {
|
||||
return false;
|
||||
}
|
||||
})
|
||||
.forEach(path -> {
|
||||
try {
|
||||
// Create compressed archive
|
||||
String fileName = path.getFileName().toString();
|
||||
String zipFileName = fileName.replace(".json", ".zip");
|
||||
Path zipPath = archiveDir.resolve(zipFileName);
|
||||
|
||||
compressFile(path, zipPath);
|
||||
|
||||
// Delete original after successful compression
|
||||
Files.delete(path);
|
||||
_logger.info("Archived and deleted old export file: {} -> {}", path, zipPath);
|
||||
|
||||
|
||||
} catch (IOException e) {
|
||||
_logger.error("Failed to archive export file: {}", path, e);
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void compressFile(Path sourceFile, Path zipFile) throws IOException {
|
||||
try (FileOutputStream fos = new FileOutputStream(zipFile.toFile());
|
||||
ZipOutputStream zos = new ZipOutputStream(fos);
|
||||
FileInputStream fis = new FileInputStream(sourceFile.toFile())) {
|
||||
|
||||
ZipEntry zipEntry = new ZipEntry(sourceFile.getFileName().toString());
|
||||
zos.putNextEntry(zipEntry);
|
||||
|
||||
byte[] buffer = new byte[1024];
|
||||
int length;
|
||||
while ((length = fis.read(buffer)) > 0) {
|
||||
zos.write(buffer, 0, length);
|
||||
}
|
||||
|
||||
zos.closeEntry();
|
||||
}
|
||||
}
|
||||
|
||||
public void extractArchivedFile(String zipFileName) throws IOException {
|
||||
Path targetDir = _extractedPath;
|
||||
extractArchivedFile(zipFileName, targetDir);
|
||||
}
|
||||
|
||||
// Method to extract archived file when needed
|
||||
public void extractArchivedFile(String zipFileName, Path targetDir) throws IOException {
|
||||
Path zipPath = _archivePath.resolve(zipFileName);
|
||||
|
||||
if (!Files.exists(zipPath)) {
|
||||
throw new FileNotFoundException("Archive file not found: " + zipFileName);
|
||||
}
|
||||
|
||||
Files.createDirectories(targetDir);
|
||||
|
||||
try (ZipInputStream zis = new ZipInputStream(new FileInputStream(zipPath.toFile()))) {
|
||||
ZipEntry entry = zis.getNextEntry();
|
||||
|
||||
while (entry != null) {
|
||||
Path filePath = targetDir.resolve(entry.getName());
|
||||
|
||||
try (FileOutputStream fos = new FileOutputStream(filePath.toFile())) {
|
||||
byte[] buffer = new byte[1024];
|
||||
int length;
|
||||
while ((length = zis.read(buffer)) > 0) {
|
||||
fos.write(buffer, 0, length);
|
||||
}
|
||||
}
|
||||
|
||||
entry = zis.getNextEntry();
|
||||
}
|
||||
}
|
||||
|
||||
_logger.info("Extracted archive {} to {}", zipFileName, targetDir.toAbsolutePath());
|
||||
|
||||
}
|
||||
|
||||
public Resource getArchivedFileResource(String zipFileName) throws IOException {
|
||||
Path zipPath = _archivePath.resolve(zipFileName);
|
||||
if (!Files.exists(zipPath)) {
|
||||
throw new FileNotFoundException("Archive file not found: " + zipFileName);
|
||||
}
|
||||
return new org.springframework.core.io.FileSystemResource(zipPath.toFile());
|
||||
}
|
||||
|
||||
public List<Map<String, Object>> getJsonDumpInfo() throws IOException {
|
||||
List<Map<String, Object>> infoList = new ArrayList<>();
|
||||
|
||||
if (!Files.exists(_root)) {
|
||||
Map<String, Object> info = new HashMap<>();
|
||||
info.put("success", true);
|
||||
info.put("files", List.of());
|
||||
info.put("count", 0);
|
||||
infoList.add(info);
|
||||
return infoList;
|
||||
}
|
||||
|
||||
// Get all JSON files in the root directory
|
||||
Files.list(_root)
|
||||
.filter(path -> path.toString().endsWith(".json"))
|
||||
.forEach(path -> {
|
||||
Map<String, Object> info = new HashMap<>();
|
||||
info.put("fileName", path.getFileName().toString());
|
||||
try {
|
||||
info.put("lastModified", Files.getLastModifiedTime(path).toInstant().toString());
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
try {
|
||||
info.put("size", Files.size(path));
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
infoList.add(info);
|
||||
});
|
||||
|
||||
return infoList;
|
||||
}
|
||||
|
||||
public Resource getJsonDumpResource(String fileName) throws IOException {
|
||||
Path filePath = _root.resolve(fileName);
|
||||
if (!Files.exists(filePath)) {
|
||||
throw new FileNotFoundException("JSON dump file not found: " + fileName);
|
||||
}
|
||||
return new org.springframework.core.io.FileSystemResource(filePath.toFile());
|
||||
}
|
||||
|
||||
// Method to list archived files
|
||||
public List<String> getArchivedFiles() throws IOException {
|
||||
Path archiveDir = _archivePath;
|
||||
|
||||
if (!Files.exists(archiveDir)) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
return Files.list(archiveDir)
|
||||
.filter(path -> path.toString().endsWith(".zip"))
|
||||
.map(path -> path.getFileName().toString())
|
||||
.sorted()
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public Map<String, Object> deleteJsonDumpFile(String fileName) throws IOException {
|
||||
Path filePath = _root.resolve(fileName);
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
|
||||
if (!Files.exists(filePath)) {
|
||||
response.put("success", false);
|
||||
response.put("message", "File not found: " + fileName);
|
||||
return response;
|
||||
}
|
||||
|
||||
Files.delete(filePath);
|
||||
response.put("success", true);
|
||||
response.put("message", "File deleted successfully: " + fileName);
|
||||
return response;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.jambotronGroup.jambotron.jsonDump;
|
||||
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class JsonDumpServiceConfiguration {
|
||||
|
||||
@Autowired
|
||||
private JsonDumpService _jsonDumpService;
|
||||
|
||||
@PostConstruct
|
||||
public void onInit(){
|
||||
// This method will be called after the Spring context is initialized
|
||||
// and will trigger the export of users and roles to JSON files.
|
||||
// try{
|
||||
// _jsonDumpService.exportAllRolesToJson();
|
||||
// _jsonDumpService.exportAllUsersToJson();
|
||||
// _jsonDumpService.exportAllTutorialsToJson();
|
||||
// } catch (Exception e) {
|
||||
// // Handle any exceptions that may occur during the export process
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
// try {
|
||||
// _jsonDumpService.importRoles();
|
||||
// _jsonDumpService.importUsers();
|
||||
// _jsonDumpService.importTutorials();
|
||||
// }catch (Exception e) {
|
||||
// // Handle any exceptions that may occur during the import process
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,7 @@ import jakarta.persistence.*;
|
||||
public class Role {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Integer id;
|
||||
private Long id;
|
||||
|
||||
@Enumerated(EnumType.STRING)
|
||||
@Column(length = 20)
|
||||
@@ -23,11 +23,11 @@ public class Role {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Integer getId() {
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ public class Tutorial {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private long id;
|
||||
private Long id;
|
||||
|
||||
@Column(name = "title")
|
||||
private String title;
|
||||
@@ -27,7 +27,7 @@ public class Tutorial {
|
||||
@Column(name = "tobepublished")
|
||||
private boolean tobepublished;
|
||||
|
||||
@ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.PERSIST)
|
||||
@ManyToOne(fetch = FetchType.EAGER)//, cascade = CascadeType.PERSIST)
|
||||
@JoinColumn(name = "userID", nullable = false)
|
||||
private User user;
|
||||
|
||||
@@ -59,10 +59,14 @@ public class Tutorial {
|
||||
this.body = body;
|
||||
}
|
||||
|
||||
public long getId() {
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
@@ -115,6 +119,10 @@ public class Tutorial {
|
||||
return user;
|
||||
}
|
||||
|
||||
public void setUser(User user) {
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Tutorial [id=" + id + ", title=" + title + ", desc=" + description + ", published=" + published + "]";
|
||||
|
||||
@@ -20,7 +20,7 @@ public class User {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(name = "id")
|
||||
private long id;
|
||||
private Long id;
|
||||
|
||||
@Column(name = "username")
|
||||
@NotBlank
|
||||
|
||||
@@ -11,4 +11,7 @@ import java.util.Optional;
|
||||
@Repository
|
||||
public interface RoleRepository extends JpaRepository<Role, Long> {
|
||||
Optional<Role> findByName(ERole name);
|
||||
|
||||
boolean existsByName(ERole name);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.jambotronGroup.jambotron.security;
|
||||
|
||||
import com.jambotronGroup.jambotron.initData.InitDataService;
|
||||
import com.jambotronGroup.jambotron.security.jwt.AuthEntryPointJwt;
|
||||
import com.jambotronGroup.jambotron.security.jwt.AuthTokenFilter;
|
||||
import com.jambotronGroup.jambotron.security.services.UserDetailsServiceImpl;
|
||||
@@ -51,7 +52,6 @@ public class WebSecurityConfig implements WebMvcConfigurer {// extends WebSecuri
|
||||
private AuthEntryPointJwt unauthorizedHandler;
|
||||
|
||||
|
||||
|
||||
@Bean
|
||||
public AuthTokenFilter authenticationJwtTokenFilter() {
|
||||
return new AuthTokenFilter();
|
||||
@@ -121,8 +121,11 @@ public class WebSecurityConfig implements WebMvcConfigurer {// extends WebSecuri
|
||||
// Access permitted for specific roles
|
||||
.requestMatchers("/api/user/**").hasRole("USER")
|
||||
.requestMatchers("/api/moderator/**").hasRole("MODERATOR")
|
||||
.requestMatchers("/api/admin/**").hasRole("ADMIN")
|
||||
|
||||
//.requestMatchers("/api/admin/**").hasRole("ADMIN")
|
||||
.requestMatchers("/api/admin/**").permitAll()
|
||||
.requestMatchers("/api/admin/json-dump/**").permitAll()
|
||||
.requestMatchers("/api/admin/json-dump/import/**").permitAll()
|
||||
.anyRequest().authenticated()
|
||||
|
||||
);
|
||||
|
||||
@@ -16,6 +16,18 @@ spring.flyway.url=jdbc:postgresql://localhost:5433/jambotronDB
|
||||
spring.flyway.user=admin
|
||||
spring.flyway.password=postgrespw
|
||||
|
||||
#spring.datasource.url= jdbc:postgresql://localhost:5433/db_for_import
|
||||
#spring.datasource.username= admin
|
||||
#spring.datasource.password= postgrespw
|
||||
#
|
||||
#spring.flyway.enabled=false
|
||||
##spring.flyway.baseline-on-migrate=true
|
||||
##spring.flyway.validate-on-migrate=true
|
||||
##
|
||||
##spring.flyway.url=jdbc:postgresql://localhost:5433/db_for_import
|
||||
##spring.flyway.user=admin
|
||||
##spring.flyway.password=postgrespw
|
||||
|
||||
#============jpa=====================
|
||||
|
||||
spring.jpa.properties.hibernate.dialect= org.hibernate.dialect.PostgreSQLDialect
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
CREATE TABLE IF NOT EXISTS public.refreshtoken
|
||||
(
|
||||
id bigint NOT NULL GENERATED ALWAYS AS IDENTITY ( INCREMENT 1 START 1 MINVALUE 1 MAXVALUE 9223372036854775807 CACHE 1 ),
|
||||
user_id bigint NOT NULL,
|
||||
token character varying COLLATE pg_catalog."default" NOT NULL,
|
||||
expiry_date timestamp with time zone,
|
||||
CONSTRAINT refreshtoken_pkey PRIMARY KEY (id),
|
||||
CONSTRAINT "FK_refreshtoken_users" FOREIGN KEY (user_id)
|
||||
REFERENCES public.users (id) MATCH SIMPLE
|
||||
ON UPDATE NO ACTION
|
||||
ON DELETE NO ACTION
|
||||
);
|
||||
@@ -1,9 +1,81 @@
|
||||
-- This script was generated by the ERD tool in pgAdmin 4.
|
||||
-- Please log an issue at https://github.com/pgadmin-org/pgadmin4/issues/new/choose if you find any bugs, including reproduction steps.
|
||||
BEGIN;
|
||||
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS roles
|
||||
CREATE TABLE IF NOT EXISTS public.refreshtoken
|
||||
(
|
||||
id INT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
name character varying(20)
|
||||
|
||||
id bigint NOT NULL GENERATED ALWAYS AS IDENTITY ( INCREMENT 1 START 1 MINVALUE 1 MAXVALUE 9223372036854775807 CACHE 1 ),
|
||||
user_id bigint NOT NULL,
|
||||
token character varying COLLATE pg_catalog."default" NOT NULL,
|
||||
expiry_date timestamp with time zone,
|
||||
CONSTRAINT refreshtoken_pkey PRIMARY KEY (id)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS public.roles
|
||||
(
|
||||
id integer NOT NULL GENERATED BY DEFAULT AS IDENTITY ( INCREMENT 1 START 1 MINVALUE 1 MAXVALUE 2147483647 CACHE 1 ),
|
||||
name character varying(20) COLLATE pg_catalog."default",
|
||||
CONSTRAINT roles_pkey PRIMARY KEY (id)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS public.tutorials
|
||||
(
|
||||
id bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY ( INCREMENT 1 START 1 MINVALUE 1 MAXVALUE 9223372036854775807 CACHE 1 ),
|
||||
published boolean,
|
||||
tobepublished boolean,
|
||||
title character varying(255) COLLATE pg_catalog."default",
|
||||
userid bigint,
|
||||
created timestamp with time zone,
|
||||
modified timestamp with time zone,
|
||||
description character varying(255) COLLATE pg_catalog."default",
|
||||
titleimage text COLLATE pg_catalog."default",
|
||||
body text COLLATE pg_catalog."default",
|
||||
CONSTRAINT tutorials_title_key UNIQUE (title)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS public.user_roles
|
||||
(
|
||||
user_id bigint NOT NULL,
|
||||
role_id integer NOT NULL,
|
||||
CONSTRAINT user_roles_pkey PRIMARY KEY (user_id, role_id)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS public.users
|
||||
(
|
||||
id integer NOT NULL GENERATED BY DEFAULT AS IDENTITY ( INCREMENT 1 START 1 MINVALUE 1 MAXVALUE 2147483647 CACHE 1 ),
|
||||
email character varying(50) COLLATE pg_catalog."default",
|
||||
password character varying(120) COLLATE pg_catalog."default",
|
||||
username character varying(20) COLLATE pg_catalog."default",
|
||||
CONSTRAINT users_pkey PRIMARY KEY (id),
|
||||
CONSTRAINT uk6dotkott2kjsp8vw4d0m25fb7 UNIQUE (email),
|
||||
CONSTRAINT ukr43af9ap4edm43mmtq01oddj6 UNIQUE (username)
|
||||
);
|
||||
|
||||
ALTER TABLE IF EXISTS public.refreshtoken
|
||||
ADD CONSTRAINT "FK_refreshtoken_users" FOREIGN KEY (user_id)
|
||||
REFERENCES public.users (id) MATCH SIMPLE
|
||||
ON UPDATE NO ACTION
|
||||
ON DELETE NO ACTION;
|
||||
|
||||
|
||||
ALTER TABLE IF EXISTS public.tutorials
|
||||
ADD CONSTRAINT "tutorial_user_FK" FOREIGN KEY (userid)
|
||||
REFERENCES public.users (id) MATCH SIMPLE
|
||||
ON UPDATE NO ACTION
|
||||
ON DELETE NO ACTION;
|
||||
|
||||
|
||||
ALTER TABLE IF EXISTS public.user_roles
|
||||
ADD CONSTRAINT fkh8ciramu9cc9q3qcqiv4ue8a6 FOREIGN KEY (role_id)
|
||||
REFERENCES public.roles (id) MATCH SIMPLE
|
||||
ON UPDATE NO ACTION
|
||||
ON DELETE NO ACTION;
|
||||
|
||||
|
||||
ALTER TABLE IF EXISTS public.user_roles
|
||||
ADD CONSTRAINT fkhfh9dx7w3ubf1co1vdev94g3f FOREIGN KEY (user_id)
|
||||
REFERENCES public.users (id) MATCH SIMPLE
|
||||
ON UPDATE NO ACTION
|
||||
ON DELETE NO ACTION;
|
||||
|
||||
END;
|
||||
@@ -1,14 +0,0 @@
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS users
|
||||
(
|
||||
id INT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
email character varying(50) COLLATE pg_catalog."default",
|
||||
password character varying(120) COLLATE pg_catalog."default",
|
||||
username character varying(20) COLLATE pg_catalog."default",
|
||||
|
||||
CONSTRAINT uk6dotkott2kjsp8vw4d0m25fb7 UNIQUE (email),
|
||||
CONSTRAINT ukr43af9ap4edm43mmtq01oddj6 UNIQUE (username)
|
||||
);
|
||||
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
|
||||
CREATE TABLE IF NOT EXISTS public.user_roles
|
||||
(
|
||||
user_id bigint NOT NULL,
|
||||
role_id integer NOT NULL,
|
||||
CONSTRAINT user_roles_pkey PRIMARY KEY (user_id, role_id),
|
||||
CONSTRAINT fkh8ciramu9cc9q3qcqiv4ue8a6 FOREIGN KEY (role_id)
|
||||
REFERENCES public.roles (id) MATCH SIMPLE
|
||||
ON UPDATE NO ACTION
|
||||
ON DELETE NO ACTION,
|
||||
CONSTRAINT fkhfh9dx7w3ubf1co1vdev94g3f FOREIGN KEY (user_id)
|
||||
REFERENCES public.users (id) MATCH SIMPLE
|
||||
ON UPDATE NO ACTION
|
||||
ON DELETE NO ACTION
|
||||
);
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS public.tutorials
|
||||
(
|
||||
id bigint NOT NULL,
|
||||
description character varying(255) COLLATE pg_catalog."default",
|
||||
published boolean,
|
||||
title character varying(255) COLLATE pg_catalog."default",
|
||||
CONSTRAINT tutorials_pkey PRIMARY KEY (id)
|
||||
);
|
||||
@@ -1,20 +0,0 @@
|
||||
|
||||
INSERT INTO roles (id, name) OVERRIDING SYSTEM VALUE VALUES (1, 'ROLE_USER');
|
||||
INSERT INTO roles (id, name) OVERRIDING SYSTEM VALUE VALUES (2, 'ROLE_MODERATOR');
|
||||
INSERT INTO roles (id, name) OVERRIDING SYSTEM VALUE VALUES (3, 'ROLE_ADMIN');
|
||||
|
||||
|
||||
INSERT INTO users (id, email, password, username)
|
||||
OVERRIDING SYSTEM VALUE
|
||||
VALUES (1, 'liosha84@gmail.com', '$2a$10$qyoKXYSukha6XCjorTzoweF4Os1pwmwyzbaSsb3RCVB0LK6WLQKPC', 'Admin');
|
||||
INSERT INTO users (id, email, password, username)
|
||||
OVERRIDING SYSTEM VALUE
|
||||
VALUES (2, 'Moderator@gmail.com', '$2a$10$zLo5th8Xbfq.MM7y/dCRQu3Ud7HHyAwm.7.yS08ytJtkHMKrbOJlu', 'Moderator');
|
||||
INSERT INTO users (id, email, password, username)
|
||||
OVERRIDING SYSTEM VALUE
|
||||
VALUES (3, 'user@gmail.com', '$2a$10$2EcwYffteBF3GhVaf5qPB.I7XiHepDEauU5D4fx9fpBXMTZI/QnnC', 'User');
|
||||
|
||||
|
||||
INSERT INTO user_roles (user_id, role_id) OVERRIDING SYSTEM VALUE VALUES (3, 1);
|
||||
INSERT INTO user_roles (user_id, role_id) OVERRIDING SYSTEM VALUE VALUES (1, 3);
|
||||
INSERT INTO user_roles (user_id, role_id) OVERRIDING SYSTEM VALUE VALUES (2, 2);
|
||||
@@ -1,2 +0,0 @@
|
||||
ALTER TABLE IF EXISTS public.tutorials
|
||||
ALTER COLUMN id ADD GENERATED ALWAYS AS IDENTITY;
|
||||
@@ -1,6 +0,0 @@
|
||||
-- Column: public.tutorials.
|
||||
|
||||
ALTER TABLE IF EXISTS public.tutorials DROP COLUMN IF EXISTS id;
|
||||
|
||||
ALTER TABLE IF EXISTS public.tutorials
|
||||
ADD COLUMN id bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY ( INCREMENT 1 START 1 MINVALUE 1 MAXVALUE 9223372036854775807 CACHE 1 );
|
||||
@@ -1,27 +0,0 @@
|
||||
DROP TABLE IF EXISTS public.tutorials;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS public.tutorials
|
||||
(
|
||||
description character varying(255) COLLATE pg_catalog."default",
|
||||
published boolean,
|
||||
title character varying(255) COLLATE pg_catalog."default",
|
||||
id bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY ( INCREMENT 1 START 1 MINVALUE 1 MAXVALUE 9223372036854775807 CACHE 1 ),
|
||||
userid bigint,
|
||||
CONSTRAINT "tutorial_user_FK" FOREIGN KEY (userid)
|
||||
REFERENCES public.users (id) MATCH SIMPLE
|
||||
ON UPDATE NO ACTION
|
||||
ON DELETE NO ACTION
|
||||
NOT VALID
|
||||
)
|
||||
|
||||
TABLESPACE pg_default;
|
||||
|
||||
|
||||
-- Index: fki_tutorial_user_FK
|
||||
|
||||
-- DROP INDEX IF EXISTS public."fki_tutorial_user_FK";
|
||||
|
||||
CREATE INDEX IF NOT EXISTS "fki_tutorial_user_FK"
|
||||
ON public.tutorials USING btree
|
||||
(userid ASC NULLS LAST)
|
||||
TABLESPACE pg_default;
|
||||
@@ -1,19 +0,0 @@
|
||||
DROP TABLE tutorials;
|
||||
|
||||
CREATE TABLE tutorials
|
||||
(
|
||||
id bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY ( INCREMENT 1 START 1 MINVALUE 1 MAXVALUE 9223372036854775807 CACHE 1 ),
|
||||
published boolean,
|
||||
tobepublished boolean,
|
||||
title character varying(255) COLLATE pg_catalog."default",
|
||||
userid bigint,
|
||||
created timestamp with time zone,
|
||||
modified timestamp with time zone,
|
||||
description character varying(255) COLLATE pg_catalog."default",
|
||||
CONSTRAINT tutorials_title_key UNIQUE (title),
|
||||
CONSTRAINT "tutorial_user_FK" FOREIGN KEY (userid)
|
||||
REFERENCES public.users (id) MATCH SIMPLE
|
||||
ON UPDATE NO ACTION
|
||||
ON DELETE NO ACTION
|
||||
)
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
ALTER TABLE IF EXISTS public.tutorials DROP COLUMN IF EXISTS titleimage;
|
||||
|
||||
ALTER TABLE IF EXISTS public.tutorials
|
||||
ADD COLUMN titleimage text COLLATE pg_catalog."default";
|
||||
|
||||
ALTER TABLE IF EXISTS public.tutorials DROP COLUMN IF EXISTS body;
|
||||
|
||||
ALTER TABLE IF EXISTS public.tutorials
|
||||
ADD COLUMN body text COLLATE pg_catalog."default";
|
||||
@@ -0,0 +1,10 @@
|
||||
[ {
|
||||
"id" : 1,
|
||||
"name" : "ROLE_USER"
|
||||
}, {
|
||||
"id" : 2,
|
||||
"name" : "ROLE_MODERATOR"
|
||||
}, {
|
||||
"id" : 3,
|
||||
"name" : "ROLE_ADMIN"
|
||||
} ]
|
||||
@@ -0,0 +1,34 @@
|
||||
[ {
|
||||
"id" : 1,
|
||||
"username" : "Admin",
|
||||
"email" : "liosha84@gmail.com",
|
||||
"password" : "$2a$10$qyoKXYSukha6XCjorTzoweF4Os1pwmwyzbaSsb3RCVB0LK6WLQKPC",
|
||||
"roles" : [ {
|
||||
"id" : 1,
|
||||
"name" : "ROLE_USER"
|
||||
}, {
|
||||
"id" : 2,
|
||||
"name" : "ROLE_MODERATOR"
|
||||
}, {
|
||||
"id" : 3,
|
||||
"name" : "ROLE_ADMIN"
|
||||
} ]
|
||||
}, {
|
||||
"id" : 2,
|
||||
"username" : "Moderator",
|
||||
"email" : "Moderator@gmail.com",
|
||||
"password" : "$2a$10$zLo5th8Xbfq.MM7y/dCRQu3Ud7HHyAwm.7.yS08ytJtkHMKrbOJlu",
|
||||
"roles" : [ {
|
||||
"id" : 2,
|
||||
"name" : "ROLE_MODERATOR"
|
||||
} ]
|
||||
}, {
|
||||
"id" : 3,
|
||||
"username" : "User",
|
||||
"email" : "user@gmail.com",
|
||||
"password" : "$2a$10$2EcwYffteBF3GhVaf5qPB.I7XiHepDEauU5D4fx9fpBXMTZI/QnnC",
|
||||
"roles" : [ {
|
||||
"id" : 1,
|
||||
"name" : "ROLE_USER"
|
||||
} ]
|
||||
} ]
|
||||
Reference in New Issue
Block a user