NIHVIVO-2279 First stab at UserAccountsListController

This commit is contained in:
j2blake 2011-05-06 14:53:47 +00:00
parent 9994b120da
commit 63b0633e35
13 changed files with 696 additions and 7 deletions

View file

@ -776,6 +776,7 @@
<url-pattern>/addRestriction</url-pattern> <url-pattern>/addRestriction</url-pattern>
</servlet-mapping> </servlet-mapping>
<!-- TODO This should go away as soon as the new UserAccounts are fully implemented. jblake -->
<servlet> <servlet>
<servlet-name>UsersListingController</servlet-name> <servlet-name>UsersListingController</servlet-name>
<servlet-class>edu.cornell.mannlib.vitro.webapp.controller.edit.listing.UsersListingController</servlet-class> <servlet-class>edu.cornell.mannlib.vitro.webapp.controller.edit.listing.UsersListingController</servlet-class>
@ -785,6 +786,15 @@
<url-pattern>/listUsers</url-pattern> <url-pattern>/listUsers</url-pattern>
</servlet-mapping> </servlet-mapping>
<servlet>
<servlet-name>UserAccountsList</servlet-name>
<servlet-class>edu.cornell.mannlib.vitro.webapp.controller.accounts.UserAccountsListController</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>UserAccountsList</servlet-name>
<url-pattern>/listUserAccounts</url-pattern>
</servlet-mapping>
<servlet> <servlet>
<servlet-name>StatementChangeListingController</servlet-name> <servlet-name>StatementChangeListingController</servlet-name>
<servlet-class>edu.cornell.mannlib.vitro.webapp.controller.edit.listing.jena.StatementChangeListingController</servlet-class> <servlet-class>edu.cornell.mannlib.vitro.webapp.controller.edit.listing.jena.StatementChangeListingController</servlet-class>

View file

@ -0,0 +1,11 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.auth.permissions;
/**
* Base class that describes a unit of authorization, or permission to perform
* requested actions.
*/
public abstract class Permission {
// no members
}

View file

@ -0,0 +1,40 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.auth.permissions;
import java.util.Set;
/**
* Reflects a collection of Permissions that can be made available to a user.
* Similar to the concept of a Role.
*/
public class PermissionSet {
private String uri;
private String label;
private Set<Permission> permissions;
public String getUri() {
return uri;
}
public void setUri(String uri) {
this.uri = uri;
}
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
public Set<Permission> getPermissions() {
return permissions;
}
public void setPermissions(Set<Permission> permissions) {
this.permissions = permissions;
}
}

View file

@ -11,6 +11,7 @@ import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.List; import java.util.List;
import java.util.Map;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.ServletRequest; import javax.servlet.ServletRequest;
@ -205,4 +206,16 @@ public class VitroHttpServlet extends HttpServlet {
"accept-language", "accept-encoding", "accept-charset", "accept-language", "accept-encoding", "accept-charset",
"keep-alive", "connection" })); "keep-alive", "connection" }));
/**
* A child class may call this if logging is set to debug level.
*/
protected void dumpRequestParameters(HttpServletRequest req) {
@SuppressWarnings("unchecked")
Map<String, String[]> map = req.getParameterMap();
for (String key : map.keySet()) {
String[] values = map.get(key);
log.debug("Parameter '" + key + "' = "
+ Arrays.deepToString(values));
}
}
} }

View file

