TemporaryToken.java
/*
* Copyright (C) 2025 B3Partners B.V.
*
* SPDX-License-Identifier: MIT
*/
package org.tailormap.api.persistence;
import static java.nio.charset.StandardCharsets.UTF_8;
import com.fasterxml.jackson.annotation.JsonIgnore;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import jakarta.validation.constraints.NotNull;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Base64;
import java.util.UUID;
import org.springframework.format.annotation.DateTimeFormat;
@Entity
@Table(name = "temporary_token")
public class TemporaryToken {
public enum TokenType {
PASSWORD_RESET
// we can add other use tokens in the future such as EMAIL_VERIFICATION
}
@Id
@GeneratedValue(strategy = GenerationType.UUID)
private UUID token;
@Enumerated(EnumType.STRING)
@Column(columnDefinition = "varchar(18) not null")
@NotNull private TokenType tokenType;
@NotNull private String username;
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
@NotNull private ZonedDateTime expirationTime;
public TemporaryToken() {
// Default constructor for JPA
}
public TemporaryToken(@NotNull TokenType tokenType, @NotNull String username, int expirationMinutes) {
this.tokenType = tokenType;
this.username = username;
this.expirationTime = ZonedDateTime.now(ZoneId.of("UTC")).plusMinutes(expirationMinutes);
}
@NotNull public UUID getToken() {
return token;
}
public TemporaryToken setToken(UUID token) {
this.token = token;
return this;
}
public TokenType getTokenType() {
return tokenType;
}
public TemporaryToken setTokenType(TokenType tokenType) {
this.tokenType = tokenType;
return this;
}
public String getUsername() {
return username;
}
public TemporaryToken setUsername(String username) {
this.username = username;
return this;
}
public ZonedDateTime getExpirationTime() {
return expirationTime;
}
public TemporaryToken setExpirationTime(ZonedDateTime expirationTime) {
this.expirationTime = expirationTime;
return this;
}
/**
* Get the token and expiration time as a base64 encoded string. The format before encoding is:
* token#expirationEpochSeconds.
*
* @return base64 encoded token and expiration time
*/
@JsonIgnore
@NotNull public String getCombinedTokenAndExpirationAsBase64() {
return Base64.getEncoder()
.encodeToString((this.token + "#" + this.expirationTime.toEpochSecond()).getBytes(UTF_8));
}
}