Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/main/java/com/wallet/secure/audit/entity/AuditLog.java
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ public class AuditLog {
* Supports both IPv4 and IPv6.
* OWASP A09: essential for geographic anomaly detection and forensics.
*/
@JdbcTypeCode(SqlTypes.INET)
@Column(name = "ip_address")
private String ipAddress;

Expand Down
3 changes: 3 additions & 0 deletions src/main/java/com/wallet/secure/auth/entity/Session.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import com.wallet.secure.user.entity.User;
import jakarta.persistence.*;
import lombok.*;
import org.hibernate.annotations.JdbcTypeCode;
import org.hibernate.type.SqlTypes;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

Expand Down Expand Up @@ -87,6 +89,7 @@ public class Session {
* OWASP A07: enables geographic anomaly detection.
* Example: session created in Colombia, refresh from Russia → suspicious.
*/
@JdbcTypeCode(SqlTypes.INET)
@Column(name = "ip_address")
private String ipAddress;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ public class AdminBootstrapProperties {
@NotBlank(message = "Contraseña obligatoria")
@Size(min = 12, max = 72, message = "La contraseña debe tener entre 12 y 72 caracteres")
@Pattern(
regexp = "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[@$!%*?&_.#^])[A-Za-z\\d@$!%*?&_.#^]{12,72}$",
// Do not whitelist symbols: passwords from password managers may contain /, +, =, etc.
regexp = "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[^A-Za-z0-9\\s])\\S{12,72}$",
message = "La contraseña debe incluir mayúscula, minúscula, número y carácter especial"
)
private String password;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ public class RegisterRequest {
@NotBlank(message = "Password is required")
@Size(min = 12, max = 72, message = "Password must be between 12 and 72 characters")
@Pattern(
regexp = "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[@$!%*?&_.#^])[A-Za-z\\d@$!%*?&_.#^]{12,}$",
// OWASP: do not restrict the symbols a password manager may generate.
regexp = "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[^A-Za-z0-9\\s])\\S{12,72}$",
message = "Password must contain uppercase, lowercase, number and special character"
)
private String password;
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/wallet/secure/wallet/entity/Wallet.java
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ public class Wallet {
private Instant createdAt;

@LastModifiedDate
@Column(name = "update_at", nullable = false)
@Column(name = "updated_at", nullable = false)
private Instant updateAt;

// --- Business Methods
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,10 @@ void disabledBootstrapDoesNotQueryOrCreateUser() throws Exception {
void validBootstrapCreatesVerifiedAdminWithEncodedPassword() throws Exception {
properties.setEnabled(true);
properties.setEmail("admin@example.test");
properties.setPassword("StrongPass1!");
properties.setPassword("Strong/Pass1!");
when(userRepository.existsByRole(UserRole.ADMIN)).thenReturn(false);
when(userRepository.existsByEmail("admin@example.test")).thenReturn(false);
when(passwordEncoder.encode("StrongPass1!")).thenReturn("$2a$12$encoded");
when(passwordEncoder.encode("Strong/Pass1!")).thenReturn("$2a$12$encoded");

service.run(new DefaultApplicationArguments());

Expand All @@ -74,15 +74,15 @@ void validBootstrapCreatesVerifiedAdminWithEncodedPassword() throws Exception {
assertThat(saved.getEmail()).isEqualTo("admin@example.test");
assertThat(saved.getPasswordHash()).isEqualTo("$2a$12$encoded");
assertThat(saved.getEmailVerified()).isTrue();
verify(passwordEncoder).encode("StrongPass1!");
verify(passwordEncoder).encode("Strong/Pass1!");
}

@Test
/** Idempotency prevents a restart from creating or replacing another ADMIN. */
void existingAdminPreventsSecondAdmin() throws Exception {
properties.setEnabled(true);
properties.setEmail("admin@example.test");
properties.setPassword("StrongPass1!");
properties.setPassword("Strong/Pass1!");
when(userRepository.existsByRole(UserRole.ADMIN)).thenReturn(true);

service.run(new DefaultApplicationArguments());
Expand Down
Loading