[Building Sakai] Dropdown menus in user-tool (velocity) do not work

Rafael Morales Gamboa rmorales at suv.udg.mx
Mon Mar 11 23:28:55 PDT 2013


Hello,

I have done some changes to UserAction.java and chef_user_create.vm in 
the User Tool, so that now I have two additional fields (organization 
and category) displayed as dropdown menus. The options for the first one 
are read from a file and everything works fine... but cannot get values 
back from the menus. Files are attached, and this is the core part of 
the changes (additions) to user_create.vm

         <p class="shorttext required">
             <label for="organization">
                 #if(!$user)<span class="reqStar">*</span>#end $tlang.getString("usecre.organization")
             </label>
             <select name="organization" id="organization"/>
                 #foreach($item in $orgList)
                     <option value="$item" #if($userOrganization && $item.equals($validator.escapeHtml($userOrganization)))selected="selected" #elseif($valueOrganization && $item.equals($validator.escapeHtml($valueOrganization)))selected="selected"#end/>$item</option>
                 #end
             </select>
         </p>
         <p class="shorttext required">
             <label for="category">
                 #if(!$user)<span class="reqStar">*</span>#end $tlang.getString("usecre.category")
             </label>
             <select name="category" id="category"/>
                 <option>Investigador</option>
                 <option>Académico</option>
                 <option>Alumno</option>
                 <option>Administrativo</option>
                 <option>Consejero CUDI</option>
                 <option>Representante CUDI</option>
                 <option>Coordinador CUDI</option>
             </select>
         </p>

It seems the point is to put something in valueOrganization and 
valueCategory, but how can I do that? It is not apparent how it is done 
for email, firstname, etc.

Any ideas?
-------------- next part --------------
## $Header: /cvs/sakai2/legacy/tools/src/webapp/vm/admin/chef_users_create.vm,v 1.2 2005/05/24 19:36:12 gsilver.umich.edu Exp $

<script type="text/javascript" language="JavaScript">
	focus_path = ["eid"];
</script>

<div class="portletBody">
#if($menu)
	#toolbar($menu)
#end

	<h3>
		$tlang.getString("usecre.entthe")
	</h3>
    <p class="instruction"><span class="reqStarInline">*</span> $tlang.getString("usecre.instruc")</p>

	#if ($alertMessage)<div class="alertMessage">$tlang.getString("useconrem.alert") $validator.escapeHtml($alertMessage)</div>#end	

	<form name="user-create_edit" id="user-create_edit" action="#toolForm("$action")" method="post">
		<p class="shorttext required">
			<label #if(!$user) for="eid" #end>
				#if(!$user)<span class="reqStar">*</span>#end $tlang.getString("useconrem.useid")
			</label>
			#if(!$user)<input type="text" name="eid" id="eid" #if($valueEid)value="$validator.escapeHtml($valueEid)"#end/>#else$validator.escapeHtml($user.Eid)#end
		</p>
		<p class="shorttext required">
			<label for="first-name">
				#if(!$user)<span class="reqStar">*</span>#end $tlang.getString("usecre.firnam")
			</label>
			<input type="text" name="first-name" id="first-name" #if($user)value="$validator.escapeHtml($user.FirstName)"#elseif($valueFirstName)value="$validator.escapeHtml($valueFirstName)"#end/>
		</p>
		<p class="shorttext required">
			<label for="last-name">
				#if(!$user)<span class="reqStar">*</span>#end $tlang.getString("usecre.lasnam")
			</label>
			<input type="text" name="last-name" id="last-name" #if($user)value="$validator.escapeHtml($user.LastName)"#elseif($valueLastName)value="$validator.escapeHtml($valueLastName)"#end/>
		</p>
		<p class="shorttext required">
			<label for="email">
				#if(!$user)<span class="reqStar">*</span>#end $tlang.getString("useconrem.ema")
			</label>
			<input type="text" name="email" id="email"#if($user)value="$validator.escapeHtml($user.Email)"#elseif($valueEmail)value="$validator.escapeHtml($valueEmail)"#end />
		</p>
		<p class="shorttext required">
			<label for="pw">
				#if ($pwRequired) <span class="reqStar">*</span> #end $tlang.getString("usecre.crenewpass")
			</label>
			<input type="password" name="pw" id="pw"/>
		</p>
		<p class="shorttext required">
			<label for="pw0">
				#if ($pwRequired) <span class="reqStar">*</span> #end $tlang.getString("usecre.vernewpass")
			</label>
			<input type="password" name="pw0" id="pw0"/>
		</p>
		<p class="shorttext">
			<label for="dtype">
				$tlang.getString("usecre.typ")
			</label>
			<input disabled type="text" name="dtype" id="dtype" value="$type"/>
			<input type="hidden" name="type" id="type" value="$type"/>
		</p>
		<p class="shorttext required">
			<label for="organization">
				#if(!$user)<span class="reqStar">*</span>#end $tlang.getString("usecre.organization")
			</label>
			<select name="organization" id="organization"/>
				#foreach($item in $orgList)
					<option value="$item" #if($userOrganization && $item.equals($validator.escapeHtml($userOrganization)))selected="selected" #elseif($valueOrganization && $item.equals($validator.escapeHtml($valueOrganization)))selected="selected"#end/>$item</option>
				#end
			</select>
		</p>
		<p class="shorttext required">
			<label for="category">
				#if(!$user)<span class="reqStar">*</span>#end $tlang.getString("usecre.category")
			</label>
			<select name="category" id="category"/>
				<option>Investigador</option>
				<option>Académico</option>
				<option>Alumno</option>
				<option>Administrativo</option>
				<option>Consejero CUDI</option>
				<option>Representante CUDI</option>
				<option>Coordinador CUDI</option>
			</select>
		</p>
		$!recaptchaScript
		<div class="act">
			<input type="submit" class="active"  name="eventSubmit_doSave" value="$tlang.getString("usecre.creaco")"  accesskey="s" />
			<input type="submit" name="eventSubmit_doCancel" value="$tlang.getString("useconrem.can")"  accesskey="x" />
		</div>
		<input type="hidden" name="sakai_csrf_token" value="$sakai_csrf_token" />
	</form>