@ -0,0 +1,81 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.controller.accounts;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import edu.cornell.mannlib.vitro.webapp.auth.permissions.PermissionSet;
import edu.cornell.mannlib.vitro.webapp.dao.PermissionSetDao;
/**
* TODO Destroy this as soon as PermissionSetDaoJena is in place.
*/
public class BogusPermissionSetDao implements PermissionSetDao {
private static final Log log = LogFactory
.getLog(BogusPermissionSetDao.class);
private final Map<String, PermissionSet> map;
public BogusPermissionSetDao() {
Map<String, PermissionSet> psMap = new HashMap<String, PermissionSet>();
putPermissionSet(psMap, createDbaPermissionSet());
putPermissionSet(psMap, createCuratorPermissionSet());
putPermissionSet(psMap, createEditorPermissionSet());
putPermissionSet(psMap, createSelfEditorPermissionSet());
this.map = Collections.unmodifiableMap(psMap);
}
private void putPermissionSet(Map<String, PermissionSet> psMap,
PermissionSet ps) {
psMap.put(ps.getUri(), ps);
}
private PermissionSet createDbaPermissionSet() {
PermissionSet ps = new PermissionSet();
ps.setUri("http://vivo.mydomain.edu/individual/role1");
ps.setLabel("DBA");
return ps;
}
private PermissionSet createCuratorPermissionSet() {
PermissionSet ps = new PermissionSet();
ps.setUri("http://vivo.mydomain.edu/individual/role2");
ps.setLabel("Curator");
return ps;
}
private PermissionSet createEditorPermissionSet() {
PermissionSet ps = new PermissionSet();
ps.setUri("http://vivo.mydomain.edu/individual/role3");
ps.setLabel("Editor");
return ps;
}
private PermissionSet createSelfEditorPermissionSet() {
PermissionSet ps = new PermissionSet();
ps.setUri("http://vivo.mydomain.edu/individual/role4");
ps.setLabel("Self-Editor");
return ps;
}
@Override
public PermissionSet getPermissionSetByUri(String uri) {
PermissionSet permissionSet = map.get(uri);
if (permissionSet == null) {
log.warn("Can't find a PermissionSet for uri '" + uri + "'");
}
return permissionSet;
}
@Override
public Collection<PermissionSet> getAllPermissionSets() {
return new ArrayList<PermissionSet>(map.values());
}
}

View file

