1
2
3
4
5
6
7 package ch.colabproject.colab.api.model.team;
8
9 import ch.colabproject.colab.api.exceptions.ColabMergeException;
10 import ch.colabproject.colab.api.model.ColabEntity;
11 import ch.colabproject.colab.api.model.WithWebsocketChannels;
12 import ch.colabproject.colab.api.model.common.DeletionStatus;
13 import ch.colabproject.colab.api.model.common.Tracking;
14 import ch.colabproject.colab.api.model.project.Project;
15 import ch.colabproject.colab.api.model.team.acl.Assignment;
16 import ch.colabproject.colab.api.model.team.acl.HierarchicalPosition;
17 import ch.colabproject.colab.api.model.tools.EntityHelper;
18 import ch.colabproject.colab.api.model.user.User;
19 import ch.colabproject.colab.api.security.permissions.Conditions;
20 import ch.colabproject.colab.api.ws.channel.tool.ChannelsBuilders.ChannelsBuilder;
21 import ch.colabproject.colab.api.ws.channel.tool.ChannelsBuilders.EmptyChannelBuilder;
22 import java.util.ArrayList;
23 import java.util.List;
24 import java.util.stream.Collectors;
25 import javax.json.bind.annotation.JsonbTransient;
26 import javax.persistence.CascadeType;
27 import javax.persistence.Embedded;
28 import javax.persistence.Entity;
29 import javax.persistence.EnumType;
30 import javax.persistence.Enumerated;
31 import javax.persistence.FetchType;
32 import javax.persistence.GeneratedValue;
33 import javax.persistence.GenerationType;
34 import javax.persistence.Id;
35 import javax.persistence.Index;
36 import javax.persistence.JoinTable;
37 import javax.persistence.ManyToMany;
38 import javax.persistence.ManyToOne;
39 import javax.persistence.NamedQuery;
40 import javax.persistence.OneToMany;
41 import javax.persistence.SequenceGenerator;
42 import javax.persistence.Table;
43 import javax.persistence.Transient;
44 import javax.validation.constraints.NotNull;
45 import javax.validation.constraints.Size;
46 import org.apache.commons.collections4.CollectionUtils;
47
48
49
50
51
52
53 @Entity
54 @Table(
55 indexes = {
56 @Index(columnList = "project_id,user_id", unique = true),
57 @Index(columnList = "project_id"),
58 @Index(columnList = "user_id")
59 }
60 )
61 @NamedQuery(
62 name = "TeamMember.areUserTeammate",
63
64 query = "SELECT true FROM TeamMember a "
65 + "JOIN TeamMember b ON a.project.id = b.project.id "
66 + "WHERE a.user.id = :aUserId AND b.user.id = :bUserId")
67 @NamedQuery(
68 name = "TeamMember.findByProjectAndUser",
69 query = "SELECT m FROM TeamMember m "
70 + "WHERE m.project.id = :projectId "
71 + "AND m.user IS NOT NULL AND m.user.id = :userId"
72 )
73 @NamedQuery(
74 name = "TeamMember.findByUser",
75 query = "SELECT m FROM TeamMember m "
76 + "WHERE m.user IS NOT NULL AND m.user.id = :userId")
77 public class TeamMember implements ColabEntity, WithWebsocketChannels {
78
79 private static final long serialVersionUID = 1L;
80
81
82 public static final String TEAM_SEQUENCE_NAME = "team_seq";
83
84
85
86
87
88
89
90
91 @Id
92 @SequenceGenerator(name = TEAM_SEQUENCE_NAME, allocationSize = 20)
93 @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = TEAM_SEQUENCE_NAME)
94 private Long id;
95
96
97
98
99 @Embedded
100 private Tracking trackingData;
101
102
103
104
105 @Enumerated(EnumType.STRING)
106 private DeletionStatus deletionStatus;
107
108
109
110
111 @Size(max = 255)
112 private String displayName;
113
114
115
116
117 @NotNull
118 @Enumerated(value = EnumType.STRING)
119 private HierarchicalPosition position = HierarchicalPosition.INTERNAL;
120
121
122
123
124 @ManyToOne(fetch = FetchType.LAZY)
125 @JsonbTransient
126 private User user;
127
128
129
130
131 @Transient
132 private Long userId;
133
134
135
136
137 @ManyToOne(fetch = FetchType.LAZY)
138 @NotNull
139 @JsonbTransient
140 private Project project;
141
142
143
144
145 @Transient
146 private Long projectId;
147
148
149
150
151 @ManyToMany
152 @JoinTable(indexes = {
153 @Index(columnList = "members_id"),
154 @Index(columnList = "roles_id"),
155 })
156 @JsonbTransient
157 private List<TeamRole> roles = new ArrayList<>();
158
159
160
161
162 @NotNull
163 @Transient
164 private List<Long> roleIds = new ArrayList<>();
165
166
167
168
169 @OneToMany(mappedBy = "member", cascade = CascadeType.ALL)
170 @JsonbTransient
171 private List<Assignment> assignments = new ArrayList<>();
172
173
174
175
176
177
178
179
180 @Override
181 public Long getId() {
182 return id;
183 }
184
185
186
187
188 public void setId(Long id) {
189 this.id = id;
190 }
191
192
193
194
195
196
197 @Override
198 public Tracking getTrackingData() {
199 return trackingData;
200 }
201
202
203
204
205
206
207 @Override
208 public void setTrackingData(Tracking trackingData) {
209 this.trackingData = trackingData;
210 }
211
212 @Override
213 public DeletionStatus getDeletionStatus() {
214 return deletionStatus;
215 }
216
217 @Override
218 public void setDeletionStatus(DeletionStatus status) {
219 this.deletionStatus = status;
220 }
221
222
223
224
225
226
227 public String getDisplayName() {
228 return displayName;
229 }
230
231
232
233
234
235
236 public void setDisplayName(String displayName) {
237 this.displayName = displayName;
238 }
239
240
241
242
243
244
245 public HierarchicalPosition getPosition() {
246 return position;
247 }
248
249
250
251
252
253
254 public void setPosition(HierarchicalPosition position) {
255 this.position = position;
256 }
257
258
259
260
261 public User getUser() {
262 return user;
263 }
264
265
266
267
268 public void setUser(User user) {
269 this.user = user;
270 }
271
272
273
274
275
276
277 public Long getUserId() {
278 if (this.user != null) {
279 return this.user.getId();
280 } else {
281 return userId;
282 }
283 }
284
285
286
287
288
289
290 public void setUserId(Long id) {
291 this.userId = id;
292 }
293
294
295
296
297 public Project getProject() {
298 return project;
299 }
300
301
302
303
304 public void setProject(Project project) {
305 this.project = project;
306 }
307
308
309
310
311
312
313 public Long getProjectId() {
314 if (this.project != null) {
315 return this.project.getId();
316 } else {
317 return projectId;
318 }
319 }
320
321
322
323
324
325
326 public void setProjectId(Long id) {
327 this.projectId = id;
328 }
329
330
331
332
333
334
335 public List<TeamRole> getRoles() {
336 return roles;
337 }
338
339
340
341
342
343
344 public void setRoles(List<TeamRole> roles) {
345 this.roles = roles;
346 }
347
348
349
350
351
352
353 public List<Long> getRoleIds() {
354 if (!CollectionUtils.isEmpty(this.roles)) {
355 return roles.stream()
356 .map(role -> role.getId())
357 .collect(Collectors.toList());
358 }
359 return roleIds;
360 }
361
362
363
364
365
366
367 public void setRoleIds(List<Long> roleIds) {
368 this.roleIds = roleIds;
369 }
370
371
372
373
374
375
376 public List<Assignment> getAssignments() {
377 return assignments;
378 }
379
380
381
382
383
384
385 public void setAssignments(List<Assignment> assignments) {
386 this.assignments = assignments;
387 }
388
389
390
391
392
393 @Override
394 public void mergeToUpdate(ColabEntity other) throws ColabMergeException {
395 if (other instanceof TeamMember) {
396 TeamMember o = (TeamMember) other;
397 this.setDeletionStatus(o.getDeletionStatus());
398 this.setDisplayName(o.getDisplayName());
399 } else {
400 throw new ColabMergeException(this, other);
401 }
402 }
403
404 @Override
405 public void mergeToDuplicate(ColabEntity other) throws ColabMergeException {
406 if (other instanceof TeamMember) {
407 TeamMember o = (TeamMember) other;
408 this.setDeletionStatus(o.getDeletionStatus());
409 this.setDisplayName(o.getDisplayName());
410 this.setPosition(o.getPosition());
411 } else {
412 throw new ColabMergeException(this, other);
413 }
414 }
415
416 @Override
417 public ChannelsBuilder getChannelsBuilder() {
418 if (this.project != null) {
419 return this.project.getChannelsBuilder();
420 } else {
421
422 return new EmptyChannelBuilder();
423 }
424 }
425
426 @Override
427 @JsonbTransient
428 public Conditions.Condition getReadCondition() {
429 if (this.user != null && this.project != null) {
430 return new Conditions.IsCurrentUserMemberOfProject(project);
431 } else {
432
433 return Conditions.alwaysTrue;
434 }
435 }
436
437 @Override
438 @JsonbTransient
439 public Conditions.Condition getUpdateCondition() {
440 if (this.user != null && this.project != null) {
441 return new Conditions.IsCurrentUserInternalToProject(project);
442 } else {
443
444 return Conditions.alwaysTrue;
445 }
446 }
447
448 @Override
449 @JsonbTransient
450 public Conditions.Condition getCreateCondition() {
451 if (this.project != null) {
452
453 return new Conditions.IsCurrentUserInternalToProject(project);
454 } else {
455 return Conditions.alwaysFalse;
456 }
457 }
458
459 @Override
460 public int hashCode() {
461 return EntityHelper.hashCode(this);
462 }
463
464 @Override
465 @SuppressWarnings("EqualsWhichDoesntCheckParameterClass")
466 public boolean equals(Object obj) {
467 return EntityHelper.equals(this, obj);
468 }
469
470 @Override
471 public String toString() {
472 if (user == null) {
473 return "TeamMember{pending}";
474 } else {
475 return "TeamMember{" + "id=" + id + ", deletion=" + getDeletionStatus()
476 + ", userId=" + userId + ", projectId=" + projectId + "}";
477 }
478 }
479
480 }