/*
* #%L
* BroadleafCommerce Open Admin Platform
* %%
* Copyright (C) 2009 - 2013 Broadleaf Commerce
* %%
* Licensed 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
*
* 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.
* #L%
*/
package org.broadleafcommerce.openadmin.server.security.service;
import org.apache.commons.lang.StringUtils;
import org.broadleafcommerce.common.security.BroadleafExternalAuthenticationUserDetails;
import org.broadleafcommerce.openadmin.server.security.domain.AdminPermission;
import org.broadleafcommerce.openadmin.server.security.domain.AdminRole;
import org.broadleafcommerce.openadmin.server.security.domain.AdminUser;
import org.broadleafcommerce.openadmin.server.security.domain.AdminUserImpl;
import org.broadleafcommerce.openadmin.server.security.external.AdminExternalLoginUserExtensionManager;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.stereotype.Service;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.annotation.Resource;
/**
* This component allows for the default provisioning of an AdminUser and roles in the Broadleaf database, based on the
* external authentication of a user (e.g. LDAP or custom external authentication provider).
*
* @author Kelly Tisdell
*
*/
@Service("blAdminUserProvisioningService")
public class AdminUserProvisioningServiceImpl implements AdminUserProvisioningService {
@Resource(name = "blAdminSecurityService")
protected AdminSecurityService securityService;
@Resource(name = "blAdminExternalLoginExtensionManager")
protected AdminExternalLoginUserExtensionManager adminExternalLoginExtensionManager;
protected Map<String, String[]> roleNameSubstitutions;
@Override
public AdminUserDetails provisionAdminUser(BroadleafExternalAuthenticationUserDetails details) {
HashSet<String> newRoles = new HashSet<String>();
if (roleNameSubstitutions != null && !roleNameSubstitutions.isEmpty()) {
for (GrantedAuthority authority : details.getAuthorities()) {
if (roleNameSubstitutions.containsKey(authority.getAuthority())) {
String[] roles = roleNameSubstitutions.get(authority.getAuthority());
for (String role : roles) {
newRoles.add(role.trim());
}
} else {
newRoles.add(authority.getAuthority());
}
}
} else {
for (GrantedAuthority authority : details.getAuthorities()) {
newRoles.add(authority.getAuthority());
}
}
HashSet<GrantedAuthority> newAuthorities = new HashSet<GrantedAuthority>();
for (String perm : AdminSecurityService.DEFAULT_PERMISSIONS) {
newAuthorities.add(new SimpleGrantedAuthority(perm));
}
HashSet<AdminRole> grantedRoles = new HashSet<AdminRole>();
List<AdminRole> adminRoles = securityService.readAllAdminRoles();
if (adminRoles != null) {
for (AdminRole role : adminRoles) {
if (newRoles.contains(role.getName())) {
grantedRoles.add(role);
Set<AdminPermission> permissions = role.getAllPermissions();
if (permissions != null && !permissions.isEmpty()) {
for (AdminPermission permission : permissions) {
if (permission.isFriendly()) {
for (AdminPermission childPermission : permission.getAllChildPermissions()) {
newAuthorities.add(new SimpleGrantedAuthority(childPermission.getName()));
}
} else {
newAuthorities.add(new SimpleGrantedAuthority(permission.getName()));
}
}
}
}
}
}
AdminUser adminUser = securityService.readAdminUserByUserName(details.getUsername());
if (adminUser == null) {
adminUser = new AdminUserImpl();
adminUser.setLogin(details.getUsername());
}
if (StringUtils.isNotBlank(details.getEmail())) {
adminUser.setEmail(details.getEmail());
}
StringBuilder name = new StringBuilder();
if (StringUtils.isNotBlank(details.getFirstName())) {
name.append(details.getFirstName()).append(" ");
}
if (StringUtils.isNotBlank(details.getLastName())) {
name.append(details.getLastName());
}
String fullName = name.toString();
if (StringUtils.isNotBlank(fullName)) {
adminUser.setName(fullName);
} else {
adminUser.setName(details.getUsername());
}
//We have to do this because BLC replies on the role relationships being stored in the DB
Set<AdminRole> roleSet = adminUser.getAllRoles();
//First, remove all roles associated with the user if they already existed
if (roleSet != null) {
//First, remove all role relationships in case they have changed
roleSet.clear();
} else {
roleSet = new HashSet<AdminRole>();
adminUser.setAllRoles(roleSet);
}
//Now, add all of the role relationships back.
if (adminRoles != null) {
for (AdminRole role : adminRoles) {
roleSet.add(role);
}
}
//Add optional support for things like Multi-Tenant, etc...
adminExternalLoginExtensionManager.getProxy().performAdditionalAuthenticationTasks(adminUser, details);
//Save the user data and all of the roles...
adminUser = securityService.saveAdminUser(adminUser);
return new AdminUserDetails(adminUser.getId(), details.getUsername(), "", true, true, true, true, newAuthorities);
}
/**
* This allows you to declaratively set a map containing values that will substitute role names from LDAP to Broadleaf roles names in cases that they might be different.
* For example, if you have a role specified in LDAP under "memberOf" with a DN of "Marketing Administrator", you might want to
* map that to the role "ADMIN". By default the prefix "ROLE_" will be pre-pended to this name. So to configure this, you would specify:
*
* <bean class="org.broadleaf.loadtest.web.security.ActiveDirectoryUserDetailsContextMapper">
* <property name="roleMappings">
* <map>
* <entry key="Marketing_Administrator" value="ROLE_CATALOG_ADMIN"/>
* </map>
* </property>
* </bean>
*
* With this configuration, all roles returned by LDAP that have a DN of "Marketing Administrator" will be converted to "ADMIN"
* @param roleNameSubstitutions
*/
public void setRoleNameSubstitutions(Map<String, String[]> roleNameSubstitutions) {
this.roleNameSubstitutions = roleNameSubstitutions;
}
}