@ -0,0 +1,307 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.controller.accounts;
import static edu.cornell.mannlib.vitro.webapp.controller.accounts.UserAccountsSelectionCriteria.DEFAULT_ACCOUNTS_PER_PAGE;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.hp.hpl.jena.ontology.OntModel;
import edu.cornell.mannlib.vitro.webapp.auth.permissions.PermissionSet;
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.Actions;
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.usepages.ManageUserAccounts;
import edu.cornell.mannlib.vitro.webapp.beans.UserAccount;
import edu.cornell.mannlib.vitro.webapp.beans.UserAccount.Status;
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
import edu.cornell.mannlib.vitro.webapp.controller.accounts.UserAccountsOrdering.Direction;
import edu.cornell.mannlib.vitro.webapp.controller.accounts.UserAccountsOrdering.Field;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.FreemarkerHttpServlet;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.TemplateResponseValues;
import edu.cornell.mannlib.vitro.webapp.dao.PermissionSetDao;
import edu.cornell.mannlib.vitro.webapp.dao.UserAccountDao;
import edu.cornell.mannlib.vitro.webapp.dao.jena.OntModelSelector;
/**
* Display the paginated list of User Accounts.
*/
public class UserAccountsListController extends FreemarkerHttpServlet {
private static final Log log = LogFactory
.getLog(UserAccountsListController.class);
public static final String PARAMETER_ACCOUNTS_PER_PAGE = "accountsPerPage";
public static final String PARAMETER_PAGE_INDEX = "pageIndex";
public static final String PARAMETER_ORDERING_DIRECTION = "orderDirection";
public static final String PARAMETER_ORDERING_FIELD = "orderField";
public static final String PARAMETER_ROLE_FILTER_URI = "roleFilterUri";
public static final String PARAMETER_SEARCH_TERM = "searchTerm";
public static final String PARAMETER_NEW_USER_URI = "newUserUri";
public static final String PARAMETER_UPDATED_USER_URI = "updatedUserUri";
public static final String FLAG_UPDATED_USER_PW = "updatedUserPw";
public static final String FLAG_USERS_DELETED = "usersDeleted";
private static final String TEMPLATE_NAME = "userAccounts-list.ftl";
private OntModel userAccountsModel;
private PermissionSetDao permissionSetDao;
private UserAccountDao userAccountDao;
@Override
public void init() throws ServletException {
super.init();
OntModelSelector oms = (OntModelSelector) getServletContext()
.getAttribute("baseOntModelSelector");
userAccountsModel = oms.getUserAccountsModel();
// TODO Fix this when we have a real framework for PermissionSetDao
permissionSetDao = new BogusPermissionSetDao();
}
@Override
protected Actions requiredActions(VitroRequest vreq) {
return new Actions(new ManageUserAccounts());
}
/**
* Assume the default criteria for display. Modify the criteria based on
* parameters in the request. Get the selected accounts and display them.
*/
@Override
protected ResponseValues processRequest(VitroRequest vreq) {
if (log.isDebugEnabled()) {
dumpRequestParameters(vreq);
}
Map<String, Object> body = new HashMap<String, Object>();
UserAccountsSelectionCriteria criteria = buildCriteria(vreq);
body.put("accountsPerPage", criteria.getAccountsPerPage());
body.put("pageIndex", criteria.getPageIndex());
body.put("orderDirection", criteria.getOrderBy().getDirection().keyword);
body.put("orderField", criteria.getOrderBy().getField().name);
body.put("roleFilterUri", criteria.getRoleFilterUri());
body.put("searchTerm", criteria.getSearchTerm());
UserAccountsSelection selection = UserAccountsSelector.select(
userAccountsModel, criteria);
body.put("accounts", wrapUserAccounts(selection));
body.put("total", selection.getResultCount());
body.put("page", buildPageMap(selection));
body.put("formUrl", buildFormUrl(vreq));
body.put("roles", buildRolesList());
body.put("messages", buildMessagesMap(vreq));
return new TemplateResponseValues(TEMPLATE_NAME, body);
}
private UserAccountsSelectionCriteria buildCriteria(VitroRequest vreq) {
int accountsPerPage = getIntegerParameter(vreq,
PARAMETER_ACCOUNTS_PER_PAGE, DEFAULT_ACCOUNTS_PER_PAGE);
int pageIndex = getIntegerParameter(vreq, PARAMETER_PAGE_INDEX, 1);
Direction orderingDirection = Direction.fromKeyword(vreq
.getParameter(PARAMETER_ORDERING_DIRECTION));
Field orderingField = Field.fromName(vreq
.getParameter(PARAMETER_ORDERING_FIELD));
UserAccountsOrdering ordering = new UserAccountsOrdering(orderingField,
orderingDirection);
String roleFilterUri = getStringParameter(vreq,
PARAMETER_ROLE_FILTER_URI, "");
String searchTerm = getStringParameter(vreq, PARAMETER_SEARCH_TERM, "");
return new UserAccountsSelectionCriteria(accountsPerPage, pageIndex,
ordering, roleFilterUri, searchTerm);
}
private String getStringParameter(VitroRequest vreq, String key,
String defaultValue) {
String value = vreq.getParameter(key);
return (value == null) ? defaultValue : value;
}
private int getIntegerParameter(VitroRequest vreq, String key,
int defaultValue) {
String value = vreq.getParameter(key);
if (value == null) {
return defaultValue;
}
try {
return Integer.parseInt(value);
} catch (NumberFormatException e) {
log.warn("Invalid integer for parameter '" + key + "': " + value);
return defaultValue;
}
}
private Map<String, Integer> buildPageMap(UserAccountsSelection selection) {
int currentPage = selection.getCriteria().getPageIndex();
float pageCount = ((float) selection.getResultCount())
/ selection.getCriteria().getAccountsPerPage();
int lastPage = (int) Math.ceil(pageCount);
Map<String, Integer> map = new HashMap<String, Integer>();
map.put("current", currentPage);
map.put("first", 1);
map.put("last", lastPage);
if (currentPage < lastPage) {
map.put("next", currentPage + 1);
}
if (currentPage > 1) {
map.put("previous", currentPage - 1);
}
return map;
}
private String buildFormUrl(VitroRequest vreq) {
UrlBuilder urlBuilder = new UrlBuilder(vreq.getAppBean());
return urlBuilder.getPortalUrl("/listUserAccounts");
}
private List<PermissionSet> buildRolesList() {
List<PermissionSet> list = new ArrayList<PermissionSet>();
list.addAll(permissionSetDao.getAllPermissionSets());
Collections.sort(list, new Comparator<PermissionSet>() {
@Override
public int compare(PermissionSet ps1, PermissionSet ps2) {
return ps1.getUri().compareTo(ps2.getUri());
}
});
return list;
}
private Map<String, Object> buildMessagesMap(VitroRequest vreq) {
Map<String, Object> map = new HashMap<String, Object>();
UserAccount newUser = getUserFromUriParameter(vreq,
PARAMETER_NEW_USER_URI);
if (newUser != null) {
map.put("newUser", newUser);
}
UserAccount updatedUser = getUserFromUriParameter(vreq,
PARAMETER_UPDATED_USER_URI);
if (updatedUser != null) {
map.put("updatedUser", updatedUser);
}
if (isFlagOnRequest(vreq, FLAG_UPDATED_USER_PW)) {
map.put("updatedUserPw", true);
}
if (isFlagOnRequest(vreq, FLAG_USERS_DELETED)) {
map.put("usersDeleted", true);
}
return map;
}
private UserAccount getUserFromUriParameter(VitroRequest vreq, String key) {
String uri = vreq.getParameter(key);
if ((uri == null) || uri.isEmpty()) {
return null;
}
return userAccountDao.getUserAccountByUri(uri);
}
private boolean isFlagOnRequest(VitroRequest vreq, String key) {
String value = vreq.getParameter(key);
return (value != null);
}
/**
* The UserAccount has a list of PermissionSetUris, but the Freemarker
* template needs a list of PermissionSet labels instead.
*/
private List<UserAccountWrapper> wrapUserAccounts(
UserAccountsSelection selection) {
List<UserAccountWrapper> list = new ArrayList<UserAccountWrapper>();
for (UserAccount account : selection.getUserAccounts()) {
list.add(new UserAccountWrapper(account,
findPermissionSetLabels(account)));
}
return list;
}
private List<String> findPermissionSetLabels(UserAccount account) {
List<String> labels = new ArrayList<String>();
for (String uri : account.getPermissionSetUris()) {
PermissionSet pSet = permissionSetDao.getPermissionSetByUri(uri);
if (pSet != null) {
labels.add(pSet.getLabel());
}
}
return labels;
}
/**
* Shows PermissionSet labels instead of PermissionSet URIs.
*/
public static class UserAccountWrapper {
private final UserAccount account;
private final List<String> permissionSets;
public UserAccountWrapper(UserAccount account,
List<String> permissionSets) {
this.account = account;
this.permissionSets = permissionSets;
}
public String getUri() {
return account.getUri();
}
public String getEmailAddress() {
return account.getEmailAddress();
}
public String getFirstName() {
return account.getFirstName();
}
public String getLastName() {
return account.getLastName();
}
public int getLoginCount() {
return account.getLoginCount();
}
public String getStatus() {
Status status = account.getStatus();
if (status == null) {
return "";
} else {
return status.toString();
}
}
public List<String> getPermissionSets() {
return permissionSets;
}
}
}