</div>
-------------- next part --------------
/**********************************************************************************
 * $URL: https://source.sakaiproject.org/svn/user/tags/sakai-2.9.0/user-tool/tool/src/java/org/sakaiproject/user/tool/UsersAction.java $
 * $Id: UsersAction.java 105553 2012-03-06 18:50:46Z ottenhoff at longsight.com $
 ***********************************************************************************
 *
 * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008 The Sakai Foundation
 *
 * Licensed under the Educational Community 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.osedu.org/licenses/ECL-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.sakaiproject.user.tool;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;

import java.util.List;
import java.util.ArrayList;
import java.util.HashMap;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.tanesha.recaptcha.ReCaptcha;
import net.tanesha.recaptcha.ReCaptchaFactory;
import net.tanesha.recaptcha.ReCaptchaResponse;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.validator.routines.EmailValidator;
import org.sakaiproject.authz.cover.SecurityService;
import org.sakaiproject.cheftool.Context;
import org.sakaiproject.cheftool.JetspeedRunData;
import org.sakaiproject.cheftool.PagedResourceActionII;
import org.sakaiproject.cheftool.PortletConfig;
import org.sakaiproject.cheftool.RunData;
import org.sakaiproject.cheftool.VelocityPortlet;
import org.sakaiproject.cheftool.api.Menu;
import org.sakaiproject.cheftool.api.MenuItem;
import org.sakaiproject.cheftool.menu.MenuEntry;
import org.sakaiproject.cheftool.menu.MenuImpl;
import org.sakaiproject.component.cover.ServerConfigurationService;
import org.sakaiproject.entity.api.ResourceProperties;
import org.sakaiproject.entity.api.ResourcePropertiesEdit;
import org.sakaiproject.event.api.SessionState;
import org.sakaiproject.event.cover.UsageSessionService;
import org.sakaiproject.exception.IdUnusedException;
import org.sakaiproject.exception.InUseException;
import org.sakaiproject.exception.PermissionException;
import org.sakaiproject.thread_local.cover.ThreadLocalManager;
import org.sakaiproject.tool.api.Session;
import org.sakaiproject.tool.cover.SessionManager;
import org.sakaiproject.user.api.Authentication;
import org.sakaiproject.user.api.AuthenticationException;
import org.sakaiproject.user.api.Evidence;
import org.sakaiproject.user.api.Preferences;
import org.sakaiproject.user.api.PreferencesEdit;
import org.sakaiproject.user.api.User;
import org.sakaiproject.user.api.UserAlreadyDefinedException;
import org.sakaiproject.user.api.UserEdit;
import org.sakaiproject.user.api.UserIdInvalidException;
import org.sakaiproject.user.api.UserLockedException;
import org.sakaiproject.user.api.UserNotDefinedException;
import org.sakaiproject.user.api.UserPermissionException;
import org.sakaiproject.user.cover.AuthenticationManager;
import org.sakaiproject.user.cover.PreferencesService;
import org.sakaiproject.user.cover.UserDirectoryService;
import org.sakaiproject.util.ExternalTrustedEvidence;
import org.sakaiproject.util.RequestFilter;
import org.sakaiproject.util.ResourceLoader;
import org.sakaiproject.util.StringUtil;

/**
 * <p>
 * UsersAction is the Sakai users editor.
 * </p>
 */
public class UsersAction extends PagedResourceActionII
{
	private static ResourceLoader rb = new ResourceLoader("admin");
	private String organizationPropertyName = "prefs_organization";
	private String categoryPropertyName = "prefs_category";
	private String configDirectory = System.getProperty("catalina.base") + "/sakai/";
	private ArrayList<String> orgList = new ArrayList<String>();

	/**
	 * {@inheritDoc}
	 */
	protected List readResourcesPage(SessionState state, int first, int last)
	{
		// search?
		String search = StringUtils.trimToNull((String) state.getAttribute(STATE_SEARCH));

		if (search != null)
		{
			return UserDirectoryService.searchUsers(search, first, last);
		}

		return UserDirectoryService.getUsers(first, last);
	}

	/**
	 * {@inheritDoc}
	 */
	protected int sizeResources(SessionState state)
	{
		// search?
		String search = StringUtils.trimToNull((String) state.getAttribute(STATE_SEARCH));

		if (search != null)
		{
			return UserDirectoryService.countSearchUsers(search);
		}

		return UserDirectoryService.countUsers();
	}

