mirror of
https://gitea.gofwd.group/Forward_Group/ballistic-builder-spring.git
synced 2026-01-21 01:01:05 -05:00
Merge remote-tracking branch 'origin/develop' into develop
This commit is contained in:
8
pom.xml
8
pom.xml
@@ -77,12 +77,7 @@
|
|||||||
<artifactId>spring-boot-starter-mail</artifactId>
|
<artifactId>spring-boot-starter-mail</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.jsonwebtoken</groupId>
|
|
||||||
<artifactId>jjwt-impl</artifactId>
|
|
||||||
<version>0.11.5</version>
|
|
||||||
<scope>runtime</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-web</artifactId>
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
@@ -151,7 +146,6 @@
|
|||||||
<version>0.11.5</version>
|
<version>0.11.5</version>
|
||||||
<scope>runtime</scope>
|
<scope>runtime</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- JSP Support -->
|
<!-- JSP Support -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.tomcat.embed</groupId>
|
<groupId>org.apache.tomcat.embed</groupId>
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package group.goforward.battlbuilder.controllers.api;
|
|||||||
import group.goforward.battlbuilder.utils.ApiResponse;
|
import group.goforward.battlbuilder.utils.ApiResponse;
|
||||||
import group.goforward.battlbuilder.dto.EmailRequestDto;
|
import group.goforward.battlbuilder.dto.EmailRequestDto;
|
||||||
import group.goforward.battlbuilder.model.EmailRequest;
|
import group.goforward.battlbuilder.model.EmailRequest;
|
||||||
|
import group.goforward.battlbuilder.model.EmailStatus;
|
||||||
import group.goforward.battlbuilder.repos.EmailRequestRepository;
|
import group.goforward.battlbuilder.repos.EmailRequestRepository;
|
||||||
import group.goforward.battlbuilder.services.utils.EmailService;
|
import group.goforward.battlbuilder.services.utils.EmailService;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
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.bind.annotation.*;
|
||||||
import org.springframework.web.server.ResponseStatusException;
|
import org.springframework.web.server.ResponseStatusException;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/api/email")
|
@RequestMapping("/api/email")
|
||||||
public class EmailController {
|
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 EmailService emailService;
|
||||||
private final EmailRequestRepository emailRequestRepository;
|
private final EmailRequestRepository emailRequestRepository;
|
||||||
@@ -28,6 +30,17 @@ public class EmailController {
|
|||||||
this.emailRequestRepository = emailRequestRepository;
|
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
|
@GetMapping
|
||||||
public ResponseEntity<ApiResponse<List<EmailRequest>>> getAllEmailRequests() {
|
public ResponseEntity<ApiResponse<List<EmailRequest>>> getAllEmailRequests() {
|
||||||
try {
|
try {
|
||||||
@@ -45,7 +58,7 @@ public class EmailController {
|
|||||||
@GetMapping("/allSent")
|
@GetMapping("/allSent")
|
||||||
public ResponseEntity<ApiResponse<List<EmailRequest>>> getNotSentEmailRequests() {
|
public ResponseEntity<ApiResponse<List<EmailRequest>>> getNotSentEmailRequests() {
|
||||||
try {
|
try {
|
||||||
List<EmailRequest> emailRequests = emailRequestRepository.findSent();
|
List<EmailRequest> emailRequests = emailRequestRepository.findByStatus(EmailStatus.SENT);
|
||||||
return ResponseEntity.ok(
|
return ResponseEntity.ok(
|
||||||
ApiResponse.success(emailRequests, "Not sent email requests retrieved successfully")
|
ApiResponse.success(emailRequests, "Not sent email requests retrieved successfully")
|
||||||
);
|
);
|
||||||
@@ -59,7 +72,7 @@ public class EmailController {
|
|||||||
@GetMapping("/allFailed")
|
@GetMapping("/allFailed")
|
||||||
public ResponseEntity<ApiResponse<List<EmailRequest>>> getFailedEmailRequests() {
|
public ResponseEntity<ApiResponse<List<EmailRequest>>> getFailedEmailRequests() {
|
||||||
try {
|
try {
|
||||||
List<EmailRequest> emailRequests = emailRequestRepository.findFailed();
|
List<EmailRequest> emailRequests = emailRequestRepository.findByStatus(EmailStatus.FAILED);
|
||||||
return ResponseEntity.ok(
|
return ResponseEntity.ok(
|
||||||
ApiResponse.success(emailRequests, "Failed email requests retrieved successfully")
|
ApiResponse.success(emailRequests, "Failed email requests retrieved successfully")
|
||||||
);
|
);
|
||||||
@@ -73,7 +86,7 @@ public class EmailController {
|
|||||||
@GetMapping("/allPending")
|
@GetMapping("/allPending")
|
||||||
public ResponseEntity<ApiResponse<List<EmailRequest>>> getPendingEmailRequests() {
|
public ResponseEntity<ApiResponse<List<EmailRequest>>> getPendingEmailRequests() {
|
||||||
try {
|
try {
|
||||||
List<EmailRequest> emailRequests = emailRequestRepository.findPending();
|
List<EmailRequest> emailRequests = emailRequestRepository.findByStatus(EmailStatus.PENDING);
|
||||||
return ResponseEntity.ok(
|
return ResponseEntity.ok(
|
||||||
ApiResponse.success(emailRequests, "Pending email requests retrieved successfully")
|
ApiResponse.success(emailRequests, "Pending email requests retrieved successfully")
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -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>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -7,19 +7,18 @@ import java.time.LocalDateTime;
|
|||||||
@Table(name = "email_requests")
|
@Table(name = "email_requests")
|
||||||
@NamedQuery(
|
@NamedQuery(
|
||||||
name = "EmailRequest.findSent",
|
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(
|
@NamedQuery(
|
||||||
name = "EmailRequest.findFailed",
|
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(
|
@NamedQuery(
|
||||||
name = "EmailRequest.findPending",
|
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 {
|
public class EmailRequest {
|
||||||
|
|
||||||
@Id
|
@Id
|
||||||
@@ -38,8 +37,9 @@ public class EmailRequest {
|
|||||||
@Column(name = "sent_at")
|
@Column(name = "sent_at")
|
||||||
private LocalDateTime sentAt;
|
private LocalDateTime sentAt;
|
||||||
|
|
||||||
|
@Enumerated(EnumType.STRING)
|
||||||
@Column(nullable = false)
|
@Column(nullable = false)
|
||||||
private String status; // PENDING, SENT, FAILED
|
private EmailStatus status; // PENDING, SENT, FAILED
|
||||||
|
|
||||||
@Column(name = "error_message")
|
@Column(name = "error_message")
|
||||||
private String errorMessage;
|
private String errorMessage;
|
||||||
@@ -52,9 +52,10 @@ public class EmailRequest {
|
|||||||
createdAt = LocalDateTime.now();
|
createdAt = LocalDateTime.now();
|
||||||
updatedAt = LocalDateTime.now();
|
updatedAt = LocalDateTime.now();
|
||||||
if (status == null) {
|
if (status == null) {
|
||||||
status = "PENDING";
|
status = EmailStatus.PENDING;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Column(name = "updated_at", nullable = false, updatable = false)
|
@Column(name = "updated_at", nullable = false, updatable = false)
|
||||||
private LocalDateTime updatedAt;
|
private LocalDateTime updatedAt;
|
||||||
|
|
||||||
@@ -99,11 +100,11 @@ public class EmailRequest {
|
|||||||
this.sentAt = sentAt;
|
this.sentAt = sentAt;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getStatus() {
|
public EmailStatus getStatus() {
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setStatus(String status) {
|
public void setStatus(EmailStatus status) {
|
||||||
this.status = status;
|
this.status = status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package group.goforward.battlbuilder.model;
|
||||||
|
|
||||||
|
public enum EmailStatus {
|
||||||
|
PENDING,
|
||||||
|
SENT,
|
||||||
|
FAILED
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package group.goforward.battlbuilder.repos;
|
package group.goforward.battlbuilder.repos;
|
||||||
|
|
||||||
import group.goforward.battlbuilder.model.EmailRequest;
|
import group.goforward.battlbuilder.model.EmailRequest;
|
||||||
|
import group.goforward.battlbuilder.model.EmailStatus;
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
import org.springframework.stereotype.Repository;
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
@@ -8,11 +9,8 @@ import java.util.List;
|
|||||||
|
|
||||||
@Repository
|
@Repository
|
||||||
public interface EmailRequestRepository extends JpaRepository<EmailRequest, Long> {
|
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();
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package group.goforward.battlbuilder.services.utils.impl;
|
package group.goforward.battlbuilder.services.utils.impl;
|
||||||
|
|
||||||
import group.goforward.battlbuilder.model.EmailRequest;
|
import group.goforward.battlbuilder.model.EmailRequest;
|
||||||
|
import group.goforward.battlbuilder.model.EmailStatus;
|
||||||
import group.goforward.battlbuilder.repos.EmailRequestRepository;
|
import group.goforward.battlbuilder.repos.EmailRequestRepository;
|
||||||
import group.goforward.battlbuilder.services.utils.EmailService;
|
import group.goforward.battlbuilder.services.utils.EmailService;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@@ -33,12 +34,11 @@ public class EmailServiceImpl implements EmailService {
|
|||||||
emailRequest.setRecipient(recipient);
|
emailRequest.setRecipient(recipient);
|
||||||
emailRequest.setSubject(subject);
|
emailRequest.setSubject(subject);
|
||||||
emailRequest.setBody(body);
|
emailRequest.setBody(body);
|
||||||
emailRequest.setStatus("PENDING");
|
emailRequest.setStatus(EmailStatus.PENDING);
|
||||||
|
|
||||||
emailRequest = emailRequestRepository.save(emailRequest);
|
emailRequest = emailRequestRepository.save(emailRequest);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Send email as HTML
|
|
||||||
MimeMessage message = mailSender.createMimeMessage();
|
MimeMessage message = mailSender.createMimeMessage();
|
||||||
MimeMessageHelper helper = new MimeMessageHelper(
|
MimeMessageHelper helper = new MimeMessageHelper(
|
||||||
message,
|
message,
|
||||||
@@ -49,19 +49,15 @@ public class EmailServiceImpl implements EmailService {
|
|||||||
helper.setFrom(fromEmail);
|
helper.setFrom(fromEmail);
|
||||||
helper.setTo(recipient);
|
helper.setTo(recipient);
|
||||||
helper.setSubject(subject);
|
helper.setSubject(subject);
|
||||||
|
|
||||||
// IMPORTANT: second argument 'true' means "this is HTML"
|
|
||||||
helper.setText(body, true);
|
helper.setText(body, true);
|
||||||
|
|
||||||
mailSender.send(message);
|
mailSender.send(message);
|
||||||
|
|
||||||
// Update status
|
emailRequest.setStatus(EmailStatus.SENT);
|
||||||
emailRequest.setStatus("SENT");
|
|
||||||
emailRequest.setSentAt(LocalDateTime.now());
|
emailRequest.setSentAt(LocalDateTime.now());
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
// Update status with error
|
emailRequest.setStatus(EmailStatus.FAILED);
|
||||||
emailRequest.setStatus("FAILED");
|
|
||||||
emailRequest.setErrorMessage(e.getMessage());
|
emailRequest.setErrorMessage(e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,6 +66,6 @@ public class EmailServiceImpl implements EmailService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void deleteById(Integer id) {
|
public void deleteById(Integer id) {
|
||||||
emailRequestRepository.deleteById(Long.valueOf(id));
|
emailRequestRepository.deleteById(id.longValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -37,11 +37,10 @@ spring.mail.properties.mail.smtp.starttls.required=true
|
|||||||
|
|
||||||
spring.datasource.hikari.max-lifetime=600000
|
spring.datasource.hikari.max-lifetime=600000
|
||||||
|
|
||||||
|
minio.endpoint=https://minioapi.dev.gofwd.group
|
||||||
minio.endpoint=https://minio.dev.gofwd.group
|
minio.access-key=dstrawsb
|
||||||
minio.access-key=<MINIO_ACCESS_KEY>
|
minio.secret-key=Cul8rman2025
|
||||||
minio.secret-key=<MINIO_SECRET_KEY>
|
minio.bucket=battlbuilders
|
||||||
minio.bucket=battlbuilds
|
|
||||||
|
|
||||||
# Public base URL used to write back into products.main_image_url
|
# Public base URL used to write back into products.main_image_url
|
||||||
minio.public-base-url=https://minio.dev.gofwd.group
|
minio.public-base-url=https://minio.dev.gofwd.group
|
||||||
|
|||||||
Reference in New Issue
Block a user