draft for borrow, update partey tags, added jwt
This commit is contained in:
parent
442bdb4996
commit
a24f0650d1
@ -12,6 +12,11 @@
|
||||
<artifactId>application</artifactId>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>de.bstly.we</groupId>
|
||||
<artifactId>webstly-borrow</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>de.bstly.we</groupId>
|
||||
<artifactId>webstly-core</artifactId>
|
||||
|
26
borrow/pom.xml
Normal file
26
borrow/pom.xml
Normal file
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
267
borrow/src/main/java/de/bstly/we/borrow/model/BorrowItem.java
Normal file
267
borrow/src/main/java/de/bstly/we/borrow/model/BorrowItem.java
Normal file
@ -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;
|
||||
}
|
||||
|
||||
}
|
212
borrow/src/main/java/de/bstly/we/borrow/model/BorrowRequest.java
Normal file
212
borrow/src/main/java/de/bstly/we/borrow/model/BorrowRequest.java
Normal file
@ -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
|
||||
}
|
@ -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> {
|
||||
}
|
@ -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.javamail.JavaMailSender;
|
||||
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.
|
||||
@ -17,6 +24,10 @@ public class EmailManager {
|
||||
|
||||
@Autowired
|
||||
private JavaMailSender javaMailSender;
|
||||
@Autowired
|
||||
private UserManager userManager;
|
||||
@Autowired
|
||||
private UserProfileFieldManager userProfileFieldManager;
|
||||
|
||||
/**
|
||||
* Send text.
|
||||
@ -57,4 +68,28 @@ public class EmailManager {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
String email = emailManager.getUserEmail(user);
|
||||
|
||||
UserMailModel userMailModel = new UserMailModel(user.getUsername(), email);
|
||||
|
||||
@ -95,7 +83,6 @@ public class EmailController extends BaseController {
|
||||
if (localeUserProfileField != null
|
||||
&& StringUtils.hasText(localeUserProfileField.getValue())) {
|
||||
userMailModel.setLocale(localeUserProfileField.getValue());
|
||||
|
||||
}
|
||||
|
||||
result.add(userMailModel);
|
||||
@ -104,4 +91,6 @@ public class EmailController extends BaseController {
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@ -34,7 +34,6 @@ public class JitsiRoomValidator implements Validator {
|
||||
private JitsiRoomRepository jitsiRoomRepository;
|
||||
private QJitsiRoom qJitsiRoom = QJitsiRoom.jitsiRoom;
|
||||
|
||||
|
||||
/*
|
||||
* @see org.springframework.validation.Validator#supports(java.lang.Class)
|
||||
*/
|
||||
@ -43,9 +42,9 @@ public class JitsiRoomValidator implements Validator {
|
||||
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
|
||||
public void validate(Object target, Errors errors) {
|
||||
|
26
jwt/pom.xml
Normal file
26
jwt/pom.xml
Normal file
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
252
jwt/src/main/java/de/bstly/we/jwt/model/JwtKey.java
Normal file
252
jwt/src/main/java/de/bstly/we/jwt/model/JwtKey.java
Normal file
@ -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> {
|
||||
}
|
@ -14,13 +14,8 @@
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>de.bstly.we</groupId>
|
||||
<artifactId>webstly-core</artifactId>
|
||||
<artifactId>webstly-jwt</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.nimbusds</groupId>
|
||||
<artifactId>nimbus-jose-jwt</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
@ -3,7 +3,6 @@
|
||||
*/
|
||||
package de.bstly.we.oidc.businesslogic;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.time.Instant;
|
||||
import java.time.ZoneId;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
@ -11,9 +10,8 @@ import java.util.Date;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
import org.apache.commons.lang3.RandomStringUtils;
|
||||
import org.springframework.beans.factory.SmartInitializingSingleton;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.Assert;
|
||||
@ -21,24 +19,22 @@ import org.springframework.util.StringUtils;
|
||||
|
||||
import com.beust.jcommander.internal.Maps;
|
||||
import com.nimbusds.jose.JOSEException;
|
||||
import com.nimbusds.jose.JOSEObjectType;
|
||||
import com.nimbusds.jose.JWSAlgorithm;
|
||||
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.RSAKey;
|
||||
import com.nimbusds.jose.jwk.gen.RSAKeyGenerator;
|
||||
import com.nimbusds.jose.jwk.KeyType;
|
||||
import com.nimbusds.jose.jwk.KeyUse;
|
||||
import com.nimbusds.jwt.JWTClaimsSet.Builder;
|
||||
import com.nimbusds.jwt.SignedJWT;
|
||||
|
||||
import de.bstly.we.businesslogic.PermissionManager;
|
||||
import de.bstly.we.businesslogic.QuotaManager;
|
||||
import de.bstly.we.businesslogic.SystemPropertyManager;
|
||||
import de.bstly.we.businesslogic.UserManager;
|
||||
import de.bstly.we.businesslogic.UserProfileFieldManager;
|
||||
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.Quota;
|
||||
import de.bstly.we.model.User;
|
||||
@ -52,17 +48,12 @@ import de.bstly.we.oidc.repository.OidcTokenRepository;
|
||||
* The Class OidcTokenManager.
|
||||
*/
|
||||
@Service
|
||||
public class OidcTokenManager {
|
||||
public class OidcTokenManager implements SmartInitializingSingleton {
|
||||
|
||||
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";
|
||||
|
||||
private RSAKey publicKey;
|
||||
private JWKSet jwkSet;
|
||||
private JWSSigner signer;
|
||||
private JWSVerifier verifier;
|
||||
|
||||
@Autowired
|
||||
private OidcTokenRepository tokenRepository;
|
||||
@Autowired
|
||||
@ -74,32 +65,37 @@ public class OidcTokenManager {
|
||||
@Autowired
|
||||
private QuotaManager quotaManager;
|
||||
@Autowired
|
||||
private SystemPropertyManager systemPropertyManager;
|
||||
private JwtKeyManager jwtKeyManager;
|
||||
private QOidcToken qOidcToken = QOidcToken.oidcToken;
|
||||
|
||||
/**
|
||||
* Inits the oidc token manager.
|
||||
*
|
||||
* @throws JOSEException the JOSE exception
|
||||
/*
|
||||
* @see org.springframework.beans.factory.SmartInitializingSingleton#afterSingletonsInstantiated()
|
||||
*/
|
||||
@PostConstruct
|
||||
public void initOidcTokenManager() throws JOSEException {
|
||||
RSAKey rsaJWK = null;
|
||||
if (systemPropertyManager.has(OIDC_JWK_PUBLIC_KEY)) {
|
||||
try {
|
||||
rsaJWK = RSAKey.parse(systemPropertyManager.get(OIDC_JWK_PUBLIC_KEY));
|
||||
} catch (ParseException e) {
|
||||
|
||||
}
|
||||
} else {
|
||||
rsaJWK = new RSAKeyGenerator(2048).keyID("1").generate();
|
||||
systemPropertyManager.add(OIDC_JWK_PUBLIC_KEY, rsaJWK.toJSONString());
|
||||
/*
|
||||
* @see org.springframework.beans.factory.SmartInitializingSingleton#
|
||||
* afterSingletonsInstantiated()
|
||||
*/
|
||||
@Override
|
||||
public void afterSingletonsInstantiated() {
|
||||
if (jwtKeyManager.getLatest(OIDC_JWT_KEY_NAME, false) == null) {
|
||||
createDefaultJwtKey();
|
||||
}
|
||||
}
|
||||
|
||||
this.publicKey = rsaJWK.toPublicJWK();
|
||||
this.signer = new RSASSASigner(rsaJWK);
|
||||
this.jwkSet = new JWKSet(this.publicKey);
|
||||
this.verifier = new RSASSAVerifier(this.publicKey);
|
||||
/**
|
||||
* Creates the default jwt key.
|
||||
*
|
||||
* @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);
|
||||
}
|
||||
|
||||
JWSHeader.Builder headerBuilder = new JWSHeader.Builder(JWSAlgorithm.RS256);
|
||||
headerBuilder.keyID(getPublicKey().getKeyID());
|
||||
JwtKey jwtKey = jwtKeyManager.getLatest(OIDC_JWT_KEY_NAME, false);
|
||||
|
||||
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());
|
||||
jwt.sign(getSigner());
|
||||
jwt.sign(jwtKeyManager.createSigner(jwtKey));
|
||||
|
||||
token.setIdToken(jwt.serialize());
|
||||
|
||||
@ -234,39 +238,12 @@ public class OidcTokenManager {
|
||||
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.
|
||||
*
|
||||
* @return the jwk set
|
||||
*/
|
||||
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());
|
||||
try {
|
||||
Long userId = Long.parseLong(userIdentifier);
|
||||
|
||||
if (StringUtils.hasText(visitCardUrlFormat)) {
|
||||
User user = userManager.get(userId);
|
||||
memberData.setVisitCardUrl(String.format(visitCardUrlFormat, user.getUsername()));
|
||||
}
|
||||
|
||||
if (permissionManager.isFullUser(userId)
|
||||
User user = userManager.get(userId);
|
||||
if (user != null && permissionManager.isFullUser(userId)
|
||||
&& permissionManager.hasPermission(userId, ParteyPermissions.PARTEY)) {
|
||||
|
||||
if (StringUtils.hasText(visitCardUrlFormat)) {
|
||||
memberData
|
||||
.setVisitCardUrl(String.format(visitCardUrlFormat, user.getUsername()));
|
||||
}
|
||||
|
||||
memberData.setAnonymous(false);
|
||||
|
||||
for (ParteyUserTag parteyUserTag : parteyUserTagManager.getForTarget(userId)) {
|
||||
for (ParteyUserTag parteyUserTag : parteyUserTagManager
|
||||
.getNonExpiredForUsername(user.getUsername())) {
|
||||
memberData.getTags().add(parteyUserTag.getTag());
|
||||
}
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ public class ParteyMapManager {
|
||||
private String internalMapUri;
|
||||
|
||||
private Pattern internalMapUriPattern = Pattern.compile("\\/@\\/(.+)");
|
||||
private Pattern externalMapUriPattern = Pattern.compile("\\/_\\/(.+)");
|
||||
private Pattern externalMapUriPattern = Pattern.compile("\\/_\\/[^/]+\\/(.+)");
|
||||
|
||||
/**
|
||||
* Gets the.
|
||||
|
@ -3,6 +3,7 @@
|
||||
*/
|
||||
package de.bstly.we.partey.businesslogic;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
|
||||
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.Sort;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
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.ParteyUserTagId;
|
||||
import de.bstly.we.partey.model.QParteyUserTag;
|
||||
import de.bstly.we.partey.repository.ParteyUserTagRepository;
|
||||
|
||||
@ -25,18 +31,20 @@ public class ParteyUserTagManager {
|
||||
|
||||
@Autowired
|
||||
private ParteyUserTagRepository parteyUserTagRepository;
|
||||
@Autowired
|
||||
private UserManager userManager;
|
||||
private QParteyUserTag qParteyUserTag = QParteyUserTag.parteyUserTag;
|
||||
|
||||
/**
|
||||
* Gets the.
|
||||
* Gets the all.
|
||||
*
|
||||
* @param page the page
|
||||
* @param size the size
|
||||
* @param sortBy the sort by
|
||||
* @param page the page
|
||||
* @param size the size
|
||||
* @param sortBy the sort by
|
||||
* @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,
|
||||
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
|
||||
* @return the for target
|
||||
* @param userId the user id
|
||||
* @return the all by user id
|
||||
*/
|
||||
public List<ParteyUserTag> getForTarget(long target) {
|
||||
return Lists
|
||||
.newArrayList(parteyUserTagRepository.findAll(qParteyUserTag.target.eq(target)));
|
||||
public List<ParteyUserTag> getAllByUserId(Long userId) {
|
||||
User user = userManager.get(userId);
|
||||
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.
|
||||
*
|
||||
* @param id the id
|
||||
* @param parteyUserTag the partey user tag
|
||||
*/
|
||||
public void delete(Long id) {
|
||||
parteyUserTagRepository.deleteById(id);
|
||||
public void delete(ParteyUserTag parteyUserTag) {
|
||||
parteyUserTagRepository.deleteById(
|
||||
new ParteyUserTagId(parteyUserTag.getUsername(), parteyUserTag.getTag()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all for target.
|
||||
*
|
||||
* @param target the target
|
||||
* @param username the username
|
||||
*/
|
||||
public void deleteAllForTarget(Long target) {
|
||||
public void deleteAllForTarget(String username) {
|
||||
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()")
|
||||
@GetMapping
|
||||
public List<ParteyUserTag> getParteyUserTagsForTarget() {
|
||||
return parteyUserTagManager.getForTarget(getCurrentUserId());
|
||||
return parteyUserTagManager.getNonExpiredByUserId(getCurrentUserId(), true);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -55,8 +55,8 @@ public class UserTagManagementController extends BaseController {
|
||||
@RequestParam("sort") Optional<String> sortParameter,
|
||||
@RequestParam("desc") Optional<Boolean> descParameter) {
|
||||
|
||||
Page<ParteyUserTag> page = parteyUserTagManager.get(pageParameter.orElse(0),
|
||||
sizeParameter.orElse(10), sortParameter.orElse("id"), descParameter.orElse(false));
|
||||
Page<ParteyUserTag> page = parteyUserTagManager.getAll(pageParameter.orElse(0),
|
||||
sizeParameter.orElse(10), sortParameter.orElse("username"), descParameter.orElse(false));
|
||||
|
||||
return page;
|
||||
}
|
||||
@ -77,7 +77,45 @@ public class UserTagManagementController extends BaseController {
|
||||
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.
|
||||
*
|
||||
* @param id the id
|
||||
* @param parteyUserTag the partey user tag
|
||||
*/
|
||||
@PreAuthorize("hasRole('ROLE_ADMIN')")
|
||||
@DeleteMapping("{id}")
|
||||
public void deleteParteyUserTag(@PathVariable("id") Long id) {
|
||||
parteyUserTagManager.delete(id);
|
||||
@DeleteMapping
|
||||
public void deleteParteyUserTag(@RequestBody ParteyUserTag parteyUserTag) {
|
||||
parteyUserTagManager.delete(parteyUserTag);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -3,59 +3,50 @@
|
||||
*/
|
||||
package de.bstly.we.partey.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
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.IdClass;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import de.bstly.we.partey.model.ParteyUserTag.ParteyUserTagId;
|
||||
|
||||
/**
|
||||
* The Class ParteyUserTag.
|
||||
*/
|
||||
@Entity
|
||||
@IdClass(ParteyUserTagId.class)
|
||||
@Table(name = "partey_user_tags")
|
||||
public class ParteyUserTag {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(name = "id")
|
||||
private Long id;
|
||||
private Long target;
|
||||
private String username;
|
||||
@Id
|
||||
private String tag;
|
||||
@Column(name = "starts", nullable = true)
|
||||
private Instant starts;
|
||||
@Column(name = "expires", nullable = true)
|
||||
private Instant expires;
|
||||
|
||||
/**
|
||||
* Gets the id.
|
||||
* Gets the username.
|
||||
*
|
||||
* @return the id
|
||||
* @return the username
|
||||
*/
|
||||
public Long getId() {
|
||||
return id;
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the id.
|
||||
* Sets the username.
|
||||
*
|
||||
* @param id the new id
|
||||
* @param username the new username
|
||||
*/
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the target.
|
||||
*
|
||||
* @return the target
|
||||
*/
|
||||
public Long getTarget() {
|
||||
return target;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the target.
|
||||
*
|
||||
* @param target the new target
|
||||
*/
|
||||
public void setTarget(Long target) {
|
||||
this.target = target;
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -76,4 +67,99 @@ public class ParteyUserTag {
|
||||
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;
|
||||
|
||||
public ParteyUserTagId() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param username
|
||||
* @param tag
|
||||
*/
|
||||
public ParteyUserTagId(String username, String tag) {
|
||||
super();
|
||||
this.username = username;
|
||||
this.tag = tag;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -8,11 +8,12 @@ import org.springframework.data.querydsl.QuerydslPredicateExecutor;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import de.bstly.we.partey.model.ParteyUserTag;
|
||||
import de.bstly.we.partey.model.ParteyUserTag.ParteyUserTagId;
|
||||
|
||||
/**
|
||||
* The Interface ParteyUserTagRepository.
|
||||
*/
|
||||
@Repository
|
||||
public interface ParteyUserTagRepository
|
||||
extends JpaRepository<ParteyUserTag, Long>, QuerydslPredicateExecutor<ParteyUserTag> {
|
||||
public interface ParteyUserTagRepository extends JpaRepository<ParteyUserTag, ParteyUserTagId>,
|
||||
QuerydslPredicateExecutor<ParteyUserTag> {
|
||||
}
|
||||
|
4
pom.xml
4
pom.xml
@ -12,7 +12,7 @@
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<java.version>11</java.version>
|
||||
<revision>1.1.0-SNAPSHOT</revision>
|
||||
<revision>1.2.0-SNAPSHOT</revision>
|
||||
</properties>
|
||||
|
||||
<parent>
|
||||
@ -24,11 +24,13 @@
|
||||
|
||||
<modules>
|
||||
<module>application</module>
|
||||
<module>borrow</module>
|
||||
<module>core</module>
|
||||
<module>email</module>
|
||||
<module>i18n</module>
|
||||
<module>invite</module>
|
||||
<module>jitsi</module>
|
||||
<module>jwt</module>
|
||||
<module>membership</module>
|
||||
<module>minetest</module>
|
||||
<module>oidc</module>
|
||||
|
Loading…
Reference in New Issue
Block a user