	/**
	 * Populate the state object, if needed.
	 */
	protected void initState(SessionState state, VelocityPortlet portlet, JetspeedRunData rundata)
	{
		super.initState(state, portlet, rundata);

		PortletConfig config = portlet.getPortletConfig();

		if (state.getAttribute("single-user") == null)
		{
			state.setAttribute("single-user", new Boolean(config.getInitParameter("single-user", "false")));
			state.setAttribute("include-password", new Boolean(config.getInitParameter("include-password", "true")));
		}

		if (state.getAttribute("create-user") == null)
		{
			state.setAttribute("create-user", new Boolean(config.getInitParameter("create-user", "false")));
			state.setAttribute("create-login", new Boolean(config.getInitParameter("create-login", "false")));
		}

		if (state.getAttribute("create-type") == null)
		{
			state.setAttribute("create-type", config.getInitParameter("create-type", ""));
		}
		
		if (state.getAttribute("user.recaptcha-enabled") == null)
		{
			String publicKey = ServerConfigurationService.getString("user.recaptcha.public-key", "");
			String privateKey = ServerConfigurationService.getString("user.recaptcha.private-key", "");
			Boolean systemEnabled = ServerConfigurationService.getBoolean("user.recaptcha.enabled", false);
			Boolean toolEnabled = Boolean.parseBoolean(config.getInitParameter("user.recaptcha-enabled", "false"));
			Boolean enabled = systemEnabled && toolEnabled;
			if (enabled)
			{
				if (publicKey == null || publicKey.length() == 0)
				{
					Log.warn("chef", "recaptcha is enabled but no public key is found.");
					enabled = Boolean.FALSE;
				}
				if (privateKey == null || privateKey.length() == 0)
				{
					Log.warn("chef", "recaptcha is enabled but no private key is found.");
					enabled = Boolean.FALSE;
				}
			}
			state.setAttribute("user.recaptcha-public-key", publicKey);
			state.setAttribute("user.recaptcha-private-key", privateKey);
			state.setAttribute("user.recaptcha-enabled", enabled);
		}

	} // initState

	/**
	 * build the context
	 */
	public String buildMainPanelContext(VelocityPortlet portlet, Context context, RunData rundata, SessionState state)
	{
		context.put("tlang", rb);
		boolean singleUser = ((Boolean) state.getAttribute("single-user")).booleanValue();
		boolean createUser = ((Boolean) state.getAttribute("create-user")).booleanValue();

		// if not logged in as the super user, we won't do anything
		if ((!singleUser) && (!createUser) && (!SecurityService.isSuperUser()))
		{
			context.put("tlang",rb);
			return (String) getContext(rundata).get("template") + "_noaccess";
		}

		String template = null;

		// for the create-user create-login case, we set this in the do so we can process the redirect here
		if (state.getAttribute("redirect") != null)
		{
			state.removeAttribute("redirect");
			Session s = SessionManager.getCurrentSession();
			// TODO: Decide if this should be in "getPortalUrl"
			// I don't think so but could be convinced - /chuck
			String controllingPortal = (String) s.getAttribute("sakai-controlling-portal");
			String portalUrl = ServerConfigurationService.getPortalUrl();
			if ( controllingPortal != null ) {
				portalUrl = portalUrl + "/" + controllingPortal;
			}
 
			sendParentRedirect((HttpServletResponse) ThreadLocalManager.get(RequestFilter.CURRENT_HTTP_RESPONSE),
					portalUrl);
			return template;
		}

		// put $action into context for menus, forms and links
		context.put(Menu.CONTEXT_ACTION, state.getAttribute(STATE_ACTION));

		// check mode and dispatch
		String mode = (String) state.getAttribute("mode");

		if ((singleUser) && (mode != null) && (mode.equals("edit")))
		{
			template = buildEditContext(state, context);
		}
		else if (singleUser)
		{
			String id = SessionManager.getCurrentSessionUserId();
			state.setAttribute("user-id", id);
			template = buildViewContext(state, context);
		}
		else if (createUser)
		{
			template = buildCreateContext(state, context);
		}
		else if (mode == null)
		{
			template = buildListContext(state, context);
		}
		else if (mode.equals("new"))
		{
			template = buildNewContext(state, context);
		}
		else if (mode.equals("edit"))
		{
			template = buildEditContext(state, context);
		}
		else if (mode.equals("confirm"))
		{
			template = buildConfirmRemoveContext(state, context);
		}
		else
		{
			Log.warn("chef", "UsersAction: mode: " + mode);
			template = buildListContext(state, context);
		}

		try {
			File orgsFile = new File(configDirectory + "organizations.txt");
 			BufferedReader in = new BufferedReader(
				new InputStreamReader(new FileInputStream(orgsFile), "UTF8"));
			String singleLine;
 
			while ((singleLine = in.readLine()) != null) {
				orgList.add(singleLine);
			}
 
            in.close();
	    } 
	    catch (UnsupportedEncodingException e) 
	    {
			Log.warn("chef", e.getMessage());
	    } 
	    catch (IOException e) 
	    {
			Log.warn("chef", e.getMessage());
	    }
	    catch (Exception e)
	    {
			Log.warn("chef", e.getMessage());
	    }

		String prefix = (String) getContext(rundata).get("template");
		return prefix + template;

	} // buildNormalContext

