trunk merge

This commit is contained in:
anupsawant 2011-06-13 15:21:53 +00:00
commit d4559a2496
20 changed files with 614 additions and 85 deletions

View file

@ -129,6 +129,7 @@ public abstract class UserAccountsPage {
map.put("myAccount", UrlBuilder.getUrl("/accounts/myAccount"));
map.put("createPassword", UrlBuilder.getUrl("/accounts/createPassword"));
map.put("resetPassword", UrlBuilder.getUrl("/accounts/resetPassword"));
map.put("firstTimeExternal", UrlBuilder.getUrl("/accounts/firstTimeExternal"));
return map;
}

View file

@ -0,0 +1,194 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.controller.accounts.user;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import edu.cornell.mannlib.vitro.webapp.auth.permissions.PermissionSetsLoader;
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.UserAccountsPage;
import edu.cornell.mannlib.vitro.webapp.controller.authenticate.Authenticator;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.TemplateResponseValues;
/**
* Handle the first-time login of an Externally Authenticated user who has no
* UserAccount - let's create one!
*
* If they get here from the login, there should an externalAuthId waiting in
* the session. Otherwise, they should get here by submitting the form, which
* will have the externalAuthId as a hidden field.
*/
public class UserAccountsFirstTimeExternalPage extends UserAccountsPage {
private static final String PARAMETER_SUBMIT = "submit";
private static final String PARAMETER_EXTERNAL_AUTH_ID = "externalAuthId";
private static final String PARAMETER_EMAIL_ADDRESS = "emailAddress";
private static final String PARAMETER_FIRST_NAME = "firstName";
private static final String PARAMETER_LAST_NAME = "lastName";
private static final String ERROR_NO_EMAIL = "errorEmailIsEmpty";
private static final String ERROR_EMAIL_IN_USE = "errorEmailInUse";
private static final String ERROR_EMAIL_INVALID_FORMAT = "errorEmailInvalidFormat";
private static final String ERROR_NO_FIRST_NAME = "errorFirstNameIsEmpty";
private static final String ERROR_NO_LAST_NAME = "errorLastNameIsEmpty";
private static final String TEMPLATE_NAME = "userAccounts-firstTimeExternal.ftl";
private static final String ATTRIBUTE_EXTERNAL_AUTH_ID = UserAccountsFirstTimeExternalPage.class
.getName();
/**
* Let some other request set the External Auth ID before redirecting to
* here.
*/
public static void setExternalAuthId(HttpServletRequest req,
String externalAuthId) {
req.getSession().setAttribute(ATTRIBUTE_EXTERNAL_AUTH_ID,
externalAuthId);
}
private final UserAccountsFirstTimeExternalPageStrategy strategy;
private boolean submit = false;
private String externalAuthId = "";
private String emailAddress = "";
private String firstName = "";
private String lastName = "";
private String errorCode = "";
private String bogusMessage = "";
protected UserAccountsFirstTimeExternalPage(VitroRequest vreq) {
super(vreq);
this.strategy = UserAccountsFirstTimeExternalPageStrategy.getInstance(
vreq, this, isEmailEnabled());
checkSessionForExternalAuthId();
if (externalAuthId.isEmpty()) {
parseRequestParameters();
}
validateExternalAuthId();
if (isSubmit() && !isBogus()) {
validateParameters();
}
}
private void checkSessionForExternalAuthId() {
HttpSession session = vreq.getSession();
Object o = session.getAttribute(ATTRIBUTE_EXTERNAL_AUTH_ID);
session.removeAttribute(ATTRIBUTE_EXTERNAL_AUTH_ID);
if (o instanceof String) {
externalAuthId = (String) o;
}
}
private void parseRequestParameters() {
submit = isFlagOnRequest(PARAMETER_SUBMIT);
externalAuthId = getStringParameter(PARAMETER_EXTERNAL_AUTH_ID, "");
emailAddress = getStringParameter(PARAMETER_EMAIL_ADDRESS, "");
firstName = getStringParameter(PARAMETER_FIRST_NAME, "");
lastName = getStringParameter(PARAMETER_LAST_NAME, "");
}
private void validateExternalAuthId() {
if (externalAuthId.isEmpty()) {
bogusMessage = "Login failed - External ID is not found.";
return;
}
if (null != userAccountsDao
.getUserAccountByExternalAuthId(externalAuthId)) {
bogusMessage = "User account already exists for '" + externalAuthId
+ "'";
return;
}
}
public boolean isBogus() {
return !bogusMessage.isEmpty();
}
public String getBogusMessage() {
return bogusMessage;
}
public boolean isSubmit() {
return submit;
}
private void validateParameters() {
if (firstName.isEmpty()) {
errorCode = ERROR_NO_FIRST_NAME;
} else if (lastName.isEmpty()) {
errorCode = ERROR_NO_LAST_NAME;
} else if (emailAddress.isEmpty()) {
errorCode = ERROR_NO_EMAIL;
} else if (isEmailInUse()) {
errorCode = ERROR_EMAIL_IN_USE;
} else if (!isEmailValidFormat()) {
errorCode = ERROR_EMAIL_INVALID_FORMAT;
}
}
private boolean isEmailInUse() {
return userAccountsDao.getUserAccountByEmail(emailAddress) != null;
}
private boolean isEmailValidFormat() {
return Authenticator.isValidEmailAddress(emailAddress);
}
public boolean isValid() {
return errorCode.isEmpty();
}
public final ResponseValues showPage() {
Map<String, Object> body = new HashMap<String, Object>();
body.put("emailAddress", emailAddress);
body.put("firstName", firstName);
body.put("lastName", lastName);
body.put("externalAuthId", externalAuthId);
body.put("formUrls", buildUrlsMap());
if (!errorCode.isEmpty()) {
body.put(errorCode, Boolean.TRUE);
}
strategy.addMoreBodyValues(body);
return new TemplateResponseValues(TEMPLATE_NAME, body);
}
public UserAccount createAccount() {
UserAccount u = new UserAccount();
u.setEmailAddress(emailAddress);
u.setFirstName(firstName);
u.setLastName(lastName);
u.setExternalAuthId(externalAuthId);
u.setPasswordChangeRequired(false);
u.setPasswordLinkExpires(0);
u.setLoginCount(0);
u.setStatus(Status.ACTIVE);
u.setPermissionSetUris(Collections
.singleton(PermissionSetsLoader.URI_SELF_EDITOR));
userAccountsDao.insertUserAccount(u);
strategy.notifyUser(u);
return u;
}
}

