View Javadoc
1   /*
2    * Copyright (C) 2023 B3Partners B.V.
3    *
4    * SPDX-License-Identifier: MIT
5    */
6   package org.tailormap.api.persistence;
7   
8   import com.fasterxml.jackson.annotation.JsonProperty;
9   import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
10  import jakarta.persistence.Column;
11  import jakarta.persistence.Entity;
12  import jakarta.persistence.EntityListeners;
13  import jakarta.persistence.Id;
14  import jakarta.persistence.JoinColumn;
15  import jakarta.persistence.JoinTable;
16  import jakarta.persistence.ManyToMany;
17  import jakarta.persistence.Table;
18  import jakarta.persistence.Version;
19  import jakarta.validation.constraints.Email;
20  import jakarta.validation.constraints.NotNull;
21  import jakarta.validation.constraints.Pattern;
22  import jakarta.validation.constraints.Size;
23  import java.time.ZonedDateTime;
24  import java.util.ArrayList;
25  import java.util.HashSet;
26  import java.util.List;
27  import java.util.Set;
28  import org.hibernate.annotations.Type;
29  import org.tailormap.api.persistence.json.AdminAdditionalProperty;
30  import org.tailormap.api.persistence.listener.EntityEventPublisher;
31  import org.tailormap.api.util.Constants;
32  import org.tailormap.api.util.TMPasswordDeserializer;
33  
34  @Entity
35  @Table(name = "users")
36  @EntityListeners(EntityEventPublisher.class)
37  public class User {
38  
39    @Id
40    @Pattern(regexp = Constants.NAME_REGEX, message = "User" + Constants.NAME_REGEX_INVALID_MESSAGE)
41    private String username;
42  
43    @Version private Long version;
44  
45    @NotNull
46    @JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
47    @JsonDeserialize(using = TMPasswordDeserializer.class)
48    // bcrypt MAX/MIN length is 60 + {bcrypt} token, but for testing we use shorter plain text
49    // passwords
50    @Size(max = (8 + 60))
51    private String password;
52  
53    @Email private String email;
54  
55    private String name;
56  
57    @Column(columnDefinition = "text")
58    private String notes;
59  
60    @Column(columnDefinition = "timestamp with time zone")
61    private ZonedDateTime validUntil;
62  
63    private boolean enabled = true;
64  
65    @Type(value = io.hypersistence.utils.hibernate.type.json.JsonBinaryType.class)
66    @Column(columnDefinition = "jsonb")
67    private List<AdminAdditionalProperty> additionalProperties = new ArrayList<>();
68  
69    @ManyToMany
70    @JoinTable(
71        name = "user_groups",
72        joinColumns = @JoinColumn(name = "username"),
73        inverseJoinColumns = @JoinColumn(name = "group_name"))
74    private Set<Group> groups = new HashSet<>();
75  
76    public String getUsername() {
77      return username;
78    }
79  
80    public User setUsername(String username) {
81      this.username = username;
82      return this;
83    }
84  
85    public Long getVersion() {
86      return version;
87    }
88  
89    public User setVersion(Long version) {
90      this.version = version;
91      return this;
92    }
93  
94    public String getPassword() {
95      return password;
96    }
97  
98    public User setPassword(String passwordHash) {
99      this.password = passwordHash;
100     return this;
101   }
102 
103   public String getEmail() {
104     return email;
105   }
106 
107   public User setEmail(String email) {
108     this.email = email;
109     return this;
110   }
111 
112   public String getName() {
113     return name;
114   }
115 
116   public User setName(String name) {
117     this.name = name;
118     return this;
119   }
120 
121   public String getNotes() {
122     return notes;
123   }
124 
125   public User setNotes(String notes) {
126     this.notes = notes;
127     return this;
128   }
129 
130   public List<AdminAdditionalProperty> getAdditionalProperties() {
131     return additionalProperties;
132   }
133 
134   public User setAdditionalProperties(List<AdminAdditionalProperty> additionalProperties) {
135     this.additionalProperties = additionalProperties;
136     return this;
137   }
138 
139   public Set<Group> getGroups() {
140     return groups;
141   }
142 
143   public User setGroups(Set<Group> groups) {
144     this.groups = groups;
145     return this;
146   }
147 
148   public Set<String> getGroupNames() {
149     return groups.stream().map(Group::getName).collect(java.util.stream.Collectors.toSet());
150   }
151 
152   public ZonedDateTime getValidUntil() {
153     return validUntil;
154   }
155 
156   public User setValidUntil(ZonedDateTime validUntil) {
157     this.validUntil = validUntil;
158     return this;
159   }
160 
161   public boolean isEnabled() {
162     return enabled;
163   }
164 
165   public User setEnabled(boolean enabled) {
166     this.enabled = enabled;
167     return this;
168   }
169 }