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 */ 019package org.apache.wiki.tags; 020 021import org.apache.wiki.api.core.Context; 022import org.apache.wiki.api.core.Engine; 023import org.apache.wiki.api.core.Session; 024import org.apache.wiki.api.spi.Wiki; 025import org.apache.wiki.auth.AuthenticationManager; 026import org.apache.wiki.auth.GroupPrincipal; 027import org.apache.wiki.auth.UserManager; 028import org.apache.wiki.auth.authorize.Role; 029import org.apache.wiki.auth.user.UserProfile; 030import org.apache.wiki.i18n.InternationalizationManager; 031import org.apache.wiki.preferences.Preferences; 032import org.apache.wiki.util.TextUtil; 033 034import javax.servlet.http.HttpServletRequest; 035import java.io.IOException; 036import java.security.Principal; 037import java.util.ArrayList; 038import java.util.List; 039import java.util.ResourceBundle; 040 041/** 042 * <p> 043 * Returns user profile attributes, or empty strings if the user has not been 044 * validated. This tag has a single attribute, "property." 045 * The <code>property</code> attribute may contain one of the following 046 * case-insensitive values: 047 * </p> 048 * <ul> 049 * <li><code>created</code> - creation date</li> 050 * <li><code>email</code> - user's e-mail address</li> 051 * <li><code>fullname</code> - user's full name</li> 052 * <li><code>groups</code> - a sorted list of the groups a user belongs to</li> 053 * <li><code>loginname</code> - user's login name. If the current user does not have a profile, the user's login principal (such as one 054 * provided by a container login module, user cookie, or anonyous IP address), will supply the login name property</li> 055 * <li><code>roles</code> - a sorted list of the roles a user possesses</li> 056 * <li><code>wikiname</code> - user's wiki name</li> 057 * <li><code>modified</code> - last modification date</li> 058 * <li><code>exists</code> - evaluates the body of the tag if user's profile exists in the user database</li> 059 * <li><code>new</code> - evaluates the body of the tag if user's profile does not exist in the user database</li> 060 * <li><code>canChangeLoginName</code> - always true if custom auth used; also true for container auth and current 061 * UserDatabase.isSharedWithContainer() is true.</li> 062 * <li><code>canChangePassword</code> - always true if custom auth used; also true for container auth 063 * and current UserDatabase.isSharedWithContainer() is true.</li> 064 * </ul> 065 * <p>In addition, the values <code>exists</code>, <code>new</code>, <code>canChangeLoginName</code> 066 * and <code>canChangeLoginName</code> can also be prefixed with <code>!</code> to indicate the 067 * negative condition (for example, <code>!exists</code>).</p> 068 * 069 * @since 2.3 070 */ 071public class UserProfileTag extends WikiTagBase { 072 073 private static final long serialVersionUID = 3258410625431582003L; 074 075 public static final String BLANK = "(not set)"; 076 077 private static final String CREATED = "created"; 078 private static final String EMAIL = "email"; 079 private static final String EXISTS = "exists"; 080 private static final String NOT_EXISTS= "!exists"; 081 private static final String FULLNAME = "fullname"; 082 private static final String GROUPS = "groups"; 083 private static final String LOGINNAME = "loginname"; 084 private static final String MODIFIED = "modified"; 085 private static final String NEW = "new"; 086 private static final String NOT_NEW = "!new"; 087 private static final String ROLES = "roles"; 088 private static final String WIKINAME = "wikiname"; 089 private static final String CHANGE_LOGIN_NAME = "canchangeloginname"; 090 private static final String NOT_CHANGE_LOGIN_NAME = "!canchangeloginname"; 091 private static final String CHANGE_PASSWORD = "canchangepassword"; 092 private static final String NOT_CHANGE_PASSWORD = "!canchangepassword"; 093 094 private String m_prop; 095 096 @Override 097 public void initTag() { 098 super.initTag(); 099 m_prop = null; 100 } 101 102 @Override 103 public final int doWikiStartTag() throws IOException { 104 final UserManager manager = m_wikiContext.getEngine().getManager( UserManager.class ); 105 final UserProfile profile = manager.getUserProfile( m_wikiContext.getWikiSession() ); 106 String result = null; 107 108 if( EXISTS.equals( m_prop ) || NOT_NEW.equals( m_prop ) ) { 109 return profile.isNew() ? SKIP_BODY : EVAL_BODY_INCLUDE; 110 } else if( NEW.equals( m_prop ) || NOT_EXISTS.equals( m_prop ) ) { 111 return profile.isNew() ? EVAL_BODY_INCLUDE : SKIP_BODY; 112 } else if( CREATED.equals( m_prop ) && profile.getCreated() != null ) { 113 result = profile.getCreated().toString(); 114 } else if( EMAIL.equals( m_prop ) ) { 115 result = profile.getEmail(); 116 } else if( FULLNAME.equals( m_prop ) ) { 117 result = profile.getFullname(); 118 } else if( GROUPS.equals( m_prop ) ) { 119 result = printGroups( m_wikiContext ); 120 } else if( LOGINNAME.equals( m_prop ) ) { 121 result = profile.getLoginName(); 122 } else if( MODIFIED.equals( m_prop ) && profile.getLastModified() != null ) { 123 result = profile.getLastModified().toString(); 124 } else if( ROLES.equals( m_prop ) ) { 125 result = printRoles( m_wikiContext ); 126 } else if( WIKINAME.equals( m_prop ) ) { 127 result = profile.getWikiName(); 128 129 if( result == null ) { 130 // 131 // Default back to the declared user name 132 // 133 final Engine engine = this.m_wikiContext.getEngine(); 134 final Session wikiSession = Wiki.session().find( engine, ( HttpServletRequest )pageContext.getRequest() ); 135 final Principal user = wikiSession.getUserPrincipal(); 136 137 if( user != null ) { 138 result = user.getName(); 139 } 140 } 141 } else if( CHANGE_PASSWORD.equals( m_prop ) || CHANGE_LOGIN_NAME.equals( m_prop ) ) { 142 final AuthenticationManager authMgr = m_wikiContext.getEngine().getManager( AuthenticationManager.class ); 143 if( !authMgr.isContainerAuthenticated() ) { 144 return EVAL_BODY_INCLUDE; 145 } 146 } else if( NOT_CHANGE_PASSWORD.equals( m_prop ) || NOT_CHANGE_LOGIN_NAME.equals( m_prop ) ) { 147 final AuthenticationManager authMgr = m_wikiContext.getEngine().getManager( AuthenticationManager.class ); 148 if( authMgr.isContainerAuthenticated() ) { 149 return EVAL_BODY_INCLUDE; 150 } 151 } 152 153 if( result != null ) { 154 pageContext.getOut().print( TextUtil.replaceEntities( result ) ); 155 } 156 return SKIP_BODY; 157 } 158 159 public void setProperty( final String property ) 160 { 161 m_prop = property.toLowerCase().trim(); 162 } 163 164 /** 165 * Returns a sorted list of the {@link org.apache.wiki.auth.authorize.Group} objects a user possesses 166 * in his or her Session. The result is computed by consulting 167 * {@link org.apache.wiki.api.core.Session#getRoles()} 168 * and extracting those that are of type Group. 169 * @return the list of groups, sorted by name 170 */ 171 public static String printGroups( final Context context ) { 172 final Principal[] roles = context.getWikiSession().getRoles(); 173 final List< String > tempRoles = new ArrayList<>(); 174 final ResourceBundle rb = Preferences.getBundle( context, InternationalizationManager.CORE_BUNDLE ); 175 176 for( final Principal role : roles ) { 177 if( role instanceof GroupPrincipal ) { 178 tempRoles.add( role.getName() ); 179 } 180 } 181 if( tempRoles.size() == 0 ) { 182 return rb.getString( "userprofile.nogroups" ); 183 } 184 185 final StringBuilder sb = new StringBuilder(); 186 for( int i = 0; i < tempRoles.size(); i++ ) { 187 final String name = tempRoles.get( i ); 188 189 sb.append( name ); 190 if( i < ( tempRoles.size() - 1 ) ) { 191 sb.append( ',' ); 192 sb.append( ' ' ); 193 } 194 195 } 196 return sb.toString(); 197 } 198 199 /** 200 * Returns a sorted list of the {@link org.apache.wiki.auth.authorize.Role} objects a user possesses 201 * in his or her Session. The result is computed by consulting 202 * {@link org.apache.wiki.api.core.Session#getRoles()} 203 * and extracting those that are of type Role. 204 * @return the list of roles, sorted by name 205 */ 206 public static String printRoles( final Context context ) { 207 final Principal[] roles = context.getWikiSession().getRoles(); 208 final List< String > tempRoles = new ArrayList<>(); 209 final ResourceBundle rb = Preferences.getBundle( context, InternationalizationManager.CORE_BUNDLE ); 210 211 for( final Principal role : roles ) { 212 if( role instanceof Role ) { 213 tempRoles.add( role.getName() ); 214 } 215 } 216 if( tempRoles.size() == 0 ) { 217 return rb.getString( "userprofile.noroles" ); 218 } 219 220 final StringBuilder sb = new StringBuilder(); 221 for( int i = 0; i < tempRoles.size(); i++ ) { 222 final String name = tempRoles.get( i ); 223 224 sb.append( name ); 225 if( i < ( tempRoles.size() - 1 ) ) { 226 sb.append( ',' ); 227 sb.append( ' ' ); 228 } 229 230 } 231 return sb.toString(); 232 } 233 234}