View file

@ -0,0 +1,107 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.controller.accounts.user;
import static javax.mail.Message.RecipientType.TO;
import java.util.HashMap;
import java.util.Map;
import edu.cornell.mannlib.vitro.webapp.beans.UserAccount;
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
import edu.cornell.mannlib.vitro.webapp.controller.accounts.UserAccountsPage;
import edu.cornell.mannlib.vitro.webapp.email.FreemarkerEmailFactory;
import edu.cornell.mannlib.vitro.webapp.email.FreemarkerEmailMessage;
/**
* Handle the variations in the UserAccountsFirstTimeExternal page. If email is
* available, inform the template, and send a notification to the user.
*
* If not, then don't.
*/
public abstract class UserAccountsFirstTimeExternalPageStrategy extends
UserAccountsPage {
public static UserAccountsFirstTimeExternalPageStrategy getInstance(
VitroRequest vreq, UserAccountsFirstTimeExternalPage page,
boolean emailEnabled) {
if (emailEnabled) {
return new EmailStrategy(vreq, page);
} else {
return new NoEmailStrategy(vreq, page);
}
}
@SuppressWarnings("unused")
private UserAccountsFirstTimeExternalPage page;
public UserAccountsFirstTimeExternalPageStrategy(VitroRequest vreq,
UserAccountsFirstTimeExternalPage page) {
super(vreq);
this.page = page;
}
public abstract void addMoreBodyValues(Map<String, Object> body);
public abstract void notifyUser(UserAccount ua);
// ----------------------------------------------------------------------
// Strategy to use if email is enabled.
// ----------------------------------------------------------------------
public static class EmailStrategy extends
UserAccountsFirstTimeExternalPageStrategy {
public EmailStrategy(VitroRequest vreq,
UserAccountsFirstTimeExternalPage page) {
super(vreq, page);
}
@Override
public void addMoreBodyValues(Map<String, Object> body) {
body.put("emailIsEnabled", Boolean.TRUE);
}
@Override
public void notifyUser(UserAccount ua) {
Map<String, Object> body = new HashMap<String, Object>();
body.put("userAccount", ua);
body.put("subjectLine", "Your VIVO account has been created.");
FreemarkerEmailMessage email = FreemarkerEmailFactory
.createNewMessage(vreq);
email.addRecipient(TO, ua.getEmailAddress());
email.setSubject("Your VIVO account has been created.");
email.setHtmlTemplate("userAccounts-firstTimeExternalEmail-html.ftl");
email.setTextTemplate("userAccounts-firstTimeExternalEmail-text.ftl");
email.setBodyMap(body);
email.send();
}
}
// ----------------------------------------------------------------------
// Strategy to use if email is disabled.
// ----------------------------------------------------------------------
public static class NoEmailStrategy extends
UserAccountsFirstTimeExternalPageStrategy {
public NoEmailStrategy(VitroRequest vreq,
UserAccountsFirstTimeExternalPage page) {
super(vreq, page);
}
@Override
public void addMoreBodyValues(Map<String, Object> body) {
// Nothing to add.
}
@Override
public void notifyUser(UserAccount ua) {
// No way to notify.
}
}
}

