Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Story/cite 178: Delete Documents from Citesphere #244

Open
wants to merge 11 commits into
base: develop
Choose a base branch
from
Original file line number Diff line number Diff line change
Expand Up @@ -85,4 +85,8 @@ CloseableIterator<ICitation> getAllGroupItems(IUser user, String groupId, String

void deleteLocalGroupCitations(String groupId);

void deleteFile(IUser user, String zoteroGroupId, String itemId, String documentId)
throws GroupDoesNotExistException, CannotFindCitationException, ZoteroHttpStatusException,
ZoteroConnectionException, CitationIsOutdatedException, ZoteroItemCreationFailedException;

}
Original file line number Diff line number Diff line change
@@ -1,15 +1,25 @@
package edu.asu.diging.citesphere.core.service.giles;

import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.HttpClientErrorException;

import edu.asu.diging.citesphere.user.IUser;

public interface IGilesConnector {

<T> ResponseEntity<T> sendRequest(IUser user, String endpoint, Class<T> returnType)
<T> ResponseEntity<T> sendRequest(IUser user, String endpoint, Class<T> returnType, HttpMethod httpMethod)
throws HttpClientErrorException;

byte[] getFile(IUser user, String fileId);

}

/**
* Deletes a document for the given user.
* @param user The user performing the document deletion.
* @param documentId The ID of the document to be deleted.
* @return The HTTP status code indicating the success or failure of the delete operation.
* @throws RestClientException if there is an issue sending the delete request to the server.
*/
HttpStatus deleteDocument(IUser user, String documentId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package edu.asu.diging.citesphere.core.service.giles;

import org.springframework.social.zotero.exception.ZoteroConnectionException;

import edu.asu.diging.citesphere.core.exceptions.CitationIsOutdatedException;
import edu.asu.diging.citesphere.core.exceptions.ZoteroHttpStatusException;
import edu.asu.diging.citesphere.core.exceptions.ZoteroItemCreationFailedException;
import edu.asu.diging.citesphere.model.bib.ICitation;
import edu.asu.diging.citesphere.model.bib.IGilesUpload;
import edu.asu.diging.citesphere.user.IUser;

public interface IGilesDeletionChecker {
void addDocumentCitationMap(IGilesUpload upload, ICitation citation, String zoteroId, IUser user);

void checkDeletion() throws ZoteroConnectionException, CitationIsOutdatedException, ZoteroHttpStatusException, ZoteroItemCreationFailedException;
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;
Expand All @@ -29,6 +30,9 @@ public class GilesConnector implements IGilesConnector {
@Value("${giles_file_endpoint}")
private String fileEndpoint;

@Value("${giles_document_endpoint}")
private String documentEndpoint;

@Autowired
private InternalTokenManager internalTokenManager;

Expand All @@ -44,25 +48,29 @@ public void init() {
* @see edu.asu.diging.citesphere.core.service.giles.impl.IGilesConnector#sendRequest(edu.asu.diging.citesphere.user.IUser, java.lang.String, java.lang.Class)
*/
@Override
public <T> ResponseEntity<T> sendRequest(IUser user, String endpoint,Class<T> returnType) throws HttpClientErrorException {
public <T> ResponseEntity<T> sendRequest(IUser user, String endpoint,Class<T> returnType, HttpMethod httpMethod) throws HttpClientErrorException {
String token = internalTokenManager.getAccessToken(user).getValue();

HttpHeaders headers = new HttpHeaders();
headers.setBearerAuth(token);
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(
headers);

return restTemplate.exchange(
gilesBaseurl + endpoint,
HttpMethod.GET, requestEntity, returnType);
httpMethod, requestEntity, returnType);
}

/* (non-Javadoc)
* @see edu.asu.diging.citesphere.core.service.giles.impl.IGilesConnector#getFile(edu.asu.diging.citesphere.user.IUser, java.lang.String)
*/
@Override
public byte[] getFile(IUser user, String fileId) {
ResponseEntity<byte[]> content = sendRequest(user, fileEndpoint.replace("{0}", fileId), byte[].class);
ResponseEntity<byte[]> content = sendRequest(user, fileEndpoint.replace("{0}", fileId), byte[].class, HttpMethod.GET);
return content.getBody();
}

@Override
public HttpStatus deleteDocument(IUser user, String documentId) {
ResponseEntity<String> response = sendRequest(user, documentEndpoint.replace("{documentId}", documentId), String.class, HttpMethod.DELETE);
return response.getStatusCode();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package edu.asu.diging.citesphere.core.service.giles.impl;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;

import javax.annotation.PostConstruct;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.social.zotero.exception.ZoteroConnectionException;
import org.springframework.stereotype.Component;

import edu.asu.diging.citesphere.core.exceptions.CitationIsOutdatedException;
import edu.asu.diging.citesphere.core.exceptions.ZoteroHttpStatusException;
import edu.asu.diging.citesphere.core.exceptions.ZoteroItemCreationFailedException;
import edu.asu.diging.citesphere.core.service.ICitationManager;
import edu.asu.diging.citesphere.core.service.giles.IGilesConnector;
import edu.asu.diging.citesphere.core.service.giles.IGilesDeletionChecker;
import edu.asu.diging.citesphere.core.user.IUserManager;
import edu.asu.diging.citesphere.model.bib.ICitation;
import edu.asu.diging.citesphere.model.bib.IGilesUpload;
import edu.asu.diging.citesphere.user.IUser;

@Component
@PropertySource({ "classpath:config.properties",
"${appConfigFile:classpath:}/app.properties" })
public class GilesDeletionChecker implements IGilesDeletionChecker {

@Autowired
private IUserManager userManager;

@Autowired
private ICitationManager citationManager;

@Autowired
private IGilesConnector gilesConnector;

@Value("${giles_document_deletion_check_endpoint}")
private String gilesDeletionCheckEndpoint;

private Queue<Map<String, String>> deletionQueue;

@PostConstruct
public void init() {
deletionQueue = new ConcurrentLinkedQueue<Map<String, String>>();
}

@Override
public void addDocumentCitationMap(IGilesUpload upload, ICitation citation, String zoteroId, IUser user) {
HashMap<String, String> documentCitationMap = new HashMap<String, String>();
documentCitationMap.put("documentId", upload.getDocumentId());
documentCitationMap.put("citationKey", citation.getKey());
documentCitationMap.put("userName", user.getUsername());
documentCitationMap.put("zoteroId", zoteroId);
if (!deletionQueue.contains(documentCitationMap)) {
deletionQueue.add(documentCitationMap);
}
}

@Override
@Scheduled(fixedDelay = 60000)
public void checkDeletion() throws ZoteroConnectionException, CitationIsOutdatedException, ZoteroHttpStatusException, ZoteroItemCreationFailedException {
for (Map<String, String> documentCitationMap: deletionQueue) {
String documentId = documentCitationMap.get("documentId");
String citationKey = documentCitationMap.get("citationKey");
String zoteroId = documentCitationMap.get("zoteroId");
ICitation citation = citationManager.getCitation(citationKey);
IUser user = userManager.findByUsername(documentCitationMap.get("userName"));
ResponseEntity<String> response = gilesConnector.sendRequest(user, gilesDeletionCheckEndpoint.replace("{documentId}", documentId), String.class, HttpMethod.GET);
if(response.getStatusCode().equals(HttpStatus.OK)) {
for (Iterator<IGilesUpload> gileUpload = citation.getGilesUploads().iterator(); gileUpload.hasNext();) {
IGilesUpload g = gileUpload.next();
if (g.getDocumentId() != null && g.getDocumentId().equals(documentId)) {
gileUpload.remove();
}
}
citationManager.updateCitation(user, zoteroId, citation);
deletionQueue.remove(documentCitationMap);
}
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import java.time.OffsetDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
Expand All @@ -18,6 +19,7 @@
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.data.util.CloseableIterator;
import org.springframework.http.HttpStatus;
import org.springframework.social.zotero.api.ZoteroUpdateItemsStatuses;
import org.springframework.social.zotero.exception.ZoteroConnectionException;
import org.springframework.stereotype.Service;
Expand All @@ -37,12 +39,15 @@
import edu.asu.diging.citesphere.core.service.ICitationManager;
import edu.asu.diging.citesphere.core.service.ICitationStore;
import edu.asu.diging.citesphere.core.service.IGroupManager;
import edu.asu.diging.citesphere.core.service.giles.IGilesConnector;
import edu.asu.diging.citesphere.core.service.giles.IGilesDeletionChecker;
import edu.asu.diging.citesphere.core.zotero.IZoteroManager;
import edu.asu.diging.citesphere.data.bib.CitationGroupRepository;
import edu.asu.diging.citesphere.data.bib.ICitationDao;
import edu.asu.diging.citesphere.model.bib.ICitation;
import edu.asu.diging.citesphere.model.bib.ICitationCollection;
import edu.asu.diging.citesphere.model.bib.ICitationGroup;
import edu.asu.diging.citesphere.model.bib.IGilesUpload;
import edu.asu.diging.citesphere.model.bib.ItemType;
import edu.asu.diging.citesphere.model.bib.impl.BibField;
import edu.asu.diging.citesphere.model.bib.impl.CitationGroup;
Expand Down Expand Up @@ -83,6 +88,12 @@ public class CitationManager implements ICitationManager {

@Autowired
private IAsyncCitationProcessor asyncCitationProcessor;

@Autowired
private IGilesConnector gilesConnector;

@Autowired
private IGilesDeletionChecker gilesDeletionChecker;

private Map<String, BiFunction<ICitation, ICitation, Integer>> sortFunctions;

Expand Down Expand Up @@ -494,4 +505,20 @@ public CitationPage getPrevAndNextCitation(IUser user, String groupId, String co
public void deleteLocalGroupCitations(String groupId) {
citationStore.deleteCitationByGroupId(groupId);
}

@Override
public void deleteFile(IUser user, String zoteroGroupId, String itemId, String documentId)
throws GroupDoesNotExistException, CannotFindCitationException, ZoteroHttpStatusException,
ZoteroConnectionException, CitationIsOutdatedException, ZoteroItemCreationFailedException {
ICitation citation = getCitation(user, zoteroGroupId, itemId);
for (Iterator<IGilesUpload> gileUpload = citation.getGilesUploads().iterator(); gileUpload.hasNext();) {
IGilesUpload g = gileUpload.next();
if (g.getDocumentId() != null && g.getDocumentId().equals(documentId)) {
HttpStatus deletionStatus = gilesConnector.deleteDocument(user, documentId);
if (deletionStatus.equals(HttpStatus.OK)) {
gilesDeletionChecker.addDocumentCitationMap(g, citation, zoteroGroupId, user);
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,33 @@

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
import org.springframework.social.zotero.exception.ZoteroConnectionException;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

import edu.asu.diging.citesphere.core.exceptions.CannotFindCitationException;
import edu.asu.diging.citesphere.core.exceptions.CitationIsOutdatedException;
import edu.asu.diging.citesphere.core.exceptions.GroupDoesNotExistException;
import edu.asu.diging.citesphere.core.exceptions.ZoteroHttpStatusException;
import edu.asu.diging.citesphere.core.exceptions.ZoteroItemCreationFailedException;
import edu.asu.diging.citesphere.core.search.service.SearchEngine;
import edu.asu.diging.citesphere.core.service.ICitationManager;
import edu.asu.diging.citesphere.core.service.impl.CitationPage;
import edu.asu.diging.citesphere.core.service.impl.async.AsyncDeleteCitationsResponse;
import edu.asu.diging.citesphere.model.bib.ICitation;
import edu.asu.diging.citesphere.user.IUser;
import edu.asu.diging.citesphere.model.bib.IGilesUpload;

@Controller
public class ItemController {
Expand Down Expand Up @@ -54,6 +63,7 @@ public String getItem(Authentication authentication, Model model, @PathVariable(
List<ICitation> notes = citationManager.getNotes((IUser)authentication.getPrincipal(), zoteroGroupId, itemId);
model.addAttribute("notes", notes);
model.addAttribute("citation", citation);
model.addAttribute("itemId", itemId);
List<String> fields = new ArrayList<>();
citationManager.getItemTypeFields((IUser)authentication.getPrincipal(), citation.getItemType()).forEach(f -> fields.add(f.getFilename()));
model.addAttribute("fields", fields);
Expand All @@ -66,4 +76,15 @@ public String getItem(Authentication authentication, Model model, @PathVariable(
}
return "auth/group/item";
}

@RequestMapping(value = "/auth/group/{zoteroGroupId}/file/delete", method = RequestMethod.POST)
public ResponseEntity<String> deleteFile(Authentication authentication,
@PathVariable("zoteroGroupId") String zoteroGroupId,
@RequestParam(value = "documentId", required = false) String documentId,
@RequestParam(value = "itemId", required = false) String itemId)
throws GroupDoesNotExistException, CannotFindCitationException, ZoteroHttpStatusException,
ZoteroConnectionException, CitationIsOutdatedException, ZoteroItemCreationFailedException {
citationManager.deleteFile((IUser) authentication.getPrincipal(), zoteroGroupId, itemId, documentId);
return new ResponseEntity<>(HttpStatus.OK);
}
}
2 changes: 2 additions & 0 deletions citesphere/src/main/resources/config.properties
Original file line number Diff line number Diff line change
Expand Up @@ -88,5 +88,7 @@ elasticsearch.connect.timeout=${elasticsearch.connect.timeout}
giles_upload_endpoint=/api/v2/files/upload
giles_check_endpoint=/api/v2/files/upload/check/
giles_file_endpoint=/api/v2/resources/files/{0}/content
giles_document_endpoint=/api/v2/resources/documents/{documentId}
giles_document_deletion_check_endpoint=/api/v2/files/deletion/check/{documentId}

javers_default_author=${javers.default.author}
Loading