/*******************************************************************************
* Copyright (c) 2011 GigaSpaces Technologies Ltd. All rights reserved
*
* 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.
*******************************************************************************/
package org.cloudifysource.securityldap;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import javax.naming.Name;
import org.springframework.ldap.core.DirContextOperations;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.ldap.ppolicy.PasswordPolicyData;
import org.springframework.security.ldap.userdetails.LdapUserDetails;
import org.springframework.util.Assert;
/**
* Extends Spring default implementation for LdapUserDetailsImpl to add groups.
* @author noak
*
*/
public class ExtendedLdapUserDetailsImpl implements LdapUserDetails, PasswordPolicyData {
/**
* serialVersionUID.
*/
private static final long serialVersionUID = -5094299715539461256L;
//~ Instance fields ==============================================================================================
private String dn;
private String password;
private String username;
private Collection<GrantedAuthority> authorities = AuthorityUtils.NO_AUTHORITIES;
private Collection<String> authGroups = new ArrayList<String>();
private boolean accountNonExpired = true;
private boolean accountNonLocked = true;
private boolean credentialsNonExpired = true;
private boolean enabled = true;
// PPolicy data
private int timeBeforeExpiration = Integer.MAX_VALUE;
private int graceLoginsRemaining = Integer.MAX_VALUE;
//~ Constructors ===================================================================================================
protected ExtendedLdapUserDetailsImpl() { }
//~ Methods ========================================================================================================
public Collection<GrantedAuthority> getAuthorities() {
return authorities;
}
public Collection<String> getAuthGroups() {
return authGroups;
}
public String getDn() {
return dn;
}
public String getPassword() {
return password;
}
public String getUsername() {
return username;
}
public boolean isAccountNonExpired() {
return accountNonExpired;
}
public boolean isAccountNonLocked() {
return accountNonLocked;
}
public boolean isCredentialsNonExpired() {
return credentialsNonExpired;
}
public boolean isEnabled() {
return enabled;
}
public int getTimeBeforeExpiration() {
return timeBeforeExpiration;
}
public int getGraceLoginsRemaining() {
return graceLoginsRemaining;
}
/**
* Returns this object's representation as String.
* @return this object's representation as String
*/
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(super.toString()).append(": ");
sb.append("Username: ").append(this.username).append("; ");
sb.append("Password: [PROTECTED]; ");
sb.append("Enabled: ").append(this.enabled).append("; ");
sb.append("AccountNonExpired: ").append(this.accountNonExpired).append("; ");
sb.append("credentialsNonExpired: ").append(this.credentialsNonExpired).append("; ");
sb.append("AccountNonLocked: ").append(this.accountNonLocked).append("; ");
if (this.getAuthorities() != null) {
sb.append("Granted Authorities: ");
boolean first = true;
for (Object authority : this.getAuthorities()) {
if (first) {
first = false;
} else {
sb.append(", ");
}
sb.append(authority.toString());
}
} else {
sb.append("Not granted any authorities");
}
if (this.getAuthGroups() != null) {
sb.append("Granted Authorization Groups: ");
boolean first = true;
for (Object authGroup : this.getAuthGroups()) {
if (first) {
first = false;
} else {
sb.append(", ");
}
sb.append(authGroup);
}
} else {
sb.append("Not granted any authorization groups");
}
return sb.toString();
}
//~ Inner Classes ==================================================================================================
/**
* Variation of essence pattern. Used to create mutable intermediate object
*/
public static class ExtendedEssence {
protected ExtendedLdapUserDetailsImpl instance = createTarget();
private List<GrantedAuthority> mutableAuthorities = new ArrayList<GrantedAuthority>();
private List<String> mutableAuthGroups = new ArrayList<String>();
public ExtendedEssence() { }
public ExtendedEssence(final DirContextOperations ctx) {
setDn(ctx.getDn());
}
public ExtendedEssence(final ExtendedLdapUserDetailsImpl copyMe) {
setDn(copyMe.getDn());
setUsername(copyMe.getUsername());
setPassword(copyMe.getPassword());
setEnabled(copyMe.isEnabled());
setAccountNonExpired(copyMe.isAccountNonExpired());
setCredentialsNonExpired(copyMe.isCredentialsNonExpired());
setAccountNonLocked(copyMe.isAccountNonLocked());
setAuthorities(copyMe.getAuthorities());
setAuthGroups(copyMe.getAuthGroups());
}
/**
* Create a target as an empty ExtendedLdapUserDetailsImpl.
* @return ExtendedLdapUserDetailsImpl
*/
protected ExtendedLdapUserDetailsImpl createTarget() {
return new ExtendedLdapUserDetailsImpl();
}
/**
* Adds the authority to the list, unless it is already there, in which case it is ignored.
* @param authority authority to add.
*/
public void addAuthority(final GrantedAuthority authority) {
if (!hasAuthority(authority)) {
mutableAuthorities.add(authority);
}
}
private boolean hasAuthority(final GrantedAuthority newAuthority) {
for (GrantedAuthority authority : mutableAuthorities) {
if (authority.equals(newAuthority)) {
return true;
}
}
return false;
}
/**
* Adds the authorization group to the list, unless it is already there, in which case it is ignored.
* @param authGroup authorization group to add.
*/
public void addAuthGroup(final String authGroup) {
if (!hasAuthGroup(authGroup)) {
mutableAuthGroups.add(authGroup);
}
}
private boolean hasAuthGroup(final String newAuthGroup) {
for (String authGroup : mutableAuthGroups) {
if (authGroup.equalsIgnoreCase(newAuthGroup)) {
return true;
}
}
return false;
}
/**
* creates a user details object with authorities and groups.
* @return user details as ExtendedLdapUserDetails
*/
public ExtendedLdapUserDetailsImpl createUserDetails() {
Assert.notNull(instance, "Essence can only be used to create a single instance");
Assert.notNull(instance.username, "username must not be null");
Assert.notNull(instance.getDn(), "Distinguished name must not be null");
instance.authorities = Collections.unmodifiableList(mutableAuthorities);
instance.authGroups = Collections.unmodifiableList(mutableAuthGroups);
ExtendedLdapUserDetailsImpl newInstance = instance;
instance = null;
return newInstance;
}
public Collection<GrantedAuthority> getGrantedAuthorities() {
return mutableAuthorities;
}
public Collection<String> getGrantedAuthGroups() {
return mutableAuthGroups;
}
public void setAccountNonExpired(final boolean accountNonExpired) {
instance.accountNonExpired = accountNonExpired;
}
public void setAccountNonLocked(final boolean accountNonLocked) {
instance.accountNonLocked = accountNonLocked;
}
/**
* Sets authorities.
* @param authorities The authorities to set.
*/
public void setAuthorities(final Collection<GrantedAuthority> authorities) {
mutableAuthorities = new ArrayList<GrantedAuthority>();
mutableAuthorities.addAll(authorities);
}
/**
* Sets authorization groups.
* @param authGroups The autorization groups to set.
*/
public void setAuthGroups(final Collection<String> authGroups) {
mutableAuthGroups = new ArrayList<String>();
mutableAuthGroups.addAll(authGroups);
}
public void setCredentialsNonExpired(final boolean credentialsNonExpired) {
instance.credentialsNonExpired = credentialsNonExpired;
}
public void setDn(final String dn) {
instance.dn = dn;
}
public void setDn(final Name dn) {
instance.dn = dn.toString();
}
public void setEnabled(final boolean enabled) {
instance.enabled = enabled;
}
public void setPassword(final String password) {
instance.password = password;
}
public void setUsername(final String username) {
instance.username = username;
}
public void setTimeBeforeExpiration(final int timeBeforeExpiration) {
instance.timeBeforeExpiration = timeBeforeExpiration;
}
public void setGraceLoginsRemaining(final int graceLoginsRemaining) {
instance.graceLoginsRemaining = graceLoginsRemaining;
}
}
}