1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.opencastproject.userdirectory;
23
24 import org.opencastproject.security.api.JaxbOrganization;
25 import org.opencastproject.security.api.JaxbRole;
26 import org.opencastproject.security.api.Organization;
27 import org.opencastproject.security.api.Role;
28 import org.opencastproject.security.api.RoleProvider;
29 import org.opencastproject.security.api.SecurityService;
30 import org.opencastproject.security.api.User;
31 import org.opencastproject.security.api.UserDirectoryService;
32 import org.opencastproject.security.api.UserProvider;
33 import org.opencastproject.util.OsgiUtil;
34 import org.opencastproject.util.data.Option;
35
36 import com.google.common.base.CharMatcher;
37
38 import org.apache.commons.lang3.BooleanUtils;
39 import org.osgi.service.cm.ConfigurationException;
40 import org.osgi.service.cm.ManagedService;
41 import org.osgi.service.component.annotations.Component;
42 import org.osgi.service.component.annotations.Reference;
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
45
46 import java.util.ArrayList;
47 import java.util.Collections;
48 import java.util.Dictionary;
49 import java.util.HashSet;
50 import java.util.Iterator;
51 import java.util.List;
52 import java.util.regex.Pattern;
53
54
55
56
57 @Component(
58 property = {
59 "service.description=Provides the user id role"
60 },
61 immediate = true,
62 service = { RoleProvider.class, UserIdRoleProvider.class, ManagedService.class }
63 )
64 public class UserIdRoleProvider implements RoleProvider, ManagedService {
65
66
67 private static final String ROLE_USER = "ROLE_USER";
68
69 private static final String ROLE_USER_PREFIX_KEY = "role.user.prefix";
70 private static final String DEFAULT_ROLE_USER_PREFIX = "ROLE_USER_";
71
72 private static final String SANITIZE_KEY = "sanitize";
73 private static final boolean DEFAULT_SANITIZE = true;
74
75 private static final CharMatcher SAFE_USERNAME = CharMatcher.inRange('a', 'z').or(CharMatcher.inRange('A', 'Z'))
76 .or(CharMatcher.inRange('0', '9')).negate().precomputed();
77
78
79 private static final Logger logger = LoggerFactory.getLogger(UserIdRoleProvider.class);
80
81
82 protected SecurityService securityService = null;
83
84 private static String userRolePrefix = DEFAULT_ROLE_USER_PREFIX;
85 private static boolean sanitize = DEFAULT_SANITIZE;
86
87
88 protected UserDirectoryService userDirectoryService = null;
89
90
91
92
93
94 @Reference
95 public void setSecurityService(SecurityService securityService) {
96 this.securityService = securityService;
97 }
98
99
100
101
102
103
104
105 @Reference
106 public void setUserDirectoryService(UserDirectoryService userDirectoryService) {
107 this.userDirectoryService = userDirectoryService;
108 }
109
110 public static boolean isSanitize() {
111 return sanitize;
112 };
113
114 public static String getUserRolePrefix() {
115 return userRolePrefix;
116 };
117
118 public static String getUserIdRole(String userName) {
119 if (sanitize) {
120 userName = SAFE_USERNAME.replaceFrom(userName, "_").toUpperCase();
121 }
122 return userRolePrefix.concat(userName);
123 }
124
125
126
127
128 @Override
129 public List<Role> getRolesForUser(String userName) {
130 Organization organization = securityService.getOrganization();
131 List<Role> roles = new ArrayList<Role>();
132 roles.add(new JaxbRole(
133 getUserIdRole(userName),
134 JaxbOrganization.fromOrganization(organization),
135 "The user id role",
136 Role.Type.SYSTEM
137 ));
138 roles.add(new JaxbRole(
139 ROLE_USER,
140 JaxbOrganization.fromOrganization(organization),
141 "The authenticated user role",
142 Role.Type.SYSTEM
143 ));
144 return Collections.unmodifiableList(roles);
145 }
146
147
148
149
150 @Override
151 public String getOrganization() {
152 return UserProvider.ALL_ORGANIZATIONS;
153 }
154
155
156
157
158 @Override
159 public Iterator<Role> findRoles(String query, Role.Target target, int offset, int limit) {
160 if (query == null) {
161 throw new IllegalArgumentException("Query must be set");
162 }
163
164
165 if (target == Role.Target.USER) {
166 return Collections.emptyIterator();
167 }
168
169 logger.debug("findRoles(query={} offset={} limit={})", query, offset, limit);
170
171 HashSet<Role> foundRoles = new HashSet<Role>();
172 Organization organization = securityService.getOrganization();
173
174
175 if (like(ROLE_USER, query)) {
176 foundRoles.add(new JaxbRole(
177 ROLE_USER,
178 JaxbOrganization.fromOrganization(organization),
179 "The authenticated user role",
180 Role.Type.SYSTEM
181 ));
182 }
183
184
185
186 if (!"%".equals(query) && !query.startsWith(userRolePrefix)) {
187 return foundRoles.iterator();
188 }
189
190 String userQuery = "%";
191 if (query.startsWith(userRolePrefix)) {
192 userQuery = query.substring(userRolePrefix.length());
193 }
194
195 Iterator<User> users = userDirectoryService.findUsers(userQuery, offset, limit);
196 while (users.hasNext()) {
197 User u = users.next();
198
199 if (!"system".equals(u.getProvider())) {
200 foundRoles.add(new JaxbRole(
201 getUserIdRole(u.getUsername()),
202 JaxbOrganization.fromOrganization(u.getOrganization()),
203 "User id role",
204 Role.Type.SYSTEM
205 ));
206 }
207 }
208
209 return foundRoles.iterator();
210 }
211
212 private static boolean like(String string, final String query) {
213 if (string == null) {
214 return false;
215 }
216 String regex = query.replace("_", ".").replace("%", ".*?");
217 Pattern p = Pattern.compile(regex, Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
218 return p.matcher(string).matches();
219 }
220
221 @Override
222 public void updated(Dictionary properties) throws ConfigurationException {
223 Option<String> userPrefixProperty = OsgiUtil.getOptCfg(properties, ROLE_USER_PREFIX_KEY);
224 if (userPrefixProperty.isSome()) {
225 userRolePrefix = userPrefixProperty.get();
226 logger.info("Using configured userRole prefix '{}'", userRolePrefix);
227 } else {
228 userRolePrefix = DEFAULT_ROLE_USER_PREFIX;
229 logger.info("Using default userRole prefix '{}'", userRolePrefix);
230 }
231
232 Option<String> sanitizeProperty = OsgiUtil.getOptCfg(properties, SANITIZE_KEY);
233 if (sanitizeProperty.isSome()) {
234 sanitize = BooleanUtils.toBoolean(sanitizeProperty.get());
235 logger.info("Using configured will sanitize user names '{}'", sanitize);
236 } else {
237 sanitize = DEFAULT_SANITIZE;
238 logger.info("Using default for sanitizing user names '{}'", sanitize);
239 }
240 }
241
242 }