1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.opencastproject.security.aai;
22
23 import org.opencastproject.security.aai.api.AttributeMapper;
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.Organization;
28 import org.opencastproject.security.api.Role;
29 import org.opencastproject.security.api.SecurityService;
30 import org.opencastproject.security.api.User;
31 import org.opencastproject.security.api.UserProvider;
32 import org.opencastproject.security.impl.jpa.JpaOrganization;
33 import org.opencastproject.security.impl.jpa.JpaRole;
34 import org.opencastproject.security.impl.jpa.JpaUserReference;
35 import org.opencastproject.security.shibboleth.ShibbolethLoginHandler;
36 import org.opencastproject.userdirectory.api.AAIRoleProvider;
37 import org.opencastproject.userdirectory.api.UserReferenceProvider;
38
39 import org.apache.commons.lang3.StringUtils;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
42 import org.springframework.beans.factory.InitializingBean;
43 import org.springframework.security.core.userdetails.UsernameNotFoundException;
44
45 import java.nio.charset.StandardCharsets;
46 import java.util.ArrayList;
47 import java.util.Date;
48 import java.util.HashSet;
49 import java.util.Iterator;
50 import java.util.List;
51 import java.util.Set;
52 import java.util.regex.Pattern;
53
54 import javax.servlet.http.HttpServletRequest;
55
56
57
58
59 public class DynamicLoginHandler implements ShibbolethLoginHandler, AAIRoleProvider, GroupProvider, InitializingBean {
60
61
62 private static final Logger logger = LoggerFactory.getLogger(DynamicLoginHandler.class);
63
64
65 private UserReferenceProvider userReferenceProvider = null;
66
67
68 private SecurityService securityService = null;
69
70
71 private AttributeMapper attributeMapper = null;
72
73 public DynamicLoginHandler() {
74 }
75
76
77
78
79
80
81
82
83
84 @Override
85 public void newUserLogin(String id, HttpServletRequest request) {
86 String name = extractName(request);
87 String email = extractEmail(request);
88 Date loginDate = new Date();
89 JpaOrganization organization = fromOrganization(securityService.getOrganization());
90
91
92 Set<JpaRole> roles = extractRoles(id, request);
93
94
95 JpaUserReference userReference = new JpaUserReference(id, name, email, MECH_SHIBBOLETH, loginDate, organization,
96 roles);
97
98 logger.debug("Shibboleth user '{}' logged in for the first time", id);
99 userReferenceProvider.addUserReference(userReference, MECH_SHIBBOLETH);
100 }
101
102
103
104
105
106
107
108
109
110 @Override
111 public void existingUserLogin(String id, HttpServletRequest request) {
112 Organization organization = securityService.getOrganization();
113
114
115 JpaUserReference userReference = userReferenceProvider.findUserReference(id, organization.getId());
116 if (userReference == null) {
117
118
119 throw new UsernameNotFoundException("User reference '" + id + "' was not found");
120 }
121
122
123 userReference.setName(extractName(request));
124 userReference.setEmail(extractEmail(request));
125 userReference.setLastLogin(new Date());
126 Set<JpaRole> roles = extractRoles(id, request);
127 userReference.setRoles(roles);
128
129 logger.debug("Shibboleth user '{}' logged in", id);
130 userReferenceProvider.updateUserReference(userReference);
131 }
132
133
134
135
136
137
138
139 public void setSecurityService(SecurityService securityService) {
140 this.securityService = securityService;
141 }
142
143
144
145
146
147
148
149 public void setUserReferenceProvider(UserReferenceProvider userReferenceProvider) {
150 this.userReferenceProvider = userReferenceProvider;
151 }
152
153
154
155
156
157
158
159
160 private String extractName(HttpServletRequest request) {
161 String displayName = extractDisplayName(request);
162 if (StringUtils.isNotBlank(displayName)) {
163 return displayName;
164 }
165 return null;
166 }
167
168
169
170
171
172
173
174
175 private String extractEmail(HttpServletRequest request) {
176 List<String> mailAdresses = attributeMapper.getMappedAttributes(request, "mail");
177
178 if (mailAdresses.size() == 0) {
179 return null;
180 }
181
182 String mailValue = mailAdresses.get(0);
183 String mail = StringUtils.isBlank(mailValue) ? ""
184 : new String(mailValue.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
185 return mail;
186 }
187
188
189
190
191
192
193
194
195 private String extractDisplayName(HttpServletRequest request) {
196 List<String> displayNames = attributeMapper.getMappedAttributes(request, "displayName");
197
198 if (displayNames.size() == 0) {
199 return null;
200 }
201
202 String displayNameValue = displayNames.get(0);
203 String displayName = StringUtils.isBlank(displayNameValue) ? ""
204 : new String(displayNameValue.getBytes(StandardCharsets.ISO_8859_1),
205 StandardCharsets.UTF_8);
206 return displayName;
207 }
208
209
210
211
212
213
214
215
216 private Set<JpaRole> extractRoles(String id, HttpServletRequest request) {
217 List<String> aaiRoles = attributeMapper.getMappedAttributes(request, "roles");
218 JpaOrganization organization = fromOrganization(securityService.getOrganization());
219 Set<JpaRole> roles = new HashSet<JpaRole>();
220 if (aaiRoles != null) {
221 for (String aaiRole : aaiRoles) {
222 roles.add(new JpaRole(aaiRole, organization));
223 }
224 }
225
226 return roles;
227 }
228
229
230
231
232
233
234
235 private JpaOrganization fromOrganization(Organization org) {
236 if (org instanceof JpaOrganization) {
237 return (JpaOrganization) org;
238 }
239
240 return new JpaOrganization(org.getId(), org.getName(), org.getServers(), org.getAdminRole(),
241 org.getAnonymousRole(), org.getProperties());
242 }
243
244
245
246
247
248
249 @Override
250 public Iterator<Role> getRoles() {
251 JaxbOrganization organization = JaxbOrganization.fromOrganization(securityService.getOrganization());
252 HashSet<Role> roles = new HashSet<Role>();
253 roles.add(new JaxbRole(organization.getAnonymousRole(), organization));
254 roles.addAll(securityService.getUser().getRoles());
255 return roles.iterator();
256 }
257
258
259
260
261 @Override
262 public List<Role> getRolesForUser(String userName) {
263 ArrayList<Role> roles = new ArrayList<Role>();
264 User user = userReferenceProvider.loadUser(userName);
265 if (user != null) {
266 roles.addAll(user.getRoles());
267 }
268 return roles;
269 }
270
271
272
273
274 @Override
275 public String getOrganization() {
276 return UserProvider.ALL_ORGANIZATIONS;
277 }
278
279
280
281
282 @Override
283 public Iterator<Role> findRoles(String query, Role.Target target, int offset, int limit) {
284 if (query == null) {
285 throw new IllegalArgumentException("Query must be set");
286 }
287 HashSet<Role> foundRoles = new HashSet<Role>();
288 for (Iterator<Role> it = getRoles(); it.hasNext();) {
289 Role role = it.next();
290 if (like(role.getName(), query) || like(role.getDescription(), query)) {
291 foundRoles.add(role);
292 }
293 }
294 return offsetLimitCollection(offset, limit, foundRoles).iterator();
295
296 }
297
298 private <T> HashSet<T> offsetLimitCollection(int offset, int limit, HashSet<T> entries) {
299 HashSet<T> result = new HashSet<T>();
300 int i = 0;
301 for (T entry : entries) {
302 if (limit != 0 && result.size() >= limit) {
303 break;
304 }
305 if (i >= offset) {
306 result.add(entry);
307 }
308 i++;
309 }
310 return result;
311 }
312
313 private boolean like(String string, final String query) {
314 if (string == null) {
315 return false;
316 }
317 String regex = query.replace("_", ".").replace("%", ".*?");
318 Pattern p = Pattern.compile(regex, Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
319 return p.matcher(string).matches();
320 }
321
322 @Override
323 public void afterPropertiesSet() throws Exception {
324 this.userReferenceProvider.setRoleProvider(this);
325 }
326
327 public AttributeMapper getAttributeMapper() {
328 return attributeMapper;
329 }
330
331 public void setAttributeMapper(AttributeMapper attributeMapper) {
332 this.attributeMapper = attributeMapper;
333 }
334
335 @Override
336 public List<Role> getRolesForGroup(String groupName) {
337 return null;
338 }
339
340 }