/** * Licensed to Apereo under one or more contributor license * agreements. See the NOTICE file distributed with this work * for additional information regarding copyright ownership. * Apereo licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a * copy of the License at the following location: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.jasig.portlet.blackboardvcportlet.security; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.regex.Pattern; import org.apache.commons.lang.StringUtils; import org.jasig.portlet.blackboardvcportlet.dao.ConferenceUserDao; import org.jasig.portlet.blackboardvcportlet.data.ConferenceUser; import org.jasig.springframework.security.portlet.authentication.PortletAuthenticationDetails; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.security.core.Authentication; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.web.authentication.preauth.PreAuthenticatedGrantedAuthoritiesUserDetailsService; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.support.TransactionCallback; import org.springframework.transaction.support.TransactionOperations; import com.google.common.collect.ImmutableList; public class ConferenceUserPreAuthenticatedGrantedAuthoritiesUserDetailsService extends PreAuthenticatedGrantedAuthoritiesUserDetailsService { private static final Pattern ATTRIBUTE_NAME_SEPERATOR = Pattern.compile(","); private ConferenceUserDao conferenceUserDao; private TransactionOperations transactionOperations; private List<String> uniqueIdAttributeName; private List<String> emailAttributeName; private List<String> displayNameAttributeName; @Autowired public void setConferenceUserDao(ConferenceUserDao conferenceUserDao) { this.conferenceUserDao = conferenceUserDao; } @Autowired public void setTransactionOperations(TransactionOperations transactionOperations) { this.transactionOperations = transactionOperations; } @Value("${emailAttributeName:mail}") public void setEmailAttributeName(String emailAttributeName) { this.emailAttributeName = ImmutableList.copyOf(ATTRIBUTE_NAME_SEPERATOR.split(emailAttributeName)); } @Value("${displayNameAttributeName:displayName}") public void setDisplayNameAttributeName(String displayNameAttributeName) { this.displayNameAttributeName = ImmutableList.copyOf(ATTRIBUTE_NAME_SEPERATOR.split(displayNameAttributeName)); } @Value("${uniqueIdAttributeName:uid}") public void setUniqueIdAttributeName(String uniqueIdAttributeName) { this.uniqueIdAttributeName = ImmutableList.copyOf(ATTRIBUTE_NAME_SEPERATOR.split(uniqueIdAttributeName)); } @Override protected UserDetails createuserDetails(Authentication token, Collection<? extends GrantedAuthority> authorities) { final PortletAuthenticationDetails authenticationDetails = (PortletAuthenticationDetails)token.getDetails(); final ConferenceUser conferenceUser = this.setupConferenceUser(authenticationDetails); return new ConferenceSecurityUser(token.getName(), conferenceUser, authorities); } protected ConferenceUser setupConferenceUser(final PortletAuthenticationDetails authenticationDetails) { final String uniqueId = getAttribute(authenticationDetails, this.uniqueIdAttributeName, true); final String mail = getAttribute(authenticationDetails, this.emailAttributeName, true); final String displayName = getAttribute(authenticationDetails, this.displayNameAttributeName, false); return this.transactionOperations.execute(new TransactionCallback<ConferenceUser>() { @Override public ConferenceUser doInTransaction(TransactionStatus status) { ConferenceUser user = conferenceUserDao.getUserByUniqueId(uniqueId); if (user == null) { user = conferenceUserDao.createInternalUser(uniqueId); } boolean modified = false; //Update with current display name if (!StringUtils.equals(user.getDisplayName(), displayName)) { modified = true; user.setDisplayName(displayName); } //Update with current email if (!StringUtils.equals(user.getEmail(), mail)) { modified = true; user.setEmail(mail); } if (modified) { //Persist modification conferenceUserDao.updateUser(user); } return user; } }); } private String getAttribute(PortletAuthenticationDetails authenticationDetails, List<String> attributeNames, boolean required) { final Map<String, String> userInfo = authenticationDetails.getUserInfo(); for (final String mailAttributeName : attributeNames) { final String value = userInfo.get(mailAttributeName); if (value != null) { return value; } } if (required) { throw new IllegalStateException("Could not find required user attribute value in attributes: " + attributeNames); } return null; } }