Add new components for AI and tutorials, update routing, and enhance file upload functionality

This commit is contained in:
liosha84
2025-08-04 10:38:46 +03:00
parent 18c6906637
commit 483d029952
206 changed files with 2362 additions and 1199 deletions
@@ -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;
}
}
@@ -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
#=============
+11 -3
View File
@@ -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";