001    /* 
002        Licensed to the Apache Software Foundation (ASF) under one
003        or more contributor license agreements.  See the NOTICE file
004        distributed with this work for additional information
005        regarding copyright ownership.  The ASF licenses this file
006        to you under the Apache License, Version 2.0 (the
007        "License"); you may not use this file except in compliance
008        with the License.  You may obtain a copy of the License at
009    
010           http://www.apache.org/licenses/LICENSE-2.0
011    
012        Unless required by applicable law or agreed to in writing,
013        software distributed under the License is distributed on an
014        "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015        KIND, either express or implied.  See the License for the
016        specific language governing permissions and limitations
017        under the License.  
018     */
019    package org.apache.wiki.tags;
020    
021    import java.io.IOException;
022    import java.security.Principal;
023    import java.util.ArrayList;
024    import java.util.List;
025    import java.util.ResourceBundle;
026    
027    import javax.servlet.http.HttpServletRequest;
028    
029    import org.apache.wiki.WikiContext;
030    import org.apache.wiki.WikiEngine;
031    import org.apache.wiki.WikiSession;
032    import org.apache.wiki.auth.AuthenticationManager;
033    import org.apache.wiki.auth.GroupPrincipal;
034    import org.apache.wiki.auth.UserManager;
035    import org.apache.wiki.auth.WikiSecurityException;
036    import org.apache.wiki.auth.authorize.Role;
037    import org.apache.wiki.auth.user.UserProfile;
038    import org.apache.wiki.i18n.InternationalizationManager;
039    import org.apache.wiki.preferences.Preferences;
040    import org.apache.wiki.util.TextUtil;
041    
042    /**
043     * <p>
044     * Returns user profile attributes, or empty strings if the user has not been
045     * validated. This tag has a single attribute, "property."
046     * The <code>property</code> attribute may contain one of the following
047     * case-insensitive values:
048     * </p>
049     * <ul>
050     * <li><code>created</code> - creation date</li>
051     * <li><code>email</code> - user's e-mail address</li>
052     * <li><code>fullname</code> - user's full name</li>
053     * <li><code>groups</code> - a sorted list of the groups a user belongs to</li>
054     * <li><code>loginname</code> - user's login name. If the current user does not have
055     * a profile, the user's login principal (such as one provided by a container
056     * login module, user cookie, or anonyous IP address), will supply the login
057     * name property</li>
058     * <li><code>roles</code> - a sorted list of the roles a user possesses</li>
059     * <li><code>wikiname</code> - user's wiki name</li>
060     * <li><code>modified</code> - last modification date</li>
061     * <li><code>exists</code> - evaluates the body of the tag if user's profile exists
062     * in the user database
063     * <li><code>new</code> - evaluates the body of the tag if user's profile does not
064     * exist in the user database
065     * <li><code>canChangeLoginName</code> - always true if custom auth used; also true for container auth
066     * and current UserDatabase.isSharedWithContainer() is true.</li>
067     * <li><code>canChangePassword</code> - always true if custom auth used; also true for container auth
068     * and current UserDatabase.isSharedWithContainer() is true.</li>
069     * </ul>
070     * <p>In addition, the values <code>exists</code>, <code>new</code>, <code>canChangeLoginName</code>
071     * and <code>canChangeLoginName</code> can also be prefixed with <code>!</code> to indicate the
072     * negative condition (for example, <code>!exists</code>).</p>
073     * @since 2.3
074     */
075    public class UserProfileTag extends WikiTagBase
076    {
077        private static final long serialVersionUID = 3258410625431582003L;
078    
079        public  static final String BLANK = "(not set)";
080    
081        private static final String CREATED   = "created";
082    
083        private static final String EMAIL     = "email";
084    
085        private static final String EXISTS    = "exists";
086    
087        private static final String NOT_EXISTS= "!exists";
088    
089        private static final String FULLNAME  = "fullname";
090    
091        private static final String GROUPS    = "groups";
092    
093        private static final String LOGINNAME = "loginname";
094    
095        private static final String MODIFIED  = "modified";
096    
097        private static final String NEW       = "new";
098    
099        private static final String NOT_NEW   = "!new";
100    
101        private static final String ROLES     = "roles";
102    
103        private static final String WIKINAME  = "wikiname";
104    
105        private static final String CHANGE_LOGIN_NAME     = "canchangeloginname";
106    
107        private static final String NOT_CHANGE_LOGIN_NAME = "!canchangeloginname";
108    
109        private static final String CHANGE_PASSWORD       = "canchangepassword";
110    
111        private static final String NOT_CHANGE_PASSWORD   = "!canchangepassword";
112    
113        private String             m_prop;
114    
115        public void initTag()
116        {
117            super.initTag();
118            m_prop = null;
119        }
120    
121        public final int doWikiStartTag() throws IOException, WikiSecurityException
122        {
123            UserManager manager = m_wikiContext.getEngine().getUserManager();
124            UserProfile profile = manager.getUserProfile( m_wikiContext.getWikiSession() );
125            String result = null;
126    
127            if ( EXISTS.equals( m_prop ) || NOT_NEW.equals( m_prop ) )
128            {
129                return profile.isNew() ? SKIP_BODY : EVAL_BODY_INCLUDE;
130            }
131            else if ( NEW.equals( m_prop ) || NOT_EXISTS.equals( m_prop ) )
132            {
133                return profile.isNew() ? EVAL_BODY_INCLUDE : SKIP_BODY;
134            }
135    
136            else if ( CREATED.equals( m_prop ) && profile.getCreated() != null )
137            {
138                result = profile.getCreated().toString();
139            }
140            else if ( EMAIL.equals( m_prop ) )
141            {
142                result = profile.getEmail();
143            }
144            else if ( FULLNAME.equals( m_prop ) )
145            {
146                result = profile.getFullname();
147            }
148            else if ( GROUPS.equals( m_prop ) )
149            {
150                result = printGroups( m_wikiContext );
151            }
152            else if ( LOGINNAME.equals( m_prop ) )
153            {
154                result = profile.getLoginName();
155            }
156            else if ( MODIFIED.equals( m_prop ) && profile.getLastModified() != null )
157            {
158                result = profile.getLastModified().toString();
159            }
160            else if ( ROLES.equals( m_prop ) )
161            {
162                result = printRoles( m_wikiContext );
163            }
164            else if ( WIKINAME.equals( m_prop ) )
165            {
166                result = profile.getWikiName();
167    
168                if( result == null )
169                {
170                    //
171                    //  Default back to the declared user name
172                    //
173                    WikiEngine engine = this.m_wikiContext.getEngine();
174                    WikiSession wikiSession = WikiSession.getWikiSession( engine, (HttpServletRequest)pageContext.getRequest() );
175                    Principal user = wikiSession.getUserPrincipal();
176    
177                    if( user != null )
178                    {
179                        result = user.getName();
180                    }
181                }
182            }
183            else if ( CHANGE_PASSWORD.equals( m_prop ) || CHANGE_LOGIN_NAME.equals( m_prop ) )
184            {
185                AuthenticationManager authMgr = m_wikiContext.getEngine().getAuthenticationManager();
186                if ( !authMgr.isContainerAuthenticated() )
187                {
188                    return EVAL_BODY_INCLUDE;
189                }
190            }
191            else if ( NOT_CHANGE_PASSWORD.equals( m_prop ) || NOT_CHANGE_LOGIN_NAME.equals( m_prop ) )
192            {
193                AuthenticationManager authMgr = m_wikiContext.getEngine().getAuthenticationManager();
194                if ( authMgr.isContainerAuthenticated() )
195                {
196                    return EVAL_BODY_INCLUDE;
197                }
198            }
199    
200            if ( result != null )
201            {
202                pageContext.getOut().print( TextUtil.replaceEntities(result) );
203            }
204            return SKIP_BODY;
205        }
206    
207        public void setProperty( String property )
208        {
209            m_prop = property.toLowerCase().trim();
210        }
211    
212        /**
213         * Returns a sorted list of the {@link org.apache.wiki.auth.authorize.Group} objects a user possesses
214         * in his or her WikiSession. The result is computed by consulting
215         * {@link org.apache.wiki.WikiSession#getRoles()}
216         * and extracting those that are of type Group.
217         * @return the list of groups, sorted by name
218         */
219        public static String printGroups( WikiContext context )
220        {
221            Principal[] roles = context.getWikiSession().getRoles();
222            List<String> tempRoles = new ArrayList<String>();
223            ResourceBundle rb = Preferences.getBundle( context, InternationalizationManager.CORE_BUNDLE );
224            
225            for ( Principal role : roles )
226            {
227                if( role instanceof GroupPrincipal )
228                {
229                    tempRoles.add( role.getName() );
230                }
231            }
232            if ( tempRoles.size() == 0 )
233            {
234                return rb.getString("userprofile.nogroups");
235            }
236    
237            StringBuffer sb = new StringBuffer();
238            for ( int i = 0; i < tempRoles.size(); i++ )
239            {
240                String name = tempRoles.get( i );
241    
242                sb.append( name );
243                if ( i < ( tempRoles.size() - 1 ) )
244                {
245                    sb.append(',');
246                    sb.append(' ');
247                }
248    
249            }
250            return sb.toString();
251        }
252    
253        /**
254         * Returns a sorted list of the {@link org.apache.wiki.auth.authorize.Role} objects a user possesses
255         * in his or her WikiSession. The result is computed by consulting
256         * {@link org.apache.wiki.WikiSession#getRoles()}
257         * and extracting those that are of type Role.
258         * @return the list of roles, sorted by name
259         */
260        public static String printRoles( WikiContext context )
261        {
262            Principal[] roles = context.getWikiSession().getRoles();
263            List<String> tempRoles = new ArrayList<String>();
264            ResourceBundle rb = Preferences.getBundle( context, InternationalizationManager.CORE_BUNDLE );
265            
266            for ( Principal role : roles )
267            {
268                if ( role instanceof Role )
269                {
270                    tempRoles.add( role.getName() );
271                }
272            }
273            if ( tempRoles.size() == 0 )
274            {
275                return rb.getString( "userprofile.noroles" );
276            }
277    
278            StringBuffer sb = new StringBuffer();
279            for ( int i = 0; i < tempRoles.size(); i++ )
280            {
281                String name = tempRoles.get( i );
282    
283                sb.append( name );
284                if ( i < ( tempRoles.size() - 1 ) )
285                {
286                    sb.append(',');
287                    sb.append(' ');
288                }
289    
290            }
291            return sb.toString();
292        }
293    }