Skip to content
This repository was archived by the owner on Jul 6, 2025. It is now read-only.

Commit eafaf0f

Browse files
authored
Merge pull request #53 from Zenfulcode/release
Email confirmations and guest login fix
2 parents 2ff7db9 + a29f7ac commit eafaf0f

31 files changed

Lines changed: 894 additions & 34 deletions

deploy/.env.example

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,9 @@ MOBILEPAY_CLIENT_SECRET=
1313
MOBILEPAY_SUBSCRIPTION_KEY=
1414
MOBILEPAY_MERCHANT_ID=
1515
MOBILEPAY_API_URL=
16-
MOBILEPAY_SYSTEM_NAME=Commercify
16+
MOBILEPAY_SYSTEM_NAME=Commercify
17+
MAIL_USERNAME=
18+
MAIL_PASSWORD=
19+
MAIL_HOST=smtp.ethereal.email
20+
MAIL_PORT=587
21+
FRONTEND_URL=http://localhost:3000

deploy/docker-compose.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ services:
4040
- MOBILEPAY_SUBSCRIPTION_KEY=${MOBILEPAY_SUBSCRIPTION_KEY}
4141
- MOBILEPAY_API_URL=${MOBILEPAY_API_URL}
4242
- MOBILEPAY_SYSTEM_NAME=${MOBILEPAY_SYSTEM_NAME}
43+
- MAIL_USERNAME=${MAIL_USERNAME}
44+
- MAIL_PASSWORD=${MAIL_PASSWORD}
45+
- MAIL_HOST=${MAIL_HOST}
46+
- MAIL_PORT=${MAIL_PORT}
4347
depends_on:
4448
mysql:
4549
condition: service_healthy

makefile

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,7 @@ endif
1212

1313
update:
1414
docker compose -f deploy/docker-compose.yml down
15-
docker compose -f deploy/docker-compose.yml build --no-cache
16-
docker compose -f deploy/docker-compose.yml up --force-recreate
15+
docker compose -f deploy/docker-compose.yml up --build
1716

1817
build:
1918
docker build -t ghcr.io/zenfulcode/commercify:$(tag) .

pom.xml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,18 @@
141141
<artifactId>spring-retry</artifactId>
142142
<version>2.0.10</version>
143143
</dependency>
144+
<dependency>
145+
<groupId>org.springframework.boot</groupId>
146+
<artifactId>spring-boot-starter-mail</artifactId>
147+
</dependency>
148+
<dependency>
149+
<groupId>org.springframework.boot</groupId>
150+
<artifactId>spring-boot-starter-thymeleaf</artifactId>
151+
</dependency>
152+
<dependency>
153+
<groupId>org.thymeleaf.extras</groupId>
154+
<artifactId>thymeleaf-extras-springsecurity6</artifactId>
155+
</dependency>
144156
</dependencies>
145157

146158
<build>

src/main/java/com/zenfulcode/commercify/commercify/api/requests/RegisterUserRequest.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,17 @@ public record RegisterUserRequest(
99
String password,
1010
String firstName,
1111
String lastName,
12+
Boolean isGuest,
1213
AddressDTO shippingAddress,
1314
AddressDTO billingAddress) {
1415
// Set a secure default password
1516
public RegisterUserRequest {
1617
if (password == null || password.isBlank()) {
1718
password = UUID.randomUUID().toString();
1819
}
20+
21+
if (isGuest == null) {
22+
isGuest = false;
23+
}
1924
}
2025
}

