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