1
2
3
4
5
6 package org.tailormap.api.persistence;
7
8 import com.fasterxml.jackson.annotation.JsonIgnore;
9 import com.fasterxml.jackson.annotation.JsonProperty;
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.ZoneId;
24 import java.time.ZonedDateTime;
25 import java.util.ArrayList;
26 import java.util.HashSet;
27 import java.util.List;
28 import java.util.Set;
29 import java.util.stream.Collectors;
30 import org.hibernate.annotations.JdbcTypeCode;
31 import org.hibernate.envers.Audited;
32 import org.hibernate.type.SqlTypes;
33 import org.springframework.data.jpa.domain.support.AuditingEntityListener;
34 import org.tailormap.api.persistence.helper.AdminAdditionalPropertyHelper;
35 import org.tailormap.api.persistence.json.AdminAdditionalProperty;
36 import org.tailormap.api.persistence.listener.EntityEventPublisher;
37 import org.tailormap.api.util.Constants;
38 import org.tailormap.api.util.TMPasswordDeserializer;
39 import tools.jackson.databind.annotation.JsonDeserialize;
40
41 @Audited
42 @Entity
43 @Table(name = "users")
44 @EntityListeners({EntityEventPublisher.class, AuditingEntityListener.class})
45 public class User extends AuditMetadata {
46
47 @Id
48 @Pattern(regexp = Constants.NAME_REGEX, message = "User" + Constants.NAME_REGEX_INVALID_MESSAGE) private String username;
49
50 @Version
51 private Long version;
52
53 @NotNull @JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
54 @JsonDeserialize(using = TMPasswordDeserializer.class)
55
56
57 @Size(max = (8 + 60))
58 private String password;
59
60 @Email private String email;
61
62 private String name;
63
64 private String organisation;
65
66 @Column(columnDefinition = "text")
67 private String notes;
68
69 @Column(columnDefinition = "timestamp with time zone")
70 private ZonedDateTime validUntil;
71
72 private boolean enabled = true;
73
74 @JdbcTypeCode(SqlTypes.JSON)
75 @Column(columnDefinition = "jsonb")
76 private List<AdminAdditionalProperty> additionalProperties = new ArrayList<>();
77
78 @ManyToMany
79 @JoinTable(
80 name = "user_groups",
81 joinColumns = @JoinColumn(name = "username"),
82 inverseJoinColumns = @JoinColumn(name = "group_name"))
83 private Set<Group> groups = new HashSet<>();
84
85 public String getUsername() {
86 return username;
87 }
88
89 public User setUsername(String username) {
90 this.username = username;
91 return this;
92 }
93
94 public Long getVersion() {
95 return version;
96 }
97
98 public User setVersion(Long version) {
99 this.version = version;
100 return this;
101 }
102
103 public String getPassword() {
104 return password;
105 }
106
107 public User setPassword(String passwordHash) {
108 this.password = passwordHash;
109 return this;
110 }
111
112 public String getEmail() {
113 return email;
114 }
115
116 public User setEmail(String email) {
117 this.email = email;
118 return this;
119 }
120
121 public String getName() {
122 return name;
123 }
124
125 public User setName(String name) {
126 this.name = name;
127 return this;
128 }
129
130 public String getOrganisation() {
131 return organisation;
132 }
133
134 public User setOrganisation(String organisation) {
135 this.organisation = organisation;
136 return this;
137 }
138
139 public String getNotes() {
140 return notes;
141 }
142
143 public User setNotes(String notes) {
144 this.notes = notes;
145 return this;
146 }
147
148 public List<AdminAdditionalProperty> getAdditionalProperties() {
149 return additionalProperties;
150 }
151
152 public User setAdditionalProperties(List<AdminAdditionalProperty> additionalProperties) {
153 this.additionalProperties = additionalProperties;
154 return this;
155 }
156
157 public Set<Group> getGroups() {
158 return groups;
159 }
160
161 public User setGroups(Set<Group> groups) {
162 this.groups = groups;
163 return this;
164 }
165
166 public Set<String> getGroupNames() {
167 return groups.stream().map(Group::getName).collect(Collectors.toSet());
168 }
169
170 public ZonedDateTime getValidUntil() {
171 return validUntil;
172 }
173
174 public User setValidUntil(ZonedDateTime validUntil) {
175 this.validUntil = validUntil;
176 return this;
177 }
178
179 public boolean isEnabled() {
180 return enabled;
181 }
182
183 public User setEnabled(boolean enabled) {
184 this.enabled = enabled;
185 return this;
186 }
187
188 public void addOrUpdateAdminProperty(String key, Object value, boolean isPublic) {
189 AdminAdditionalPropertyHelper.addOrUpdateAdminProperty(additionalProperties, key, value, isPublic);
190 }
191
192
193
194
195
196
197 @JsonIgnore
198 public boolean isEnabledAndValidUntil() {
199 return enabled && (validUntil == null || validUntil.isAfter(ZonedDateTime.now(ZoneId.systemDefault())));
200 }
201 }