View Javadoc
1   /*
2    * Licensed to The Apereo Foundation under one or more contributor license
3    * agreements. See the NOTICE file distributed with this work for additional
4    * information regarding copyright ownership.
5    *
6    *
7    * The Apereo Foundation licenses this file to you under the Educational
8    * Community License, Version 2.0 (the "License"); you may not use this file
9    * except in compliance with the License. You may obtain a copy of the License
10   * at:
11   *
12   *   http://opensource.org/licenses/ecl2.txt
13   *
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
16   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
17   * License for the specific language governing permissions and limitations under
18   * the License.
19   *
20   */
21  
22  package org.opencastproject.security.impl.jpa;
23  
24  import org.opencastproject.security.api.Group;
25  import org.opencastproject.security.api.Role;
26  import org.opencastproject.util.EqualsUtil;
27  
28  import java.util.HashSet;
29  import java.util.Set;
30  import java.util.stream.Collectors;
31  
32  import javax.persistence.Access;
33  import javax.persistence.AccessType;
34  import javax.persistence.CascadeType;
35  import javax.persistence.CollectionTable;
36  import javax.persistence.Column;
37  import javax.persistence.ElementCollection;
38  import javax.persistence.Entity;
39  import javax.persistence.FetchType;
40  import javax.persistence.GeneratedValue;
41  import javax.persistence.Id;
42  import javax.persistence.JoinColumn;
43  import javax.persistence.JoinTable;
44  import javax.persistence.ManyToMany;
45  import javax.persistence.NamedQueries;
46  import javax.persistence.NamedQuery;
47  import javax.persistence.OneToOne;
48  import javax.persistence.Table;
49  import javax.persistence.UniqueConstraint;
50  
51  /**
52   * JPA-annotated group object.
53   */
54  @Entity
55  @Access(AccessType.FIELD)
56  @Table(
57      name = "oc_group",
58      uniqueConstraints = { @UniqueConstraint(columnNames = { "group_id", "organization" }) }
59  )
60  @NamedQueries({
61      @NamedQuery(
62          name = "Group.findAll",
63          query = "Select g FROM JpaGroup g WHERE g.organization.id = :organization"
64      ),
65      @NamedQuery(
66          name = "Group.findByUser",
67          query = "Select g FROM JpaGroup g WHERE g.organization.id = :organization AND :username MEMBER OF g.members"
68      ),
69      @NamedQuery(
70          name = "Group.findById",
71          query = "Select g FROM JpaGroup g WHERE g.groupId = :groupId AND g.organization.id = :organization"
72      ),
73      @NamedQuery(
74          name = "Group.findByRole",
75          query = "Select g FROM JpaGroup g WHERE g.role = :role AND g.organization.id = :organization"
76      ),
77  })
78  public final class JpaGroup implements Group {
79    @Id
80    @GeneratedValue
81    @Column(name = "id")
82    private Long id;
83  
84    @Column(name = "group_id", length = 128)
85    private String groupId;
86  
87    @Column(name = "name", length = 128)
88    private String name;
89  
90    @OneToOne()
91    @JoinColumn(name = "organization")
92    private JpaOrganization organization;
93  
94    @Column(name = "description")
95    private String description;
96  
97    @Column(name = "role")
98    private String role;
99  
100   @ElementCollection
101   @CollectionTable(name = "oc_group_member", joinColumns = {
102       @JoinColumn(name = "group_id", nullable = false) })
103   @Column(name = "member")
104   private Set<String> members;
105 
106   @ManyToMany(cascade = { CascadeType.MERGE }, fetch = FetchType.LAZY)
107   @JoinTable(name = "oc_group_role", joinColumns = {
108       @JoinColumn(name = "group_id")
109       }, inverseJoinColumns = {
110       @JoinColumn(name = "role_id")
111       }, uniqueConstraints = {
112       @UniqueConstraint(name = "UNQ_oc_group_role", columnNames = { "group_id", "role_id" }) })
113   private Set<JpaRole> roles;
114 
115   /**
116    * No-arg constructor needed by JPA
117    */
118   public JpaGroup() {
119   }
120 
121   /**
122    * Constructs a group with the specified groupId, name, description and group role.
123    *
124    * @param groupId
125    *          the group id
126    * @param organization
127    *          the organization
128    * @param name
129    *          the name
130    * @param description
131    *          the description
132    * @throws IllegalArgumentException
133    *           if group id or name is longer than 128 Bytes
134    */
135   public JpaGroup(String groupId, JpaOrganization organization, String name, String description)
136           throws IllegalArgumentException {
137     super();
138     if (groupId.length() > 128) {
139       throw new IllegalArgumentException("Group id must not be longer than 128 Bytes");
140     }
141     if (name.length() > 128) {
142       throw new IllegalArgumentException("Name must not be longer than 128 Bytes");
143     }
144     this.groupId = groupId;
145     this.organization = organization;
146     this.name = name;
147     this.description = description;
148     this.role = ROLE_PREFIX + groupId.toUpperCase();
149     this.roles = new HashSet<JpaRole>();
150   }
151 
152   /**
153    * Constructs a group with the specified groupId, name, description, group role and roles.
154    *
155    * @param groupId
156    *          the group id
157    * @param organization
158    *          the organization
159    * @param name
160    *          the name
161    * @param description
162    *          the description
163    * @param roles
164    *          the additional group roles
165    * @throws IllegalArgumentException
166    *           if group id or name is longer than 128 Bytes
167    */
168   public JpaGroup(String groupId, JpaOrganization organization, String name, String description, Set<JpaRole> roles)
169           throws IllegalArgumentException {
170     this(groupId, organization, name, description);
171     this.roles = roles;
172   }
173 
174   /**
175    * Constructs a group with the specified groupId, name, description, group role and roles.
176    *
177    * @param groupId
178    *          the group id
179    * @param organization
180    *          the organization
181    * @param name
182    *          the name
183    * @param description
184    *          the description
185    * @param roles
186    *          the additional group roles
187    * @param members
188    *          the group members
189    * @throws IllegalArgumentException
190    *           if group id or name is longer than 128 Bytes
191    */
192   public JpaGroup(String groupId, JpaOrganization organization, String name, String description, Set<JpaRole> roles,
193           Set<String> members) throws IllegalArgumentException {
194     this(groupId, organization, name, description, roles);
195     this.members = members;
196   }
197 
198   /**
199    * @see org.opencastproject.security.api.Group#getGroupId()
200    */
201   @Override
202   public String getGroupId() {
203     return groupId;
204   }
205 
206   /**
207    * @see org.opencastproject.security.api.Group#getName()
208    */
209   @Override
210   public String getName() {
211     return name;
212   }
213 
214   /**
215    * Sets the group name
216    *
217    * @param name
218    *          the name
219    */
220   public void setName(String name) {
221     this.name = name;
222   }
223 
224   /**
225    * @see org.opencastproject.security.api.Group#getOrganization()
226    */
227   @Override
228   public JpaOrganization getOrganization() {
229     return organization;
230   }
231 
232   /**
233    * @see org.opencastproject.security.api.Group#getDescription()
234    */
235   @Override
236   public String getDescription() {
237     return description;
238   }
239 
240   /**
241    * Sets the description
242    *
243    * @param description
244    *          the description
245    */
246   public void setDescription(String description) {
247     this.description = description;
248   }
249 
250   @Override
251   public String getRole() {
252     return role;
253   }
254 
255   @Override
256   public Set<String> getMembers() {
257     return members;
258   }
259 
260   /**
261    * Sets the members
262    *
263    * @param members
264    *          the members
265    */
266   public void setMembers(Set<String> members) {
267     this.members = members;
268   }
269 
270   /**
271    * Add a member
272    *
273    * @param member
274    *          The member's name.
275    */
276   public void addMember(String member) {
277     if (members == null) {
278       members = new HashSet<>();
279     }
280     members.add(member);
281   }
282 
283   /**
284    * Remove a member
285    *
286    * @param member
287    *          The member's name.
288    */
289   public void removeMember(String member) {
290     if (members != null) {
291       members.remove(member);
292     }
293   }
294 
295   @Override
296   public Set<Role> getRoles() {
297     return new HashSet<Role>(roles);
298   }
299 
300   /**
301    * Get only the names of the roles
302    *
303    * @return the role names in a set
304    */
305   public Set<String> getRoleNames() {
306     return roles.stream().map(role -> role.getName()).collect(Collectors.toSet());
307   }
308 
309   /**
310    * Sets the roles
311    *
312    * @param roles
313    *          the roles
314    */
315   public void setRoles(Set<JpaRole> roles) {
316     this.roles = roles;
317   }
318 
319   @Override
320   public int hashCode() {
321     return EqualsUtil.hash(id, organization);
322   }
323 
324   @Override
325   public boolean equals(Object obj) {
326     if (!(obj instanceof Group)) {
327       return false;
328     }
329     Group other = (Group) obj;
330     return groupId.equals(other.getGroupId()) && organization.equals(other.getOrganization());
331   }
332 
333   @Override
334   public String toString() {
335     return new StringBuilder(groupId).append(":").append(organization).toString();
336   }
337 
338 }