356 lines
12 KiB
Java
356 lines
12 KiB
Java
/**
|
|
*
|
|
*/
|
|
package de.bstly.board.controller;
|
|
|
|
import java.io.IOException;
|
|
import java.io.InputStream;
|
|
import java.net.URL;
|
|
import java.net.URLDecoder;
|
|
import java.time.Instant;
|
|
import java.time.temporal.ChronoUnit;
|
|
import java.util.List;
|
|
import java.util.Optional;
|
|
import java.util.Scanner;
|
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
import org.springframework.data.domain.Page;
|
|
import org.springframework.http.HttpStatus;
|
|
import org.springframework.security.access.prepost.PreAuthorize;
|
|
import org.springframework.web.bind.annotation.DeleteMapping;
|
|
import org.springframework.web.bind.annotation.GetMapping;
|
|
import org.springframework.web.bind.annotation.PatchMapping;
|
|
import org.springframework.web.bind.annotation.PathVariable;
|
|
import org.springframework.web.bind.annotation.PostMapping;
|
|
import org.springframework.web.bind.annotation.RequestBody;
|
|
import org.springframework.web.bind.annotation.RequestMapping;
|
|
import org.springframework.web.bind.annotation.RequestParam;
|
|
import org.springframework.web.bind.annotation.RestController;
|
|
|
|
import com.google.common.collect.Lists;
|
|
|
|
import de.bstly.board.businesslogic.EntryManager;
|
|
import de.bstly.board.businesslogic.SettingsManager;
|
|
import de.bstly.board.businesslogic.UserManager;
|
|
import de.bstly.board.businesslogic.ViewManager;
|
|
import de.bstly.board.businesslogic.VoteManager;
|
|
import de.bstly.board.controller.model.EntryFilter;
|
|
import de.bstly.board.controller.support.EntityResponseStatusException;
|
|
import de.bstly.board.controller.support.RequestBodyErrors;
|
|
import de.bstly.board.controller.validation.EntryValidator;
|
|
import de.bstly.board.model.Entry;
|
|
import de.bstly.board.model.View;
|
|
import de.bstly.board.model.Vote;
|
|
import de.bstly.board.model.support.EntryStatus;
|
|
import de.bstly.board.model.support.EntryType;
|
|
import de.bstly.board.model.support.FlaggedStatus;
|
|
import de.bstly.board.model.support.Types;
|
|
import de.bstly.board.model.support.VoteType;
|
|
|
|
/**
|
|
* The Class EntryController.
|
|
*/
|
|
@RestController
|
|
@RequestMapping("/entries")
|
|
public class EntryController extends BaseController {
|
|
|
|
@Autowired
|
|
private EntryManager entryManager;
|
|
@Autowired
|
|
private UserManager userManager;
|
|
@Autowired
|
|
private EntryValidator entryValidator;
|
|
@Autowired
|
|
private VoteManager voteManager;
|
|
@Autowired
|
|
private SettingsManager settingsManager;
|
|
@Autowired
|
|
private ViewManager viewManager;
|
|
|
|
/**
|
|
* Fetch by view.
|
|
*
|
|
* @param name the name
|
|
* @param usernameParameter the username parameter
|
|
* @param pageParameter the page parameter
|
|
* @param sizeParameter the size parameter
|
|
* @param dateParameter the date parameter
|
|
* @param tagsParameter the tags parameter
|
|
* @param excludedTagsParameter the excluded tags parameter
|
|
* @param typeParameter the type parameter
|
|
* @param gravityParameter the gravity parameter
|
|
* @param ascParameter the asc parameter
|
|
* @param ignoreParameter the ignore parameter
|
|
* @return the page
|
|
*/
|
|
@PreAuthorize("isAuthenticated()")
|
|
@GetMapping("/{name}")
|
|
public Page<Entry> fetchByView(@PathVariable("name") String name,
|
|
@RequestParam("user") Optional<String> usernameParameter,
|
|
@RequestParam("page") Optional<Integer> pageParameter,
|
|
@RequestParam("size") Optional<Integer> sizeParameter,
|
|
@RequestParam("date") Optional<Instant> dateParameter,
|
|
@RequestParam("tags") Optional<List<String>> tagsParameter,
|
|
@RequestParam("excludedTags") Optional<List<String>> excludedTagsParameter,
|
|
@RequestParam("type") Optional<EntryType> typeParameter,
|
|
@RequestParam("gravity") Optional<Float> gravityParameter,
|
|
@RequestParam("asc") Optional<Boolean> ascParameter,
|
|
@RequestParam("ignore") Optional<List<String>> ignoreParameter) {
|
|
|
|
View view = viewManager.get(usernameParameter.orElse(getCurrentUsername()), name);
|
|
|
|
if (view == null || usernameParameter.isPresent() && !view.isPublicView()) {
|
|
throw new EntityResponseStatusException(HttpStatus.UNPROCESSABLE_ENTITY);
|
|
}
|
|
|
|
if (sizeParameter.isPresent() && sizeParameter.get() > 100) {
|
|
sizeParameter = Optional.of(100);
|
|
}
|
|
|
|
EntryFilter filter = buildFilter(dateParameter.orElse(null), FlaggedStatus.NORMAL, tagsParameter.orElse(null),
|
|
excludedTagsParameter.orElse(null), typeParameter.orElse(null));
|
|
|
|
filter.setFixedTags(view.getTags());
|
|
filter.setFixedExcludedTags(view.getExcludedTags());
|
|
|
|
Page<Entry> entries = null;
|
|
|
|
switch (view.getSorting()) {
|
|
case TOP:
|
|
entries = entryManager.fetchByRanking(getCurrentUsername(), filter, getGravity(), pageParameter.orElse(0),
|
|
sizeParameter.orElse(settingsManager.getPageSize()), ascParameter.orElse(false));
|
|
break;
|
|
case NEW:
|
|
entries = entryManager.fetchByDate(getCurrentUsername(), filter, pageParameter.orElse(0),
|
|
sizeParameter.orElse(settingsManager.getPageSize()), ascParameter.orElse(false));
|
|
break;
|
|
case HOT:
|
|
entries = entryManager.fetchByComments(getCurrentUsername(), filter, getGravity(), pageParameter.orElse(0),
|
|
sizeParameter.orElse(settingsManager.getPageSize()), ascParameter.orElse(false));
|
|
break;
|
|
case LAST:
|
|
entries = entryManager.fetchByLastComment(getCurrentUsername(), filter, pageParameter.orElse(0),
|
|
sizeParameter.orElse(settingsManager.getPageSize()), ascParameter.orElse(false));
|
|
break;
|
|
}
|
|
|
|
if (entries == null) {
|
|
throw new EntityResponseStatusException(HttpStatus.BAD_REQUEST);
|
|
}
|
|
|
|
List<String> ignore = ignoreParameter.orElse(Lists.newArrayList());
|
|
entryManager.applyMetadata(getCurrentUsername(), userManager.getKarma(getCurrentUsername()),
|
|
entries.getContent(), ignore);
|
|
return entries;
|
|
}
|
|
|
|
/**
|
|
* Fetch by user.
|
|
*
|
|
* @param username the username
|
|
* @param pageParameter the page parameter
|
|
* @param sizeParameter the size parameter
|
|
* @param dateParameter the date parameter
|
|
* @param tagsParameter the tags parameter
|
|
* @param excludedTagsParameter the excluded tags parameter
|
|
* @param typeParameter the type parameter
|
|
* @param ascParameter the asc parameter
|
|
* @param ignoreParameter the ignore parameter
|
|
* @return the page
|
|
*/
|
|
@PreAuthorize("isAuthenticated()")
|
|
@GetMapping("/byuser/{username}")
|
|
public Page<Entry> fetchByUser(@PathVariable("username") String username,
|
|
@RequestParam("page") Optional<Integer> pageParameter,
|
|
@RequestParam("size") Optional<Integer> sizeParameter,
|
|
@RequestParam("date") Optional<Instant> dateParameter,
|
|
@RequestParam("tags") Optional<List<String>> tagsParameter,
|
|
@RequestParam("excludedTags") Optional<List<String>> excludedTagsParameter,
|
|
@RequestParam("type") Optional<EntryType> typeParameter,
|
|
@RequestParam("asc") Optional<Boolean> ascParameter,
|
|
@RequestParam("ignore") Optional<List<String>> ignoreParameter) {
|
|
|
|
if (sizeParameter.isPresent() && sizeParameter.get() > 100) {
|
|
sizeParameter = Optional.of(100);
|
|
}
|
|
|
|
if (dateParameter.isPresent() && dateParameter.get().isAfter(Instant.now())) {
|
|
dateParameter = Optional.of(Instant.now());
|
|
}
|
|
|
|
EntryFilter filter = buildFilter(dateParameter.orElse(null), FlaggedStatus.NORMAL, tagsParameter.orElse(null),
|
|
excludedTagsParameter.orElse(null), typeParameter.orElse(null));
|
|
|
|
Page<Entry> entries = entryManager.fetchByUser(getCurrentUsername(), username, filter, pageParameter.orElse(0),
|
|
sizeParameter.orElse(settingsManager.getPageSize()), ascParameter.orElse(false));
|
|
List<String> ignore = ignoreParameter.orElse(Lists.newArrayList());
|
|
entryManager.applyMetadata(getCurrentUsername(), userManager.getKarma(getCurrentUsername()),
|
|
entries.getContent(), ignore);
|
|
return entries;
|
|
}
|
|
|
|
/**
|
|
* Builds the filter.
|
|
*
|
|
* @param date the date
|
|
* @param flaggedStatus the flagged status
|
|
* @param tags the tags
|
|
* @param excludedTags the excluded tags
|
|
* @param type the type
|
|
* @return the entry filter
|
|
*/
|
|
protected EntryFilter buildFilter(Instant date, FlaggedStatus flaggedStatus, List<String> tags,
|
|
List<String> excludedTags, EntryType type) {
|
|
EntryFilter filter = new EntryFilter();
|
|
filter.setDate(date);
|
|
filter.setFlaggedStatus(flaggedStatus);
|
|
filter.setEntryType(type);
|
|
filter.setTags(tags);
|
|
filter.setExcludedTags(excludedTags);
|
|
return filter;
|
|
}
|
|
|
|
/**
|
|
* Gets the entry.
|
|
*
|
|
* @param id the id
|
|
* @param ignoreParameter the ignore parameter
|
|
* @return the entry
|
|
*/
|
|
@PreAuthorize("isAuthenticated()")
|
|
@GetMapping("/entry/{id}")
|
|
public Entry getEntry(@PathVariable("id") Long id, @RequestParam("ignore") Optional<List<String>> ignoreParameter) {
|
|
Entry entry = entryManager.get(id);
|
|
|
|
if (entry == null) {
|
|
throw new EntityResponseStatusException(HttpStatus.NOT_FOUND);
|
|
}
|
|
|
|
List<String> ignore = ignoreParameter.orElse(Lists.newArrayList());
|
|
entryManager.applyMetadata(getCurrentUsername(), userManager.getKarma(getCurrentUsername()), entry, ignore);
|
|
|
|
return entry;
|
|
}
|
|
|
|
/**
|
|
* Creates the entry.
|
|
*
|
|
* @param entry the entry
|
|
* @param ignoreParameter the ignore parameter
|
|
* @return the entry
|
|
*/
|
|
@PreAuthorize("isAuthenticated()")
|
|
@PostMapping()
|
|
public Entry createEntry(@RequestBody Entry entry, @RequestParam("ignore") Optional<List<String>> ignoreParameter) {
|
|
RequestBodyErrors bindingResult = new RequestBodyErrors(entry);
|
|
entryValidator.validate(entry, bindingResult);
|
|
|
|
if (bindingResult.hasErrors()) {
|
|
throw new EntityResponseStatusException(bindingResult.getAllErrors(), HttpStatus.UNPROCESSABLE_ENTITY);
|
|
}
|
|
|
|
entry.setCreated(Instant.now().plus(getEntryDelay(), ChronoUnit.MINUTES));
|
|
entry.setAuthor(getCurrentUsername());
|
|
entry.setEntryStatus(EntryStatus.NORMAL);
|
|
entry.setFlaggedStatus(FlaggedStatus.NORMAL);
|
|
entry.setTitle(entry.getTitle().trim());
|
|
entry.setText(entry.getText().trim());
|
|
entry = entryManager.save(entry);
|
|
|
|
Vote vote = new Vote();
|
|
vote.setTarget(entry.getId());
|
|
vote.setType(VoteType.up);
|
|
vote.setTargetType(Types.entry);
|
|
vote.setAuthor(getCurrentUsername());
|
|
voteManager.save(vote);
|
|
|
|
List<String> ignore = ignoreParameter.orElse(Lists.newArrayList());
|
|
entryManager.applyMetadata(getCurrentUsername(), userManager.getKarma(getCurrentUsername()), entry, ignore);
|
|
|
|
return entry;
|
|
}
|
|
|
|
/**
|
|
* Update entry.
|
|
*
|
|
* @param entry the entry
|
|
* @param ignoreParameter the ignore parameter
|
|
* @return the entry
|
|
*/
|
|
@PreAuthorize("isAuthenticated()")
|
|
@PatchMapping
|
|
public Entry updateEntry(@RequestBody Entry entry, @RequestParam("ignore") Optional<List<String>> ignoreParameter) {
|
|
Entry orgEntry = entryManager.get(entry.getId());
|
|
if (orgEntry == null || !orgEntry.getAuthor().equals(getCurrentUsername())
|
|
|| orgEntry.getCreated().plus(getEntryDelay(), ChronoUnit.MINUTES).isBefore(Instant.now())) {
|
|
throw new EntityResponseStatusException(HttpStatus.FORBIDDEN);
|
|
}
|
|
|
|
RequestBodyErrors bindingResult = new RequestBodyErrors(entry);
|
|
entryValidator.validate(entry, bindingResult);
|
|
|
|
if (bindingResult.hasErrors()) {
|
|
throw new EntityResponseStatusException(bindingResult.getAllErrors(), HttpStatus.UNPROCESSABLE_ENTITY);
|
|
}
|
|
|
|
orgEntry.setUrl(entry.getUrl());
|
|
orgEntry.setTitle(entry.getTitle().trim());
|
|
orgEntry.setText(entry.getText().trim());
|
|
orgEntry.setTags(entry.getTags());
|
|
orgEntry = entryManager.save(orgEntry);
|
|
|
|
List<String> ignore = ignoreParameter.orElse(Lists.newArrayList());
|
|
entryManager.applyMetadata(getCurrentUsername(), userManager.getKarma(getCurrentUsername()), orgEntry, ignore);
|
|
return orgEntry;
|
|
}
|
|
|
|
/**
|
|
* Detele entry.
|
|
*
|
|
* @param id the id
|
|
*/
|
|
@PreAuthorize("isAuthenticated()")
|
|
@DeleteMapping("{id}")
|
|
public void deteleEntry(@PathVariable("id") Long id) {
|
|
Entry orgEntry = entryManager.get(id);
|
|
if (orgEntry == null || !orgEntry.getAuthor().equals(getCurrentUsername())
|
|
|| orgEntry.getCreated().plus(getEntryDelay(), ChronoUnit.MINUTES).isBefore(Instant.now())) {
|
|
throw new EntityResponseStatusException(HttpStatus.FORBIDDEN);
|
|
}
|
|
|
|
entryManager.delete(orgEntry);
|
|
}
|
|
|
|
/**
|
|
* Gets the title.
|
|
*
|
|
* @param url the url
|
|
* @return the title
|
|
*/
|
|
@PreAuthorize("isAuthenticated()")
|
|
@GetMapping("/helper/title")
|
|
public String getTitle(@RequestParam("url") String url) {
|
|
InputStream response = null;
|
|
Scanner scanner = null;
|
|
try {
|
|
response = new URL(URLDecoder.decode(url, "utf-8")).openStream();
|
|
scanner = new Scanner(response);
|
|
String responseBody = scanner.useDelimiter("\\A").next();
|
|
return responseBody.substring(responseBody.indexOf("<title>") + 7, responseBody.indexOf("</title>"));
|
|
} catch (IOException ex) {
|
|
} finally {
|
|
try {
|
|
if (response != null) {
|
|
response.close();
|
|
}
|
|
if (scanner != null) {
|
|
scanner.close();
|
|
}
|
|
} catch (IOException ex) {
|
|
}
|
|
}
|
|
return "";
|
|
}
|
|
|
|
}
|