	/**
	 * Build the context for the main list mode.
	 */
	private String buildListContext(SessionState state, Context context)
	{
		// put the service in the context
		context.put("service", UserDirectoryService.getInstance());
	
		List<User> users = (List<User>) prepPage(state);
		HashMap<String,String> orgs = new HashMap(); 
		HashMap<String,String> cats = new HashMap(); 
		
		for (User u : users) {
			try {
				String id = UserDirectoryService.getUserId(u.getEid());
				orgs.put(id,getUserProperty(state,id,organizationPropertyName));
				cats.put(id,getUserProperty(state,id,categoryPropertyName));
			} catch (UserNotDefinedException e)
			{
			}
		}
		
		// put all (internal) users into the context
		context.put("users", users);
		context.put("organizations", orgs);
		context.put("categories", cats);

		// build the menu
		Menu bar = new MenuImpl();
		if (UserDirectoryService.allowAddUser())
		{
			bar.add(new MenuEntry(rb.getString("useact.newuse"), null, true, MenuItem.CHECKED_NA, "doNew"));
		}

		// add the paging commands
		//addListPagingMenus(bar, state);
		int pageSize = Integer.valueOf(state.getAttribute(STATE_PAGESIZE).toString()).intValue();
		int currentPageNubmer = Integer.valueOf(state.getAttribute(STATE_CURRENT_PAGE).toString()).intValue();
		int startNumber = pageSize * (currentPageNubmer - 1) + 1;
		int endNumber = pageSize * currentPageNubmer;

		int totalNumber = 0;
		Object[] params;
		ArrayList list = new ArrayList();
		list.add(new Integer[]{Integer.valueOf(5)});
		list.add(new Integer[]{Integer.valueOf(10)});
		list.add(new Integer[]{Integer.valueOf(20)});
		list.add(new Integer[]{Integer.valueOf(50)});
		list.add(new Integer[]{Integer.valueOf(100)});
		list.add(new Integer[]{Integer.valueOf(200)});

		try
		{
			totalNumber = Integer.valueOf(state.getAttribute(STATE_NUM_MESSAGES).toString()).intValue();
		}
		catch (java.lang.NullPointerException ignore) {}
		catch (java.lang.NumberFormatException ignore) {}

		if (totalNumber < endNumber) endNumber = totalNumber;

		params = new Object[]{startNumber, endNumber, totalNumber};

		context.put("startNumber", Integer.valueOf(startNumber));
		context.put("endNumber", Integer.valueOf(endNumber));
		context.put("totalNumber", Integer.valueOf(totalNumber));
		context.put("params", params);
		context.put("list", list);
		pagingInfoToContext(state, context);

		// add the search commands
		addSearchMenus(bar, state);

		// add the refresh commands
		addRefreshMenus(bar, state);

		if (bar.size() > 0)
		{
			context.put(Menu.CONTEXT_MENU, bar);
		}

		return "_list";

	} // buildListContext

	/**
	 * Build the context for the new user mode.
	 */
	private String buildNewContext(SessionState state, Context context)
	{
		// put the service in the context
		context.put("service", UserDirectoryService.getInstance());

		// name the html form for user edit fields
		context.put("form-name", "user-form");
		
		// include the password fields?
		context.put("incPw", state.getAttribute("include-password"));

		context.put("incType", Boolean.valueOf(true));

		context.put("superUser", Boolean.valueOf(SecurityService.isSuperUser()));

		String value = (String) state.getAttribute("valueEid");
		if (value != null) context.put("valueEid", value);

		value = (String) state.getAttribute("valueFirstName");
		if (value != null) context.put("valueFirstName", value);

		value = (String) state.getAttribute("valueLastName");
		if (value != null) context.put("valueLastName", value);

		value = (String) state.getAttribute("valueEmail");
		if (value != null) context.put("valueEmail", value);

		value = (String) state.getAttribute("valueType");
		if (value != null) context.put("valueType", value);

		value = (String) state.getAttribute("valueOrganization");
		if (value != null) context.put("valueOrganization", value);

		value = (String) state.getAttribute("valueCategory");
		if (value != null) context.put("valueCategory", value);

		context.put("orgList", orgList);
		
		return "_edit";
	} // buildNewContext

	/**
	 * Build the context for the create user mode.
	 */
	private String buildCreateContext(SessionState state, Context context)
	{
		// put the service in the context
		context.put("service", UserDirectoryService.getInstance());

		// is the type to be pre-set
		context.put("type", state.getAttribute("create-type"));

		// password is required when using Gateway New Account tool
		// attribute "create-user" is true only for New Account tool
		context.put("pwRequired", state.getAttribute("create-user"));

		String value = (String) state.getAttribute("valueEid");
		if (value != null) context.put("valueEid", value);

		value = (String) state.getAttribute("valueFirstName");
		if (value != null) context.put("valueFirstName", value);

		value = (String) state.getAttribute("valueLastName");
		if (value != null) context.put("valueLastName", value);

		value = (String) state.getAttribute("valueEmail");
		if (value != null) context.put("valueEmail", value);

		value = (String) state.getAttribute("valueOrganization");
		if (value != null) context.put("valueOrganization", value);
		
		value = (String) state.getAttribute("valueCategory");
		if (value != null) context.put("valueCategory", value);
		
		if ((Boolean)state.getAttribute("user.recaptcha-enabled"))
		{
			ReCaptcha captcha = ReCaptchaFactory.newReCaptcha((String)state.getAttribute("user.recaptcha-public-key"), (String)state.getAttribute("user.recaptcha-private-key"), false);
	        String captchaScript = captcha.createRecaptchaHtml((String)state.getAttribute("recaptcha-error"), null);
	        state.removeAttribute("recaptcha-error");
	        context.put("recaptchaScript", captchaScript);
		}

		context.put("orgList", orgList);
		
		return "_create";

	} // buildCreateContext

	/**
	 * Build the context for the edit user mode.
	 */
	private String buildEditContext(SessionState state, Context context)
	{
		
		// put the service in the context
		context.put("service", UserDirectoryService.getInstance());

		// name the html form for user edit fields
		context.put("form-name", "user-form");

		// get the user to edit
		UserEdit user = (UserEdit) state.getAttribute("user");
		context.put("user", user);
		
		// is super user/admin user?
		context.put("superUser", Boolean.valueOf(SecurityService.isSuperUser()));

		// include the password fields?
		context.put("incPw", state.getAttribute("include-password"));

		// include type fields (not if single user)
		boolean singleUser = ((Boolean) state.getAttribute("single-user")).booleanValue();
		context.put("incType", Boolean.valueOf(!singleUser));

		// build the menu
		// we need the form fields for the remove...
		boolean menuPopulated = false;
		Menu bar = new MenuImpl();
		if ((!singleUser) && (UserDirectoryService.allowRemoveUser(user.getId())))
		{
			bar.add(new MenuEntry(rb.getString("useact.remuse"), null, true, MenuItem.CHECKED_NA, "doRemove", "user-form"));
			menuPopulated = true;
		}

		if (menuPopulated)
		{
			context.put(Menu.CONTEXT_MENU, bar);
		}

		String value = (String) state.getAttribute("valueEid");
		if (value != null) context.put("valueEid", value);

		value = (String) state.getAttribute("valueFirstName");
		if (value != null) context.put("valueFirstName", value);

		value = (String) state.getAttribute("valueLastName");
		if (value != null) context.put("valueLastName", value);

		value = (String) state.getAttribute("valueEmail");
		if (value != null) context.put("valueEmail", value);

		value = (String) state.getAttribute("valueType");
		if (value != null) context.put("valueType", value);

		value = (String) state.getAttribute("valueOrganization");
		if (value != null) context.put("valueOrganization", value);

		value = (String) state.getAttribute("valueCategory");
		if (value != null) context.put("valueCategory", value);

		context.put("orgList", orgList);

		return "_edit";

	} // buildEditContext

