generated from Gallardo7761/miarma-template-full
Compare commits
2 Commits
5ef4d0f2e0
...
fdc3120aa7
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fdc3120aa7 | ||
|
|
af65e3b51e |
@@ -0,0 +1,53 @@
|
||||
package es.adeptusminiaturium.backend.config;
|
||||
|
||||
import es.adeptusminiaturium.backend.service.CustomUserDetailsService;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.config.Customizer;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
|
||||
@Configuration
|
||||
public class SecurityConfig {
|
||||
|
||||
private final CustomUserDetailsService userDetailsService;
|
||||
|
||||
public SecurityConfig(CustomUserDetailsService userDetailsService) {
|
||||
this.userDetailsService = userDetailsService;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.csrf(Customizer.withDefaults())
|
||||
.authorizeHttpRequests(auth -> auth
|
||||
//.requestMatchers("/admin/**").hasRole("ADMIN")
|
||||
//.requestMatchers("/posts/**").authenticated()
|
||||
.anyRequest().permitAll()
|
||||
)
|
||||
.formLogin(Customizer.withDefaults())
|
||||
.httpBasic(Customizer.withDefaults());
|
||||
|
||||
return http.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public PasswordEncoder passwordEncoder() {
|
||||
return new BCryptPasswordEncoder(12);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public AuthenticationManager authManager(HttpSecurity http) {
|
||||
AuthenticationManagerBuilder authBuilder =
|
||||
http.getSharedObject(AuthenticationManagerBuilder.class);
|
||||
|
||||
authBuilder.userDetailsService(userDetailsService)
|
||||
.passwordEncoder(passwordEncoder());
|
||||
|
||||
return authBuilder.build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package es.adeptusminiaturium.backend.controller;
|
||||
|
||||
import es.adeptusminiaturium.backend.dto.MediaDto;
|
||||
import es.adeptusminiaturium.backend.service.MediaService;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/media")
|
||||
public class MediaController {
|
||||
|
||||
private final MediaService service;
|
||||
|
||||
public MediaController(MediaService service) { this.service = service; }
|
||||
|
||||
@GetMapping
|
||||
public ResponseEntity<List<MediaDto.Response>> getAll() {
|
||||
return ResponseEntity.ok(service.getAll());
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
public ResponseEntity<MediaDto.Response> getOne(@PathVariable Long id) {
|
||||
return ResponseEntity.ofNullable(service.getById(id));
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
public ResponseEntity<MediaDto.Response> create(@RequestBody MediaDto.Request dto) {
|
||||
return ResponseEntity.ok(service.create(dto));
|
||||
}
|
||||
|
||||
@PutMapping("/{id}")
|
||||
public ResponseEntity<MediaDto.Response> update(@PathVariable Long id, @RequestBody MediaDto.Request dto) {
|
||||
return ResponseEntity.ofNullable(service.update(id, dto));
|
||||
}
|
||||
|
||||
@DeleteMapping("/{id}")
|
||||
public ResponseEntity<Void> delete(@PathVariable Long id) {
|
||||
service.delete(id);
|
||||
return ResponseEntity.noContent().build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package es.adeptusminiaturium.backend.controller;
|
||||
|
||||
import es.adeptusminiaturium.backend.service.PostService;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import es.adeptusminiaturium.backend.dto.PostDto;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/posts")
|
||||
public class PostController {
|
||||
|
||||
private final PostService postService;
|
||||
|
||||
public PostController(PostService postService) {
|
||||
this.postService = postService;
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public ResponseEntity<List<PostDto.Response>> getAll() {
|
||||
return ResponseEntity.ok(postService.getAllPosts());
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
public ResponseEntity<PostDto.Response> getById(@PathVariable Long id) {
|
||||
return ResponseEntity.ok(postService.getPostById(id));
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
public ResponseEntity<PostDto.Response> create(@RequestBody PostDto.Request dto) {
|
||||
return ResponseEntity.ok(postService.createPost(dto));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package es.adeptusminiaturium.backend.controller;
|
||||
|
||||
import es.adeptusminiaturium.backend.dto.PublicationDto;
|
||||
import es.adeptusminiaturium.backend.service.PublicationService;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/publications")
|
||||
public class PublicationController {
|
||||
|
||||
private final PublicationService service;
|
||||
|
||||
public PublicationController(PublicationService service) { this.service = service; }
|
||||
|
||||
@GetMapping
|
||||
public ResponseEntity<List<PublicationDto.Response>> getAll() {
|
||||
return ResponseEntity.ok(service.getAll());
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
public ResponseEntity<PublicationDto.Response> getOne(@PathVariable Long id) {
|
||||
return ResponseEntity.ofNullable(service.getById(id));
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
public ResponseEntity<PublicationDto.Response> create(@RequestBody PublicationDto.Request dto) {
|
||||
return ResponseEntity.ok(service.create(dto));
|
||||
}
|
||||
|
||||
@PutMapping("/{id}")
|
||||
public ResponseEntity<PublicationDto.Response> update(@PathVariable Long id, @RequestBody PublicationDto.Request dto) {
|
||||
return ResponseEntity.ofNullable(service.update(id, dto));
|
||||
}
|
||||
|
||||
@DeleteMapping("/{id}")
|
||||
public ResponseEntity<Void> delete(@PathVariable Long id) {
|
||||
service.delete(id);
|
||||
return ResponseEntity.noContent().build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package es.adeptusminiaturium.backend.controller;
|
||||
|
||||
import es.adeptusminiaturium.backend.service.UserService;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import es.adeptusminiaturium.backend.dto.UserDto;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/users")
|
||||
public class UserController {
|
||||
|
||||
private final UserService service;
|
||||
|
||||
public UserController(UserService service) { this.service = service; }
|
||||
|
||||
@GetMapping
|
||||
public ResponseEntity<List<UserDto.Response>> getAll() {
|
||||
return ResponseEntity.ok(service.getAllUsers());
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
public ResponseEntity<UserDto.Response> getOne(@PathVariable UUID id) {
|
||||
return ResponseEntity.ofNullable(service.getUser(id));
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
public ResponseEntity<UserDto.Response> create(@RequestBody UserDto.Request dto) {
|
||||
return ResponseEntity.ok(service.createUser(dto));
|
||||
}
|
||||
|
||||
@PutMapping("/{id}")
|
||||
public ResponseEntity<UserDto.Response> update(@PathVariable UUID id, @RequestBody UserDto.Request dto) {
|
||||
return ResponseEntity.ofNullable(service.updateUser(id, dto));
|
||||
}
|
||||
|
||||
@DeleteMapping("/{id}")
|
||||
public ResponseEntity<Void> delete(@PathVariable UUID id) {
|
||||
service.deleteUser(id);
|
||||
return ResponseEntity.noContent().build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package es.adeptusminiaturium.backend.dto;
|
||||
|
||||
import es.adeptusminiaturium.backend.enums.MediaType;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
public class MediaDto {
|
||||
|
||||
public static class Request {
|
||||
private Long postId;
|
||||
private MediaType mediaType;
|
||||
private String url;
|
||||
private Integer position;
|
||||
|
||||
public Long getPostId() { return postId; }
|
||||
public void setPostId(Long postId) { this.postId = postId; }
|
||||
public MediaType getMediaType() { return mediaType; }
|
||||
public void setMediaType(MediaType mediaType) { this.mediaType = mediaType; }
|
||||
public String getUrl() { return url; }
|
||||
public void setUrl(String url) { this.url = url; }
|
||||
public Integer getPosition() { return position; }
|
||||
public void setPosition(Integer position) { this.position = position; }
|
||||
}
|
||||
|
||||
public static class Response {
|
||||
private Long mediaId;
|
||||
private PostDto.Response post;
|
||||
private MediaType mediaType;
|
||||
private String url;
|
||||
private Integer position;
|
||||
private LocalDateTime createdAt;
|
||||
|
||||
public Long getMediaId() { return mediaId; }
|
||||
public void setMediaId(Long mediaId) { this.mediaId = mediaId; }
|
||||
public PostDto.Response getPost() { return post; }
|
||||
public void setPost(PostDto.Response post) { this.post = post; }
|
||||
public MediaType getMediaType() { return mediaType; }
|
||||
public void setMediaType(MediaType mediaType) { this.mediaType = mediaType; }
|
||||
public String getUrl() { return url; }
|
||||
public void setUrl(String url) { this.url = url; }
|
||||
public Integer getPosition() { return position; }
|
||||
public void setPosition(Integer position) { this.position = position; }
|
||||
public LocalDateTime getCreatedAt() { return createdAt; }
|
||||
public void setCreatedAt(LocalDateTime createdAt) { this.createdAt = createdAt; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package es.adeptusminiaturium.backend.dto;
|
||||
|
||||
import es.adeptusminiaturium.backend.enums.PostStatus;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.UUID;
|
||||
|
||||
public class PostDto {
|
||||
|
||||
public static class Request {
|
||||
private UUID authorId;
|
||||
private String title;
|
||||
private String body;
|
||||
private String hashtags;
|
||||
private PostStatus status;
|
||||
|
||||
public UUID getAuthorId() { return authorId; }
|
||||
public void setAuthorId(UUID authorId) { this.authorId = authorId; }
|
||||
public String getTitle() { return title; }
|
||||
public void setTitle(String title) { this.title = title; }
|
||||
public String getBody() { return body; }
|
||||
public void setBody(String body) { this.body = body; }
|
||||
public String getHashtags() { return hashtags; }
|
||||
public void setHashtags(String hashtags) { this.hashtags = hashtags; }
|
||||
public PostStatus getStatus() { return status; }
|
||||
public void setStatus(PostStatus status) { this.status = status; }
|
||||
}
|
||||
|
||||
public static class Response {
|
||||
private Long postId;
|
||||
private UserDto.Response author;
|
||||
private String title;
|
||||
private String body;
|
||||
private String hashtags;
|
||||
private PostStatus status;
|
||||
private LocalDateTime createdAt;
|
||||
private LocalDateTime updatedAt;
|
||||
private LocalDateTime publishedAt;
|
||||
|
||||
public Long getPostId() { return postId; }
|
||||
public void setPostId(Long postId) { this.postId = postId; }
|
||||
public UserDto.Response getAuthor() { return author; }
|
||||
public void setAuthor(UserDto.Response author) { this.author = author; }
|
||||
public String getTitle() { return title; }
|
||||
public void setTitle(String title) { this.title = title; }
|
||||
public String getBody() { return body; }
|
||||
public void setBody(String body) { this.body = body; }
|
||||
public String getHashtags() { return hashtags; }
|
||||
public void setHashtags(String hashtags) { this.hashtags = hashtags; }
|
||||
public PostStatus getStatus() { return status; }
|
||||
public void setStatus(PostStatus status) { this.status = status; }
|
||||
public LocalDateTime getCreatedAt() { return createdAt; }
|
||||
public void setCreatedAt(LocalDateTime createdAt) { this.createdAt = createdAt; }
|
||||
public LocalDateTime getUpdatedAt() { return updatedAt; }
|
||||
public void setUpdatedAt(LocalDateTime updatedAt) { this.updatedAt = updatedAt; }
|
||||
public LocalDateTime getPublishedAt() { return publishedAt; }
|
||||
public void setPublishedAt(LocalDateTime publishedAt) { this.publishedAt = publishedAt; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package es.adeptusminiaturium.backend.dto;
|
||||
|
||||
import es.adeptusminiaturium.backend.enums.Platform;
|
||||
import es.adeptusminiaturium.backend.enums.PublicationStatus;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
public class PublicationDto {
|
||||
|
||||
public static class Request {
|
||||
private Long postId;
|
||||
private Platform platform;
|
||||
private String externalId;
|
||||
private PublicationStatus status;
|
||||
|
||||
// getters y setters
|
||||
public Long getPostId() { return postId; }
|
||||
public void setPostId(Long postId) { this.postId = postId; }
|
||||
public Platform getPlatform() { return platform; }
|
||||
public void setPlatform(Platform platform) { this.platform = platform; }
|
||||
public String getExternalId() { return externalId; }
|
||||
public void setExternalId(String externalId) { this.externalId = externalId; }
|
||||
public PublicationStatus getStatus() { return status; }
|
||||
public void setStatus(PublicationStatus status) { this.status = status; }
|
||||
}
|
||||
|
||||
public static class Response {
|
||||
private Long publicationId;
|
||||
private PostDto.Response post;
|
||||
private Platform platform;
|
||||
private String externalId;
|
||||
private PublicationStatus status;
|
||||
private LocalDateTime publishedAt;
|
||||
private String errorMessage;
|
||||
private LocalDateTime createdAt;
|
||||
|
||||
// getters y setters
|
||||
public Long getPublicationId() { return publicationId; }
|
||||
public void setPublicationId(Long publicationId) { this.publicationId = publicationId; }
|
||||
public PostDto.Response getPost() { return post; }
|
||||
public void setPost(PostDto.Response post) { this.post = post; }
|
||||
public Platform getPlatform() { return platform; }
|
||||
public void setPlatform(Platform platform) { this.platform = platform; }
|
||||
public String getExternalId() { return externalId; }
|
||||
public void setExternalId(String externalId) { this.externalId = externalId; }
|
||||
public PublicationStatus getStatus() { return status; }
|
||||
public void setStatus(PublicationStatus status) { this.status = status; }
|
||||
public LocalDateTime getPublishedAt() { return publishedAt; }
|
||||
public void setPublishedAt(LocalDateTime publishedAt) { this.publishedAt = publishedAt; }
|
||||
public String getErrorMessage() { return errorMessage; }
|
||||
public void setErrorMessage(String errorMessage) { this.errorMessage = errorMessage; }
|
||||
public LocalDateTime getCreatedAt() { return createdAt; }
|
||||
public void setCreatedAt(LocalDateTime createdAt) { this.createdAt = createdAt; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package es.adeptusminiaturium.backend.dto;
|
||||
|
||||
import es.adeptusminiaturium.backend.enums.UserRole;
|
||||
import es.adeptusminiaturium.backend.enums.UserStatus;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.UUID;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.UUID;
|
||||
|
||||
public class UserDto {
|
||||
|
||||
public static class Request {
|
||||
private String displayName;
|
||||
private String userName;
|
||||
private String password;
|
||||
private String avatar;
|
||||
private UserRole role;
|
||||
private UserStatus status;
|
||||
|
||||
public String getDisplayName() { return displayName; }
|
||||
public void setDisplayName(String displayName) { this.displayName = displayName; }
|
||||
public String getUserName() { return userName; }
|
||||
public void setUserName(String userName) { this.userName = userName; }
|
||||
public String getPassword() { return password; }
|
||||
public void setPassword(String password) { this.password = password; }
|
||||
public String getAvatar() { return avatar; }
|
||||
public void setAvatar(String avatar) { this.avatar = avatar; }
|
||||
public UserRole getRole() { return role; }
|
||||
public void setRole(UserRole role) { this.role = role; }
|
||||
public UserStatus getStatus() { return status; }
|
||||
public void setStatus(UserStatus status) { this.status = status; }
|
||||
}
|
||||
|
||||
public static class Response {
|
||||
private UUID userId;
|
||||
private String displayName;
|
||||
private String userName;
|
||||
private String avatar;
|
||||
private UserRole role;
|
||||
private UserStatus status;
|
||||
private LocalDateTime createdAt;
|
||||
private LocalDateTime updatedAt;
|
||||
|
||||
public UUID getUserId() { return userId; }
|
||||
public void setUserId(UUID userId) { this.userId = userId; }
|
||||
public String getDisplayName() { return displayName; }
|
||||
public void setDisplayName(String displayName) { this.displayName = displayName; }
|
||||
public String getUserName() { return userName; }
|
||||
public void setUserName(String userName) { this.userName = userName; }
|
||||
public String getAvatar() { return avatar; }
|
||||
public void setAvatar(String avatar) { this.avatar = avatar; }
|
||||
public UserRole getRole() { return role; }
|
||||
public void setRole(UserRole role) { this.role = role; }
|
||||
public UserStatus getStatus() { return status; }
|
||||
public void setStatus(UserStatus status) { this.status = status; }
|
||||
public LocalDateTime getCreatedAt() { return createdAt; }
|
||||
public void setCreatedAt(LocalDateTime createdAt) { this.createdAt = createdAt; }
|
||||
public LocalDateTime getUpdatedAt() { return updatedAt; }
|
||||
public void setUpdatedAt(LocalDateTime updatedAt) { this.updatedAt = updatedAt; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package es.adeptusminiaturium.backend.enums;
|
||||
|
||||
public enum MediaType {
|
||||
IMAGE, // 0
|
||||
VIDEO // 1
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package es.adeptusminiaturium.backend.enums;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public enum Platform {
|
||||
WEB, // 0
|
||||
INSTAGRAM, // 1
|
||||
TIKTOK, // 2
|
||||
TWITTER; // 3
|
||||
|
||||
public static List<Platform> valuesList() {
|
||||
return List.of(values());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package es.adeptusminiaturium.backend.enums;
|
||||
|
||||
public enum PostStatus {
|
||||
DRAFT, // 0
|
||||
PUBLISHED, // 1
|
||||
ARCHIVED // 2
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package es.adeptusminiaturium.backend.enums;
|
||||
|
||||
public enum PublicationStatus {
|
||||
PENDING, // 0
|
||||
PUBLISHED, // 1
|
||||
FAILED // 2
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package es.adeptusminiaturium.backend.enums;
|
||||
|
||||
public enum UserRole {
|
||||
USER, // 0
|
||||
ADMIN // 1
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package es.adeptusminiaturium.backend.enums;
|
||||
|
||||
public enum UserStatus {
|
||||
INACTIVE, // 0
|
||||
ACTIVE // 1
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package es.adeptusminiaturium.backend.mapper;
|
||||
|
||||
import es.adeptusminiaturium.backend.dto.MediaDto;
|
||||
import es.adeptusminiaturium.backend.model.Media;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
public class MediaMapper {
|
||||
|
||||
public static MediaDto.Response toResponse(Media entity) {
|
||||
MediaDto.Response dto = new MediaDto.Response();
|
||||
dto.setMediaId(entity.getMediaId());
|
||||
dto.setPost(PostMapper.toResponse(entity.getPost()));
|
||||
dto.setMediaType(entity.getMediaType());
|
||||
dto.setUrl(entity.getUrl());
|
||||
dto.setPosition(entity.getPosition());
|
||||
dto.setCreatedAt(entity.getCreatedAt());
|
||||
return dto;
|
||||
}
|
||||
|
||||
public static Media toEntity(MediaDto.Request dto) {
|
||||
Media entity = new Media();
|
||||
entity.setMediaId(null); // autoincrement
|
||||
entity.setPost(null); // se setea después con repo.findById(dto.getPostId())
|
||||
entity.setMediaType(dto.getMediaType());
|
||||
entity.setUrl(dto.getUrl());
|
||||
entity.setPosition(dto.getPosition());
|
||||
entity.setCreatedAt(LocalDateTime.now());
|
||||
return entity;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package es.adeptusminiaturium.backend.mapper;
|
||||
|
||||
import es.adeptusminiaturium.backend.dto.PostDto;
|
||||
import es.adeptusminiaturium.backend.dto.UserDto;
|
||||
import es.adeptusminiaturium.backend.model.Post;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
public class PostMapper {
|
||||
|
||||
public static PostDto.Response toResponse(Post entity) {
|
||||
PostDto.Response dto = new PostDto.Response();
|
||||
dto.setPostId(entity.getPostId());
|
||||
dto.setAuthor(UserMapper.toResponse(entity.getAuthor()));
|
||||
dto.setTitle(entity.getTitle());
|
||||
dto.setBody(entity.getBody());
|
||||
dto.setHashtags(entity.getHashtags());
|
||||
dto.setStatus(entity.getStatus());
|
||||
dto.setCreatedAt(entity.getCreatedAt());
|
||||
dto.setUpdatedAt(entity.getUpdatedAt());
|
||||
dto.setPublishedAt(entity.getPublishedAt());
|
||||
return dto;
|
||||
}
|
||||
|
||||
public static Post toEntity(PostDto.Request dto) {
|
||||
Post entity = new Post();
|
||||
entity.setPostId(null);
|
||||
entity.setAuthor(null);
|
||||
entity.setTitle(dto.getTitle());
|
||||
entity.setBody(dto.getBody());
|
||||
entity.setHashtags(dto.getHashtags());
|
||||
entity.setStatus(dto.getStatus());
|
||||
entity.setCreatedAt(LocalDateTime.now());
|
||||
entity.setUpdatedAt(LocalDateTime.now());
|
||||
entity.setPublishedAt(null);
|
||||
return entity;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package es.adeptusminiaturium.backend.mapper;
|
||||
|
||||
import es.adeptusminiaturium.backend.dto.PublicationDto;
|
||||
import es.adeptusminiaturium.backend.model.Publication;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
public class PublicationMapper {
|
||||
|
||||
public static PublicationDto.Response toResponse(Publication entity) {
|
||||
PublicationDto.Response dto = new PublicationDto.Response();
|
||||
dto.setPublicationId(entity.getPublicationId());
|
||||
dto.setPost(PostMapper.toResponse(entity.getPost()));
|
||||
dto.setPlatform(entity.getPlatform());
|
||||
dto.setExternalId(entity.getExternalId());
|
||||
dto.setStatus(entity.getStatus());
|
||||
dto.setPublishedAt(entity.getPublishedAt());
|
||||
dto.setErrorMessage(entity.getErrorMessage());
|
||||
dto.setCreatedAt(entity.getCreatedAt());
|
||||
return dto;
|
||||
}
|
||||
|
||||
public static Publication toEntity(PublicationDto.Request dto) {
|
||||
Publication entity = new Publication();
|
||||
entity.setPublicationId(null);
|
||||
entity.setPost(null);
|
||||
entity.setPlatform(dto.getPlatform());
|
||||
entity.setExternalId(dto.getExternalId());
|
||||
entity.setStatus(dto.getStatus());
|
||||
entity.setPublishedAt(null);
|
||||
entity.setErrorMessage(null);
|
||||
entity.setCreatedAt(LocalDateTime.now());
|
||||
return entity;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package es.adeptusminiaturium.backend.mapper;
|
||||
|
||||
import es.adeptusminiaturium.backend.dto.UserDto;
|
||||
import es.adeptusminiaturium.backend.model.User;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.UUID;
|
||||
|
||||
public class UserMapper {
|
||||
|
||||
public static UserDto.Response toResponse(User entity) {
|
||||
UserDto.Response dto = new UserDto.Response();
|
||||
dto.setUserId(entity.getUserId());
|
||||
dto.setDisplayName(entity.getDisplayName());
|
||||
dto.setUserName(entity.getUserName());
|
||||
dto.setAvatar(entity.getAvatar());
|
||||
dto.setRole(entity.getRole());
|
||||
dto.setStatus(entity.getStatus());
|
||||
dto.setCreatedAt(entity.getCreatedAt());
|
||||
dto.setUpdatedAt(entity.getUpdatedAt());
|
||||
return dto;
|
||||
}
|
||||
|
||||
public static User toEntity(UserDto.Request dto) {
|
||||
User entity = new User();
|
||||
entity.setUserId(UUID.randomUUID());
|
||||
entity.setDisplayName(dto.getDisplayName());
|
||||
entity.setUserName(dto.getUserName());
|
||||
entity.setPassword(dto.getPassword());
|
||||
entity.setAvatar(dto.getAvatar());
|
||||
entity.setRole(dto.getRole());
|
||||
entity.setStatus(dto.getStatus());
|
||||
entity.setCreatedAt(LocalDateTime.now());
|
||||
entity.setUpdatedAt(LocalDateTime.now());
|
||||
return entity;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package es.adeptusminiaturium.backend.repository;
|
||||
|
||||
import es.adeptusminiaturium.backend.model.Media;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface MediaRepository extends JpaRepository<Media, Long> {
|
||||
List<Media> findByPostPostId(Long postId);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package es.adeptusminiaturium.backend.repository;
|
||||
|
||||
import es.adeptusminiaturium.backend.model.Post;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
public interface PostRepository extends JpaRepository<Post, Long> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package es.adeptusminiaturium.backend.repository;
|
||||
|
||||
import es.adeptusminiaturium.backend.model.Publication;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface PublicationRepository extends JpaRepository<Publication, Long> {
|
||||
List<Publication> findByPostPostId(Long postId);
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package es.adeptusminiaturium.backend.repository;
|
||||
|
||||
import es.adeptusminiaturium.backend.model.User;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
public interface UserRepository extends JpaRepository<User, UUID> {
|
||||
Optional<User> findByUserName(String userName);
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package es.adeptusminiaturium.backend.security;
|
||||
|
||||
import es.adeptusminiaturium.backend.enums.UserStatus;
|
||||
import es.adeptusminiaturium.backend.model.User;
|
||||
import es.adeptusminiaturium.backend.enums.UserRole;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
public class CustomUserDetails implements UserDetails {
|
||||
|
||||
private final User user;
|
||||
|
||||
public CustomUserDetails(User user) {
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<? extends GrantedAuthority> getAuthorities() {
|
||||
return List.of(new SimpleGrantedAuthority("ROLE_" + user.getRole().name()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPassword() {
|
||||
return user.getPassword();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsername() {
|
||||
return user.getUserName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return user.getStatus().equals(UserStatus.ACTIVE);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package es.adeptusminiaturium.backend.service;
|
||||
|
||||
import es.adeptusminiaturium.backend.repository.UserRepository;
|
||||
import es.adeptusminiaturium.backend.security.CustomUserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class CustomUserDetailsService implements UserDetailsService {
|
||||
|
||||
private final UserRepository userRepo;
|
||||
|
||||
public CustomUserDetailsService(UserRepository userRepo) {
|
||||
this.userRepo = userRepo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
|
||||
return userRepo.findByUserName(username)
|
||||
.map(CustomUserDetails::new)
|
||||
.orElseThrow(() -> new UsernameNotFoundException("User not found: " + username));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package es.adeptusminiaturium.backend.service;
|
||||
|
||||
import es.adeptusminiaturium.backend.dto.MediaDto;
|
||||
import es.adeptusminiaturium.backend.mapper.MediaMapper;
|
||||
import es.adeptusminiaturium.backend.model.Media;
|
||||
import es.adeptusminiaturium.backend.repository.MediaRepository;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
public class MediaService {
|
||||
|
||||
private final MediaRepository repo;
|
||||
|
||||
public MediaService(MediaRepository repo) { this.repo = repo; }
|
||||
|
||||
@Transactional
|
||||
public List<MediaDto.Response> getAll() {
|
||||
return repo.findAll().stream().map(MediaMapper::toResponse).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public MediaDto.Response getById(Long id) {
|
||||
return repo.findById(id).map(MediaMapper::toResponse).orElse(null);
|
||||
}
|
||||
|
||||
public MediaDto.Response create(MediaDto.Request dto) {
|
||||
Media media = MediaMapper.toEntity(dto);
|
||||
return MediaMapper.toResponse(repo.save(media));
|
||||
}
|
||||
|
||||
public MediaDto.Response update(Long id, MediaDto.Request dto) {
|
||||
return repo.findById(id).map(media -> {
|
||||
media.setMediaType(dto.getMediaType());
|
||||
media.setUrl(dto.getUrl());
|
||||
media.setPosition(dto.getPosition());
|
||||
return MediaMapper.toResponse(repo.save(media));
|
||||
}).orElse(null);
|
||||
}
|
||||
|
||||
public void delete(Long id) { repo.deleteById(id); }
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package es.adeptusminiaturium.backend.service;
|
||||
|
||||
import es.adeptusminiaturium.backend.dto.PostDto;
|
||||
import es.adeptusminiaturium.backend.mapper.PostMapper;
|
||||
import es.adeptusminiaturium.backend.model.Post;
|
||||
import es.adeptusminiaturium.backend.repository.PostRepository;
|
||||
import es.adeptusminiaturium.backend.repository.UserRepository;
|
||||
import es.adeptusminiaturium.backend.validator.PostValidator;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
public class PostService {
|
||||
|
||||
private final PostRepository postRepository;
|
||||
private final UserRepository userRepository;
|
||||
|
||||
public PostService(PostRepository postRepository, UserRepository userRepository) {
|
||||
this.postRepository = postRepository;
|
||||
this.userRepository = userRepository;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public List<PostDto.Response> getAllPosts() {
|
||||
return postRepository.findAll().stream()
|
||||
.map(PostMapper::toResponse)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public PostDto.Response createPost(PostDto.Request dto) {
|
||||
Post post = PostMapper.toEntity(dto);
|
||||
post.setAuthor(userRepository.findById(dto.getAuthorId()).orElseThrow());
|
||||
Post saved = postRepository.save(post);
|
||||
return PostMapper.toResponse(saved);
|
||||
}
|
||||
|
||||
public PostDto.Response getPostById(Long postId) {
|
||||
Post post = postRepository.findById(postId).orElseThrow();
|
||||
return PostMapper.toResponse(post);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package es.adeptusminiaturium.backend.service;
|
||||
|
||||
import es.adeptusminiaturium.backend.dto.PublicationDto;
|
||||
import es.adeptusminiaturium.backend.mapper.PublicationMapper;
|
||||
import es.adeptusminiaturium.backend.model.Publication;
|
||||
import es.adeptusminiaturium.backend.repository.PublicationRepository;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
public class PublicationService {
|
||||
|
||||
private final PublicationRepository repo;
|
||||
|
||||
public PublicationService(PublicationRepository repo) { this.repo = repo; }
|
||||
|
||||
@Transactional
|
||||
public List<PublicationDto.Response> getAll() {
|
||||
return repo.findAll().stream().map(PublicationMapper::toResponse).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public PublicationDto.Response getById(Long id) {
|
||||
return repo.findById(id).map(PublicationMapper::toResponse).orElse(null);
|
||||
}
|
||||
|
||||
public PublicationDto.Response create(PublicationDto.Request dto) {
|
||||
Publication pub = PublicationMapper.toEntity(dto);
|
||||
return PublicationMapper.toResponse(repo.save(pub));
|
||||
}
|
||||
|
||||
public PublicationDto.Response update(Long id, PublicationDto.Request dto) {
|
||||
return repo.findById(id).map(pub -> {
|
||||
pub.setPlatform(dto.getPlatform());
|
||||
pub.setExternalId(dto.getExternalId());
|
||||
pub.setStatus(dto.getStatus());
|
||||
return PublicationMapper.toResponse(repo.save(pub));
|
||||
}).orElse(null);
|
||||
}
|
||||
|
||||
public void delete(Long id) { repo.deleteById(id); }
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package es.adeptusminiaturium.backend.service;
|
||||
|
||||
|
||||
import es.adeptusminiaturium.backend.dto.UserDto;
|
||||
import es.adeptusminiaturium.backend.mapper.UserMapper;
|
||||
import es.adeptusminiaturium.backend.model.User;
|
||||
import es.adeptusminiaturium.backend.repository.UserRepository;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
public class UserService {
|
||||
|
||||
private final UserRepository repo;
|
||||
|
||||
public UserService(UserRepository repo) { this.repo = repo; }
|
||||
|
||||
public List<UserDto.Response> getAllUsers() {
|
||||
return repo.findAll().stream().map(UserMapper::toResponse).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public UserDto.Response getUser(UUID userId) {
|
||||
return repo.findById(userId).map(UserMapper::toResponse).orElse(null);
|
||||
}
|
||||
|
||||
public UserDto.Response createUser(UserDto.Request dto) {
|
||||
User user = UserMapper.toEntity(dto);
|
||||
return UserMapper.toResponse(repo.save(user));
|
||||
}
|
||||
|
||||
public UserDto.Response updateUser(UUID userId, UserDto.Request dto) {
|
||||
return repo.findById(userId).map(user -> {
|
||||
user.setDisplayName(dto.getDisplayName());
|
||||
user.setUserName(dto.getUserName());
|
||||
user.setPassword(dto.getPassword());
|
||||
user.setRole(dto.getRole());
|
||||
user.setStatus(dto.getStatus());
|
||||
user.setUpdatedAt(LocalDateTime.now());
|
||||
return UserMapper.toResponse(repo.save(user));
|
||||
}).orElse(null);
|
||||
}
|
||||
|
||||
public void deleteUser(UUID userId) { repo.deleteById(userId); }
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package es.adeptusminiaturium.backend.validator;
|
||||
|
||||
import es.adeptusminiaturium.backend.model.Media;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class MediaValidator {
|
||||
|
||||
public static List<String> validate(Media media) {
|
||||
List<String> errors = new ArrayList<>();
|
||||
|
||||
if (media.getPost() == null) {
|
||||
errors.add("Media must belong to a post");
|
||||
}
|
||||
|
||||
if (media.getUrl() == null || media.getUrl().isBlank()) {
|
||||
errors.add("URL cannot be empty");
|
||||
} else if (media.getUrl().length() > 512) {
|
||||
errors.add("URL too long");
|
||||
}
|
||||
|
||||
if (media.getPosition() == null || media.getPosition() < 0) {
|
||||
errors.add("Position cannot be negative");
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
public static void validateOrThrow(Media media) {
|
||||
List<String> errors = validate(media);
|
||||
if (!errors.isEmpty()) {
|
||||
throw new IllegalArgumentException(String.join(", ", errors));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package es.adeptusminiaturium.backend.validator;
|
||||
|
||||
import es.adeptusminiaturium.backend.model.Post;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class PostValidator {
|
||||
|
||||
public static List<String> validate(Post post) {
|
||||
List<String> errors = new ArrayList<>();
|
||||
|
||||
if (post.getAuthor() == null) {
|
||||
errors.add("Post must have an author");
|
||||
}
|
||||
|
||||
if (post.getTitle() == null || post.getTitle().isBlank()) {
|
||||
errors.add("Title cannot be empty");
|
||||
} else if (post.getTitle().length() > 255) {
|
||||
errors.add("Title too long");
|
||||
}
|
||||
|
||||
if (post.getBody() != null && post.getBody().length() > 10000) {
|
||||
errors.add("Body too long");
|
||||
}
|
||||
|
||||
if (post.getHashtags() != null && post.getHashtags().length() > 1000) {
|
||||
errors.add("Hashtags too long");
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
public static void validateOrThrow(Post post) {
|
||||
List<String> errors = validate(post);
|
||||
if (!errors.isEmpty()) {
|
||||
throw new IllegalArgumentException(String.join(", ", errors));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package es.adeptusminiaturium.backend.validator;
|
||||
|
||||
import es.adeptusminiaturium.backend.enums.Platform;
|
||||
import es.adeptusminiaturium.backend.model.Publication;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class PublicationValidator {
|
||||
|
||||
public static List<String> validate(Publication pub) {
|
||||
List<String> errors = new ArrayList<>();
|
||||
|
||||
if (pub.getPost() == null) {
|
||||
errors.add("Publication must belong to a post");
|
||||
}
|
||||
|
||||
if (pub.getPlatform() == null) {
|
||||
errors.add("Platform cannot be null");
|
||||
} else if (!Platform.valuesList().contains(pub.getPlatform())) {
|
||||
errors.add("Invalid platform");
|
||||
}
|
||||
|
||||
if (pub.getStatus() == null) {
|
||||
errors.add("Status cannot be null");
|
||||
}
|
||||
|
||||
if (pub.getExternalId() != null && pub.getExternalId().length() > 255) {
|
||||
errors.add("ExternalId too long");
|
||||
}
|
||||
|
||||
if (pub.getErrorMessage() != null && pub.getErrorMessage().length() > 1000) {
|
||||
errors.add("ErrorMessage too long");
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
public static void validateOrThrow(Publication pub) {
|
||||
List<String> errors = validate(pub);
|
||||
if (!errors.isEmpty()) {
|
||||
throw new IllegalArgumentException(String.join(", ", errors));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package es.adeptusminiaturium.backend.validator;
|
||||
|
||||
import es.adeptusminiaturium.backend.model.User;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class UserValidator {
|
||||
|
||||
public static List<String> validate(User user) {
|
||||
List<String> errors = new ArrayList<>();
|
||||
|
||||
if (user.getUserName() == null || user.getUserName().isBlank()) {
|
||||
errors.add("Username cannot be empty");
|
||||
}
|
||||
|
||||
if (user.getPassword() == null || user.getPassword().length() < 8) {
|
||||
errors.add("Password must have at least 8 characters");
|
||||
}
|
||||
|
||||
if (user.getDisplayName() != null && user.getDisplayName().length() > 255) {
|
||||
errors.add("DisplayName too long");
|
||||
}
|
||||
|
||||
if (user.getAvatar() != null && user.getAvatar().length() > 255) {
|
||||
errors.add("Avatar URL too long");
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
public static void validateOrThrow(User user) {
|
||||
List<String> errors = validate(user);
|
||||
if (!errors.isEmpty()) {
|
||||
throw new IllegalArgumentException(String.join(", ", errors));
|
||||
}
|
||||
}
|
||||
}
|
||||
52
backend/src/main/resources/bd.sql
Normal file
52
backend/src/main/resources/bd.sql
Normal file
@@ -0,0 +1,52 @@
|
||||
CREATE TABLE users(
|
||||
user_id UUID PRIMARY KEY,
|
||||
display_name VARCHAR(255),
|
||||
user_name VARCHAR(255) NOT NULL UNIQUE,
|
||||
password VARCHAR(255) NOT NULL,
|
||||
avatar VARCHAR(255) DEFAULT NULL,
|
||||
role TINYINT NOT NULL DEFAULT 0, -- 0 = user, 1 = admin
|
||||
status TINYINT NOT NULL DEFAULT 1, -- 0 = inactivo, 1 = activo
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP(),
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP() ON UPDATE CURRENT_TIMESTAMP()
|
||||
);
|
||||
|
||||
CREATE TABLE posts(
|
||||
post_id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
author_id UUID NOT NULL,
|
||||
title VARCHAR(255) NOT NULL,
|
||||
body TEXT,
|
||||
hashtags TEXT,
|
||||
status TINYINT NOT NULL DEFAULT 0, -- 0 = draft, 1 = published, 2 = archived
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP(),
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP() ON UPDATE CURRENT_TIMESTAMP(),
|
||||
published_at TIMESTAMP NULL,
|
||||
FOREIGN KEY (author_id) REFERENCES users(user_id)
|
||||
);
|
||||
|
||||
CREATE TABLE media(
|
||||
media_id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
post_id BIGINT NOT NULL,
|
||||
media_type TINYINT NOT NULL DEFAULT 0, -- 0 = image, 1 = video
|
||||
url VARCHAR(512) NOT NULL,
|
||||
position BIGINT NOT NULL DEFAULT 0,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP(),
|
||||
FOREIGN KEY (post_id) REFERENCES posts(post_id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE TABLE publications(
|
||||
publication_id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
post_id BIGINT NOT NULL,
|
||||
platform TINYINT NOT NULL, -- 0 = web, 1 = instagram, 2 = tiktok, 3 = twitter
|
||||
external_id VARCHAR(255) DEFAULT NULL,
|
||||
status TINYINT NOT NULL DEFAULT 0, -- 0 = pending, 1 = published, 2 = failed
|
||||
published_at TIMESTAMP NULL,
|
||||
error_message TEXT DEFAULT NULL,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP(),
|
||||
UNIQUE (post_id, platform),
|
||||
FOREIGN KEY (post_id) REFERENCES posts(post_id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE INDEX idx_posts_author ON posts(author_id);
|
||||
CREATE INDEX idx_posts_status_published ON posts(status, published_at);
|
||||
CREATE INDEX idx_media_post_position ON media(post_id, position);
|
||||
CREATE INDEX idx_publications_status ON publications(status);
|
||||
Reference in New Issue
Block a user