draft for borrow, update partey tags, added jwt
This commit is contained in:
@@ -12,6 +12,11 @@
|
|||||||
<artifactId>application</artifactId>
|
<artifactId>application</artifactId>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>de.bstly.we</groupId>
|
||||||
|
<artifactId>webstly-borrow</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>de.bstly.we</groupId>
|
<groupId>de.bstly.we</groupId>
|
||||||
<artifactId>webstly-core</artifactId>
|
<artifactId>webstly-core</artifactId>
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>de.bstly.we</groupId>
|
||||||
|
<artifactId>webstly-main</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<name>borrow</name>
|
||||||
|
<artifactId>webstly-borrow</artifactId>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>de.bstly.we</groupId>
|
||||||
|
<artifactId>webstly-email</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>de.bstly.we</groupId>
|
||||||
|
<artifactId>webstly-jwt</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,245 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package de.bstly.we.borrow.businesslogic;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.data.domain.Page;
|
||||||
|
import org.springframework.data.domain.PageRequest;
|
||||||
|
import org.springframework.data.domain.Sort;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import com.beust.jcommander.internal.Lists;
|
||||||
|
import com.querydsl.core.BooleanBuilder;
|
||||||
|
|
||||||
|
import de.bstly.we.borrow.model.BorrowItem;
|
||||||
|
import de.bstly.we.borrow.model.BorrowItemManualSlot;
|
||||||
|
import de.bstly.we.borrow.model.BorrowItemPeriodSlot;
|
||||||
|
import de.bstly.we.borrow.model.BorrowItemSlot;
|
||||||
|
import de.bstly.we.borrow.model.QBorrowItem;
|
||||||
|
import de.bstly.we.borrow.model.QBorrowItemManualSlot;
|
||||||
|
import de.bstly.we.borrow.model.QBorrowItemPeriodSlot;
|
||||||
|
import de.bstly.we.borrow.repository.BorrowItemManualSlotRepository;
|
||||||
|
import de.bstly.we.borrow.repository.BorrowItemPeriodSlotRepository;
|
||||||
|
import de.bstly.we.borrow.repository.BorrowItemRepository;
|
||||||
|
import de.bstly.we.businesslogic.UserManager;
|
||||||
|
import de.bstly.we.email.businesslogic.EmailManager;
|
||||||
|
import de.bstly.we.model.User;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Class BorrowItemManager.
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class BorrowItemManager {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private BorrowItemRepository borrowItemRepository;
|
||||||
|
@Autowired
|
||||||
|
private BorrowItemManualSlotRepository borrowItemManualSlotRepository;
|
||||||
|
@Autowired
|
||||||
|
private BorrowItemPeriodSlotRepository borrowItemPeriodSlotRepository;
|
||||||
|
@Autowired
|
||||||
|
private UserManager userManager;
|
||||||
|
@Autowired
|
||||||
|
private EmailManager emailManager;
|
||||||
|
|
||||||
|
private QBorrowItem qBorrowItem = QBorrowItem.borrowItem;
|
||||||
|
private QBorrowItemManualSlot qBorrowItemManualSlot = QBorrowItemManualSlot.borrowItemManualSlot;
|
||||||
|
private QBorrowItemPeriodSlot qBorrowItemPeriodSlot = QBorrowItemPeriodSlot.borrowItemPeriodSlot;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exists.
|
||||||
|
*
|
||||||
|
* @param id the id
|
||||||
|
* @return true, if successful
|
||||||
|
*/
|
||||||
|
public boolean exists(Long id) {
|
||||||
|
return borrowItemRepository.existsById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the.
|
||||||
|
*
|
||||||
|
* @param id the id
|
||||||
|
* @return the borrow item
|
||||||
|
*/
|
||||||
|
public BorrowItem get(Long id) {
|
||||||
|
return borrowItemRepository.findById(id).orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void applySlots(BorrowItem borrowItem) {
|
||||||
|
if (borrowItem != null) {
|
||||||
|
switch (borrowItem.getAvailability()) {
|
||||||
|
case MANUAL:
|
||||||
|
borrowItem.setSlots((List<? extends BorrowItemSlot>) borrowItemManualSlotRepository
|
||||||
|
.findAll(qBorrowItemManualSlot.item.eq(borrowItem.getId())));
|
||||||
|
break;
|
||||||
|
case PERIOD:
|
||||||
|
borrowItem.setSlots((List<? extends BorrowItemSlot>) borrowItemPeriodSlotRepository
|
||||||
|
.findAll(qBorrowItemPeriodSlot.item.eq(borrowItem.getId())));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (borrowItem.getSlots() == null) {
|
||||||
|
borrowItem.setSlots(Lists.newArrayList());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the.
|
||||||
|
*
|
||||||
|
* @param page the page
|
||||||
|
* @param size the size
|
||||||
|
* @param sortBy the sort by
|
||||||
|
* @param descending the descending
|
||||||
|
* @param search the search
|
||||||
|
* @return the page
|
||||||
|
*/
|
||||||
|
public Page<BorrowItem> get(int page, int size, String sortBy, boolean descending,
|
||||||
|
String search) {
|
||||||
|
|
||||||
|
if (StringUtils.hasText(search)) {
|
||||||
|
return borrowItemRepository.findAll(
|
||||||
|
qBorrowItem.name.contains(search).or(qBorrowItem.description.contains(search)),
|
||||||
|
PageRequest.of(page, size, descending ? Sort.by(sortBy).descending()
|
||||||
|
: Sort.by(sortBy).ascending()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return borrowItemRepository.findAll(PageRequest.of(page, size,
|
||||||
|
descending ? Sort.by(sortBy).descending() : Sort.by(sortBy).ascending()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the for user.
|
||||||
|
*
|
||||||
|
* @param userId the user id
|
||||||
|
* @param page the page
|
||||||
|
* @param size the size
|
||||||
|
* @param sortBy the sort by
|
||||||
|
* @param descending the descending
|
||||||
|
* @param search the search
|
||||||
|
* @return the for user
|
||||||
|
*/
|
||||||
|
public Page<BorrowItem> getForUser(Long userId, int page, int size, String sortBy,
|
||||||
|
boolean descending, String search) {
|
||||||
|
|
||||||
|
BooleanBuilder query = new BooleanBuilder();
|
||||||
|
|
||||||
|
query.and(qBorrowItem.owner.eq(userId));
|
||||||
|
|
||||||
|
if (StringUtils.hasText(search)) {
|
||||||
|
query.and(
|
||||||
|
qBorrowItem.name.contains(search).or(qBorrowItem.description.contains(search)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return borrowItemRepository.findAll(query.getValue(), PageRequest.of(page, size,
|
||||||
|
descending ? Sort.by(sortBy).descending() : Sort.by(sortBy).ascending()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save.
|
||||||
|
*
|
||||||
|
* @param borrowItem the borrow item
|
||||||
|
* @return the borrow item
|
||||||
|
*/
|
||||||
|
public BorrowItem save(BorrowItem borrowItem) {
|
||||||
|
|
||||||
|
if (borrowItem.getId() != null && !borrowItem.getId().equals(0L)) {
|
||||||
|
borrowItemManualSlotRepository.deleteAll(borrowItemManualSlotRepository
|
||||||
|
.findAll(qBorrowItemManualSlot.item.eq(borrowItem.getId())));
|
||||||
|
borrowItemPeriodSlotRepository.deleteAll(borrowItemPeriodSlotRepository
|
||||||
|
.findAll(qBorrowItemPeriodSlot.item.eq(borrowItem.getId())));
|
||||||
|
}
|
||||||
|
|
||||||
|
List<? extends BorrowItemSlot> slots = borrowItem.getSlots();
|
||||||
|
|
||||||
|
borrowItem = borrowItemRepository.save(borrowItem);
|
||||||
|
|
||||||
|
if (borrowItem != null) {
|
||||||
|
borrowItem.setSlots(slots);
|
||||||
|
|
||||||
|
if (borrowItem.getSlots() == null) {
|
||||||
|
borrowItem.setSlots(Lists.newArrayList());
|
||||||
|
}
|
||||||
|
|
||||||
|
List<BorrowItemSlot> invalidBorrowItemSlots = Lists.newArrayList();
|
||||||
|
for (BorrowItemSlot borrowItemSlot : borrowItem.getSlots()) {
|
||||||
|
borrowItemSlot.setItem(borrowItem.getId());
|
||||||
|
switch (borrowItem.getAvailability()) {
|
||||||
|
case MANUAL:
|
||||||
|
if (borrowItemSlot instanceof BorrowItemManualSlot) {
|
||||||
|
borrowItemManualSlotRepository.save((BorrowItemManualSlot) borrowItemSlot);
|
||||||
|
} else {
|
||||||
|
invalidBorrowItemSlots.add(borrowItemSlot);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case PERIOD:
|
||||||
|
if (borrowItemSlot instanceof BorrowItemPeriodSlot) {
|
||||||
|
borrowItemPeriodSlotRepository.save((BorrowItemPeriodSlot) borrowItemSlot);
|
||||||
|
} else {
|
||||||
|
invalidBorrowItemSlots.add(borrowItemSlot);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
borrowItem.getSlots().removeAll(invalidBorrowItemSlots);
|
||||||
|
}
|
||||||
|
|
||||||
|
return borrowItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete.
|
||||||
|
*
|
||||||
|
* @param borrowItem the borrow item
|
||||||
|
*/
|
||||||
|
public void delete(BorrowItem borrowItem) {
|
||||||
|
borrowItemManualSlotRepository.deleteAll(borrowItemManualSlotRepository
|
||||||
|
.findAll(qBorrowItemManualSlot.item.eq(borrowItem.getId())));
|
||||||
|
borrowItemPeriodSlotRepository.deleteAll(borrowItemPeriodSlotRepository
|
||||||
|
.findAll(qBorrowItemPeriodSlot.item.eq(borrowItem.getId())));
|
||||||
|
|
||||||
|
borrowItemRepository.delete(borrowItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete.
|
||||||
|
*
|
||||||
|
* @param id the id
|
||||||
|
*/
|
||||||
|
public void delete(Long id) {
|
||||||
|
borrowItemRepository.deleteById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notify owner.
|
||||||
|
*
|
||||||
|
* @param borrowItem the borrow item
|
||||||
|
*/
|
||||||
|
public void notifyOwner(BorrowItem borrowItem) {
|
||||||
|
Assert.isTrue(
|
||||||
|
borrowItem.getEmailNotification() != null
|
||||||
|
&& borrowItem.getEmailNotification().booleanValue(),
|
||||||
|
"Email notification not enabled for '"
|
||||||
|
+ borrowItem.getId()
|
||||||
|
+ "'!");
|
||||||
|
String email = borrowItem.getEmail();
|
||||||
|
|
||||||
|
if (!StringUtils.hasText(email)) {
|
||||||
|
User user = userManager.get(borrowItem.getOwner());
|
||||||
|
Assert.notNull(user, "invalid owner");
|
||||||
|
email = emailManager.getUserEmail(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: send email
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package de.bstly.we.borrow.businesslogic;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Interface BorrowPermissions.
|
||||||
|
*/
|
||||||
|
public interface BorrowPermissions {
|
||||||
|
|
||||||
|
public static final String BORROW_ITEMS = "borrow_items";
|
||||||
|
public static final String BORROW_REQUESTS = "borrow_requests";
|
||||||
|
}
|
||||||
@@ -0,0 +1,242 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package de.bstly.we.borrow.businesslogic;
|
||||||
|
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.data.domain.Page;
|
||||||
|
import org.springframework.data.domain.PageRequest;
|
||||||
|
import org.springframework.data.domain.Sort;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import com.nimbusds.jose.JOSEException;
|
||||||
|
import com.nimbusds.jose.JOSEObjectType;
|
||||||
|
import com.nimbusds.jose.JWSHeader;
|
||||||
|
import com.nimbusds.jose.KeySourceException;
|
||||||
|
import com.nimbusds.jwt.JWTClaimsSet.Builder;
|
||||||
|
import com.nimbusds.jwt.SignedJWT;
|
||||||
|
|
||||||
|
import de.bstly.we.borrow.model.BorrowItem;
|
||||||
|
import de.bstly.we.borrow.model.BorrowRequest;
|
||||||
|
import de.bstly.we.borrow.model.BorrowRequestStatus;
|
||||||
|
import de.bstly.we.borrow.model.QBorrowRequest;
|
||||||
|
import de.bstly.we.borrow.repository.BorrowRequestRepository;
|
||||||
|
import de.bstly.we.businesslogic.UserManager;
|
||||||
|
import de.bstly.we.jwt.businesslogic.JwtKeyManager;
|
||||||
|
import de.bstly.we.jwt.model.JwtKey;
|
||||||
|
import de.bstly.we.model.User;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Class BorrowRequestManager.
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class BorrowRequestManager {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private BorrowRequestRepository borrowRequestRepository;
|
||||||
|
@Autowired
|
||||||
|
private BorrowItemManager borrowItemManager;
|
||||||
|
@Autowired
|
||||||
|
private JwtKeyManager jwtKeyManager;
|
||||||
|
@Autowired
|
||||||
|
private UserManager userManager;
|
||||||
|
|
||||||
|
private QBorrowRequest qBorrowRequest = QBorrowRequest.borrowRequest;
|
||||||
|
|
||||||
|
public static final String JWT_BORROW_KEY_NAME = "borrow";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the.
|
||||||
|
*
|
||||||
|
* @param id the id
|
||||||
|
* @return the borrow request
|
||||||
|
*/
|
||||||
|
public BorrowRequest get(Long id) {
|
||||||
|
return borrowRequestRepository.findById(id).orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the for user.
|
||||||
|
*
|
||||||
|
* @param userId the user id
|
||||||
|
* @param page the page
|
||||||
|
* @param size the size
|
||||||
|
* @param sortBy the sort by
|
||||||
|
* @param descending the descending
|
||||||
|
* @return the for user
|
||||||
|
*/
|
||||||
|
public Page<BorrowRequest> getForUser(Long userId, int page, int size, String sortBy,
|
||||||
|
boolean descending) {
|
||||||
|
return borrowRequestRepository.findAll(qBorrowRequest.user.eq(userId), PageRequest.of(page,
|
||||||
|
size, descending ? Sort.by(sortBy).descending() : Sort.by(sortBy).ascending()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the for user and stauts.
|
||||||
|
*
|
||||||
|
* @param userId the user id
|
||||||
|
* @param status the status
|
||||||
|
* @param page the page
|
||||||
|
* @param size the size
|
||||||
|
* @param sortBy the sort by
|
||||||
|
* @param descending the descending
|
||||||
|
* @return the for user and stauts
|
||||||
|
*/
|
||||||
|
public Page<BorrowRequest> getForUserAndStauts(Long userId, BorrowRequestStatus status,
|
||||||
|
int page, int size, String sortBy, boolean descending) {
|
||||||
|
return borrowRequestRepository.findAll(
|
||||||
|
qBorrowRequest.user.eq(userId).and(qBorrowRequest.status.eq(status)),
|
||||||
|
PageRequest.of(page, size,
|
||||||
|
descending ? Sort.by(sortBy).descending() : Sort.by(sortBy).ascending()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the for owner.
|
||||||
|
*
|
||||||
|
* @param userId the user id
|
||||||
|
* @param page the page
|
||||||
|
* @param size the size
|
||||||
|
* @param sortBy the sort by
|
||||||
|
* @param descending the descending
|
||||||
|
* @return the for owner
|
||||||
|
*/
|
||||||
|
public Page<BorrowRequest> getForOwner(Long userId, int page, int size, String sortBy,
|
||||||
|
boolean descending) {
|
||||||
|
return borrowRequestRepository.findAllByOwner(userId, PageRequest.of(page, size,
|
||||||
|
descending ? Sort.by(sortBy).descending() : Sort.by(sortBy).ascending()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the for owner and status.
|
||||||
|
*
|
||||||
|
* @param userId the user id
|
||||||
|
* @param status the status
|
||||||
|
* @param page the page
|
||||||
|
* @param size the size
|
||||||
|
* @param sortBy the sort by
|
||||||
|
* @param descending the descending
|
||||||
|
* @return the for owner and status
|
||||||
|
*/
|
||||||
|
public Page<BorrowRequest> getForOwnerAndStatus(Long userId, BorrowRequestStatus status,
|
||||||
|
int page, int size, String sortBy, boolean descending) {
|
||||||
|
return borrowRequestRepository.findAllByOwnerAndStatus(userId, status, PageRequest.of(page,
|
||||||
|
size, descending ? Sort.by(sortBy).descending() : Sort.by(sortBy).ascending()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save.
|
||||||
|
*
|
||||||
|
* @param borrowRequest the borrow request
|
||||||
|
* @return the borrow request
|
||||||
|
*/
|
||||||
|
public BorrowRequest save(BorrowRequest borrowRequest) {
|
||||||
|
return borrowRequestRepository.save(borrowRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete.
|
||||||
|
*
|
||||||
|
* @param borrowRequest the borrow request
|
||||||
|
*/
|
||||||
|
public void delete(BorrowRequest borrowRequest) {
|
||||||
|
borrowRequestRepository.delete(borrowRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete.
|
||||||
|
*
|
||||||
|
* @param id the id
|
||||||
|
*/
|
||||||
|
public void delete(Long id) {
|
||||||
|
borrowRequestRepository.deleteById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the code.
|
||||||
|
*
|
||||||
|
* @param borrowRequest the borrow request
|
||||||
|
* @param issuer the issuer
|
||||||
|
* @return the signed JWT
|
||||||
|
* @throws JOSEException the JOSE exception
|
||||||
|
*/
|
||||||
|
public SignedJWT createCode(BorrowRequest borrowRequest, String issuer) throws JOSEException {
|
||||||
|
|
||||||
|
BorrowItem borrowItem = borrowItemManager.get(borrowRequest.getItem());
|
||||||
|
|
||||||
|
User owner = userManager.get(borrowItem.getOwner());
|
||||||
|
User user = userManager.get(borrowRequest.getUser());
|
||||||
|
|
||||||
|
borrowRequest.setBorrowItem(borrowItem);
|
||||||
|
|
||||||
|
Builder claimsSetBuilder = new Builder();
|
||||||
|
claimsSetBuilder.audience(JWT_BORROW_KEY_NAME);
|
||||||
|
// issuer
|
||||||
|
claimsSetBuilder.issuer(issuer);
|
||||||
|
claimsSetBuilder.issueTime(Date.from(Instant.now()));
|
||||||
|
|
||||||
|
// item
|
||||||
|
claimsSetBuilder.subject(String.valueOf(borrowItem.getId()));
|
||||||
|
claimsSetBuilder.claim("name", borrowItem.getName());
|
||||||
|
|
||||||
|
// dates
|
||||||
|
claimsSetBuilder.expirationTime(Date.from(borrowRequest.getEnds()));
|
||||||
|
claimsSetBuilder.notBeforeTime(Date.from(borrowRequest.getStarts()));
|
||||||
|
|
||||||
|
// owner
|
||||||
|
claimsSetBuilder.claim("owner", owner.getUsername());
|
||||||
|
|
||||||
|
// user
|
||||||
|
claimsSetBuilder.claim("user", user.getUsername());
|
||||||
|
|
||||||
|
// status
|
||||||
|
claimsSetBuilder.claim("status", borrowRequest.getStatus());
|
||||||
|
|
||||||
|
if (StringUtils.hasText(borrowItem.getUrl())) {
|
||||||
|
claimsSetBuilder.claim("url", borrowItem.getUrl());
|
||||||
|
}
|
||||||
|
|
||||||
|
JwtKey jwtKey = jwtKeyManager.getLatest(JWT_BORROW_KEY_NAME, true);
|
||||||
|
|
||||||
|
JWSHeader.Builder headerBuilder = new JWSHeader.Builder(
|
||||||
|
jwtKeyManager.getJwsAlgorithm(jwtKey));
|
||||||
|
headerBuilder.keyID(jwtKey.getKeyID());
|
||||||
|
headerBuilder.type(JOSEObjectType.JWT);
|
||||||
|
|
||||||
|
SignedJWT jwt = new SignedJWT(headerBuilder.build(), claimsSetBuilder.build());
|
||||||
|
jwt.sign(jwtKeyManager.createSigner(jwtKey));
|
||||||
|
return jwt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify.
|
||||||
|
*
|
||||||
|
* @param jwt the jwt
|
||||||
|
* @return true, if successful
|
||||||
|
* @throws JOSEException the JOSE exception
|
||||||
|
* @throws ParseException the parse exception
|
||||||
|
*/
|
||||||
|
public boolean verify(SignedJWT jwt) throws JOSEException, ParseException {
|
||||||
|
|
||||||
|
if (jwt.getHeader() == null || !StringUtils.hasText(jwt.getHeader().getKeyID())) {
|
||||||
|
throw new KeySourceException("No KeyID provided!");
|
||||||
|
}
|
||||||
|
|
||||||
|
JwtKey jwtKey = jwtKeyManager.getByKeyID(jwt.getHeader().getKeyID());
|
||||||
|
if (jwtKey == null) {
|
||||||
|
throw new KeySourceException("No key found for given KeyID! ("
|
||||||
|
+ jwt.getHeader().getKeyID()
|
||||||
|
+ ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (jwt.getJWTClaimsSet() == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return jwt.verify(jwtKeyManager.createVerfifier(jwtKey));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,204 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package de.bstly.we.borrow.controller;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
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.validation.Errors;
|
||||||
|
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
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 de.bstly.we.borrow.businesslogic.BorrowItemManager;
|
||||||
|
import de.bstly.we.borrow.businesslogic.BorrowPermissions;
|
||||||
|
import de.bstly.we.borrow.controller.validation.BorrowItemValidator;
|
||||||
|
import de.bstly.we.borrow.model.BorrowItem;
|
||||||
|
import de.bstly.we.borrow.model.BorrowItemAvailability;
|
||||||
|
import de.bstly.we.businesslogic.PermissionManager;
|
||||||
|
import de.bstly.we.controller.BaseController;
|
||||||
|
import de.bstly.we.controller.support.EntityResponseStatusException;
|
||||||
|
import de.bstly.we.controller.support.RequestBodyErrors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Class BorrowItemController.
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/borrow/items")
|
||||||
|
public class BorrowItemController extends BaseController {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private BorrowItemManager borrowItemManager;
|
||||||
|
@Autowired
|
||||||
|
private PermissionManager permissionManager;
|
||||||
|
@Autowired
|
||||||
|
private BorrowItemValidator borrowItemValidator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the borrow items.
|
||||||
|
*
|
||||||
|
* @param pageParameter the page parameter
|
||||||
|
* @param sizeParameter the size parameter
|
||||||
|
* @param sortParameter the sort parameter
|
||||||
|
* @param descParameter the desc parameter
|
||||||
|
* @param searchParameter the search parameter
|
||||||
|
* @return the borrow items
|
||||||
|
*/
|
||||||
|
@PreAuthorize("isAuthenticated()")
|
||||||
|
@GetMapping
|
||||||
|
public Page<BorrowItem> getBorrowItems(@RequestParam("page") Optional<Integer> pageParameter,
|
||||||
|
@RequestParam("size") Optional<Integer> sizeParameter,
|
||||||
|
@RequestParam("sort") Optional<String> sortParameter,
|
||||||
|
@RequestParam("desc") Optional<Boolean> descParameter,
|
||||||
|
@RequestParam("search") Optional<String> searchParameter) {
|
||||||
|
|
||||||
|
if (!permissionManager.hasPermission(getCurrentUserId(), BorrowPermissions.BORROW_REQUESTS)
|
||||||
|
|| !permissionManager.isFullUser(getCurrentUserId())) {
|
||||||
|
throw new EntityResponseStatusException(HttpStatus.FORBIDDEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
Page<BorrowItem> borrowItems = borrowItemManager.get(pageParameter.orElse(0),
|
||||||
|
sizeParameter.orElse(10), sortParameter.orElse("id"), descParameter.orElse(false),
|
||||||
|
searchParameter.orElse(null));
|
||||||
|
|
||||||
|
for (BorrowItem borrowItem : borrowItems.getContent()) {
|
||||||
|
if (!borrowItem.getOwner().equals(getCurrentUserId())) {
|
||||||
|
borrowItem.setEmail(null);
|
||||||
|
borrowItem.setEmailNotification(null);
|
||||||
|
}
|
||||||
|
borrowItemManager.applySlots(borrowItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
return borrowItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the owner borrow items.
|
||||||
|
*
|
||||||
|
* @param pageParameter the page parameter
|
||||||
|
* @param sizeParameter the size parameter
|
||||||
|
* @param sortParameter the sort parameter
|
||||||
|
* @param descParameter the desc parameter
|
||||||
|
* @param searchParameter the search parameter
|
||||||
|
* @return the owner borrow items
|
||||||
|
*/
|
||||||
|
@PreAuthorize("isAuthenticated()")
|
||||||
|
@GetMapping("/mine")
|
||||||
|
public Page<BorrowItem> getOwnerBorrowItems(
|
||||||
|
@RequestParam("page") Optional<Integer> pageParameter,
|
||||||
|
@RequestParam("size") Optional<Integer> sizeParameter,
|
||||||
|
@RequestParam("sort") Optional<String> sortParameter,
|
||||||
|
@RequestParam("desc") Optional<Boolean> descParameter,
|
||||||
|
@RequestParam("search") Optional<String> searchParameter) {
|
||||||
|
|
||||||
|
if (!permissionManager.hasPermission(getCurrentUserId(), BorrowPermissions.BORROW_ITEMS)
|
||||||
|
|| !permissionManager.isFullUser(getCurrentUserId())) {
|
||||||
|
throw new EntityResponseStatusException(HttpStatus.FORBIDDEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
Page<BorrowItem> borrowItems = borrowItemManager.getForUser(getCurrentUserId(),
|
||||||
|
pageParameter.orElse(0), sizeParameter.orElse(10), sortParameter.orElse("id"),
|
||||||
|
descParameter.orElse(false), searchParameter.orElse(null));
|
||||||
|
|
||||||
|
for (BorrowItem borrowItem : borrowItems.getContent()) {
|
||||||
|
if (!borrowItem.getOwner().equals(getCurrentUserId())) {
|
||||||
|
borrowItem.setEmail(null);
|
||||||
|
borrowItem.setEmailNotification(null);
|
||||||
|
}
|
||||||
|
borrowItemManager.applySlots(borrowItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
return borrowItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete borrow item.
|
||||||
|
*
|
||||||
|
* @param id the id
|
||||||
|
*/
|
||||||
|
@PreAuthorize("isAuthenticated()")
|
||||||
|
@GetMapping("/{id}")
|
||||||
|
public BorrowItem getBorrowItem(@PathVariable("id") Long id) {
|
||||||
|
if (!permissionManager.hasPermission(getCurrentUserId(), BorrowPermissions.BORROW_REQUESTS)
|
||||||
|
|| !permissionManager.isFullUser(getCurrentUserId())) {
|
||||||
|
throw new EntityResponseStatusException(HttpStatus.FORBIDDEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
BorrowItem borrowItem = borrowItemManager.get(id);
|
||||||
|
|
||||||
|
if (borrowItem == null) {
|
||||||
|
throw new EntityResponseStatusException(HttpStatus.NO_CONTENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!borrowItem.getOwner().equals(getCurrentUserId())) {
|
||||||
|
borrowItem.setEmail(null);
|
||||||
|
borrowItem.setEmailNotification(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
borrowItemManager.applySlots(borrowItem);
|
||||||
|
|
||||||
|
return borrowItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the or update borrow item.
|
||||||
|
*
|
||||||
|
* @param borrowItem the borrow item
|
||||||
|
* @return the borrow item
|
||||||
|
*/
|
||||||
|
@PreAuthorize("isAuthenticated()")
|
||||||
|
@PostMapping
|
||||||
|
public BorrowItem createOrUpdateBorrowItem(@RequestBody BorrowItem borrowItem) {
|
||||||
|
if (!permissionManager.hasPermission(getCurrentUserId(), BorrowPermissions.BORROW_ITEMS)
|
||||||
|
|| !permissionManager.isFullUser(getCurrentUserId())) {
|
||||||
|
throw new EntityResponseStatusException(HttpStatus.FORBIDDEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (borrowItem.getId() != null && !borrowItem.getId().equals(0L)) {
|
||||||
|
BorrowItem original = borrowItemManager.get(borrowItem.getId());
|
||||||
|
if (original == null || !original.getOwner().equals(getCurrentUserId())) {
|
||||||
|
throw new EntityResponseStatusException(HttpStatus.FORBIDDEN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (borrowItem.getAvailability() == null) {
|
||||||
|
borrowItem.setAvailability(BorrowItemAvailability.MANUAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
borrowItem.setOwner(getCurrentUserId());
|
||||||
|
|
||||||
|
Errors errors = new RequestBodyErrors(borrowItem);
|
||||||
|
borrowItemValidator.validate(borrowItem, errors);
|
||||||
|
|
||||||
|
if (errors.hasErrors()) {
|
||||||
|
throw new EntityResponseStatusException(errors.getAllErrors(), HttpStatus.CONFLICT);
|
||||||
|
}
|
||||||
|
|
||||||
|
return borrowItemManager.save(borrowItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete borrow item.
|
||||||
|
*
|
||||||
|
* @param id the id
|
||||||
|
*/
|
||||||
|
@PreAuthorize("isAuthenticated()")
|
||||||
|
@DeleteMapping("/{id}")
|
||||||
|
public void deleteBorrowItem(@PathVariable("id") Long id) {
|
||||||
|
BorrowItem borrowItem = borrowItemManager.get(id);
|
||||||
|
if (borrowItem == null || !borrowItem.getOwner().equals(getCurrentUserId())) {
|
||||||
|
throw new EntityResponseStatusException(HttpStatus.FORBIDDEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
borrowItemManager.delete(borrowItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,300 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package de.bstly.we.borrow.controller;
|
||||||
|
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.data.domain.Page;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
import org.springframework.validation.Errors;
|
||||||
|
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PutMapping;
|
||||||
|
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.nimbusds.jose.JOSEException;
|
||||||
|
import com.nimbusds.jwt.SignedJWT;
|
||||||
|
|
||||||
|
import de.bstly.we.borrow.businesslogic.BorrowItemManager;
|
||||||
|
import de.bstly.we.borrow.businesslogic.BorrowPermissions;
|
||||||
|
import de.bstly.we.borrow.businesslogic.BorrowRequestManager;
|
||||||
|
import de.bstly.we.borrow.controller.validation.BorrowJwtValidator;
|
||||||
|
import de.bstly.we.borrow.controller.validation.BorrowRequestValidator;
|
||||||
|
import de.bstly.we.borrow.model.BorrowItem;
|
||||||
|
import de.bstly.we.borrow.model.BorrowRequest;
|
||||||
|
import de.bstly.we.borrow.model.BorrowRequestStatus;
|
||||||
|
import de.bstly.we.businesslogic.PermissionManager;
|
||||||
|
import de.bstly.we.controller.BaseController;
|
||||||
|
import de.bstly.we.controller.support.EntityResponseStatusException;
|
||||||
|
import de.bstly.we.controller.support.RequestBodyErrors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Class BorrowRequestController.
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/borrow/requests")
|
||||||
|
public class BorrowRequestController extends BaseController {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private BorrowRequestManager borrowRequestManager;
|
||||||
|
@Autowired
|
||||||
|
private BorrowItemManager borrowItemManager;
|
||||||
|
@Autowired
|
||||||
|
private BorrowRequestValidator borrowRequestValidator;
|
||||||
|
@Autowired
|
||||||
|
private BorrowJwtValidator borrowJwtValidator;
|
||||||
|
@Autowired
|
||||||
|
private PermissionManager permissionManager;
|
||||||
|
|
||||||
|
@Value("${bstly.we.jwtBorrowIssuer:}")
|
||||||
|
private String jwtBorrowIssuer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the borrow requests.
|
||||||
|
*
|
||||||
|
* @param pageParameter the page parameter
|
||||||
|
* @param sizeParameter the size parameter
|
||||||
|
* @param sortParameter the sort parameter
|
||||||
|
* @param descParameter the desc parameter
|
||||||
|
* @return the borrow requests
|
||||||
|
*/
|
||||||
|
@PreAuthorize("isAuthenticated()")
|
||||||
|
@GetMapping
|
||||||
|
public Page<BorrowRequest> getBorrowRequests(
|
||||||
|
@RequestParam("page") Optional<Integer> pageParameter,
|
||||||
|
@RequestParam("size") Optional<Integer> sizeParameter,
|
||||||
|
@RequestParam("sort") Optional<String> sortParameter,
|
||||||
|
@RequestParam("desc") Optional<Boolean> descParameter) {
|
||||||
|
|
||||||
|
if (!permissionManager.hasPermission(getCurrentUserId(), BorrowPermissions.BORROW_REQUESTS)
|
||||||
|
|| !permissionManager.isFullUser(getCurrentUserId())) {
|
||||||
|
throw new EntityResponseStatusException(HttpStatus.FORBIDDEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
Page<BorrowRequest> borrowRequests = borrowRequestManager.getForUser(getCurrentUserId(),
|
||||||
|
pageParameter.orElse(0), sizeParameter.orElse(10), sortParameter.orElse("id"),
|
||||||
|
descParameter.orElse(false));
|
||||||
|
|
||||||
|
for (BorrowRequest borrowRequest : borrowRequests.getContent()) {
|
||||||
|
BorrowItem borrowItem = borrowItemManager.get(borrowRequest.getItem());
|
||||||
|
borrowItem.setEmail(null);
|
||||||
|
borrowItem.setEmailNotification(null);
|
||||||
|
borrowRequest.setBorrowItem(borrowItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
return borrowRequests;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the owner borrow requests.
|
||||||
|
*
|
||||||
|
* @param pageParameter the page parameter
|
||||||
|
* @param sizeParameter the size parameter
|
||||||
|
* @param sortParameter the sort parameter
|
||||||
|
* @param descParameter the desc parameter
|
||||||
|
* @return the owner borrow requests
|
||||||
|
*/
|
||||||
|
@PreAuthorize("isAuthenticated()")
|
||||||
|
@GetMapping("/mine")
|
||||||
|
public Page<BorrowRequest> getOwnerBorrowRequests(
|
||||||
|
@RequestParam("page") Optional<Integer> pageParameter,
|
||||||
|
@RequestParam("size") Optional<Integer> sizeParameter,
|
||||||
|
@RequestParam("sort") Optional<String> sortParameter,
|
||||||
|
@RequestParam("desc") Optional<Boolean> descParameter) {
|
||||||
|
|
||||||
|
if (!permissionManager.hasPermission(getCurrentUserId(), BorrowPermissions.BORROW_ITEMS)
|
||||||
|
|| !permissionManager.isFullUser(getCurrentUserId())) {
|
||||||
|
throw new EntityResponseStatusException(HttpStatus.FORBIDDEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
Page<BorrowRequest> borrowRequests = borrowRequestManager.getForOwner(getCurrentUserId(),
|
||||||
|
pageParameter.orElse(0), sizeParameter.orElse(10), sortParameter.orElse("id"),
|
||||||
|
descParameter.orElse(false));
|
||||||
|
|
||||||
|
for (BorrowRequest borrowRequest : borrowRequests.getContent()) {
|
||||||
|
BorrowItem borrowItem = borrowItemManager.get(borrowRequest.getItem());
|
||||||
|
borrowItem.setEmail(null);
|
||||||
|
borrowItem.setEmailNotification(null);
|
||||||
|
borrowRequest.setBorrowItem(borrowItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
return borrowRequests;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the or update borrow request.
|
||||||
|
*
|
||||||
|
* @param borrowRequest the borrow request
|
||||||
|
* @return the borrow request
|
||||||
|
*/
|
||||||
|
@PreAuthorize("isAuthenticated()")
|
||||||
|
@PostMapping
|
||||||
|
public BorrowRequest createOrUpdateBorrowRequest(@RequestBody BorrowRequest borrowRequest) {
|
||||||
|
if (!permissionManager.hasPermission(getCurrentUserId(), BorrowPermissions.BORROW_REQUESTS)
|
||||||
|
|| !permissionManager.isFullUser(getCurrentUserId())) {
|
||||||
|
throw new EntityResponseStatusException(HttpStatus.FORBIDDEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (borrowRequest.getId() != null && !borrowRequest.getId().equals(0L)) {
|
||||||
|
BorrowRequest original = borrowRequestManager.get(borrowRequest.getId());
|
||||||
|
if (original == null || !original.getUser().equals(getCurrentUserId())
|
||||||
|
|| !original.getStatus().equals(BorrowRequestStatus.PENDING)) {
|
||||||
|
throw new EntityResponseStatusException(HttpStatus.FORBIDDEN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
borrowRequest.setUser(getCurrentUserId());
|
||||||
|
borrowRequest.setStatus(BorrowRequestStatus.PENDING);
|
||||||
|
borrowRequest.setReply(null);
|
||||||
|
|
||||||
|
Errors errors = new RequestBodyErrors(borrowRequest);
|
||||||
|
borrowRequestValidator.validate(borrowRequest, errors);
|
||||||
|
|
||||||
|
if (errors.hasErrors()) {
|
||||||
|
throw new EntityResponseStatusException(errors.getAllErrors(), HttpStatus.CONFLICT);
|
||||||
|
}
|
||||||
|
|
||||||
|
BorrowItem borrowItem = borrowItemManager.get(borrowRequest.getItem());
|
||||||
|
|
||||||
|
if (borrowItem.isAutoAccept()) {
|
||||||
|
borrowRequest.setStatus(BorrowRequestStatus.ACCEPTED);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (borrowRequest.getId() == null || borrowRequest.getId().equals(0L)) {
|
||||||
|
if (borrowItem.getEmailNotification() != null
|
||||||
|
&& borrowItem.getEmailNotification().booleanValue()) {
|
||||||
|
borrowItemManager.notifyOwner(borrowItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return borrowRequestManager.save(borrowRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete borrow request.
|
||||||
|
*
|
||||||
|
* @param id the id
|
||||||
|
*/
|
||||||
|
@PreAuthorize("isAuthenticated()")
|
||||||
|
@DeleteMapping("/{id}")
|
||||||
|
public void deleteBorrowRequest(@PathVariable("id") Long id) {
|
||||||
|
BorrowRequest borrowRequest = borrowRequestManager.get(id);
|
||||||
|
if (borrowRequest == null || !borrowRequest.getUser().equals(getCurrentUserId())) {
|
||||||
|
throw new EntityResponseStatusException(HttpStatus.FORBIDDEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
borrowRequestManager.delete(borrowRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the status.
|
||||||
|
*
|
||||||
|
* @param borrowRequest the borrow request
|
||||||
|
* @return the borrow request
|
||||||
|
*/
|
||||||
|
@PreAuthorize("isAuthenticated()")
|
||||||
|
@PutMapping
|
||||||
|
public BorrowRequest setStatus(@RequestBody BorrowRequest borrowRequest) {
|
||||||
|
BorrowRequest original = borrowRequestManager.get(borrowRequest.getId());
|
||||||
|
if (original == null || original.getItem() == null || original.getItem().equals(0L)
|
||||||
|
|| !borrowItemManager.exists(original.getItem())) {
|
||||||
|
throw new EntityResponseStatusException(HttpStatus.FORBIDDEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
BorrowItem borrowItem = borrowItemManager.get(original.getItem());
|
||||||
|
|
||||||
|
if (!borrowItem.getOwner().equals(getCurrentUserId())) {
|
||||||
|
throw new EntityResponseStatusException(HttpStatus.FORBIDDEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (borrowRequest.getStatus().equals(BorrowRequestStatus.PENDING)) {
|
||||||
|
throw new EntityResponseStatusException(HttpStatus.CONFLICT);
|
||||||
|
}
|
||||||
|
|
||||||
|
original.setStatus(borrowRequest.getStatus());
|
||||||
|
original.setReply(borrowRequest.getReply());
|
||||||
|
|
||||||
|
return borrowRequestManager.save(original);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the code.
|
||||||
|
*
|
||||||
|
* @param id the id
|
||||||
|
* @param request the request
|
||||||
|
* @return the code
|
||||||
|
*/
|
||||||
|
@PreAuthorize("isAuthenticated()")
|
||||||
|
@GetMapping("/code/{id}")
|
||||||
|
public String getCode(@PathVariable("id") Long id, HttpServletRequest request) {
|
||||||
|
BorrowRequest borrowRequest = borrowRequestManager.get(id);
|
||||||
|
if (borrowRequest == null || !borrowRequest.getUser().equals(getCurrentUserId())) {
|
||||||
|
throw new EntityResponseStatusException(HttpStatus.FORBIDDEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!borrowRequest.getStatus().equals(BorrowRequestStatus.ACCEPTED)) {
|
||||||
|
throw new EntityResponseStatusException(HttpStatus.UNPROCESSABLE_ENTITY);
|
||||||
|
}
|
||||||
|
|
||||||
|
String issuer = jwtBorrowIssuer;
|
||||||
|
if (!StringUtils.hasText(issuer)) {
|
||||||
|
issuer = request.getScheme()
|
||||||
|
+ "://"
|
||||||
|
+ request.getServerName();
|
||||||
|
if (request.getServerPort() != 443 && request.getServerPort() != 80) {
|
||||||
|
issuer += ":"
|
||||||
|
+ request.getServerPort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return borrowRequestManager.createCode(borrowRequest, issuer).serialize();
|
||||||
|
} catch (JOSEException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
throw new EntityResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verfiy.
|
||||||
|
*
|
||||||
|
* @param serialized the serialized
|
||||||
|
* @param request the request
|
||||||
|
* @param response the response
|
||||||
|
* @return the object
|
||||||
|
*/
|
||||||
|
@PostMapping("verify")
|
||||||
|
public Object verfiy(@RequestBody String serialized, HttpServletRequest request,
|
||||||
|
HttpServletResponse response) {
|
||||||
|
try {
|
||||||
|
SignedJWT signedJwt = SignedJWT.parse(serialized);
|
||||||
|
Errors errors = new RequestBodyErrors(signedJwt);
|
||||||
|
borrowJwtValidator.validate(signedJwt, errors);
|
||||||
|
if (errors.hasErrors()) {
|
||||||
|
if (errors.getGlobalErrors().isEmpty()) {
|
||||||
|
throw new EntityResponseStatusException(errors.getAllErrors(),
|
||||||
|
HttpStatus.PRECONDITION_FAILED);
|
||||||
|
} else {
|
||||||
|
throw new EntityResponseStatusException(HttpStatus.NOT_ACCEPTABLE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return signedJwt.getJWTClaimsSet().getClaims();
|
||||||
|
} catch (ParseException e) {
|
||||||
|
throw new EntityResponseStatusException(HttpStatus.UNPROCESSABLE_ENTITY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+110
@@ -0,0 +1,110 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package de.bstly.we.borrow.controller.validation;
|
||||||
|
|
||||||
|
import org.apache.commons.validator.routines.EmailValidator;
|
||||||
|
import org.apache.commons.validator.routines.UrlValidator;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
import org.springframework.validation.Errors;
|
||||||
|
import org.springframework.validation.Validator;
|
||||||
|
|
||||||
|
import de.bstly.we.borrow.model.BorrowItem;
|
||||||
|
import de.bstly.we.borrow.model.BorrowItemManualSlot;
|
||||||
|
import de.bstly.we.borrow.model.BorrowItemPeriodSlot;
|
||||||
|
import de.bstly.we.borrow.model.BorrowItemSlot;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Class BorrowItemValidator.
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class BorrowItemValidator implements Validator {
|
||||||
|
|
||||||
|
private UrlValidator urlValidator = new UrlValidator(UrlValidator.ALLOW_ALL_SCHEMES);
|
||||||
|
private EmailValidator emailValidator = EmailValidator.getInstance();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.springframework.validation.Validator#supports(java.lang.Class)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean supports(Class<?> clazz) {
|
||||||
|
return clazz.isAssignableFrom(BorrowItem.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.springframework.validation.Validator#validate(java.lang.Object,
|
||||||
|
* org.springframework.validation.Errors)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void validate(Object target, Errors errors) {
|
||||||
|
BorrowItem borrowItem = (BorrowItem) target;
|
||||||
|
|
||||||
|
if (!StringUtils.hasText(borrowItem.getName())) {
|
||||||
|
errors.rejectValue("name", "REQUIRED");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (borrowItem.getAvailability() == null) {
|
||||||
|
errors.rejectValue("availability", "REQUIRED");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StringUtils.hasText(borrowItem.getUrl())
|
||||||
|
&& !urlValidator.isValid(borrowItem.getUrl())) {
|
||||||
|
errors.rejectValue("url", "INVALID_URL");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StringUtils.hasText(borrowItem.getEmail())
|
||||||
|
&& !emailValidator.isValid(borrowItem.getEmail())) {
|
||||||
|
errors.rejectValue("email", "INVALID_EMAIL");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (borrowItem.getMinDuration() != null && borrowItem.getMaxDuration() != null
|
||||||
|
&& borrowItem.getMinDuration().compareTo(borrowItem.getMaxDuration()) > 0) {
|
||||||
|
errors.rejectValue("minDuration", "INVALID");
|
||||||
|
errors.rejectValue("maxDuration", "INVALID");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (borrowItem.getAvailability() != null && borrowItem.getSlots() != null
|
||||||
|
&& !borrowItem.getSlots().isEmpty()) {
|
||||||
|
for (BorrowItemSlot borrowItemSlot : borrowItem.getSlots()) {
|
||||||
|
switch (borrowItem.getAvailability()) {
|
||||||
|
case MANUAL:
|
||||||
|
if (borrowItemSlot instanceof BorrowItemManualSlot) {
|
||||||
|
BorrowItemManualSlot borrowItemManualSlot = (BorrowItemManualSlot) borrowItemSlot;
|
||||||
|
if (borrowItemManualSlot.getStart() == null
|
||||||
|
|| borrowItemManualSlot.getEnd() == null) {
|
||||||
|
errors.rejectValue("slots", "MISSING_DATES");
|
||||||
|
} else if (borrowItemManualSlot.getStart()
|
||||||
|
.isAfter(borrowItemManualSlot.getEnd())) {
|
||||||
|
errors.rejectValue("slots", "INVALID_DATES");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case PERIOD:
|
||||||
|
if (borrowItemSlot instanceof BorrowItemPeriodSlot) {
|
||||||
|
BorrowItemPeriodSlot borrowItemPeriodSlot = (BorrowItemPeriodSlot) borrowItemSlot;
|
||||||
|
if (borrowItemPeriodSlot.getStartDay() == null
|
||||||
|
|| borrowItemPeriodSlot.getStartTime() == null
|
||||||
|
|| borrowItemPeriodSlot.getEndDay() == null
|
||||||
|
|| borrowItemPeriodSlot.getEndTime() == null) {
|
||||||
|
errors.rejectValue("slots", "MISSING_DATES");
|
||||||
|
} else if (borrowItemPeriodSlot.getStartDay()
|
||||||
|
.compareTo(borrowItemPeriodSlot.getEndDay()) > 0) {
|
||||||
|
errors.rejectValue("slots", "INVALID_DAY");
|
||||||
|
} else if (borrowItemPeriodSlot.getStartDay()
|
||||||
|
.compareTo(borrowItemPeriodSlot.getEndDay()) == 0
|
||||||
|
&& borrowItemPeriodSlot.getStartTime()
|
||||||
|
.isAfter(borrowItemPeriodSlot.getEndTime())) {
|
||||||
|
errors.rejectValue("slots", "INVALID_TIME");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+125
@@ -0,0 +1,125 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package de.bstly.we.borrow.controller.validation;
|
||||||
|
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.validation.Errors;
|
||||||
|
import org.springframework.validation.Validator;
|
||||||
|
|
||||||
|
import com.nimbusds.jose.JOSEException;
|
||||||
|
import com.nimbusds.jwt.JWTClaimsSet;
|
||||||
|
import com.nimbusds.jwt.SignedJWT;
|
||||||
|
|
||||||
|
import de.bstly.we.borrow.businesslogic.BorrowItemManager;
|
||||||
|
import de.bstly.we.borrow.businesslogic.BorrowRequestManager;
|
||||||
|
import de.bstly.we.borrow.model.BorrowItem;
|
||||||
|
import de.bstly.we.borrow.model.BorrowRequestStatus;
|
||||||
|
import de.bstly.we.businesslogic.UserManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Class BorrowJwtValidator.
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class BorrowJwtValidator implements Validator {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private BorrowRequestManager borrowRequestManager;
|
||||||
|
@Autowired
|
||||||
|
private BorrowItemManager borrowItemManager;
|
||||||
|
@Autowired
|
||||||
|
private UserManager userManager;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.springframework.validation.Validator#supports(java.lang.Class)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean supports(Class<?> clazz) {
|
||||||
|
return clazz.isAssignableFrom(SignedJWT.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.springframework.validation.Validator#validate(java.lang.Object,
|
||||||
|
* org.springframework.validation.Errors)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void validate(Object target, Errors errors) {
|
||||||
|
SignedJWT signedJwt = (SignedJWT) target;
|
||||||
|
JWTClaimsSet claims = null;
|
||||||
|
try {
|
||||||
|
if (!borrowRequestManager.verify(signedJwt)) {
|
||||||
|
errors.reject("INVALID");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
claims = signedJwt.getJWTClaimsSet();
|
||||||
|
|
||||||
|
if (claims == null) {
|
||||||
|
errors.reject("INVALID");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} catch (JOSEException | ParseException e) {
|
||||||
|
errors.reject("INVALID");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (claims.getNotBeforeTime() == null) {
|
||||||
|
errors.reject("INVALID");
|
||||||
|
return;
|
||||||
|
} else if (claims.getNotBeforeTime().after(new Date())) {
|
||||||
|
errors.rejectValue("nbf", "UPCOMING");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (claims.getExpirationTime() == null) {
|
||||||
|
errors.reject("INVALID");
|
||||||
|
return;
|
||||||
|
} else if (claims.getExpirationTime().before(new Date())) {
|
||||||
|
errors.rejectValue("exp", "EXPIRED");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (userManager.getByUsername(claims.getStringClaim("owner")) == null) {
|
||||||
|
errors.rejectValue("owner", "INVALID");
|
||||||
|
}
|
||||||
|
} catch (ParseException e) {
|
||||||
|
errors.reject("INVALID");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (userManager.getByUsername(claims.getStringClaim("user")) == null) {
|
||||||
|
errors.rejectValue("user", "INVALID");
|
||||||
|
}
|
||||||
|
} catch (ParseException e) {
|
||||||
|
errors.reject("INVALID");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
BorrowItem borrowItem = borrowItemManager.get(Long.valueOf(claims.getSubject()));
|
||||||
|
if (borrowItem == null) {
|
||||||
|
errors.rejectValue("sub", "INVALID");
|
||||||
|
} else if (!borrowItem.getName().equals(claims.getStringClaim("name"))) {
|
||||||
|
errors.rejectValue("name", "INVALID");
|
||||||
|
}
|
||||||
|
} catch (ParseException e) {
|
||||||
|
errors.reject("INVALID");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (!BorrowRequestStatus.valueOf(claims.getStringClaim("status"))
|
||||||
|
.equals(BorrowRequestStatus.ACCEPTED)) {
|
||||||
|
errors.rejectValue("status", "INVALID");
|
||||||
|
}
|
||||||
|
} catch (ParseException e) {
|
||||||
|
errors.reject("INVALID");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+172
@@ -0,0 +1,172 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package de.bstly.we.borrow.controller.validation;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.time.OffsetTime;
|
||||||
|
import java.time.ZoneOffset;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.validation.Errors;
|
||||||
|
import org.springframework.validation.Validator;
|
||||||
|
|
||||||
|
import de.bstly.we.borrow.businesslogic.BorrowItemManager;
|
||||||
|
import de.bstly.we.borrow.model.BorrowItem;
|
||||||
|
import de.bstly.we.borrow.model.BorrowItemManualSlot;
|
||||||
|
import de.bstly.we.borrow.model.BorrowItemPeriodSlot;
|
||||||
|
import de.bstly.we.borrow.model.BorrowItemSlot;
|
||||||
|
import de.bstly.we.borrow.model.BorrowRequest;
|
||||||
|
import de.bstly.we.borrow.model.BorrowRequestStatus;
|
||||||
|
import de.bstly.we.borrow.model.QBorrowRequest;
|
||||||
|
import de.bstly.we.borrow.repository.BorrowRequestRepository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Class BorrowRequestValidator.
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class BorrowRequestValidator implements Validator {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private BorrowItemManager borrowItemManager;
|
||||||
|
@Autowired
|
||||||
|
private BorrowRequestRepository borrowRequestRepository;
|
||||||
|
private QBorrowRequest qBorrowRequest = QBorrowRequest.borrowRequest;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.springframework.validation.Validator#supports(java.lang.Class)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean supports(Class<?> clazz) {
|
||||||
|
return clazz.isAssignableFrom(BorrowRequest.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.springframework.validation.Validator#validate(java.lang.Object,
|
||||||
|
* org.springframework.validation.Errors)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void validate(Object target, Errors errors) {
|
||||||
|
BorrowRequest borrowRequest = (BorrowRequest) target;
|
||||||
|
if (borrowRequest.getItem() == null || borrowRequest.getItem().equals(0L)) {
|
||||||
|
errors.rejectValue("item", "REQUIRED");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
BorrowItem borrowItem = borrowItemManager.get(borrowRequest.getItem());
|
||||||
|
|
||||||
|
if (borrowItem == null) {
|
||||||
|
errors.rejectValue("item", "INVALID");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (borrowRequest.getStarts() == null) {
|
||||||
|
errors.rejectValue("starts", "REQUIRED");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (borrowRequest.getEnds() == null) {
|
||||||
|
errors.rejectValue("ends", "REQUIRED");
|
||||||
|
}
|
||||||
|
|
||||||
|
// expiry + start
|
||||||
|
if (borrowRequest.getEnds() != null && borrowRequest.getStarts() != null) {
|
||||||
|
if (borrowRequest.getStarts().isAfter(borrowRequest.getEnds())
|
||||||
|
|| borrowRequestRepository.exists(qBorrowRequest.item
|
||||||
|
.eq(borrowRequest.getItem())
|
||||||
|
// exlude self
|
||||||
|
.and(qBorrowRequest.id.ne(
|
||||||
|
borrowRequest.getId() == null ? -1L : borrowRequest.getId()))
|
||||||
|
// accepted
|
||||||
|
.and(qBorrowRequest.status.eq(BorrowRequestStatus.ACCEPTED))
|
||||||
|
// expires after start
|
||||||
|
.and(qBorrowRequest.ends.after(borrowRequest.getStarts()))
|
||||||
|
// start before expires
|
||||||
|
.and(qBorrowRequest.starts.before(borrowRequest.getEnds())))) {
|
||||||
|
errors.rejectValue("starts", "ALREADY_USED");
|
||||||
|
errors.rejectValue("ends", "ALREADY_USED");
|
||||||
|
} else {
|
||||||
|
if (borrowItem.getMinDuration() != null && borrowItem.getMinDuration().compareTo(
|
||||||
|
Duration.between(borrowRequest.getEnds(), borrowRequest.getStarts())) > 0) {
|
||||||
|
errors.rejectValue("starts", "TOO_SHORT");
|
||||||
|
errors.rejectValue("ends", "TOO_SHORT");
|
||||||
|
} else if (borrowItem.getMaxDuration() != null
|
||||||
|
&& Duration.between(borrowRequest.getEnds(), borrowRequest.getStarts())
|
||||||
|
.compareTo(borrowItem.getMaxDuration()) > 0) {
|
||||||
|
errors.rejectValue("starts", "TOO_LONG");
|
||||||
|
errors.rejectValue("ends", "TOO_LONG");
|
||||||
|
} else {
|
||||||
|
boolean validSlot = false;
|
||||||
|
boolean validStart = false;
|
||||||
|
boolean validEnd = false;
|
||||||
|
borrowItemManager.applySlots(borrowItem);
|
||||||
|
|
||||||
|
switch (borrowItem.getAvailability()) {
|
||||||
|
case ALWAYS:
|
||||||
|
validSlot = true;
|
||||||
|
break;
|
||||||
|
case MANUAL:
|
||||||
|
for (BorrowItemSlot borrowItemSlot : borrowItem.getSlots()) {
|
||||||
|
if (borrowItemSlot instanceof BorrowItemManualSlot) {
|
||||||
|
BorrowItemManualSlot borrowItemManualSlot = (BorrowItemManualSlot) borrowItemSlot;
|
||||||
|
if (borrowRequest.getStarts()
|
||||||
|
.compareTo(borrowItemManualSlot.getStart()) >= 0) {
|
||||||
|
validStart = true;
|
||||||
|
}
|
||||||
|
if (borrowRequest.getEnds()
|
||||||
|
.compareTo(borrowItemManualSlot.getEnd()) <= 0) {
|
||||||
|
validEnd = true;
|
||||||
|
}
|
||||||
|
if (validStart && validEnd) {
|
||||||
|
validSlot = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case PERIOD:
|
||||||
|
for (BorrowItemSlot borrowItemSlot : borrowItem.getSlots()) {
|
||||||
|
if (borrowItemSlot instanceof BorrowItemPeriodSlot) {
|
||||||
|
BorrowItemPeriodSlot borrowItemPeriodSlot = (BorrowItemPeriodSlot) borrowItemSlot;
|
||||||
|
if (borrowRequest.getStarts().atZone(ZoneOffset.UTC).getDayOfWeek()
|
||||||
|
.compareTo(borrowItemPeriodSlot.getStartDay()) >= 0
|
||||||
|
&& OffsetTime
|
||||||
|
.ofInstant(borrowRequest.getStarts(),
|
||||||
|
ZoneOffset.UTC)
|
||||||
|
.compareTo(
|
||||||
|
borrowItemPeriodSlot.getStartTime()) >= 0) {
|
||||||
|
validStart = true;
|
||||||
|
}
|
||||||
|
if (borrowRequest.getEnds().atZone(ZoneOffset.UTC).getDayOfWeek()
|
||||||
|
.compareTo(borrowItemPeriodSlot.getEndDay()) <= 0
|
||||||
|
&& OffsetTime
|
||||||
|
.ofInstant(borrowRequest.getEnds(), ZoneOffset.UTC)
|
||||||
|
.compareTo(
|
||||||
|
borrowItemPeriodSlot.getEndTime()) <= 0) {
|
||||||
|
validEnd = true;
|
||||||
|
}
|
||||||
|
if (validStart && validEnd) {
|
||||||
|
validSlot = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!validSlot) {
|
||||||
|
if (!validStart) {
|
||||||
|
errors.rejectValue("starts", "INVALID");
|
||||||
|
}
|
||||||
|
if (!validEnd) {
|
||||||
|
errors.rejectValue("ends", "INVALID");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,267 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package de.bstly.we.borrow.model;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.EnumType;
|
||||||
|
import javax.persistence.Enumerated;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.GenerationType;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.Lob;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
import javax.persistence.Transient;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Class BorrowItem.
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
@Table(name = "borrow_items")
|
||||||
|
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||||
|
public class BorrowItem {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
@Column(name = "id")
|
||||||
|
private Long id;
|
||||||
|
@Column(name = "owner", nullable = false)
|
||||||
|
private Long owner;
|
||||||
|
@Column(name = "name", nullable = false)
|
||||||
|
private String name;
|
||||||
|
@Lob
|
||||||
|
@Column(name = "description", nullable = true)
|
||||||
|
private String description;
|
||||||
|
@Column(name = "url", nullable = true)
|
||||||
|
private String url;
|
||||||
|
@Column(name = "email_notification", columnDefinition = "boolean default false")
|
||||||
|
private Boolean emailNotification;
|
||||||
|
@Column(name = "email", nullable = true)
|
||||||
|
private String email;
|
||||||
|
@Column(name = "auto_acceppt", columnDefinition = "boolean default false")
|
||||||
|
private boolean autoAccept;
|
||||||
|
@Column(name = "min_duration", nullable = true)
|
||||||
|
private Duration minDuration;
|
||||||
|
@Column(name = "max_duration", nullable = true)
|
||||||
|
private Duration maxDuration;
|
||||||
|
@Enumerated(EnumType.STRING)
|
||||||
|
@Column(name = "availability", nullable = false)
|
||||||
|
private BorrowItemAvailability availability = BorrowItemAvailability.ALWAYS;
|
||||||
|
@Transient
|
||||||
|
private List<? extends BorrowItemSlot> slots;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the id.
|
||||||
|
*
|
||||||
|
* @return the id
|
||||||
|
*/
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the id.
|
||||||
|
*
|
||||||
|
* @param id the new id
|
||||||
|
*/
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the owner.
|
||||||
|
*
|
||||||
|
* @return the owner
|
||||||
|
*/
|
||||||
|
public Long getOwner() {
|
||||||
|
return owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the owner.
|
||||||
|
*
|
||||||
|
* @param owner the new owner
|
||||||
|
*/
|
||||||
|
public void setOwner(Long owner) {
|
||||||
|
this.owner = owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the name.
|
||||||
|
*
|
||||||
|
* @return the name
|
||||||
|
*/
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the name.
|
||||||
|
*
|
||||||
|
* @param name the new name
|
||||||
|
*/
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the description.
|
||||||
|
*
|
||||||
|
* @return the description
|
||||||
|
*/
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the description.
|
||||||
|
*
|
||||||
|
* @param description the new description
|
||||||
|
*/
|
||||||
|
public void setDescription(String description) {
|
||||||
|
this.description = description;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the url.
|
||||||
|
*
|
||||||
|
* @return the url
|
||||||
|
*/
|
||||||
|
public String getUrl() {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the url.
|
||||||
|
*
|
||||||
|
* @param url the new url
|
||||||
|
*/
|
||||||
|
public void setUrl(String url) {
|
||||||
|
this.url = url;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the email notification.
|
||||||
|
*
|
||||||
|
* @return the email notification
|
||||||
|
*/
|
||||||
|
public Boolean getEmailNotification() {
|
||||||
|
return emailNotification;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the email notification.
|
||||||
|
*
|
||||||
|
* @param emailNotification the new email notification
|
||||||
|
*/
|
||||||
|
public void setEmailNotification(Boolean emailNotification) {
|
||||||
|
this.emailNotification = emailNotification;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the email.
|
||||||
|
*
|
||||||
|
* @return the email
|
||||||
|
*/
|
||||||
|
public String getEmail() {
|
||||||
|
return email;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the email.
|
||||||
|
*
|
||||||
|
* @param email the new email
|
||||||
|
*/
|
||||||
|
public void setEmail(String email) {
|
||||||
|
this.email = email;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if is auto accept.
|
||||||
|
*
|
||||||
|
* @return true, if is auto accept
|
||||||
|
*/
|
||||||
|
public boolean isAutoAccept() {
|
||||||
|
return autoAccept;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the auto accept.
|
||||||
|
*
|
||||||
|
* @param autoAccept the new auto accept
|
||||||
|
*/
|
||||||
|
public void setAutoAccept(boolean autoAccept) {
|
||||||
|
this.autoAccept = autoAccept;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the min duration.
|
||||||
|
*
|
||||||
|
* @return the min duration
|
||||||
|
*/
|
||||||
|
public Duration getMinDuration() {
|
||||||
|
return minDuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the min duration.
|
||||||
|
*
|
||||||
|
* @param minDuration the new min duration
|
||||||
|
*/
|
||||||
|
public void setMinDuration(Duration minDuration) {
|
||||||
|
this.minDuration = minDuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the max duration.
|
||||||
|
*
|
||||||
|
* @return the max duration
|
||||||
|
*/
|
||||||
|
public Duration getMaxDuration() {
|
||||||
|
return maxDuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the max duration.
|
||||||
|
*
|
||||||
|
* @param maxDuration the new max duration
|
||||||
|
*/
|
||||||
|
public void setMaxDuration(Duration maxDuration) {
|
||||||
|
this.maxDuration = maxDuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the availability
|
||||||
|
*/
|
||||||
|
public BorrowItemAvailability getAvailability() {
|
||||||
|
return availability;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param availability the availability to set
|
||||||
|
*/
|
||||||
|
public void setAvailability(BorrowItemAvailability availability) {
|
||||||
|
this.availability = availability;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the slots
|
||||||
|
*/
|
||||||
|
public List<? extends BorrowItemSlot> getSlots() {
|
||||||
|
return slots;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param slots the slots to set
|
||||||
|
*/
|
||||||
|
public void setSlots(List<? extends BorrowItemSlot> slots) {
|
||||||
|
this.slots = slots;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package de.bstly.we.borrow.model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Enum BorrowItemAvailability.
|
||||||
|
*/
|
||||||
|
public enum BorrowItemAvailability {
|
||||||
|
|
||||||
|
ALWAYS, PERIOD, MANUAL
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package de.bstly.we.borrow.model;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Class BorrowItemManualSlot.
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
@Table(name = "borrow_item_manual_slots")
|
||||||
|
public class BorrowItemManualSlot extends BorrowItemSlot {
|
||||||
|
|
||||||
|
@Column(name = "start")
|
||||||
|
private Instant start;
|
||||||
|
@Column(name = "end")
|
||||||
|
private Instant end;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the start
|
||||||
|
*/
|
||||||
|
public Instant getStart() {
|
||||||
|
return start;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param start the start to set
|
||||||
|
*/
|
||||||
|
public void setStart(Instant start) {
|
||||||
|
this.start = start;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the end
|
||||||
|
*/
|
||||||
|
public Instant getEnd() {
|
||||||
|
return end;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param end the end to set
|
||||||
|
*/
|
||||||
|
public void setEnd(Instant end) {
|
||||||
|
this.end = end;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package de.bstly.we.borrow.model;
|
||||||
|
|
||||||
|
import java.time.DayOfWeek;
|
||||||
|
import java.time.OffsetTime;
|
||||||
|
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Class BorrowItemPeriodSlot.
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
@Table(name = "borrow_item_period_slots")
|
||||||
|
public class BorrowItemPeriodSlot extends BorrowItemSlot {
|
||||||
|
|
||||||
|
@Column(name = "start_day")
|
||||||
|
private DayOfWeek startDay;
|
||||||
|
@Column(name = "end_day")
|
||||||
|
private DayOfWeek endDay;
|
||||||
|
@Column(name = "start_time")
|
||||||
|
private OffsetTime startTime;
|
||||||
|
@Column(name = "end_time")
|
||||||
|
private OffsetTime endTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the startDay
|
||||||
|
*/
|
||||||
|
public DayOfWeek getStartDay() {
|
||||||
|
return startDay;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param startDay the startDay to set
|
||||||
|
*/
|
||||||
|
public void setStartDay(DayOfWeek startDay) {
|
||||||
|
this.startDay = startDay;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the endDay
|
||||||
|
*/
|
||||||
|
public DayOfWeek getEndDay() {
|
||||||
|
return endDay;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param endDay the endDay to set
|
||||||
|
*/
|
||||||
|
public void setEndDay(DayOfWeek endDay) {
|
||||||
|
this.endDay = endDay;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the startTime
|
||||||
|
*/
|
||||||
|
public OffsetTime getStartTime() {
|
||||||
|
return startTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param startTime the startTime to set
|
||||||
|
*/
|
||||||
|
public void setStartTime(OffsetTime startTime) {
|
||||||
|
this.startTime = startTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the endTime
|
||||||
|
*/
|
||||||
|
public OffsetTime getEndTime() {
|
||||||
|
return endTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param endTime the endTime to set
|
||||||
|
*/
|
||||||
|
public void setEndTime(OffsetTime endTime) {
|
||||||
|
this.endTime = endTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package de.bstly.we.borrow.model;
|
||||||
|
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.DiscriminatorColumn;
|
||||||
|
import javax.persistence.DiscriminatorType;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.GenerationType;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.Inheritance;
|
||||||
|
import javax.persistence.InheritanceType;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonSubTypes;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonTypeInfo.As;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Class BorrowItemSlot.
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
|
||||||
|
@DiscriminatorColumn(name = "type", discriminatorType = DiscriminatorType.STRING)
|
||||||
|
@JsonTypeInfo(use = com.fasterxml.jackson.annotation.JsonTypeInfo.Id.NAME, include = As.PROPERTY, property = "type")
|
||||||
|
@JsonSubTypes({ @JsonSubTypes.Type(value = BorrowItemManualSlot.class, name = "MANUAL"),
|
||||||
|
@JsonSubTypes.Type(value = BorrowItemPeriodSlot.class, name = "PERIOD") })
|
||||||
|
public abstract class BorrowItemSlot {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.SEQUENCE)
|
||||||
|
@Column(name = "id")
|
||||||
|
private Long id;
|
||||||
|
@Column(name = "item")
|
||||||
|
private Long item;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the id
|
||||||
|
*/
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param id the id to set
|
||||||
|
*/
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the item
|
||||||
|
*/
|
||||||
|
public Long getItem() {
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param item the item to set
|
||||||
|
*/
|
||||||
|
public void setItem(Long item) {
|
||||||
|
this.item = item;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,212 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package de.bstly.we.borrow.model;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.EnumType;
|
||||||
|
import javax.persistence.Enumerated;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.GenerationType;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.Lob;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
import javax.persistence.Transient;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Class BorrowRequest.
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
@Table(name = "borrow_requests")
|
||||||
|
public class BorrowRequest {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
@Column(name = "id")
|
||||||
|
private Long id;
|
||||||
|
@Column(name = "item", nullable = false)
|
||||||
|
private Long item;
|
||||||
|
@Column(name = "user", nullable = false)
|
||||||
|
private Long user;
|
||||||
|
@Enumerated(EnumType.STRING)
|
||||||
|
@Column(name = "status", nullable = false)
|
||||||
|
private BorrowRequestStatus status;
|
||||||
|
@Column(name = "starts", nullable = false)
|
||||||
|
private Instant starts;
|
||||||
|
@Column(name = "ends", nullable = false)
|
||||||
|
private Instant ends;
|
||||||
|
@Lob
|
||||||
|
@Column(name = "reply", nullable = true)
|
||||||
|
private String reply;
|
||||||
|
@Lob
|
||||||
|
@Column(name = "comment", nullable = true)
|
||||||
|
private String comment;
|
||||||
|
@Transient
|
||||||
|
private BorrowItem borrowItem;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the id.
|
||||||
|
*
|
||||||
|
* @return the id
|
||||||
|
*/
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the id.
|
||||||
|
*
|
||||||
|
* @param id the new id
|
||||||
|
*/
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the item.
|
||||||
|
*
|
||||||
|
* @return the item
|
||||||
|
*/
|
||||||
|
public Long getItem() {
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the item.
|
||||||
|
*
|
||||||
|
* @param item the new item
|
||||||
|
*/
|
||||||
|
public void setItem(Long item) {
|
||||||
|
this.item = item;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the user.
|
||||||
|
*
|
||||||
|
* @return the user
|
||||||
|
*/
|
||||||
|
public Long getUser() {
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the user.
|
||||||
|
*
|
||||||
|
* @param user the new user
|
||||||
|
*/
|
||||||
|
public void setUser(Long user) {
|
||||||
|
this.user = user;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the status.
|
||||||
|
*
|
||||||
|
* @return the status
|
||||||
|
*/
|
||||||
|
public BorrowRequestStatus getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the status.
|
||||||
|
*
|
||||||
|
* @param status the new status
|
||||||
|
*/
|
||||||
|
public void setStatus(BorrowRequestStatus status) {
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the starts.
|
||||||
|
*
|
||||||
|
* @return the starts
|
||||||
|
*/
|
||||||
|
public Instant getStarts() {
|
||||||
|
return starts;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the starts.
|
||||||
|
*
|
||||||
|
* @param starts the new starts
|
||||||
|
*/
|
||||||
|
public void setStarts(Instant starts) {
|
||||||
|
this.starts = starts;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the ends.
|
||||||
|
*
|
||||||
|
* @return the ends
|
||||||
|
*/
|
||||||
|
public Instant getEnds() {
|
||||||
|
return ends;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the ends.
|
||||||
|
*
|
||||||
|
* @param ends the new ends
|
||||||
|
*/
|
||||||
|
public void setEnds(Instant ends) {
|
||||||
|
this.ends = ends;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the reply.
|
||||||
|
*
|
||||||
|
* @return the reply
|
||||||
|
*/
|
||||||
|
public String getReply() {
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the reply.
|
||||||
|
*
|
||||||
|
* @param reply the new reply
|
||||||
|
*/
|
||||||
|
public void setReply(String reply) {
|
||||||
|
this.reply = reply;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the comment.
|
||||||
|
*
|
||||||
|
* @return the comment
|
||||||
|
*/
|
||||||
|
public String getComment() {
|
||||||
|
return comment;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the comment.
|
||||||
|
*
|
||||||
|
* @param comment the new comment
|
||||||
|
*/
|
||||||
|
public void setComment(String comment) {
|
||||||
|
this.comment = comment;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the borrow item.
|
||||||
|
*
|
||||||
|
* @return the borrow item
|
||||||
|
*/
|
||||||
|
public BorrowItem getBorrowItem() {
|
||||||
|
return borrowItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the borrow item.
|
||||||
|
*
|
||||||
|
* @param borrowItem the new borrow item
|
||||||
|
*/
|
||||||
|
public void setBorrowItem(BorrowItem borrowItem) {
|
||||||
|
this.borrowItem = borrowItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package de.bstly.we.borrow.model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Enum BorrowRequestStatus.
|
||||||
|
*/
|
||||||
|
public enum BorrowRequestStatus {
|
||||||
|
|
||||||
|
PENDING, ACCEPTED, DENIED
|
||||||
|
}
|
||||||
+18
@@ -0,0 +1,18 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package de.bstly.we.borrow.repository;
|
||||||
|
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.data.querydsl.QuerydslPredicateExecutor;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
import de.bstly.we.borrow.model.BorrowItemManualSlot;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Interface BorrowItemRepository.
|
||||||
|
*/
|
||||||
|
@Repository
|
||||||
|
public interface BorrowItemManualSlotRepository extends JpaRepository<BorrowItemManualSlot, Long>,
|
||||||
|
QuerydslPredicateExecutor<BorrowItemManualSlot> {
|
||||||
|
}
|
||||||
+18
@@ -0,0 +1,18 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package de.bstly.we.borrow.repository;
|
||||||
|
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.data.querydsl.QuerydslPredicateExecutor;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
import de.bstly.we.borrow.model.BorrowItemPeriodSlot;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Interface BorrowItemRepository.
|
||||||
|
*/
|
||||||
|
@Repository
|
||||||
|
public interface BorrowItemPeriodSlotRepository extends JpaRepository<BorrowItemPeriodSlot, Long>,
|
||||||
|
QuerydslPredicateExecutor<BorrowItemPeriodSlot> {
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package de.bstly.we.borrow.repository;
|
||||||
|
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.data.querydsl.QuerydslPredicateExecutor;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
import de.bstly.we.borrow.model.BorrowItem;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Interface BorrowItemRepository.
|
||||||
|
*/
|
||||||
|
@Repository
|
||||||
|
public interface BorrowItemRepository
|
||||||
|
extends JpaRepository<BorrowItem, Long>, QuerydslPredicateExecutor<BorrowItem> {
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package de.bstly.we.borrow.repository;
|
||||||
|
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.data.querydsl.QuerydslPredicateExecutor;
|
||||||
|
import org.springframework.data.repository.NoRepositoryBean;
|
||||||
|
|
||||||
|
import de.bstly.we.borrow.model.BorrowItemSlot;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Interface BorrowItemRepository.
|
||||||
|
*/
|
||||||
|
@NoRepositoryBean
|
||||||
|
public interface BorrowItemSlotRepository
|
||||||
|
extends JpaRepository<BorrowItemSlot, Long>, QuerydslPredicateExecutor<BorrowItemSlot> {
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package de.bstly.we.borrow.repository;
|
||||||
|
|
||||||
|
import org.springframework.data.domain.Page;
|
||||||
|
import org.springframework.data.domain.Pageable;
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.data.jpa.repository.Query;
|
||||||
|
import org.springframework.data.querydsl.QuerydslPredicateExecutor;
|
||||||
|
import org.springframework.data.repository.query.Param;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
import de.bstly.we.borrow.model.BorrowRequest;
|
||||||
|
import de.bstly.we.borrow.model.BorrowRequestStatus;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Interface BorrowRequestRepository.
|
||||||
|
*/
|
||||||
|
@Repository
|
||||||
|
public interface BorrowRequestRepository
|
||||||
|
extends JpaRepository<BorrowRequest, Long>, QuerydslPredicateExecutor<BorrowRequest> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find all by owner.
|
||||||
|
*
|
||||||
|
* @param owner the owner
|
||||||
|
* @param pageable the pageable
|
||||||
|
* @return the page
|
||||||
|
*/
|
||||||
|
@Query("SELECT request FROM BorrowRequest request INNER JOIN BorrowItem item ON request.item = item.id WHERE item.owner = :owner")
|
||||||
|
Page<BorrowRequest> findAllByOwner(@Param("owner") Long owner, Pageable pageable);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find all by owner and status.
|
||||||
|
*
|
||||||
|
* @param owner the owner
|
||||||
|
* @param status the status
|
||||||
|
* @param pageable the pageable
|
||||||
|
* @return the page
|
||||||
|
*/
|
||||||
|
@Query("SELECT request FROM BorrowRequest request INNER JOIN BorrowItem as item ON request.item = item.id WHERE item.owner = :owner AND request.status = :status")
|
||||||
|
Page<BorrowRequest> findAllByOwnerAndStatus(@Param("owner") Long owner,
|
||||||
|
@Param("status") BorrowRequestStatus status, Pageable pageable);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -8,6 +8,13 @@ import org.springframework.mail.MailMessage;
|
|||||||
import org.springframework.mail.SimpleMailMessage;
|
import org.springframework.mail.SimpleMailMessage;
|
||||||
import org.springframework.mail.javamail.JavaMailSender;
|
import org.springframework.mail.javamail.JavaMailSender;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import de.bstly.we.businesslogic.UserManager;
|
||||||
|
import de.bstly.we.businesslogic.UserProfileFieldManager;
|
||||||
|
import de.bstly.we.businesslogic.UserProfileFields;
|
||||||
|
import de.bstly.we.model.User;
|
||||||
|
import de.bstly.we.model.UserProfileField;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Class EmailManager.
|
* The Class EmailManager.
|
||||||
@@ -17,6 +24,10 @@ public class EmailManager {
|
|||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private JavaMailSender javaMailSender;
|
private JavaMailSender javaMailSender;
|
||||||
|
@Autowired
|
||||||
|
private UserManager userManager;
|
||||||
|
@Autowired
|
||||||
|
private UserProfileFieldManager userProfileFieldManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send text.
|
* Send text.
|
||||||
@@ -57,4 +68,28 @@ public class EmailManager {
|
|||||||
|
|
||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the user email.
|
||||||
|
*
|
||||||
|
* @param user the user
|
||||||
|
* @return the user email
|
||||||
|
*/
|
||||||
|
public String getUserEmail(User user) {
|
||||||
|
String email = userManager.getBstlyEmail(user.getUsername());
|
||||||
|
|
||||||
|
UserProfileField primaryEmailUserProfileField = userProfileFieldManager.get(user.getId(),
|
||||||
|
UserProfileFields.PROFILE_FIELD_EMAIL_PRIMARY);
|
||||||
|
if (primaryEmailUserProfileField != null
|
||||||
|
&& "true".equals(primaryEmailUserProfileField.getValue())) {
|
||||||
|
UserProfileField emailUserProfileField = userProfileFieldManager.get(user.getId(),
|
||||||
|
UserProfileFields.PROFILE_FIELD_EMAIL);
|
||||||
|
if (emailUserProfileField != null
|
||||||
|
&& StringUtils.hasText(emailUserProfileField.getValue())) {
|
||||||
|
email = emailUserProfileField.getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return email;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,19 +74,7 @@ public class EmailController extends BaseController {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
String email = userManager.getBstlyEmail(user.getUsername());
|
String email = emailManager.getUserEmail(user);
|
||||||
|
|
||||||
UserProfileField primaryEmailUserProfileField = userProfileFieldManager
|
|
||||||
.get(user.getId(), UserProfileFields.PROFILE_FIELD_EMAIL_PRIMARY);
|
|
||||||
if (primaryEmailUserProfileField != null
|
|
||||||
&& "true".equals(primaryEmailUserProfileField.getValue())) {
|
|
||||||
UserProfileField emailUserProfileField = userProfileFieldManager.get(user.getId(),
|
|
||||||
UserProfileFields.PROFILE_FIELD_EMAIL);
|
|
||||||
if (emailUserProfileField != null
|
|
||||||
&& StringUtils.hasText(emailUserProfileField.getValue())) {
|
|
||||||
email = emailUserProfileField.getValue();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
UserMailModel userMailModel = new UserMailModel(user.getUsername(), email);
|
UserMailModel userMailModel = new UserMailModel(user.getUsername(), email);
|
||||||
|
|
||||||
@@ -95,7 +83,6 @@ public class EmailController extends BaseController {
|
|||||||
if (localeUserProfileField != null
|
if (localeUserProfileField != null
|
||||||
&& StringUtils.hasText(localeUserProfileField.getValue())) {
|
&& StringUtils.hasText(localeUserProfileField.getValue())) {
|
||||||
userMailModel.setLocale(localeUserProfileField.getValue());
|
userMailModel.setLocale(localeUserProfileField.getValue());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
result.add(userMailModel);
|
result.add(userMailModel);
|
||||||
@@ -104,4 +91,6 @@ public class EmailController extends BaseController {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,6 @@ public class JitsiRoomValidator implements Validator {
|
|||||||
private JitsiRoomRepository jitsiRoomRepository;
|
private JitsiRoomRepository jitsiRoomRepository;
|
||||||
private QJitsiRoom qJitsiRoom = QJitsiRoom.jitsiRoom;
|
private QJitsiRoom qJitsiRoom = QJitsiRoom.jitsiRoom;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @see org.springframework.validation.Validator#supports(java.lang.Class)
|
* @see org.springframework.validation.Validator#supports(java.lang.Class)
|
||||||
*/
|
*/
|
||||||
@@ -43,9 +42,9 @@ public class JitsiRoomValidator implements Validator {
|
|||||||
return clazz.isAssignableFrom(JitsiRoom.class);
|
return clazz.isAssignableFrom(JitsiRoom.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @see org.springframework.validation.Validator#validate(java.lang.Object, org.springframework.validation.Errors)
|
* @see org.springframework.validation.Validator#validate(java.lang.Object,
|
||||||
|
* org.springframework.validation.Errors)
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void validate(Object target, Errors errors) {
|
public void validate(Object target, Errors errors) {
|
||||||
|
|||||||
+26
@@ -0,0 +1,26 @@
|
|||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>de.bstly.we</groupId>
|
||||||
|
<artifactId>webstly-main</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<name>jwt</name>
|
||||||
|
<artifactId>webstly-jwt</artifactId>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>de.bstly.we</groupId>
|
||||||
|
<artifactId>webstly-core</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.nimbusds</groupId>
|
||||||
|
<artifactId>nimbus-jose-jwt</artifactId>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,293 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package de.bstly.we.jwt.businesslogic;
|
||||||
|
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.time.temporal.ChronoUnit;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import javax.transaction.Transactional;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.data.domain.PageRequest;
|
||||||
|
import org.springframework.data.domain.Sort;
|
||||||
|
import org.springframework.data.domain.Sort.Order;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import com.nimbusds.jose.JOSEException;
|
||||||
|
import com.nimbusds.jose.JWSAlgorithm;
|
||||||
|
import com.nimbusds.jose.JWSSigner;
|
||||||
|
import com.nimbusds.jose.JWSVerifier;
|
||||||
|
import com.nimbusds.jose.crypto.ECDSASigner;
|
||||||
|
import com.nimbusds.jose.crypto.ECDSAVerifier;
|
||||||
|
import com.nimbusds.jose.crypto.Ed25519Signer;
|
||||||
|
import com.nimbusds.jose.crypto.Ed25519Verifier;
|
||||||
|
import com.nimbusds.jose.crypto.RSASSASigner;
|
||||||
|
import com.nimbusds.jose.crypto.RSASSAVerifier;
|
||||||
|
import com.nimbusds.jose.jwk.Curve;
|
||||||
|
import com.nimbusds.jose.jwk.ECKey;
|
||||||
|
import com.nimbusds.jose.jwk.JWK;
|
||||||
|
import com.nimbusds.jose.jwk.JWKSet;
|
||||||
|
import com.nimbusds.jose.jwk.KeyType;
|
||||||
|
import com.nimbusds.jose.jwk.KeyUse;
|
||||||
|
import com.nimbusds.jose.jwk.OctetKeyPair;
|
||||||
|
import com.nimbusds.jose.jwk.RSAKey;
|
||||||
|
import com.nimbusds.jose.jwk.gen.ECKeyGenerator;
|
||||||
|
import com.nimbusds.jose.jwk.gen.OctetKeyPairGenerator;
|
||||||
|
import com.nimbusds.jose.jwk.gen.RSAKeyGenerator;
|
||||||
|
|
||||||
|
import de.bstly.we.jwt.model.JwtKey;
|
||||||
|
import de.bstly.we.jwt.model.QJwtKey;
|
||||||
|
import de.bstly.we.jwt.repository.JwtKeyRepository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Class JwtKeyManager.
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class JwtKeyManager {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private JwtKeyRepository jwtKeyRepository;
|
||||||
|
|
||||||
|
private QJwtKey qJwtKey = QJwtKey.jwtKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the jwk set.
|
||||||
|
*
|
||||||
|
* @param name the name
|
||||||
|
* @param createDefault the create default
|
||||||
|
* @return the jwk set
|
||||||
|
*/
|
||||||
|
@Transactional
|
||||||
|
public JWKSet getJwkSet(String name, boolean createDefault) {
|
||||||
|
List<JWK> jwkList = Lists.newArrayList();
|
||||||
|
|
||||||
|
for (JwtKey jwtKey : jwtKeyRepository.findAll(qJwtKey.name.eq(name))) {
|
||||||
|
JWK jwk = parseKey(jwtKey);
|
||||||
|
if (jwk != null) {
|
||||||
|
jwkList.add(jwk.toPublicJWK());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (jwkList.isEmpty()) {
|
||||||
|
JwtKey jwtKey = getLatest(name, createDefault);
|
||||||
|
if (jwtKey == null) {
|
||||||
|
// ERROR
|
||||||
|
}
|
||||||
|
JWK jwk = parseKey(jwtKey);
|
||||||
|
if (jwk != null) {
|
||||||
|
jwkList.add(jwk.toPublicJWK());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new JWKSet(jwkList);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the latest.
|
||||||
|
*
|
||||||
|
* @param name the name
|
||||||
|
* @param createDefault the create default
|
||||||
|
* @return the latest
|
||||||
|
*/
|
||||||
|
@Transactional
|
||||||
|
public JwtKey getLatest(String name, boolean createDefault) {
|
||||||
|
List<JwtKey> jwtKeys = Lists.newArrayList(jwtKeyRepository.findAll(qJwtKey.name.eq(name),
|
||||||
|
PageRequest.of(0, 1, Sort.by(Order.desc("created")))));
|
||||||
|
|
||||||
|
JwtKey jwtKey = null;
|
||||||
|
|
||||||
|
if (!jwtKeys.isEmpty()) {
|
||||||
|
jwtKey = jwtKeys.get(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (jwtKey != null) {
|
||||||
|
if (jwtKey.getLifetime() == -1L || jwtKey.getExpires()
|
||||||
|
.isAfter(Instant.now().plus(jwtKey.getLifetime(), ChronoUnit.SECONDS))) {
|
||||||
|
return jwtKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
JwtKey newKey = new JwtKey();
|
||||||
|
newKey.setName(name);
|
||||||
|
newKey.setKeyParameter(jwtKey.getKeyParameter());
|
||||||
|
newKey.setKeyType(jwtKey.getKeyType());
|
||||||
|
newKey.setKeyUse(jwtKey.getKeyUse());
|
||||||
|
newKey.setLifetime(jwtKey.getLifetime());
|
||||||
|
newKey.setExpires(Instant.now().plus(jwtKey.getLifetime(), ChronoUnit.SECONDS));
|
||||||
|
return createKey(newKey);
|
||||||
|
} else if (createDefault) {
|
||||||
|
jwtKey = new JwtKey();
|
||||||
|
jwtKey.setName(name);
|
||||||
|
return createKey(jwtKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the by key ID.
|
||||||
|
*
|
||||||
|
* @param keyID the key ID
|
||||||
|
* @return the by key ID
|
||||||
|
*/
|
||||||
|
@Transactional
|
||||||
|
public JwtKey getByKeyID(String keyID) {
|
||||||
|
return jwtKeyRepository.findOne(qJwtKey.keyID.eq(keyID)).orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public JwtKey getByCreated(String name, Instant created) {
|
||||||
|
return jwtKeyRepository
|
||||||
|
.findOne(qJwtKey.name.eq(name)
|
||||||
|
.and(qJwtKey.created.before(created)
|
||||||
|
.and(qJwtKey.lifetime.eq(-1L).or(qJwtKey.expires.after(created)))))
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the key.
|
||||||
|
*
|
||||||
|
* @param jwtKey the jwt key
|
||||||
|
* @return the jwt key
|
||||||
|
*/
|
||||||
|
public JwtKey createKey(JwtKey jwtKey) {
|
||||||
|
JWK jwk = null;
|
||||||
|
String keyID = UUID.randomUUID().toString();
|
||||||
|
while (jwtKeyRepository.exists(qJwtKey.keyID.eq(keyID))) {
|
||||||
|
keyID = UUID.randomUUID().toString();
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
KeyType keyType = KeyType.parse(jwtKey.getKeyType());
|
||||||
|
if (KeyType.EC.equals(keyType)) {
|
||||||
|
jwk = new ECKeyGenerator(Curve.parse(jwtKey.getKeyParameter()))
|
||||||
|
.keyUse(KeyUse.parse(jwtKey.getKeyUse())).keyID(keyID).generate();
|
||||||
|
} else if (KeyType.OCT.equals(keyType)) {
|
||||||
|
jwk = new OctetKeyPairGenerator(Curve.parse(jwtKey.getKeyParameter()))
|
||||||
|
.keyUse(KeyUse.parse(jwtKey.getKeyUse())).keyID(keyID).generate();
|
||||||
|
} else if (KeyType.RSA.equals(keyType)) {
|
||||||
|
jwk = new RSAKeyGenerator(Integer.valueOf(jwtKey.getKeyParameter()))
|
||||||
|
.keyUse(KeyUse.parse(jwtKey.getKeyUse())).keyID(keyID).generate();
|
||||||
|
}
|
||||||
|
} catch (JOSEException | ParseException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (jwk != null) {
|
||||||
|
jwtKey.setKeyID(keyID);
|
||||||
|
jwtKey.setData(jwk.toJSONString());
|
||||||
|
jwtKey.setCreated(Instant.now());
|
||||||
|
jwtKey.setExpires(Instant.now().plus(jwtKey.getLifetime(), ChronoUnit.SECONDS));
|
||||||
|
return jwtKeyRepository.save(jwtKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
jwtKeyRepository.delete(jwtKey);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the key.
|
||||||
|
*
|
||||||
|
* @param jwtKey the jwt key
|
||||||
|
* @return the jwk
|
||||||
|
*/
|
||||||
|
public JWK parseKey(JwtKey jwtKey) {
|
||||||
|
try {
|
||||||
|
KeyType keyType = KeyType.parse(jwtKey.getKeyType());
|
||||||
|
if (KeyType.EC.equals(keyType)) {
|
||||||
|
return ECKey.parse(jwtKey.getData());
|
||||||
|
} else if (KeyType.OCT.equals(keyType)) {
|
||||||
|
return OctetKeyPair.parse(jwtKey.getData());
|
||||||
|
} else if (KeyType.RSA.equals(keyType)) {
|
||||||
|
return RSAKey.parse(jwtKey.getData());
|
||||||
|
}
|
||||||
|
} catch (ParseException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the jws algorithm.
|
||||||
|
*
|
||||||
|
* @param jwtKey the jwt key
|
||||||
|
* @return the jws algorithm
|
||||||
|
*/
|
||||||
|
public JWSAlgorithm getJwsAlgorithm(JwtKey jwtKey) {
|
||||||
|
if (jwtKey != null && StringUtils.hasText(jwtKey.getJwsAlgorithm())) {
|
||||||
|
return JWSAlgorithm.parse(jwtKey.getJwsAlgorithm());
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the jws algorithm.
|
||||||
|
*
|
||||||
|
* @param name the name
|
||||||
|
* @param createDefault the create default
|
||||||
|
* @return the jws algorithm
|
||||||
|
*/
|
||||||
|
public JWSAlgorithm getJwsAlgorithm(String name, boolean createDefault) {
|
||||||
|
return getJwsAlgorithm(getLatest(name, createDefault));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the signer.
|
||||||
|
*
|
||||||
|
* @param jwtKey the jwt key
|
||||||
|
* @return the JWS signer
|
||||||
|
*/
|
||||||
|
public JWSSigner createSigner(JwtKey jwtKey) {
|
||||||
|
JWK jwk = parseKey(jwtKey);
|
||||||
|
if (jwk != null) {
|
||||||
|
try {
|
||||||
|
KeyType keyType = KeyType.parse(jwtKey.getKeyType());
|
||||||
|
if (KeyType.EC.equals(keyType)) {
|
||||||
|
return new ECDSASigner((ECKey) jwk);
|
||||||
|
} else if (KeyType.OCT.equals(keyType)) {
|
||||||
|
return new Ed25519Signer((OctetKeyPair) jwk);
|
||||||
|
} else if (KeyType.RSA.equals(keyType)) {
|
||||||
|
return new RSASSASigner((RSAKey) jwk);
|
||||||
|
}
|
||||||
|
} catch (JOSEException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the verfifier.
|
||||||
|
*
|
||||||
|
* @param jwtKey the jwt key
|
||||||
|
* @return the JWS verifier
|
||||||
|
*/
|
||||||
|
public JWSVerifier createVerfifier(JwtKey jwtKey) {
|
||||||
|
JWK jwk = parseKey(jwtKey);
|
||||||
|
|
||||||
|
if (jwk != null) {
|
||||||
|
try {
|
||||||
|
KeyType keyType = KeyType.parse(jwtKey.getKeyType());
|
||||||
|
if (KeyType.EC.equals(keyType)) {
|
||||||
|
return new ECDSAVerifier((ECKey) jwk);
|
||||||
|
} else if (KeyType.OCT.equals(keyType)) {
|
||||||
|
return new Ed25519Verifier((OctetKeyPair) jwk);
|
||||||
|
} else if (KeyType.RSA.equals(keyType)) {
|
||||||
|
return new RSASSAVerifier((RSAKey) jwk);
|
||||||
|
}
|
||||||
|
} catch (JOSEException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package de.bstly.we.jwt.businesslogic;
|
||||||
|
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.time.temporal.ChronoUnit;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import com.nimbusds.jose.JOSEException;
|
||||||
|
import com.nimbusds.jose.JOSEObjectType;
|
||||||
|
import com.nimbusds.jose.JWSHeader;
|
||||||
|
import com.nimbusds.jose.KeySourceException;
|
||||||
|
import com.nimbusds.jwt.JWTClaimsSet.Builder;
|
||||||
|
import com.nimbusds.jwt.SignedJWT;
|
||||||
|
|
||||||
|
import de.bstly.we.businesslogic.UserManager;
|
||||||
|
import de.bstly.we.jwt.model.JwtKey;
|
||||||
|
import de.bstly.we.model.User;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Lurkars
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class JwtUserManager {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private JwtKeyManager jwtKeyManager;
|
||||||
|
@Autowired
|
||||||
|
private UserManager userManager;
|
||||||
|
|
||||||
|
public static final String JWT_USER_DATA_KEY_NAME = "user";
|
||||||
|
|
||||||
|
public SignedJWT createSignedJwt(Long userId, Object data, String issuer, Long lifetime)
|
||||||
|
throws JOSEException {
|
||||||
|
User user = userManager.get(userId);
|
||||||
|
|
||||||
|
if (user == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Builder claimsSetBuilder = new Builder();
|
||||||
|
claimsSetBuilder.subject(String.valueOf(user.getId()));
|
||||||
|
claimsSetBuilder.claim("name", user.getUsername());
|
||||||
|
claimsSetBuilder.issuer(issuer);
|
||||||
|
claimsSetBuilder.issueTime(new Date());
|
||||||
|
|
||||||
|
if (lifetime != null && lifetime > 0) {
|
||||||
|
claimsSetBuilder
|
||||||
|
.expirationTime(Date.from(Instant.now().plus(lifetime, ChronoUnit.SECONDS)));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data != null) {
|
||||||
|
claimsSetBuilder.claim("data", data);
|
||||||
|
}
|
||||||
|
|
||||||
|
JwtKey jwtKey = jwtKeyManager.getLatest(JWT_USER_DATA_KEY_NAME, true);
|
||||||
|
|
||||||
|
JWSHeader.Builder headerBuilder = new JWSHeader.Builder(
|
||||||
|
jwtKeyManager.getJwsAlgorithm(jwtKey));
|
||||||
|
headerBuilder.keyID(jwtKey.getKeyID());
|
||||||
|
headerBuilder.type(JOSEObjectType.JWT);
|
||||||
|
|
||||||
|
SignedJWT jwt = new SignedJWT(headerBuilder.build(), claimsSetBuilder.build());
|
||||||
|
jwt.sign(jwtKeyManager.createSigner(jwtKey));
|
||||||
|
return jwt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean verify(SignedJWT jwt) throws JOSEException, ParseException {
|
||||||
|
if (jwt.getHeader() == null || !StringUtils.hasText(jwt.getHeader().getKeyID())) {
|
||||||
|
throw new KeySourceException("No KeyID provided!");
|
||||||
|
}
|
||||||
|
|
||||||
|
JwtKey jwtKey = jwtKeyManager.getByKeyID(jwt.getHeader().getKeyID());
|
||||||
|
if (jwtKey == null) {
|
||||||
|
throw new KeySourceException("No key found for given keyID!");
|
||||||
|
}
|
||||||
|
return jwt.verify(jwtKeyManager.createVerfifier(jwtKey));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,105 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package de.bstly.we.jwt.controller;
|
||||||
|
|
||||||
|
import java.text.ParseException;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
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.RestController;
|
||||||
|
|
||||||
|
import com.nimbusds.jose.JOSEException;
|
||||||
|
import com.nimbusds.jwt.SignedJWT;
|
||||||
|
|
||||||
|
import de.bstly.we.controller.BaseController;
|
||||||
|
import de.bstly.we.controller.support.EntityResponseStatusException;
|
||||||
|
import de.bstly.we.jwt.businesslogic.JwtUserManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Lurkars
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/jwt/user")
|
||||||
|
public class JwtUserDataController extends BaseController {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private JwtUserManager jwtUserDataManager;
|
||||||
|
|
||||||
|
@Value("${bstly.we.jwtUserIssuer:}")
|
||||||
|
private String jwtUserIssuer;
|
||||||
|
|
||||||
|
@PreAuthorize("isAuthenticated()")
|
||||||
|
@GetMapping("/auth")
|
||||||
|
public String createSignedJwtAuth(HttpServletRequest request) {
|
||||||
|
String issuer = jwtUserIssuer;
|
||||||
|
if (!StringUtils.hasText(issuer)) {
|
||||||
|
issuer = request.getScheme()
|
||||||
|
+ "://"
|
||||||
|
+ request.getServerName();
|
||||||
|
if (request.getServerPort() != 443 && request.getServerPort() != 80) {
|
||||||
|
issuer += ":"
|
||||||
|
+ request.getServerPort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return jwtUserDataManager.createSignedJwt(getCurrentUserId(), null, issuer, 120L)
|
||||||
|
.serialize();
|
||||||
|
} catch (JOSEException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
throw new EntityResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@PreAuthorize("isAuthenticated()")
|
||||||
|
@PostMapping("/create")
|
||||||
|
public String createSignedJwt(@RequestBody Object data, HttpServletRequest request) {
|
||||||
|
String issuer = jwtUserIssuer;
|
||||||
|
if (!StringUtils.hasText(issuer)) {
|
||||||
|
issuer = request.getScheme()
|
||||||
|
+ "://"
|
||||||
|
+ request.getServerName();
|
||||||
|
if (request.getServerPort() != 443 && request.getServerPort() != 80) {
|
||||||
|
issuer += ":"
|
||||||
|
+ request.getServerPort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return jwtUserDataManager.createSignedJwt(getCurrentUserId(), data, issuer, -1L)
|
||||||
|
.serialize();
|
||||||
|
} catch (JOSEException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
throw new EntityResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("verify")
|
||||||
|
public Object verfiy(@RequestBody String serialized, HttpServletRequest request,
|
||||||
|
HttpServletResponse response) {
|
||||||
|
try {
|
||||||
|
SignedJWT signedJwt = SignedJWT.parse(serialized);
|
||||||
|
if (jwtUserDataManager.verify(signedJwt)) {
|
||||||
|
return signedJwt.getJWTClaimsSet();
|
||||||
|
} else {
|
||||||
|
throw new EntityResponseStatusException(HttpStatus.NOT_ACCEPTABLE);
|
||||||
|
}
|
||||||
|
} catch (ParseException e) {
|
||||||
|
throw new EntityResponseStatusException(HttpStatus.UNPROCESSABLE_ENTITY);
|
||||||
|
} catch (JOSEException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
throw new EntityResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,252 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package de.bstly.we.jwt.model;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.GenerationType;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.Lob;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
|
||||||
|
import com.nimbusds.jose.JWSAlgorithm;
|
||||||
|
import com.nimbusds.jose.jwk.Curve;
|
||||||
|
import com.nimbusds.jose.jwk.KeyType;
|
||||||
|
import com.nimbusds.jose.jwk.KeyUse;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Class JwtKey.
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
@Table(name = "jwt_keys")
|
||||||
|
public class JwtKey {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
@Column(name = "id")
|
||||||
|
private Long id;
|
||||||
|
@Column(name = "name", nullable = false)
|
||||||
|
private String name;
|
||||||
|
@Column(name = "key_id", nullable = true)
|
||||||
|
private String keyID;
|
||||||
|
@Lob
|
||||||
|
@Column(name = "data", nullable = true)
|
||||||
|
private String data;
|
||||||
|
@Column(name = "key_type", nullable = false)
|
||||||
|
private String keyType = KeyType.EC.getValue();
|
||||||
|
@Column(name = "key_parameter", nullable = false)
|
||||||
|
private String keyParameter = Curve.P_256.toString();
|
||||||
|
@Column(name = "key_use", nullable = false)
|
||||||
|
private String keyUse = KeyUse.SIGNATURE.getValue();
|
||||||
|
@Column(name = "jws_algorithm", nullable = false)
|
||||||
|
private String jwsAlgorithm = JWSAlgorithm.ES256.getName();
|
||||||
|
@Column(name = "lifetime", nullable = false)
|
||||||
|
private Long lifetime = -1L;
|
||||||
|
@Column(name = "created", nullable = false)
|
||||||
|
private Instant created;
|
||||||
|
@Column(name = "expires", nullable = false)
|
||||||
|
private Instant expires;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the id.
|
||||||
|
*
|
||||||
|
* @return the id
|
||||||
|
*/
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the id.
|
||||||
|
*
|
||||||
|
* @param id the new id
|
||||||
|
*/
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the name.
|
||||||
|
*
|
||||||
|
* @return the name
|
||||||
|
*/
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the name.
|
||||||
|
*
|
||||||
|
* @param name the new name
|
||||||
|
*/
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the key ID.
|
||||||
|
*
|
||||||
|
* @return the key ID
|
||||||
|
*/
|
||||||
|
public String getKeyID() {
|
||||||
|
return keyID;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the key ID.
|
||||||
|
*
|
||||||
|
* @param keyID the new key ID
|
||||||
|
*/
|
||||||
|
public void setKeyID(String keyID) {
|
||||||
|
this.keyID = keyID;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the data.
|
||||||
|
*
|
||||||
|
* @return the data
|
||||||
|
*/
|
||||||
|
public String getData() {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the data.
|
||||||
|
*
|
||||||
|
* @param data the new data
|
||||||
|
*/
|
||||||
|
public void setData(String data) {
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the key type.
|
||||||
|
*
|
||||||
|
* @return the key type
|
||||||
|
*/
|
||||||
|
public String getKeyType() {
|
||||||
|
return keyType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the key type.
|
||||||
|
*
|
||||||
|
* @param keyType the new key type
|
||||||
|
*/
|
||||||
|
public void setKeyType(String keyType) {
|
||||||
|
this.keyType = keyType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the key parameter.
|
||||||
|
*
|
||||||
|
* @return the key parameter
|
||||||
|
*/
|
||||||
|
public String getKeyParameter() {
|
||||||
|
return keyParameter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the key parameter.
|
||||||
|
*
|
||||||
|
* @param keyParameter the new key parameter
|
||||||
|
*/
|
||||||
|
public void setKeyParameter(String keyParameter) {
|
||||||
|
this.keyParameter = keyParameter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the key use.
|
||||||
|
*
|
||||||
|
* @return the key use
|
||||||
|
*/
|
||||||
|
public String getKeyUse() {
|
||||||
|
return keyUse;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the key use.
|
||||||
|
*
|
||||||
|
* @param keyUse the new key use
|
||||||
|
*/
|
||||||
|
public void setKeyUse(String keyUse) {
|
||||||
|
this.keyUse = keyUse;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the jws algorithm.
|
||||||
|
*
|
||||||
|
* @return the jws algorithm
|
||||||
|
*/
|
||||||
|
public String getJwsAlgorithm() {
|
||||||
|
return jwsAlgorithm;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the jws algorithm.
|
||||||
|
*
|
||||||
|
* @param jwsAlgorithm the new jws algorithm
|
||||||
|
*/
|
||||||
|
public void setJwsAlgorithm(String jwsAlgorithm) {
|
||||||
|
this.jwsAlgorithm = jwsAlgorithm;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the lifetime.
|
||||||
|
*
|
||||||
|
* @return the lifetime
|
||||||
|
*/
|
||||||
|
public Long getLifetime() {
|
||||||
|
return lifetime;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the lifetime.
|
||||||
|
*
|
||||||
|
* @param lifetime the new lifetime
|
||||||
|
*/
|
||||||
|
public void setLifetime(Long lifetime) {
|
||||||
|
this.lifetime = lifetime;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the created.
|
||||||
|
*
|
||||||
|
* @return the created
|
||||||
|
*/
|
||||||
|
public Instant getCreated() {
|
||||||
|
return created;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the created.
|
||||||
|
*
|
||||||
|
* @param created the new created
|
||||||
|
*/
|
||||||
|
public void setCreated(Instant created) {
|
||||||
|
this.created = created;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the expires.
|
||||||
|
*
|
||||||
|
* @return the expires
|
||||||
|
*/
|
||||||
|
public Instant getExpires() {
|
||||||
|
return expires;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the expires.
|
||||||
|
*
|
||||||
|
* @param expires the new expires
|
||||||
|
*/
|
||||||
|
public void setExpires(Instant expires) {
|
||||||
|
this.expires = expires;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package de.bstly.we.jwt.repository;
|
||||||
|
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.data.querydsl.QuerydslPredicateExecutor;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
import de.bstly.we.jwt.model.JwtKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Interface JwtKeyRepository.
|
||||||
|
*/
|
||||||
|
@Repository
|
||||||
|
public interface JwtKeyRepository
|
||||||
|
extends JpaRepository<JwtKey, Long>, QuerydslPredicateExecutor<JwtKey> {
|
||||||
|
}
|
||||||
+1
-6
@@ -14,13 +14,8 @@
|
|||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>de.bstly.we</groupId>
|
<groupId>de.bstly.we</groupId>
|
||||||
<artifactId>webstly-core</artifactId>
|
<artifactId>webstly-jwt</artifactId>
|
||||||
<version>${revision}</version>
|
<version>${revision}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.nimbusds</groupId>
|
|
||||||
<artifactId>nimbus-jose-jwt</artifactId>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
*/
|
*/
|
||||||
package de.bstly.we.oidc.businesslogic;
|
package de.bstly.we.oidc.businesslogic;
|
||||||
|
|
||||||
import java.text.ParseException;
|
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.time.ZoneId;
|
import java.time.ZoneId;
|
||||||
import java.time.temporal.ChronoUnit;
|
import java.time.temporal.ChronoUnit;
|
||||||
@@ -11,9 +10,8 @@ import java.util.Date;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import javax.annotation.PostConstruct;
|
|
||||||
|
|
||||||
import org.apache.commons.lang3.RandomStringUtils;
|
import org.apache.commons.lang3.RandomStringUtils;
|
||||||
|
import org.springframework.beans.factory.SmartInitializingSingleton;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
@@ -21,24 +19,22 @@ import org.springframework.util.StringUtils;
|
|||||||
|
|
||||||
import com.beust.jcommander.internal.Maps;
|
import com.beust.jcommander.internal.Maps;
|
||||||
import com.nimbusds.jose.JOSEException;
|
import com.nimbusds.jose.JOSEException;
|
||||||
|
import com.nimbusds.jose.JOSEObjectType;
|
||||||
import com.nimbusds.jose.JWSAlgorithm;
|
import com.nimbusds.jose.JWSAlgorithm;
|
||||||
import com.nimbusds.jose.JWSHeader;
|
import com.nimbusds.jose.JWSHeader;
|
||||||
import com.nimbusds.jose.JWSSigner;
|
|
||||||
import com.nimbusds.jose.JWSVerifier;
|
|
||||||
import com.nimbusds.jose.crypto.RSASSASigner;
|
|
||||||
import com.nimbusds.jose.crypto.RSASSAVerifier;
|
|
||||||
import com.nimbusds.jose.jwk.JWKSet;
|
import com.nimbusds.jose.jwk.JWKSet;
|
||||||
import com.nimbusds.jose.jwk.RSAKey;
|
import com.nimbusds.jose.jwk.KeyType;
|
||||||
import com.nimbusds.jose.jwk.gen.RSAKeyGenerator;
|
import com.nimbusds.jose.jwk.KeyUse;
|
||||||
import com.nimbusds.jwt.JWTClaimsSet.Builder;
|
import com.nimbusds.jwt.JWTClaimsSet.Builder;
|
||||||
import com.nimbusds.jwt.SignedJWT;
|
import com.nimbusds.jwt.SignedJWT;
|
||||||
|
|
||||||
import de.bstly.we.businesslogic.PermissionManager;
|
import de.bstly.we.businesslogic.PermissionManager;
|
||||||
import de.bstly.we.businesslogic.QuotaManager;
|
import de.bstly.we.businesslogic.QuotaManager;
|
||||||
import de.bstly.we.businesslogic.SystemPropertyManager;
|
|
||||||
import de.bstly.we.businesslogic.UserManager;
|
import de.bstly.we.businesslogic.UserManager;
|
||||||
import de.bstly.we.businesslogic.UserProfileFieldManager;
|
import de.bstly.we.businesslogic.UserProfileFieldManager;
|
||||||
import de.bstly.we.businesslogic.UserProfileFields;
|
import de.bstly.we.businesslogic.UserProfileFields;
|
||||||
|
import de.bstly.we.jwt.businesslogic.JwtKeyManager;
|
||||||
|
import de.bstly.we.jwt.model.JwtKey;
|
||||||
import de.bstly.we.model.Permission;
|
import de.bstly.we.model.Permission;
|
||||||
import de.bstly.we.model.Quota;
|
import de.bstly.we.model.Quota;
|
||||||
import de.bstly.we.model.User;
|
import de.bstly.we.model.User;
|
||||||
@@ -52,17 +48,12 @@ import de.bstly.we.oidc.repository.OidcTokenRepository;
|
|||||||
* The Class OidcTokenManager.
|
* The Class OidcTokenManager.
|
||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
public class OidcTokenManager {
|
public class OidcTokenManager implements SmartInitializingSingleton {
|
||||||
|
|
||||||
public static final int ACCESS_TOKEN_LENGTH = 64;
|
public static final int ACCESS_TOKEN_LENGTH = 64;
|
||||||
public static final String OIDC_JWK_PUBLIC_KEY = "oidc-jwk-public-key";
|
public static final String OIDC_JWT_KEY_NAME = "oidc";
|
||||||
public static final String BEARER_TOKEN_TYPE = "Bearer";
|
public static final String BEARER_TOKEN_TYPE = "Bearer";
|
||||||
|
|
||||||
private RSAKey publicKey;
|
|
||||||
private JWKSet jwkSet;
|
|
||||||
private JWSSigner signer;
|
|
||||||
private JWSVerifier verifier;
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private OidcTokenRepository tokenRepository;
|
private OidcTokenRepository tokenRepository;
|
||||||
@Autowired
|
@Autowired
|
||||||
@@ -74,32 +65,37 @@ public class OidcTokenManager {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private QuotaManager quotaManager;
|
private QuotaManager quotaManager;
|
||||||
@Autowired
|
@Autowired
|
||||||
private SystemPropertyManager systemPropertyManager;
|
private JwtKeyManager jwtKeyManager;
|
||||||
private QOidcToken qOidcToken = QOidcToken.oidcToken;
|
private QOidcToken qOidcToken = QOidcToken.oidcToken;
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Inits the oidc token manager.
|
* @see org.springframework.beans.factory.SmartInitializingSingleton#afterSingletonsInstantiated()
|
||||||
*
|
|
||||||
* @throws JOSEException the JOSE exception
|
|
||||||
*/
|
*/
|
||||||
@PostConstruct
|
/*
|
||||||
public void initOidcTokenManager() throws JOSEException {
|
* @see org.springframework.beans.factory.SmartInitializingSingleton#
|
||||||
RSAKey rsaJWK = null;
|
* afterSingletonsInstantiated()
|
||||||
if (systemPropertyManager.has(OIDC_JWK_PUBLIC_KEY)) {
|
*/
|
||||||
try {
|
@Override
|
||||||
rsaJWK = RSAKey.parse(systemPropertyManager.get(OIDC_JWK_PUBLIC_KEY));
|
public void afterSingletonsInstantiated() {
|
||||||
} catch (ParseException e) {
|
if (jwtKeyManager.getLatest(OIDC_JWT_KEY_NAME, false) == null) {
|
||||||
|
createDefaultJwtKey();
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
rsaJWK = new RSAKeyGenerator(2048).keyID("1").generate();
|
|
||||||
systemPropertyManager.add(OIDC_JWK_PUBLIC_KEY, rsaJWK.toJSONString());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.publicKey = rsaJWK.toPublicJWK();
|
/**
|
||||||
this.signer = new RSASSASigner(rsaJWK);
|
* Creates the default jwt key.
|
||||||
this.jwkSet = new JWKSet(this.publicKey);
|
*
|
||||||
this.verifier = new RSASSAVerifier(this.publicKey);
|
* @return the jwt key
|
||||||
|
*/
|
||||||
|
protected JwtKey createDefaultJwtKey() {
|
||||||
|
JwtKey jwtKey = new JwtKey();
|
||||||
|
jwtKey.setName(OIDC_JWT_KEY_NAME);
|
||||||
|
jwtKey.setKeyType(KeyType.RSA.getValue());
|
||||||
|
jwtKey.setKeyParameter("2048");
|
||||||
|
jwtKey.setJwsAlgorithm(JWSAlgorithm.RS256.getName());
|
||||||
|
jwtKey.setKeyUse(KeyUse.SIGNATURE.getValue());
|
||||||
|
jwtKey.setLifetime(-1L);
|
||||||
|
return jwtKeyManager.createKey(jwtKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -154,11 +150,19 @@ public class OidcTokenManager {
|
|||||||
claimsSetBuilder.claim("nonce", nonce);
|
claimsSetBuilder.claim("nonce", nonce);
|
||||||
}
|
}
|
||||||
|
|
||||||
JWSHeader.Builder headerBuilder = new JWSHeader.Builder(JWSAlgorithm.RS256);
|
JwtKey jwtKey = jwtKeyManager.getLatest(OIDC_JWT_KEY_NAME, false);
|
||||||
headerBuilder.keyID(getPublicKey().getKeyID());
|
|
||||||
|
if (jwtKey == null) {
|
||||||
|
jwtKey = createDefaultJwtKey();
|
||||||
|
}
|
||||||
|
|
||||||
|
JWSHeader.Builder headerBuilder = new JWSHeader.Builder(
|
||||||
|
jwtKeyManager.getJwsAlgorithm(jwtKey));
|
||||||
|
headerBuilder.keyID(jwtKey.getKeyID());
|
||||||
|
headerBuilder.type(JOSEObjectType.JWT);
|
||||||
|
|
||||||
SignedJWT jwt = new SignedJWT(headerBuilder.build(), claimsSetBuilder.build());
|
SignedJWT jwt = new SignedJWT(headerBuilder.build(), claimsSetBuilder.build());
|
||||||
jwt.sign(getSigner());
|
jwt.sign(jwtKeyManager.createSigner(jwtKey));
|
||||||
|
|
||||||
token.setIdToken(jwt.serialize());
|
token.setIdToken(jwt.serialize());
|
||||||
|
|
||||||
@@ -234,39 +238,12 @@ public class OidcTokenManager {
|
|||||||
return tokenRepository.findOne(qOidcToken.accessToken.eq(accessToken)).orElse(null);
|
return tokenRepository.findOne(qOidcToken.accessToken.eq(accessToken)).orElse(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the signer.
|
|
||||||
*
|
|
||||||
* @return the signer
|
|
||||||
*/
|
|
||||||
public JWSSigner getSigner() {
|
|
||||||
return signer;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the verifier.
|
|
||||||
*
|
|
||||||
* @return the verifier
|
|
||||||
*/
|
|
||||||
public JWSVerifier getVerifier() {
|
|
||||||
return verifier;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the public key.
|
|
||||||
*
|
|
||||||
* @return the public key
|
|
||||||
*/
|
|
||||||
public RSAKey getPublicKey() {
|
|
||||||
return publicKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the jwk set.
|
* Gets the jwk set.
|
||||||
*
|
*
|
||||||
* @return the jwk set
|
* @return the jwk set
|
||||||
*/
|
*/
|
||||||
public JWKSet getJwkSet() {
|
public JWKSet getJwkSet() {
|
||||||
return jwkSet;
|
return jwtKeyManager.getJwkSet(OIDC_JWT_KEY_NAME, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,17 +80,19 @@ public class RoomController extends DebugLogger {
|
|||||||
memberData.setTags(Lists.newArrayList());
|
memberData.setTags(Lists.newArrayList());
|
||||||
try {
|
try {
|
||||||
Long userId = Long.parseLong(userIdentifier);
|
Long userId = Long.parseLong(userIdentifier);
|
||||||
|
User user = userManager.get(userId);
|
||||||
|
if (user != null && permissionManager.isFullUser(userId)
|
||||||
|
&& permissionManager.hasPermission(userId, ParteyPermissions.PARTEY)) {
|
||||||
|
|
||||||
if (StringUtils.hasText(visitCardUrlFormat)) {
|
if (StringUtils.hasText(visitCardUrlFormat)) {
|
||||||
User user = userManager.get(userId);
|
memberData
|
||||||
memberData.setVisitCardUrl(String.format(visitCardUrlFormat, user.getUsername()));
|
.setVisitCardUrl(String.format(visitCardUrlFormat, user.getUsername()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (permissionManager.isFullUser(userId)
|
|
||||||
&& permissionManager.hasPermission(userId, ParteyPermissions.PARTEY)) {
|
|
||||||
memberData.setAnonymous(false);
|
memberData.setAnonymous(false);
|
||||||
|
|
||||||
for (ParteyUserTag parteyUserTag : parteyUserTagManager.getForTarget(userId)) {
|
for (ParteyUserTag parteyUserTag : parteyUserTagManager
|
||||||
|
.getNonExpiredForUsername(user.getUsername())) {
|
||||||
memberData.getTags().add(parteyUserTag.getTag());
|
memberData.getTags().add(parteyUserTag.getTag());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ public class ParteyMapManager {
|
|||||||
private String internalMapUri;
|
private String internalMapUri;
|
||||||
|
|
||||||
private Pattern internalMapUriPattern = Pattern.compile("\\/@\\/(.+)");
|
private Pattern internalMapUriPattern = Pattern.compile("\\/@\\/(.+)");
|
||||||
private Pattern externalMapUriPattern = Pattern.compile("\\/_\\/(.+)");
|
private Pattern externalMapUriPattern = Pattern.compile("\\/_\\/[^/]+\\/(.+)");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the.
|
* Gets the.
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
*/
|
*/
|
||||||
package de.bstly.we.partey.businesslogic;
|
package de.bstly.we.partey.businesslogic;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@@ -10,10 +11,15 @@ import org.springframework.data.domain.Page;
|
|||||||
import org.springframework.data.domain.PageRequest;
|
import org.springframework.data.domain.PageRequest;
|
||||||
import org.springframework.data.domain.Sort;
|
import org.springframework.data.domain.Sort;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
import com.querydsl.core.BooleanBuilder;
|
||||||
|
|
||||||
|
import de.bstly.we.businesslogic.UserManager;
|
||||||
|
import de.bstly.we.model.User;
|
||||||
import de.bstly.we.partey.model.ParteyUserTag;
|
import de.bstly.we.partey.model.ParteyUserTag;
|
||||||
|
import de.bstly.we.partey.model.ParteyUserTag.ParteyUserTagId;
|
||||||
import de.bstly.we.partey.model.QParteyUserTag;
|
import de.bstly.we.partey.model.QParteyUserTag;
|
||||||
import de.bstly.we.partey.repository.ParteyUserTagRepository;
|
import de.bstly.we.partey.repository.ParteyUserTagRepository;
|
||||||
|
|
||||||
@@ -25,18 +31,20 @@ public class ParteyUserTagManager {
|
|||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ParteyUserTagRepository parteyUserTagRepository;
|
private ParteyUserTagRepository parteyUserTagRepository;
|
||||||
|
@Autowired
|
||||||
|
private UserManager userManager;
|
||||||
private QParteyUserTag qParteyUserTag = QParteyUserTag.parteyUserTag;
|
private QParteyUserTag qParteyUserTag = QParteyUserTag.parteyUserTag;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the.
|
* Gets the all.
|
||||||
*
|
*
|
||||||
* @param page the page
|
* @param page the page
|
||||||
* @param size the size
|
* @param size the size
|
||||||
* @param sortBy the sort by
|
* @param sortBy the sort by
|
||||||
* @param descending the descending
|
* @param descending the descending
|
||||||
* @return the page
|
* @return the all
|
||||||
*/
|
*/
|
||||||
public Page<ParteyUserTag> get(int page, int size, String sortBy, boolean descending) {
|
public Page<ParteyUserTag> getAll(int page, int size, String sortBy, boolean descending) {
|
||||||
PageRequest pageRequest = PageRequest.of(page, size,
|
PageRequest pageRequest = PageRequest.of(page, size,
|
||||||
descending ? Sort.by(sortBy).descending() : Sort.by(sortBy).ascending());
|
descending ? Sort.by(sortBy).descending() : Sort.by(sortBy).ascending());
|
||||||
|
|
||||||
@@ -44,14 +52,85 @@ public class ParteyUserTagManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the for target.
|
* Gets the all by user id.
|
||||||
*
|
*
|
||||||
* @param target the target
|
* @param userId the user id
|
||||||
* @return the for target
|
* @return the all by user id
|
||||||
*/
|
*/
|
||||||
public List<ParteyUserTag> getForTarget(long target) {
|
public List<ParteyUserTag> getAllByUserId(Long userId) {
|
||||||
return Lists
|
User user = userManager.get(userId);
|
||||||
.newArrayList(parteyUserTagRepository.findAll(qParteyUserTag.target.eq(target)));
|
Assert.notNull(user, "invalid userId: '"
|
||||||
|
+ userId
|
||||||
|
+ "'!");
|
||||||
|
return getAllForUsername(user.getUsername());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the non expired by user id.
|
||||||
|
*
|
||||||
|
* @param userId the user id
|
||||||
|
* @return the non expired by user id
|
||||||
|
*/
|
||||||
|
public List<ParteyUserTag> getNonExpiredByUserId(Long userId) {
|
||||||
|
return getNonExpiredByUserId(userId, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the non expired by user id.
|
||||||
|
*
|
||||||
|
* @param userId the user id
|
||||||
|
* @param upcoming the upcoming
|
||||||
|
* @return the non expired by user id
|
||||||
|
*/
|
||||||
|
public List<ParteyUserTag> getNonExpiredByUserId(Long userId, boolean upcoming) {
|
||||||
|
User user = userManager.get(userId);
|
||||||
|
Assert.notNull(user, "invalid userId: '"
|
||||||
|
+ userId
|
||||||
|
+ "'!");
|
||||||
|
return getNonExpiredForUsername(user.getUsername(), upcoming);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the all for username.
|
||||||
|
*
|
||||||
|
* @param username the username
|
||||||
|
* @return the all for username
|
||||||
|
*/
|
||||||
|
public List<ParteyUserTag> getAllForUsername(String username) {
|
||||||
|
return Lists.newArrayList(
|
||||||
|
parteyUserTagRepository.findAll(qParteyUserTag.username.eq(username)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the non expired for username.
|
||||||
|
*
|
||||||
|
* @param username the username
|
||||||
|
* @return the non expired for username
|
||||||
|
*/
|
||||||
|
public List<ParteyUserTag> getNonExpiredForUsername(String username) {
|
||||||
|
return getNonExpiredForUsername(username, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the non expired for username.
|
||||||
|
*
|
||||||
|
* @param username the username
|
||||||
|
* @param upcoming the upcoming
|
||||||
|
* @return the non expired for username
|
||||||
|
*/
|
||||||
|
public List<ParteyUserTag> getNonExpiredForUsername(String username, boolean upcoming) {
|
||||||
|
|
||||||
|
BooleanBuilder query = new BooleanBuilder();
|
||||||
|
|
||||||
|
query.and(qParteyUserTag.username.eq(username));
|
||||||
|
query.and(qParteyUserTag.expires.isNull().or(qParteyUserTag.expires.after(Instant.now())));
|
||||||
|
|
||||||
|
if (!upcoming) {
|
||||||
|
query.and(
|
||||||
|
qParteyUserTag.starts.isNull().or(qParteyUserTag.starts.before(Instant.now())));
|
||||||
|
}
|
||||||
|
|
||||||
|
return Lists.newArrayList(parteyUserTagRepository.findAll(query.getValue()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -67,20 +146,21 @@ public class ParteyUserTagManager {
|
|||||||
/**
|
/**
|
||||||
* Delete.
|
* Delete.
|
||||||
*
|
*
|
||||||
* @param id the id
|
* @param parteyUserTag the partey user tag
|
||||||
*/
|
*/
|
||||||
public void delete(Long id) {
|
public void delete(ParteyUserTag parteyUserTag) {
|
||||||
parteyUserTagRepository.deleteById(id);
|
parteyUserTagRepository.deleteById(
|
||||||
|
new ParteyUserTagId(parteyUserTag.getUsername(), parteyUserTag.getTag()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete all for target.
|
* Delete all for target.
|
||||||
*
|
*
|
||||||
* @param target the target
|
* @param username the username
|
||||||
*/
|
*/
|
||||||
public void deleteAllForTarget(Long target) {
|
public void deleteAllForTarget(String username) {
|
||||||
parteyUserTagRepository
|
parteyUserTagRepository
|
||||||
.deleteAll(parteyUserTagRepository.findAll(qParteyUserTag.target.eq(target)));
|
.deleteAll(parteyUserTagRepository.findAll(qParteyUserTag.username.eq(username)));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ public class UserTagController extends BaseController {
|
|||||||
@PreAuthorize("isAuthenticated()")
|
@PreAuthorize("isAuthenticated()")
|
||||||
@GetMapping
|
@GetMapping
|
||||||
public List<ParteyUserTag> getParteyUserTagsForTarget() {
|
public List<ParteyUserTag> getParteyUserTagsForTarget() {
|
||||||
return parteyUserTagManager.getForTarget(getCurrentUserId());
|
return parteyUserTagManager.getNonExpiredByUserId(getCurrentUserId(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+45
-7
@@ -55,8 +55,8 @@ public class UserTagManagementController extends BaseController {
|
|||||||
@RequestParam("sort") Optional<String> sortParameter,
|
@RequestParam("sort") Optional<String> sortParameter,
|
||||||
@RequestParam("desc") Optional<Boolean> descParameter) {
|
@RequestParam("desc") Optional<Boolean> descParameter) {
|
||||||
|
|
||||||
Page<ParteyUserTag> page = parteyUserTagManager.get(pageParameter.orElse(0),
|
Page<ParteyUserTag> page = parteyUserTagManager.getAll(pageParameter.orElse(0),
|
||||||
sizeParameter.orElse(10), sortParameter.orElse("id"), descParameter.orElse(false));
|
sizeParameter.orElse(10), sortParameter.orElse("username"), descParameter.orElse(false));
|
||||||
|
|
||||||
return page;
|
return page;
|
||||||
}
|
}
|
||||||
@@ -77,7 +77,45 @@ public class UserTagManagementController extends BaseController {
|
|||||||
throw new EntityResponseStatusException(HttpStatus.NO_CONTENT);
|
throw new EntityResponseStatusException(HttpStatus.NO_CONTENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
return parteyUserTagManager.getForTarget(user.getId());
|
return parteyUserTagManager.getAllForUsername(username);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the non expired partey user tags for target.
|
||||||
|
*
|
||||||
|
* @param username the username
|
||||||
|
* @return the non expired partey user tags for target
|
||||||
|
*/
|
||||||
|
@PreAuthorize("hasRole('ROLE_ADMIN')")
|
||||||
|
@GetMapping("{username}/active")
|
||||||
|
public List<ParteyUserTag> getNonExpiredParteyUserTagsForTarget(
|
||||||
|
@PathVariable("username") String username) {
|
||||||
|
User user = userManager.getByUsername(username);
|
||||||
|
|
||||||
|
if (user == null) {
|
||||||
|
throw new EntityResponseStatusException(HttpStatus.NO_CONTENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
return parteyUserTagManager.getNonExpiredForUsername(username);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the upcoming partey user tags for target.
|
||||||
|
*
|
||||||
|
* @param username the username
|
||||||
|
* @return the upcoming partey user tags for target
|
||||||
|
*/
|
||||||
|
@PreAuthorize("hasRole('ROLE_ADMIN')")
|
||||||
|
@GetMapping("{username}/upcoming")
|
||||||
|
public List<ParteyUserTag> getUpcomingParteyUserTagsForTarget(
|
||||||
|
@PathVariable("username") String username) {
|
||||||
|
User user = userManager.getByUsername(username);
|
||||||
|
|
||||||
|
if (user == null) {
|
||||||
|
throw new EntityResponseStatusException(HttpStatus.NO_CONTENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
return parteyUserTagManager.getNonExpiredForUsername(username, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -95,12 +133,12 @@ public class UserTagManagementController extends BaseController {
|
|||||||
/**
|
/**
|
||||||
* Delete partey user tag.
|
* Delete partey user tag.
|
||||||
*
|
*
|
||||||
* @param id the id
|
* @param parteyUserTag the partey user tag
|
||||||
*/
|
*/
|
||||||
@PreAuthorize("hasRole('ROLE_ADMIN')")
|
@PreAuthorize("hasRole('ROLE_ADMIN')")
|
||||||
@DeleteMapping("{id}")
|
@DeleteMapping
|
||||||
public void deleteParteyUserTag(@PathVariable("id") Long id) {
|
public void deleteParteyUserTag(@RequestBody ParteyUserTag parteyUserTag) {
|
||||||
parteyUserTagManager.delete(id);
|
parteyUserTagManager.delete(parteyUserTag);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,59 +3,143 @@
|
|||||||
*/
|
*/
|
||||||
package de.bstly.we.partey.model;
|
package de.bstly.we.partey.model;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.time.Instant;
|
||||||
|
|
||||||
import javax.persistence.Column;
|
import javax.persistence.Column;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
import javax.persistence.GeneratedValue;
|
|
||||||
import javax.persistence.GenerationType;
|
|
||||||
import javax.persistence.Id;
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.IdClass;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
|
||||||
|
import de.bstly.we.partey.model.ParteyUserTag.ParteyUserTagId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Class ParteyUserTag.
|
* The Class ParteyUserTag.
|
||||||
*/
|
*/
|
||||||
@Entity
|
@Entity
|
||||||
|
@IdClass(ParteyUserTagId.class)
|
||||||
|
@Table(name = "partey_user_tags")
|
||||||
public class ParteyUserTag {
|
public class ParteyUserTag {
|
||||||
|
|
||||||
@Id
|
@Id
|
||||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
private String username;
|
||||||
@Column(name = "id")
|
@Id
|
||||||
private Long id;
|
private String tag;
|
||||||
private Long target;
|
@Column(name = "starts", nullable = true)
|
||||||
|
private Instant starts;
|
||||||
|
@Column(name = "expires", nullable = true)
|
||||||
|
private Instant expires;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the username.
|
||||||
|
*
|
||||||
|
* @return the username
|
||||||
|
*/
|
||||||
|
public String getUsername() {
|
||||||
|
return username;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the username.
|
||||||
|
*
|
||||||
|
* @param username the new username
|
||||||
|
*/
|
||||||
|
public void setUsername(String username) {
|
||||||
|
this.username = username;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the tag.
|
||||||
|
*
|
||||||
|
* @return the tag
|
||||||
|
*/
|
||||||
|
public String getTag() {
|
||||||
|
return tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the tag.
|
||||||
|
*
|
||||||
|
* @param tag the new tag
|
||||||
|
*/
|
||||||
|
public void setTag(String tag) {
|
||||||
|
this.tag = tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the starts.
|
||||||
|
*
|
||||||
|
* @return the starts
|
||||||
|
*/
|
||||||
|
public Instant getStarts() {
|
||||||
|
return starts;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the starts.
|
||||||
|
*
|
||||||
|
* @param starts the new starts
|
||||||
|
*/
|
||||||
|
public void setStarts(Instant starts) {
|
||||||
|
this.starts = starts;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the expires.
|
||||||
|
*
|
||||||
|
* @return the expires
|
||||||
|
*/
|
||||||
|
public Instant getExpires() {
|
||||||
|
return expires;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the expires.
|
||||||
|
*
|
||||||
|
* @param expires the new expires
|
||||||
|
*/
|
||||||
|
public void setExpires(Instant expires) {
|
||||||
|
this.expires = expires;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ParteyUserTagId implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private String username;
|
||||||
private String tag;
|
private String tag;
|
||||||
|
|
||||||
/**
|
public ParteyUserTagId() {
|
||||||
* Gets the id.
|
super();
|
||||||
*
|
|
||||||
* @return the id
|
|
||||||
*/
|
|
||||||
public Long getId() {
|
|
||||||
return id;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the id.
|
* @param username
|
||||||
*
|
* @param tag
|
||||||
* @param id the new id
|
|
||||||
*/
|
*/
|
||||||
public void setId(Long id) {
|
public ParteyUserTagId(String username, String tag) {
|
||||||
this.id = id;
|
super();
|
||||||
|
this.username = username;
|
||||||
|
this.tag = tag;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the target.
|
* Gets the username.
|
||||||
*
|
*
|
||||||
* @return the target
|
* @return the username
|
||||||
*/
|
*/
|
||||||
public Long getTarget() {
|
public String getUsername() {
|
||||||
return target;
|
return username;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the target.
|
* Sets the username.
|
||||||
*
|
*
|
||||||
* @param target the new target
|
* @param username the new username
|
||||||
*/
|
*/
|
||||||
public void setTarget(Long target) {
|
public void setUsername(String username) {
|
||||||
this.target = target;
|
this.username = username;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -77,3 +161,5 @@ public class ParteyUserTag {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@@ -8,11 +8,12 @@ import org.springframework.data.querydsl.QuerydslPredicateExecutor;
|
|||||||
import org.springframework.stereotype.Repository;
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
import de.bstly.we.partey.model.ParteyUserTag;
|
import de.bstly.we.partey.model.ParteyUserTag;
|
||||||
|
import de.bstly.we.partey.model.ParteyUserTag.ParteyUserTagId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Interface ParteyUserTagRepository.
|
* The Interface ParteyUserTagRepository.
|
||||||
*/
|
*/
|
||||||
@Repository
|
@Repository
|
||||||
public interface ParteyUserTagRepository
|
public interface ParteyUserTagRepository extends JpaRepository<ParteyUserTag, ParteyUserTagId>,
|
||||||
extends JpaRepository<ParteyUserTag, Long>, QuerydslPredicateExecutor<ParteyUserTag> {
|
QuerydslPredicateExecutor<ParteyUserTag> {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
<properties>
|
<properties>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
<java.version>11</java.version>
|
<java.version>11</java.version>
|
||||||
<revision>1.1.0-SNAPSHOT</revision>
|
<revision>1.2.0-SNAPSHOT</revision>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<parent>
|
<parent>
|
||||||
@@ -24,11 +24,13 @@
|
|||||||
|
|
||||||
<modules>
|
<modules>
|
||||||
<module>application</module>
|
<module>application</module>
|
||||||
|
<module>borrow</module>
|
||||||
<module>core</module>
|
<module>core</module>
|
||||||
<module>email</module>
|
<module>email</module>
|
||||||
<module>i18n</module>
|
<module>i18n</module>
|
||||||
<module>invite</module>
|
<module>invite</module>
|
||||||
<module>jitsi</module>
|
<module>jitsi</module>
|
||||||
|
<module>jwt</module>
|
||||||
<module>membership</module>
|
<module>membership</module>
|
||||||
<module>minetest</module>
|
<module>minetest</module>
|
||||||
<module>oidc</module>
|
<module>oidc</module>
|
||||||
|
|||||||
Reference in New Issue
Block a user