User.java
package com.seebie.server.entity;
import com.github.f4b6a3.uuid.UuidCreator;
import jakarta.persistence.*;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import java.io.Serializable;
import java.time.Instant;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
@Entity
@Table(name = "app_user", uniqueConstraints = {@UniqueConstraint(columnNames = {"public_id"})})
public class User implements Serializable {
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name = "id", updatable = false, insertable = false, nullable = false)
    private Long id;
    @Column(unique = true, name = "public_id", updatable = false, insertable = true, nullable = false)
    private UUID publicId;
    @NotNull
    private String password = "";
    @NotNull
    @Column(unique=true)
    @Size(min = 3, message = "must be at least three characters")
    private String email = "";
    @NotNull
    @Size(min = 3, message = "must be at least three characters")
    @Column(name="display_name")
    private String displayName = "";
    @Basic
    @NotNull
    private Instant registrationTime;
    @ElementCollection(fetch=FetchType.LAZY, targetClass=Role.class)
    @CollectionTable(name = "user_role", joinColumns = @JoinColumn(name = "user_id"))
    @Column(name = "role_id")
    @Enumerated(EnumType.ORDINAL)
    private Set<Role> roles = new HashSet<>();
    // If we start using more user settings, this could be moved to a settings entity.
    @Basic
    private boolean notificationsEnabled = false;
    /**
     * Since this field isn't a primary key, we can't use Hibernate's generator annotations.
     * Once Postgres supports UUID v7 natively (in PG 18)
     * we can just make that the default value on the column and remove this.
     * Alternatively if we migrate the publicId to be the PK, we can use the generator annotations.
     */
    @PrePersist
    public void ensurePublicIdUuidV7() {
        if (publicId == null) {
            publicId = UuidCreator.getTimeOrderedEpoch();
        }
    }
    protected User() {
        // no arg constructor is required by JPA
    }
    public User(String displayName, String email, String encryptedPassword) {
        this.displayName = displayName;
        this.email = email;
        this.password = encryptedPassword;
        this.registrationTime = Instant.now();
        this.roles.add(Role.USER);
    }
    public User withUserData(String displayName, boolean notificationsEnabled) {
        this.displayName = displayName;
        this.notificationsEnabled = notificationsEnabled;
        return this;
    }
    public UUID getPublicId() {
        return publicId;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public String getEmail() {
        return email;
    }
    public String getDisplayName() {
        return displayName;
    }
    public Set<Role> getRoles() {
        return roles;
    }
    public Instant getRegistrationTime() {
        return registrationTime;
    }
    public boolean isNotificationsEnabled() {
        return notificationsEnabled;
    }
}