Add new components for AI and tutorials, update routing, and enhance file upload functionality
This commit is contained in:
@@ -1,11 +1,14 @@
|
||||
package com.jambotronGroup.jambotron;
|
||||
|
||||
|
||||
import com.jambotronGroup.jambotron.fileUpload.FilesStorageService;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.slf4j.Marker;
|
||||
import org.slf4j.event.Level;
|
||||
import org.slf4j.helpers.BasicMarker;
|
||||
import org.springframework.boot.CommandLineRunner;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.context.annotation.Import;
|
||||
@@ -13,7 +16,9 @@ import org.springframework.context.annotation.Import;
|
||||
import java.util.Iterator;
|
||||
|
||||
@SpringBootApplication
|
||||
public class JambotronApplication {
|
||||
public class JambotronApplication implements CommandLineRunner {
|
||||
@Resource
|
||||
FilesStorageService storageService;
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(JambotronApplication.class);
|
||||
public static void main(String[] args) {
|
||||
@@ -25,5 +30,9 @@ public class JambotronApplication {
|
||||
logger.debug("Application Run. This is a debug message.");
|
||||
logger.info("Application Run. This is an info message.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(String... arg) throws Exception {
|
||||
// storageService.deleteAll();
|
||||
storageService.init();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.jambotronGroup.jambotron.ZhiPuAi;
|
||||
|
||||
import com.jambotronGroup.jambotron.controllers.FilesController;
|
||||
import com.jambotronGroup.jambotron.fileUpload.FilesStorageService;
|
||||
import com.jambotronGroup.jambotron.model.NameValueItem;
|
||||
import org.springframework.ai.image.Image;
|
||||
import org.springframework.ai.image.ImagePrompt;
|
||||
@@ -8,8 +10,18 @@ import org.springframework.ai.zhipuai.ZhiPuAiImageModel;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.mock.web.MockMultipartFile;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
|
||||
//@CrossOrigin(origins = "http://localhost:4200, https://pony-sincere-chimp.ngrok-free.app/",
|
||||
@@ -21,6 +33,9 @@ import java.util.List;
|
||||
@RequestMapping("/api/public/zhipuai")
|
||||
public class ImageController {
|
||||
|
||||
@Autowired
|
||||
FilesStorageService storageService;
|
||||
|
||||
@Autowired
|
||||
ZhiPuAiImageService _zhiPuAiImageService;
|
||||
|
||||
@@ -30,7 +45,6 @@ public class ImageController {
|
||||
Image returnValue = _zhiPuAiImageService.generateImage(query).getResult().getOutput();
|
||||
//userRepository.findAll().forEach(users::add);
|
||||
|
||||
|
||||
if (returnValue == null) {
|
||||
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,155 @@
|
||||
package com.jambotronGroup.jambotron.controllers;
|
||||
|
||||
import com.jambotronGroup.jambotron.fileUpload.FilesStorageService;
|
||||
import com.jambotronGroup.jambotron.fileUpload.ResponseMessage;
|
||||
import com.jambotronGroup.jambotron.model.FileInfo;
|
||||
import com.jambotronGroup.jambotron.model.User;
|
||||
import com.jambotronGroup.jambotron.payload.request.SaveZhipuAiImageRequest;
|
||||
import com.jambotronGroup.jambotron.security.AuthenticationFacade;
|
||||
import com.jambotronGroup.jambotron.system.SystemServiceImpl;
|
||||
import jakarta.validation.Valid;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.mock.web.MockMultipartFile;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Controller
|
||||
//@CrossOrigin("http://localhost:8081")
|
||||
public class FilesController {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(FilesController.class);
|
||||
|
||||
|
||||
@Autowired
|
||||
AuthenticationFacade authenticationFacade;
|
||||
@Autowired
|
||||
FilesStorageService storageService;
|
||||
|
||||
@PostMapping("/api/user/saveZhipuAiImage")
|
||||
public ResponseEntity<ResponseMessage> saveZhipuAiImage(@Valid @RequestBody SaveZhipuAiImageRequest request) {
|
||||
|
||||
if (request.getImageUrl() == null || request.getImageUrl().isEmpty()) {
|
||||
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseMessage("URL cannot be empty"));
|
||||
}
|
||||
|
||||
String url = request.getImageUrl();
|
||||
|
||||
String message = "";
|
||||
|
||||
|
||||
RestTemplate restTemplate = new RestTemplate();
|
||||
|
||||
try {
|
||||
// Make a GET request to fetch the image as a byte array
|
||||
ResponseEntity<byte[]> response = restTemplate.getForEntity(url, byte[].class);
|
||||
|
||||
if (response.getStatusCode().is2xxSuccessful() && response.getBody() != null) {
|
||||
// Save the image to a file
|
||||
|
||||
int lastSlashIndex = url.lastIndexOf("/");
|
||||
String fileName = (lastSlashIndex != -1) ? url.substring(lastSlashIndex + 1) : url;
|
||||
|
||||
MultipartFile multipartFile = new MockMultipartFile(
|
||||
fileName, // Name of the file
|
||||
fileName, // Original filename
|
||||
"application/octet-stream", // Content type
|
||||
response.getBody() // File content
|
||||
);
|
||||
|
||||
User user = authenticationFacade.getUser();
|
||||
|
||||
storageService.save(user.getId().toString(), multipartFile);
|
||||
|
||||
message = "Uploaded the file successfully: " + fileName;
|
||||
|
||||
} else {
|
||||
|
||||
message = "Failed to download image. HTTP Status: " + response.getStatusCode();
|
||||
System.err.println(message);
|
||||
return ResponseEntity.status(HttpStatus.EXPECTATION_FAILED).body(new ResponseMessage(message));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
message = "Error fetching the image from URL: " + url + ". Error: " + e.getMessage();
|
||||
System.err.println(message);
|
||||
return ResponseEntity.status(HttpStatus.EXPECTATION_FAILED).body(new ResponseMessage(message));
|
||||
}
|
||||
return ResponseEntity.status(HttpStatus.OK).body(new ResponseMessage(message));
|
||||
}
|
||||
|
||||
@PostMapping("/api/file/upload")
|
||||
public ResponseEntity<ResponseMessage> uploadFile(@RequestParam("file") MultipartFile file) {
|
||||
String message = "";
|
||||
try {
|
||||
storageService.save(file);
|
||||
|
||||
message = "Uploaded the file successfully: " + file.getOriginalFilename();
|
||||
return ResponseEntity.status(HttpStatus.OK).body(new ResponseMessage(message));
|
||||
} catch (Exception e) {
|
||||
message = "Could not upload the file: " + file.getOriginalFilename() + ". Error: " + e.getMessage();
|
||||
return ResponseEntity.status(HttpStatus.EXPECTATION_FAILED).body(new ResponseMessage(message));
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping("/api/user/getImages")
|
||||
public ResponseEntity<List<FileInfo>> getImages() {
|
||||
|
||||
User user = authenticationFacade.getUser();
|
||||
|
||||
List<FileInfo> fileInfos = storageService.loadUserImages(user.getId().toString()).map(path -> {
|
||||
String filename = path.getFileName().toString();
|
||||
String url = MvcUriComponentsBuilder
|
||||
.fromMethodName(FilesController.class, "getUserImage", path.getFileName().toString()).build().toString();
|
||||
|
||||
return new FileInfo(filename, url);
|
||||
}).collect(Collectors.toList());
|
||||
|
||||
return ResponseEntity.status(HttpStatus.OK).body(fileInfos);
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("/api/file/files")
|
||||
public ResponseEntity<List<FileInfo>> getListFiles() {
|
||||
List<FileInfo> fileInfos = storageService.loadAll().map(path -> {
|
||||
String filename = path.getFileName().toString();
|
||||
String url = MvcUriComponentsBuilder
|
||||
.fromMethodName(FilesController.class, "getFile", path.getFileName().toString()).build().toString();
|
||||
|
||||
return new FileInfo(filename, url);
|
||||
}).collect(Collectors.toList());
|
||||
|
||||
return ResponseEntity.status(HttpStatus.OK).body(fileInfos);
|
||||
}
|
||||
|
||||
@GetMapping("/files/{filename:.+}")
|
||||
@ResponseBody
|
||||
public ResponseEntity<Resource> getFile(@PathVariable String filename) {
|
||||
Resource file = storageService.load(filename);
|
||||
return ResponseEntity.ok()
|
||||
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + file.getFilename() + "\"").body(file);
|
||||
}
|
||||
|
||||
@GetMapping("/api/user/user-images/{filename:.+}")
|
||||
@ResponseBody
|
||||
public ResponseEntity<Resource> getUserImage(@PathVariable String filename) {
|
||||
User user = authenticationFacade.getUser();
|
||||
Resource file = storageService.loadUserImage(user.getId().toString(),filename);
|
||||
return ResponseEntity.ok()
|
||||
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + file.getFilename() + "\"").body(file);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
package com.jambotronGroup.jambotron.controllers;
|
||||
|
||||
|
||||
import com.jambotronGroup.jambotron.fileUpload.FilesStorageService;
|
||||
import com.jambotronGroup.jambotron.fileUpload.FilesStorageServiceImpl;
|
||||
import com.jambotronGroup.jambotron.model.Tutorial;
|
||||
import com.jambotronGroup.jambotron.model.User;
|
||||
import com.jambotronGroup.jambotron.repository.TutorialRepository;
|
||||
@@ -14,7 +16,9 @@ import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.sql.Timestamp;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
@@ -33,6 +37,44 @@ public class TutorialController {
|
||||
@Autowired
|
||||
TutorialRepository tutorialRepository;
|
||||
|
||||
@Autowired
|
||||
FilesStorageService filesStorageService;
|
||||
|
||||
//--------------------public methods----------------------------
|
||||
|
||||
@GetMapping("/public/tutorials")
|
||||
public ResponseEntity<List<Tutorial>> getAllTutorials(@RequestParam(required = false) String title) {
|
||||
try {
|
||||
List<Tutorial> tutorials = new ArrayList<Tutorial>();
|
||||
|
||||
tutorialRepository.findByPublished(true).forEach(tutorials::add);
|
||||
|
||||
if (tutorials.isEmpty()) {
|
||||
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
|
||||
}
|
||||
|
||||
return new ResponseEntity<>(tutorials, HttpStatus.OK);
|
||||
} catch (Exception e) {
|
||||
return new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping("public/tutorial-get/{id}")
|
||||
public ResponseEntity<Tutorial> getPublicTutorial(@PathVariable("id") long id) {
|
||||
|
||||
Optional<Tutorial> tutorialData = tutorialRepository.findById(id);
|
||||
|
||||
if (tutorialData.isPresent() && tutorialData.get().isPublished()) {
|
||||
|
||||
return new ResponseEntity<Tutorial>(tutorialData.get(), HttpStatus.OK);
|
||||
} else {
|
||||
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------user methods----------------------------
|
||||
|
||||
@GetMapping("/user/tutorials")
|
||||
public ResponseEntity<List<Tutorial>> getUserTutorials(@RequestParam(required = false) String title) {
|
||||
try {
|
||||
@@ -60,49 +102,26 @@ public class TutorialController {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("/public/tutorials")
|
||||
public ResponseEntity<List<Tutorial>> getAllTutorials(@RequestParam(required = false) String title) {
|
||||
try {
|
||||
List<Tutorial> tutorials = new ArrayList<Tutorial>();
|
||||
|
||||
tutorialRepository.findByPublished(true).forEach(tutorials::add);
|
||||
|
||||
if (tutorials.isEmpty()) {
|
||||
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
|
||||
}
|
||||
|
||||
return new ResponseEntity<>(tutorials, HttpStatus.OK);
|
||||
} catch (Exception e) {
|
||||
return new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping("/moderator/tutorials")
|
||||
public ResponseEntity<List<Tutorial>> getBePublishedTutorials(@RequestParam(required = false) String title) {
|
||||
try {
|
||||
List<Tutorial> tutorials = new ArrayList<Tutorial>();
|
||||
|
||||
tutorialRepository.findBytobepublished(true).forEach(tutorials::add);
|
||||
|
||||
if (tutorials.isEmpty()) {
|
||||
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
|
||||
}
|
||||
|
||||
return new ResponseEntity<>(tutorials, HttpStatus.OK);
|
||||
} catch (Exception e) {
|
||||
return new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping("user/tutorial-add")
|
||||
public ResponseEntity<Tutorial> createTutorial(@RequestBody Tutorial tutorial) {
|
||||
@PostMapping("user/tutorial-add")
|
||||
public ResponseEntity<Tutorial> createTutorial(@RequestBody Tutorial tutorial) throws Exception {
|
||||
|
||||
// not work from white IP port 80 to docker container port 8080 or 8081
|
||||
//UserDetails userDetails = authenticationFacade.getUserDetails();
|
||||
|
||||
User user = authenticationFacade.getUser();
|
||||
|
||||
|
||||
String newFilename = FilesStorageServiceImpl.getFileNameFromUrl(tutorial.getTitleimage());
|
||||
Path path= filesStorageService.moveFile(
|
||||
user.getId().toString(),
|
||||
tutorial.getTitleimage(),
|
||||
String.format("Tutorial_%s",newFilename )
|
||||
);
|
||||
|
||||
String url = MvcUriComponentsBuilder
|
||||
.fromMethodName(FilesController.class, "getFile", path.getFileName().toString()).build().toString();
|
||||
|
||||
|
||||
try {
|
||||
Tutorial newTutorial =new Tutorial(
|
||||
tutorial.getTitle(),
|
||||
@@ -111,11 +130,13 @@ public class TutorialController {
|
||||
false,
|
||||
user,
|
||||
Timestamp.valueOf(LocalDateTime.now()),
|
||||
Timestamp.valueOf(LocalDateTime.now())
|
||||
Timestamp.valueOf(LocalDateTime.now()),
|
||||
url,
|
||||
tutorial.getBody()
|
||||
);
|
||||
|
||||
Tutorial _tutorial = tutorialRepository
|
||||
.save(newTutorial);
|
||||
.save(newTutorial);
|
||||
return new ResponseEntity<>(_tutorial, HttpStatus.CREATED);
|
||||
} catch (Exception e) {
|
||||
return new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
@@ -124,21 +145,13 @@ public class TutorialController {
|
||||
|
||||
@GetMapping("user/tutorial-get/{id}")
|
||||
public ResponseEntity<Tutorial> getTutorial(@PathVariable("id") long id) {
|
||||
|
||||
User user = userRepository.findById(authenticationFacade.getUserDetails().getId()).get();
|
||||
|
||||
Optional<Tutorial> tutorialData = tutorialRepository.findById(id);
|
||||
|
||||
if (tutorialData.isPresent()) {
|
||||
|
||||
return new ResponseEntity<Tutorial>(tutorialData.get(), HttpStatus.OK);
|
||||
} else {
|
||||
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping("moderator/tutorial-get/{id}")
|
||||
public ResponseEntity<Tutorial> getBePublishedTutorial(@PathVariable("id") long id) {
|
||||
Optional<Tutorial> tutorialData = tutorialRepository.findById(id);
|
||||
|
||||
if (tutorialData.isPresent()) {
|
||||
if (tutorialData.isPresent() && tutorialData.get().getUser().getId() == user.getId()) {
|
||||
|
||||
return new ResponseEntity<Tutorial>(tutorialData.get(), HttpStatus.OK);
|
||||
} else {
|
||||
@@ -170,30 +183,6 @@ public class TutorialController {
|
||||
}
|
||||
}
|
||||
|
||||
@PutMapping("moderator/tutorial-update/{id}")
|
||||
public ResponseEntity<?> moderatorUpdateTutorial(@PathVariable("id") long id, @RequestBody Tutorial tutorial) {
|
||||
Optional<Tutorial> tutorialData = tutorialRepository.findById(id);
|
||||
Map<String, Object> map = new LinkedHashMap<String, Object>();
|
||||
if (tutorialData.isPresent()) {
|
||||
Tutorial servTutorial = tutorialData.get();
|
||||
servTutorial.setTitle(tutorial.getTitle());
|
||||
servTutorial.setDescription(tutorial.getDescription());
|
||||
servTutorial.setPublished(tutorial.isPublished());
|
||||
servTutorial.setTobepublished(tutorial.isTobepublished());
|
||||
try {
|
||||
servTutorial = tutorialRepository.save(servTutorial);
|
||||
} catch (Exception e) {
|
||||
|
||||
map.put("status", 0);
|
||||
map.put("message", e.getMessage());
|
||||
return new ResponseEntity<>(map,HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
return new ResponseEntity<>(servTutorial, HttpStatus.OK);
|
||||
} else {
|
||||
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
@DeleteMapping("user/tutorials/{id}")
|
||||
public ResponseEntity<HttpStatus> deleteTutorial(@PathVariable("id") long id) {
|
||||
try {
|
||||
@@ -204,6 +193,64 @@ public class TutorialController {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------moderator methods----------------------------
|
||||
|
||||
@GetMapping("/moderator/tutorials")
|
||||
public ResponseEntity<List<Tutorial>> getBePublishedTutorials(@RequestParam(required = false) String title) {
|
||||
try {
|
||||
List<Tutorial> tutorials = new ArrayList<Tutorial>();
|
||||
|
||||
tutorialRepository.findBytobepublished(true).forEach(tutorials::add);
|
||||
|
||||
if (tutorials.isEmpty()) {
|
||||
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
|
||||
}
|
||||
|
||||
return new ResponseEntity<>(tutorials, HttpStatus.OK);
|
||||
} catch (Exception e) {
|
||||
return new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping("moderator/tutorial-get/{id}")
|
||||
public ResponseEntity<Tutorial> getBePublishedTutorial(@PathVariable("id") long id) {
|
||||
Optional<Tutorial> tutorialData = tutorialRepository.findById(id);
|
||||
|
||||
if (tutorialData.isPresent()) {
|
||||
|
||||
return new ResponseEntity<Tutorial>(tutorialData.get(), HttpStatus.OK);
|
||||
} else {
|
||||
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
@PutMapping("moderator/tutorial-update/{id}")
|
||||
public ResponseEntity<?> moderatorUpdateTutorial(@PathVariable("id") long id, @RequestBody Tutorial tutorial) {
|
||||
Optional<Tutorial> tutorialData = tutorialRepository.findById(id);
|
||||
Map<String, Object> map = new LinkedHashMap<String, Object>();
|
||||
if (tutorialData.isPresent()) {
|
||||
Tutorial servTutorial = tutorialData.get();
|
||||
servTutorial.setTitle(tutorial.getTitle());
|
||||
servTutorial.setDescription(tutorial.getDescription());
|
||||
servTutorial.setPublished(tutorial.isPublished());
|
||||
servTutorial.setTobepublished(tutorial.isTobepublished());
|
||||
try {
|
||||
servTutorial = tutorialRepository.save(servTutorial);
|
||||
} catch (Exception e) {
|
||||
|
||||
map.put("status", 0);
|
||||
map.put("message", e.getMessage());
|
||||
return new ResponseEntity<>(map,HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
return new ResponseEntity<>(servTutorial, HttpStatus.OK);
|
||||
} else {
|
||||
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@DeleteMapping("/tutorials")
|
||||
public ResponseEntity<HttpStatus> deleteAllTutorials() {
|
||||
try {
|
||||
@@ -228,5 +275,6 @@ public class TutorialController {
|
||||
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.jambotronGroup.jambotron.fileUpload;
|
||||
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.multipart.MaxUploadSizeExceededException;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
|
||||
|
||||
@ControllerAdvice
|
||||
public class FileUploadExceptionAdvice extends ResponseEntityExceptionHandler {
|
||||
|
||||
|
||||
// @ExceptionHandler(MaxUploadSizeExceededException.class)
|
||||
// public ResponseEntity<ResponseMessage> handleMaxSizeException(MaxUploadSizeExceededException exc) {
|
||||
// return ResponseEntity.status(HttpStatus.EXPECTATION_FAILED).body(new ResponseMessage("File too large!"));
|
||||
// }
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.jambotronGroup.jambotron.fileUpload;
|
||||
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Path;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public interface FilesStorageService {
|
||||
public void init();
|
||||
|
||||
public void save(String userID,MultipartFile file);
|
||||
|
||||
public void save(MultipartFile file);
|
||||
|
||||
public Resource load(String filename);
|
||||
|
||||
public Resource loadUserImage(String userID, String filename);
|
||||
|
||||
public void deleteAll();
|
||||
|
||||
public Stream<Path> loadAll();
|
||||
|
||||
public Stream<Path> loadUserImages(String userID);
|
||||
|
||||
public Path moveFile(String userID, String url, String newFilename) throws Exception;
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
package com.jambotronGroup.jambotron.fileUpload;
|
||||
|
||||
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.UrlResource;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.FileSystemUtils;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.nio.file.FileAlreadyExistsException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@Service
|
||||
public class FilesStorageServiceImpl implements FilesStorageService {
|
||||
|
||||
private final Path root = Paths.get("uploads/user-images/");
|
||||
|
||||
private final Path rootPublic = Paths.get("uploads/public-images/");
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
try {
|
||||
Files.createDirectories(root);
|
||||
Files.createDirectories(rootPublic);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Could not initialize folder for upload!");
|
||||
}
|
||||
}
|
||||
|
||||
public static String getFileNameFromUrl(String urlString) throws Exception {
|
||||
URL url = new URL(urlString); // Create a URL object
|
||||
String path = url.getPath(); // Get the path from the URL
|
||||
return path.substring(path.lastIndexOf('/') + 1); // Extract the file name
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path moveFile(String userID, String url, String newFilename) throws Exception {
|
||||
|
||||
String filename = FilesStorageServiceImpl.getFileNameFromUrl(url);
|
||||
|
||||
try {
|
||||
Path sourcePath = this.root.resolve(userID).resolve(filename);
|
||||
Path targetPath = this.rootPublic.resolve(newFilename);
|
||||
Files.copy(sourcePath, targetPath, java.nio.file.StandardCopyOption.REPLACE_EXISTING);
|
||||
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Could not move the file: " + e.getMessage());
|
||||
}
|
||||
|
||||
return this.rootPublic.resolve(newFilename);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(String userID,MultipartFile file) {
|
||||
try {
|
||||
Path path = this.root.resolve(userID);
|
||||
path.toFile().mkdirs(); // Ensure user directory exists
|
||||
|
||||
Files.copy(file.getInputStream(), path.resolve(file.getOriginalFilename()),
|
||||
java.nio.file.StandardCopyOption.REPLACE_EXISTING);
|
||||
} catch (Exception e) {
|
||||
if (e instanceof FileAlreadyExistsException) {
|
||||
throw new RuntimeException("A file of that name already exists.");
|
||||
}
|
||||
|
||||
throw new RuntimeException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(MultipartFile file) {
|
||||
try {
|
||||
Files.copy(file.getInputStream(), this.root.resolve(file.getOriginalFilename()),
|
||||
java.nio.file.StandardCopyOption.REPLACE_EXISTING);
|
||||
} catch (Exception e) {
|
||||
if (e instanceof FileAlreadyExistsException) {
|
||||
throw new RuntimeException("A file of that name already exists.");
|
||||
}
|
||||
|
||||
throw new RuntimeException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Resource load(String filename) {
|
||||
try {
|
||||
Path file = rootPublic.resolve(filename);
|
||||
Resource resource = new UrlResource(file.toUri());
|
||||
|
||||
if (resource.exists() || resource.isReadable()) {
|
||||
return resource;
|
||||
} else {
|
||||
throw new RuntimeException("Could not read the file!");
|
||||
}
|
||||
} catch (MalformedURLException e) {
|
||||
throw new RuntimeException("Error: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Resource loadUserImage(String userID,String filename) {
|
||||
try {
|
||||
Path file = root.resolve(filename);
|
||||
Path userPath = this.root.resolve(userID);
|
||||
file = userPath.resolve(filename);
|
||||
Resource resource = new UrlResource(file.toUri());
|
||||
|
||||
if (resource.exists() || resource.isReadable()) {
|
||||
return resource;
|
||||
} else {
|
||||
throw new RuntimeException("Could not read the file!");
|
||||
}
|
||||
} catch (MalformedURLException e) {
|
||||
throw new RuntimeException("Error: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteAll() {
|
||||
FileSystemUtils.deleteRecursively(root.toFile());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<Path> loadAll() {
|
||||
try {
|
||||
return Files.walk(this.root, 1).filter(path -> !path.equals(this.root)).map(this.root::relativize);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Could not load the files!");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<Path> loadUserImages(String userID) {
|
||||
Path userPath = this.root.resolve(userID);
|
||||
userPath.toFile().mkdirs();
|
||||
try {
|
||||
return Files.walk(userPath, 1).filter(path -> !path.equals(userPath)).map(userPath::relativize);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Could not load the files!");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.jambotronGroup.jambotron.fileUpload;
|
||||
|
||||
public class ResponseMessage {
|
||||
private String message;
|
||||
|
||||
public ResponseMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -20,6 +20,10 @@ public class Bean {
|
||||
private String typeShortName;
|
||||
private String scope;
|
||||
|
||||
public Bean() {
|
||||
// Default constructor
|
||||
}
|
||||
|
||||
public Bean(String name, String type, String scope) {
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
|
||||
@@ -23,7 +23,9 @@ public class DataBaseSettings {
|
||||
private String password;
|
||||
|
||||
|
||||
|
||||
public DataBaseSettings() {
|
||||
// Default constructor
|
||||
}
|
||||
|
||||
public DataBaseSettings(String name) {
|
||||
this.name = name;
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.jambotronGroup.jambotron.model;
|
||||
|
||||
public class FileInfo {
|
||||
private String name;
|
||||
private String url;
|
||||
|
||||
public FileInfo(String name, String url) {
|
||||
this.name = name;
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return this.url;
|
||||
}
|
||||
|
||||
public void setUrl(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,10 @@ import jakarta.persistence.Id;
|
||||
@Entity
|
||||
public class NameValueItem {
|
||||
|
||||
public NameValueItem() {
|
||||
// Default constructor
|
||||
}
|
||||
|
||||
public NameValueItem(String name, String value){
|
||||
_name = name;
|
||||
_value = value;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.jambotronGroup.jambotron.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import jakarta.persistence.*;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
@@ -7,6 +8,7 @@ import java.sql.Timestamp;
|
||||
|
||||
@Entity
|
||||
@Table(name = "tutorials")
|
||||
@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
|
||||
public class Tutorial {
|
||||
|
||||
@Id
|
||||
@@ -25,7 +27,7 @@ public class Tutorial {
|
||||
@Column(name = "tobepublished")
|
||||
private boolean tobepublished;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY, optional = false)
|
||||
@ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
|
||||
@JoinColumn(name = "userID", nullable = false)
|
||||
private User user;
|
||||
|
||||
@@ -35,13 +37,17 @@ public class Tutorial {
|
||||
@Column(name = "modified")
|
||||
private java.sql.Timestamp modified;
|
||||
|
||||
@Column(name = "titleimage")
|
||||
private String titleimage;
|
||||
|
||||
@Column(name = "body")
|
||||
private String body;
|
||||
|
||||
public Tutorial() {
|
||||
|
||||
}
|
||||
|
||||
public Tutorial(String title, String description, boolean published, boolean tobepublished, User user, Timestamp created, Timestamp modified) {
|
||||
public Tutorial(String title, String description, boolean published, boolean tobepublished, User user, Timestamp created, Timestamp modified, String titleimage, String body) {
|
||||
this.title = title;
|
||||
this.description = description;
|
||||
this.published = published;
|
||||
@@ -49,6 +55,8 @@ public class Tutorial {
|
||||
this.user = user;
|
||||
this.created = created;
|
||||
this.modified = modified;
|
||||
this.titleimage = titleimage;
|
||||
this.body = body;
|
||||
}
|
||||
|
||||
public long getId() {
|
||||
@@ -103,8 +111,28 @@ public class Tutorial {
|
||||
return modified;
|
||||
}
|
||||
|
||||
public User getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Tutorial [id=" + id + ", title=" + title + ", desc=" + description + ", published=" + published + "]";
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
package com.jambotronGroup.jambotron.payload.request;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
|
||||
public class SaveZhipuAiImageRequest {
|
||||
@NotBlank
|
||||
private String imageUrl;
|
||||
|
||||
public String getImageUrl() {
|
||||
return imageUrl;
|
||||
}
|
||||
|
||||
public void setImageUrl(String imageUrl) {
|
||||
this.imageUrl = imageUrl;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -41,7 +41,6 @@ public class AuthenticationFacade implements IAuthenticationFacade {
|
||||
}
|
||||
if (!(authentication.getPrincipal() instanceof UserDetails)) {
|
||||
|
||||
|
||||
throw new IllegalStateException("Authentication principal is not an instance of UserDetails");
|
||||
}
|
||||
UserDetails userDetails = (UserDetails) authentication.getPrincipal();
|
||||
@@ -53,21 +52,8 @@ public class AuthenticationFacade implements IAuthenticationFacade {
|
||||
|
||||
@Override
|
||||
public com.jambotronGroup.jambotron.model.User getUser() {
|
||||
User returnValue = null;
|
||||
|
||||
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||
if (!(authentication.getPrincipal() instanceof UserDetails)) {
|
||||
logger.info("Authentication principal is not an instance of UserDetails, returning null");
|
||||
logger.info(authentication.toString());
|
||||
|
||||
Optional<User> user = userRepository.findByUsername(authentication.getPrincipal().toString());
|
||||
|
||||
returnValue = user.get();
|
||||
}else{
|
||||
UserDetails userDetails = (UserDetails) authentication.getPrincipal();
|
||||
UserDetailsImpl userDetailsImpl = (UserDetailsImpl) userDetails;
|
||||
returnValue = userRepository.findById(userDetailsImpl.getId()).get();
|
||||
}
|
||||
User returnValue = userRepository.findById(this.getUserDetails().getId()).get();
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
@@ -23,8 +23,12 @@ import org.springframework.web.cors.CorsConfiguration;
|
||||
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
|
||||
import org.springframework.web.filter.CorsFilter;
|
||||
import org.springframework.web.servlet.config.annotation.CorsRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import static org.springframework.security.config.Customizer.withDefaults;
|
||||
|
||||
@Configuration
|
||||
@@ -46,6 +50,8 @@ public class WebSecurityConfig implements WebMvcConfigurer {// extends WebSecuri
|
||||
@Autowired
|
||||
private AuthEntryPointJwt unauthorizedHandler;
|
||||
|
||||
|
||||
|
||||
@Bean
|
||||
public AuthTokenFilter authenticationJwtTokenFilter() {
|
||||
return new AuthTokenFilter();
|
||||
@@ -96,9 +102,14 @@ public class WebSecurityConfig implements WebMvcConfigurer {// extends WebSecuri
|
||||
.requestMatchers("/*").permitAll()
|
||||
.requestMatchers("/resources/**").permitAll()
|
||||
|
||||
.requestMatchers("/tutorials-images/**").permitAll()
|
||||
|
||||
.requestMatchers("/files/**").permitAll()
|
||||
|
||||
.requestMatchers("/api/auth/**").permitAll()
|
||||
// Allow public access to tutorials (without login)
|
||||
.requestMatchers("/api/public/tutorials").permitAll()
|
||||
.requestMatchers("/api/public/**").permitAll()
|
||||
//.requestMatchers("/api/public/tutorials").permitAll()
|
||||
//.requestMatchers("/api/public/tutorials/**").permitAll()
|
||||
//TODO: need check the puth
|
||||
.requestMatchers("/api/public/zhipuai/image/**").permitAll()
|
||||
@@ -111,47 +122,8 @@ public class WebSecurityConfig implements WebMvcConfigurer {// extends WebSecuri
|
||||
|
||||
.anyRequest().authenticated()
|
||||
|
||||
|
||||
/* // Allow access to specific API endpoints without authentication
|
||||
.requestMatchers("/api/auth/**").permitAll()
|
||||
|
||||
// Allow access to specific resources
|
||||
|
||||
.requestMatchers("/*", "/home", "/resources/**").permitAll()
|
||||
.requestMatchers("/resources/public/media/**").permitAll()
|
||||
.requestMatchers("/resources/public/browser/**").permitAll()
|
||||
.requestMatchers("/media/**").permitAll()
|
||||
|
||||
.requestMatchers("/main/**").permitAll()
|
||||
.requestMatchers("/api/test/**").permitAll()
|
||||
|
||||
.requestMatchers("/api/tutorials").permitAll()
|
||||
|
||||
|
||||
|
||||
.requestMatchers("/api/users").permitAll()
|
||||
.requestMatchers("/api/users/**").permitAll()
|
||||
|
||||
.requestMatchers("/api/roles").permitAll()
|
||||
.requestMatchers("/api/roles/**").permitAll()
|
||||
|
||||
.requestMatchers("/api/tutorials/**").permitAll()
|
||||
|
||||
.requestMatchers("/api/settings").permitAll()
|
||||
.requestMatchers("/api/system/**").permitAll()
|
||||
*/
|
||||
|
||||
|
||||
);
|
||||
|
||||
/* if(_environment.getProperty("app.cors_enabled") != null &&
|
||||
_environment.getProperty("app.cors_enabled").equalsIgnoreCase("true")) {
|
||||
http.cors(withDefaults());
|
||||
} else {
|
||||
http.cors(cors -> cors.disable());
|
||||
}*/
|
||||
|
||||
|
||||
if(_environment.getProperty("server.port") != null &&
|
||||
_environment.getProperty("server.port").equalsIgnoreCase("443")) {
|
||||
http.redirectToHttps(withDefaults());
|
||||
@@ -164,18 +136,20 @@ public class WebSecurityConfig implements WebMvcConfigurer {// extends WebSecuri
|
||||
return http.build();
|
||||
}
|
||||
|
||||
/* @Bean
|
||||
public CorsFilter corsFilter() {
|
||||
CorsConfiguration corsConfiguration = new CorsConfiguration();
|
||||
corsConfiguration.setAllowCredentials(true); // Allow credentials
|
||||
corsConfiguration.addAllowedOrigin("http://localhost:4200/");
|
||||
corsConfiguration.addAllowedHeader("*"); // Allow all headers
|
||||
@Override
|
||||
public void addResourceHandlers(ResourceHandlerRegistry registry) {
|
||||
exposeDirectory("tutorials-images", registry);
|
||||
}
|
||||
|
||||
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
|
||||
source.registerCorsConfiguration("/**", corsConfiguration); // Apply to all endpoints
|
||||
private void exposeDirectory(String dirName, ResourceHandlerRegistry registry) {
|
||||
Path uploadDir = Paths.get(dirName);
|
||||
String uploadPath = uploadDir.toFile().getAbsolutePath();
|
||||
|
||||
if (dirName.startsWith("../")) dirName = dirName.replace("../", "");
|
||||
|
||||
registry.addResourceHandler("/" + dirName + "/**").addResourceLocations("file:/"+ uploadPath + "/");
|
||||
}
|
||||
|
||||
return new CorsFilter(source);
|
||||
}*/
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -34,3 +34,10 @@ app.jwtSecret= ======================spring=back====================
|
||||
app.jwtExpirationMs= 800000
|
||||
app.jwtCookieName=springangularts
|
||||
|
||||
#=============File Upload Configurations========================
|
||||
spring.servlet.multipart.max-file-size=50MB
|
||||
spring.servlet.multipart.max-request-size=50MB
|
||||
|
||||
|
||||
server.tomcat.max-swallow-size=100MB
|
||||
#=============
|
||||
@@ -45,6 +45,11 @@ spring.jpa.properties.hibernate.dialect= org.hibernate.dialect.PostgreSQLDialect
|
||||
|
||||
spring.jpa.show-sql=true
|
||||
|
||||
#=============Zhipuai Configurations========================
|
||||
|
||||
spring.ai.zhipuai.base-url=https://open.bigmodel.cn/api/paas/v4/images/generations
|
||||
spring.ai.zhipuai.api-key = 628447c8c65845a48a7226391464a2ea.Dw8ci6TiW0BRF5LI
|
||||
|
||||
#==================Custom App Properties=====================
|
||||
|
||||
app.jwtSecret= ======================spring=back====================
|
||||
@@ -52,7 +57,10 @@ app.jwtExpirationMs= 800000
|
||||
app.jwtCookieName=springangularts
|
||||
|
||||
|
||||
#=============Zhipuai Configurations========================
|
||||
#=============File Upload Configurations========================
|
||||
spring.servlet.multipart.max-file-size=50MB
|
||||
spring.servlet.multipart.max-request-size=50MB
|
||||
|
||||
spring.ai.zhipuai.base-url=https://open.bigmodel.cn/api/paas/v4/images/generations
|
||||
spring.ai.zhipuai.api-key = 628447c8c65845a48a7226391464a2ea.Dw8ci6TiW0BRF5LI
|
||||
server.tomcat.max-swallow-size=100MB
|
||||
|
||||
#=============
|
||||
|
||||
@@ -1,2 +1,4 @@
|
||||
#bootJar with profile prod
|
||||
spring.profiles.active=prod
|
||||
|
||||
#spring.profiles.active=dev
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
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";
|
||||
Reference in New Issue
Block a user