	/**
	 * Build the context for the view user mode.
	 */
	private String buildViewContext(SessionState state, Context context)
	{
		if (Log.getLogger("chef").isDebugEnabled())
		{
			Log.debug("chef", this + ".buildViewContext");
		}

		// get current user's id
		String id = (String) state.getAttribute("user-id");

		// get the user and put in state as "user"
		try
		{
			User user = UserDirectoryService.getUser(id);
			context.put("user", user);

			String organization = getUserProperty(state, id, organizationPropertyName);
			context.put("userOrganization", organization);
			
			String category = getUserProperty(state, id, categoryPropertyName);
			context.put("userCategory", category);
			
			// name the html form for user edit fields
			context.put("form-name", "user-form");

			state.setAttribute("mode", "view");

			// make sure we can do an edit
			try
			{
				UserEdit edit = UserDirectoryService.editUser(id);
				UserDirectoryService.cancelEdit(edit);
				context.put("enableEdit", "true");
			}
			catch (UserNotDefinedException e)
			{
			}
			catch (UserPermissionException e)
			{
			}
			catch (UserLockedException e)
			{
			}

			// disable auto-updates while not in list mode
			disableObservers(state);
		}
		catch (UserNotDefinedException e)
		{
			Log.warn("chef", "UsersAction.doEdit: user not found: " + id);

			Object[] params = new Object[]{id};
			addAlert(state, rb.getFormattedMessage("useact.use_notfou", params));
			state.removeAttribute("mode");

			// make sure auto-updates are enabled
			enableObserver(state);
		}

		return "_view";

	} // buildViewContext

	/**
	 * Build the context for the new user mode.
	 */
	private String buildConfirmRemoveContext(SessionState state, Context context)
	{
		// get the user to edit
		UserEdit user = (UserEdit) state.getAttribute("user");
		context.put("user", user);

		return "_confirm_remove";

	} // buildConfirmRemoveContext

	/**
	 * doNew called when "eventSubmit_doNew" is in the request parameters to add a new user
	 */
	public void doNew(RunData data, Context context)
	{
		SessionState state = ((JetspeedRunData) data).getPortletSessionState(((JetspeedRunData) data).getJs_peid());
		state.setAttribute("mode", "new");

		// mark the user as new, so on cancel it can be deleted
		state.setAttribute("new", "true");

		// disable auto-updates while not in list mode
		disableObservers(state);

	} // doNew

	/**
	 * doEdit called when "eventSubmit_doEdit" is in the request parameters to edit a user
	 */
	public void doEdit(RunData data, Context context)
	{
		SessionState state = ((JetspeedRunData) data).getPortletSessionState(((JetspeedRunData) data).getJs_peid());
		String id = data.getParameters().getString("id");
		state.removeAttribute("user");
		state.removeAttribute("newuser");

		// get the user
		try
		{
			UserEdit user = UserDirectoryService.editUser(id);
			state.setAttribute("user", user);
			String organization = getUserProperty(state, id, organizationPropertyName);
			if (organization != null) {
				state.setAttribute("userOrganization", organization);
			}

			String category = getUserProperty(state, id, categoryPropertyName);
			if (category != null) {
				state.setAttribute("userCategory", category);
			}

			state.setAttribute("mode", "edit");

			// disable auto-updates while not in list mode
			disableObservers(state);
		}
		catch (UserNotDefinedException e)
		{
			Log.warn("chef", "UsersAction.doEdit: user not found: " + id);

			Object[] params = new Object[]{id};
			addAlert(state, rb.getFormattedMessage("useact.use_notfou", params));
			state.removeAttribute("mode");

			// make sure auto-updates are enabled
			enableObserver(state);
		}
		catch (UserPermissionException e)
		{
			addAlert(state, rb.getFormattedMessage("useact.youdonot1", new Object[]{id}));
			state.removeAttribute("mode");

			// make sure auto-updates are enabled
			enableObserver(state);
		}
		catch (UserLockedException e)
		{
			addAlert(state, rb.getFormattedMessage("useact.somels", new Object[]{id}));
			state.removeAttribute("mode");

			// make sure auto-updates are enabled
			enableObserver(state);
		}

	} // doEdit