View file

@ -2,16 +2,23 @@
package edu.cornell.mannlib.vitro.webapp.controller.accounts.user;
import static edu.cornell.mannlib.vedit.beans.LoginStatusBean.AuthenticationSource.EXTERNAL;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import edu.cornell.mannlib.vedit.beans.LoginStatusBean.AuthenticationSource;
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.Actions;
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.usepages.EditOwnAccount;
import edu.cornell.mannlib.vitro.webapp.beans.DisplayMessage;
import edu.cornell.mannlib.vitro.webapp.beans.UserAccount;
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
import edu.cornell.mannlib.vitro.webapp.controller.authenticate.Authenticator;
import edu.cornell.mannlib.vitro.webapp.controller.authenticate.LoginRedirector;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.FreemarkerHttpServlet;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.RedirectResponseValues;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues;
import edu.cornell.mannlib.vitro.webapp.controller.login.LoginProcessBean;
/**
* Parcel out the different actions required of the UserAccounts GUI.
@ -25,6 +32,7 @@ public class UserAccountsUserController extends FreemarkerHttpServlet {
private static final String ACTION_CREATE_PASSWORD = "/createPassword";
private static final String ACTION_RESET_PASSWORD = "/resetPassword";
private static final String ACTION_MY_ACCOUNT = "/myAccount";
private static final String ACTION_FIRST_TIME_EXTERNAL = "/firstTimeExternal";
@Override
protected Actions requiredActions(VitroRequest vreq) {
@ -52,6 +60,8 @@ public class UserAccountsUserController extends FreemarkerHttpServlet {
return handleCreatePasswordRequest(vreq);
} else if (ACTION_RESET_PASSWORD.equals(action)) {
return handleResetPasswordRequest(vreq);
} else if (ACTION_FIRST_TIME_EXTERNAL.equals(action)) {
return handleFirstTimeLoginFromExternalAccount(vreq);
} else {
return handleInvalidRequest(vreq);
}
@ -95,6 +105,24 @@ public class UserAccountsUserController extends FreemarkerHttpServlet {
}
private ResponseValues handleFirstTimeLoginFromExternalAccount(
VitroRequest vreq) {
UserAccountsFirstTimeExternalPage page = new UserAccountsFirstTimeExternalPage(
vreq);
if (page.isBogus()) {
return showHomePage(vreq, page.getBogusMessage());
} else if (page.isSubmit() && page.isValid()) {
UserAccount userAccount = page.createAccount();
Authenticator auth = Authenticator.getInstance(vreq);
auth.recordLoginAgainstUserAccount(userAccount, EXTERNAL);
LoginProcessBean.removeBean(vreq);
return showLoginRedirection(vreq);
} else {
return page.showPage();
}
}
private ResponseValues handleInvalidRequest(VitroRequest vreq) {
return showHomePage(vreq, BOGUS_STANDARD_MESSAGE);
}
@ -104,4 +132,10 @@ public class UserAccountsUserController extends FreemarkerHttpServlet {
return new RedirectResponseValues("/");
}
private ResponseValues showLoginRedirection(VitroRequest vreq) {
LoginRedirector lr = new LoginRedirector(vreq);
DisplayMessage.setMessage(vreq, lr.assembleWelcomeMessage());
String uri = lr.getRedirectionUriForLoggedInUser();
return new RedirectResponseValues(uri);
}
}

View file

@ -57,7 +57,7 @@ public class LoginExternalAuthReturn extends BaseLoginServlet {
getAuthenticator(req).recordLoginAgainstUserAccount(userAccount,
AuthenticationSource.EXTERNAL);
removeLoginProcessArtifacts(req);
new LoginRedirector(req, resp).redirectLoggedInUser();
new LoginRedirector(req).redirectLoggedInUser(resp);
return;
}
@ -71,14 +71,14 @@ public class LoginExternalAuthReturn extends BaseLoginServlet {
getAuthenticator(req).recordLoginWithoutUserAccount(uri);
removeLoginProcessArtifacts(req);
new LoginRedirector(req, resp).redirectLoggedInUser();
new LoginRedirector(req).redirectLoggedInUser(resp);
return;
}
log.debug("User is not recognized: " + externalAuthId);
removeLoginProcessArtifacts(req);
new LoginRedirector(req, resp)
.redirectUnrecognizedExternalUser(externalAuthId);
new LoginRedirector(req).redirectUnrecognizedExternalUser(resp,
externalAuthId);
}
private void removeLoginProcessArtifacts(HttpServletRequest req) {

View file

@ -29,17 +29,14 @@ public class LoginRedirector {
private static final Log log = LogFactory.getLog(LoginRedirector.class);
private final HttpServletRequest request;
private final HttpServletResponse response;
private final HttpSession session;
private final String uriOfAssociatedIndividual;
private final String afterLoginPage;
public LoginRedirector(HttpServletRequest request,
HttpServletResponse response) {
public LoginRedirector(HttpServletRequest request) {
this.request = request;
this.session = request.getSession();
this.response = response;
uriOfAssociatedIndividual = getAssociatedIndividualUri();
@ -70,28 +67,45 @@ public class LoginRedirector {
}
}
public void redirectLoggedInUser() throws IOException {
DisplayMessage.setMessage(request, assembleWelcomeMessage());
try {
public String getRedirectionUriForLoggedInUser() {
if (isSelfEditorWithIndividual()) {
log.debug("Going to Individual home page.");
response.sendRedirect(getAssociatedIndividualHomePage());
return getAssociatedIndividualHomePage();
} else if (isMerelySelfEditor()) {
log.debug("User not recognized. Going to application home.");
response.sendRedirect(getApplicationHomePageUrl());
return getApplicationHomePageUrl();
} else {
if (isLoginPage(afterLoginPage)) {
log.debug("Coming from /login. Going to site admin page.");
response.sendRedirect(getSiteAdminPageUrl());
return getSiteAdminPageUrl();
} else if (null != afterLoginPage) {
log.debug("Returning to requested page: " + afterLoginPage);
response.sendRedirect(afterLoginPage);
return afterLoginPage;
} else {
log.debug("Don't know what to do. Go home.");
response.sendRedirect(getApplicationHomePageUrl());
return getApplicationHomePageUrl();
}
}
}
public String getRedirectionUriForCancellingUser() {
if (isLoginPage(afterLoginPage)) {
log.debug("Coming from /login. Going to home.");
return getApplicationHomePageUrl();
} else if (null != afterLoginPage) {
log.debug("Returning to requested page: " + afterLoginPage);
return afterLoginPage;
} else {
log.debug("Don't know what to do. Go home.");
return getApplicationHomePageUrl();
}
}
public void redirectLoggedInUser(HttpServletResponse response)
throws IOException {
try {
DisplayMessage.setMessage(request, assembleWelcomeMessage());
response.sendRedirect(getRedirectionUriForLoggedInUser());
LoginProcessBean.removeBean(request);
} catch (IOException e) {
log.debug("Problem with re-direction", e);
@ -99,7 +113,7 @@ public class LoginRedirector {
}
}
private String assembleWelcomeMessage() {
public String assembleWelcomeMessage() {
if (isMerelySelfEditor() && !isSelfEditorWithIndividual()) {
// A special message for unrecognized self-editors:
return "You have logged in, "
@ -124,18 +138,10 @@ public class LoginRedirector {
return "Welcome" + backString + ", " + greeting;
}
public void redirectCancellingUser() throws IOException {
public void redirectCancellingUser(HttpServletResponse response)
throws IOException {
try {
if (isLoginPage(afterLoginPage)) {
log.debug("Coming from /login. Going to home.");
response.sendRedirect(getApplicationHomePageUrl());
} else if (null != afterLoginPage) {
log.debug("Returning to requested page: " + afterLoginPage);
response.sendRedirect(afterLoginPage);
} else {
log.debug("Don't know what to do. Go home.");
response.sendRedirect(getApplicationHomePageUrl());
}
response.sendRedirect(getRedirectionUriForCancellingUser());
LoginProcessBean.removeBean(request);
} catch (IOException e) {
log.debug("Problem with re-direction", e);
@ -143,8 +149,8 @@ public class LoginRedirector {
}
}
public void redirectUnrecognizedExternalUser(String username)
throws IOException {
public void redirectUnrecognizedExternalUser(HttpServletResponse response,
String username) throws IOException {
log.debug("Redirecting unrecognized external user: " + username);
DisplayMessage.setMessage(request,
"VIVO cannot find a profile for your account.");

View file

@ -124,7 +124,7 @@ public class Authenticate extends VitroHttpServlet {
// Send them on their way.
switch (exitState) {
case NOWHERE:
new LoginRedirector(vreq, response).redirectCancellingUser();
new LoginRedirector(vreq).redirectCancellingUser(response);
break;
case LOGGING_IN:
showLoginScreen(vreq, response);
@ -133,7 +133,7 @@ public class Authenticate extends VitroHttpServlet {
showLoginScreen(vreq, response);
break;
default: // LOGGED_IN:
new LoginRedirector(vreq, response).redirectLoggedInUser();
new LoginRedirector(vreq).redirectLoggedInUser(response);
break;
}
} catch (Exception e) {

View file

@ -10,6 +10,7 @@ import edu.cornell.mannlib.vitro.webapp.beans.DataPropertyStatement;
import edu.cornell.mannlib.vitro.webapp.beans.Individual;
import edu.cornell.mannlib.vitro.webapp.beans.Keyword;
import edu.cornell.mannlib.vitro.webapp.beans.VClass;
import edu.cornell.mannlib.vitro.webapp.edit.EditLiteral;
import edu.cornell.mannlib.vitro.webapp.search.beans.ObjectSourceIface;
public interface IndividualDao extends ObjectSourceIface {
@ -136,6 +137,8 @@ public interface IndividualDao extends ObjectSourceIface {
*/
String getUnusedURI(Individual individual) throws InsertException;
EditLiteral getLabelEditLiteral(String individualUri);
@Deprecated
public abstract Individual getIndividualByExternalId(int externalIdType,
String externalIdValue);

