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