Add: complete MPaste service rewritten in Spring
This commit is contained in:
@@ -6,5 +6,9 @@ cd ..
|
|||||||
cd huertos/
|
cd huertos/
|
||||||
mvn clean package
|
mvn clean package
|
||||||
cd ..
|
cd ..
|
||||||
|
cd mpaste/
|
||||||
|
mvn clean package
|
||||||
|
cd ..
|
||||||
scp core/target/core-1.0.0.jar jomaa@10.0.0.254:/home/jomaa/transfer
|
scp core/target/core-1.0.0.jar jomaa@10.0.0.254:/home/jomaa/transfer
|
||||||
scp huertos/target/huertos-1.0.0.jar jomaa@10.0.0.254:/home/jomaa/transfer
|
scp huertos/target/huertos-1.0.0.jar jomaa@10.0.0.254:/home/jomaa/transfer
|
||||||
|
scp mpaste/target/mpaste-1.0.0.jar jomaa@10.0.0.254:/home/jomaa/transfer
|
||||||
@@ -31,10 +31,6 @@
|
|||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-security</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.mariadb.jdbc</groupId>
|
<groupId>org.mariadb.jdbc</groupId>
|
||||||
<artifactId>mariadb-java-client</artifactId>
|
<artifactId>mariadb-java-client</artifactId>
|
||||||
@@ -58,7 +54,13 @@
|
|||||||
<version>0.11.5</version>
|
<version>0.11.5</version>
|
||||||
<scope>runtime</scope>
|
<scope>runtime</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
<dependency>
|
||||||
|
<groupId>net.miarma</groupId>
|
||||||
|
<artifactId>backlib</artifactId>
|
||||||
|
<version>1.1.1</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package net.miarma.backend.mpaste;
|
||||||
|
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
|
||||||
|
@SpringBootApplication(scanBasePackages = {
|
||||||
|
"net.miarma.backend.mpaste",
|
||||||
|
"net.miarma.backlib"
|
||||||
|
})
|
||||||
|
public class MPasteApplication {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(MPasteApplication.class, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package net.miarma.backend.mpaste.config;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class NoSecurityConfig {
|
||||||
|
@Bean
|
||||||
|
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||||
|
http
|
||||||
|
.csrf(csrf -> csrf.disable())
|
||||||
|
.authorizeHttpRequests(auth -> auth.anyRequest().permitAll());
|
||||||
|
return http.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package net.miarma.backend.mpaste.config;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||||
|
|
||||||
|
@EnableScheduling
|
||||||
|
@Configuration
|
||||||
|
public class SchedulingConfig {
|
||||||
|
}
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
package net.miarma.backend.mpaste.controller;
|
||||||
|
|
||||||
|
import net.miarma.backend.mpaste.dto.PasteDto;
|
||||||
|
import net.miarma.backend.mpaste.dto.PastePassword;
|
||||||
|
import net.miarma.backend.mpaste.mapper.PasteMapper;
|
||||||
|
import net.miarma.backend.mpaste.service.PasteService;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/pastes")
|
||||||
|
public class PasteController {
|
||||||
|
private PasteService pasteService;
|
||||||
|
|
||||||
|
public PasteController(PasteService pasteService) {
|
||||||
|
this.pasteService = pasteService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping
|
||||||
|
public ResponseEntity<List<PasteDto.Response>> getAll() {
|
||||||
|
return ResponseEntity.ok(
|
||||||
|
pasteService.getAll().stream()
|
||||||
|
.map(PasteMapper::toResponse)
|
||||||
|
.toList()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/by-id/{paste_id}")
|
||||||
|
public ResponseEntity<PasteDto.Response> getById(@PathVariable("paste_id") UUID pasteId) {
|
||||||
|
return ResponseEntity.ok(
|
||||||
|
PasteMapper.toResponse(pasteService.getById(pasteId))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/{paste_key}")
|
||||||
|
public ResponseEntity<PasteDto.Response> getByKey(@PathVariable("paste_key") String pasteKey, @RequestBody PastePassword dto) {
|
||||||
|
return ResponseEntity.ok(
|
||||||
|
PasteMapper.toResponse(pasteService.getByKey(pasteKey, dto.password()))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping
|
||||||
|
public ResponseEntity<PasteDto.Response> create(PasteDto.Request request) {
|
||||||
|
return ResponseEntity.ok(
|
||||||
|
PasteMapper.toResponse(
|
||||||
|
pasteService.create(
|
||||||
|
PasteMapper.toEntity(request)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PutMapping("/{paste_id}")
|
||||||
|
public void update() {
|
||||||
|
throw new UnsupportedOperationException("Pastes cannot be updated");
|
||||||
|
}
|
||||||
|
|
||||||
|
@DeleteMapping("/{paste_id}")
|
||||||
|
public ResponseEntity<PasteDto.Response> delete(@PathVariable("paste_id") UUID pasteId) {
|
||||||
|
return ResponseEntity.ok(
|
||||||
|
PasteMapper.toResponse(
|
||||||
|
pasteService.delete(pasteId)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
157
mpaste/src/main/java/net/miarma/backend/mpaste/dto/PasteDto.java
Normal file
157
mpaste/src/main/java/net/miarma/backend/mpaste/dto/PasteDto.java
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
package net.miarma.backend.mpaste.dto;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class PasteDto {
|
||||||
|
|
||||||
|
private PasteDto() { }
|
||||||
|
|
||||||
|
public static class Request {
|
||||||
|
|
||||||
|
private String title;
|
||||||
|
private String content;
|
||||||
|
private String syntax;
|
||||||
|
|
||||||
|
private Boolean burnAfter;
|
||||||
|
private Boolean isPrivate;
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
public String getTitle() {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTitle(String title) {
|
||||||
|
this.title = title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getContent() {
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContent(String content) {
|
||||||
|
this.content = content;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSyntax() {
|
||||||
|
return syntax;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSyntax(String syntax) {
|
||||||
|
this.syntax = syntax;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean getBurnAfter() {
|
||||||
|
return burnAfter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBurnAfter(Boolean burnAfter) {
|
||||||
|
this.burnAfter = burnAfter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean getIsPrivate() {
|
||||||
|
return isPrivate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIsPrivate(Boolean isPrivate) {
|
||||||
|
this.isPrivate = isPrivate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPassword() {
|
||||||
|
return password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPassword(String password) {
|
||||||
|
this.password = password;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Response {
|
||||||
|
|
||||||
|
private UUID pasteId;
|
||||||
|
private String pasteKey;
|
||||||
|
|
||||||
|
private String title;
|
||||||
|
private String content;
|
||||||
|
private String syntax;
|
||||||
|
|
||||||
|
private Integer views;
|
||||||
|
|
||||||
|
private Boolean burnAfter;
|
||||||
|
private Boolean isPrivate;
|
||||||
|
|
||||||
|
private Instant createdAt;
|
||||||
|
|
||||||
|
public UUID getPasteId() {
|
||||||
|
return pasteId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPasteId(UUID pasteId) {
|
||||||
|
this.pasteId = pasteId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPasteKey() {
|
||||||
|
return pasteKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPasteKey(String pasteKey) {
|
||||||
|
this.pasteKey = pasteKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTitle() {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTitle(String title) {
|
||||||
|
this.title = title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getContent() {
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContent(String content) {
|
||||||
|
this.content = content;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSyntax() {
|
||||||
|
return syntax;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSyntax(String syntax) {
|
||||||
|
this.syntax = syntax;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getViews() {
|
||||||
|
return views;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setViews(Integer views) {
|
||||||
|
this.views = views;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean getBurnAfter() {
|
||||||
|
return burnAfter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBurnAfter(Boolean burnAfter) {
|
||||||
|
this.burnAfter = burnAfter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean getIsPrivate() {
|
||||||
|
return isPrivate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIsPrivate(Boolean isPrivate) {
|
||||||
|
this.isPrivate = isPrivate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Instant getCreatedAt() {
|
||||||
|
return createdAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCreatedAt(Instant createdAt) {
|
||||||
|
this.createdAt = createdAt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
package net.miarma.backend.mpaste.dto;
|
||||||
|
|
||||||
|
public record PastePassword(String password) {}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
package net.miarma.backend.mpaste.mapper;
|
||||||
|
|
||||||
|
import net.miarma.backend.mpaste.dto.PasteDto;
|
||||||
|
import net.miarma.backend.mpaste.model.Paste;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
|
||||||
|
public final class PasteMapper {
|
||||||
|
|
||||||
|
private PasteMapper() { }
|
||||||
|
|
||||||
|
public static Paste toEntity(PasteDto.Request request) {
|
||||||
|
|
||||||
|
Paste paste = new Paste();
|
||||||
|
|
||||||
|
paste.setTitle(request.getTitle());
|
||||||
|
paste.setContent(request.getContent());
|
||||||
|
paste.setSyntax(request.getSyntax());
|
||||||
|
|
||||||
|
paste.setBurnAfter(Boolean.TRUE.equals(request.getBurnAfter()));
|
||||||
|
paste.setPrivate(Boolean.TRUE.equals(request.getIsPrivate()));
|
||||||
|
|
||||||
|
paste.setPassword(request.getPassword());
|
||||||
|
|
||||||
|
paste.setViews(0);
|
||||||
|
paste.setCreatedAt(Instant.now());
|
||||||
|
|
||||||
|
return paste;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PasteDto.Response toResponse(Paste paste) {
|
||||||
|
|
||||||
|
PasteDto.Response response = new PasteDto.Response();
|
||||||
|
|
||||||
|
response.setPasteId(paste.getPasteId());
|
||||||
|
response.setPasteKey(paste.getPasteKey());
|
||||||
|
|
||||||
|
response.setTitle(paste.getTitle());
|
||||||
|
response.setContent(paste.getContent());
|
||||||
|
response.setSyntax(paste.getSyntax());
|
||||||
|
|
||||||
|
response.setViews(paste.getViews());
|
||||||
|
|
||||||
|
response.setBurnAfter(paste.isBurnAfter());
|
||||||
|
response.setIsPrivate(paste.isPrivate());
|
||||||
|
|
||||||
|
response.setCreatedAt(paste.getCreatedAt());
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
}
|
||||||
158
mpaste/src/main/java/net/miarma/backend/mpaste/model/Paste.java
Normal file
158
mpaste/src/main/java/net/miarma/backend/mpaste/model/Paste.java
Normal file
@@ -0,0 +1,158 @@
|
|||||||
|
package net.miarma.backend.mpaste.model;
|
||||||
|
|
||||||
|
import jakarta.persistence.*;
|
||||||
|
import net.miarma.backlib.util.UuidUtil;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name = "mpaste_pastes")
|
||||||
|
public class Paste {
|
||||||
|
@Id
|
||||||
|
@Column(name = "paste_id", columnDefinition = "BINARY(16)")
|
||||||
|
private byte[] pasteIdBin;
|
||||||
|
|
||||||
|
@Transient
|
||||||
|
private UUID pasteId;
|
||||||
|
|
||||||
|
@Column(name = "owner_id", columnDefinition = "BINARY(16)")
|
||||||
|
private byte[] ownerIdBin;
|
||||||
|
|
||||||
|
@Transient
|
||||||
|
private UUID ownerId;
|
||||||
|
|
||||||
|
@Column(name = "paste_key", updatable = false, insertable = false, unique = true, nullable = false)
|
||||||
|
private String pasteKey;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private String title;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private String content;
|
||||||
|
|
||||||
|
private String syntax;
|
||||||
|
private Integer views;
|
||||||
|
|
||||||
|
@Column(name = "burn_after")
|
||||||
|
private Boolean burnAfter;
|
||||||
|
|
||||||
|
@Column(name = "is_private")
|
||||||
|
private Boolean isPrivate;
|
||||||
|
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
@Column(name = "created_at")
|
||||||
|
private Instant createdAt;
|
||||||
|
|
||||||
|
@PrePersist
|
||||||
|
@PreUpdate
|
||||||
|
private void prePersist() {
|
||||||
|
if (pasteId != null) {
|
||||||
|
pasteIdBin = UuidUtil.uuidToBin(pasteId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ownerId != null) {
|
||||||
|
ownerIdBin = UuidUtil.uuidToBin(ownerId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostLoad
|
||||||
|
private void postLoad() {
|
||||||
|
if (pasteIdBin != null) {
|
||||||
|
pasteId = UuidUtil.binToUUID(pasteIdBin);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ownerIdBin != null) {
|
||||||
|
ownerId = UuidUtil.binToUUID(ownerIdBin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public UUID getPasteId() {
|
||||||
|
return pasteId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPasteId(UUID pasteId) {
|
||||||
|
this.pasteId = pasteId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UUID getOwnerId() {
|
||||||
|
return ownerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOwnerId(UUID ownerId) {
|
||||||
|
this.ownerId = ownerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPasteKey() {
|
||||||
|
return pasteKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPasteKey(String pasteKey) {
|
||||||
|
this.pasteKey = pasteKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTitle() {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTitle(String title) {
|
||||||
|
this.title = title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getContent() {
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContent(String content) {
|
||||||
|
this.content = content;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSyntax() {
|
||||||
|
return syntax;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSyntax(String syntax) {
|
||||||
|
this.syntax = syntax;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getViews() {
|
||||||
|
return views;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setViews(Integer views) {
|
||||||
|
this.views = views;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean isBurnAfter() {
|
||||||
|
return burnAfter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBurnAfter(Boolean burnAfter) {
|
||||||
|
this.burnAfter = burnAfter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean isPrivate() {
|
||||||
|
return isPrivate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPrivate(Boolean aPrivate) {
|
||||||
|
isPrivate = aPrivate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPassword() {
|
||||||
|
return password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPassword(String password) {
|
||||||
|
this.password = password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Instant getCreatedAt() {
|
||||||
|
return createdAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCreatedAt(Instant createdAt) {
|
||||||
|
this.createdAt = createdAt;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package net.miarma.backend.mpaste.repository;
|
||||||
|
|
||||||
|
import net.miarma.backend.mpaste.model.Paste;
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public interface PasteRepository extends JpaRepository<Paste, byte[]> {
|
||||||
|
Optional<Paste> findByPasteKey(String pasteKey);
|
||||||
|
}
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
package net.miarma.backend.mpaste.service;
|
||||||
|
|
||||||
|
import jakarta.transaction.Transactional;
|
||||||
|
import net.miarma.backend.mpaste.model.Paste;
|
||||||
|
import net.miarma.backend.mpaste.repository.PasteRepository;
|
||||||
|
import net.miarma.backend.mpaste.validation.PasteValidator;
|
||||||
|
import net.miarma.backlib.exception.ForbiddenException;
|
||||||
|
import net.miarma.backlib.exception.NotFoundException;
|
||||||
|
import net.miarma.backlib.util.UuidUtil;
|
||||||
|
import org.springframework.scheduling.TaskScheduler;
|
||||||
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@Transactional
|
||||||
|
public class PasteService {
|
||||||
|
private final PasteRepository pasteRepository;
|
||||||
|
private final PasswordEncoder passwordEncoder;
|
||||||
|
private final TaskScheduler taskScheduler;
|
||||||
|
|
||||||
|
public PasteService(PasteRepository pasteRepository, PasswordEncoder passwordEncoder, TaskScheduler taskScheduler) {
|
||||||
|
this.pasteRepository = pasteRepository;
|
||||||
|
this.passwordEncoder = passwordEncoder;
|
||||||
|
this.taskScheduler = taskScheduler;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Paste> getAll() {
|
||||||
|
return pasteRepository.findAll().stream()
|
||||||
|
.filter(p -> !Boolean.TRUE.equals(p.isPrivate()))
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Paste getById(UUID pasteId) {
|
||||||
|
byte[] idBytes = UuidUtil.uuidToBin(pasteId);
|
||||||
|
return pasteRepository.findById(idBytes)
|
||||||
|
.orElseThrow(() -> new NotFoundException("Paste not found"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Paste getByKey(String pasteKey, String password) {
|
||||||
|
Paste paste = pasteRepository.findByPasteKey(pasteKey)
|
||||||
|
.orElseThrow(() -> new NotFoundException("Paste not found"));
|
||||||
|
|
||||||
|
if(Boolean.TRUE.equals(paste.isPrivate())) {
|
||||||
|
if(password == null || passwordEncoder.matches(password, paste.getPassword())) {
|
||||||
|
throw new ForbiddenException("Incorrect password");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(Boolean.TRUE.equals(paste.isBurnAfter())) {
|
||||||
|
taskScheduler.schedule(
|
||||||
|
() -> pasteRepository.delete(paste),
|
||||||
|
Instant.now().plusSeconds(5)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return paste;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Paste create(Paste paste) {
|
||||||
|
PasteValidator.validate(paste);
|
||||||
|
return pasteRepository.save(paste);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Paste update(UUID pasteId, Paste changes) {
|
||||||
|
throw new UnsupportedOperationException("Pastes cannot be updated");
|
||||||
|
}
|
||||||
|
|
||||||
|
public Paste delete(UUID pasteId) {
|
||||||
|
byte[] idBytes = UuidUtil.uuidToBin(pasteId);
|
||||||
|
if(!pasteRepository.existsById(idBytes)) {
|
||||||
|
throw new NotFoundException("Paste not found");
|
||||||
|
}
|
||||||
|
Paste paste = getById(pasteId);
|
||||||
|
pasteRepository.deleteById(idBytes);
|
||||||
|
return paste;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package net.miarma.backend.mpaste.util;
|
||||||
|
|
||||||
|
import java.security.SecureRandom;
|
||||||
|
|
||||||
|
public class PasteKeyGenerator {
|
||||||
|
private static final String ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||||
|
private static final SecureRandom RANDOM = new SecureRandom();
|
||||||
|
|
||||||
|
public static String generate(int length) {
|
||||||
|
StringBuilder sb = new StringBuilder(length);
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
int index = RANDOM.nextInt(ALPHABET.length());
|
||||||
|
sb.append(ALPHABET.charAt(index));
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package net.miarma.backend.mpaste.validation;
|
||||||
|
|
||||||
|
import net.miarma.backend.mpaste.model.Paste;
|
||||||
|
import net.miarma.backlib.exception.ValidationException;
|
||||||
|
|
||||||
|
public class PasteValidator {
|
||||||
|
public static void validate(Paste paste) {
|
||||||
|
if (paste.getTitle() == null || paste.getTitle().trim().isEmpty()) {
|
||||||
|
throw new ValidationException("title", "The title cannot be empty");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (paste.getContent() == null || paste.getContent().trim().isEmpty()) {
|
||||||
|
throw new ValidationException("content", "The content cannot be empty");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Boolean.TRUE.equals(paste.isPrivate())) {
|
||||||
|
if (paste.getPassword() == null || paste.getPassword().trim().isEmpty()) {
|
||||||
|
throw new ValidationException("password", "Private pastes require password");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (paste.getTitle() != null && paste.getTitle().length() > 128) {
|
||||||
|
throw new ValidationException("title", "Title too long (128 characters max.)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
16
mpaste/src/main/resources/application-dev.yml
Normal file
16
mpaste/src/main/resources/application-dev.yml
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
server:
|
||||||
|
port: 8081
|
||||||
|
servlet:
|
||||||
|
context-path: /v2/mpaste
|
||||||
|
|
||||||
|
spring:
|
||||||
|
datasource:
|
||||||
|
url: jdbc:mariadb://localhost:3306/miarma_v2
|
||||||
|
username: admin
|
||||||
|
password: ${DB_PASS}
|
||||||
|
driver-class-name: org.mariadb.jdbc.Driver
|
||||||
|
|
||||||
|
logging:
|
||||||
|
level:
|
||||||
|
org.hibernate.SQL: DEBUG
|
||||||
|
org.hibernate.orm.jdbc.bind: TRACE
|
||||||
15
mpaste/src/main/resources/application-prod.yml
Normal file
15
mpaste/src/main/resources/application-prod.yml
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
server:
|
||||||
|
port: 8081
|
||||||
|
servlet:
|
||||||
|
context-path: /v2/mpaste
|
||||||
|
|
||||||
|
spring:
|
||||||
|
datasource:
|
||||||
|
url: jdbc:mariadb://mariadb:3306/miarma_v2
|
||||||
|
username: ${DB_USER}
|
||||||
|
password: ${DB_PASS}
|
||||||
|
driver-class-name: org.mariadb.jdbc.Driver
|
||||||
|
|
||||||
|
logging:
|
||||||
|
level:
|
||||||
|
org.hibernate.SQL: WARN
|
||||||
25
mpaste/src/main/resources/application.yml
Normal file
25
mpaste/src/main/resources/application.yml
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
spring:
|
||||||
|
application:
|
||||||
|
name: mpaste-service
|
||||||
|
|
||||||
|
jpa:
|
||||||
|
open-in-view: false
|
||||||
|
hibernate:
|
||||||
|
ddl-auto: validate
|
||||||
|
properties:
|
||||||
|
hibernate:
|
||||||
|
jdbc:
|
||||||
|
time_zone: UTC
|
||||||
|
|
||||||
|
jackson:
|
||||||
|
default-property-inclusion: non_null
|
||||||
|
time-zone: Europe/Madrid
|
||||||
|
|
||||||
|
jwt:
|
||||||
|
expiration-ms: 3600000
|
||||||
|
|
||||||
|
management:
|
||||||
|
endpoints:
|
||||||
|
web:
|
||||||
|
exposure:
|
||||||
|
include: health,info
|
||||||
Reference in New Issue
Block a user