import to minio works

This commit is contained in:
2025-12-19 13:06:11 -05:00
parent e15486b2cc
commit d40a6a1d46
9 changed files with 46 additions and 78 deletions

View File

@@ -77,12 +77,7 @@
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.11.5</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
@@ -151,7 +146,6 @@
<version>0.11.5</version>
<scope>runtime</scope>
</dependency>
<!-- JSP Support -->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>

View File

@@ -3,6 +3,7 @@ package group.goforward.battlbuilder.controllers.api;
import group.goforward.battlbuilder.utils.ApiResponse;
import group.goforward.battlbuilder.dto.EmailRequestDto;
import group.goforward.battlbuilder.model.EmailRequest;
import group.goforward.battlbuilder.model.EmailStatus;
import group.goforward.battlbuilder.repos.EmailRequestRepository;
import group.goforward.battlbuilder.services.utils.EmailService;
import org.springframework.beans.factory.annotation.Autowired;
@@ -11,13 +12,14 @@ import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.server.ResponseStatusException;
import java.util.Arrays;
import java.util.List;
@RestController
@RequestMapping("/api/email")
public class EmailController {
private static final String EMAIL_STATUS_SENT = "SENT";
private static final EmailStatus EMAIL_STATUS_SENT = EmailStatus.SENT;
private final EmailService emailService;
private final EmailRequestRepository emailRequestRepository;
@@ -28,6 +30,17 @@ public class EmailController {
this.emailRequestRepository = emailRequestRepository;
}
@GetMapping("/statuses")
public ResponseEntity<ApiResponse<List<String>>> getEmailStatuses() {
List<String> statuses = Arrays.stream(EmailStatus.values())
.map(Enum::name)
.toList();
return ResponseEntity.ok(
ApiResponse.success(statuses, "Email statuses retrieved successfully")
);
}
@GetMapping
public ResponseEntity<ApiResponse<List<EmailRequest>>> getAllEmailRequests() {
try {
@@ -45,7 +58,7 @@ public class EmailController {
@GetMapping("/allSent")
public ResponseEntity<ApiResponse<List<EmailRequest>>> getNotSentEmailRequests() {
try {
List<EmailRequest> emailRequests = emailRequestRepository.findSent();
List<EmailRequest> emailRequests = emailRequestRepository.findByStatus(EmailStatus.SENT);
return ResponseEntity.ok(
ApiResponse.success(emailRequests, "Not sent email requests retrieved successfully")
);
@@ -59,7 +72,7 @@ public class EmailController {
@GetMapping("/allFailed")
public ResponseEntity<ApiResponse<List<EmailRequest>>> getFailedEmailRequests() {
try {
List<EmailRequest> emailRequests = emailRequestRepository.findFailed();
List<EmailRequest> emailRequests = emailRequestRepository.findByStatus(EmailStatus.FAILED);
return ResponseEntity.ok(
ApiResponse.success(emailRequests, "Failed email requests retrieved successfully")
);
@@ -73,7 +86,7 @@ public class EmailController {
@GetMapping("/allPending")
public ResponseEntity<ApiResponse<List<EmailRequest>>> getPendingEmailRequests() {
try {
List<EmailRequest> emailRequests = emailRequestRepository.findPending();
List<EmailRequest> emailRequests = emailRequestRepository.findByStatus(EmailStatus.PENDING);
return ResponseEntity.ok(
ApiResponse.success(emailRequests, "Pending email requests retrieved successfully")
);

View File

@@ -1,40 +0,0 @@
"use client";
import { useState } from "react";
import { sendEmailAction, type ApiResponse, type EmailRequest } from "./actions/sendEmail";
export default function SendEmailForm(): JSX.Element {
const [result, setResult] = useState<ApiResponse<EmailRequest> | { error: string } | null>(null);
async function onSubmit(e: React.FormEvent<HTMLFormElement>): Promise<void> {
e.preventDefault();
setResult(null);
const form = new FormData(e.currentTarget);
const recipient = String(form.get("recipient") ?? "");
const subject = String(form.get("subject") ?? "");
const body = String(form.get("body") ?? "");
try {
const data = await sendEmailAction({ recipient, subject, body });
setResult(data);
} catch (err) {
const message = err instanceof Error ? err.message : "Unknown error";
setResult({ error: message });
}
}
return (
<form onSubmit={onSubmit}>
<input name="recipient" placeholder="recipient" defaultValue="user@example.com" />
<input name="subject" placeholder="subject" defaultValue="Test subject" />
<textarea name="body" placeholder="body" defaultValue="Test body" />
<button type="submit">Send</button>
<pre style={{ marginTop: 12 }}>
{result ? JSON.stringify(result, null, 2) : "No response yet."}
</pre>
</form>
);
}

View File

@@ -7,19 +7,18 @@ import java.time.LocalDateTime;
@Table(name = "email_requests")
@NamedQuery(
name = "EmailRequest.findSent",
query = "SELECT e FROM EmailRequest e WHERE e.status = 'SENT'"
query = "SELECT e FROM EmailRequest e WHERE e.status = group.goforward.battlbuilder.model.EmailStatus.SENT"
)
@NamedQuery(
name = "EmailRequest.findFailed",
query = "SELECT e FROM EmailRequest e WHERE e.status = 'FAILED'"
query = "SELECT e FROM EmailRequest e WHERE e.status = group.goforward.battlbuilder.model.EmailStatus.FAILED"
)
@NamedQuery(
name = "EmailRequest.findPending",
query = "SELECT e FROM EmailRequest e WHERE e.status = 'PENDING'"
query = "SELECT e FROM EmailRequest e WHERE e.status = group.goforward.battlbuilder.model.EmailStatus.PENDING"
)
public class EmailRequest {
@Id
@@ -38,8 +37,9 @@ public class EmailRequest {
@Column(name = "sent_at")
private LocalDateTime sentAt;
@Enumerated(EnumType.STRING)
@Column(nullable = false)
private String status; // PENDING, SENT, FAILED
private EmailStatus status; // PENDING, SENT, FAILED
@Column(name = "error_message")
private String errorMessage;
@@ -52,9 +52,10 @@ public class EmailRequest {
createdAt = LocalDateTime.now();
updatedAt = LocalDateTime.now();
if (status == null) {
status = "PENDING";
status = EmailStatus.PENDING;
}
}
@Column(name = "updated_at", nullable = false, updatable = false)
private LocalDateTime updatedAt;
@@ -99,11 +100,11 @@ public class EmailRequest {
this.sentAt = sentAt;
}
public String getStatus() {
public EmailStatus getStatus() {
return status;
}
public void setStatus(String status) {
public void setStatus(EmailStatus status) {
this.status = status;
}

View File

@@ -0,0 +1,7 @@
package group.goforward.battlbuilder.model;
public enum EmailStatus {
PENDING,
SENT,
FAILED
}

View File

@@ -1,6 +1,7 @@
package group.goforward.battlbuilder.repos;
import group.goforward.battlbuilder.model.EmailRequest;
import group.goforward.battlbuilder.model.EmailStatus;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@@ -8,11 +9,8 @@ import java.util.List;
@Repository
public interface EmailRequestRepository extends JpaRepository<EmailRequest, Long> {
List<EmailRequest> findByStatus(String status);
List<EmailRequest> findFailed();
List<EmailRequest> findByStatus(EmailStatus status);
List<EmailRequest> findByStatusOrderByCreatedAtDesc(EmailStatus status);
List<EmailRequest> findSent();
List<EmailRequest> findPending();
}

View File

@@ -1,6 +1,7 @@
package group.goforward.battlbuilder.services.utils.impl;
import group.goforward.battlbuilder.model.EmailRequest;
import group.goforward.battlbuilder.model.EmailStatus;
import group.goforward.battlbuilder.repos.EmailRequestRepository;
import group.goforward.battlbuilder.services.utils.EmailService;
import org.springframework.beans.factory.annotation.Autowired;
@@ -33,12 +34,11 @@ public class EmailServiceImpl implements EmailService {
emailRequest.setRecipient(recipient);
emailRequest.setSubject(subject);
emailRequest.setBody(body);
emailRequest.setStatus("PENDING");
emailRequest.setStatus(EmailStatus.PENDING);
emailRequest = emailRequestRepository.save(emailRequest);
try {
// Send email as HTML
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(
message,
@@ -49,19 +49,15 @@ public class EmailServiceImpl implements EmailService {
helper.setFrom(fromEmail);
helper.setTo(recipient);
helper.setSubject(subject);
// IMPORTANT: second argument 'true' means "this is HTML"
helper.setText(body, true);
mailSender.send(message);
// Update status
emailRequest.setStatus("SENT");
emailRequest.setStatus(EmailStatus.SENT);
emailRequest.setSentAt(LocalDateTime.now());
} catch (Exception e) {
// Update status with error
emailRequest.setStatus("FAILED");
emailRequest.setStatus(EmailStatus.FAILED);
emailRequest.setErrorMessage(e.getMessage());
}
@@ -70,6 +66,6 @@ public class EmailServiceImpl implements EmailService {
@Override
public void deleteById(Integer id) {
emailRequestRepository.deleteById(Long.valueOf(id));
emailRequestRepository.deleteById(id.longValue());
}
}

View File

@@ -37,11 +37,10 @@ spring.mail.properties.mail.smtp.starttls.required=true
spring.datasource.hikari.max-lifetime=600000
minio.endpoint=https://minio.dev.gofwd.group
minio.access-key=<MINIO_ACCESS_KEY>
minio.secret-key=<MINIO_SECRET_KEY>
minio.bucket=battlbuilds
minio.endpoint=https://minioapi.dev.gofwd.group
minio.access-key=dstrawsb
minio.secret-key=Cul8rman2025
minio.bucket=battlbuilders
# Public base URL used to write back into products.main_image_url
minio.public-base-url=https://minio.dev.gofwd.group