	/**
	 * doModify called when "eventSubmit_doModify" is in the request parameters to edit a user
	 */
	public void doModify(RunData data, Context context)
	{
		if (Log.getLogger("chef").isDebugEnabled())
		{
			Log.debug("chef", this + ".doModify");
		}

		SessionState state = ((JetspeedRunData) data).getPortletSessionState(((JetspeedRunData) data).getJs_peid());
		String id = data.getParameters().getString("id");
		state.removeAttribute("user");
		state.removeAttribute("newuser");

		// get the user
		try
		{
			UserEdit user = UserDirectoryService.editUser(id);
			state.setAttribute("user", user);
			String organization = getUserProperty(state, id, organizationPropertyName);
			if (organization != null) {
				state.setAttribute("userOrganization", organization);
			}

			String category = getUserProperty(state, id, categoryPropertyName);
			if (category != null) {
				state.setAttribute("userCategory", category);
			}

			state.setAttribute("mode", "edit");

			// disable auto-updates while not in list mode
			disableObservers(state);
		}
		catch (UserNotDefinedException e)
		{
			Log.warn("chef", "UsersAction.doEdit: user not found: " + id);

			Object[] params = new Object[]{id};
			addAlert(state, rb.getFormattedMessage("useact.use_notfou", params));
			state.removeAttribute("mode");

			// make sure auto-updates are enabled
			enableObserver(state);
		}
		catch (UserPermissionException e)
		{
			addAlert(state, rb.getFormattedMessage("useact.youdonot1", new Object[]{id}));
			state.removeAttribute("mode");

			// make sure auto-updates are enabled
			enableObserver(state);
		}
		catch (UserLockedException e)
		{
			addAlert(state, rb.getFormattedMessage("useact.somels", new Object[]{id}));
			state.removeAttribute("mode");

			// make sure auto-updates are enabled
			enableObserver(state);
		}

	} // doModify

	/**
	 * doSave called when "eventSubmit_doSave" is in the request parameters to save user edits
	 */
	public void doSave(RunData data, Context context)
	{
		SessionState state = ((JetspeedRunData) data).getPortletSessionState(((JetspeedRunData) data).getJs_peid());
		
		if (!"POST".equals(data.getRequest().getMethod())) {
			return;
		}

		// read the form - if rejected, leave things as they are
		if (!readUserForm(data, state)) return;

		// commit the change
		UserEdit edit = (UserEdit) state.getAttribute("user");
		if (edit != null)
		{
			try
			{
				UserDirectoryService.commitEdit(edit);
				String eid = (String) state.getAttribute("valueEid");
				String id = UserDirectoryService.getUserId(eid);
				String organization = (String) state.getAttribute("valueOrganization");
				setUserProperty(state, id, organizationPropertyName, organization);
				String category = (String) state.getAttribute("valueCategory");
				setUserProperty(state, id, categoryPropertyName, category);
			}
			catch (UserAlreadyDefinedException e)
			{
				// TODO: this means the EID value is not unique... when we implement EID fully, we need to check this and send it back to the user
				Log.warn("chef", "UsersAction.doSave()" + e);
				addAlert(state, rb.getString("useact.theuseid1"));
				return;
			} catch (UserNotDefinedException e) {
				addAlert(state, rb.getString("useprop.notset"));
				return;
			}
		}

		User user = edit;
		if (user == null)
		{
			user = (User) state.getAttribute("newuser");

			String id = user.getId();
			String organization = (String) state.getAttribute("valueOrganization");
			setUserProperty(state, id, organizationPropertyName, organization);
			String category = (String) state.getAttribute("valueCategory");
			setUserProperty(state, id, categoryPropertyName, category);
		}

		// cleanup
		state.removeAttribute("user");
		state.removeAttribute("newuser");
		state.removeAttribute("new");
		state.removeAttribute("valueEid");
		state.removeAttribute("valueFirstName");
		state.removeAttribute("valueLastName");
		state.removeAttribute("valueEmail");
		state.removeAttribute("valueType");
		state.removeAttribute("valueOrganization");
		state.removeAttribute("userOrganization");
		state.removeAttribute("valueCategory");
		state.removeAttribute("userCategory");

		// return to main mode
		state.removeAttribute("mode");

		// make sure auto-updates are enabled
		enableObserver(state);

		if ((user != null) && ((Boolean) state.getAttribute("create-login")).booleanValue())
		{
			try
			{
				// login - use the fact that we just created the account as external evidence
				Evidence e = new ExternalTrustedEvidence(user.getEid());
				Authentication a = AuthenticationManager.authenticate(e);
				if (!UsageSessionService.login(a, (HttpServletRequest) ThreadLocalManager.get(RequestFilter.CURRENT_HTTP_REQUEST)))
				{
					addAlert(state, rb.getString("useact.tryloginagain"));
				}
			}
			catch (AuthenticationException ex)
			{
				Log.warn("chef", "UsersAction.doSave: authentication failure: " + ex);
			}

			// redirect to home (on next build)
			state.setAttribute("redirect", "");
		}

	} // doSave

	/**
	 * doCancel called when "eventSubmit_doCancel" is in the request parameters to cancel user edits
	 */
	public void doCancel(RunData data, Context context)
	{
		SessionState state = ((JetspeedRunData) data).getPortletSessionState(((JetspeedRunData) data).getJs_peid());
		
		if (!"POST".equals(data.getRequest().getMethod())) {
			return;
		}

		// get the user
		UserEdit user = (UserEdit) state.getAttribute("user");
		if (user != null)
		{
			// if this was a new, delete the user
			if ("true".equals(state.getAttribute("new")))
			{
				// remove
				try
				{
					UserDirectoryService.removeUser(user);
				}
				catch (UserPermissionException e)
				{
					addAlert(state, rb.getFormattedMessage("useact.youdonot2", new Object[]{user.getId()}));
				}
			}
			else
			{
				UserDirectoryService.cancelEdit(user);
			}
		}

		// cleanup
		state.removeAttribute("user");
		state.removeAttribute("newuser");
		state.removeAttribute("new");
		state.removeAttribute("valueEid");
		state.removeAttribute("valueFirstName");
		state.removeAttribute("valueLastName");
		state.removeAttribute("valueEmail");
		state.removeAttribute("valueType");
		state.removeAttribute("valueOrganization");
		state.removeAttribute("userOrganization");
		state.removeAttribute("valueCategory");
		state.removeAttribute("userCategory");

		// return to main mode
		state.removeAttribute("mode");

		// make sure auto-updates are enabled
		enableObserver(state);

	} // doCancel

