Compare commits

..

1 commit

Author SHA1 Message Date
595e122043 Added code for deleting individuals 2021-02-18 19:06:34 +01:00
31 changed files with 259 additions and 253 deletions

View file

@ -7,11 +7,17 @@ import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
import org.apache.commons.lang3.RandomStringUtils; import edu.cornell.mannlib.vitro.webapp.controller.authenticate.Authenticator;
/** /**
* Information about the account of a user. URI, email, password, etc. * Information about the account of a user. URI, email, password, etc.
* *
* The "password link expires hash" is just a string that is derived from the
* value in the passwordLinkExpires field. It doesn't have to be a hash, and
* there is no need for it to be cryptographic, but it seems embarrassing to
* just send the value as a clear string. There is no real need for security
* here, except that a brute force attack would allow someone to change the
* password on an account that they know has a password change pending.
*/ */
public class UserAccount { public class UserAccount {
public static final int MIN_PASSWORD_LENGTH = 6; public static final int MIN_PASSWORD_LENGTH = 6;
@ -46,7 +52,6 @@ public class UserAccount {
private String md5Password = ""; // Never null. private String md5Password = ""; // Never null.
private String oldPassword = ""; // Never null. private String oldPassword = ""; // Never null.
private long passwordLinkExpires = 0L; // Never negative. private long passwordLinkExpires = 0L; // Never negative.
private String emailKey = "";
private boolean passwordChangeRequired = false; private boolean passwordChangeRequired = false;
private int loginCount = 0; // Never negative. private int loginCount = 0; // Never negative.
@ -128,27 +133,15 @@ public class UserAccount {
return passwordLinkExpires; return passwordLinkExpires;
} }
public String getPasswordLinkExpiresHash() {
return limitStringLength(8, Authenticator.applyArgon2iEncoding(String
.valueOf(passwordLinkExpires)));
}
public void setPasswordLinkExpires(long passwordLinkExpires) { public void setPasswordLinkExpires(long passwordLinkExpires) {
this.passwordLinkExpires = Math.max(0, passwordLinkExpires); this.passwordLinkExpires = Math.max(0, passwordLinkExpires);
} }
public void generateEmailKey() {
boolean useLetters = true;
boolean useNumbers = true;
int length = 64;
emailKey = RandomStringUtils.random(length, useLetters, useNumbers);
}
public void setEmailKey(String emailKey) {
if (emailKey != null) {
this.emailKey = emailKey;
}
}
public String getEmailKey() {
return emailKey;
}
public boolean isPasswordChangeRequired() { public boolean isPasswordChangeRequired() {
return passwordChangeRequired; return passwordChangeRequired;
} }
@ -254,7 +247,6 @@ public class UserAccount {
+ (", oldPassword=" + oldPassword) + (", oldPassword=" + oldPassword)
+ (", argon2password=" + argon2Password) + (", argon2password=" + argon2Password)
+ (", passwordLinkExpires=" + passwordLinkExpires) + (", passwordLinkExpires=" + passwordLinkExpires)
+ (", emailKey =" + emailKey)
+ (", passwordChangeRequired=" + passwordChangeRequired) + (", passwordChangeRequired=" + passwordChangeRequired)
+ (", externalAuthOnly=" + externalAuthOnly) + (", externalAuthOnly=" + externalAuthOnly)
+ (", loginCount=" + loginCount) + (", status=" + status) + (", loginCount=" + loginCount) + (", status=" + status)

View file

@ -249,7 +249,6 @@ public class UserAccountsSelector {
user.setMd5Password(ifLiteralPresent(solution, "md5pwd", "")); user.setMd5Password(ifLiteralPresent(solution, "md5pwd", ""));
user.setArgon2Password(ifLiteralPresent(solution, "a2pwd", "")); user.setArgon2Password(ifLiteralPresent(solution, "a2pwd", ""));
user.setPasswordLinkExpires(ifLongPresent(solution, "expire", 0L)); user.setPasswordLinkExpires(ifLongPresent(solution, "expire", 0L));
user.setEmailKey(ifLiteralPresent(solution, "emailKey", ""));
user.setLoginCount(ifIntPresent(solution, "count", 0)); user.setLoginCount(ifIntPresent(solution, "count", 0));
user.setLastLoginTime(ifLongPresent(solution, "lastLogin", 0)); user.setLastLoginTime(ifLongPresent(solution, "lastLogin", 0));
user.setStatus(parseStatus(solution, "status", null)); user.setStatus(parseStatus(solution, "status", null));

View file

@ -156,7 +156,6 @@ public class UserAccountsAddPage extends UserAccountsPage {
u.setOldPassword(""); u.setOldPassword("");
u.setPasswordChangeRequired(false); u.setPasswordChangeRequired(false);
u.setPasswordLinkExpires(0); u.setPasswordLinkExpires(0);
u.setEmailKey("");
u.setLoginCount(0); u.setLoginCount(0);
u.setLastLoginTime(0L); u.setLastLoginTime(0L);
u.setStatus(Status.INACTIVE); u.setStatus(Status.INACTIVE);

View file

@ -84,7 +84,6 @@ public abstract class UserAccountsAddPageStrategy extends UserAccountsPage {
u.setStatus(Status.ACTIVE); u.setStatus(Status.ACTIVE);
} else { } else {
u.setPasswordLinkExpires(figureExpirationDate().getTime()); u.setPasswordLinkExpires(figureExpirationDate().getTime());
u.generateEmailKey();
u.setStatus(Status.INACTIVE); u.setStatus(Status.INACTIVE);
} }
} }
@ -120,8 +119,10 @@ public abstract class UserAccountsAddPageStrategy extends UserAccountsPage {
private String buildCreatePasswordLink() { private String buildCreatePasswordLink() {
try { try {
String email = page.getAddedAccount().getEmailAddress(); String email = page.getAddedAccount().getEmailAddress();
String key = page.getAddedAccount().getEmailKey(); String hash = page.getAddedAccount()
String relativeUrl = UrlBuilder.getUrl(CREATE_PASSWORD_URL, "user", email, "key", key); .getPasswordLinkExpiresHash();
String relativeUrl = UrlBuilder.getUrl(CREATE_PASSWORD_URL,
"user", email, "key", hash);
URL context = new URL(vreq.getRequestURL().toString()); URL context = new URL(vreq.getRequestURL().toString());
URL url = new URL(context, relativeUrl); URL url = new URL(context, relativeUrl);

View file

@ -274,7 +274,6 @@ public class UserAccountsEditPage extends UserAccountsPage {
userAccount.setOldPassword(""); userAccount.setOldPassword("");
userAccount.setPasswordChangeRequired(false); userAccount.setPasswordChangeRequired(false);
userAccount.setPasswordLinkExpires(0L); userAccount.setPasswordLinkExpires(0L);
userAccount.setEmailKey("");
} }
if (isRootUser()) { if (isRootUser()) {

View file

@ -82,7 +82,6 @@ public abstract class UserAccountsEditPageStrategy extends UserAccountsPage {
protected void setAdditionalProperties(UserAccount u) { protected void setAdditionalProperties(UserAccount u) {
if (resetPassword && !page.isExternalAuthOnly()) { if (resetPassword && !page.isExternalAuthOnly()) {
u.setPasswordLinkExpires(figureExpirationDate().getTime()); u.setPasswordLinkExpires(figureExpirationDate().getTime());
u.generateEmailKey();
} }
} }
@ -122,8 +121,10 @@ public abstract class UserAccountsEditPageStrategy extends UserAccountsPage {
private String buildResetPasswordLink() { private String buildResetPasswordLink() {
try { try {
String email = page.getUpdatedAccount().getEmailAddress(); String email = page.getUpdatedAccount().getEmailAddress();
String key = page.getUpdatedAccount().getEmailKey(); String hash = page.getUpdatedAccount()
String relativeUrl = UrlBuilder.getUrl(RESET_PASSWORD_URL, "user", email, "key", key); .getPasswordLinkExpiresHash();
String relativeUrl = UrlBuilder.getUrl(RESET_PASSWORD_URL,
"user", email, "key", hash);
URL context = new URL(vreq.getRequestURL().toString()); URL context = new URL(vreq.getRequestURL().toString());
URL url = new URL(context, relativeUrl); URL url = new URL(context, relativeUrl);

View file

@ -36,7 +36,6 @@ public class UserAccountsCreatePasswordPage extends
userAccount.setArgon2Password(Authenticator.applyArgon2iEncoding(newPassword)); userAccount.setArgon2Password(Authenticator.applyArgon2iEncoding(newPassword));
userAccount.setMd5Password(""); userAccount.setMd5Password("");
userAccount.setPasswordLinkExpires(0L); userAccount.setPasswordLinkExpires(0L);
userAccount.setEmailKey("");
userAccount.setPasswordChangeRequired(false); userAccount.setPasswordChangeRequired(false);
userAccount.setStatus(Status.ACTIVE); userAccount.setStatus(Status.ACTIVE);
userAccountsDao.updateUserAccount(userAccount); userAccountsDao.updateUserAccount(userAccount);
@ -55,11 +54,6 @@ public class UserAccountsCreatePasswordPage extends
return i18n.text("account_already_activated", userEmail); return i18n.text("account_already_activated", userEmail);
} }
@Override
protected String passwordChangeInavlidKeyMessage() {
return i18n.text("password_change_invalid_key", userEmail);
}
@Override @Override
protected String templateName() { protected String templateName() {
return TEMPLATE_NAME; return TEMPLATE_NAME;

View file

@ -195,7 +195,6 @@ public class UserAccountsFirstTimeExternalPage extends UserAccountsPage {
u.setExternalAuthId(externalAuthId); u.setExternalAuthId(externalAuthId);
u.setPasswordChangeRequired(false); u.setPasswordChangeRequired(false);
u.setPasswordLinkExpires(0); u.setPasswordLinkExpires(0);
u.setEmailKey("");
u.setExternalAuthOnly(true); u.setExternalAuthOnly(true);
u.setLoginCount(0); u.setLoginCount(0);
u.setStatus(Status.ACTIVE); u.setStatus(Status.ACTIVE);

View file

@ -159,7 +159,6 @@ public abstract class UserAccountsMyAccountPageStrategy extends
userAccount.setMd5Password(""); userAccount.setMd5Password("");
userAccount.setPasswordChangeRequired(false); userAccount.setPasswordChangeRequired(false);
userAccount.setPasswordLinkExpires(0L); userAccount.setPasswordLinkExpires(0L);
userAccount.setEmailKey("");
} }
} }

View file

@ -103,12 +103,12 @@ public abstract class UserAccountsPasswordBasePage extends UserAccountsPage {
return; return;
} }
String expectedKey = userAccount.getEmailKey(); String expectedKey = userAccount.getPasswordLinkExpiresHash();
if (key.isEmpty() || !key.equals(expectedKey)) { if (!key.equals(expectedKey)) {
log.warn("Password request for '" + userEmail + "' is bogus: key (" log.warn("Password request for '" + userEmail + "' is bogus: key ("
+ key + ") doesn't match expected key (" + expectedKey + key + ") doesn't match expected key (" + expectedKey
+ ")"); + ")");
bogusMessage = passwordChangeInavlidKeyMessage(); bogusMessage = passwordChangeNotPendingMessage();
return; return;
} }
@ -153,7 +153,7 @@ public abstract class UserAccountsPasswordBasePage extends UserAccountsPage {
body.put("minimumLength", UserAccount.MIN_PASSWORD_LENGTH); body.put("minimumLength", UserAccount.MIN_PASSWORD_LENGTH);
body.put("maximumLength", UserAccount.MAX_PASSWORD_LENGTH); body.put("maximumLength", UserAccount.MAX_PASSWORD_LENGTH);
body.put("userAccount", userAccount); body.put("userAccount", userAccount);
body.put("key", userAccount.getEmailKey()); body.put("key", userAccount.getPasswordLinkExpiresHash());
body.put("newPassword", newPassword); body.put("newPassword", newPassword);
body.put("confirmPassword", confirmPassword); body.put("confirmPassword", confirmPassword);
body.put("formUrls", buildUrlsMap()); body.put("formUrls", buildUrlsMap());
@ -177,7 +177,5 @@ public abstract class UserAccountsPasswordBasePage extends UserAccountsPage {
protected abstract String passwordChangeNotPendingMessage(); protected abstract String passwordChangeNotPendingMessage();
protected abstract String passwordChangeInavlidKeyMessage();
protected abstract String templateName(); protected abstract String templateName();
} }

View file

@ -56,11 +56,6 @@ public class UserAccountsResetPasswordPage extends UserAccountsPasswordBasePage
return i18n.text("password_change_not_pending", userEmail); return i18n.text("password_change_not_pending", userEmail);
} }
@Override
protected String passwordChangeInavlidKeyMessage() {
return i18n.text("password_change_invalid_key", userEmail);
}
@Override @Override
protected String templateName() { protected String templateName() {
return TEMPLATE_NAME; return TEMPLATE_NAME;

View file

@ -134,7 +134,6 @@ public class BasicAuthenticator extends Authenticator {
userAccount.setMd5Password(""); userAccount.setMd5Password("");
userAccount.setPasswordChangeRequired(false); userAccount.setPasswordChangeRequired(false);
userAccount.setPasswordLinkExpires(0L); userAccount.setPasswordLinkExpires(0L);
userAccount.setEmailKey("");
getUserAccountsDao().updateUserAccount(userAccount); getUserAccountsDao().updateUserAccount(userAccount);
} }

View file

@ -154,11 +154,11 @@ public class DeleteIndividualController extends FreemarkerHttpServlet{
private byte[] getIndividualsToDelete(String targetIndividual, String deleteQuery,VitroRequest vreq) { private byte[] getIndividualsToDelete(String targetIndividual, String deleteQuery,VitroRequest vreq) {
ByteArrayOutputStream out = new ByteArrayOutputStream(); ByteArrayOutputStream out = new ByteArrayOutputStream();
try {
Query queryForTypeSpecificDeleteQuery = QueryFactory.create(deleteQuery); Query queryForTypeSpecificDeleteQuery = QueryFactory.create(deleteQuery);
QuerySolutionMap initialBindings = new QuerySolutionMap(); QuerySolutionMap initialBindings = new QuerySolutionMap();
initialBindings.add("individualURI", ResourceFactory.createResource( targetIndividual )); initialBindings.add("individualURI", ResourceFactory.createResource( targetIndividual ));
Model ontModel = vreq.getJenaOntModel(); Model ontModel = vreq.getJenaOntModel();
try {
QueryExecution qexec = QueryExecutionFactory.create(queryForTypeSpecificDeleteQuery,ontModel,initialBindings ); QueryExecution qexec = QueryExecutionFactory.create(queryForTypeSpecificDeleteQuery,ontModel,initialBindings );
Model results = qexec.execDescribe(); Model results = qexec.execDescribe();
results.write(out,"N3"); results.write(out,"N3");

View file

@ -155,7 +155,6 @@ public class VitroVocabulary {
public static final String USERACCOUNT_LAST_LOGIN_TIME = VITRO_AUTH + "lastLoginTime"; public static final String USERACCOUNT_LAST_LOGIN_TIME = VITRO_AUTH + "lastLoginTime";
public static final String USERACCOUNT_STATUS = VITRO_AUTH + "status"; public static final String USERACCOUNT_STATUS = VITRO_AUTH + "status";
public static final String USERACCOUNT_PASSWORD_LINK_EXPIRES = VITRO_AUTH + "passwordLinkExpires"; public static final String USERACCOUNT_PASSWORD_LINK_EXPIRES = VITRO_AUTH + "passwordLinkExpires";
public static final String USERACCOUNT_EMAIL_KEY = VITRO_AUTH + "emailKey";
public static final String USERACCOUNT_PASSWORD_CHANGE_REQUIRED = VITRO_AUTH + "passwordChangeRequired"; public static final String USERACCOUNT_PASSWORD_CHANGE_REQUIRED = VITRO_AUTH + "passwordChangeRequired";
public static final String USERACCOUNT_EXTERNAL_AUTH_ID = VITRO_AUTH + "externalAuthId"; public static final String USERACCOUNT_EXTERNAL_AUTH_ID = VITRO_AUTH + "externalAuthId";
public static final String USERACCOUNT_EXTERNAL_AUTH_ONLY = VITRO_AUTH + "externalAuthOnly"; public static final String USERACCOUNT_EXTERNAL_AUTH_ONLY = VITRO_AUTH + "externalAuthOnly";

View file

@ -121,7 +121,6 @@ public class JenaBaseDaoCon {
protected DatatypeProperty USERACCOUNT_LAST_LOGIN_TIME = _constModel.createDatatypeProperty(VitroVocabulary.USERACCOUNT_LAST_LOGIN_TIME); protected DatatypeProperty USERACCOUNT_LAST_LOGIN_TIME = _constModel.createDatatypeProperty(VitroVocabulary.USERACCOUNT_LAST_LOGIN_TIME);
protected DatatypeProperty USERACCOUNT_STATUS = _constModel.createDatatypeProperty(VitroVocabulary.USERACCOUNT_STATUS); protected DatatypeProperty USERACCOUNT_STATUS = _constModel.createDatatypeProperty(VitroVocabulary.USERACCOUNT_STATUS);
protected DatatypeProperty USERACCOUNT_PASSWORD_LINK_EXPIRES = _constModel.createDatatypeProperty(VitroVocabulary.USERACCOUNT_PASSWORD_LINK_EXPIRES); protected DatatypeProperty USERACCOUNT_PASSWORD_LINK_EXPIRES = _constModel.createDatatypeProperty(VitroVocabulary.USERACCOUNT_PASSWORD_LINK_EXPIRES);
protected DatatypeProperty USERACCOUNT_EMAIL_KEY = _constModel.createDatatypeProperty(VitroVocabulary.USERACCOUNT_EMAIL_KEY);
protected DatatypeProperty USERACCOUNT_PASSWORD_CHANGE_REQUIRED = _constModel.createDatatypeProperty(VitroVocabulary.USERACCOUNT_PASSWORD_CHANGE_REQUIRED); protected DatatypeProperty USERACCOUNT_PASSWORD_CHANGE_REQUIRED = _constModel.createDatatypeProperty(VitroVocabulary.USERACCOUNT_PASSWORD_CHANGE_REQUIRED);
protected DatatypeProperty USERACCOUNT_EXTERNAL_AUTH_ID = _constModel.createDatatypeProperty(VitroVocabulary.USERACCOUNT_EXTERNAL_AUTH_ID); protected DatatypeProperty USERACCOUNT_EXTERNAL_AUTH_ID = _constModel.createDatatypeProperty(VitroVocabulary.USERACCOUNT_EXTERNAL_AUTH_ID);
protected DatatypeProperty USERACCOUNT_EXTERNAL_AUTH_ONLY = _constModel.createDatatypeProperty(VitroVocabulary.USERACCOUNT_EXTERNAL_AUTH_ONLY); protected DatatypeProperty USERACCOUNT_EXTERNAL_AUTH_ONLY = _constModel.createDatatypeProperty(VitroVocabulary.USERACCOUNT_EXTERNAL_AUTH_ONLY);

View file

@ -12,10 +12,10 @@ import java.util.function.Supplier;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.apache.jena.graph.Capabilities; import org.apache.jena.graph.Capabilities;
import org.apache.jena.graph.Graph; import org.apache.jena.graph.Graph;
import org.apache.jena.graph.GraphEventManager; import org.apache.jena.graph.GraphEventManager;
import org.apache.jena.graph.GraphListener;
import org.apache.jena.graph.GraphStatisticsHandler; import org.apache.jena.graph.GraphStatisticsHandler;
import org.apache.jena.graph.Node; import org.apache.jena.graph.Node;
import org.apache.jena.graph.TransactionHandler; import org.apache.jena.graph.TransactionHandler;
@ -23,6 +23,7 @@ import org.apache.jena.graph.Triple;
import org.apache.jena.graph.impl.GraphWithPerform; import org.apache.jena.graph.impl.GraphWithPerform;
import org.apache.jena.graph.impl.SimpleEventManager; import org.apache.jena.graph.impl.SimpleEventManager;
import org.apache.jena.query.QuerySolution; import org.apache.jena.query.QuerySolution;
import org.apache.jena.rdf.listeners.StatementListener;
import org.apache.jena.rdf.model.Model; import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.ModelFactory; import org.apache.jena.rdf.model.ModelFactory;
import org.apache.jena.rdf.model.StmtIterator; import org.apache.jena.rdf.model.StmtIterator;
@ -403,18 +404,7 @@ public class RDFServiceGraph implements GraphWithPerform {
@Override @Override
public GraphEventManager getEventManager() { public GraphEventManager getEventManager() {
if (eventManager == null) { if (eventManager == null) {
eventManager = new SimpleEventManager() { eventManager = new SimpleEventManager(this);
@Override
public void notifyEvent(Graph g, Object event) {
ChangeSet changeSet = rdfService.manufactureChangeSet();
changeSet.addPreChangeEvent(event);
try {
rdfService.changeSetUpdate(changeSet);
} catch (RDFServiceException e) {
throw new RuntimeException(e);
}
}
};
} }
return eventManager; return eventManager;
} }
@ -600,7 +590,21 @@ public class RDFServiceGraph implements GraphWithPerform {
} }
public static Model createRDFServiceModel(final RDFServiceGraph g) { public static Model createRDFServiceModel(final RDFServiceGraph g) {
return VitroModelFactory.createModelForGraph(g); Model m = VitroModelFactory.createModelForGraph(g);
m.register(new StatementListener() {
@Override
public void notifyEvent(Model m, Object event) {
ChangeSet changeSet = g.getRDFService().manufactureChangeSet();
changeSet.addPreChangeEvent(event);
try {
g.getRDFService().changeSetUpdate(changeSet);
} catch (RDFServiceException e) {
throw new RuntimeException(e);
}
}
});
return m;
} }
@Override @Override

View file

@ -4,6 +4,7 @@ package edu.cornell.mannlib.vitro.webapp.dao.jena;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.List; import java.util.List;
import java.util.Random; import java.util.Random;
@ -97,8 +98,6 @@ public class UserAccountsDaoJena extends JenaBaseDao implements UserAccountsDao
u.setOldPassword(getPropertyStringValue(r, USERACCOUNT_OLD_PASSWORD)); u.setOldPassword(getPropertyStringValue(r, USERACCOUNT_OLD_PASSWORD));
u.setPasswordLinkExpires(getPropertyLongValue(r, u.setPasswordLinkExpires(getPropertyLongValue(r,
USERACCOUNT_PASSWORD_LINK_EXPIRES)); USERACCOUNT_PASSWORD_LINK_EXPIRES));
u.setEmailKey(getPropertyStringValue(r,USERACCOUNT_EMAIL_KEY));
u.setPasswordChangeRequired(getPropertyBooleanValue(r, u.setPasswordChangeRequired(getPropertyBooleanValue(r,
USERACCOUNT_PASSWORD_CHANGE_REQUIRED)); USERACCOUNT_PASSWORD_CHANGE_REQUIRED));
u.setExternalAuthOnly(getPropertyBooleanValue(r, u.setExternalAuthOnly(getPropertyBooleanValue(r,
@ -241,8 +240,6 @@ public class UserAccountsDaoJena extends JenaBaseDao implements UserAccountsDao
userAccount.getLoginCount(), model); userAccount.getLoginCount(), model);
addPropertyLongValue(res, USERACCOUNT_LAST_LOGIN_TIME, addPropertyLongValue(res, USERACCOUNT_LAST_LOGIN_TIME,
userAccount.getLastLoginTime(), model); userAccount.getLastLoginTime(), model);
addPropertyStringValue(res, USERACCOUNT_EMAIL_KEY,
userAccount.getEmailKey(), model);
if (userAccount.getStatus() != null) { if (userAccount.getStatus() != null) {
addPropertyStringValue(res, USERACCOUNT_STATUS, userAccount addPropertyStringValue(res, USERACCOUNT_STATUS, userAccount
.getStatus().toString(), model); .getStatus().toString(), model);
@ -309,8 +306,6 @@ public class UserAccountsDaoJena extends JenaBaseDao implements UserAccountsDao
userAccount.getLoginCount(), model); userAccount.getLoginCount(), model);
updatePropertyLongValue(res, USERACCOUNT_LAST_LOGIN_TIME, updatePropertyLongValue(res, USERACCOUNT_LAST_LOGIN_TIME,
userAccount.getLastLoginTime(), model); userAccount.getLastLoginTime(), model);
updatePropertyStringValue(res, USERACCOUNT_EMAIL_KEY,
userAccount.getEmailKey(), model);
if (userAccount.getStatus() == null) { if (userAccount.getStatus() == null) {
updatePropertyStringValue(res, USERACCOUNT_STATUS, null, model); updatePropertyStringValue(res, USERACCOUNT_STATUS, null, model);
} else { } else {

View file

@ -61,10 +61,6 @@ public class EditConfigurationUtils {
return vreq.getParameter("rangeUri"); return vreq.getParameter("rangeUri");
} }
public static String getTypeOfNew(VitroRequest vreq) {
return vreq.getParameter("typeOfNew");
}
public static VClass getRangeVClass(VitroRequest vreq) { public static VClass getRangeVClass(VitroRequest vreq) {
// This needs a WebappDaoFactory with no filtering/RDFService // This needs a WebappDaoFactory with no filtering/RDFService
// funny business because it needs to be able to retrieve anonymous union // funny business because it needs to be able to retrieve anonymous union

View file

@ -49,26 +49,18 @@ public class DefaultDeleteGenerator extends BaseEditConfigurationGenerator imple
prepare(vreq, editConfiguration); prepare(vreq, editConfiguration);
if (editConfiguration.getPredicateUri() == null && editConfiguration.getSubjectUri() == null) { if (editConfiguration.getPredicateUri() == null && editConfiguration.getSubjectUri() == null) {
editConfiguration.setTemplate(individualTemplate); editConfiguration.setTemplate(individualTemplate);
addDeleteParams(vreq, editConfiguration); addRedirectUrl(vreq, editConfiguration);
}else { }else {
editConfiguration.setTemplate(propertyTemplate); editConfiguration.setTemplate(propertyTemplate);
} }
return editConfiguration; return editConfiguration;
} }
private void addDeleteParams(VitroRequest vreq, EditConfigurationVTwo editConfiguration) { private void addRedirectUrl(VitroRequest vreq, EditConfigurationVTwo editConfiguration) {
String redirectUrl = vreq.getParameter("redirectUrl"); String redirectUrl = vreq.getParameter("redirectUrl");
if (redirectUrl != null) { if (redirectUrl != null) {
editConfiguration.addFormSpecificData("redirectUrl", redirectUrl); editConfiguration.addFormSpecificData("redirectUrl", redirectUrl);
} }
String individualName = vreq.getParameter("individualName");
if (redirectUrl != null) {
editConfiguration.addFormSpecificData("individualName", individualName);
}
String individualType = vreq.getParameter("individualType");
if (redirectUrl != null) {
editConfiguration.addFormSpecificData("individualType", individualType);
}
} }
private EditConfigurationVTwo setupEditConfiguration(VitroRequest vreq, HttpSession session) { private EditConfigurationVTwo setupEditConfiguration(VitroRequest vreq, HttpSession session) {

View file

@ -11,7 +11,6 @@ import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession; import javax.servlet.http.HttpSession;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.apache.jena.ontology.OntModel; import org.apache.jena.ontology.OntModel;
@ -68,19 +67,9 @@ public class EditRequestDispatchController extends FreemarkerHttpServlet {
//TODO: Create this generator //TODO: Create this generator
final String RDFS_LABEL_FORM = "edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.generators.RDFSLabelGenerator"; final String RDFS_LABEL_FORM = "edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.generators.RDFSLabelGenerator";
final String DEFAULT_DELETE_FORM = "edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.generators.DefaultDeleteGenerator"; final String DEFAULT_DELETE_FORM = "edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.generators.DefaultDeleteGenerator";
final String MANAGE_MENUS_FORM = "edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.generators.ManagePageGenerator";
@Override @Override
protected AuthorizationRequest requiredActions(VitroRequest vreq) { protected AuthorizationRequest requiredActions(VitroRequest vreq) {
// If request is for new individual, return simple do back end editing action permission
if (StringUtils.isNotEmpty(EditConfigurationUtils.getTypeOfNew(vreq))) {
return SimplePermission.DO_BACK_END_EDITING.ACTION;
} else if(MANAGE_MENUS_FORM.equals(vreq.getParameter("editForm"))) {
return SimplePermission.MANAGE_MENUS.ACTION;
}
if (isIndividualDeletion(vreq)) {
return SimplePermission.DO_BACK_END_EDITING.ACTION;
}
//Check if this statement can be edited here and return unauthorized if not //Check if this statement can be edited here and return unauthorized if not
String subjectUri = EditConfigurationUtils.getSubjectUri(vreq); String subjectUri = EditConfigurationUtils.getSubjectUri(vreq);
String predicateUri = EditConfigurationUtils.getPredicateUri(vreq); String predicateUri = EditConfigurationUtils.getPredicateUri(vreq);
@ -109,16 +98,6 @@ public class EditRequestDispatchController extends FreemarkerHttpServlet {
return isAuthorized? SimplePermission.DO_FRONT_END_EDITING.ACTION: AuthorizationRequest.UNAUTHORIZED; return isAuthorized? SimplePermission.DO_FRONT_END_EDITING.ACTION: AuthorizationRequest.UNAUTHORIZED;
} }
private boolean isIndividualDeletion(VitroRequest vreq) {
String subjectUri = EditConfigurationUtils.getSubjectUri(vreq);
String predicateUri = EditConfigurationUtils.getPredicateUri(vreq);
String objectUri = EditConfigurationUtils.getObjectUri(vreq);
if (objectUri != null && subjectUri == null && predicateUri == null && isDeleteForm(vreq)) {
return true;
}
return false;
}
@Override @Override
protected ResponseValues processRequest(VitroRequest vreq) { protected ResponseValues processRequest(VitroRequest vreq) {

View file

@ -5,14 +5,15 @@ package edu.cornell.mannlib.vitro.webapp.search.controller;
import java.io.IOException; import java.io.IOException;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Base64;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet; import javax.servlet.annotation.WebServlet;
@ -40,6 +41,7 @@ import edu.cornell.mannlib.vitro.webapp.dao.VClassDao;
import edu.cornell.mannlib.vitro.webapp.dao.VClassGroupDao; import edu.cornell.mannlib.vitro.webapp.dao.VClassGroupDao;
import edu.cornell.mannlib.vitro.webapp.dao.VClassGroupsForRequest; import edu.cornell.mannlib.vitro.webapp.dao.VClassGroupsForRequest;
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary; import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
import edu.cornell.mannlib.vitro.webapp.dao.jena.QueryUtils;
import edu.cornell.mannlib.vitro.webapp.dao.jena.VClassGroupCache; import edu.cornell.mannlib.vitro.webapp.dao.jena.VClassGroupCache;
import edu.cornell.mannlib.vitro.webapp.i18n.I18n; import edu.cornell.mannlib.vitro.webapp.i18n.I18n;
import edu.cornell.mannlib.vitro.webapp.modules.searchEngine.SearchEngine; import edu.cornell.mannlib.vitro.webapp.modules.searchEngine.SearchEngine;
@ -54,6 +56,9 @@ import edu.cornell.mannlib.vitro.webapp.web.templatemodels.LinkTemplateModel;
import edu.cornell.mannlib.vitro.webapp.web.templatemodels.searchresult.IndividualSearchResult; import edu.cornell.mannlib.vitro.webapp.web.templatemodels.searchresult.IndividualSearchResult;
import edu.ucsf.vitro.opensocial.OpenSocialManager; import edu.ucsf.vitro.opensocial.OpenSocialManager;
import org.apache.jena.query.QuerySolution;
import org.apache.jena.query.ResultSet;
import org.apache.jena.rdf.model.Literal;
/** /**
* Paged search controller that uses the search engine * Paged search controller that uses the search engine
*/ */
@ -75,6 +80,18 @@ public class CustomSearchController extends FreemarkerHttpServlet {
private static final String PARAM_RDFTYPE = "type"; private static final String PARAM_RDFTYPE = "type";
private static final String PARAM_QUERY_TEXT = "querytext"; private static final String PARAM_QUERY_TEXT = "querytext";
private static String FILTERS_QUERY = ""
+ "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>"
+ "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>"
+ "PREFIX search: <https://dideside.com/searchOntology#>"
+ "SELECT ?filterID ?fieldField ?filterLabel"
+ "WHERE"
+ "{ ?filterStatement rdf:type search:filter ."
+ " ?filterStatement search:field ?fieldField ."
+ " ?filterStatement search:id ?filterID ."
+ " ?filterStatement rdfs:label ?filterLabel ."
+ "} ORDER BY ?fileterLabel";
protected static final Map<Format,Map<Result,String>> templateTable; protected static final Map<Format,Map<Result,String>> templateTable;
protected enum Format { protected enum Format {
@ -128,39 +145,6 @@ public class CustomSearchController extends FreemarkerHttpServlet {
} }
} }
@Override
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
VitroRequest vreq = new VitroRequest(request);
boolean wasXmlRequested = isRequestedFormatXml(vreq);
boolean wasCSVRequested = isRequestedFormatCSV(vreq);
if( !wasXmlRequested && !wasCSVRequested){
super.doGet(vreq,response);
}else if (wasXmlRequested){
try {
ResponseValues rvalues = processRequest(vreq);
response.setCharacterEncoding("UTF-8");
response.setContentType("text/xml;charset=UTF-8");
response.setHeader("Content-Disposition", "attachment; filename=search.xml");
writeTemplate(rvalues.getTemplateName(), rvalues.getMap(), request, response);
} catch (Exception e) {
log.error(e, e);
}
}else if (wasCSVRequested){
try {
ResponseValues rvalues = processRequest(vreq);
response.setCharacterEncoding("UTF-8");
response.setContentType("text/csv;charset=UTF-8");
response.setHeader("Content-Disposition", "attachment; filename=search.csv");
writeTemplate(rvalues.getTemplateName(), rvalues.getMap(), request, response);
} catch (Exception e) {
log.error(e, e);
}
}
}
@Override @Override
protected ResponseValues processRequest(VitroRequest vreq) { protected ResponseValues processRequest(VitroRequest vreq) {
@ -190,8 +174,6 @@ public class CustomSearchController extends FreemarkerHttpServlet {
int startIndex = getStartIndex(vreq); int startIndex = getStartIndex(vreq);
int hitsPerPage = getHitsPerPage( vreq ); int hitsPerPage = getHitsPerPage( vreq );
String queryBuilderRules = getQueryBuilderRules(vreq);
String queryText = vreq.getParameter(PARAM_QUERY_TEXT); String queryText = vreq.getParameter(PARAM_QUERY_TEXT);
log.debug("Query text is \""+ queryText + "\""); log.debug("Query text is \""+ queryText + "\"");
@ -235,6 +217,10 @@ public class CustomSearchController extends FreemarkerHttpServlet {
for (SearchResultDocument doc : docs) { for (SearchResultDocument doc : docs) {
try { try {
String uri = doc.getStringValue(VitroSearchTermNames.URI); String uri = doc.getStringValue(VitroSearchTermNames.URI);
/*
* if(possibleExcerpts.contains(uri)) { log.info("FOUND AVAILIBLE URI " + uri);
* }
*/
Individual ind = iDao.getIndividualByURI(uri); Individual ind = iDao.getIndividualByURI(uri);
if (ind != null) { if (ind != null) {
ind.setSearchSnippet(getSnippet(doc, response)); ind.setSearchSnippet(getSnippet(doc, response));
@ -317,10 +303,6 @@ public class CustomSearchController extends FreemarkerHttpServlet {
body.put("nextPage", getNextPageLink(startIndex, hitsPerPage, body.put("nextPage", getNextPageLink(startIndex, hitsPerPage,
vreq.getServletPath(), pagingLinkParams)); vreq.getServletPath(), pagingLinkParams));
} }
if (queryBuilderRules != null) {
body.put("queryBuilderRules", queryBuilderRules);
}
body.put(PARAM_HITS_PER_PAGE, hitsPerPage);
// VIVO OpenSocial Extension by UCSF // VIVO OpenSocial Extension by UCSF
try { try {
@ -354,15 +336,25 @@ public class CustomSearchController extends FreemarkerHttpServlet {
} }
} }
private String getQueryBuilderRules(VitroRequest vreq) { private Set<String> getExistingExcerpts( VitroRequest vreq) {
String rules = null; Set<String> labels = new HashSet<String>();
try { try {
rules = vreq.getParameter("queryBuilderRules"); //We want to get the labels for all the languages, not just the display language
} catch (Throwable e) { ResultSet results = QueryUtils.getLanguageNeutralQueryResults(FILTERS_QUERY, vreq);
log.error(e); while (results.hasNext()) {
QuerySolution solution = results.nextSolution();
String nodeLiteral = solution.get("individualUri").toString();
log.debug(nodeLiteral.toString());
labels.add(nodeLiteral);
} }
return rules; } catch (Exception e) {
log.error(e, e);
} }
return labels;
}
private int getHitsPerPage(VitroRequest vreq) { private int getHitsPerPage(VitroRequest vreq) {
int hitsPerPage = DEFAULT_HITS_PER_PAGE; int hitsPerPage = DEFAULT_HITS_PER_PAGE;

View file

@ -157,12 +157,13 @@ public abstract class BaseIndividualTemplateModel extends BaseTemplateModel {
ParamMap params = new ParamMap( ParamMap params = new ParamMap(
"objectUri", individual.getURI(), "objectUri", individual.getURI(),
"cmd", "delete", "cmd", "delete",
"individualName",getNameStatement().getValue() "statement_label",getNameStatement().getValue(),
"statement_object",individual.getURI()
); );
Iterator<String> typesIterator = types.iterator(); Iterator<String> typesIterator = types.iterator();
if (types.iterator().hasNext()) { if (types.iterator().hasNext()) {
String type = typesIterator.next(); String type = typesIterator.next();
params.put("individualType", type); params.put("statement_type", type);
} }
return UrlBuilder.getUrl(EDIT_PATH, params); return UrlBuilder.getUrl(EDIT_PATH, params);

View file

@ -1,62 +0,0 @@
package edu.cornell.mannlib.vitro.webapp.dao.jena;
import static org.junit.Assert.assertEquals;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.ModelFactory;
import org.junit.Test;
import edu.cornell.mannlib.vitro.testing.AbstractTestClass;
import edu.cornell.mannlib.vitro.webapp.rdfservice.ChangeListener;
import edu.cornell.mannlib.vitro.webapp.rdfservice.ModelChange;
import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService;
import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFServiceException;
import edu.cornell.mannlib.vitro.webapp.rdfservice.impl.jena.model.RDFServiceModel;
public class RDFServiceGraphTest extends AbstractTestClass {
@Test
/**
* Test that creating a new model with the same underlying RDFServiceGraph
* does not result in a new listener registered on that graph. No matter
* how many models have been created using a given RDFServiceGraph, an event
* sent to the last-created model should be heard only once by the
* RDFService.
* @throws RDFServiceException
*/
public void testEventListening() throws RDFServiceException {
Model m = ModelFactory.createDefaultModel();
RDFService rdfService = new RDFServiceModel(m);
EventsCounter counter = new EventsCounter();
rdfService.registerListener(counter);
RDFServiceGraph g = new RDFServiceGraph(rdfService);
Model model = null;
for (int i = 0; i < 100; i++) {
model = RDFServiceGraph.createRDFServiceModel(g);
}
model.notifyEvent("event");
assertEquals(1, counter.getCount());
}
private class EventsCounter implements ChangeListener {
private int count = 0;
public int getCount() {
return count;
}
@Override
public void notifyModelChange(ModelChange modelChange) {
// TODO Auto-generated method stub
}
@Override
public void notifyEvent(String graphURI, Object event) {
count++;
}
}
}

View file

@ -11,3 +11,31 @@
# Find out how to use this file at # Find out how to use this file at
# https://wiki.duraspace.org/display/VIVO/Using+Short+Views+in+Release+1.5 # https://wiki.duraspace.org/display/VIVO/Using+Short+Views+in+Release+1.5
# #
@prefix ts_: <https://litvinovg.pro/text_structures#> .
@prefix display: <http://vitro.mannlib.cornell.edu/ontologies/display/1.1#> .
@prefix mydomain: <http://vivo.mydomain.edu/individual/> .
ts_:elenphExcerpt display:hasCustomView mydomain:elenphExcerptShortView .
mydomain:elenphExcerptShortView
a display:customViewForIndividual ;
display:appliesToContext "SEARCH" ;
display:hasTemplate "elenphExcerptShortView.ftl" ;
display:hasDataGetter mydomain:elenphExcerptShortViewDataGetter .
mydomain:elenphExcerptShortViewDataGetter
a <java:edu.cornell.mannlib.vitro.webapp.utils.dataGetter.SparqlQueryDataGetter>;
display:saveToVar "excerptInfo";
display:query
"""
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX vivo: <http://vivoweb.org/ontology/core#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX ts_: <https://litvinovg.pro/text_structures#>
SELECT ?property ?value
WHERE {
?individualUri ?property ?value .
?individualUri rdf:type ts_:elenphExcerpt .
}
""" .

View file

@ -26,7 +26,7 @@
<form method="POST" action="${formUrls.createPassword}" class="customForm" role="create password"> <form method="POST" action="${formUrls.createPassword}" class="customForm" role="create password">
<input type="hidden" name="user" value="${userAccount.emailAddress}" role="input" /> <input type="hidden" name="user" value="${userAccount.emailAddress}" role="input" />
<input type="hidden" name="key" value="${userAccount.emailKey}" role="input" /> <input type="hidden" name="key" value="${userAccount.passwordLinkExpiresHash}" role="input" />
<label for="new-password">${strings.new_password}<span class="requiredHint"> *</span></label> <label for="new-password">${strings.new_password}<span class="requiredHint"> *</span></label>
<input type="password" name="newPassword" value="${newPassword}" id="new-password" role="input" /> <input type="password" name="newPassword" value="${newPassword}" id="new-password" role="input" />

View file

@ -26,7 +26,7 @@
<section id="reset-password" role="region"> <section id="reset-password" role="region">
<form method="POST" action="${formUrls.resetPassword}" class="customForm" role="create password"> <form method="POST" action="${formUrls.resetPassword}" class="customForm" role="create password">
<input type="hidden" name="user" value="${userAccount.emailAddress}" /> <input type="hidden" name="user" value="${userAccount.emailAddress}" />
<input type="hidden" name="key" value="${userAccount.emailKey}" /> <input type="hidden" name="key" value="${userAccount.passwordLinkExpiresHash}" />
<label for="new-password">${strings.new_password}<span class="requiredHint"> *</span></label> <label for="new-password">${strings.new_password}<span class="requiredHint"> *</span></label>
<input type="password" name="newPassword" value="${newPassword}" id="new-password" role="input" /> <input type="password" name="newPassword" value="${newPassword}" id="new-password" role="input" />

View file

@ -26,7 +26,7 @@
</ul> </ul>
<nav id="alpha-browse-container" role="navigation"> <nav id="alpha-browse-container" role="navigation">
<h3 class="selected-class"></h3> <h3 class="selected-class"></h3>
<#assign alphabet = ["A", "B", "C", "D", "E", "F", "G" "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"] /> <#assign alphabet = ["А", "Б", "В", "Г", "Д", "Е", "Ё" "Ж", "З", "И", "Й", "К", "Л", "М", "Н", "О", "П", "Р", "С", "Т", "У", "Ф", "Х", "Ц", "Ч", "Ш", "Щ", "Э", "Ю", "Я" ] />
<ul id="alpha-browse-individuals"> <ul id="alpha-browse-individuals">
<li><a href="#" class="selected" data-alpha="all" title="${i18n().select_all}">${i18n().all}</a></li> <li><a href="#" class="selected" data-alpha="all" title="${i18n().select_all}">${i18n().all}</a></li>
<#list alphabet as letter> <#list alphabet as letter>

View file

@ -9,4 +9,5 @@
<p> <p>
${message?html} ${message?html}
</p> </p>
<#include "searchSelector.ftl">
<#include "search-help.ftl" > <#include "search-help.ftl" >

View file

@ -3,10 +3,13 @@
<#-- Template for displaying paged search results --> <#-- Template for displaying paged search results -->
<h2 class="searchResultsHeader"> <h2 class="searchResultsHeader">
<#include "searchSelector.ftl">
<#escape x as x?html> <#escape x as x?html>
${i18n().search_results_for} '${querytext}' <div id='searchQueryResults'> ${i18n().search_results_for} '${querytext}'</div>
<#if classGroupName?has_content>${i18n().limited_to_type} '${classGroupName}'</#if> <div id='limitedToClassGroup'> <#if classGroupName?has_content>${i18n().limited_to_type} '${classGroupName}'</#if> </div>
<#if typeName?has_content>${i18n().limited_to_type} '${typeName}'</#if> <div id='limitedToType'> <#if typeName?has_content>${i18n().limited_to_type} '${typeName}'</#if> </div>
</#escape> </#escape>
<script type="text/javascript"> <script type="text/javascript">
var url = window.location.toString(); var url = window.location.toString();
@ -28,7 +31,7 @@
<div class="contentsBrowseGroup"> <div class="contentsBrowseGroup">
<#-- Refinement links --> <#-- Refinement links -->
<#if classGroupLinks?has_content> <#if classGroupLinks?has_content && classGroupLinks?size gt 1>
<div class="searchTOC"> <div class="searchTOC">
<h4>${i18n().display_only}</h4> <h4>${i18n().display_only}</h4>
<ul> <ul>
@ -39,7 +42,7 @@
</div> </div>
</#if> </#if>
<#if classLinks?has_content> <#if classLinks?has_content && classLinks?size gt 1 >
<div class="searchTOC"> <div class="searchTOC">
<#if classGroupName?has_content> <#if classGroupName?has_content>
<h4>${i18n().limit} ${classGroupName} ${i18n().to}</h4> <h4>${i18n().limit} ${classGroupName} ${i18n().to}</h4>
@ -54,6 +57,17 @@
</div> </div>
</#if> </#if>
<div class="virtualArticleSwitch">
<label class="switch">Показать виртуальную статью
<input id="virtualArticleCheck" type="checkbox" checked="false" onclick="showVirtualArticles();">
</label>
</div>
<#if user.loggedIn>
<div>
<button onclick="createNewCompilation()">Сохранить</button>
</div>
</#if>
<#-- Search results --> <#-- Search results -->
<ul class="searchhits"> <ul class="searchhits">
<#list individuals as individual> <#list individuals as individual>
@ -108,6 +122,108 @@
</div> <!-- end contentsBrowseGroup --> </div> <!-- end contentsBrowseGroup -->
<script>
$('input[type=checkbox]').removeAttr('checked');
function showVirtualArticles(){
var checkBox = document.getElementById("virtualArticleCheck");
if (checkBox.checked == true){
$('.excerptSearchResult').hide();
$('.virtualArticlePart').show();
} else {
$('.excerptSearchResult').show();
$('.virtualArticlePart').hide();
}
}
function createNewCompilation() {
var compilationName = window.prompt("Введите название подборки.");
if (!compilationName){
alert("Для создания подоборки необходимо ввести её название.");
return;
}
var iframe = document.createElement("iframe");
var excerptsCounter = $('.virtualArticlePart').length;
iframe.setAttribute("src", "${urls.base}/editRequestDispatch?typeOfNew=https%3A%2F%2Flitvinovg.pro%2Ftext_structures%23compilation&editForm=edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.generators.CompilationGenerator&excerptsCount=" + excerptsCounter);
iframe.style.width = "1px";
iframe.style.height = "1px";
iframe.id="newCompilationIframe";
//iframe.style.display="none";
document.body.appendChild(iframe);
$('#newCompilationIframe').on('load', function(){
fillOutForm(compilationName);
});
}
function fillOutForm(compilationName){
var iframeDoc = document.getElementById('newCompilationIframe').contentWindow.document;
iframeDoc.getElementById('newCompilationLabel').value = compilationName;
var excerpts = $('.virtualArticlePart').toArray();
for (i = 0;i < excerpts.length;i++){
var excerptUri = excerpts[i].getAttribute('parturi');
var excerptName = $(excerpts[i]).children('button').html();
var number = i + 1;
iframeDoc.getElementById("tocLevel" + number + "Name").value = excerptName + " (" + compilationName + ")";
iframeDoc.getElementById("tocItem" + number + "Name").value = excerptName + " (" + compilationName + ")";
iframeDoc.getElementById("excerpt" + number).value = excerptUri;
}
$('#newCompilationIframe').off('load');
iframeDoc.getElementById('submit').click();
$('#newCompilationIframe').on('load', function(){
redirectToNewCompilation();
});
}
function redirectToNewCompilation(){
var newURL = document.getElementById('newCompilationIframe').contentWindow.location.href;
window.open(newURL,"_self");
}
</script>
<script>
let workSet = new Set();
let biblioSet = new Set();
var workDivs = $('.virtualArticleWork');
var biblioDivs = $('.virtualArticleBibliography');
biblioDivs.each(function() {
biblioSet.add($(this).html());
});
workDivs.each(function() {
workSet.add($(this).html());
});
var workArr = Array.from(workSet);
workArr.sort();
var biblioArr = Array.from(biblioSet);
biblioArr.sort();
if (workArr.length > 0 ) {
$('<div class="virtualArticleWorks"><button type="button" style="margin-top:16px;border:none;padding: 18px;width: 100%; text-align:left;" class="collapsible">Работы</button><div class="virtualWorks"></div></div>').insertAfter($('.virtualArticlePart').last());
for (let value of workArr){
$('.virtualWorks').last().append( '<div class="work"><p>' + value + '</p></div>' );
}
}
if (biblioArr.length > 0 ) {
$('<div class="virtualArticleBiblio"><button type="button" style="margin-top:16px;border:none;padding: 18px;width: 100%; text-align:left;" class="collapsible">Литература</button><div class="virtualBibliography"></div></div>').insertAfter($('.virtualArticlePart').last());
for (let value of biblioArr){
$('.virtualBibliography').last().append( '<div class="bibliography"><p>' + value + '</p></div>' );
}
}
</script>
<script>
$('.virtualWorks').hide();
$('.virtualBibliography').hide();
$('.virtualArticlePart').hide();
var coll = document.getElementsByClassName("collapsible");
var i;
for (i = 0; i < coll.length; i++) {
coll[i].addEventListener("click", function() {
this.classList.toggle("active");
var content = this.nextElementSibling;
if (content.style.display === "block") {
content.style.display = "none";
} else {
content.style.display = "block";
}
});
}
</script>
${stylesheets.add('<link rel="stylesheet" href="//code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css" />', ${stylesheets.add('<link rel="stylesheet" href="//code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css" />',
'<link rel="stylesheet" href="${urls.base}/css/search.css" />', '<link rel="stylesheet" href="${urls.base}/css/search.css" />',
'<link rel="stylesheet" type="text/css" href="${urls.base}/css/jquery_plugins/qtip/jquery.qtip.min.css" />')} '<link rel="stylesheet" type="text/css" href="${urls.base}/css/jquery_plugins/qtip/jquery.qtip.min.css" />')}

View file

@ -4,28 +4,19 @@
<#else> <#else>
<#assign redirectUrl = "/" /> <#assign redirectUrl = "/" />
</#if> </#if>
<#if editConfiguration.pageData.individualName??> <#assign statement = editConfiguration.objectStatementDisplay />
<#assign individualName = editConfiguration.pageData.individualName /> <#assign deletionTemplateName = editConfiguration.deleteTemplate/>
</#if>
<#if editConfiguration.pageData.individualType??>
<#assign individualType = editConfiguration.pageData.individualType />
</#if>
<form action="${editConfiguration.deleteIndividualProcessingUrl}" method="get"> <form action="${editConfiguration.deleteIndividualProcessingUrl}" method="get">
<h2>${i18n().confirm_individual_deletion} </h2> <h2>${i18n().confirm_individual_deletion} </h2>
<input type="hidden" name="individualUri" value="${editConfiguration.objectUri}" role="input" /> <input type="hidden" name="individualUri" value="${editConfiguration.objectUri}" role="input" />
<input type="hidden" name="redirectUrl" value="${redirectUrl}" role="input" /> <input type="hidden" name="redirectUrl" value="${redirectUrl}" role="input" />
<#assign deletionTemplateName = editConfiguration.deleteTemplate/>
<p> <#if statement?has_content>
<#if individualType??> <#include deletionTemplateName />
${individualType}
</#if> </#if>
<#if individualName??>
${individualName}
</#if>
</p>
<br /> <br />
<p class="submit"> <p class="submit">
<input type="submit" id="submit" value="${i18n().delete_button}" role="button"/> <input type="submit" id="submit" value="${i18n().delete_button}" role="button"/>

View file

@ -39,7 +39,7 @@
theme_advanced_resizing : true, theme_advanced_resizing : true,
height : "${height}", height : "${height}",
width : "${width}", width : "${width}",
valid_elements : "tr[*],td[*],tbody[*],table[*],a[href|name|title],br,p[style],i,em,cite,strong/b,u,sub,sup,ul,ol,li,h1[dir|style|id],h2[dir|style|id],h3[dir|style|id],h4,h5,h6,div[style|class],span[dir|style|class]", valid_elements : "a[href|name|title],br,p[style],i,em,cite,strong/b,u,sub,sup,ul,ol,li,h1[dir|style|id],h2[dir|style|id],h3[dir|style|id],h4,h5,h6,div[style|class],span[dir|style|class]",
fix_list_elements : true, fix_list_elements : true,
fix_nesting : true, fix_nesting : true,
cleanup_on_startup : true, cleanup_on_startup : true,