View file

@ -19,6 +19,7 @@ import edu.cornell.mannlib.vitro.webapp.beans.VClass;
import edu.cornell.mannlib.vitro.webapp.dao.IndividualDao;
import edu.cornell.mannlib.vitro.webapp.dao.InsertException;
import edu.cornell.mannlib.vitro.webapp.dao.filtering.filters.VitroFilters;
import edu.cornell.mannlib.vitro.webapp.edit.EditLiteral;
class IndividualDaoFiltering extends BaseFiltering implements IndividualDao{
@ -242,4 +243,10 @@ class IndividualDaoFiltering extends BaseFiltering implements IndividualDao{
return innerIndividualDao.getUnusedURI(individual);
}
@Override
public EditLiteral getLabelEditLiteral(String individualUri) {
return innerIndividualDao.getLabelEditLiteral(individualUri);
}
}

View file

@ -58,6 +58,7 @@ import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
import edu.cornell.mannlib.vitro.webapp.dao.jena.event.IndividualCreationEvent;
import edu.cornell.mannlib.vitro.webapp.dao.jena.event.IndividualDeletionEvent;
import edu.cornell.mannlib.vitro.webapp.dao.jena.event.IndividualUpdateEvent;
import edu.cornell.mannlib.vitro.webapp.edit.EditLiteral;
public class IndividualDaoJena extends JenaBaseDao implements IndividualDao {
@ -1048,4 +1049,19 @@ public class IndividualDaoJena extends JenaBaseDao implements IndividualDao {
return uri;
}
@Override
// This method returns an EditLiteral rather than a Jena Literal, since IndividualDao
// should not reference Jena objects. (However, the problem isn't really solved
// because EditLiteral currently references the Jena API.)
public EditLiteral getLabelEditLiteral(String individualUri) {
Literal literal = getLabelLiteral(individualUri);
if (literal == null) {
return null;
}
String value = literal.getLexicalForm();
String datatype = literal.getDatatypeURI();
String lang = literal.getLanguage();
return new EditLiteral(value, datatype, lang);
}
}