	/**
	 * doRemove called when "eventSubmit_doRemove" is in the request par ameters to confirm removal of the user
	 */
	public void doRemove(RunData data, Context context)
	{
		SessionState state = ((JetspeedRunData) data).getPortletSessionState(((JetspeedRunData) data).getJs_peid());
		
		// set mode so we can skip some checks in readUserForm
		state.setAttribute("mode", "remove");

		// read the form - if rejected, leave things as they are
		if (!readUserForm(data, state)) return;

		// go to remove confirm mode
		state.setAttribute("mode", "confirm");

	} // doRemove

	/**
	 * doRemove_confirmed called when "eventSubmit_doRemove_confirmed" is in the request parameters to remove the user
	 */
	public void doRemove_confirmed(RunData data, Context context)
	{
		SessionState state = ((JetspeedRunData) data).getPortletSessionState(((JetspeedRunData) data).getJs_peid());
		
		if (!"POST".equals(data.getRequest().getMethod())) {
			return;
		}

		// get the user
		UserEdit user = (UserEdit) state.getAttribute("user");

		// remove
		try
		{
			UserDirectoryService.removeUser(user);
		}
		catch (UserPermissionException e)
		{
			addAlert(state, rb.getFormattedMessage("useact.youdonot2", new Object[]{user.getId()}));
		}

		// cleanup
		state.removeAttribute("user");
		state.removeAttribute("newuser");
		state.removeAttribute("new");
		state.removeAttribute("valueEid");
		state.removeAttribute("valueFirstName");
		state.removeAttribute("valueLastName");
		state.removeAttribute("valueEmail");
		state.removeAttribute("valueType");
		state.removeAttribute("valueOrganization");
		state.removeAttribute("userOrganization");
		state.removeAttribute("valueCategory");
		state.removeAttribute("userCategory");

		// go to main mode
		state.removeAttribute("mode");

		// make sure auto-updates are enabled
		enableObserver(state);

	} // doRemove_confirmed

	/**
	 * doCancel_remove called when "eventSubmit_doCancel_remove" is in the request parameters to cancel user removal
	 */
	public void doCancel_remove(RunData data, Context context)
	{
		SessionState state = ((JetspeedRunData) data).getPortletSessionState(((JetspeedRunData) data).getJs_peid());
		
		if (!"POST".equals(data.getRequest().getMethod())) {
			return;
		}

		// return to edit mode
		state.setAttribute("mode", "edit");

	} // doCancel_remove

