2 * Copyright (C) 2010 Mathieu Baudier <mbaudier@argeo.org>
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package org
.argeo
.security
.ldap
;
19 import java
.util
.Collections
;
20 import java
.util
.List
;
22 import java
.util
.TreeSet
;
24 import javax
.naming
.Name
;
25 import javax
.naming
.NamingException
;
26 import javax
.naming
.directory
.DirContext
;
28 import org
.springframework
.ldap
.core
.ContextExecutor
;
29 import org
.springframework
.ldap
.core
.ContextMapper
;
30 import org
.springframework
.ldap
.core
.DirContextAdapter
;
31 import org
.springframework
.ldap
.core
.DistinguishedName
;
32 import org
.springframework
.ldap
.core
.LdapTemplate
;
33 import org
.springframework
.ldap
.core
.support
.BaseLdapPathContextSource
;
34 import org
.springframework
.security
.ldap
.LdapUsernameToDnMapper
;
35 import org
.springframework
.security
.ldap
.LdapUtils
;
38 * Wraps low-level LDAP operation on user and roles, used by
39 * {@link ArgeoLdapUserDetailsManager}
41 public class ArgeoUserAdminDaoLdap
{
42 private String userBase
;
43 private String usernameAttribute
;
44 private String groupBase
;
45 private String
[] groupClasses
;
47 private String groupRoleAttribute
;
48 private String groupMemberAttribute
;
49 private String defaultRole
;
50 private String rolePrefix
;
52 private final LdapTemplate ldapTemplate
;
53 private LdapUsernameToDnMapper usernameMapper
;
56 * Standard constructor, using the LDAP context source shared with Spring
57 * Security components.
59 public ArgeoUserAdminDaoLdap(BaseLdapPathContextSource contextSource
) {
60 this.ldapTemplate
= new LdapTemplate(contextSource
);
63 @SuppressWarnings("unchecked")
64 public synchronized Set
<String
> listUsers() {
65 List
<String
> usernames
= (List
<String
>) ldapTemplate
.listBindings(
66 new DistinguishedName(userBase
), new ContextMapper() {
67 public Object
mapFromContext(Object ctxArg
) {
68 DirContextAdapter ctx
= (DirContextAdapter
) ctxArg
;
69 return ctx
.getStringAttribute(usernameAttribute
);
74 .unmodifiableSortedSet(new TreeSet
<String
>(usernames
));
77 @SuppressWarnings("unchecked")
78 public Set
<String
> listEditableRoles() {
79 return Collections
.unmodifiableSortedSet(new TreeSet
<String
>(
80 ldapTemplate
.listBindings(groupBase
, new ContextMapper() {
81 public Object
mapFromContext(Object ctxArg
) {
82 String groupName
= ((DirContextAdapter
) ctxArg
)
83 .getStringAttribute(groupRoleAttribute
);
84 String roleName
= convertGroupToRole(groupName
);
90 @SuppressWarnings("unchecked")
91 public Set
<String
> listUsersInRole(String role
) {
92 return (Set
<String
>) ldapTemplate
.lookup(
93 buildGroupDn(convertRoleToGroup(role
)), new ContextMapper() {
94 public Object
mapFromContext(Object ctxArg
) {
95 DirContextAdapter ctx
= (DirContextAdapter
) ctxArg
;
96 String
[] userDns
= ctx
97 .getStringAttributes(groupMemberAttribute
);
98 TreeSet
<String
> set
= new TreeSet
<String
>();
99 for (String userDn
: userDns
) {
100 DistinguishedName dn
= new DistinguishedName(userDn
);
101 String username
= dn
.getValue(usernameAttribute
);
104 return Collections
.unmodifiableSortedSet(set
);
109 public void createRole(String role
, final String superuserName
) {
110 String group
= convertRoleToGroup(role
);
111 DistinguishedName superuserDn
= (DistinguishedName
) ldapTemplate
112 .executeReadWrite(new ContextExecutor() {
113 public Object
executeWithContext(DirContext ctx
)
114 throws NamingException
{
115 return LdapUtils
.getFullDn(
116 usernameMapper
.buildDn(superuserName
), ctx
);
120 Name groupDn
= buildGroupDn(group
);
121 DirContextAdapter context
= new DirContextAdapter();
122 context
.setAttributeValues("objectClass", groupClasses
);
123 context
.setAttributeValue("cn", group
);
124 // Add superuser because cannot create empty group
125 context
.setAttributeValue(groupMemberAttribute
, superuserDn
.toString());
126 ldapTemplate
.bind(groupDn
, context
, null);
129 public void deleteRole(String role
) {
130 String group
= convertRoleToGroup(role
);
131 Name dn
= buildGroupDn(group
);
132 ldapTemplate
.unbind(dn
);
135 /** Maps a role (ROLE_XXX) to the related LDAP group (xxx) */
136 protected String
convertRoleToGroup(String role
) {
138 if (group
.startsWith(rolePrefix
)) {
139 group
= group
.substring(rolePrefix
.length());
140 group
= group
.toLowerCase();
145 /** Maps anLDAP group (xxx) to the related role (ROLE_XXX) */
146 protected String
convertGroupToRole(String groupName
) {
147 groupName
= groupName
.toUpperCase();
149 return rolePrefix
+ groupName
;
152 protected Name
buildGroupDn(String name
) {
153 return new DistinguishedName(groupRoleAttribute
+ "=" + name
+ ","
157 public void setUserBase(String userBase
) {
158 this.userBase
= userBase
;
161 public void setUsernameAttribute(String usernameAttribute
) {
162 this.usernameAttribute
= usernameAttribute
;
165 public void setGroupBase(String groupBase
) {
166 this.groupBase
= groupBase
;
169 public void setGroupRoleAttribute(String groupRoleAttributeName
) {
170 this.groupRoleAttribute
= groupRoleAttributeName
;
173 public void setGroupMemberAttribute(String groupMemberAttributeName
) {
174 this.groupMemberAttribute
= groupMemberAttributeName
;
177 public void setDefaultRole(String defaultRole
) {
178 this.defaultRole
= defaultRole
;
181 public void setRolePrefix(String rolePrefix
) {
182 this.rolePrefix
= rolePrefix
;
185 public void setUsernameMapper(LdapUsernameToDnMapper usernameMapper
) {
186 this.usernameMapper
= usernameMapper
;
189 public String
getDefaultRole() {
193 public void setGroupClasses(String
[] groupClasses
) {
194 this.groupClasses
= groupClasses
;