src/main/java/com/zenfulcode/commercify/commercify/component/AdminDataLoader.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ public CommandLineRunner loadData() {
3333
.firstName("Admin")
3434
.lastName("User")
3535
.roles(List.of("ADMIN", "USER"))
36+
.shippingAddress(null)
37+
.billingAddress(null)
38+
.emailConfirmed(true)
3639
.build();
3740

3841
userRepository.save(adminUser);

src/main/java/com/zenfulcode/commercify/commercify/controller/AuthenticationController.java

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,16 @@
44
import com.zenfulcode.commercify.commercify.api.requests.LoginUserRequest;
55
import com.zenfulcode.commercify.commercify.api.requests.RegisterUserRequest;
66
import com.zenfulcode.commercify.commercify.api.responses.AuthResponse;
7-
import com.zenfulcode.commercify.commercify.api.responses.RegisterUserResponse;
87
import com.zenfulcode.commercify.commercify.dto.UserDTO;
98
import com.zenfulcode.commercify.commercify.service.AuthenticationService;
109
import com.zenfulcode.commercify.commercify.service.JwtService;
1110
import lombok.RequiredArgsConstructor;
11+
import lombok.extern.slf4j.Slf4j;
1212
import org.springframework.http.ResponseEntity;
1313
import org.springframework.security.access.prepost.PreAuthorize;
1414
import org.springframework.web.bind.annotation.*;
1515

16+
@Slf4j
1617
@RestController
1718
@RequestMapping("/api/v1/auth")
1819
@RequiredArgsConstructor
@@ -21,13 +22,19 @@ public class AuthenticationController {
2122
private final AuthenticationService authenticationService;
2223

2324
@PostMapping("/signup")
24-
public ResponseEntity<?> register(@RequestBody RegisterUserRequest registerRequest) {
25+
public ResponseEntity<AuthResponse> register(@RequestBody RegisterUserRequest registerRequest) {
2526
try {
2627
UserDTO user = authenticationService.registerUser(registerRequest);
27-
return ResponseEntity.ok(RegisterUserResponse.UserRegistered(user));
28+
29+
if (registerRequest.isGuest()) {
30+
UserDTO authenticated = authenticationService.authenticate(new LoginUserRequest(registerRequest.email(), registerRequest.password()));
31+
String jwt = jwtService.generateToken(authenticated);
32+
return ResponseEntity.ok(AuthResponse.UserAuthenticated(authenticated, jwt, jwtService.getExpirationTime()));
33+
}
34+
35+
return ResponseEntity.ok(AuthResponse.UserAuthenticated(user, "", 0));
2836
} catch (RuntimeException e) {
29-
RegisterUserResponse error = RegisterUserResponse.RegistrationFailed(e.getMessage());
30-
return ResponseEntity.badRequest().body(error);
37+
return ResponseEntity.badRequest().body(AuthResponse.AuthenticationFailed(e.getMessage()));
3138
}
3239
}
3340

src/main/java/com/zenfulcode/commercify/commercify/controller/PaymentController.java

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,36 @@
33
import com.zenfulcode.commercify.commercify.PaymentStatus;
44
import com.zenfulcode.commercify.commercify.service.PaymentService;
55
import lombok.AllArgsConstructor;
6+
import lombok.extern.slf4j.Slf4j;
67
import org.springframework.http.ResponseEntity;
8+
import org.springframework.security.access.prepost.PreAuthorize;
79
import org.springframework.web.bind.annotation.*;
810

911
@CrossOrigin
1012
@RestController
1113
@RequestMapping("/api/v1/payments")
1214
@AllArgsConstructor
15+
@Slf4j
1316
public class PaymentController {
1417
private final PaymentService paymentService;
1518

19+
@PostMapping("/{orderId}/status")
20+
@PreAuthorize("hasRole('ADMIN')")
21+
public ResponseEntity<String> updatePaymentStatus(
22+
@PathVariable Long orderId,
23+
@RequestParam PaymentStatus status) {
24+
try {
25+
paymentService.handlePaymentStatusUpdate(orderId, status);
26+
return ResponseEntity.ok("Payment status updated successfully");
27+
} catch (Exception e) {
28+
log.error("Error updating payment status", e);
29+
return ResponseEntity.badRequest().body("Error updating payment status");
30+
}
31+
}
32+
1633
@GetMapping("/{orderId}/status")
17-
public ResponseEntity<String> getPaymentStatus(@PathVariable Long orderId) {
34+
public ResponseEntity<PaymentStatus> getPaymentStatus(@PathVariable Long orderId) {
1835
PaymentStatus status = paymentService.getPaymentStatus(orderId);
19-
return ResponseEntity.ok(status.name());
36+
return ResponseEntity.ok(status);
2037
}
2138
}
Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
package com.zenfulcode.commercify.commercify.dto;
22

3+
import lombok.AllArgsConstructor;
34
import lombok.Builder;
4-
import lombok.Value;
5-
6-
import java.io.Serializable;
5+
import lombok.Data;
76

87
/**
98
* DTO for {@link com.zenfulcode.commercify.commercify.entity.VariantOptionEntity}
109
*/
11-
@Value
1210
@Builder
13-
public class VariantOptionEntityDto implements Serializable {
14-
Long id;
15-
String name;
16-
String value;
11+
@Data
12+
@AllArgsConstructor
13+
public class VariantOptionEntityDto {
14+
private Long id;
15+
private String name;
16+
private String value;
1717
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package com.zenfulcode.commercify.commercify.entity;
2+
3+
import jakarta.persistence.*;
4+
import lombok.*;
5+
import org.hibernate.annotations.CreationTimestamp;
6+
7+
import java.time.Instant;
8+
import java.util.UUID;
9+
10+
@Entity
11+
@Table(name = "confirmation_tokens")
12+
@Getter
13+
@Setter
14+
@NoArgsConstructor
15+
@AllArgsConstructor
16+
@Builder
17+
public class ConfirmationTokenEntity {
18+
@Id
19+
@GeneratedValue(strategy = GenerationType.IDENTITY)
20+
private Long id;
21+
22+
@Column(nullable = false, unique = true)
23+
private String token;
24+
25+
@Column(nullable = false, name = "expiry_date")
26+
private Instant expiryDate;
27+
28+
@Column(nullable = false)
29+
private boolean confirmed;
30+
31+
@ManyToOne(fetch = FetchType.LAZY)
32+
@JoinColumn(name = "user_id", nullable = false)
33+
private UserEntity user;
34+
35+
@CreationTimestamp
36+
@Column(nullable = false, name = "created_at")
37+
private Instant createdAt;
38+
39+
@PrePersist
40+
public void prePersist() {
41+
if (token == null) {
42+
token = UUID.randomUUID().toString();
43+
}
44+
if (expiryDate == null) {
45+
expiryDate = Instant.now().plusSeconds(24 * 60 * 60); // 24 hours
46+
}
47+
}
48+
}

0 commit comments

Comments
 (0)