	/**
	 * Read the user form and update the user in state.
	 * 
	 * @return true if the form is accepted, false if there's a validation error (an alertMessage will be set)
	 */
	private boolean readUserForm(RunData data, SessionState state)
	{
		// boolean parameters and values
		// --------------Mode--singleUser-createUser-typeEnable
		// Admin New-----new---false------false------true
		// Admin Update--edit--false------false------true
		// Gateway New---null---false------true-------false
		// Account Edit--edit--true-------false------false

		// read the form
		String id = StringUtils.trimToNull(data.getParameters().getString("id"));
		String eid = StringUtils.trimToNull(data.getParameters().getString("eid"));
		state.setAttribute("valueEid", eid);
		String firstName = StringUtils.trimToNull(data.getParameters().getString("first-name"));
		state.setAttribute("valueFirstName", firstName);
		String lastName = StringUtils.trimToNull(data.getParameters().getString("last-name"));
		state.setAttribute("valueLastName", lastName);
		String email = StringUtils.trimToNull(data.getParameters().getString("email"));
		state.setAttribute("valueEmail", email);
		String organization = StringUtils.trimToNull(data.getParameters().getString("organization"));
		state.setAttribute("valueOrganization", organization);
		String category = StringUtils.trimToNull(data.getParameters().getString("category"));
		state.setAttribute("valueCategory", category);
		String pw = StringUtils.trimToNull(data.getParameters().getString("pw"));
        String pwConfirm = StringUtils.trimToNull(data.getParameters().getString("pw0"));
        String pwcur = StringUtils.trimToNull(data.getParameters().getString("pwcur"));
       	String mode = (String) state.getAttribute("mode");

		boolean singleUser = ((Boolean) state.getAttribute("single-user")).booleanValue();
		boolean createUser = ((Boolean) state.getAttribute("create-user")).booleanValue();

		boolean typeEnable = false;
		String type = null;

		if ((mode != null) && (mode.equalsIgnoreCase("new")))
		{
			typeEnable = true;
		}
		else if ((mode != null) && (mode.equalsIgnoreCase("edit")) && (!singleUser))
		{
			typeEnable = true;
		}

		if (typeEnable)
		{
			// for the case of Admin User tool creating new user
			type = StringUtils.trimToNull(data.getParameters().getString("type"));
			state.setAttribute("valueType", type);
		}
		else
		{
			if (createUser)
			{
				// for the case of Gateway Account tool creating new user
				type = (String) state.getAttribute("create-type");
			}
		}
		
		if ((Boolean)state.getAttribute("user.recaptcha-enabled"))
		{
			String challengeField = data.getParameters().getString("recaptcha_challenge_field");
			String responseField = data.getParameters().getString("recaptcha_response_field");
			if (challengeField == null) challengeField = "";
			if (responseField == null) responseField = "";
			ReCaptcha captcha = ReCaptchaFactory.newReCaptcha((String)state.getAttribute("user.recaptcha-public-key"), (String)state.getAttribute("user.recaptcha-private-key"), false);
			ReCaptchaResponse response = captcha.checkAnswer(data.getRequest().getRemoteAddr(), challengeField, responseField);
			if (!response.isValid())
			{
				addAlert(state, rb.getString("useact.capterr"));
		        state.setAttribute("recaptcha-error", response.getErrorMessage());
				return false;
			}
		}
		
		
		//insure valid email address
		//email.matches(".+ at .+\\..+")
		if(email != null && !EmailValidator.getInstance().isValid(email)) {
				addAlert(state, rb.getString("useact.invemail"));	
				return false;
		}

		// get the user
		UserEdit user = (UserEdit) state.getAttribute("user");

		// add if needed
		if (user == null)
		{
			// make sure we have eid
			if (eid == null)
			{
				addAlert(state, rb.getString("usecre.eidmis"));
				return false;
			}
			
			// if in create mode, make sure we have a password
			if (createUser)
			{
				if (pw == null)
				{
					addAlert(state, rb.getString("usecre.pasismis"));
					return false;
				}				
			}

			// make sure we have matching password fields
			if (StringUtil.different(pw, pwConfirm))
			{
				addAlert(state, rb.getString("usecre.pass"));
				return false;
			}

			//At CUDI we want all fields filled.
			if (email == null)
			{
				addAlert(state, rb.getString("usecre.emailmis"));
				return false;
			}

			if (firstName == null)
			{
				addAlert(state, rb.getString("usecre.fnamemis"));
				return false;
			}

			if (lastName == null)
			{
				addAlert(state, rb.getString("usecre.lnamemis"));
				return false;
			}

			if (organization == null)
			{
				addAlert(state, rb.getString("usecre.orgmis"));
				return false;
			}

			if (category == null)
			{
				addAlert(state, rb.getString("usecre.catmis"));
				return false;
			}

			try
			{
				// add the user in one step so that all you need is add not update permission
				// (the added might be "anon", and anon has add but not update permission)
				
				//SAK-18209 only an admin user should be able to specify a ID
				if (!SecurityService.isSuperUser()) {
					id = null;
				}
				User newUser = UserDirectoryService.addUser(id, eid, firstName, lastName, email, pw, type, null);

				// put the user in the state
				state.setAttribute("newuser", newUser);
			}
			catch (UserAlreadyDefinedException e)
			{
				addAlert(state, rb.getString("useact.theuseid1"));
				return false;
			}
			catch (UserIdInvalidException e)
			{
				addAlert(state, rb.getString("useact.theuseid2"));
				return false;
			}
			catch (UserPermissionException e)
			{
				addAlert(state, rb.getString("useact.youdonot3"));
				return false;
			}
		}

		// update
		else
		{
			if (!user.isActiveEdit())
			{
				try
				{
					// add the user in one step so that all you need is add not update permission
					// (the added might be "anon", and anon has add but not update permission)
					user = UserDirectoryService.editUser(user.getId());
	
					// put the user in the state
					state.setAttribute("user", user);

					String uorganization = getUserProperty(state, user.getId(), organizationPropertyName);
					if (uorganization != null) {
						state.setAttribute("userOrganization", uorganization);
					}
					String ucategory = getUserProperty(state, user.getId(), categoryPropertyName);
					if (ucategory != null) {
						state.setAttribute("userCategory", ucategory);
					}
				}
				catch (UserLockedException e)
				{
					addAlert(state, rb.getString("useact.somels"));
					return false;
				}
				catch (UserNotDefinedException e)
				{
					Object[] params = new Object[]{id};
					addAlert(state, rb.getFormattedMessage("useact.use_notfou", params));
					
					return false;
				}
				catch (UserPermissionException e)
				{
					addAlert(state, rb.getString("useact.youdonot3"));
					return false;
				}
			}
			
			// eid, pw, type might not be editable
			if (eid != null) user.setEid(eid);
			user.setFirstName(firstName);
			user.setLastName(lastName);
			user.setEmail(email);
			if (type != null) user.setType(type);
			

			if (mode == null || !mode.equalsIgnoreCase("remove")) {
				// make sure we have matching password fields
				if (StringUtil.different(pw, pwConfirm))
				{
					addAlert(state, rb.getString("usecre.pass"));
					return false;
				}
	
				if (pw != null) user.setPassword(pw);
			}

			//At CUDI we want all fields filled.
			if (email == null)
			{
				addAlert(state, rb.getString("usecre.emailmis"));
				return false;
			}

			if (firstName == null)
			{
				addAlert(state, rb.getString("usecre.fnamemis"));
				return false;
			}

			if (lastName == null)
			{
				addAlert(state, rb.getString("usecre.lnamemis"));
				return false;
			}

			if (organization == null)
			{
				addAlert(state, rb.getString("usecre.orgmis"));
				return false;
			}

			if (category == null)
			{
				addAlert(state, rb.getString("usecre.catmis"));
				return false;
			}	
		}
		return true;
	}

	private String getUserProperty (SessionState state, String userId, String pName) {
		
		Preferences prefs;

		Log.info("chef", "UsersAction.getUserProperty: " + userId);
		
		try {
			prefs = PreferencesService.getPreferences(userId);			
		} catch (Exception e) {
			return null;
		}
		
		ResourceProperties props = prefs.getProperties();
		return props.getProperty(pName);
	}

	private void setUserProperty (SessionState state, String userId, String pName, String pValue) {
		
		PreferencesEdit prefs;

		try {
			try {
				prefs = PreferencesService.edit(userId);
			} catch (Exception e) {
				// We assume any exception here means the preferences has not been created.
				prefs = PreferencesService.add(userId);
			}
			ResourcePropertiesEdit props = prefs.getPropertiesEdit();
			props.addProperty(pName, pValue);
			PreferencesService.commit(prefs);
		} catch (Exception e) {
			addAlert(state, rb.getString("useprop.notset") + " userId: " + userId + "Msg: " + e.getMessage());
		}
	}
}


More information about the sakai-dev mailing list