001/**
002 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003 *
004 * Copyright (c) 2005 Sun Microsystems Inc. All Rights Reserved
005 *
006 * The contents of this file are subject to the terms
007 * of the Common Development and Distribution License
008 * (the License). You may not use this file except in
009 * compliance with the License.
010 *
011 * You can obtain a copy of the License at
012 * https://opensso.dev.java.net/public/CDDLv1.0.html or
013 * opensso/legal/CDDLv1.0.txt
014 * See the License for the specific language governing
015 * permission and limitations under the License.
016 *
017 * When distributing Covered Code, include this CDDL
018 * Header Notice in each file and include the License file
019 * at opensso/legal/CDDLv1.0.txt.
020 * If applicable, add the following below the CDDL Header,
021 * with the fields enclosed by brackets [] replaced by
022 * your own identifying information:
023 * "Portions Copyrighted [year] [name of copyright owner]"
024 *
025 * $Id: AssignableDynamicGroup.java,v 1.6 2009/01/28 05:34:50 ww203982 Exp $
026 *
027 */
028/**
029 * Portions Copyrighted 2013 ForgeRock, Inc.
030 */
031package com.iplanet.ums;
032
033import com.iplanet.services.ldap.Attr;
034import com.iplanet.services.ldap.AttrSet;
035import com.iplanet.services.ldap.ModSet;
036import com.iplanet.services.util.I18n;
037import com.sun.identity.shared.debug.Debug;
038import com.sun.identity.shared.ldap.LDAPUrl;
039import com.sun.identity.shared.ldap.LDAPv2;
040import com.sun.identity.shared.ldap.util.DN;
041
042/**
043 * Represents a dynamic group entry that uses memberOf as its filter. It checks
044 * whether the user is the member of the specified group
045 *
046 * @supported.api
047 */
048public class AssignableDynamicGroup extends DynamicGroup implements
049        IAssignableMembership {
050
051    private static I18n i18n = I18n.getInstance(IUMSConstants.UMS_PKG);
052
053    private static Debug debug;
054    static {
055        debug = Debug.getInstance(IUMSConstants.UMS_DEBUG);
056    }
057
058    /**
059     * Default constructor
060     *
061     * @supported.api
062     */
063    public AssignableDynamicGroup() {
064    }
065
066    /**
067     * Constructs an in memory AssignableDynamicGroup object. Default registered
068     * template will be used. This is an in memory Group object and one needs to
069     * call <code>save</code> method to save this newly created object to
070     * persistent storage.
071     * 
072     * @param attrSet Attribute/value set.
073     * @exception UMSException if fail to instantiate from persistent storage.
074     */
075    AssignableDynamicGroup(AttrSet attrSet) throws UMSException {
076        this(TemplateManager.getTemplateManager().getCreationTemplate(_class,
077                null), attrSet);
078    }
079
080    /**
081     * Constructs an in memory <code>AssignableDynamicGroup</code> object with
082     * a given template. This is an in memory Group object and one needs to
083     * call save method to <code>save</code> this newly created object to
084     * persistent storage.
085     * 
086     * @param template Template for creating a group.
087     * @param attrSet Attribute/value set.
088     * @exception UMSException if fail to instantiate from persistent storage.
089     *
090     * @supported.api
091     */
092    public AssignableDynamicGroup(CreationTemplate template, AttrSet attrSet)
093            throws UMSException {
094        super(template, attrSet);
095    }
096
097    /**
098     * Constructs an in memory <code>AssignableDynamicGroup</code> object using
099     * default registered for <code>AssignableDynamicGroup</code>. This is an
100     * in memory Group object and one needs to call <code>save</code> method to
101     * save this newly created object to persistent storage.
102     * 
103     * @param attrSet Attribute/value set, which should not contain
104     *        <code>memberUrl</code>; any values of <code>memberUrl</code> will
105     *        be overwritten by the explicit search criteria arguments.
106     * @param base Search base for evaluating members of the group.
107     * @param scope Search scope for evaluating members of the group the value
108     *        has to be <code>LDAPv2.SCOPE_ONE</code> or
109     *        <code>LDAPv2.SCOPE_SUB</code>.
110     * @exception UMSException if fail to instantiate from persistent storage.
111     */
112    AssignableDynamicGroup(AttrSet attrSet, Guid baseGuid, int scope)
113            throws UMSException {
114        this(TemplateManager.getTemplateManager().getCreationTemplate(_class,
115                null), attrSet, baseGuid, scope);
116    }
117
118    /**
119     * Constructs an <code>AssignableDynamicGroup</code> object with a given
120     * template. This is an in memory Group object and one needs to call
121     * <code>save</code> method to save this newly created object to
122     * persistent storage.
123     * 
124     * @param template Template for creating a group.
125     * @param attrSet Attribute-value set which should not contain member URL;
126     *        any values of member URL will be overwritten by the explicit
127     *        search criteria arguments.
128     * @param baseGuid Search base for evaluating members of the group
129     * @param scope Search scope for evaluating members of the group has to be
130     *        <code>LDAPv2.SCOPE_ONE</code> or <code>LDAPv2.SCOPE_SUB</code>.
131     * @exception UMSException if fail to instantiate from persistent storage
132     *
133     * @supported.api
134     */
135    public AssignableDynamicGroup(CreationTemplate template, AttrSet attrSet,
136            Guid baseGuid, int scope) throws UMSException {
137        super(template, attrSet);
138        // No host, port, or attributes in the URL
139        // setUrl( new LDAPUrl( null, 0, base, (String[])null, scope, "" ) );
140        setUrl(baseGuid, null, scope);
141    }
142
143    /**
144     * Sets the search filter used to evaluate this dynamic group. For an 
145     * <code>AssignableDynamicGroup</code>, the filter is always
146     * <code>"memberof=THIS_DN"</code>, so this method should not generally be
147     * called outside the package.
148     * 
149     * @param filter Search filter for evaluating members of the group the
150     *        scope in the filter has to be <code>LDAPv2.SCOPE_ONE</code> or
151     *        <code>LDAPv2.SCOPE_SUB</code>.
152     *
153     * @supported.api
154     */
155    public void setSearchFilter(String filter) {
156        LDAPUrl url = getUrl();
157        int scope = url.getScope();
158        if (scope != LDAPv2.SCOPE_ONE && scope != LDAPv2.SCOPE_SUB) {
159            String msg = i18n.getString(IUMSConstants.ILLEGAL_ADGROUP_SCOPE);
160            throw new IllegalArgumentException(msg);
161        }
162        Guid baseGuid = new Guid(url.getDN());
163        setUrl(baseGuid, filter, scope);
164    }
165
166    /**
167     * Sets the GUID of the entity; used within the package.
168     * 
169     * @param guid GUID <code>REVIEW</code>: This method overloads the
170     *        <code>PersistentObject.setGuid()</code> method. Hence the
171     *        signature has to match, and we can't throw the
172     *        <code>UMSException</code> that could be thrown from
173     *        <code>"setSearchFilter"</code>. Is it enough to log such an
174     *        error ???
175     */
176    protected void setGuid(Guid guid) {
177        super.setGuid(guid);
178        // setSearchFilter( "(" + "memberof=" + getDN() + ")" );
179        try {
180            setSearchFilter("memberof=" + getDN());
181        } catch (Exception e) {
182            // TODO - Log Exception
183            if (debug.messageEnabled()) {
184                debug.message("AssignableDynamicGroup.setGuid() : "
185                        + "Exception : " + e.getMessage());
186            }
187        }
188    }
189
190    /**
191     * Adds a member to the group. The change is saved to persistent storage.
192     * 
193     * @param userGuid Globally unique identifier for the member to be added.
194     * @exception UMSException if fail to save to persistent storage or if the
195     *            user is not within the scope of the group.
196     *
197     * @supported.api
198     */
199    public void addMember(Guid userGuid) throws UMSException {
200        // UMSSession session = getUMSSession();
201        if (getPrincipal() == null) {
202            throw new IllegalArgumentException(i18n
203                    .getString(IUMSConstants.NULL_PRINCIPAL));
204        }
205
206        addMember(UMSObject.getObject(getPrincipal(), userGuid));
207    }
208
209    /**
210     * Adds a member to the group. The change is saved to persistent storage.
211     * 
212     * @param member Object to be added as member.
213     * @exception UMSException if fail to save to persistent storage or if the
214     *            user is not within the scope of the group.
215     *
216     * @supported.api
217     */
218    public void addMember(PersistentObject member) throws UMSException {
219        // check whether the userGuid is within the scope of memberUrl
220        DN userDN = new DN(member.getGuid().getDn());
221        LDAPUrl memberUrl = getUrl();
222        DN memberDN = new DN(memberUrl.getDN());
223
224        if (!userDN.isDescendantOf(memberDN) || userDN.equals(memberDN)) {
225            String args[] = new String[2];
226            args[0] = userDN.toString();
227            args[1] = memberUrl.toString();
228            String msg = i18n.getString(IUMSConstants.USER_NOT_IN_GROUP_SCOPE,
229                    args);
230            throw new UMSException(msg);
231        } else if (((userDN.countRDNs() - memberDN.countRDNs()) > 1)
232                && (memberUrl.getScope() == LDAPv2.SCOPE_ONE)) {
233            String args[] = new String[2];
234            args[0] = userDN.toString();
235            args[1] = memberUrl.toString();
236            String msg = i18n.getString(IUMSConstants.USER_NOT_IN_GROUP_SCOPE,
237                    args);
238            throw new UMSException(msg);
239        }
240        member.modify(new Attr(MEMBER_ATTR_NAME, this.getDN()), ModSet.ADD);
241        member.save();
242    }
243
244    /**
245     * Adds a list of members to the group. The change is saved to persistent
246     * storage.
247     * 
248     * @param guids Array of member GUIDs to be added as members to the group.
249     * @exception UMSException if fail to save to persistent storage.
250     *
251     * @supported.api
252     */
253    public void addMembers(Guid[] guids) throws UMSException {
254        if (guids == null) {
255            throw new IllegalArgumentException(i18n
256                    .getString(IUMSConstants.NULL_GUIDS));
257        }
258        for (int i = 0; i < guids.length; i++) {
259            addMember(guids[i]);
260        }
261    }
262
263    /**
264     * Removes a member from the group. The change is saved to persistent
265     * storage.
266     * 
267     * @param guid Unique identifier for the member to be removed.
268     * @exception UMSException if fail to save to persistent storage.
269     *
270     * @supported.api
271     */
272    public void removeMember(Guid guid) throws UMSException {
273        PersistentObject member = UMSObject.getObject(getPrincipal(), guid);
274        removeMember(member);
275    }
276
277    /**
278     * Removes a member from the group. The change is saved to persistent
279     * storage.
280     * 
281     * @param member Object to be removed.
282     * @exception UMSException if fail to save to persistent storage.
283     *
284     * @supported.api
285     */
286    public void removeMember(PersistentObject member) throws UMSException {
287        member.modify(new Attr(MEMBER_ATTR_NAME, this.getDN()), ModSet.DELETE);
288        member.save();
289    }
290
291    /**
292     * Removes all members of the group.
293     * 
294     * @exception UMSException if fail to save to persistent storage.
295     *
296     * @supported.api
297     */
298    public void removeAllMembers() throws UMSException {
299
300        String filter = getSearchFilter();
301        if (filter == null) {
302            return;
303        }
304        String[] attributesToGet = { "dn" };
305        SearchResults searchResults = getMemberIDs(attributesToGet);
306        while (searchResults.hasMoreElements()) {
307            PersistentObject member = searchResults.next();
308            member.setPrincipal(getPrincipal());
309            removeMember(member);
310        }
311    }
312
313    /**
314     * Returns <code>true</code> if a given identifier is a member of the
315     * group.
316     * 
317     * @param guid Identity of member to be checked for membership.
318     * @return <code>true</code> if it is a member.
319     * @exception UMSException if fail to read object for guid.
320     *
321     * @supported.api
322     */
323    public boolean hasMember(Guid guid) throws UMSException {
324        if (getPrincipal() == null) {
325            throw new IllegalArgumentException(i18n
326                    .getString(IUMSConstants.NULL_PRINCIPAL));
327        }
328        PersistentObject object = UMSObject.getObject(getPrincipal(), guid);
329        Attr attr = object.getAttribute(MEMBER_ATTR_NAME);
330        if (attr == null) {
331            if (debug.messageEnabled()) {
332                debug.message("AssignableDynamicGroup.hasMember: no "
333                        + "attribute " + MEMBER_ATTR_NAME + " in "
334                        + guid.getDn());
335            }
336            return false;
337        }
338
339        // need to normalize DN to escape spaces and such
340        // for accurate checking of membership
341        // TODO: This ties guids to DNS. The methods to normalize and compare
342        // should be managed separately.
343        // TODO: The members should have been normalized before adding to
344        // the group (i.e. when creating or modifying it), so it should not
345        // be necessary to have normalizing code spread out in the classes
346        // and methods.
347        String normalized = getGuid().getDn();
348        String[] members = attr.getStringValues();
349        for (int i = 0; i < members.length; i++) {
350            String target = members[i];
351            if (debug.messageEnabled()) {
352                debug.message("AssignableDynamicGroup.hasMember: comparing "
353                        + normalized + " to " + target);
354            }
355            if (Guid.equals(normalized, target)) {
356                return true;
357            }
358        }
359
360        return false;
361    }
362
363    /**
364     * Saves the modification(s) to the object to persistent storage.
365     * 
366     * @return UMSException on failure to save to persistent storage.
367     */
368    /*
369     * public void save () throws UMSException { String filter =
370     * getSearchFilter(); if ( (filter == null) || (filter.length() < 1) ) {
371     * setSearchFilter( "memberof=" + getDN() ); } super.save(); }
372     */
373
374    private static final String MEMBER_ATTR_NAME = "memberof";
375
376    private static final Class _class = new AssignableDynamicGroup().getClass();
377}




























































Copyright © 2010-2017, ForgeRock All Rights Reserved.