View file

@ -2,6 +2,7 @@
package edu.cornell.mannlib.vitro.webapp.controller.accounts; package edu.cornell.mannlib.vitro.webapp.controller.accounts;
/** /**
* How are the accounts to be sorted? * How are the accounts to be sorted?
*/ */
@ -9,6 +10,22 @@ public class UserAccountsOrdering {
public enum Direction { public enum Direction {
ASCENDING("ASC"), DESCENDING("DESC"); ASCENDING("ASC"), DESCENDING("DESC");
public static Direction DEFAULT_DIRECTION = ASCENDING;
public static Direction fromKeyword(String keyword) {
if (keyword == null) {
return DEFAULT_DIRECTION;
}
for (Direction d : Direction.values()) {
if (d.keyword.equals(keyword)) {
return d;
}
}
return DEFAULT_DIRECTION;
}
public final String keyword; public final String keyword;
Direction(String keyword) { Direction(String keyword) {
@ -20,15 +37,31 @@ public class UserAccountsOrdering {
EMAIL("email"), FIRST_NAME("firstName"), LAST_NAME("lastName"), STATUS( EMAIL("email"), FIRST_NAME("firstName"), LAST_NAME("lastName"), STATUS(
"status"), ROLE("ps"), LOGIN_COUNT("count"); "status"), ROLE("ps"), LOGIN_COUNT("count");
public final String variableName; public static Field DEFAULT_FIELD = EMAIL;
Field(String variableName) { public static Field fromName(String name) {
this.variableName = variableName; if (name == null) {
return DEFAULT_FIELD;
}
for (Field f : Field.values()) {
if (f.name.equals(name)) {
return f;
}
}
return DEFAULT_FIELD;
}
public final String name;
Field(String name) {
this.name = name;
} }
} }
public static final UserAccountsOrdering DEFAULT_ORDERING = new UserAccountsOrdering( public static final UserAccountsOrdering DEFAULT_ORDERING = new UserAccountsOrdering(
Field.EMAIL, Direction.ASCENDING); Field.DEFAULT_FIELD, Direction.DEFAULT_DIRECTION);
private final Field field; private final Field field;
private final Direction direction; private final Direction direction;

View file

@ -7,6 +7,8 @@ package edu.cornell.mannlib.vitro.webapp.controller.accounts;
* On what basis are we selecting user accounts? * On what basis are we selecting user accounts?
*/ */
public class UserAccountsSelectionCriteria { public class UserAccountsSelectionCriteria {
public static final int DEFAULT_ACCOUNTS_PER_PAGE = 25;
/** How many accounts should we bring back, at most? */ /** How many accounts should we bring back, at most? */
private final int accountsPerPage; private final int accountsPerPage;
@ -66,4 +68,5 @@ public class UserAccountsSelectionCriteria {
private <T> T nonNull(T t, T nullValue) { private <T> T nonNull(T t, T nullValue) {
return (t == null) ? nullValue : t; return (t == null) ? nullValue : t;
} }
} }

View file

@ -171,11 +171,11 @@ public class UserAccountsSelector {
private String ordering() { private String ordering() {
UserAccountsOrdering orderBy = criteria.getOrderBy(); UserAccountsOrdering orderBy = criteria.getOrderBy();
String keyword = orderBy.getDirection().keyword; String keyword = orderBy.getDirection().keyword;
String variable = orderBy.getField().variableName; String variable = orderBy.getField().name;
if (orderBy.getField() == Field.EMAIL) { if (orderBy.getField() == Field.EMAIL) {
return keyword + "(?" + variable + ")"; return keyword + "(?" + variable + ")";
} else { } else {
return keyword + "(?" + variable + ") ?" + Field.EMAIL.variableName; return keyword + "(?" + variable + ") ?" + Field.EMAIL.name;
} }
} }
@ -272,7 +272,7 @@ public class UserAccountsSelector {
user.setMd5password(ifLiteralPresent(solution, "pwd", "")); user.setMd5password(ifLiteralPresent(solution, "pwd", ""));
user.setPasswordChangeExpires(ifLongPresent(solution, "expire", 0L)); user.setPasswordChangeExpires(ifLongPresent(solution, "expire", 0L));
user.setLoginCount(ifIntPresent(solution, "count", 0)); user.setLoginCount(ifIntPresent(solution, "count", 0));
user.setStatus(parseStatus(solution, "status", Status.INACTIVE)); user.setStatus(parseStatus(solution, "status", null));
return user; return user;
} }

View file

@ -19,6 +19,7 @@ import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.Actions;
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.usepages.EditIndividuals; import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.usepages.EditIndividuals;
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.usepages.EditOntology; import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.usepages.EditOntology;
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.usepages.EditSiteInformation; import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.usepages.EditSiteInformation;
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.usepages.ManageUserAccounts;
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.usepages.SeeSiteAdminPage; import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.usepages.SeeSiteAdminPage;
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.usepages.UseAdvancedDataToolsPages; import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.usepages.UseAdvancedDataToolsPages;
import edu.cornell.mannlib.vitro.webapp.beans.VClassGroup; import edu.cornell.mannlib.vitro.webapp.beans.VClassGroup;
@ -123,9 +124,13 @@ public class SiteAdminController extends FreemarkerHttpServlet {
urls.put("tabs", urlBuilder.getPortalUrl("/listTabs")); urls.put("tabs", urlBuilder.getPortalUrl("/listTabs"));
} }
// TODO remove this when the UserAccounts are fully implemented. -- jblake
if (PolicyHelper.isAuthorizedForActions(vreq, UsersListingController.REQUIRED_ACTIONS)) { if (PolicyHelper.isAuthorizedForActions(vreq, UsersListingController.REQUIRED_ACTIONS)) {
urls.put("users", urlBuilder.getPortalUrl("/listUsers")); urls.put("users", urlBuilder.getPortalUrl("/listUsers"));
} }
if (PolicyHelper.isAuthorizedForActions(vreq, new ManageUserAccounts())) {
urls.put("userList", urlBuilder.getPortalUrl("/listUserAccounts"));
}
if (PolicyHelper.isAuthorizedForActions(vreq, new EditSiteInformation())) { if (PolicyHelper.isAuthorizedForActions(vreq, new EditSiteInformation())) {
urls.put("siteInfo", urlBuilder.getPortalUrl("/editForm", new ParamMap("controller", "ApplicationBean"))); urls.put("siteInfo", urlBuilder.getPortalUrl("/editForm", new ParamMap("controller", "ApplicationBean")));

View file

@ -0,0 +1,16 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.dao;
import java.util.Collection;
import edu.cornell.mannlib.vitro.webapp.auth.permissions.PermissionSet;
/**
* Methods for manipulating PermissionSets.
*/
public interface PermissionSetDao {
public PermissionSet getPermissionSetByUri(String uri);
public Collection<PermissionSet> getAllPermissionSets();
}

View file

@ -0,0 +1,36 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.dao;
import edu.cornell.mannlib.vitro.webapp.beans.UserAccount;
/**
* TODO
*/
public interface UserAccountDao {
public UserAccount getUserAccountByUri(String uri);
/**
* <pre>
* public User getUserByUsername(String username);
*
* public User getUserByURI(String URI);
*
* public List&lt;User&gt; getAllUsers();
*
* public void updateUser(User user);
*
* public String insertUser(User user);
*
* public void deleteUser(User user);
*
* public List&lt;String&gt; getIndividualsUserMayEditAs(String userURI);
*
* public List&lt;String&gt; getUserAccountEmails();
*
* public String getUserEmailAddress(String userURI);
* </pre>
*/
}

View file

@ -0,0 +1,134 @@
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
<#-- Template for displaying list of user accounts -->
<h2>
Accounts
</h2>
<div style="border: solid">
<form method="POST" action="${formUrl}">
<input type="submit" name="add" value="Add new account" />
<!-- When this is clicked, all other fields are ignored. -->
<input type="submit" name="delete" value="Delete selected accounts" />
<!-- When this is clicked, the checkboxes are noticed and all other fields are ignored. -->
<br>
current page: <input type="text" name="pageIndex" value="${page.current}" />
<br>
<!--
When roleFilterUri or searchTerm changes,
pageIndex should be set to 1. When any of these changes (including pageIndex), the form
should be submitted.
-->
show <input type="text" name="accountsPerPage" value="${accountsPerPage}" /> accounts per page
<!-- When accountsPerPage changes,
set pageIndex to 1
submit the form (submit action is "list") -->
<br>
sort order:
<!-- Manolo: I don't know the right way to handle these links in the column headers. -->
<#assign directions = ["ASC", "DESC"]>
<select name="orderDirection" >
<#list directions as direction>
<option value="${direction}" <#if orderDirection = direction>selected</#if> >${direction}</option>
</#list>
</select>
<!-- When orderDirection changes,
set pageIndex to 1
submit the form (submit action is "list") -->
<br>
sort field:
<!-- Manolo: I don't know the right way to handle these links in the column headers. -->
<#assign fields = ["email", "firstName", "lastName", "status", "count"]>
<select name="orderField" >
<#list fields as field>
<option value="${field}" <#if orderField = field>selected</#if> >${field}</option>
</#list>
</select>
<!-- When orderField changes,
set pageIndex to 1
set orderDirection to "ASC"
submit the form (submit action is "list") -->
<br>
search term: <input type="text" name="searchTerm" value="${searchTerm}" />
<!-- When searchTerm changes,
set pageIndex to 1
set orderDirection to "ASC"
set orderField to "email"
submit the form (submit action is "list") -->
<br>
<select name="roleFilterUri">
<option value="" <#if roleFilterUri = "">selected</#if> >Filter by roles</option>
<#list roles as role>
<option value="${role.uri}" <#if roleFilterUri = role.uri>selected</#if> >${role.label}</option>
</#list>
</select>
<!-- When searchTerm changes,
set pageIndex to 1
set orderDirection to "ASC"
set orderField to "email"
submit the form (submit action is "list") -->
<br>
<input type="submit" name="list" value="Refresh page" />
</form>
</div>
<div style="border: solid">
Current page: ${page.current}
<br> Last page: ${page.last}
<#if page.next?has_content>
<br> Next page: ${page.next}
<!-- only present if current page is not last page. -->
</#if>
<#if page.previous?has_content>
<br> Previous page: ${page.previous}
<!-- only present if current page is not 1. -->
</#if>
</div>
<div style="border: solid">
<table style="border: solid">
<tr>
<th>Email Address</th>
<th>First Name</th>
<th>Last Name</th>
<th>Status</th>
<th>Roles</th>
<th>Login Count</th>
</tr>
<#list accounts as account>
<tr>
<td>
<input type="checkbox" name="deleteAccount" value="${account.uri}" />
<!-- ignored unless submit action is "delete" -->
<a href="${formUrl}?edit&editAccount=${account.uri}" >${account.emailAddress}</a>
<!-- if submit action is "edit", editAccount is noticed and all other fields are ignored. -->
</td>
<td>${account.firstName}</td>
<td>${account.lastName}</td>
<td>${account.status}</td>
<td>
<#list account.permissionSets as permissionSet>
<div>${permissionSet}</div>
</#list>
</td>
<td>${account.loginCount}</td>
</tr>
</#list>
</table>
<br>
link on user's email address currently does nothing
</div>