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.jwt;
23  
24  import org.opencastproject.security.api.GroupProvider;
25  import org.opencastproject.security.api.JaxbOrganization;
26  import org.opencastproject.security.api.JaxbRole;
27  import org.opencastproject.security.api.Role;
28  import org.opencastproject.security.api.SecurityService;
29  import org.opencastproject.security.api.User;
30  import org.opencastproject.security.api.UserProvider;
31  import org.opencastproject.userdirectory.api.AAIRoleProvider;
32  import org.opencastproject.userdirectory.api.UserReferenceProvider;
33  
34  import java.util.ArrayList;
35  import java.util.HashSet;
36  import java.util.Iterator;
37  import java.util.List;
38  import java.util.regex.Pattern;
39  
40  /**
41   * Role provider for users authenticated based on JWTs.
42   */
43  public class JWTRoleProvider implements AAIRoleProvider, GroupProvider {
44  
45    /** Security service */
46    private final SecurityService securityService;
47  
48    /** User reference provider */
49    private final UserReferenceProvider userReferenceProvider;
50  
51    public JWTRoleProvider(SecurityService securityService, UserReferenceProvider userReferenceProvider) {
52      this.securityService = securityService;
53      this.userReferenceProvider = userReferenceProvider;
54    }
55  
56    @Override
57    public Iterator<Role> getRoles() {
58      JaxbOrganization organization = JaxbOrganization.fromOrganization(securityService.getOrganization());
59      HashSet<Role> roles = new HashSet<>();
60      roles.add(new JaxbRole(organization.getAnonymousRole(), organization));
61      roles.addAll(securityService.getUser().getRoles());
62      return roles.iterator();
63    }
64  
65    @Override
66    public List<Role> getRolesForUser(String userName) {
67      ArrayList<Role> roles = new ArrayList<>();
68      User user = userReferenceProvider.loadUser(userName);
69      if (user != null) {
70        roles.addAll(user.getRoles());
71      }
72      return roles;
73    }
74  
75    @Override
76    public String getOrganization() {
77      return UserProvider.ALL_ORGANIZATIONS;
78    }
79  
80    @Override
81    public Iterator<Role> findRoles(String query, Role.Target target, int offset, int limit) {
82      if (query == null) {
83        throw new IllegalArgumentException("Query must be set");
84      }
85      HashSet<Role> foundRoles = new HashSet<Role>();
86      for (Iterator<Role> it = getRoles(); it.hasNext();) {
87        Role role = it.next();
88        if (like(role.getName(), query) || like(role.getDescription(), query)) {
89          foundRoles.add(role);
90        }
91      }
92      return offsetLimitCollection(offset, limit, foundRoles).iterator();
93  
94    }
95  
96    /**
97     * Slices a given hash set with a given offset and a given limit of entries.
98     *
99     * @param offset The offset.
100    * @param limit The limit for the number of entries.
101    * @param entries The original entries.
102    * @return The sliced hash set.
103    */
104   private <T> HashSet<T> offsetLimitCollection(int offset, int limit, HashSet<T> entries) {
105     HashSet<T> result = new HashSet<T>();
106     int i = 0;
107     for (T entry : entries) {
108       if (limit != 0 && result.size() >= limit) {
109         break;
110       }
111       if (i >= offset) {
112         result.add(entry);
113       }
114       i++;
115     }
116     return result;
117   }
118 
119   /**
120    * Evaluates whether a given query matches on a string.
121    *
122    * @param string The string.
123    * @param query The query.
124    * @return <code>true</code> if the query matches, <code>false</code> otherwise.
125    */
126   private boolean like(String string, final String query) {
127     if (string == null) {
128       return false;
129     }
130 
131     String regex = query.replace("_", ".").replace("%", ".*?");
132     Pattern p = Pattern.compile(regex, Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
133     return p.matcher(string).matches();
134   }
135 
136   @Override
137   public List<Role> getRolesForGroup(String groupName) {
138     return null;
139   }
140 
141 }