View file

@ -777,11 +777,16 @@ public class JenaBaseDao extends JenaBaseDaoCon {
return label;
}
protected Literal getLabelLiteral(String individualUri) {
OntResource resource = webappDaoFactory.getOntModel().createOntResource(individualUri);
return getLabelLiteral(resource);
}
/**
* works through list of PREFERRED_LANGUAGES to find an appropriate
* label, or NULL if not found.
*/
public Literal getLabelLiteral(OntResource r) {
protected Literal getLabelLiteral(OntResource r) {
Literal labelLiteral = null;
r.getOntModel().enterCriticalSection(Lock.READ);
try {

View file

@ -29,7 +29,7 @@ public class DataPropertyStatementTemplateModel extends PropertyStatementTemplat
protected String value = null;
// Used for editing
private String dataPropHash = null;
protected String dataPropHash = null;
//Useful in case additional params to be retrieved for URL
private VitroRequest vitroRequest= null;
@ -84,7 +84,7 @@ public class DataPropertyStatementTemplateModel extends PropertyStatementTemplat
}
// Determine whether the statement can be deleted
// Hack for rdfs:label - the policy doesn't prevent deletion
// Hack for rdfs:label - the policy doesn't prevent deletion.
if ( ! propertyUri.equals(VitroVocabulary.LABEL) ) {
action = new DropDataPropStmt(dps);
if (policyHelper.isAuthorizedAction(action)) {

View file

@ -9,16 +9,21 @@ import org.apache.commons.logging.LogFactory;
import org.openrdf.model.URI;
import org.openrdf.model.impl.URIImpl;
import com.hp.hpl.jena.ontology.OntModel;
import com.hp.hpl.jena.ontology.OntResource;
import com.hp.hpl.jena.rdf.model.Literal;
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.ifaces.RequestedAction;
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.propstmt.DropDataPropStmt;
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.propstmt.EditDataPropStmt;
import edu.cornell.mannlib.vitro.webapp.beans.DataPropertyStatement;
import edu.cornell.mannlib.vitro.webapp.beans.DataPropertyStatementImpl;
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
import edu.cornell.mannlib.vitro.webapp.dao.DataPropertyStatementDao;
import edu.cornell.mannlib.vitro.webapp.dao.IndividualDao;
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
import edu.cornell.mannlib.vitro.webapp.dao.jena.JenaBaseDao;
import edu.cornell.mannlib.vitro.webapp.dao.jena.WebappDaoFactoryJena;
import edu.cornell.mannlib.vitro.webapp.edit.EditLiteral;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.processEdit.RdfLiteralHash;
public class NameStatementTemplateModel extends
DataPropertyStatementTemplateModel {
@ -27,43 +32,49 @@ public class NameStatementTemplateModel extends
/*
* This method handles the special case where we are creating a DataPropertyStatementTemplateModel outside the GroupedPropertyList.
* Specifically, it allows rdfs:label to be treated like a data property statement and thus have editing links. It is not possible
* to handle rdfs:label like vitro links and vitroPublic image, because it is not possible to construct a DataProperty from
* rdfs:label.
* Specifically, it allows rdfs:label to be treated like a data property statement and thus have editing links.
*/
NameStatementTemplateModel(String subjectUri, VitroRequest vreq, EditingPolicyHelper policyHelper) {
super(subjectUri, VitroVocabulary.LABEL, vreq, policyHelper);
Literal literal = null;
WebappDaoFactory wdf = vreq.getWebappDaoFactory();
// Use the same methods to get the label that are used elsewhere in the application, to
// guarantee consistent results for individuals with multiple labels.
// RY The problem here is we have a WebappDaoFactoryFiltering instead of WebappDaoFactoryJena.
if (wdf instanceof WebappDaoFactoryJena) {
WebappDaoFactoryJena wdfj = (WebappDaoFactoryJena) wdf;
OntResource resource = wdfj.getOntModel().createOntResource(subjectUri);
JenaBaseDao baseDao = wdfj.getJenaBaseDao();
literal = baseDao.getLabelLiteral(resource);
} else {
DataPropertyStatementDao dpsDao = vreq.getWebappDaoFactory().getDataPropertyStatementDao();
List<Literal> literals = dpsDao.getDataPropertyValuesForIndividualByProperty(subjectUri, VitroVocabulary.LABEL);
// Make sure the subject has a value for this property
if (literals.size() > 0) {
literal = literals.get(0);
}
}
// NIHVIVO-2466 Use the same methods to get the label that are used elsewhere in the
// application, to guarantee consistent results for individuals with multiple labels
// across the application.
IndividualDao iDao = wdf.getIndividualDao();
EditLiteral literal = iDao.getLabelEditLiteral(subjectUri);
if (literal != null) {
value = literal.getLexicalForm();
setEditAccess(literal, policyHelper);
} else {
// If the individual has no rdfs:label, use the local name. It will not be editable (this replicates previous behavior;
// If the individual has no rdfs:label, use the local name. It will not be editable. (This replicates previous behavior;
// perhaps we would want to allow a label to be added. But such individuals do not usually have their profiles viewed or
// edited directly.
// edited directly.)
URI uri = new URIImpl(subjectUri);
value = uri.getLocalName();
}
}
protected void setEditAccess(EditLiteral value, EditingPolicyHelper policyHelper) {
if (policyHelper != null) { // we're editing
DataPropertyStatement dps = new DataPropertyStatementImpl(subjectUri, propertyUri, value.getLexicalForm());
// Language and datatype are needed to get the correct hash value
dps.setLanguage(value.getLanguage());
dps.setDatatypeURI(value.getDatatypeURI());
this.dataPropHash = String.valueOf(RdfLiteralHash.makeRdfLiteralHash(dps));
// Determine whether the statement can be edited
RequestedAction action = new EditDataPropStmt(dps);
if (policyHelper.isAuthorizedAction(action)) {
markEditable();
}
// The label cannot be deleted, so we don't need to check
// the policy for the delete action.
}
}
}

View file

@ -14,6 +14,7 @@ import edu.cornell.mannlib.vitro.webapp.beans.Keyword;
import edu.cornell.mannlib.vitro.webapp.beans.VClass;
import edu.cornell.mannlib.vitro.webapp.dao.IndividualDao;
import edu.cornell.mannlib.vitro.webapp.dao.InsertException;
import edu.cornell.mannlib.vitro.webapp.edit.EditLiteral;
/**
* A minimal implementation of the IndividualDao.
@ -237,4 +238,10 @@ public class IndividualDaoStub implements IndividualDao {
"IndividualDaoStub.getIndividualByExternalId() not implemented.");
}
@Override
public EditLiteral getLabelEditLiteral(String individualUri) {
throw new RuntimeException(
"IndividualDaoStub.getLabelLiteral() not implemented.");
}
}

View file

@ -64,11 +64,13 @@ ul#browse-classgroups .count-classes {
border: 1px solid #dde6e5;
background: #fff;
min-height: 230px;
padding-top: 10px;
}
a.browse-superclass {
position: absolute;
right: 0.5em;
font-size: 0.9em;
top: 3px;
}
ul#classes-in-classgroup {
float: left;

View file

@ -1,10 +1,17 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
// Change form actions in account main page
function changeAction(form, url) {
form.action = url;
return true;
}
$(document).ready(function(){
//Accounts per page
//Hide is javascrip is disable
$('.accounts-per-page-form input[type="submit"]').hide();
//Hide is javascrip is enable
$('input[name="accounts-per-page"]').addClass('hide');
$('.accounts-per-page').change(function() {
$('#account-display').submit();

View file

@ -0,0 +1,64 @@
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
<#-- Template for creating an account for the first time an external user logs in. -->
<h3>First time log in</h3>
<#if errorEmailIsEmpty??>
<#assign errorMessage = "You must supply an email address." />
</#if>
<#if errorEmailInUse??>
<#assign errorMessage = "An account with that email address already exists." />
</#if>
<#if errorEmailInvalidFormat??>
<#assign errorMessage = "'${emailAddress}' is not a valid email address." />
</#if>
<#if errorFirstNameIsEmpty??>
<#assign errorMessage = "You must supply a first name." />
</#if>
<#if errorLastNameIsEmpty??>
<#assign errorMessage = "You must supply a last name." />
</#if>
<#if errorMessage?has_content>
<section id="error-alert" role="alert">
<img src="${urls.images}/iconAlert.png" width="24" height="24" alert="Error alert icon"/>
<p>${errorMessage}</p>
</section>
</#if>
<section id="first-time-login" role="region">
<fieldset>
<p class="note">
Please provide your contact information to finish creating your account.
</p>
<form method="POST" action="${formUrls.firstTimeExternal}" class="customForm" role="my account">
<input type="hidden" name="externalAuthId" value="${externalAuthId}" />
<label for="first-name">First name<span class="requiredHint"> *</span></label>
<input type="text" name="firstName" value="${firstName}" id="first-name" role="input "/>
<label for="last-name">Last name<span class="requiredHint"> *</span></label>
<input type="text" name="lastName" value="${lastName}" id="last-name" role="input "/>
<label for="email-address">Email address<span class="requiredHint"> *</span></label>
<input type="text" name="emailAddress" value="${emailAddress}" id="email-address" role="input "/>
<#if emailIsEnabled??>
<p class="note">
Note: An email will be sent to the address entered above notifying
that an account has been created.
</p>
</#if>
<input type="submit" name="submit" value="Create account" class="submit"/> or <a href="${urls.home}">Cancel</a>
</form>
</fieldset>
</section>
${stylesheets.add('<link rel="stylesheet" href="${urls.base}/edit/forms/css/customForm.css" />')}

View file

@ -0,0 +1,26 @@
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
<#-- Confirmation that an account has been created for an externally-authenticated user. -->
<html>
<head>
<title>${subjectLine}</title>
</head>
<body>
<p>
${userAccount.firstName} ${userAccount.lastName}
</p>
<p>
<strong>Congratulations!</strong>
</p>
<p>
We have created your new VIVO account associated with ${userAccount.emailAddress}.
</p>
<p>
Thanks!
</p>
</body>
</html>

View file

@ -0,0 +1,12 @@
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
<#-- Confirmation that an account has been created for an externally-authenticated user. -->
${userAccount.firstName} ${userAccount.lastName}
Congratulations!
We have created your new VIVO account associated with
${userAccount.emailAddress}.
Thanks!

View file

@ -107,13 +107,6 @@
</section>
</form>
<SCRIPT TYPE="text/javascript">
function changeAction(form, url) {
form.action = url;
return true;
}
</SCRIPT>
<form method="POST" action="${formUrls.list}" id="account-display" class="customForm" role="">
<section class="accounts">
<input type="submit" name="delete-account" class="delete-account submit" value="Delete" onClick="changeAction(this.form, '${formUrls.delete}')" />
@ -126,6 +119,7 @@
<span>| <a href="#">n</a> accounts | </span>
<#assign counts = [25, 50, 100]>
<select name="accountsPerPage" class="accounts-per-page">
<#list counts as count>
<option value="${count}" <#if accountsPerPage= count>selected</#if> >${count}</option>
@ -137,9 +131,7 @@
-->
</select>
<input class="hide" type="submit" value="Update" />
accounts per page |
accounts per page <input type="submit" name="accounts-per-page" value="Update" /> |
<#if page.previous?has_content>
<a href="${formUrls.list}?accountsPerPage=${accountsPerPage}&pageIndex=${page.previous}">Previous</a> <!-- only present if current page is not 1.-->
@ -192,6 +184,41 @@
</#list>
</tbody>
</table>
<section class="accounts">
<input type="submit" name="delete-account" class="delete-account submit" value="Delete" onClick="changeAction(this.form, '${formUrls.delete}')" />
<!--
When this is clicked, the checkboxes are noticed and all other fields are ignored.
submit the form (submit action is formUrls.delete)
-->
<nav class="display-tools">
<span>| <a href="#">n</a> accounts | </span>
<#assign counts = [25, 50, 100]>
<select name="accountsPerPage" class="accounts-per-page">
<#list counts as count>
<option value="${count}" <#if accountsPerPage= count>selected</#if> >${count}</option>
</#list>
<!--
When accountsPerPage changes,
set pageIndex to 1
submit the form (submit action is formUrls.list)
-->
</select>
accounts per page <input type="submit" name="accounts-per-page" value="Update" /> |
<#if page.previous?has_content>
<a href="${formUrls.list}?accountsPerPage=${accountsPerPage}&pageIndex=${page.previous}">Previous</a> <!-- only present if current page is not 1.-->
</#if>
${page.current} of ${page.last}
<#if page.next?has_content>
<a href="${formUrls.list}?accountsPerPage=${accountsPerPage}&pageIndex=${page.next}">Next</a><!-- only present if current page is not last page.-->
</#if>
</nav>
</section>
</form>
${scripts.add('<script type="text/javascript" src="${urls.base}/js/account/accountUtils.js"></script>')}