initial commit

This commit is contained in:
2021-10-03 17:07:01 +02:00
commit 456332f24e
246 changed files with 24590 additions and 0 deletions
@@ -0,0 +1,30 @@
/**
*
*/
package de.bstly.we;
import javax.persistence.EntityManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.querydsl.jpa.impl.JPAQueryFactory;
/**
*
* @author _bastler@bstly.de
*
*/
@Configuration
public class CoreConfiguration {
@Autowired
private EntityManager em;
@Bean
public JPAQueryFactory jpaQueryFactory() {
return new JPAQueryFactory(em);
}
}
@@ -0,0 +1,369 @@
/**
*
*/
package de.bstly.we.businesslogic;
import java.time.Instant;
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import com.google.common.collect.Lists;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import de.bstly.we.businesslogic.support.InstantHelper;
import de.bstly.we.model.Permission;
import de.bstly.we.model.PermissionMapping;
import de.bstly.we.model.QPermission;
import de.bstly.we.model.UserData;
import de.bstly.we.repository.PermissionRepository;
/**
*
* @author _bastler@bstly.de
*
*/
@Component
public class PermissionManager implements UserDataProvider {
@Autowired
private PermissionRepository permissionRepository;
@Autowired
private PermissionMappingManager permissionMappingManager;
private QPermission qPermission = QPermission.permission;
DateTimeFormatter pretixOffsetDateTime = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ssx");
/**
*
* @param target
* @param name
* @return
*/
public List<Permission> get(Long target, String name) {
if (target != null) {
return Lists.newArrayList(permissionRepository
.findAll(qPermission.name.eq(name).and(qPermission.target.eq(target))));
}
return Lists.newArrayList();
}
/**
*
* @param target
* @return
*/
public List<Permission> getAllByTarget(Long target) {
if (target != null) {
return Lists.newArrayList(permissionRepository.findAll(qPermission.target.eq(target)));
}
return Lists.newArrayList();
}
/**
*
* @param target
* @return
*/
public List<Permission> getNotExpiresByTarget(Long target) {
if (target != null) {
return Lists.newArrayList(permissionRepository.findAll(qPermission.target.eq(target)
.and(qPermission.expires.after(Instant.now()).and(qPermission.starts.isNull()
.or(qPermission.starts.before(Instant.now()))))));
}
return Lists.newArrayList();
}
/**
*
* @param name
* @return
*/
public List<Permission> getNotExpiresByName(String name) {
if (name != null) {
return Lists.newArrayList(permissionRepository.findAll(qPermission.name.eq(name)
.and(qPermission.expires.after(Instant.now()).and(qPermission.starts.isNull()
.or(qPermission.starts.before(Instant.now()))))));
}
return Lists.newArrayList();
}
/**
*
* @param target
* @return
*/
public List<Permission> getNotExpiresByTargetIgnoreStart(Long target) {
if (target != null) {
return Lists.newArrayList(permissionRepository.findAll(
qPermission.target.eq(target).and(qPermission.expires.after(Instant.now()))));
}
return Lists.newArrayList();
}
/**
*
* @param target
* @return
*/
public boolean isFullUser(Long target) {
return permissionRepository.exists(qPermission.target.eq(target)
.and(qPermission.addon.isFalse()).and(qPermission.expires.after(Instant.now()).and(
qPermission.starts.isNull().or(qPermission.starts.before(Instant.now())))));
}
/**
*
* @param target
* @param name
* @return
*/
public boolean hasPermission(Long target, String name) {
if (!Permissions.ROLE_ADMIN.equals(name) && hasPermission(target, Permissions.ROLE_ADMIN)) {
return true;
}
return target != null && permissionRepository.exists(qPermission.name.eq(name)
.and(qPermission.target.eq(target))
.and(qPermission.expires.after(Instant.now()).and(
qPermission.starts.isNull().or(qPermission.starts.before(Instant.now())))));
}
/**
*
* @param target
* @param name
* @param addon
* @param expires
* @return
*/
public Permission create(Long target, String name, boolean addon, Instant starts,
Instant expires) {
Permission newPermission = new Permission();
newPermission.setTarget(target);
newPermission.setName(name);
newPermission.setAddon(addon);
newPermission.setStarts(starts);
newPermission.setExpires(expires);
return permissionRepository.save(newPermission);
}
/**
*
* @param permission
* @return
*/
public Permission update(Permission permission) {
Assert.isTrue(
permissionRepository.exists(qPermission.target.eq(permission.getTarget())
.and(qPermission.name.eq(permission.getName()))),
"Permission '" + permission.getName() + "' for target + '" + permission.getTarget()
+ "' not exists!");
Permission updatePermission = permissionRepository.findOne(qPermission.target
.eq(permission.getTarget()).and(qPermission.name.eq(permission.getName()))).get();
updatePermission.setStarts(permission.getStarts());
updatePermission.setExpires(permission.getExpires());
updatePermission.setAddon(permission.isAddon());
return permissionRepository.save(updatePermission);
}
/**
*
* @param name
* @param clone
* @return
*/
public List<Permission> clone(String name, String clone) {
List<Permission> permissions = Lists.newArrayList();
for (Permission permission : permissionRepository
.findAll(qPermission.name.eq(name).and(qPermission.expires.after(Instant.now())))) {
if (!permissionRepository.exists(
qPermission.name.eq(clone).and(qPermission.target.eq(permission.getTarget()))
.and(qPermission.expires.goe(permission.getExpires())))) {
permissions.add(create(permission.getTarget(), clone, permission.isAddon(),
permission.getStarts(), permission.getExpires()));
}
}
return permissions;
}
/**
*
* @param target
* @param name
*/
public void delete(Long target, String name) {
Assert.isTrue(
permissionRepository
.exists(qPermission.target.eq(target).and(qPermission.name.eq(name))),
"Permission '" + name + "' for target + '" + target + "' not exists!");
Permission delete = permissionRepository
.findOne(qPermission.target.eq(target).and(qPermission.name.eq(name))).get();
permissionRepository.delete(delete);
}
/**
*
* @param target
*/
public void deleteAll(Long target) {
permissionRepository.deleteAll(permissionRepository.findAll(qPermission.target.eq(target)));
}
/**
*
* @param name
*/
public void deleteAll(String name) {
permissionRepository.deleteAll(permissionRepository.findAll(qPermission.name.eq(name)));
}
/**
*
* @param target
* @param item
* @param answers
*/
public void applyItem(Long target, Integer item, JsonArray answers, Instant start) {
for (Permission permission : getForItem(target, item, answers, start)) {
permissionRepository.save(permission);
}
}
/**
*
* @param target
* @param item
* @param answers
* @return
*/
public List<Permission> getForItem(Long target, Integer item, JsonArray answers,
Instant start) {
List<Permission> permissions = Lists.newArrayList();
if (start == null) {
start = Instant.now();
}
for (PermissionMapping permissionMapping : permissionMappingManager.getAllByItem(item)) {
for (String name : permissionMapping.getNames()) {
Instant starts = null;
Instant expires = InstantHelper.plus(start, permissionMapping.getLifetime(),
permissionMapping.getLifetimeUnit());
boolean additional = true;
for (JsonElement anwser : answers) {
if (anwser.isJsonObject()
&& anwser.getAsJsonObject().has("question_identifier")) {
if (StringUtils.hasText(permissionMapping.getStartsQuestion())
&& permissionMapping.getStartsQuestion()
.equals(anwser.getAsJsonObject().get("question_identifier")
.getAsString())
&& anwser.getAsJsonObject().has("answer")) {
String dateTimeString = anwser.getAsJsonObject().get("answer")
.getAsString();
if (StringUtils.hasText(dateTimeString)) {
dateTimeString = dateTimeString.replace(" ", "T");
starts = OffsetDateTime.parse(dateTimeString).toInstant();
expires = InstantHelper.plus(starts,
permissionMapping.getLifetime(),
permissionMapping.getLifetimeUnit());
additional = false;
}
}
if (StringUtils.hasText(permissionMapping.getExpiresQuestion())
&& permissionMapping.getExpiresQuestion()
.equals(anwser.getAsJsonObject().get("question_identifier")
.getAsString())
&& anwser.getAsJsonObject().has("answer")) {
String dateTimeString = anwser.getAsJsonObject().get("answer")
.getAsString();
if (StringUtils.hasText(dateTimeString)) {
dateTimeString = dateTimeString.replace(" ", "T");
expires = InstantHelper.plus(
OffsetDateTime.parse(dateTimeString).toInstant(),
permissionMapping.getLifetime(),
permissionMapping.getLifetimeUnit());
additional = false;
}
}
}
}
Permission permission = null;
List<Permission> existingPermissions = get(target, name);
for (Permission existingPermission : existingPermissions) {
if (existingPermission.getStarts() == null) {
permission = existingPermission;
break;
}
}
if (permission == null || !additional) {
permission = new Permission();
permission.setTarget(target);
permission.setName(name);
permission.setAddon(permissionMapping.isAddon());
permission.setStarts(starts);
permission.setExpires(expires);
} else {
permission.setExpires(InstantHelper.plus(permission.getExpires(),
permissionMapping.getLifetime(), permissionMapping.getLifetimeUnit()));
}
if (permissionMapping.isLifetimeRound()) {
permission.setExpires(InstantHelper.truncate(permission.getExpires(),
permissionMapping.getLifetimeUnit()));
}
permissions.add(permission);
}
}
return permissions;
}
/*
* @see de.bstly.we.businesslogic.UserDataProvider#getId()
*/
@Override
public String getId() {
return "permissions";
}
/*
* @see de.bstly.we.businesslogic.UserDataProvider#getUserData(java.lang.Long)
*/
@Override
public List<UserData> getUserData(Long userId) {
List<UserData> result = Lists.newArrayList();
for (Permission permission : getAllByTarget(userId)) {
result.add(permission);
}
return result;
}
/*
* @see de.bstly.we.businesslogic.UserDataProvider#purgeUserData(java.lang.Long)
*/
@Override
public void purgeUserData(Long userId) {
for (Permission permission : getAllByTarget(userId)) {
permissionRepository.delete(permission);
}
}
}
@@ -0,0 +1,139 @@
/**
*
*/
package de.bstly.we.businesslogic;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.Set;
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 com.google.common.collect.Lists;
import de.bstly.we.model.PermissionMapping;
import de.bstly.we.model.QPermissionMapping;
import de.bstly.we.repository.PermissionMappingRepository;
/**
*
* @author _bastler@bstly.de
*
*/
@Component
public class PermissionMappingManager {
@Autowired
private PermissionMappingRepository permissionMappingRepository;
private QPermissionMapping qPermissionMapping = QPermissionMapping.permissionMapping;
/**
*
* @param item
* @return
*/
public List<PermissionMapping> getAllByItem(Integer item) {
return Lists.newArrayList(
permissionMappingRepository.findAll(qPermissionMapping.item.eq(item)));
}
/**
*
* @param name
* @return
*/
public List<PermissionMapping> getAllByName(String name) {
return Lists.newArrayList(
permissionMappingRepository.findAll(qPermissionMapping.names.contains(name)));
}
/**
*
* @param item
* @return
*/
public boolean exists(Integer item) {
return permissionMappingRepository.exists(qPermissionMapping.item.eq(item));
}
/**
*
* @param item
* @param name
* @return
*/
public boolean exists(Integer item, String name) {
return permissionMappingRepository.exists(
qPermissionMapping.item.eq(item).and(qPermissionMapping.names.contains(name)));
}
/**
*
* @param item
* @param names
* @param lifetime
* @param lifetimeUnit
* @param addon
* @param product
* @return
*/
public PermissionMapping create(Integer item, Set<String> names, Long lifetime,
ChronoUnit lifetimeUnit, boolean lifetimeRound, boolean addon, String product,
String startsQuestion, String expiresQuestion) {
for (String name : names) {
Assert.isTrue(!exists(item, name), "PermissionMapping for item '" + item
+ "' with permission '" + name + "' already exists!");
}
PermissionMapping permissionMapping = new PermissionMapping();
permissionMapping.setItem(item);
permissionMapping.setNames(names);
permissionMapping.setLifetime(lifetime);
permissionMapping.setLifetimeUnit(lifetimeUnit);
permissionMapping.setLifetimeRound(lifetimeRound);
permissionMapping.setAddon(addon);
permissionMapping.setProduct(product);
permissionMapping.setStartsQuestion(startsQuestion);
permissionMapping.setExpiresQuestion(expiresQuestion);
return permissionMappingRepository.save(permissionMapping);
}
/**
*
* @param permissionMapping
* @return
*/
public PermissionMapping update(PermissionMapping permissionMapping) {
return permissionMappingRepository.save(permissionMapping);
}
/**
*
* @param item
* @param name
*/
public void delete(Long id) {
Assert.isTrue(permissionMappingRepository.existsById(id),
"Permission Mapping '" + id + "' does not exists!");
PermissionMapping permissionMapping = permissionMappingRepository.findById(id).get();
permissionMappingRepository.delete(permissionMapping);
}
/**
*
* @param page
* @param size
* @param sortBy
* @param descending
* @return
*/
public Page<PermissionMapping> get(int page, int size, String sortBy, boolean descending) {
Sort sort = descending ? Sort.by(sortBy).descending() : Sort.by(sortBy).ascending();
return permissionMappingRepository.findAll(PageRequest.of(page, size, sort));
}
}
@@ -0,0 +1,18 @@
/**
*
*/
package de.bstly.we.businesslogic;
/**
* @author _bastler@bstly.de
*
*/
public interface Permissions {
public static final String ROLE_ADMIN = "ROLE_ADMIN";
public static final String ROLE_USER = "ROLE_USER";
public static final String ROLE_MEMBER = "ROLE_MEMBER";
public static final String ROLE_GUEST = "ROLE_GUEST";
public static final String MAIL = "mail";
}
@@ -0,0 +1,12 @@
/**
*
*/
package de.bstly.we.businesslogic;
/**
* @author _bastler@bstly.de
*
*/
public enum PretixItemStatus {
ERROR, NOT_FOUND, PENDING, PAID, EXPIRED, CANCELED, REDEEMED
}
@@ -0,0 +1,542 @@
/**
*
*/
package de.bstly.we.businesslogic;
import java.time.Instant;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.reactive.function.client.WebClientResponseException;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
/**
*
* @author _bastler@bstly.de
*
*/
@Component
public class PretixManager implements SmartInitializingSingleton {
public static final int invalid_item = -1;
private Logger logger = LoggerFactory.getLogger(PretixManager.class);
@Autowired
private Environment environment;
@Autowired
private SystemPropertyManager systemPropertyManager;
protected static Gson gson = new Gson();
public static final String SYSTEM_PROPERTY_PRETIX_HOST = "pretix.host";
public static final String SYSTEM_PROPERTY_PRETIX_TOKEN = "pretix.token";
public static final String SYSTEM_PROPERTY_PRETIX_ORGANIZER = "pretix.organizer";
public static final String SYSTEM_PROPERTY_PRETIX_EVENT = "pretix.event";
public static final String SYSTEM_PROPERTY_PRETIX_CHECKINLIST = "pretix.checkinlist";
public static final String SYSTEM_PROPERTY_PRETIX_QUOTA_REGISTRATIONS = "pretix.quota.registrations";
public static final String SYSTEM_PROPERTY_PRETIX_QUOTA_ADDONS = "pretix.quota.addons";
public static final String SYSTEM_PROPERTY_PRETIX_MEMBERSHIP_ITEM = "pretix.membership.item";
public static final String SYSTEM_PROPERTY_PRETIX_MEMBERSHIPFEE_ITEM = "pretix.membershipfee.item";
// membership ID management
public static final String SYSTEM_PROPERTY_PRETIX_MEMBERSHIP_ID_QUESTION = "pretix.membershipid.question";
public static final String SYSTEM_PROPERTY_PRETIX_MEMBERSHIPFEE_REFERENCE_QUESTION = "pretix.membershipfeereference.question";
public static final String SYSTEM_PROPERTY_PRETIX_MEMBERSHIPFEE_CODE_QUESTION = "pretix.membershipfeecode.question";
public static final String SYSTEM_PROPERTY_PRETIX_MEMBERSHIP_INTERNAL_ID_QUESTION = "pretix.membershipinternalid.question";
public static final String SYSTEM_PROPERTY_PRETIX_MEMBERSHIP_ACTIVE_QUESTION = "pretix.membershipactive.question";
public static final String SYSTEM_PROPERTY_PRETIX_MEMBERSHIP_DISCOUNT_PERIOD = "pretix.membership.discount.period";
public static final String SYSTEM_PROPERTY_PRETIX_MEMBERSHIPFEE_ORDER_DAYS = "pretix.membershipfee.order.days";
public static final String SYSTEM_PROPERTY_PRETIX_MEMBERSHIPFEE_REMINDER_DAYS = "pretix.membershipfee.reminder.days";
public static final String SYSTEM_PROPERTY_PRETIX_MEMBERSHIPFEE_REMINDER_QUESTION = "pretix.membershipfee.reminder.question";
public static final String SYSTEM_PROPERTY_PRETIX_ORDER_SENDMAIL = "pretix.order.sendmail";
public static final String SYSTEM_PROPERTY_PRETIX_ORDER_TESTMODE = "pretix.order.testmode";
public static final String SYSTEM_PROPERTY_PRETIX_ORDER_SIMULATE = "pretix.order.simulate";
public enum ITEM_STATUS {
ERROR, NOT_FOUND, PENDING, PAID, EXPIRED, CANCELED, REDEEMED
}
private String host;
private String token;
private String organizer;
private String event;
private String checkinlist;
private int quotaRegistration;
private int quotaAddons;
protected WebClient webClient;
/*
* @see org.springframework.beans.factory.SmartInitializingSingleton#
* afterSingletonsInstantiated()
*/
@Override
public void afterSingletonsInstantiated() {
if (!systemPropertyManager.has(SYSTEM_PROPERTY_PRETIX_HOST)) {
systemPropertyManager.add(SYSTEM_PROPERTY_PRETIX_HOST,
environment.getProperty("we.bstly." + SYSTEM_PROPERTY_PRETIX_HOST, ""));
}
if (!systemPropertyManager.has(SYSTEM_PROPERTY_PRETIX_TOKEN)) {
systemPropertyManager.add(SYSTEM_PROPERTY_PRETIX_TOKEN,
environment.getProperty("we.bstly." + SYSTEM_PROPERTY_PRETIX_TOKEN, ""));
}
if (!systemPropertyManager.has(SYSTEM_PROPERTY_PRETIX_ORGANIZER)) {
systemPropertyManager.add(SYSTEM_PROPERTY_PRETIX_ORGANIZER,
environment.getProperty("we.bstly." + SYSTEM_PROPERTY_PRETIX_ORGANIZER, ""));
}
if (!systemPropertyManager.has(SYSTEM_PROPERTY_PRETIX_EVENT)) {
systemPropertyManager.add(SYSTEM_PROPERTY_PRETIX_EVENT,
environment.getProperty("we.bstly." + SYSTEM_PROPERTY_PRETIX_EVENT, ""));
}
if (!systemPropertyManager.has(SYSTEM_PROPERTY_PRETIX_CHECKINLIST)) {
systemPropertyManager.add(SYSTEM_PROPERTY_PRETIX_CHECKINLIST,
environment.getProperty("we.bstly." + SYSTEM_PROPERTY_PRETIX_CHECKINLIST, ""));
}
if (!systemPropertyManager.has(SYSTEM_PROPERTY_PRETIX_QUOTA_REGISTRATIONS)) {
systemPropertyManager.add(SYSTEM_PROPERTY_PRETIX_QUOTA_REGISTRATIONS, environment
.getProperty("we.bstly." + SYSTEM_PROPERTY_PRETIX_QUOTA_REGISTRATIONS, "0"));
}
if (!systemPropertyManager.has(SYSTEM_PROPERTY_PRETIX_QUOTA_ADDONS)) {
systemPropertyManager.add(SYSTEM_PROPERTY_PRETIX_QUOTA_ADDONS, environment
.getProperty("we.bstly." + SYSTEM_PROPERTY_PRETIX_QUOTA_ADDONS, "0"));
}
if (!systemPropertyManager.has(SYSTEM_PROPERTY_PRETIX_MEMBERSHIP_ITEM)) {
systemPropertyManager.add(SYSTEM_PROPERTY_PRETIX_MEMBERSHIP_ITEM, environment
.getProperty("we.bstly." + SYSTEM_PROPERTY_PRETIX_MEMBERSHIP_ITEM, "0"));
}
if (!systemPropertyManager.has(SYSTEM_PROPERTY_PRETIX_MEMBERSHIPFEE_ITEM)) {
systemPropertyManager.add(SYSTEM_PROPERTY_PRETIX_MEMBERSHIPFEE_ITEM, environment
.getProperty("we.bstly." + SYSTEM_PROPERTY_PRETIX_MEMBERSHIPFEE_ITEM, "0"));
}
buildWebClient();
}
/**
*
*/
public void buildWebClient() {
host = systemPropertyManager.get(SYSTEM_PROPERTY_PRETIX_HOST);
token = systemPropertyManager.get(SYSTEM_PROPERTY_PRETIX_TOKEN);
organizer = systemPropertyManager.get(SYSTEM_PROPERTY_PRETIX_ORGANIZER);
event = systemPropertyManager.get(SYSTEM_PROPERTY_PRETIX_EVENT);
checkinlist = systemPropertyManager.get(SYSTEM_PROPERTY_PRETIX_CHECKINLIST);
quotaRegistration = systemPropertyManager
.getInteger(SYSTEM_PROPERTY_PRETIX_QUOTA_REGISTRATIONS);
quotaAddons = systemPropertyManager.getInteger(SYSTEM_PROPERTY_PRETIX_QUOTA_ADDONS);
webClient = WebClient.builder().baseUrl(host)
.defaultHeader(HttpHeaders.CONTENT_TYPE, "application/json")
.defaultHeader(HttpHeaders.AUTHORIZATION, "Token " + token).build();
}
/**
*
* @param secret
* @return
*/
public ITEM_STATUS getItemStatus(String secret) {
try {
JsonObject item = getCheckInItemBySecret(secret);
if (item != null) {
if (item.get("secret").getAsString().equals(secret)) {
if (item.getAsJsonArray("checkins").size() < 1
&& "p".equals(item.get("order__status").getAsString())) {
return ITEM_STATUS.PAID;
} else if (item.getAsJsonArray("checkins").size() > 0) {
return ITEM_STATUS.REDEEMED;
}
} else {
return ITEM_STATUS.ERROR;
}
} else {
item = getOrderBySecret(secret);
if (item != null) {
logger.warn("Checked secret: '" + secret + "' without valid payment!");
return ITEM_STATUS.ERROR;
}
}
return ITEM_STATUS.NOT_FOUND;
} catch (WebClientResponseException e) {
return ITEM_STATUS.ERROR;
}
}
/**
*
* @param secret
* @return
*/
public JsonObject getCheckInItemBySecret(String secret) {
MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<String, String>();
queryParams.add("secret", secret);
JsonObject orderPositions = request(
String.format("/api/v1/organizers/%s/events/%s/checkinlists/%s/positions/",
organizer, event, checkinlist),
HttpMethod.GET, queryParams).getAsJsonObject();
JsonArray results = orderPositions.getAsJsonArray("results");
if (results.size() == 1) {
return results.get(0).getAsJsonObject();
}
return null;
}
/**
*
* @param code
* @return
*/
public JsonObject getOrder(String code) {
return request(
String.format("/api/v1/organizers/%s/events/%s/orders/%s/", organizer, event, code),
HttpMethod.GET).getAsJsonObject();
}
/**
*
* @param secret
* @return
*/
public JsonObject getOrderBySecret(String secret) {
MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<String, String>();
queryParams.add("secret", secret);
JsonObject orderPositions = request(
String.format("/api/v1/organizers/%s/events/%s/orderpositions/", organizer, event),
HttpMethod.GET, queryParams).getAsJsonObject();
JsonArray results = orderPositions.getAsJsonArray("results");
if (results.size() == 1) {
JsonObject orderPosition = results.get(0).getAsJsonObject();
return request(String.format("/api/v1/organizers/%s/events/%s/orders/%s/", organizer,
event, orderPosition.get("order").getAsString()), HttpMethod.GET)
.getAsJsonObject();
}
return null;
}
/**
*
* @param order
* @return
*/
public JsonObject createOrder(JsonObject order) {
return request(String.format("/api/v1/organizers/%s/events/%s/orders/", organizer, event),
HttpMethod.POST, order).getAsJsonObject();
}
/**
*
* @param order
* @return
*/
public JsonObject extendOrder(String code, JsonObject expire) {
return request(String.format("/api/v1/organizers/%s/events/%s/orders/%s/extend/", organizer,
event, code), HttpMethod.POST, expire).getAsJsonObject();
}
/**
*
* @param code
*/
public void sendEmail(String code) {
request(String.format("/api/v1/organizers/%s/events/%s/orders/%s/resend_link/", organizer,
event, code), HttpMethod.POST);
}
/**
*
* @param secret
* @return
*/
public Instant getLastPaymentDateBySecret(String secret) {
MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<String, String>();
queryParams.add("secret", secret);
JsonObject orderPositions = request(
String.format("/api/v1/organizers/%s/events/%s/orderpositions/", organizer, event),
HttpMethod.GET, queryParams).getAsJsonObject();
JsonArray results = orderPositions.getAsJsonArray("results");
if (results.size() == 1) {
JsonObject orderPosition = results.get(0).getAsJsonObject();
return getLastPaymentDateForOrder(orderPosition.get("order").getAsString());
}
return null;
}
/**
*
* @param secret
* @return
*/
public Instant getLastPaymentDateForOrder(String order) {
JsonArray paymentResults = request(
String.format("/api/v1/organizers/%s/events/%s/orders/%s/payments/", organizer,
event, order),
HttpMethod.GET).getAsJsonObject().getAsJsonArray("results");
Instant lastDate = null;
for (JsonElement element : paymentResults) {
JsonObject payment = element.getAsJsonObject();
if ("confirmed".equalsIgnoreCase(payment.get("state").getAsString())) {
Instant currentDate = Instant.parse(payment.get("payment_date").getAsString());
if (lastDate == null) {
lastDate = currentDate;
} else if (currentDate.isAfter(lastDate)) {
lastDate = currentDate;
}
}
}
return lastDate;
}
/**
*
* @param secret
* @return
*/
public JsonObject getCheckInItemByItem(Integer item) {
MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<String, String>();
queryParams.add("item", String.valueOf(item));
JsonObject orderPositions = request(
String.format("/api/v1/organizers/%s/events/%s/checkinlists/%s/positions/",
organizer, event, checkinlist),
HttpMethod.GET, queryParams).getAsJsonObject();
JsonArray results = orderPositions.getAsJsonArray("results");
if (results.size() == 1) {
return results.get(0).getAsJsonObject();
}
return null;
}
/**
*
* @param secret
* @return
*/
public JsonObject redeemItem(String secret) {
if (getItemStatus(secret) == ITEM_STATUS.PAID) {
JsonObject checkIn = getCheckInPositions(secret);
return redeem(checkIn.get("id").getAsString());
}
return null;
}
/**
*
* @param idOrSecret
* @return
*/
public JsonObject getCheckInPositions(String idOrSecret) {
return request(
String.format("/api/v1/organizers/%s/events/%s/checkinlists/%s/positions/%s/",
organizer, event, checkinlist, idOrSecret),
HttpMethod.GET).getAsJsonObject();
}
/**
*
* @param idOrSecret
* @return
*/
public JsonObject redeem(String idOrSecret) {
return request(String.format(
"/api/v1/organizers/%s/events/%s/checkinlists/%s/positions/%s/redeem/", organizer,
event, checkinlist, idOrSecret), HttpMethod.POST).getAsJsonObject();
}
/**
*
* @return
*/
public JsonObject createRegistrationVoucher() {
return createVoucher(quotaRegistration);
}
/**
*
* @return
*/
public JsonObject createAddOnVoucher() {
return createVoucher(quotaAddons);
}
/**
*
* @param quotaId
* @return
*/
public JsonObject createVoucher(int quotaId) {
JsonObject voucher = new JsonObject();
voucher.addProperty("max_usages", 1);
voucher.addProperty("quota", quotaId);
voucher.addProperty("block_quota", true);
return request(String.format("/api/v1/organizers/%s/events/%s/vouchers/", organizer, event),
HttpMethod.POST, voucher).getAsJsonObject();
}
/**
*
* @param secret
* @return
*/
public JsonObject getItem(Integer item) {
return request(
String.format("/api/v1/organizers/%s/events/%s/items/%s/", organizer, event, item),
HttpMethod.GET).getAsJsonObject();
}
public JsonArray getVariations(Integer item) {
return request(String.format("/api/v1/organizers/%s/events/%s/items/%s/variations/",
organizer, event, item), HttpMethod.GET).getAsJsonObject()
.getAsJsonArray("results");
}
/**
*
* @param item
* @param variationId
* @param variation
*/
public void updateVariation(Integer item, Integer variationId, JsonObject variation) {
request(String.format("/api/v1/organizers/%s/events/%s/items/%s/variations/%s/", organizer,
event, item, variationId), HttpMethod.PATCH, variation);
}
/**
*
* @param item
* @param variation
*/
public void deleteVariation(Integer item, Integer variation) {
request(String.format("/api/v1/organizers/%s/events/%s/items/%s/variations/%s/", organizer,
event, item, variation), HttpMethod.DELETE);
}
/**
*
* @param item
*/
public void deleteVariations(Integer item) {
for (JsonElement variationElement : getVariations(item)) {
JsonObject variation = variationElement.getAsJsonObject();
deleteVariation(item, variation.get("id").getAsInt());
}
}
/**
*
* @param path
* @param method
* @return
*/
public JsonElement request(String path, HttpMethod method) {
return request(path, method, null, new LinkedMultiValueMap<String, String>());
}
/**
*
* @param path
* @param method
* @param queryParameters
* @return
*/
public JsonElement request(String path, HttpMethod method,
MultiValueMap<String, String> queryParameters) {
return request(path, method, null, queryParameters);
}
/**
*
* @param path
* @param method
* @param queryParameters
* @return
*/
public JsonElement request(String path, HttpMethod method, JsonElement payload) {
return request(path, method, payload, new LinkedMultiValueMap<String, String>());
}
/**
*
* @param path
* @param payload
* @param method
* @param queryParameters
* @return
*/
public JsonElement request(String path, HttpMethod method, JsonElement payload,
MultiValueMap<String, String> queryParameters) {
WebClient.RequestBodySpec request = webClient.method(method)
.uri(uriBuilder -> uriBuilder.path(path).queryParams(queryParameters).build());
if (payload != null) {
request.bodyValue(gson.toJson(payload));
}
String jsonString = request.retrieve().bodyToMono(String.class).block();
if (StringUtils.hasText(jsonString)) {
return JsonParser.parseString(jsonString);
}
return null;
}
/**
* @return the organizer
*/
public String getOrganizer() {
return organizer;
}
/**
* @return the event
*/
public String getEvent() {
return event;
}
/**
* @return the checkinlist
*/
public String getCheckinlist() {
return checkinlist;
}
}
@@ -0,0 +1,233 @@
/**
*
*/
package de.bstly.we.businesslogic;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import com.google.common.collect.Lists;
import de.bstly.we.model.QQuota;
import de.bstly.we.model.Quota;
import de.bstly.we.model.QuotaMapping;
import de.bstly.we.model.UserData;
import de.bstly.we.repository.QuotaRepository;
/**
*
* @author _bastler@bstly.de
*
*/
@Component
public class QuotaManager implements UserDataProvider {
@Autowired
private QuotaRepository quotaRepository;
@Autowired
private QuotaMappingManager quotaMappingManager;
private QQuota qQuota = QQuota.quota;
/**
*
* @param target
* @param name
* @return
*/
public Quota get(Long target, String name) {
if (target != null && name != null) {
return quotaRepository.findOne(qQuota.name.eq(name).and(qQuota.target.eq(target)))
.orElse(null);
}
return null;
}
/**
*
* @param name
* @return
*/
public List<Quota> getAllByName(String name) {
return Lists.newArrayList(quotaRepository.findAll(qQuota.name.eq(name)));
}
/**
*
* @param target
* @return
*/
public List<Quota> getAllByTarget(Long target) {
if (target != null) {
return Lists.newArrayList(quotaRepository.findAll(qQuota.target.eq(target)));
}
return Lists.newArrayList();
}
/**
*
* @param target
* @return
*/
public List<Quota> getNotExpiresByTarget(Long target) {
if (target != null) {
return Lists.newArrayList(
quotaRepository.findAll(qQuota.target.eq(target).and(qQuota.value.gt(0))));
}
return Lists.newArrayList();
}
/**
*
* @param target
* @param name
* @return
*/
public boolean hasQuota(Long target, String name) {
return target != null && quotaRepository
.exists(qQuota.name.eq(name).and(qQuota.target.eq(target)).and(qQuota.value.gt(0)));
}
/**
*
* @param target
* @param name
* @param addon
* @param value
* @param unit
* @return
*/
public Quota create(Long target, String name, long value, String unit, boolean disposable) {
Quota newQuota = new Quota();
newQuota.setTarget(target);
newQuota.setName(name);
newQuota.setValue(value);
newQuota.setUnit(unit);
newQuota.setDisposable(disposable);
return quotaRepository.save(newQuota);
}
/**
*
* @param quota
* @return
*/
public Quota update(Quota quota) {
Assert.isTrue(
quotaRepository.exists(
qQuota.target.eq(quota.getTarget()).and(qQuota.name.eq(quota.getName()))),
"Quota '" + quota.getName() + "' for target + '" + quota.getTarget()
+ "' not exists!");
Quota updateQuota = quotaRepository
.findOne(qQuota.target.eq(quota.getTarget()).and(qQuota.name.eq(quota.getName())))
.get();
updateQuota.setValue(quota.getValue());
updateQuota.setUnit(quota.getUnit());
updateQuota.setDisposable(quota.isDisposable());
return quotaRepository.save(updateQuota);
}
/**
*
* @param name
* @param clone
* @return
*/
public List<Quota> clone(String name, String clone, long value) {
List<Quota> quotas = Lists.newArrayList();
for (Quota quota : quotaRepository.findAll(qQuota.name.eq(name))) {
if (!quotaRepository
.exists(qQuota.name.eq(clone).and(qQuota.target.eq(quota.getTarget())))) {
quotas.add(create(quota.getTarget(), clone, value >= 0 ? value : quota.getValue(),
quota.getUnit(), quota.isDisposable()));
}
}
return quotas;
}
/**
*
* @param target
* @param name
*/
public void delete(Long target, String name) {
Assert.isTrue(quotaRepository.exists(qQuota.target.eq(target).and(qQuota.name.eq(name))),
"Quota '" + name + "' for target + '" + target + "' not exists!");
Quota delete = quotaRepository.findOne(qQuota.target.eq(target).and(qQuota.name.eq(name)))
.get();
quotaRepository.delete(delete);
}
/**
*
* @param target
*/
public void deleteAll(Long target) {
quotaRepository.deleteAll(quotaRepository.findAll(qQuota.target.eq(target)));
}
/**
*
* @param name
*/
public void deleteAll(String name) {
quotaRepository.deleteAll(quotaRepository.findAll(qQuota.name.eq(name)));
}
/**
*
* @param target
* @param item
*/
public void applyItem(Long target, Integer item) {
for (QuotaMapping quotaMapping : quotaMappingManager.getAllByItem(item)) {
Quota quota = get(target, quotaMapping.getName());
if (quota == null) {
quota = create(target, quotaMapping.getName(), quotaMapping.getValue(),
quotaMapping.getUnit(), quotaMapping.isDisposable());
} else {
quota.setValue(quotaMapping.isAppend() ? quota.getValue() + quotaMapping.getValue()
: quotaMapping.getValue());
quota = update(quota);
}
}
}
/*
* @see de.bstly.we.businesslogic.UserDataProvider#getId()
*/
@Override
public String getId() {
return "quotas";
}
/*
* @see de.bstly.we.businesslogic.UserDataProvider#getUserData(java.lang.Long)
*/
@Override
public List<UserData> getUserData(Long userId) {
List<UserData> result = Lists.newArrayList();
for (Quota quota : getAllByTarget(userId)) {
result.add(quota);
}
return result;
}
/*
* @see de.bstly.we.businesslogic.UserDataProvider#purgeUserData(java.lang.Long)
*/
@Override
public void purgeUserData(Long userId) {
for (Quota quota : getAllByTarget(userId)) {
quotaRepository.delete(quota);
}
}
}
@@ -0,0 +1,134 @@
/**
*
*/
package de.bstly.we.businesslogic;
import java.util.List;
import java.util.Set;
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 com.google.common.collect.Lists;
import de.bstly.we.model.QQuotaMapping;
import de.bstly.we.model.QuotaMapping;
import de.bstly.we.repository.QuotaMappingRepository;
/**
*
* @author _bastler@bstly.de
*
*/
@Component
public class QuotaMappingManager {
@Autowired
private QuotaMappingRepository quotaMappingRepository;
private QQuotaMapping qQuotaMapping = QQuotaMapping.quotaMapping;
/**
*
* @param item
* @return
*/
public List<QuotaMapping> getAllByItem(Integer item) {
return Lists
.newArrayList(quotaMappingRepository.findAll(qQuotaMapping.items.contains(item)));
}
/**
*
* @param item
* @return
*/
public boolean exists(Integer item) {
return quotaMappingRepository.exists(qQuotaMapping.items.contains(item));
}
/**
*
* @param item
* @param name
* @return
*/
public boolean exists(Integer item, String name) {
return quotaMappingRepository
.exists(qQuotaMapping.items.contains(item).and(qQuotaMapping.name.eq(name)));
}
/**
*
* @param item
* @param quota
* @param lifetime
* @return
*/
public QuotaMapping create(Set<Integer> items, String name, long value, String unit,
boolean append, Set<String> products, boolean disposable) {
for (Integer item : items) {
Assert.isTrue(!exists(item, name), "QuotaMapping for item '" + item + "' with quota '"
+ name + "' already exists!");
}
QuotaMapping quotaMapping = new QuotaMapping();
quotaMapping.setItems(items);
quotaMapping.setName(name);
quotaMapping.setValue(value);
quotaMapping.setUnit(unit);
quotaMapping.setAppend(append);
quotaMapping.setProducts(products);
quotaMapping.setDisposable(disposable);
return quotaMappingRepository.save(quotaMapping);
}
/**
*
* @param quotaMapping
* @return
*/
public QuotaMapping update(QuotaMapping quotaMapping) {
Assert.isTrue(
quotaMapping.getId() != null
&& quotaMappingRepository.existsById(quotaMapping.getId()),
"QuotaMapping '" + quotaMapping.getId() + "' does not exists!");
QuotaMapping updateQuotaMapping = quotaMappingRepository.findById(quotaMapping.getId())
.get();
updateQuotaMapping.setProducts(quotaMapping.getProducts());
updateQuotaMapping.setItems(quotaMapping.getItems());
updateQuotaMapping.setValue(quotaMapping.getValue());
updateQuotaMapping.setUnit(quotaMapping.getUnit());
updateQuotaMapping.setAppend(quotaMapping.isAppend());
updateQuotaMapping.setDisposable(quotaMapping.isDisposable());
return quotaMappingRepository.save(updateQuotaMapping);
}
/**
*
* @param item
* @param name
*/
public void delete(Long id) {
Assert.isTrue(quotaMappingRepository.existsById(id),
"QuotaMapping '" + id + "' does not exists!");
quotaMappingRepository.deleteById(id);
}
/**
*
* @param page
* @param size
* @param sortBy
* @param descending
* @return
*/
public Page<QuotaMapping> get(int page, int size, String sortBy, boolean descending) {
Sort sort = descending ? Sort.by(sortBy).descending() : Sort.by(sortBy).ascending();
return quotaMappingRepository.findAll(PageRequest.of(page, size, sort));
}
}
@@ -0,0 +1,15 @@
/**
*
*/
package de.bstly.we.businesslogic;
/**
* @author _bastler@bstly.de
*
*/
public interface Quotas {
public static final String REGISTRATION_VOUCHERS = "registration_vouchers";
public static final String ALIAS_CREATION = "alias_creation";
}
+107
View File
@@ -0,0 +1,107 @@
/**
*
*/
package de.bstly.we.businesslogic;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.List;
import org.apache.commons.lang3.RandomStringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import com.google.common.collect.Lists;
import de.bstly.we.businesslogic.support.InstantHelper;
import de.bstly.we.controller.validation.UserModelValidator;
import de.bstly.we.model.User;
import de.bstly.we.model.UserStatus;
/**
*
* @author _bastler@bstly.de
*
*/
@Component
public class Setup implements SmartInitializingSingleton {
@Autowired
private UserManager userManager;
@Autowired
private PermissionManager permissionManager;
@Autowired
private ResourceLoader resourceLoader;
@Autowired
private SystemPropertyManager systemPropertyManager;
protected static final long TAUSEND_JAHRE = 1000;
@Value("${we.bstly.admin.password:}")
private String adminPassword;
@Value("${we.bstly.setup:true}")
private boolean setup;
private Logger logger = LoggerFactory.getLogger(Setup.class);
/*
* @see org.springframework.beans.factory.SmartInitializingSingleton#
* afterSingletonsInstantiated()
*/
@Override
public void afterSingletonsInstantiated() {
// create admin account if not found
if (!setup || !systemPropertyManager.has("setup")) {
if (!StringUtils.hasText(adminPassword)) {
adminPassword = RandomStringUtils.random(24, true, true);
logger.error("password for 'admin': " + adminPassword);
}
User admin = userManager.create("admin", adminPassword, UserStatus.SLEEP);
permissionManager.create(admin.getId(), Permissions.ROLE_ADMIN, false, null,
InstantHelper.plus(Instant.now(), TAUSEND_JAHRE, ChronoUnit.YEARS));
systemPropertyManager.add("setup", "true");
}
try {
Resource resource = resourceLoader.getResource("classpath:usernames.txt");
if (resource.exists()) {
BufferedReader br = new BufferedReader(
new InputStreamReader(resource.getInputStream()));
List<String> usernames = Lists.newArrayList();
String line;
while ((line = br.readLine()) != null) {
if (StringUtils.hasText(line) && !usernames.contains(line)
&& !line.startsWith("#")) {
usernames.add(line);
}
}
if (systemPropertyManager.has(UserModelValidator.RESERVED_USERNAMES)) {
systemPropertyManager.update(UserModelValidator.RESERVED_USERNAMES,
org.apache.commons.lang3.StringUtils.join(usernames, ","));
} else {
systemPropertyManager.add(UserModelValidator.RESERVED_USERNAMES,
org.apache.commons.lang3.StringUtils.join(usernames, ","));
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
@@ -0,0 +1,64 @@
/**
*
*/
package de.bstly.we.businesslogic;
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 de.bstly.we.model.SystemProfileField;
import de.bstly.we.repository.SystemProfileFieldRepository;
/**
* @author _bastler@bstly.de
*
*/
@Component
public class SystemProfileFieldManager {
@Autowired
private SystemProfileFieldRepository systemProfileFieldRepository;
/**
*
* @param systemProfileField
* @return
*/
public SystemProfileField save(SystemProfileField systemProfileField) {
return systemProfileFieldRepository.save(systemProfileField);
}
/**
*
* @param name
* @return
*/
public SystemProfileField get(String name) {
return systemProfileFieldRepository.findById(name).orElse(null);
}
/**
*
* @param page
* @param size
* @param sortBy
* @param descending
* @return
*/
public Page<SystemProfileField> get(int page, int size, String sortBy, boolean descending) {
Sort sort = descending ? Sort.by(sortBy).descending() : Sort.by(sortBy).ascending();
return systemProfileFieldRepository.findAll(PageRequest.of(page, size, sort));
}
/**
*
* @param name
*/
public void delete(String name) {
systemProfileFieldRepository.deleteById(name);
}
}
@@ -0,0 +1,133 @@
/**
*
*/
package de.bstly.we.businesslogic;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import de.bstly.we.model.SystemProperty;
import de.bstly.we.repository.SystemPropertyRepository;
/**
*
* @author _bastler@bstly.de
*
*/
@Component
public class SystemPropertyManager {
@Autowired
private SystemPropertyRepository systemPropertyRepository;
/**
*
* @param key
* @return
*/
public boolean has(String key) {
return systemPropertyRepository.existsById(key);
}
/**
*
* @param key
* @return
*/
public String get(String key) {
return systemPropertyRepository.findById(key).orElse(new SystemProperty()).getValue();
}
/**
*
* @param key
* @param defaultValue
* @return
*/
public String get(String key, String defaultValue) {
return systemPropertyRepository.findById(key).orElse(new SystemProperty(key, defaultValue)).getValue();
}
/**
*
* @param key
* @return
*/
public boolean getBoolean(String key) {
return getBoolean(key, false);
}
/**
*
* @param key
* @param defaultValue
* @return
*/
public boolean getBoolean(String key, boolean defaultValue) {
return Boolean.valueOf(get(key, String.valueOf(defaultValue)));
}
/**
*
* @param key
* @return
*/
public int getInteger(String key) {
return getInteger(key, 0);
}
/**
*
* @param key
* @param defaultValue
* @return
*/
public int getInteger(String key, int defaultValue) {
return Integer.valueOf(get(key, String.valueOf(defaultValue)));
}
/**
*
* @param key
* @return
*/
public long getLong(String key) {
return getLong(key, 0L);
}
/**
*
* @param key
* @param defaultValue
* @return
*/
public long getLong(String key, long defaultValue) {
return Long.valueOf(get(key, String.valueOf(defaultValue)));
}
/**
*
* @param key
* @param value
*/
public void add(String key, String value) {
Assert.isTrue(!systemPropertyRepository.existsById(key),
"System Property already exists, use update method to change value!");
systemPropertyRepository.save(new SystemProperty(key, value));
}
/**
*
* @param key
* @param value
*/
public void update(String key, String value) {
Assert.isTrue(systemPropertyRepository.existsById(key),
"System Property does not exists, use add method to add new!");
SystemProperty systemProperty = systemPropertyRepository.findById(key).get();
systemProperty.setValue(value);
systemPropertyRepository.save(systemProperty);
}
}
@@ -0,0 +1,128 @@
/**
*
*/
package de.bstly.we.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 com.google.common.collect.Lists;
import de.bstly.we.model.QUserAlias;
import de.bstly.we.model.UserAlias;
import de.bstly.we.model.UserData;
import de.bstly.we.repository.UserAliasRepository;
/**
* @author _bastler@bstly.de
*
*/
@Component
public class UserAliasManager implements UserDataProvider {
@Autowired
private UserManager userManager;
@Autowired
private UserAliasRepository userAliasRepository;
private QUserAlias qUserAlias = QUserAlias.userAlias;
/**
*
* @param id
* @return
*/
public UserAlias get(Long id) {
return userAliasRepository.findById(id).orElse(null);
}
/**
*
* @param userAlias
* @return
*/
public UserAlias save(UserAlias userAlias) {
Assert.notNull(userAlias.getAlias(), "No alias defined!");
Assert.notNull(userAlias.getTarget(), "No target defined!");
Assert.notNull(userManager.get(userAlias.getTarget()), "Invalid target defined!");
return userAliasRepository.save(userAlias);
}
/**
*
* @param alias
* @return
*/
public UserAlias getByAlias(String alias) {
return userAliasRepository.findOne(qUserAlias.alias.eq(alias)).orElse(null);
}
/**
*
* @param userId
* @return
*/
public List<UserAlias> getAllByTarget(Long userId) {
return Lists.newArrayList(userAliasRepository.findAll(qUserAlias.target.eq(userId)));
}
/**
*
* @param id
*/
public void delete(Long id) {
UserAlias userAlias = get(id);
if (userAlias != null) {
userAliasRepository.delete(userAlias);
}
}
/**
*
* @param page
* @param size
* @param sortBy
* @param descending
* @return
*/
public Page<UserAlias> get(int page, int size, String sortBy, boolean descending) {
Sort sort = descending ? Sort.by(sortBy).descending() : Sort.by(sortBy).ascending();
return userAliasRepository.findAll(PageRequest.of(page, size, sort));
}
/*
* @see de.bstly.we.businesslogic.UserDataProvider#getId()
*/
@Override
public String getId() {
return "aliases";
}
/*
* @see de.bstly.we.businesslogic.UserDataProvider#getUserData(java.lang.Long)
*/
@Override
public List<UserData> getUserData(Long userId) {
List<UserData> result = Lists.newArrayList();
for (UserAlias userAlias : getAllByTarget(userId)) {
result.add(userAlias);
}
return result;
}
/*
* @see de.bstly.we.businesslogic.UserDataProvider#purgeUserData(java.lang.Long)
*/
@Override
public void purgeUserData(Long userId) {
for (UserAlias userAlias : getAllByTarget(userId)) {
userAliasRepository.delete(userAlias);
}
}
}
@@ -0,0 +1,181 @@
/**
*
*/
package de.bstly.we.businesslogic;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import com.beust.jcommander.internal.Maps;
import com.google.common.collect.Lists;
import com.google.gson.Gson;
import de.bstly.we.model.Permission;
import de.bstly.we.model.User;
import de.bstly.we.model.UserData;
import de.bstly.we.model.UserStatus;
import de.bstly.we.repository.UserRepository;
/**
* @author _bastler@bstly.de
*
*/
@Component
public class UserDataManager implements SmartInitializingSingleton {
@Autowired
private ApplicationContext context;
public static final String SYSTEM_PROPERTY_USERDATA_DAYS = "userdata.days";
public static final long SYSTEM_PROPERTY_USERDATA_DAYS_DEFAULT = 30;
private Logger logger = LoggerFactory.getLogger(UserDataManager.class);
@Autowired
private UserRepository userRepository;
@Autowired
private PermissionManager permissionManager;
@Autowired
private SystemPropertyManager systemPropertyManager;
@Value("${we.bstly.userdata.purge:false}")
private boolean purge;
/**
* UserData Provider
*/
private List<UserDataProvider> providers;
private Gson gson = new Gson();
/*
* @see org.springframework.beans.factory.SmartInitializingSingleton#
* afterSingletonsInstantiated()
*/
@Override
public void afterSingletonsInstantiated() {
providers = Lists.newArrayList();
for (UserDataProvider provider : context.getBeansOfType(UserDataProvider.class).values()) {
providers.add(provider);
}
}
/**
*
*/
@Scheduled(cron = "${we.bstly.userdata.cron:0 0 0 * * * }")
public void purge() {
long days = systemPropertyManager.getLong(SYSTEM_PROPERTY_USERDATA_DAYS,
SYSTEM_PROPERTY_USERDATA_DAYS_DEFAULT);
Pageable pageable = PageRequest.of(0, 100, Sort.by("id"));
Page<User> page;
do {
page = userRepository.findAll(pageable);
for (User user : page.getContent()) {
if (!UserStatus.SLEEP.equals(user.getStatus())) {
if (permissionManager.getNotExpiresByTargetIgnoreStart(user.getId())
.isEmpty()) {
if (UserStatus.PURGE.equals(user.getStatus())) {
purge(user, !purge);
} else if (UserStatus.NORMAL.equals(user.getStatus())) {
Instant last = Instant.MIN;
for (Permission permission : permissionManager
.getAllByTarget(user.getId())) {
if (permission.getExpires().isAfter(last)) {
last = permission.getExpires();
}
}
if (Instant.now().minus(days, ChronoUnit.DAYS).isAfter(last)) {
purge(user, !purge);
}
}
}
}
}
pageable = page.nextPageable();
} while (page.hasNext());
}
/**
*
* @param username
*/
public void purge(User user, boolean dry) {
Long userId = user.getId();
if (dry) {
logger.debug("Would purge all data of user '" + user.getUsername() + "' [id="
+ user.getId() + "]!");
} else {
logger.warn("Purge all data of user '" + user.getUsername() + "' [id=" + user.getId()
+ "]!");
}
for (UserDataProvider provider : providers) {
if (dry) {
List<UserData> result = provider.getUserData(userId);
if (!result.isEmpty()) {
logger.debug("\tWould have purged '" + provider.getId() + "' data of user '"
+ user.getUsername() + "' [id=" + user.getId() + "]!");
if (logger.isTraceEnabled()) {
for (UserData userData : result) {
logger.trace("\t\t" + gson.toJson(userData));
}
}
}
} else {
List<UserData> result = provider.getUserData(userId);
if (!result.isEmpty()) {
logger.warn("\tPurge '" + provider.getId() + "' data of user '"
+ user.getUsername() + "' [id=" + user.getId() + "]!");
if (logger.isTraceEnabled()) {
for (UserData userData : result) {
logger.trace("\t\t" + gson.toJson(userData));
}
}
provider.purgeUserData(userId);
}
}
}
if (!dry) {
logger.warn("Purged all data of user '" + user.getUsername() + "' [id=" + user.getId()
+ "]!");
}
}
/**
*
* @param userId
* @return
*/
public Map<String, List<UserData>> get(Long userId) {
Map<String, List<UserData>> userData = Maps.newHashMap();
for (UserDataProvider provider : providers) {
List<UserData> result = provider.getUserData(userId);
if (!result.isEmpty()) {
userData.put(provider.getId(), result);
}
}
return userData;
}
}
@@ -0,0 +1,36 @@
/**
*
*/
package de.bstly.we.businesslogic;
import java.util.List;
import de.bstly.we.model.UserData;
/**
* @author _bastler@bstly.de
*
*/
public interface UserDataProvider {
/**
*
* @return
*/
String getId();
/**
*
* @param userId
* @return
*/
List<UserData> getUserData(Long userId);
/**
*
* @param userId
* @return
*/
void purgeUserData(Long userId);
}
@@ -0,0 +1,202 @@
/**
*
*/
package de.bstly.we.businesslogic;
import java.util.Hashtable;
import java.util.List;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.InitialDirContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.scheduling.annotation.Scheduled;
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.model.QUserDomain;
import de.bstly.we.model.UserData;
import de.bstly.we.model.UserDomain;
import de.bstly.we.repository.UserDomainRepository;
/**
* @author _bastler@bstly.de
*
*/
@Component
public class UserDomainManager implements UserDataProvider {
public static final int DEFAULT_SECRET_LENGTH = 64;
@Autowired
private UserManager userManager;
@Autowired
private UserDomainRepository userDomainRepository;
private QUserDomain qUserDomain = QUserDomain.userDomain;
private InitialDirContext dirContext;
/**
*
*/
public UserDomainManager() {
Hashtable<String, String> env = new Hashtable<String, String>();
env.put("java.naming.factory.initial", "com.sun.jndi.dns.DnsContextFactory");
env.put("java.naming.provider.url", "dns:");
try {
dirContext = new InitialDirContext(env);
} catch (NamingException e) {
e.printStackTrace();
throw new RuntimeException("Could not crate InitialDirContext");
}
}
/**
*
* @param id
* @return
*/
public UserDomain get(Long id) {
return userDomainRepository.findById(id).orElse(null);
}
/**
*
* @param userDomain
* @return
*/
public UserDomain save(UserDomain userDomain) {
Assert.notNull(userDomain.getDomain(), "No domain defined!");
Assert.notNull(userDomain.getTarget(), "No target defined!");
Assert.notNull(userManager.get(userDomain.getTarget()), "Invalid target defined!");
return userDomainRepository.save(userDomain);
}
/**
*
* @param domain
* @return
*/
public UserDomain getByDomain(String domain) {
return userDomainRepository.findOne(qUserDomain.domain.eq(domain)).orElse(null);
}
/**
*
* @param userId
* @return
*/
public List<UserDomain> getAllByTarget(Long userId) {
return Lists.newArrayList(userDomainRepository.findAll(qUserDomain.target.eq(userId)));
}
/**
*
* @param id
*/
public void delete(Long id) {
UserDomain userDomain = get(id);
if (userDomain != null) {
userDomainRepository.delete(userDomain);
}
}
/**
*
* @param page
* @param size
* @param sortBy
* @param descending
* @return
*/
public Page<UserDomain> get(int page, int size, String sortBy, boolean descending) {
Sort sort = descending ? Sort.by(sortBy).descending() : Sort.by(sortBy).ascending();
return userDomainRepository.findAll(PageRequest.of(page, size, sort));
}
/**
*
*/
@Scheduled(cron = "0 */15 * * * *")
public void validate() {
Pageable pageable = PageRequest.of(0, 100, Sort.by("id"));
BooleanBuilder filter = new BooleanBuilder();
filter.and(qUserDomain.validated.isFalse()
.and(qUserDomain.secret.isNotNull().and(qUserDomain.secret.isNotEmpty())));
Page<UserDomain> page;
do {
page = userDomainRepository.findAll(filter.getValue(), pageable);
for (UserDomain userDomain : page.getContent()) {
try {
validate(userDomain);
} catch (NamingException e) {
e.printStackTrace();
}
}
pageable = page.nextPageable();
} while (page.hasNext());
}
/**
*
* @param userDomain
* @throws NamingException
*/
public boolean validate(UserDomain userDomain) throws NamingException {
Attributes attributes = dirContext.getAttributes("_bstly." + userDomain.getDomain(),
new String[] { "TXT" });
NamingEnumeration<? extends Attribute> attributeEnumeration = attributes.getAll();
while (attributeEnumeration.hasMore()) {
if (attributeEnumeration.next().toString().endsWith(userDomain.getSecret())) {
userDomain.setValidated(true);
save(userDomain);
return true;
}
}
return false;
}
/*
* @see de.bstly.we.businesslogic.UserDataProvider#getId()
*/
@Override
public String getId() {
return "domains";
}
/*
* @see de.bstly.we.businesslogic.UserDataProvider#getUserData(java.lang.Long)
*/
@Override
public List<UserData> getUserData(Long userId) {
List<UserData> result = Lists.newArrayList();
for (UserDomain userDomain : getAllByTarget(userId)) {
result.add(userDomain);
}
return result;
}
/*
* @see de.bstly.we.businesslogic.UserDataProvider#purgeUserData(java.lang.Long)
*/
@Override
public void purgeUserData(Long userId) {
for (UserDomain userDomain : getAllByTarget(userId)) {
userDomainRepository.delete(userDomain);
}
}
}
@@ -0,0 +1,318 @@
/**
*
*/
package de.bstly.we.businesslogic;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletOutputStream;
import org.apache.commons.lang3.RandomStringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.session.FindByIndexNameSessionRepository;
import org.springframework.session.Session;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import com.beust.jcommander.internal.Lists;
import de.bstly.we.model.QUser;
import de.bstly.we.model.User;
import de.bstly.we.model.UserData;
import de.bstly.we.model.UserStatus;
import de.bstly.we.repository.UserRepository;
/**
*
* @author _bastler@bstly.de
*
*/
@Component
public class UserManager implements UserDataProvider {
private Logger logger = LoggerFactory.getLogger(UserManager.class);
@Autowired
private UserRepository userRepository;
@Autowired
private PasswordEncoder passwordEncoder;
@Autowired
private UserDataManager userDataManager;
@Autowired
private FindByIndexNameSessionRepository<? extends Session> sessionRepository;
private QUser qUser = QUser.user;
@Value("${we.bstly.userdata.directory}")
private String userDataDirectory;
@Value("${we.bstly.email.domain:we.bstly.de}")
private String userEmailDomain;
/**
* @param id
* @return
*/
public User get(Long id) {
return userRepository.findById(id).orElse(null);
}
/**
*
* @param username
* @return
*/
public User getByUsername(String username) {
return userRepository.findOne(qUser.username.equalsIgnoreCase(username)).orElse(null);
}
/**
*
* @param resetToken
* @return
*/
public User getByResetToken(String resetToken) {
return userRepository.findOne(qUser.resetToken.eq(resetToken)).orElse(null);
}
/**
* @param id
* @return
*/
public String getPasswordHash(Long id) {
Assert.isTrue(userRepository.existsById(id), "User with id '" + id + "' not exists!");
return userRepository.findById(id).get().getPasswordHash();
}
/**
*
* @param id
* @param passwordHash
*/
public User setPassword(Long id, String password) {
Assert.isTrue(userRepository.existsById(id), "User with id '" + id + "' not exists!");
User user = userRepository.findById(id).get();
user.setPasswordHash(passwordEncoder.encode(password));
return userRepository.save(user);
}
/**
*
* @param username
* @param email
* @param password
* @param publicKey
* @return
*/
public User create(String username, String password, UserStatus status) {
Assert.isTrue(!userRepository.exists(qUser.username.equalsIgnoreCase(username)),
"Username '" + username + "' already exists!");
User user = new User();
user.setUsername(username);
if (StringUtils.hasText(password)) {
user.setPasswordHash(passwordEncoder.encode(password));
}
user.setDisabled(false);
user.setLocked(false);
user.setStatus(status);
user = userRepository.save(user);
return user;
}
/**
*
* @param page
* @param size
* @param sortBy
* @param descending
* @return
*/
public Page<User> get(int page, int size, String sortBy, boolean descending) {
Sort sort = descending ? Sort.by(sortBy).descending() : Sort.by(sortBy).ascending();
return userRepository.findAll(PageRequest.of(page, size, sort));
}
/**
* @param user
* @return
*/
public User update(User user) {
Assert.isTrue(userRepository.existsById(user.getId()),
"User with id '" + user.getId() + "' not exists!");
User merge = get(user.getId());
merge.setUsername(user.getUsername());
merge.setStatus(user.getStatus());
merge.setDisabled(user.isDisabled());
merge.setLocked(user.isLocked());
if (merge.isDisabled() || merge.isLocked()) {
deleteSessionsForUser(merge);
}
return userRepository.save(merge);
}
/**
*
* @param user
*/
public void delete(User user) {
Assert.isTrue(userRepository.existsById(user.getId()),
"User with id '" + user.getId() + "' not exists!");
File publicKey = new File(getPublicKeyPath(user.getUsername()));
if (publicKey.exists()) {
publicKey.delete();
}
deleteSessionsForUser(user);
userDataManager.purge(user, false);
}
/**
*
* @param username
* @return
*/
public String getBstlyEmail(String username) {
return username + "@" + userEmailDomain;
}
/**
*
* @param username
* @param publicKey
*/
public void writePublicKey(String username, String publicKey) {
if (StringUtils.hasText(publicKey)) {
if (!userDataDirectory.endsWith(File.separator)) {
userDataDirectory += File.separator;
}
File userDir = new File(userDataDirectory + username);
if (!userDir.exists()) {
userDir.mkdirs();
}
try {
String publicKeyPath = getPublicKeyPath(username);
FileWriter myWriter = new FileWriter(publicKeyPath);
myWriter.write(publicKey);
myWriter.close();
String command = "gpg --import " + publicKeyPath;
Runtime.getRuntime().exec(command);
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
*
* @param username
* @return
*/
public String getPublicKeyPath(String username) {
return userDataDirectory + username + File.separator + "public.key";
}
/**
* @param user
* @param outputStream
*/
public void passwordReset(User user, ServletOutputStream outputStream) {
String resetToken = RandomStringUtils.random(64, true, true);
String command = "echo \"" + resetToken + "\" | gpg -ear "
+ getBstlyEmail(user.getUsername()) + " --always-trust";
user.setResetToken(resetToken);
try {
ProcessBuilder b = new ProcessBuilder("/bin/bash", "-c", command);
Process process = b.start();
BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getInputStream()));
BufferedReader errorReader = new BufferedReader(
new InputStreamReader(process.getErrorStream()));
int c;
while ((c = reader.read()) != -1) {
outputStream.write(c);
}
String error = "";
String line;
while ((line = errorReader.readLine()) != null) {
error += line;
}
if (StringUtils.hasText(error)) {
logger.warn(error);
}
reader.close();
errorReader.close();
} catch (IOException e) {
return;
}
update(user);
}
/**
*
* @param user
*/
protected void deleteSessionsForUser(User user) {
Map<String, ? extends Session> usersSessions = sessionRepository
.findByPrincipalName(user.getUsername());
for (Session session : usersSessions.values()) {
sessionRepository.deleteById(session.getId());
}
}
/*
* @see de.bstly.we.businesslogic.UserDataProvider#getId()
*/
@Override
public String getId() {
return "user";
}
/*
* @see de.bstly.we.businesslogic.UserDataProvider#getUserData(java.lang.Long)
*/
@Override
public List<UserData> getUserData(Long userId) {
List<UserData> result = Lists.newArrayList();
result.add(get(userId));
return result;
}
/*
* @see de.bstly.we.businesslogic.UserDataProvider#purgeUserData(java.lang.Long)
*/
@Override
public void purgeUserData(Long userId) {
userRepository.deleteById(userId);
}
}
@@ -0,0 +1,143 @@
/**
*
*/
package de.bstly.we.businesslogic;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import com.google.common.collect.Lists;
import de.bstly.we.model.QUserProfileField;
import de.bstly.we.model.UserData;
import de.bstly.we.model.UserProfileField;
import de.bstly.we.model.Visibility;
import de.bstly.we.repository.UserProfileFieldRepository;
/**
* @author _bastler@bstly.de
*
*/
@Component
public class UserProfileFieldManager implements UserDataProvider {
@Autowired
private UserProfileFieldRepository userProfileFieldRepository;
private QUserProfileField qUserProfileField = QUserProfileField.userProfileField;
/**
*
* @param target
* @param name
* @return
*/
public UserProfileField get(Long target, String name) {
return userProfileFieldRepository
.findOne(qUserProfileField.name.eq(name).and(qUserProfileField.target.eq(target)))
.orElse(null);
}
/**
*
* @param target
* @return
*/
public List<UserProfileField> getAllByTarget(Long target) {
return Lists.newArrayList(userProfileFieldRepository.findAll(
qUserProfileField.target.eq(target), Sort.by("index", "name").ascending()));
}
/**
*
* @param target
* @return
*/
public List<UserProfileField> getByTargetFiltered(Long target, List<String> names) {
return Lists.newArrayList(userProfileFieldRepository.findAll(
qUserProfileField.target.eq(target).and(qUserProfileField.name.in(names)),
Sort.by("index", "name").ascending()));
}
/**
*
* @param target
* @param visibilities
* @return
*/
public List<UserProfileField> getAllByTargetAndVisibilities(Long target,
List<Visibility> visibilities) {
return Lists.newArrayList(userProfileFieldRepository.findAll(
qUserProfileField.target.eq(target)
.and(qUserProfileField.visibility.in(visibilities)),
Sort.by("index", "name").ascending()));
}
/**
*
* @param userProfileField
* @return
*/
public UserProfileField save(UserProfileField userProfileField) {
return userProfileFieldRepository.save(userProfileField);
}
/**
*
* @param target
* @param name
*/
public void delete(Long target, String name) {
Assert.isTrue(
userProfileFieldRepository.exists(
qUserProfileField.target.eq(target).and(qUserProfileField.name.eq(name))),
"ProfileField '" + name + "' for target + '" + target + "' not exists!");
UserProfileField delete = userProfileFieldRepository
.findOne(qUserProfileField.target.eq(target).and(qUserProfileField.name.eq(name)))
.get();
userProfileFieldRepository.delete(delete);
}
/**
*
* @param target
*/
public void deleteAll(Long target) {
userProfileFieldRepository
.deleteAll(userProfileFieldRepository.findAll(qUserProfileField.target.eq(target)));
}
/*
* @see de.bstly.we.businesslogic.UserDataProvider#getId()
*/
@Override
public String getId() {
return "profilefields";
}
/*
* @see de.bstly.we.businesslogic.UserDataProvider#getUserData(java.lang.Long)
*/
@Override
public List<UserData> getUserData(Long userId) {
List<UserData> result = Lists.newArrayList();
for (UserProfileField userProfileField : getAllByTarget(userId)) {
result.add(userProfileField);
}
return result;
}
/*
* @see de.bstly.we.businesslogic.UserDataProvider#purgeUserData(java.lang.Long)
*/
@Override
public void purgeUserData(Long userId) {
for (UserProfileField userProfileField : getAllByTarget(userId)) {
userProfileFieldRepository.delete(userProfileField);
}
}
}
@@ -0,0 +1,15 @@
/**
*
*/
package de.bstly.we.businesslogic;
/**
* @author _bastler@bstly.de
*
*/
public interface UserProfileFields {
public static final String PROFILE_FIELD_EMAIL = "email";
public static final String PROFILE_FIELD_EMAIL_PRIMARY = "primaryEmail";
public static final String PROFILE_FIELD_LOCALE = "locale";
}
@@ -0,0 +1,178 @@
/**
*
*/
package de.bstly.we.businesslogic;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.beust.jcommander.internal.Lists;
import de.bstly.we.model.QUserTotp;
import de.bstly.we.model.User;
import de.bstly.we.model.UserData;
import de.bstly.we.model.UserTotp;
import de.bstly.we.repository.UserTotpRepository;
import de.bstly.we.security.businesslogic.SecondFactorProvider;
import dev.samstevens.totp.code.CodeVerifier;
import dev.samstevens.totp.qr.QrData;
import dev.samstevens.totp.qr.QrDataFactory;
import dev.samstevens.totp.recovery.RecoveryCodeGenerator;
import dev.samstevens.totp.secret.SecretGenerator;
/**
* @author _bastler@bstly.de
*
*/
@Component
public class UserTotpManager implements SecondFactorProvider<UserTotp> {
@Autowired
private UserTotpRepository userTotpRepository;
@Autowired
private UserManager userManager;
@Autowired
private SecretGenerator secretGenerator;
@Autowired
private CodeVerifier verifier;
@Autowired
private QrDataFactory qrDataFactory;
@Autowired
private RecoveryCodeGenerator recoveryCodeGenerator;
private QUserTotp qUserTotp = QUserTotp.userTotp;
/*
* @see de.bstly.we.security.businesslogic.SecondFactorProvider#getId()
*/
@Override
public String getId() {
return "totp";
}
/*
* @see
* de.bstly.we.security.businesslogic.SecondFactorProvider#supports(java.lang.
* String)
*/
@Override
public boolean supports(String provider) {
return getId().equals(provider);
}
/*
*
* @see
* de.bstly.we.security.businesslogic.SecondFactorProvider#isEnabled(java.lang.
* Long)
*/
@Override
public boolean isEnabled(Long userId) {
return userTotpRepository
.exists(qUserTotp.target.eq(userId).and(qUserTotp.enabled.isTrue()));
}
/*
*
* @see
* de.bstly.we.security.businesslogic.SecondFactorProvider#validate(java.lang.
* Long, java.lang.String)
*/
@Override
public boolean validate(Long userId, String code) {
UserTotp userTotp = userTotpRepository.findOne(qUserTotp.target.eq(userId)).orElse(null);
if (userTotp != null) {
return verifier.isValidCode(userTotp.getSecret(), code);
}
return false;
}
/*
* @see
* de.bstly.we.security.businesslogic.SecondFactorProvider#getForUser(java.lang.
* Long)
*/
@Override
public UserTotp get(Long userId) {
return userTotpRepository.findOne(qUserTotp.target.eq(userId)).orElse(null);
}
/*
* @see
* de.bstly.we.security.businesslogic.SecondFactorProvider#createByUser(java.
* lang.Long)
*/
@Override
public UserTotp create(Long userId) {
if (!isEnabled(userId)) {
delete(userId);
UserTotp userTotp = new UserTotp();
userTotp.setTarget(userId);
userTotp.setSecret(secretGenerator.generate());
User user = userManager.get(userId);
QrData data = qrDataFactory.newBuilder().label(user.getUsername())
.secret(userTotp.getSecret()).issuer("we.bstly").build();
userTotp.setQrData(data.getUri());
userTotp.setRecoveryCodes(Lists.newArrayList(recoveryCodeGenerator.generateCodes(16)));
return userTotpRepository.save(userTotp);
}
return userTotpRepository.findOne(qUserTotp.target.eq(userId)).orElse(null);
}
/*
* @see
* de.bstly.we.security.businesslogic.SecondFactorProvider#enableByUser(java.
* lang.Long, java.lang.String)
*/
@Override
public boolean enable(Long userId, String code) {
if (validate(userId, code)) {
UserTotp userTotp = userTotpRepository.findOne(qUserTotp.target.eq(userId))
.orElse(null);
userTotp.setEnabled(true);
userTotpRepository.save(userTotp);
return true;
}
return false;
}
/*
* @see
* de.bstly.we.security.businesslogic.SecondFactorProvider#deleteByUser(java.
* lang.Long)
*/
@Override
public void delete(Long userId) {
UserTotp userTotp = get(userId);
if (userTotp != null) {
userTotpRepository.delete(userTotp);
}
}
/*
* @see de.bstly.we.businesslogic.UserDataProvider#getUserData(java.lang.Long)
*/
@Override
public List<UserData> getUserData(Long userId) {
List<UserData> result = Lists.newArrayList();
UserTotp userTotp = get(userId);
if (userTotp != null) {
result.add(userTotp);
}
return result;
}
/*
* @see de.bstly.we.businesslogic.UserDataProvider#purgeUserData(java.lang.Long)
*/
@Override
public void purgeUserData(Long userId) {
delete(userId);
}
}
@@ -0,0 +1,67 @@
/**
*
*/
package de.bstly.we.businesslogic.support;
import javax.persistence.PostLoad;
import javax.persistence.PostPersist;
import javax.persistence.PostRemove;
import javax.persistence.PostUpdate;
import javax.persistence.PrePersist;
import javax.persistence.PreRemove;
import javax.persistence.PreUpdate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;
import de.bstly.we.event.AbstractModelEvent;
import de.bstly.we.event.AbstractModelEventType;
import de.bstly.we.model.AbstractModel;
/**
* @author Lurkars
*
*/
@Component
public class AbstractModelEventListener {
@Autowired
private ApplicationEventPublisher applicationEventPublisher;
@PrePersist
private void prePersist(AbstractModel model) {
applicationEventPublisher.publishEvent(new AbstractModelEvent(AbstractModelEventType.PRE_PERSIST, model));
}
@PreUpdate
private void preUpdate(AbstractModel model) {
applicationEventPublisher.publishEvent(new AbstractModelEvent(AbstractModelEventType.PRE_UPDATE, model));
}
@PreRemove
private void preRemove(AbstractModel model) {
applicationEventPublisher.publishEvent(new AbstractModelEvent(AbstractModelEventType.PRE_REMOVE, model));
}
@PostPersist
private void postPersist(AbstractModel model) {
applicationEventPublisher.publishEvent(new AbstractModelEvent(AbstractModelEventType.POST_PERSIST, model));
}
@PostUpdate
private void postUpdate(AbstractModel model) {
applicationEventPublisher.publishEvent(new AbstractModelEvent(AbstractModelEventType.POST_UPDATE, model));
}
@PostRemove
private void postRemove(AbstractModel model) {
applicationEventPublisher.publishEvent(new AbstractModelEvent(AbstractModelEventType.POST_REMOVE, model));
}
@PostLoad
private void postLoad(AbstractModel model) {
applicationEventPublisher.publishEvent(new AbstractModelEvent(AbstractModelEventType.POST_LOAD, model));
}
}
@@ -0,0 +1,83 @@
/**
*
*/
package de.bstly.we.businesslogic.support;
import java.time.Instant;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoField;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAmount;
import java.time.temporal.TemporalUnit;
/**
* @author _bastler@bstly.de
*
*/
public class InstantHelper {
/**
*
* @param instant
* @param amount
* @return
*/
public static Instant plus(Instant instant, TemporalAmount amount) {
return ZonedDateTime.ofInstant(instant, ZoneOffset.UTC).plus(amount).toInstant();
}
/**
*
* @param instant
* @param amountToAdd
* @param unit
* @return
*/
public static Instant plus(Instant instant, long amountToAdd, TemporalUnit unit) {
return ZonedDateTime.ofInstant(instant, ZoneOffset.UTC).plus(amountToAdd, unit).toInstant();
}
/**
*
* @param instant
* @param amount
* @return
*/
public static Instant minus(Instant instant, TemporalAmount amount) {
return ZonedDateTime.ofInstant(instant, ZoneOffset.UTC).minus(amount).toInstant();
}
/**
*
* @param instant
* @param amountToAdd
* @param unit
* @return
*/
public static Instant minus(Instant instant, long amountToAdd, TemporalUnit unit) {
return ZonedDateTime.ofInstant(instant, ZoneOffset.UTC).minus(amountToAdd, unit)
.toInstant();
}
/**
*
* @param instant
* @param unit
* @return
*/
public static Instant truncate(Instant instant, TemporalUnit unit) {
if (ChronoUnit.YEARS.equals(unit)) {
instant = instant.truncatedTo(ChronoUnit.DAYS);
return ZonedDateTime.ofInstant(instant, ZoneOffset.UTC)
.with(ChronoField.DAY_OF_YEAR, 1L).toInstant();
} else if (ChronoUnit.MONTHS.equals(unit)) {
instant = instant.truncatedTo(ChronoUnit.DAYS);
return ZonedDateTime.ofInstant(instant, ZoneOffset.UTC)
.with(ChronoField.DAY_OF_MONTH, 1L).toInstant();
}
return ZonedDateTime.ofInstant(instant, ZoneOffset.UTC).truncatedTo(unit).toInstant();
}
}
@@ -0,0 +1,202 @@
/**
*
*/
package de.bstly.we.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.beust.jcommander.internal.Lists;
import de.bstly.we.controller.model.SecondFactorProviderModel;
import de.bstly.we.controller.support.EntityResponseStatusException;
import de.bstly.we.model.SecondFactor;
import de.bstly.we.security.businesslogic.SecondFactorProvider;
import de.bstly.we.security.businesslogic.SecondFactorProviderManager;
import de.bstly.we.security.businesslogic.SecondFactorRequestProvider;
import de.bstly.we.security.model.LocalUserDetails;
/**
*
* @author _bastler@bstly.de
*
*/
@RestController
@RequestMapping("/auth/2fa")
public class Authentication2FAController extends BaseController {
@Autowired
private SecondFactorProviderManager secondFactorProviderManager;
/**
*
* @return
*/
protected Long getPreAuthenticationId() {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if (auth != null && auth.getPrincipal() instanceof LocalUserDetails) {
return ((LocalUserDetails) auth.getPrincipal()).getUserId();
}
return null;
}
/**
*
* @return
*/
@GetMapping
public List<SecondFactorProviderModel> getEnabled() {
Long userId = getPreAuthenticationId();
if (userId == null) {
throw new EntityResponseStatusException(HttpStatus.UNAUTHORIZED);
}
List<SecondFactorProviderModel> result = Lists.newArrayList();
for (SecondFactorProvider<?> provider : secondFactorProviderManager.getEnabled(userId)) {
result.add(new SecondFactorProviderModel(provider.getId(),
provider instanceof SecondFactorRequestProvider<?>));
}
return result;
}
/**
*
* @return
*/
@GetMapping("/available")
public List<SecondFactorProviderModel> getAvailable() {
Long userId = getPreAuthenticationId();
if (userId == null) {
throw new EntityResponseStatusException(HttpStatus.UNAUTHORIZED);
}
List<SecondFactorProviderModel> result = Lists.newArrayList();
for (SecondFactorProvider<?> provider : secondFactorProviderManager.getAll()) {
result.add(new SecondFactorProviderModel(provider.getId(),
provider instanceof SecondFactorRequestProvider<?>));
}
for (SecondFactorProvider<?> provider : secondFactorProviderManager.getEnabled(userId)) {
SecondFactorProviderModel enabledProvider = new SecondFactorProviderModel(
provider.getId(), provider instanceof SecondFactorRequestProvider<?>);
result.remove(enabledProvider);
}
return result;
}
/**
*
* @return
*/
@PreAuthorize("authentication.authenticated")
@GetMapping("/{id}")
public void isSecondFactorEnabled(@PathVariable("id") String providerId) {
SecondFactorProvider<?> provider = secondFactorProviderManager.getProvider(providerId);
if (provider == null) {
throw new EntityResponseStatusException(HttpStatus.UNAUTHORIZED);
}
if (!provider.isEnabled(getCurrentUserId())) {
throw new EntityResponseStatusException(HttpStatus.NOT_MODIFIED);
}
}
/**
*
*/
@PreAuthorize("hasRole('ROLE_PRE_AUTH_USER')")
@PostMapping("/{id}")
public void requestSecondFactorMail(@PathVariable("id") String providerId) {
Long userId = getPreAuthenticationId();
if (userId == null) {
throw new EntityResponseStatusException(HttpStatus.UNAUTHORIZED);
}
SecondFactorProvider<?> provider = secondFactorProviderManager.getProvider(providerId);
if (provider == null) {
throw new EntityResponseStatusException(HttpStatus.UNAUTHORIZED);
}
if (!(provider instanceof SecondFactorRequestProvider<?>)) {
throw new EntityResponseStatusException(HttpStatus.UNAUTHORIZED);
}
SecondFactorRequestProvider<?> requestProvider = (SecondFactorRequestProvider<?>) provider;
requestProvider.request(userId);
}
/**
*
* @return
*/
@PreAuthorize("authentication.authenticated")
@PutMapping("/{id}")
public SecondFactor createSecondFactor(@PathVariable("id") String providerId) {
SecondFactorProvider<?> provider = secondFactorProviderManager.getProvider(providerId);
if (provider == null) {
throw new EntityResponseStatusException(HttpStatus.UNAUTHORIZED);
}
if (provider.isEnabled(getCurrentUserId())) {
throw new EntityResponseStatusException(HttpStatus.CONFLICT);
}
return provider.create(getCurrentUserId());
}
/**
*
* @return
*/
@PreAuthorize("authentication.authenticated")
@PatchMapping("/{id}")
public void enableSecondFactor(@PathVariable("id") String providerId,
@RequestBody String token) {
SecondFactorProvider<?> provider = secondFactorProviderManager.getProvider(providerId);
if (provider == null) {
throw new EntityResponseStatusException(HttpStatus.UNAUTHORIZED);
}
if (!provider.enable(getCurrentUserId(), token)) {
throw new EntityResponseStatusException(HttpStatus.UNAUTHORIZED);
}
}
/**
*
*/
@PreAuthorize("authentication.authenticated")
@DeleteMapping("/{id}")
public void removeSecondFactorMail(@PathVariable("id") String providerId) {
SecondFactorProvider<?> provider = secondFactorProviderManager.getProvider(providerId);
if (provider == null) {
throw new EntityResponseStatusException(HttpStatus.UNAUTHORIZED);
}
provider.delete(getCurrentUserId());
}
}
@@ -0,0 +1,107 @@
/**
*
*/
package de.bstly.we.controller;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.validation.Errors;
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 de.bstly.we.businesslogic.UserManager;
import de.bstly.we.controller.model.PasswordResetModel;
import de.bstly.we.controller.support.EntityResponseStatusException;
import de.bstly.we.controller.support.RequestBodyErrors;
import de.bstly.we.controller.validation.PasswordModelValidator;
import de.bstly.we.model.User;
/**
*
* @author _bastler@bstly.de
*
*/
@RestController
@RequestMapping("/auth")
public class AuthenticationController extends BaseController {
@Autowired
private UserManager userManager;
@Autowired
private PasswordModelValidator passwordModelValidator;
/**
*
* @return
*/
@GetMapping("/me")
public Authentication me() {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
return auth;
}
/**
*
* @param username
* @param req
* @param resp
* @throws IOException
*/
@PreAuthorize("isAnonymous()")
@PostMapping("/password/request")
public void passwordRequest(@RequestBody String username, HttpServletRequest req,
HttpServletResponse resp) throws IOException {
User user = userManager.getByUsername(username);
if (user != null) {
resp.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_PLAIN_VALUE);
userManager.passwordReset(user, resp.getOutputStream());
resp.getOutputStream().flush();
resp.getOutputStream().close();
}
}
/**
*
* @param passwordResetModel
* @param req
* @param resp
*/
@PreAuthorize("isAnonymous()")
@PostMapping("/password/reset")
public void passwordReset(@RequestBody PasswordResetModel passwordResetModel,
HttpServletRequest req, HttpServletResponse resp) {
User user = userManager.getByResetToken(passwordResetModel.getToken().trim());
if (user == null) {
throw new EntityResponseStatusException(HttpStatus.UNAUTHORIZED);
}
Errors errors = new RequestBodyErrors(passwordResetModel);
passwordModelValidator.validate(passwordResetModel, errors);
if (errors.hasErrors()) {
throw new EntityResponseStatusException(errors.getAllErrors(), HttpStatus.CONFLICT);
}
user = userManager.setPassword(user.getId(), passwordResetModel.getPassword());
user.setResetToken(null);
userManager.update(user);
}
}
@@ -0,0 +1,32 @@
/**
*
*/
package de.bstly.we.controller;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import de.bstly.we.security.model.LocalUserDetails;
/**
*
* @author _bastler@bstly.de
*
*/
public class BaseController {
/**
*
* @return
*/
public Long getCurrentUserId() {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if (auth != null && auth.isAuthenticated() && auth.getPrincipal() instanceof LocalUserDetails) {
LocalUserDetails details = (LocalUserDetails) auth.getPrincipal();
return details.getUserId();
}
return null;
}
}
@@ -0,0 +1,147 @@
/**
*
*/
package de.bstly.we.controller;
import java.util.Map;
import java.util.Set;
import javax.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.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.RestController;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.gson.JsonObject;
import de.bstly.we.businesslogic.PretixManager;
import de.bstly.we.businesslogic.PretixManager.ITEM_STATUS;
import de.bstly.we.businesslogic.UserManager;
import de.bstly.we.controller.model.ItemModel;
import de.bstly.we.controller.model.ItemResultModel;
import de.bstly.we.controller.support.EntityResponseStatusException;
import de.bstly.we.controller.support.TokenSessionManager;
import de.bstly.we.model.User;
/**
*
* @author _bastler@bstly.de
*
*/
@RestController
@RequestMapping("/items")
public class ItemController extends BaseController {
@Autowired
private TokenSessionManager tokenSessionManager;
@Autowired
private PretixManager pretixManager;
@Autowired
private UserManager userManager;
/**
*
*/
@GetMapping
public Set<ItemModel> getItems(HttpSession session) {
Set<ItemModel> result = Sets.newHashSet();
if (tokenSessionManager.getTokenFromSession(session).isEmpty()) {
return result;
}
for (String token : tokenSessionManager.getTokenFromSession(session)) {
JsonObject checkInItem = pretixManager.getCheckInItemBySecret(token);
JsonObject item = pretixManager.getItem(checkInItem.get("item").getAsInt());
ItemModel itemModel = new ItemModel();
itemModel.setSecret(token);
Map<String, String> name = Maps.newHashMap();
for (String lang : item.getAsJsonObject("name").keySet()) {
name.put(lang, item.getAsJsonObject("name").get(lang).getAsString());
}
itemModel.setName(name);
result.add(itemModel);
}
return result;
}
/**
*
* @param secret
*/
@PutMapping("")
public void addItem(@RequestBody String secret, HttpSession session) {
ITEM_STATUS status = pretixManager.getItemStatus(secret);
if (status == ITEM_STATUS.PAID) {
tokenSessionManager.addTokenToSession(secret, session);
throw new EntityResponseStatusException(HttpStatus.ACCEPTED);
} else if (pretixManager.getItemStatus(secret) == ITEM_STATUS.REDEEMED) {
throw new EntityResponseStatusException(HttpStatus.GONE);
}
throw new EntityResponseStatusException(HttpStatus.NOT_ACCEPTABLE);
}
/**
*
* @param secret
*/
@DeleteMapping
public void removeItem(@RequestBody String secret, HttpSession session) {
tokenSessionManager.removeTokenFromSession(secret, session);
}
/**
*
* @return
*/
@PreAuthorize("isAuthenticated()")
@PostMapping
public ItemResultModel redeem(HttpSession session) {
if (tokenSessionManager.getTokenFromSession(session).isEmpty()) {
throw new EntityResponseStatusException(HttpStatus.NOT_MODIFIED);
}
ItemResultModel result = tokenSessionManager.applyTokens(getCurrentUserId(),
tokenSessionManager.getTokenFromSession(session));
tokenSessionManager.removeTokensFromSession(session);
return result;
}
/**
*
* @param username
* @param session
*/
@PreAuthorize("isAuthenticated()")
@PostMapping("/{username}")
public void redeemForUser(@PathVariable("username") String username, HttpSession session) {
if (tokenSessionManager.getTokenFromSession(session).isEmpty()) {
throw new EntityResponseStatusException(HttpStatus.NOT_MODIFIED);
}
User user = userManager.getByUsername(username);
if (user == null) {
throw new EntityResponseStatusException(HttpStatus.CONFLICT);
}
tokenSessionManager.applyTokens(user.getId(),
tokenSessionManager.getTokenFromSession(session));
tokenSessionManager.removeTokensFromSession(session);
}
}
@@ -0,0 +1,81 @@
/**
*
*/
package de.bstly.we.controller;
import java.util.List;
import javax.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.google.common.collect.Lists;
import de.bstly.we.businesslogic.PermissionManager;
import de.bstly.we.controller.support.TokenSessionManager;
import de.bstly.we.model.Permission;
/**
*
* @author _bastler@bstly.de
*
*/
@RestController
@RequestMapping("/permissions")
public class PermissionController extends BaseController {
@Autowired
private PermissionManager permissionManager;
@Autowired
private TokenSessionManager tokenSessionManager;
/**
*
* @return
*/
@GetMapping
public List<Permission> getPermissions() {
if (getCurrentUserId() == null) {
return Lists.newArrayList();
}
return permissionManager.getNotExpiresByTargetIgnoreStart(getCurrentUserId());
}
/**
*
* @return
*/
@GetMapping("/new")
public List<Permission> getNewPermissions(HttpSession session) {
List<Permission> permissions = Lists.newArrayList();
if (tokenSessionManager.getTokenFromSession(session).isEmpty()) {
return permissions;
}
for (String token : tokenSessionManager.getTokenFromSession(session)) {
permissions
.addAll(tokenSessionManager.getPermissionsForToken(getCurrentUserId(), token));
}
return permissions;
}
/**
*
* @return
*/
@GetMapping("/all")
public List<Permission> getAllPermissions() {
if (getCurrentUserId() == null) {
return Lists.newArrayList();
}
return permissionManager.getAllByTarget(getCurrentUserId());
}
}
@@ -0,0 +1,153 @@
/**
*
*/
package de.bstly.we.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import de.bstly.we.businesslogic.PermissionManager;
import de.bstly.we.businesslogic.UserManager;
import de.bstly.we.controller.support.EntityResponseStatusException;
import de.bstly.we.model.Permission;
import de.bstly.we.model.User;
/**
*
* @author _bastler@bstly.de
*
*/
@RestController
@RequestMapping("/permissions/manage")
public class PermissionManagementController extends BaseController {
@Autowired
private PermissionManager permissionManager;
@Autowired
private UserManager userManager;
/**
*
* @param username
* @return
*/
@PreAuthorize("hasRole('ROLE_ADMIN')")
@GetMapping("/{username}")
public List<Permission> getPermissionsForUser(@PathVariable("username") String username) {
User user = userManager.getByUsername(username);
if (user == null) {
throw new EntityResponseStatusException(HttpStatus.NO_CONTENT);
}
return permissionManager.getNotExpiresByTargetIgnoreStart(user.getId());
}
/**
*
* @param username
* @return
*/
@PreAuthorize("hasRole('ROLE_ADMIN')")
@GetMapping("/{username}/all")
public List<Permission> getAllPermissionsForUser(@PathVariable("username") String username) {
User user = userManager.getByUsername(username);
if (user == null) {
throw new EntityResponseStatusException(HttpStatus.NO_CONTENT);
}
return permissionManager.getAllByTarget(user.getId());
}
/**
*
* @param permission
* @return
*/
@PreAuthorize("hasRole('ROLE_ADMIN')")
@PostMapping
public Permission createPermission(@RequestBody Permission permission) {
return permissionManager.create(permission.getTarget(), permission.getName(),
permission.isAddon(), permission.getStarts(), permission.getExpires());
}
/**
*
* @param permission
* @return
*/
@PreAuthorize("hasRole('ROLE_ADMIN')")
@PatchMapping
public Permission updatePermission(@RequestBody Permission permission) {
if (permission.getId() == null) {
throw new EntityResponseStatusException(HttpStatus.CONFLICT);
}
return permissionManager.update(permission);
}
/**
*
* @param name
* @param clone
* @return
*/
@PreAuthorize("hasRole('ROLE_ADMIN')")
@PostMapping("/{name}/clone/{clone}")
public List<Permission> clone(@PathVariable("name") String name,
@PathVariable("clone") String clone) {
if (name.equals(clone)) {
throw new EntityResponseStatusException(HttpStatus.CONFLICT);
}
return permissionManager.clone(name, clone);
}
/**
*
* @param permission
*/
@PreAuthorize("hasRole('ROLE_ADMIN')")
@DeleteMapping
public void deletePermission(@RequestBody Permission permission) {
if (permissionManager.get(permission.getTarget(), permission.getName()) == null) {
throw new EntityResponseStatusException(HttpStatus.NOT_MODIFIED);
}
permissionManager.delete(permission.getTarget(), permission.getName());
}
/**
*
* @param target
*/
@PreAuthorize("hasRole('ROLE_ADMIN')")
@DeleteMapping("/{target}")
public void deleteAll(@PathVariable("target") Long target) {
permissionManager.deleteAll(target);
}
/**
*
* @param name
*/
@PreAuthorize("hasRole('ROLE_ADMIN')")
@DeleteMapping("/byname/{name}")
public void deleteAllByName(@PathVariable("name") String name) {
permissionManager.deleteAll(name);
}
}
@@ -0,0 +1,152 @@
/**
*
*/
package de.bstly.we.controller;
import java.util.List;
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.PatchMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.google.common.collect.Lists;
import de.bstly.we.businesslogic.PermissionMappingManager;
import de.bstly.we.controller.support.EntityResponseStatusException;
import de.bstly.we.controller.support.RequestBodyErrors;
import de.bstly.we.controller.validation.PermissionMappingValidator;
import de.bstly.we.model.PermissionMapping;
/**
*
* @author _bastler@bstly.de
*
*/
@RestController
@RequestMapping("/permissions/mappings")
public class PermissionMappingController extends BaseController {
@Autowired
private PermissionMappingManager permissionMappingManager;
@Autowired
private PermissionMappingValidator permissionMappingValidator;
/**
*
* @param pageParameter
* @param sizeParameter
* @return
*/
@PreAuthorize("hasRole('ROLE_ADMIN')")
@GetMapping
public Page<PermissionMapping> getPermissionMappings(
@RequestParam("page") Optional<Integer> pageParameter,
@RequestParam("size") Optional<Integer> sizeParameter) {
return permissionMappingManager.get(pageParameter.orElse(0), sizeParameter.orElse(10), "item", true);
}
/**
*
* @param permissionMapping
* @return
*/
@PreAuthorize("hasRole('ROLE_ADMIN')")
@PostMapping
public PermissionMapping create(@RequestBody PermissionMapping permissionMapping) {
Errors errors = new RequestBodyErrors(permissionMapping);
permissionMappingValidator.validate(permissionMapping, errors);
if (errors.hasErrors()) {
throw new EntityResponseStatusException(errors.getAllErrors(), HttpStatus.CONFLICT);
}
return permissionMappingManager.create(permissionMapping.getItem(),
permissionMapping.getNames(), permissionMapping.getLifetime(),
permissionMapping.getLifetimeUnit(), permissionMapping.isLifetimeRound(),
permissionMapping.isAddon(), permissionMapping.getProduct(),
permissionMapping.getStartsQuestion(), permissionMapping.getExpiresQuestion());
}
/**
*
* @param permissionMappings
* @return
*/
@PreAuthorize("hasRole('ROLE_ADMIN')")
@PostMapping("/list")
public List<PermissionMapping> createList(
@RequestBody List<PermissionMapping> permissionMappings) {
List<PermissionMapping> result = Lists.newArrayList();
for (PermissionMapping permissionMapping : permissionMappings) {
Errors errors = new RequestBodyErrors(permissionMapping);
permissionMappingValidator.validate(permissionMapping, errors);
if (errors.hasErrors()) {
throw new EntityResponseStatusException(errors.getAllErrors(), HttpStatus.CONFLICT);
}
result.add(permissionMappingManager.create(permissionMapping.getItem(),
permissionMapping.getNames(), permissionMapping.getLifetime(),
permissionMapping.getLifetimeUnit(), permissionMapping.isLifetimeRound(),
permissionMapping.isAddon(), permissionMapping.getProduct(),
permissionMapping.getStartsQuestion(), permissionMapping.getExpiresQuestion()));
}
return result;
}
/**
*
* @param permissionMapping
* @return
*/
@PreAuthorize("hasRole('ROLE_ADMIN')")
@PatchMapping
public PermissionMapping update(@RequestBody PermissionMapping permissionMapping) {
Errors errors = new RequestBodyErrors(permissionMapping);
if (errors.hasErrors()) {
throw new EntityResponseStatusException(errors.getAllErrors(), HttpStatus.CONFLICT);
}
return permissionMappingManager.update(permissionMapping);
}
/**
*
* @param permissionMappings
* @return
*/
@PreAuthorize("hasRole('ROLE_ADMIN')")
@PatchMapping("/list")
public List<PermissionMapping> updateList(
@RequestBody List<PermissionMapping> permissionMappings) {
List<PermissionMapping> result = Lists.newArrayList();
for (PermissionMapping permissionMapping : permissionMappings) {
Errors errors = new RequestBodyErrors(permissionMapping);
if (errors.hasErrors()) {
throw new EntityResponseStatusException(errors.getAllErrors(), HttpStatus.CONFLICT);
}
result.add(permissionMappingManager.update(permissionMapping));
}
return result;
}
/**
*
* @param permissionMapping
*/
@PreAuthorize("hasRole('ROLE_ADMIN')")
@DeleteMapping
public void delete(@RequestBody PermissionMapping permissionMapping) {
permissionMappingManager.delete(permissionMapping.getId());
}
}
@@ -0,0 +1,71 @@
/**
*
*/
package de.bstly.we.controller;
import java.io.IOException;
import java.util.Map.Entry;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
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 org.springframework.web.reactive.function.client.WebClientResponseException;
import com.google.common.collect.Lists;
import com.google.gson.Gson;
import com.google.gson.JsonIOException;
import de.bstly.we.businesslogic.PretixManager;
import de.bstly.we.controller.model.PretixRequest;
import de.bstly.we.controller.support.EntityResponseStatusException;
/**
*
* @author _bastler@bstly.de
*
*/
@RestController
@RequestMapping("/pretix")
public class PretixApiController extends BaseController {
@Autowired
private PretixManager pretixManager;
private Gson gson = new Gson();
/**
*
* @param pretixRequest
* @return
* @throws IOException
* @throws JsonIOException
*/
@PreAuthorize("hasRole('ROLE_ADMIN')")
@PostMapping("/debug")
public void debug(@RequestBody PretixRequest pretixRequest, HttpServletResponse response)
throws JsonIOException, IOException {
try {
MultiValueMap<String, String> queryParemeters = new LinkedMultiValueMap<String, String>();
if (pretixRequest.getQueryParameters() != null) {
for (Entry<String, String> entry : pretixRequest.getQueryParameters().entrySet()) {
queryParemeters.put(entry.getKey(), Lists.newArrayList(entry.getValue()));
}
}
gson.toJson(
pretixManager.request(pretixRequest.getPath(), pretixRequest.getMethod(),
gson.toJsonTree(pretixRequest.getPayload()), queryParemeters),
response.getWriter());
} catch (WebClientResponseException e) {
throw new EntityResponseStatusException(e.getMessage(), e.getStatusCode());
}
}
}
@@ -0,0 +1,114 @@
/**
*
*/
package de.bstly.we.controller;
import java.util.List;
import javax.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.google.common.collect.Lists;
import de.bstly.we.businesslogic.QuotaManager;
import de.bstly.we.controller.support.TokenSessionManager;
import de.bstly.we.model.Quota;
import de.bstly.we.model.QuotaMapping;
/**
*
* @author _bastler@bstly.de
*
*/
@RestController
@RequestMapping("/quotas")
public class QuotaController extends BaseController {
@Autowired
private QuotaManager quotaManager;
@Autowired
private TokenSessionManager tokenSessionManager;
/**
*
* @return
*/
@GetMapping
public List<Quota> getQuotas() {
if (getCurrentUserId() == null) {
return Lists.newArrayList();
}
return quotaManager.getNotExpiresByTarget(getCurrentUserId());
}
/**
*
* @return
*/
@GetMapping("/new")
public List<Quota> getNewQuotas(HttpSession session) {
List<Quota> quotas = Lists.newArrayList();
if (tokenSessionManager.getTokenFromSession(session).isEmpty()) {
return quotas;
}
for (String token : tokenSessionManager.getTokenFromSession(session)) {
for (QuotaMapping quotaMapping : tokenSessionManager
.getQuotaMappingsForToken(getCurrentUserId(), token)) {
boolean added = false;
for (Quota quota : quotas) {
if (quota.getName().equals(quotaMapping.getName())) {
quota.setValue(
quotaMapping.isAppend() ? quota.getValue() + quotaMapping.getValue()
: quotaMapping.getValue());
added = true;
}
}
if (!added) {
if (quotaManager.hasQuota(getCurrentUserId(), quotaMapping.getName())) {
Quota quota = quotaManager.get(getCurrentUserId(), quotaMapping.getName());
quota.setValue(
quotaMapping.isAppend() ? quota.getValue() + quotaMapping.getValue()
: quotaMapping.getValue());
quotas.add(quota);
added = true;
}
if (!added) {
Quota quota = new Quota();
quota.setName(quotaMapping.getName());
quota.setValue(quotaMapping.getValue());
quota.setUnit(quotaMapping.getUnit());
quota.setDisposable(quotaMapping.isDisposable());
quotas.add(quota);
}
}
}
}
return quotas;
}
/**
*
* @return
*/
@GetMapping("/all")
public List<Quota> getAllQuotas() {
if (getCurrentUserId() == null) {
return Lists.newArrayList();
}
return quotaManager.getAllByTarget(getCurrentUserId());
}
}
@@ -0,0 +1,190 @@
/**
*
*/
package de.bstly.we.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.beust.jcommander.internal.Lists;
import de.bstly.we.businesslogic.QuotaManager;
import de.bstly.we.businesslogic.UserManager;
import de.bstly.we.controller.support.EntityResponseStatusException;
import de.bstly.we.model.Quota;
import de.bstly.we.model.User;
/**
*
* @author _bastler@bstly.de
*
*/
@RestController
@RequestMapping("/quotas/manage")
public class QuotaManagementController extends BaseController {
@Autowired
private QuotaManager quotaManager;
@Autowired
private UserManager userManager;
/**
*
* @param username
* @return
*/
@PreAuthorize("hasRole('ROLE_ADMIN')")
@GetMapping("/{username}")
public List<Quota> getQuotasForUser(@PathVariable("username") String username) {
User user = userManager.getByUsername(username);
if (user == null) {
throw new EntityResponseStatusException(HttpStatus.NO_CONTENT);
}
return quotaManager.getNotExpiresByTarget(user.getId());
}
/**
*
* @param username
* @return
*/
@PreAuthorize("hasRole('ROLE_ADMIN')")
@GetMapping("/{username}/all")
public List<Quota> getAllQuotasForUser(@PathVariable("username") String username) {
User user = userManager.getByUsername(username);
if (user == null) {
throw new EntityResponseStatusException(HttpStatus.NO_CONTENT);
}
return quotaManager.getAllByTarget(user.getId());
}
/**
*
* @param name
* @return
*/
@PreAuthorize("hasRole('ROLE_ADMIN')")
@GetMapping("/byname/{name}")
public List<Quota> getQuotasByName(@PathVariable("name") String name) {
return quotaManager.getAllByName(name);
}
/**
*
* @param quota
* @return
*/
@PreAuthorize("hasRole('ROLE_ADMIN')")
@PostMapping
public Quota createQuota(@RequestBody Quota quota) {
if (quotaManager.get(quota.getTarget(), quota.getName()) != null) {
throw new EntityResponseStatusException(HttpStatus.CONFLICT);
}
return quotaManager.create(quota.getTarget(), quota.getName(), quota.getValue(),
quota.getUnit(), quota.isDisposable());
}
/**
*
* @param quota
* @return
*/
@PreAuthorize("hasRole('ROLE_ADMIN')")
@PatchMapping
public Quota updateQuota(@RequestBody Quota quota) {
if (quotaManager.get(quota.getTarget(), quota.getName()) == null) {
throw new EntityResponseStatusException(HttpStatus.CONFLICT);
}
return quotaManager.update(quota);
}
/**
*
* @param quotas
* @return
*/
@PreAuthorize("hasRole('ROLE_ADMIN')")
@PatchMapping("/list")
public List<Quota> updateQuotaList(@RequestBody List<Quota> quotas) {
List<Quota> result = Lists.newArrayList();
for (Quota quota : quotas) {
if (quotaManager.get(quota.getTarget(), quota.getName()) == null) {
throw new EntityResponseStatusException(HttpStatus.CONFLICT);
}
result.add(quotaManager.update(quota));
}
return result;
}
/**
*
* @param name
* @param clone
* @return
*/
@PreAuthorize("hasRole('ROLE_ADMIN')")
@PostMapping("/{name}/clone/{clone}")
public List<Quota> clone(@PathVariable("name") String name, @PathVariable("clone") String clone,
@RequestBody long value) {
if (name.equals(clone)) {
throw new EntityResponseStatusException(HttpStatus.CONFLICT);
}
return quotaManager.clone(name, clone, value);
}
/**
*
* @param quota
*/
@PreAuthorize("hasRole('ROLE_ADMIN')")
@DeleteMapping
public void deleteQuota(@RequestBody Quota quota) {
if (quotaManager.get(quota.getTarget(), quota.getName()) == null) {
throw new EntityResponseStatusException(HttpStatus.NOT_MODIFIED);
}
quotaManager.delete(quota.getTarget(), quota.getName());
}
/**
*
* @param target
*/
@PreAuthorize("hasRole('ROLE_ADMIN')")
@DeleteMapping("/{target}")
public void deleteAll(@PathVariable("target") Long target) {
quotaManager.deleteAll(target);
}
/**
*
* @param name
*/
@PreAuthorize("hasRole('ROLE_ADMIN')")
@DeleteMapping("/byname/{name}")
public void deleteAllByName(@PathVariable("name") String name) {
quotaManager.deleteAll(name);
}
}
@@ -0,0 +1,136 @@
/**
*
*/
package de.bstly.we.controller;
import java.util.List;
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.PatchMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.google.common.collect.Lists;
import de.bstly.we.businesslogic.QuotaMappingManager;
import de.bstly.we.controller.support.EntityResponseStatusException;
import de.bstly.we.controller.support.RequestBodyErrors;
import de.bstly.we.controller.validation.QuotaMappingValidator;
import de.bstly.we.model.QuotaMapping;
/**
*
* @author _bastler@bstly.de
*
*/
@RestController
@RequestMapping("/quotas/mappings")
public class QuotaMappingController extends BaseController {
@Autowired
private QuotaMappingManager quotaMappingManager;
@Autowired
private QuotaMappingValidator quotaMappingValidator;
/**
*
* @param pageParameter
* @param sizeParameter
* @return
*/
@PreAuthorize("hasRole('ROLE_ADMIN')")
@GetMapping
public Page<QuotaMapping> getQuotaMappings(
@RequestParam("page") Optional<Integer> pageParameter,
@RequestParam("size") Optional<Integer> sizeParameter) {
return quotaMappingManager.get(pageParameter.orElse(0), sizeParameter.orElse(10), "name",
true);
}
/**
*
* @param userModel
* @return
*/
@PreAuthorize("hasRole('ROLE_ADMIN')")
@PostMapping
public QuotaMapping create(@RequestBody QuotaMapping quotaMapping) {
Errors errors = new RequestBodyErrors(quotaMapping);
quotaMappingValidator.validate(quotaMapping, errors);
if (errors.hasErrors()) {
throw new EntityResponseStatusException(errors.getAllErrors(), HttpStatus.CONFLICT);
}
return quotaMappingManager.create(quotaMapping.getItems(), quotaMapping.getName(),
quotaMapping.getValue(), quotaMapping.getUnit(), quotaMapping.isAppend(),
quotaMapping.getProducts(), quotaMapping.isDisposable());
}
/**
*
* @param userModel
* @return
*/
@PreAuthorize("hasRole('ROLE_ADMIN')")
@PostMapping("/list")
public List<QuotaMapping> createList(@RequestBody List<QuotaMapping> quotaMappings) {
List<QuotaMapping> result = Lists.newArrayList();
for (QuotaMapping quotaMapping : quotaMappings) {
Errors errors = new RequestBodyErrors(quotaMapping);
quotaMappingValidator.validate(quotaMapping, errors);
if (errors.hasErrors()) {
throw new EntityResponseStatusException(errors.getAllErrors(), HttpStatus.CONFLICT);
}
result.add(quotaMappingManager.create(quotaMapping.getItems(), quotaMapping.getName(),
quotaMapping.getValue(), quotaMapping.getUnit(), quotaMapping.isAppend(),
quotaMapping.getProducts(), quotaMapping.isDisposable()));
}
return result;
}
/**
*
* @param userModel
* @return
*/
@PreAuthorize("hasRole('ROLE_ADMIN')")
@PatchMapping
public QuotaMapping update(@RequestBody QuotaMapping quotaMapping) {
Errors errors = new RequestBodyErrors(quotaMapping);
if (errors.hasErrors()) {
throw new EntityResponseStatusException(errors.getAllErrors(), HttpStatus.CONFLICT);
}
return quotaMappingManager.update(quotaMapping);
}
/**
*
* @param userModel
* @return
*/
@PreAuthorize("hasRole('ROLE_ADMIN')")
@DeleteMapping
public void delete(@RequestBody QuotaMapping quotaMapping) {
quotaMappingManager.delete(quotaMapping.getId());
}
}
@@ -0,0 +1,107 @@
/**
*
*/
package de.bstly.we.controller;
import java.util.List;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.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.businesslogic.PretixManager;
import de.bstly.we.controller.support.EntityResponseStatusException;
import de.bstly.we.model.SystemProperty;
import de.bstly.we.repository.SystemPropertyRepository;
/**
*
* @author _bastler@bstly.de
*
*/
@RestController
@RequestMapping("/system")
public class SystemController extends BaseController {
@Autowired
private SystemPropertyRepository systemPropertyRepository;
@Autowired
private PretixManager pretixManager;
/**
*
*/
@PreAuthorize("hasRole('ROLE_ADMIN')")
@PostMapping("/pretix")
public void updatePretixClient() {
pretixManager.buildWebClient();
}
/**
*
* @param pageParameter
* @param sizeParameter
* @return
*/
@PreAuthorize("hasRole('ROLE_ADMIN')")
@GetMapping("/properties")
public List<SystemProperty> getProperties(@RequestParam("page") Optional<Integer> pageParameter,
@RequestParam("size") Optional<Integer> sizeParameter) {
Sort sort = Sort.by("key").ascending();
return systemPropertyRepository
.findAll(PageRequest.of(pageParameter.orElse(0), sizeParameter.orElse(10), sort))
.getContent();
}
/**
*
* @param key
* @return
*/
@PreAuthorize("hasRole('ROLE_ADMIN')")
@GetMapping("/properties/{key}")
public SystemProperty getProperty(@PathVariable("key") String key) {
if (!systemPropertyRepository.existsById(key)) {
throw new EntityResponseStatusException(HttpStatus.NO_CONTENT);
}
return systemPropertyRepository.findById(key).get();
}
/**
*
* @param systemProperty
* @return
*/
@PreAuthorize("hasRole('ROLE_ADMIN')")
@PostMapping("/properties")
public SystemProperty createOrUpdate(@RequestBody SystemProperty systemProperty) {
return systemPropertyRepository.save(systemProperty);
}
/**
*
* @param key
* @return
*/
@PreAuthorize("hasRole('ROLE_ADMIN')")
@DeleteMapping("/properties/{key}")
public void deleteProperty(@PathVariable("key") String key) {
if (!systemPropertyRepository.existsById(key)) {
throw new EntityResponseStatusException(HttpStatus.NOT_MODIFIED);
}
systemPropertyRepository.deleteById(key);
}
}
@@ -0,0 +1,115 @@
/**
*
*/
package de.bstly.we.controller;
import java.util.List;
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.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 com.beust.jcommander.internal.Lists;
import de.bstly.we.businesslogic.SystemProfileFieldManager;
import de.bstly.we.controller.support.EntityResponseStatusException;
import de.bstly.we.model.SystemProfileField;
/**
* @author _bastler@bstly.de
*
*/
@RestController
@RequestMapping("/profiles/system")
public class SystemProfileFieldController extends BaseController {
@Autowired
private SystemProfileFieldManager systemProfileFieldManager;
/**
*
* @param pageParameter
* @param sizeParameter
* @return
*/
@PreAuthorize("hasRole('ROLE_ADMIN')")
@GetMapping
public Page<SystemProfileField> get(@RequestParam("page") Optional<Integer> pageParameter,
@RequestParam("size") Optional<Integer> sizeParameter) {
return systemProfileFieldManager.get(pageParameter.orElse(0), sizeParameter.orElse(10),
"name", true);
}
/**
*
* @param name
* @return
*/
@PreAuthorize("hasRole('ROLE_ADMIN')")
@GetMapping("/{name}")
public SystemProfileField getByName(@PathVariable("name") String name) {
SystemProfileField systemProfileField = systemProfileFieldManager.get(name);
if (systemProfileField == null) {
throw new EntityResponseStatusException(HttpStatus.NO_CONTENT);
}
return systemProfileField;
}
/**
*
* @param systemProfileField
* @return
*/
@PreAuthorize("hasRole('ROLE_ADMIN')")
@PostMapping
public SystemProfileField update(@RequestBody SystemProfileField systemProfileField) {
return systemProfileFieldManager.save(systemProfileField);
}
/**
*
* @param systemProfileField
* @return
*/
@PreAuthorize("hasRole('ROLE_ADMIN')")
@PostMapping("/list")
public List<SystemProfileField> updateList(
@RequestBody List<SystemProfileField> systemProfileFields) {
List<SystemProfileField> result = Lists.newArrayList();
for (SystemProfileField systemProfileField : systemProfileFields) {
result.add(systemProfileFieldManager.save(systemProfileField));
}
return result;
}
/**
*
* @param name
*/
@PreAuthorize("hasRole('ROLE_ADMIN')")
@DeleteMapping("/{name}")
public void deleteByName(@PathVariable("name") String name) {
SystemProfileField systemProfileField = systemProfileFieldManager.get(name);
if (systemProfileField == null) {
throw new EntityResponseStatusException(HttpStatus.NOT_MODIFIED);
}
systemProfileFieldManager.delete(name);
}
}
@@ -0,0 +1,141 @@
/**
*
*/
package de.bstly.we.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
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.PatchMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import de.bstly.we.businesslogic.PermissionManager;
import de.bstly.we.businesslogic.QuotaManager;
import de.bstly.we.businesslogic.Quotas;
import de.bstly.we.businesslogic.UserAliasManager;
import de.bstly.we.controller.support.EntityResponseStatusException;
import de.bstly.we.controller.support.RequestBodyErrors;
import de.bstly.we.controller.validation.UserAliasValidator;
import de.bstly.we.model.Quota;
import de.bstly.we.model.UserAlias;
/**
* @author _bastler@bstly.de
*
*/
@RestController
@RequestMapping("/users/aliases")
public class UserAliasController extends BaseController {
@Autowired
private QuotaManager quotaManager;
@Autowired
private UserAliasManager userAliasManager;
@Autowired
private UserAliasValidator userAliasValidator;
@Autowired
private PermissionManager permissionManager;
/**
*
* @param alias
* @return
*/
@PreAuthorize("isAuthenticated()")
@PostMapping
public UserAlias createAlias(@RequestBody UserAlias userAlias) {
if (!permissionManager.isFullUser(getCurrentUserId())) {
throw new EntityResponseStatusException(HttpStatus.FORBIDDEN);
}
Quota aliasCreation = quotaManager.get(getCurrentUserId(), Quotas.ALIAS_CREATION);
if (aliasCreation == null || aliasCreation.getValue() < 1) {
throw new EntityResponseStatusException(HttpStatus.CONFLICT);
}
userAlias.setTarget(getCurrentUserId());
Errors errors = new RequestBodyErrors(userAlias);
userAliasValidator.validate(userAlias, errors);
if (errors.hasErrors()) {
throw new EntityResponseStatusException(errors.getAllErrors(), HttpStatus.CONFLICT);
}
aliasCreation.setValue(aliasCreation.getValue() - 1);
quotaManager.update(aliasCreation);
return userAliasManager.save(userAlias);
}
/**
*
* @param alias
* @return
*/
@PreAuthorize("isAuthenticated()")
@PatchMapping
public UserAlias updateAlias(@RequestBody UserAlias userAlias) {
if (userAlias.getId() == null) {
throw new EntityResponseStatusException(HttpStatus.CONFLICT);
}
UserAlias oldAlias = userAliasManager.get(userAlias.getId());
if (oldAlias == null) {
throw new EntityResponseStatusException(HttpStatus.CONFLICT);
}
if (!oldAlias.getTarget().equals(getCurrentUserId())) {
throw new EntityResponseStatusException(HttpStatus.FORBIDDEN);
}
oldAlias.setVisibility(userAlias.getVisibility());
return userAliasManager.save(oldAlias);
}
/**
*
* @return
*/
@PreAuthorize("isAuthenticated()")
@GetMapping
public List<UserAlias> getAliases() {
return userAliasManager.getAllByTarget(getCurrentUserId());
}
/**
*
* @param id
*/
@PreAuthorize("isAuthenticated()")
@DeleteMapping("/{id}")
public void deleteAlias(@PathVariable("id") Long id) {
UserAlias userAlias = userAliasManager.get(id);
if (userAlias == null || !userAlias.getTarget().equals(getCurrentUserId())) {
throw new EntityResponseStatusException(HttpStatus.CONFLICT);
}
Quota aliasCreation = quotaManager.get(getCurrentUserId(), Quotas.ALIAS_CREATION);
if (aliasCreation == null) {
aliasCreation = quotaManager.create(getCurrentUserId(), Quotas.ALIAS_CREATION, 0, "#",
true);
}
aliasCreation.setValue(aliasCreation.getValue() + 1);
quotaManager.update(aliasCreation);
userAliasManager.delete(id);
}
}
@@ -0,0 +1,105 @@
/**
*
*/
package de.bstly.we.controller;
import java.util.List;
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.businesslogic.UserAliasManager;
import de.bstly.we.businesslogic.UserManager;
import de.bstly.we.controller.support.EntityResponseStatusException;
import de.bstly.we.controller.support.RequestBodyErrors;
import de.bstly.we.controller.validation.UserAliasValidator;
import de.bstly.we.model.User;
import de.bstly.we.model.UserAlias;
/**
* @author _bastler@bstly.de
*
*/
@RestController
@RequestMapping("/users/aliases/manage")
public class UserAliasManagementController extends BaseController {
@Autowired
private UserManager userManager;
@Autowired
private UserAliasManager userAliasManager;
@Autowired
private UserAliasValidator userAliasValidator;
/**
*
* @return
*/
@PreAuthorize("hasRole('ROLE_ADMIN')")
@GetMapping
public Page<UserAlias> getAliases(@RequestParam("page") Optional<Integer> pageParameter,
@RequestParam("size") Optional<Integer> sizeParameter) {
return userAliasManager.get(pageParameter.orElse(0), sizeParameter.orElse(10), "id", true);
}
/**
*
* @return
*/
@PreAuthorize("hasRole('ROLE_ADMIN')")
@GetMapping("/{username}")
public List<UserAlias> getAliasesForUser(@PathVariable("username") String username) {
User user = userManager.getByUsername(username);
if (user == null) {
throw new EntityResponseStatusException(HttpStatus.CONFLICT);
}
return userAliasManager.getAllByTarget(user.getId());
}
/**
*
* @param alias
* @return
*/
@PreAuthorize("hasRole('ROLE_ADMIN')")
@PostMapping
public UserAlias createOrUpdateAlias(@RequestBody UserAlias userAlias) {
Errors errors = new RequestBodyErrors(userAlias);
userAliasValidator.validate(userAlias, errors);
if (errors.hasErrors()) {
throw new EntityResponseStatusException(errors.getAllErrors(), HttpStatus.CONFLICT);
}
return userAliasManager.save(userAlias);
}
/**
*
* @param id
*/
@PreAuthorize("hasRole('ROLE_ADMIN')")
@DeleteMapping("/{id}")
public void deleteAlias(@PathVariable("id") Long id) {
UserAlias userAlias = userAliasManager.get(id);
if (userAlias == null) {
throw new EntityResponseStatusException(HttpStatus.CONFLICT);
}
userAliasManager.delete(id);
}
}
@@ -0,0 +1,257 @@
/**
*
*/
package de.bstly.we.controller;
import javax.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.util.StringUtils;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PatchMapping;
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.beust.jcommander.internal.Lists;
import de.bstly.we.businesslogic.PermissionManager;
import de.bstly.we.businesslogic.PretixManager;
import de.bstly.we.businesslogic.PretixManager.ITEM_STATUS;
import de.bstly.we.businesslogic.QuotaManager;
import de.bstly.we.businesslogic.UserManager;
import de.bstly.we.businesslogic.UserProfileFieldManager;
import de.bstly.we.controller.model.ItemResultModel;
import de.bstly.we.controller.model.PasswordModel;
import de.bstly.we.controller.model.UserModel;
import de.bstly.we.controller.support.EntityResponseStatusException;
import de.bstly.we.controller.support.RequestBodyErrors;
import de.bstly.we.controller.support.TokenSessionManager;
import de.bstly.we.controller.validation.PasswordModelValidator;
import de.bstly.we.controller.validation.UserModelValidator;
import de.bstly.we.controller.validation.UserProfileFieldValidator;
import de.bstly.we.model.PermissionMapping;
import de.bstly.we.model.ProfileFieldType;
import de.bstly.we.model.User;
import de.bstly.we.model.UserProfileField;
import de.bstly.we.model.Visibility;
import de.bstly.we.model.UserStatus;
/**
*
* @author _bastler@bstly.de
*
*/
@RestController
@RequestMapping("/users")
public class UserController extends BaseController {
@Autowired
private UserManager userManager;
@Autowired
private UserProfileFieldManager userProfileFieldManager;
@Autowired
private PermissionManager permissionManager;
@Autowired
private QuotaManager quotaManager;
@Autowired
private PasswordModelValidator passwordModelValidator;
@Autowired
private UserModelValidator userModelValidator;
@Autowired
private UserProfileFieldValidator userProfileFieldValidator;
@Autowired
private TokenSessionManager tokenSessionManager;
@Autowired
private PretixManager pretixManager;
@Autowired
private PasswordEncoder passwordEncoder;
/**
*
* @return
*/
@PreAuthorize("isAuthenticated()")
@GetMapping
public UserModel get() {
User user = userManager.get(getCurrentUserId());
UserModel userModel = new UserModel();
userModel.setUsername(user.getUsername());
userModel.setStatus(user.getStatus());
return userModel;
}
/**
*
* @param userModel
* @param session
* @return
*/
@PostMapping("/model")
public UserModel checkModel(@RequestBody UserModel userModel, HttpSession session) {
Errors errors = new RequestBodyErrors(userModel);
userModelValidator.validate(userModel, errors);
if (errors.hasErrors()) {
throw new EntityResponseStatusException(errors.getAllErrors(), HttpStatus.CONFLICT);
}
return userModel;
}
/**
*
* @param userModel
* @param session
* @return
*/
@PreAuthorize("isAnonymous()")
@PostMapping
public UserModel register(@RequestBody UserModel userModel, HttpSession session) {
Errors errors = new RequestBodyErrors(userModel);
if (tokenSessionManager.getTokenFromSession(session).isEmpty()) {
if (StringUtils.hasText(userModel.getToken())) {
String secret = userModel.getToken();
ITEM_STATUS status = pretixManager.getItemStatus(secret);
if (status == ITEM_STATUS.PAID) {
tokenSessionManager.addTokenToSession(secret, session);
} else if (pretixManager.getItemStatus(secret) == ITEM_STATUS.REDEEMED) {
throw new EntityResponseStatusException(HttpStatus.GONE);
}
} else {
throw new EntityResponseStatusException(HttpStatus.UNAUTHORIZED);
}
}
boolean register = false;
for (String token : tokenSessionManager.getTokenFromSession(session)) {
for (PermissionMapping permissionMapping : tokenSessionManager
.getPermissionMappingsForToken(getCurrentUserId(), token)) {
if (!permissionMapping.isAddon()) {
register = true;
break;
}
}
}
if (!register) {
throw new EntityResponseStatusException(HttpStatus.UNAUTHORIZED);
}
userModelValidator.validate(userModel, errors);
passwordModelValidator.validate(userModel, errors);
if (userModel.getProfileFields() == null) {
userModel.setProfileFields(Lists.newArrayList());
}
if (userModel.getStatus() == null) {
userModel.setStatus(UserStatus.NORMAL);
}
for (UserProfileField userProfileField : userModel.getProfileFields()) {
userProfileFieldValidator.validate(userProfileField, errors);
}
if (errors.hasErrors()) {
throw new EntityResponseStatusException(errors.getAllErrors(), HttpStatus.CONFLICT);
}
User user = userManager.create(userModel.getUsername(), userModel.getPassword(),
userModel.getStatus());
for (UserProfileField userProfileField : userModel.getProfileFields()) {
userProfileField.setTarget(user.getId());
if (userProfileField.getType() == null) {
userProfileField.setType(ProfileFieldType.TEXT);
}
if (userProfileField.getVisibility() == null) {
userProfileField.setVisibility(Visibility.PRIVATE);
}
userProfileField = userProfileFieldManager.save(userProfileField);
}
UserModel responseModel = new UserModel();
responseModel.setUsername(user.getUsername());
responseModel.setStatus(user.getStatus());
ItemResultModel result = tokenSessionManager.applyTokens(user.getId(),
tokenSessionManager.getTokenFromSession(session));
responseModel.setPermissionMappings(result.getPermissionMappings());
responseModel.setPermissions(permissionManager.getNotExpiresByTarget(user.getId()));
responseModel.setQuotaMappings(result.getQuotaMappings());
responseModel.setQuotas(quotaManager.getNotExpiresByTarget(user.getId()));
responseModel.setProfileFields(userProfileFieldManager.getAllByTarget(user.getId()));
tokenSessionManager.removeTokensFromSession(session);
return responseModel;
}
/**
*
* @param passwordModel
*/
@PreAuthorize("isAuthenticated()")
@PatchMapping("/password")
public void changePassword(@RequestBody PasswordModel passwordModel) {
Errors errors = new RequestBodyErrors(passwordModel);
User user = userManager.get(getCurrentUserId());
if (!StringUtils.hasText(passwordModel.getOld()) || !passwordEncoder
.matches(passwordModel.getOld(), userManager.getPasswordHash(user.getId()))) {
throw new EntityResponseStatusException(HttpStatus.UNAUTHORIZED);
}
passwordModelValidator.validate(passwordModel, errors);
if (errors.hasErrors()) {
throw new EntityResponseStatusException(errors.getAllErrors(), HttpStatus.CONFLICT);
}
userManager.setPassword(user.getId(), passwordModel.getPassword());
}
/**
*
* @param userModel
*/
@PreAuthorize("isAuthenticated()")
@PatchMapping
public void update(@RequestBody UserModel userModel) {
User user = userManager.get(getCurrentUserId());
if (StringUtils.hasText(userModel.getOld())) {
Errors errors = new RequestBodyErrors(userModel);
if (!passwordEncoder.matches(userModel.getOld(),
userManager.getPasswordHash(getCurrentUserId()))) {
throw new EntityResponseStatusException(HttpStatus.UNAUTHORIZED);
}
passwordModelValidator.validate(userModel, errors);
if (errors.hasErrors()) {
throw new EntityResponseStatusException(errors.getAllErrors(), HttpStatus.CONFLICT);
}
user = userManager.setPassword(user.getId(), userModel.getPassword());
}
if (userModel.getStatus() != null) {
user.setStatus(userModel.getStatus());
}
user = userManager.update(user);
}
}
@@ -0,0 +1,129 @@
/**
*
*/
package de.bstly.we.controller;
import java.util.List;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.beans.factory.annotation.Autowired;
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.PatchMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import de.bstly.we.businesslogic.PermissionManager;
import de.bstly.we.businesslogic.UserDomainManager;
import de.bstly.we.controller.support.EntityResponseStatusException;
import de.bstly.we.controller.support.RequestBodyErrors;
import de.bstly.we.controller.validation.UserDomainValidator;
import de.bstly.we.model.UserDomain;
import de.bstly.we.model.Visibility;
/**
* @author _bastler@bstly.de
*
*/
@RestController
@RequestMapping("/users/domains")
public class UserDomainController extends BaseController {
@Autowired
private UserDomainManager userDomainManager;
@Autowired
private UserDomainValidator userDomainValidator;
@Autowired
private PermissionManager permissionManager;
/**
*
* @param userDomain
* @return
*/
@PreAuthorize("isAuthenticated()")
@PostMapping
public UserDomain createDomain(@RequestBody UserDomain userDomain) {
if (!permissionManager.isFullUser(getCurrentUserId())) {
throw new EntityResponseStatusException(HttpStatus.FORBIDDEN);
}
if (userDomain.getVisibility() == null) {
userDomain.setVisibility(Visibility.PRIVATE);
}
userDomain.setTarget(getCurrentUserId());
userDomain.setValidated(false);
userDomain.setSecret(
RandomStringUtils.random(UserDomainManager.DEFAULT_SECRET_LENGTH, true, true));
Errors errors = new RequestBodyErrors(userDomain);
userDomainValidator.validate(userDomain, errors);
if (errors.hasErrors()) {
throw new EntityResponseStatusException(errors.getAllErrors(), HttpStatus.CONFLICT);
}
return userDomainManager.save(userDomain);
}
/**
*
* @param userDomain
* @return
*/
@PreAuthorize("isAuthenticated()")
@PatchMapping
public UserDomain updateDomain(@RequestBody UserDomain userDomain) {
if (userDomain.getId() == null) {
throw new EntityResponseStatusException(HttpStatus.CONFLICT);
}
UserDomain oldDomain = userDomainManager.get(userDomain.getId());
if (oldDomain == null) {
throw new EntityResponseStatusException(HttpStatus.CONFLICT);
}
if (!oldDomain.getTarget().equals(getCurrentUserId())) {
throw new EntityResponseStatusException(HttpStatus.FORBIDDEN);
}
oldDomain.setVisibility(userDomain.getVisibility());
return userDomainManager.save(oldDomain);
}
/**
*
* @return
*/
@PreAuthorize("isAuthenticated()")
@GetMapping
public List<UserDomain> getDomains() {
return userDomainManager.getAllByTarget(getCurrentUserId());
}
/**
*
* @param id
*/
@PreAuthorize("isAuthenticated()")
@DeleteMapping("/{id}")
public void deleteDomain(@PathVariable("id") Long id) {
UserDomain userDomain = userDomainManager.get(id);
if (userDomain == null || !userDomain.getTarget().equals(getCurrentUserId())) {
throw new EntityResponseStatusException(HttpStatus.CONFLICT);
}
userDomainManager.delete(id);
}
}
@@ -0,0 +1,142 @@
/**
*
*/
package de.bstly.we.controller;
import java.util.List;
import java.util.Optional;
import javax.naming.NamingException;
import org.apache.commons.lang3.RandomStringUtils;
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.businesslogic.UserDomainManager;
import de.bstly.we.businesslogic.UserManager;
import de.bstly.we.controller.support.EntityResponseStatusException;
import de.bstly.we.controller.support.RequestBodyErrors;
import de.bstly.we.controller.validation.UserDomainValidator;
import de.bstly.we.model.User;
import de.bstly.we.model.UserDomain;
import de.bstly.we.model.Visibility;
/**
* @author _bastler@bstly.de
*
*/
@RestController
@RequestMapping("/users/domains/manage")
public class UserDomainManagementController extends BaseController {
@Autowired
private UserManager userManager;
@Autowired
private UserDomainManager userDomainManager;
@Autowired
private UserDomainValidator userDomainValidator;
/**
*
* @return
*/
@PreAuthorize("hasRole('ROLE_ADMIN')")
@GetMapping
public Page<UserDomain> getDomains(@RequestParam("page") Optional<Integer> pageParameter,
@RequestParam("size") Optional<Integer> sizeParameter) {
return userDomainManager.get(pageParameter.orElse(0), sizeParameter.orElse(10), "id", true);
}
/**
*
* @return
*/
@PreAuthorize("hasRole('ROLE_ADMIN')")
@GetMapping("/{username}")
public List<UserDomain> getDomainsForUser(@PathVariable("username") String username) {
User user = userManager.getByUsername(username);
if (user == null) {
throw new EntityResponseStatusException(HttpStatus.CONFLICT);
}
return userDomainManager.getAllByTarget(user.getId());
}
/**
*
* @param alias
* @return
*/
@PreAuthorize("hasRole('ROLE_ADMIN')")
@PostMapping
public UserDomain createOrUpdateDomain(@RequestBody UserDomain userDomain) {
if (userDomain.getVisibility() == null) {
userDomain.setVisibility(Visibility.PRIVATE);
}
Errors errors = new RequestBodyErrors(userDomain);
userDomainValidator.validate(userDomain, errors);
if (errors.hasErrors()) {
throw new EntityResponseStatusException(errors.getAllErrors(), HttpStatus.CONFLICT);
}
if (userDomain.getId() == null) {
userDomain.setValidated(false);
userDomain.setSecret(
RandomStringUtils.random(UserDomainManager.DEFAULT_SECRET_LENGTH, true, true));
}
return userDomainManager.save(userDomain);
}
/**
*
* @param id
*/
@PreAuthorize("hasRole('ROLE_ADMIN')")
@DeleteMapping("/{id}")
public void deleteDomain(@PathVariable("id") Long id) {
UserDomain userDomain = userDomainManager.get(id);
if (userDomain == null) {
throw new EntityResponseStatusException(HttpStatus.CONFLICT);
}
userDomainManager.delete(id);
}
/**
*
* @param id
*/
@PreAuthorize("hasRole('ROLE_ADMIN')")
@PostMapping("/validate/{id}")
public void validate(@PathVariable("id") Long id) {
UserDomain userDomain = userDomainManager.get(id);
if (userDomain == null) {
throw new EntityResponseStatusException(HttpStatus.CONFLICT);
}
try {
if (userDomainManager.validate(userDomain)) {
throw new EntityResponseStatusException(HttpStatus.ACCEPTED);
}
} catch (NamingException e) {
e.printStackTrace();
}
throw new EntityResponseStatusException(HttpStatus.NOT_ACCEPTABLE);
}
}
@@ -0,0 +1,229 @@
/**
*
*/
package de.bstly.we.controller;
import java.time.Instant;
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.PatchMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.beust.jcommander.internal.Lists;
import de.bstly.we.businesslogic.PermissionManager;
import de.bstly.we.businesslogic.QuotaManager;
import de.bstly.we.businesslogic.UserDataManager;
import de.bstly.we.businesslogic.UserManager;
import de.bstly.we.businesslogic.UserProfileFieldManager;
import de.bstly.we.businesslogic.support.InstantHelper;
import de.bstly.we.controller.model.UserModel;
import de.bstly.we.controller.support.EntityResponseStatusException;
import de.bstly.we.controller.support.RequestBodyErrors;
import de.bstly.we.controller.validation.PasswordModelValidator;
import de.bstly.we.controller.validation.UserModelValidator;
import de.bstly.we.controller.validation.UserProfileFieldValidator;
import de.bstly.we.model.Permission;
import de.bstly.we.model.PermissionMapping;
import de.bstly.we.model.ProfileFieldType;
import de.bstly.we.model.Quota;
import de.bstly.we.model.QuotaMapping;
import de.bstly.we.model.User;
import de.bstly.we.model.UserProfileField;
import de.bstly.we.model.UserStatus;
import de.bstly.we.model.Visibility;
/**
*
* @author _bastler@bstly.de
*
*/
@RestController
@RequestMapping("/users/manage")
public class UserManagementController extends BaseController {
@Autowired
private UserManager userManager;
@Autowired
private PermissionManager permissionManager;
@Autowired
private QuotaManager quotaManager;
@Autowired
private UserProfileFieldManager userProfileFieldManager;
@Autowired
private PasswordModelValidator passwordModelValidator;
@Autowired
private UserModelValidator userModelValidator;
@Autowired
private UserProfileFieldValidator userProfileFieldValidator;
@Autowired
private UserDataManager userDataManager;
/**
*
* @param pageParameter
* @param sizeParameter
* @return
*/
@PreAuthorize("hasRole('ROLE_ADMIN')")
@GetMapping
public Page<User> getUsers(@RequestParam("page") Optional<Integer> pageParameter,
@RequestParam("size") Optional<Integer> sizeParameter) {
return userManager.get(pageParameter.orElse(0), sizeParameter.orElse(10), "username", true);
}
/**
*
* @param username
* @return
*/
@PreAuthorize("hasRole('ROLE_ADMIN')")
@GetMapping("/{username}")
public User getUserByUsername(@PathVariable("username") String username) {
User user = userManager.getByUsername(username);
if (user == null) {
throw new EntityResponseStatusException(HttpStatus.NO_CONTENT);
}
return user;
}
/**
*
* @param userModel
* @return
*/
@PreAuthorize("hasRole('ROLE_ADMIN')")
@PostMapping
public User create(@RequestBody UserModel userModel) {
Errors errors = new RequestBodyErrors(userModel);
userModelValidator.validate(userModel, errors);
passwordModelValidator.validate(userModel, errors);
if (userModel.getStatus() == null) {
userModel.setStatus(UserStatus.SLEEP);
}
if (userModel.getProfileFields() == null) {
userModel.setProfileFields(Lists.newArrayList());
}
for (UserProfileField userProfileField : userModel.getProfileFields()) {
userProfileFieldValidator.validate(userProfileField, errors);
}
if (errors.hasErrors()) {
throw new EntityResponseStatusException(errors.getAllErrors(), HttpStatus.CONFLICT);
}
User user = userManager.create(userModel.getUsername(), userModel.getPassword(),
userModel.getStatus());
if (userModel.getPermissionMappings() != null) {
for (PermissionMapping permissionMapping : userModel.getPermissionMappings()) {
for (String name : permissionMapping.getNames()) {
permissionManager.create(user.getId(), name, permissionMapping.isAddon(), null,
InstantHelper.plus(Instant.now(), permissionMapping.getLifetime(),
permissionMapping.getLifetimeUnit()));
}
}
}
if (userModel.getPermissions() != null) {
for (Permission permission : userModel.getPermissions()) {
permissionManager.create(user.getId(), permission.getName(), permission.isAddon(),
permission.getStarts(), permission.getExpires());
}
}
if (userModel.getQuotaMappings() != null) {
for (QuotaMapping quotaMapping : userModel.getQuotaMappings()) {
quotaManager.create(user.getId(), quotaMapping.getName(), quotaMapping.getValue(),
quotaMapping.getUnit(), quotaMapping.isDisposable());
}
}
if (userModel.getQuotas() != null) {
for (Quota quota : userModel.getQuotas()) {
quotaManager.create(user.getId(), quota.getName(), quota.getValue(),
quota.getUnit(), quota.isDisposable());
}
}
for (UserProfileField userProfileField : userModel.getProfileFields()) {
userProfileField.setTarget(user.getId());
if (userProfileField.getType() == null) {
userProfileField.setType(ProfileFieldType.TEXT);
}
if (userProfileField.getVisibility() == null) {
userProfileField.setVisibility(Visibility.PRIVATE);
}
userProfileField = userProfileFieldManager.save(userProfileField);
}
return user;
}
/**
*
* @param user
* @return
*/
@PreAuthorize("hasRole('ROLE_ADMIN')")
@PatchMapping
public User update(@RequestBody User user) {
return userManager.update(user);
}
/**
*
* @param username
*/
@PreAuthorize("hasRole('ROLE_ADMIN')")
@DeleteMapping("/{username}")
public void deleteUserByUsername(@PathVariable("username") String username) {
User user = userManager.getByUsername(username);
if (user == null) {
throw new EntityResponseStatusException(HttpStatus.NOT_MODIFIED);
}
userManager.delete(user);
}
/**
*
*/
@PreAuthorize("hasRole('ROLE_ADMIN')")
@PostMapping("/purge")
public void purge(@RequestParam("username") Optional<String> username,
@RequestParam("dry") Optional<Boolean> dry) {
if (username.isPresent()) {
User user = userManager.getByUsername(username.get());
if (user == null) {
throw new EntityResponseStatusException(HttpStatus.NOT_MODIFIED);
}
userDataManager.purge(user, dry.isPresent() && dry.get());
} else {
userDataManager.purge();
}
}
}
@@ -0,0 +1,284 @@
/**
*
*/
package de.bstly.we.controller;
import java.util.List;
import java.util.Optional;
import org.apache.commons.lang3.RandomUtils;
import org.springframework.beans.factory.annotation.Autowired;
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 com.beust.jcommander.internal.Lists;
import de.bstly.we.businesslogic.PermissionManager;
import de.bstly.we.businesslogic.UserAliasManager;
import de.bstly.we.businesslogic.UserManager;
import de.bstly.we.businesslogic.UserProfileFieldManager;
import de.bstly.we.controller.model.ProfileModel;
import de.bstly.we.controller.support.EntityResponseStatusException;
import de.bstly.we.controller.support.RequestBodyErrors;
import de.bstly.we.controller.validation.UserProfileFieldValidator;
import de.bstly.we.model.ProfileFieldType;
import de.bstly.we.model.User;
import de.bstly.we.model.UserAlias;
import de.bstly.we.model.UserProfileField;
import de.bstly.we.model.Visibility;
/**
* @author _bastler@bstly.de
*
*/
@RestController
@RequestMapping("/profiles")
public class UserProfileFieldController extends BaseController {
@Autowired
private UserProfileFieldManager userProfileFieldManager;
@Autowired
private UserManager userManager;
@Autowired
private UserAliasManager userAliasManager;
@Autowired
private UserProfileFieldValidator userProfileFieldModelValidator;
@Autowired
private PermissionManager permissionManager;
/**
*
* @return
*/
@PreAuthorize("isAuthenticated()")
@GetMapping
public List<UserProfileField> get(@RequestParam("filter") Optional<String> filter) {
if (filter.isEmpty()) {
return userProfileFieldManager.getAllByTarget(getCurrentUserId());
}
return userProfileFieldManager.getByTargetFiltered(getCurrentUserId(),
Lists.newArrayList(filter.get().split(",")));
}
/**
*
* @return
*/
@PreAuthorize("isAuthenticated()")
@GetMapping("/field/{name}")
public UserProfileField getField(@PathVariable("name") String name) {
UserProfileField userProfileField = userProfileFieldManager.get(getCurrentUserId(), name);
if (userProfileField == null) {
throw new EntityResponseStatusException(HttpStatus.NO_CONTENT);
}
return userProfileField;
}
/**
*
* @return
*/
@GetMapping("/{username}")
public ProfileModel getForUser(@PathVariable("username") String username) {
Long currentUserId = getCurrentUserId();
User user = userManager.getByUsername(username);
if (user == null) {
UserAlias userAlias = userAliasManager.getByAlias(username);
if (userAlias != null) {
switch (userAlias.getVisibility()) {
case PRIVATE:
if (currentUserId != null && currentUserId.equals(userAlias.getTarget())) {
user = userManager.get(userAlias.getTarget());
}
break;
case PROTECTED:
if (currentUserId != null && permissionManager.isFullUser(getCurrentUserId())) {
user = userManager.get(userAlias.getTarget());
}
break;
case PUBLIC:
user = userManager.get(userAlias.getTarget());
break;
}
}
}
if (user == null) {
throttleForbidden();
}
List<UserProfileField> profileFields = Lists.newArrayList();
List<Visibility> visibilities = Lists.newArrayList(Visibility.PUBLIC);
if (currentUserId != null) {
visibilities.add(Visibility.PROTECTED);
if (currentUserId.equals(user.getId())) {
visibilities.add(Visibility.PRIVATE);
}
}
profileFields.addAll(
userProfileFieldManager.getAllByTargetAndVisibilities(user.getId(), visibilities));
if (profileFields.isEmpty()) {
throttleForbidden();
}
List<String> aliases = Lists.newArrayList();
for (UserAlias userAlias : userAliasManager.getAllByTarget(user.getId())) {
switch (userAlias.getVisibility()) {
case PRIVATE:
if (currentUserId != null && currentUserId.equals(user.getId())) {
aliases.add(userAlias.getAlias());
}
break;
case PROTECTED:
if (currentUserId != null) {
aliases.add(userAlias.getAlias());
}
break;
case PUBLIC:
aliases.add(userAlias.getAlias());
break;
}
}
ProfileModel profileModel = new ProfileModel();
profileModel.setUsername(user.getUsername());
profileModel.setProfileFields(profileFields);
profileModel.setAliases(aliases);
return profileModel;
}
/**
*
* @return
*/
@GetMapping("/{username}/field/{name}")
public UserProfileField getFieldForUser(@PathVariable("username") String username,
@PathVariable("name") String name) {
User user = userManager.getByUsername(username);
if (user == null) {
throttleForbidden();
}
UserProfileField userProfileField = userProfileFieldManager.get(user.getId(), name);
if (userProfileField == null) {
throttleForbidden();
}
Long currentUserId = getCurrentUserId();
if (currentUserId == null && !Visibility.PUBLIC.equals(userProfileField.getVisibility())) {
throttleForbidden();
}
if (currentUserId != null && !currentUserId.equals(user.getId())
&& Visibility.PRIVATE.equals(userProfileField.getVisibility())) {
throttleForbidden();
}
return userProfileField;
}
/**
*
* @param userProfileField
* @return
*/
@PreAuthorize("isAuthenticated()")
@PostMapping
public UserProfileField createOrupdate(@RequestBody UserProfileField userProfileField) {
UserProfileField oldUserProfileField = userProfileFieldManager.get(getCurrentUserId(),
userProfileField.getName());
userProfileField.setTarget(getCurrentUserId());
Errors errors = new RequestBodyErrors(userProfileField);
userProfileFieldModelValidator.validate(userProfileField, errors);
if (errors.hasErrors()) {
throw new EntityResponseStatusException(errors.getAllErrors(), HttpStatus.CONFLICT);
}
if (oldUserProfileField == null) {
if (userProfileField.getType() == null) {
userProfileField.setType(ProfileFieldType.TEXT);
}
if (userProfileField.getVisibility() == null) {
userProfileField.setVisibility(Visibility.PRIVATE);
}
return userProfileFieldManager.save(userProfileField);
} else {
oldUserProfileField.setValue(userProfileField.getValue());
oldUserProfileField.setBlob(userProfileField.getBlob());
if (userProfileField.getType() != null) {
oldUserProfileField.setType(userProfileField.getType());
}
if (userProfileField.getVisibility() != null) {
oldUserProfileField.setVisibility(userProfileField.getVisibility());
}
if (userProfileField.getIndex() != null) {
oldUserProfileField.setIndex(userProfileField.getIndex());
}
return userProfileFieldManager.save(oldUserProfileField);
}
}
/**
*
* @param name
*/
@PreAuthorize("isAuthenticated()")
@DeleteMapping("/{name}")
public void delete(@PathVariable("name") String name) {
if (userProfileFieldManager.get(getCurrentUserId(), name) == null) {
throw new EntityResponseStatusException(HttpStatus.NOT_MODIFIED);
}
userProfileFieldManager.delete(getCurrentUserId(), name);
}
/**
*
*/
protected void throttleForbidden() {
try {
Thread.sleep(RandomUtils.nextInt(10, 500));
} catch (InterruptedException e) {
throw new EntityResponseStatusException(HttpStatus.FORBIDDEN);
}
throw new EntityResponseStatusException(HttpStatus.FORBIDDEN);
}
}
@@ -0,0 +1,75 @@
/**
*
*/
package de.bstly.we.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import de.bstly.we.businesslogic.PermissionManager;
import de.bstly.we.businesslogic.PretixManager;
import de.bstly.we.businesslogic.QuotaManager;
import de.bstly.we.businesslogic.Quotas;
import de.bstly.we.controller.support.EntityResponseStatusException;
import de.bstly.we.model.Quota;
/**
*
* @author _bastler@bstly.de
*
*/
@RestController
@RequestMapping("/vouchers")
public class VoucherController extends BaseController {
@Autowired
private QuotaManager quotaManager;
@Autowired
private PretixManager pretixManager;
@Autowired
private PermissionManager permissionManager;
/**
*
* @return
*/
@PreAuthorize("isAuthenticated()")
@PostMapping("/registration")
public String getRegistrationVoucher() {
Quota registrationVouchers = quotaManager.get(getCurrentUserId(),
Quotas.REGISTRATION_VOUCHERS);
if (registrationVouchers == null || registrationVouchers.getValue() < 1) {
throw new EntityResponseStatusException(HttpStatus.CONFLICT);
}
if (!permissionManager.isFullUser(getCurrentUserId())) {
throw new EntityResponseStatusException(HttpStatus.FORBIDDEN);
}
String result = pretixManager.createRegistrationVoucher().get("code").getAsString();
registrationVouchers.setValue(registrationVouchers.getValue() - 1);
quotaManager.update(registrationVouchers);
return result;
}
/**
*
* @return
*/
@PreAuthorize("isAuthenticated()")
@PostMapping("/addon")
public String getAddonVoucher() {
if (!permissionManager.isFullUser(getCurrentUserId())) {
throw new EntityResponseStatusException(HttpStatus.FORBIDDEN);
}
return pretixManager.createAddOnVoucher().get("code").getAsString();
}
}
@@ -0,0 +1,64 @@
/**
*
*/
package de.bstly.we.controller.debug;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.session.FindByIndexNameSessionRepository;
import org.springframework.session.Session;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import de.bstly.we.controller.BaseController;
import de.bstly.we.model.User;
import de.bstly.we.repository.UserRepository;
/**
* @author _bastler@bstly.de
*
*/
@RestController
@RequestMapping("/migration")
public class MigrationController extends BaseController {
@Autowired
private UserRepository userRepository;
@Autowired
private FindByIndexNameSessionRepository<? extends Session> sessionRepository;
/**
*
*/
@PreAuthorize("hasRole('ROLE_ADMIN')")
@DeleteMapping("/sessions")
public void deleteAllSessions() {
Pageable pageable = PageRequest.of(0, 100, Sort.by("id"));
Page<User> page;
do {
page = userRepository.findAll(pageable);
for (User user : page.getContent()) {
try {
Map<String, ? extends Session> usersSessions = sessionRepository
.findByPrincipalName(user.getUsername());
for (Session session : usersSessions.values()) {
sessionRepository.deleteById(session.getId());
}
} catch (Exception e) {
e.printStackTrace();
}
}
pageable = page.nextPageable();
} while (page.hasNext());
}
}
@@ -0,0 +1,45 @@
/**
*
*/
package de.bstly.we.controller.model;
import java.util.Map;
/**
* @author _bastler@bstly.de
*
*/
public class ItemModel {
private Map<String, String> name;
private String secret;
/**
* @return the name
*/
public Map<String, String> getName() {
return name;
}
/**
* @param name the name to set
*/
public void setName(Map<String, String> name) {
this.name = name;
}
/**
* @return the secret
*/
public String getSecret() {
return secret;
}
/**
* @param secret the secret to set
*/
public void setSecret(String secret) {
this.secret = secret;
}
}
@@ -0,0 +1,48 @@
/**
*
*/
package de.bstly.we.controller.model;
import java.util.List;
import de.bstly.we.model.PermissionMapping;
import de.bstly.we.model.QuotaMapping;
/**
* @author _bastler@bstly.de
*
*/
public class ItemResultModel {
private List<PermissionMapping> permissionMappings;
private List<QuotaMapping> quotaMappings;
/**
* @return the permissionMappings
*/
public List<PermissionMapping> getPermissionMappings() {
return permissionMappings;
}
/**
* @param permissionMappings the permissionMappings to set
*/
public void setPermissionMappings(List<PermissionMapping> permissionMappings) {
this.permissionMappings = permissionMappings;
}
/**
* @return the quotaMappings
*/
public List<QuotaMapping> getQuotaMappings() {
return quotaMappings;
}
/**
* @param quotaMappings the quotaMappings to set
*/
public void setQuotaMappings(List<QuotaMapping> quotaMappings) {
this.quotaMappings = quotaMappings;
}
}
@@ -0,0 +1,44 @@
/**
*
*/
package de.bstly.we.controller.model;
/**
*
* @author _bastler@bstly.de
*
*/
public class LoginModel {
private String username;
private String password;
/**
* @return the username
*/
public String getUsername() {
return username;
}
/**
* @param username the username to set
*/
public void setUsername(String username) {
this.username = username;
}
/**
* @return the password
*/
public String getPassword() {
return password;
}
/**
* @param password the password to set
*/
public void setPassword(String password) {
this.password = password;
}
}
@@ -0,0 +1,90 @@
/**
*
*/
package de.bstly.we.controller.model;
import java.util.List;
/**
* @author _bastler@bstly.de
*
*/
public class PagesResult<T extends Object> {
private List<T> result;
private int size;
private int page;
private int totalElements;
private int totalPages;
/**
* @return the result
*/
public List<T> getResult() {
return result;
}
/**
* @param result the result to set
*/
public void setResult(List<T> result) {
this.result = result;
}
/**
* @return the size
*/
public int getSize() {
return size;
}
/**
* @param size the size to set
*/
public void setSize(int size) {
this.size = size;
}
/**
* @return the page
*/
public int getPage() {
return page;
}
/**
* @param page the page to set
*/
public void setPage(int page) {
this.page = page;
}
/**
* @return the totalElements
*/
public int getTotalElements() {
return totalElements;
}
/**
* @param totalElements the totalElements to set
*/
public void setTotalElements(int totalElements) {
this.totalElements = totalElements;
}
/**
* @return the totalPages
*/
public int getTotalPages() {
return totalPages;
}
/**
* @param totalPages the totalPages to set
*/
public void setTotalPages(int totalPages) {
this.totalPages = totalPages;
}
}
@@ -0,0 +1,58 @@
/**
*
*/
package de.bstly.we.controller.model;
/**
*
* @author _bastler@bstly.de
*
*/
public class PasswordModel {
private String old;
private String password;
private String password2;
/**
* @return the old
*/
public String getOld() {
return old;
}
/**
* @param old the old to set
*/
public void setOld(String old) {
this.old = old;
}
/**
* @return the password
*/
public String getPassword() {
return password;
}
/**
* @param password the password to set
*/
public void setPassword(String password) {
this.password = password;
}
/**
* @return the password2
*/
public String getPassword2() {
return password2;
}
/**
* @param password2 the password2 to set
*/
public void setPassword2(String password2) {
this.password2 = password2;
}
}
@@ -0,0 +1,28 @@
/**
*
*/
package de.bstly.we.controller.model;
/**
* @author _bastler@bstly.de
*
*/
public class PasswordResetModel extends PasswordModel {
private String token;
/**
* @return the token
*/
public String getToken() {
return token;
}
/**
* @param token the token to set
*/
public void setToken(String token) {
this.token = token;
}
}
@@ -0,0 +1,78 @@
/**
*
*/
package de.bstly.we.controller.model;
import java.util.Map;
import org.springframework.http.HttpMethod;
/**
*
* @author _bastler@bstly.de
*
*/
public class PretixRequest {
private String path;
private HttpMethod method;
private Map<String, String> queryParameters;
private Object payload;
/**
* @return the path
*/
public String getPath() {
return path;
}
/**
* @param path the path to set
*/
public void setPath(String path) {
this.path = path;
}
/**
* @return the method
*/
public HttpMethod getMethod() {
return method;
}
/**
* @param method the method to set
*/
public void setMethod(HttpMethod method) {
this.method = method;
}
/**
* @return the queryParameters
*/
public Map<String, String> getQueryParameters() {
return queryParameters;
}
/**
* @param queryParameters the queryParameters to set
*/
public void setQueryParameters(Map<String, String> queryParameters) {
this.queryParameters = queryParameters;
}
/**
* @return the payload
*/
public Object getPayload() {
return payload;
}
/**
* @param payload the payload to set
*/
public void setPayload(Object payload) {
this.payload = payload;
}
}
@@ -0,0 +1,62 @@
/**
*
*/
package de.bstly.we.controller.model;
import java.util.List;
import de.bstly.we.model.UserProfileField;
/**
* @author _bastler@bstly.de
*
*/
public class ProfileModel {
private String username;
private List<String> aliases;
private List<UserProfileField> profileFields;
/**
* @return the username
*/
public String getUsername() {
return username;
}
/**
* @param username the username to set
*/
public void setUsername(String username) {
this.username = username;
}
/**
* @return the aliases
*/
public List<String> getAliases() {
return aliases;
}
/**
* @param aliases the aliases to set
*/
public void setAliases(List<String> aliases) {
this.aliases = aliases;
}
/**
* @return the profileFields
*/
public List<UserProfileField> getProfileFields() {
return profileFields;
}
/**
* @param profileFields the profileFields to set
*/
public void setProfileFields(List<UserProfileField> profileFields) {
this.profileFields = profileFields;
}
}
@@ -0,0 +1,53 @@
/**
*
*/
package de.bstly.we.controller.model;
/**
* @author _bastler@bstly.de
*
*/
public class SecondFactorProviderModel {
private String id;
private boolean request;
/**
* @param provider
* @param request
*/
public SecondFactorProviderModel(String id, boolean request) {
super();
this.id = id;
this.request = request;
}
/**
* @return the id
*/
public String getId() {
return id;
}
/**
* @param id the id to set
*/
public void setId(String id) {
this.id = id;
}
/**
* @return the request
*/
public boolean isRequest() {
return request;
}
/**
* @param request the request to set
*/
public void setRequest(boolean request) {
this.request = request;
}
}
@@ -0,0 +1,143 @@
/**
*
*/
package de.bstly.we.controller.model;
import java.util.List;
import de.bstly.we.model.Permission;
import de.bstly.we.model.PermissionMapping;
import de.bstly.we.model.Quota;
import de.bstly.we.model.QuotaMapping;
import de.bstly.we.model.UserProfileField;
import de.bstly.we.model.UserStatus;
/**
*
* @author _bastler@bstly.de
*
*/
public class UserModel extends PasswordModel {
private String username;
private List<Permission> permissions;
private List<PermissionMapping> permissionMappings;
private List<Quota> quotas;
private List<QuotaMapping> quotaMappings;
private UserStatus status;
private String token;
private List<UserProfileField> profileFields;
/**
* @return the username
*/
public String getUsername() {
return username;
}
/**
* @param username the username to set
*/
public void setUsername(String username) {
this.username = username;
}
/**
* @return the permissions
*/
public List<Permission> getPermissions() {
return permissions;
}
/**
* @param permissions the permissions to set
*/
public void setPermissions(List<Permission> permissions) {
this.permissions = permissions;
}
/**
* @return the permissionMappings
*/
public List<PermissionMapping> getPermissionMappings() {
return permissionMappings;
}
/**
* @param permissionMappings the permissionMappings to set
*/
public void setPermissionMappings(List<PermissionMapping> permissionMappings) {
this.permissionMappings = permissionMappings;
}
/**
* @return the quotas
*/
public List<Quota> getQuotas() {
return quotas;
}
/**
* @param quotas the quotas to set
*/
public void setQuotas(List<Quota> quotas) {
this.quotas = quotas;
}
/**
* @return the quotaMappings
*/
public List<QuotaMapping> getQuotaMappings() {
return quotaMappings;
}
/**
* @param quotaMappings the quotaMappings to set
*/
public void setQuotaMappings(List<QuotaMapping> quotaMappings) {
this.quotaMappings = quotaMappings;
}
/**
* @return the status
*/
public UserStatus getStatus() {
return status;
}
/**
* @param status the status to set
*/
public void setStatus(UserStatus status) {
this.status = status;
}
/**
* @return the token
*/
public String getToken() {
return token;
}
/**
* @param token the token to set
*/
public void setToken(String token) {
this.token = token;
}
/**
* @return the profileFields
*/
public List<UserProfileField> getProfileFields() {
return profileFields;
}
/**
* @param profileFields the profileFields to set
*/
public void setProfileFields(List<UserProfileField> profileFields) {
this.profileFields = profileFields;
}
}
@@ -0,0 +1,47 @@
/**
*
*/
package de.bstly.we.controller.support;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
/**
*
* @author _bastler@bstly.de
*
*/
@ControllerAdvice
public class ControllerExceptionHandler extends ResponseEntityExceptionHandler {
/**
*
* @param exception
* @param request
* @return
*/
@ExceptionHandler(value = { EntityResponseStatusException.class })
protected ResponseEntity<Object> handleResponseEntityStatusException(RuntimeException exception,
WebRequest request) {
EntityResponseStatusException entityResponseStatusException = (EntityResponseStatusException) exception;
return handleExceptionInternal(exception, entityResponseStatusException.getBody(), new HttpHeaders(),
entityResponseStatusException.getStatus(), request);
}
// /**
// *
// * @param exception
// * @param request
// * @return
// */
// @ExceptionHandler(value = { IllegalArgumentException.class })
// protected ResponseEntity<Object> handleRIllegalArgumentException(RuntimeException exception, WebRequest request) {
// IllegalArgumentException illegalArgumentException = (IllegalArgumentException) exception;
// return handleExceptionInternal(exception, illegalArgumentException.getMessage(), new HttpHeaders(),
// HttpStatus.BAD_REQUEST, request);
// }
}
@@ -0,0 +1,87 @@
/**
*
*/
package de.bstly.we.controller.support;
import javax.annotation.Nullable;
import org.springframework.core.NestedExceptionUtils;
import org.springframework.core.NestedRuntimeException;
import org.springframework.http.HttpStatus;
import org.springframework.util.Assert;
/**
*
* @author _bastler@bstly.de
*
*/
public class EntityResponseStatusException extends NestedRuntimeException {
/**
* default serialVersionUID
*/
private static final long serialVersionUID = 1L;
private final HttpStatus status;
@Nullable
private final Object body;
/**
*
* @param status
*/
public EntityResponseStatusException(HttpStatus status) {
this(null, status);
}
/**
*
* @param body
* @param status
*/
public EntityResponseStatusException(@Nullable Object body, HttpStatus status) {
this(body, status, null);
}
/**
*
* @param body
* @param status
* @param cause
*/
public EntityResponseStatusException(@Nullable Object body, HttpStatus status, @Nullable Throwable cause) {
super(null, cause);
Assert.notNull(status, "HttpStatus is required");
this.status = status;
this.body = body;
}
/**
*
* @return
*/
public HttpStatus getStatus() {
return this.status;
}
/**
*
* @return
*/
@Nullable
public Object getBody() {
return this.body;
}
/**
*
* @return
*/
@Override
public String getMessage() {
String msg = this.status + (this.body != null ? " \"" + this.body + "\"" : "");
return NestedExceptionUtils.buildMessage(msg, getCause());
}
}
@@ -0,0 +1,107 @@
/**
*
*/
package de.bstly.we.controller.support;
import java.io.IOException;
import java.lang.reflect.Type;
import org.springframework.core.MethodParameter;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
import com.google.gson.Gson;
import com.google.gson.JsonPrimitive;
/**
* @author _bastler@bstly.de
*
*/
@ControllerAdvice
public class JsonStringBodyControllerAdvice implements RequestBodyAdvice, ResponseBodyAdvice<String> {
private Gson gson = new Gson();
/*
* @see org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdvice#
* supports(org.springframework.core.MethodParameter, java.lang.reflect.Type,
* java.lang.Class)
*/
@Override
public boolean supports(MethodParameter methodParameter, Type targetType,
Class<? extends HttpMessageConverter<?>> converterType) {
return targetType instanceof Class && String.class.equals((Class<?>) targetType);
}
/*
* @see org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdvice#
* beforeBodyRead(org.springframework.http.HttpInputMessage,
* org.springframework.core.MethodParameter, java.lang.reflect.Type,
* java.lang.Class)
*/
@Override
public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter, Type targetType,
Class<? extends HttpMessageConverter<?>> converterType) throws IOException {
return inputMessage;
}
/*
* @see org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdvice#
* afterBodyRead(java.lang.Object, org.springframework.http.HttpInputMessage,
* org.springframework.core.MethodParameter, java.lang.reflect.Type,
* java.lang.Class)
*/
@Override
public Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType,
Class<? extends HttpMessageConverter<?>> converterType) {
body = ((String) body).replaceAll("^\"|\"$", "");
return body;
}
/*
* @see org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdvice#
* handleEmptyBody(java.lang.Object, org.springframework.http.HttpInputMessage,
* org.springframework.core.MethodParameter, java.lang.reflect.Type,
* java.lang.Class)
*/
@Override
public Object handleEmptyBody(Object body, HttpInputMessage inputMessage, MethodParameter parameter,
Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
return body;
}
/*
* @see
* org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice#
* supports(org.springframework.core.MethodParameter, java.lang.Class)
*/
@Override
public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
return converterType == StringHttpMessageConverter.class;
}
/*
* @see
* org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice#
* beforeBodyWrite(java.lang.Object, org.springframework.core.MethodParameter,
* org.springframework.http.MediaType, java.lang.Class,
* org.springframework.http.server.ServerHttpRequest,
* org.springframework.http.server.ServerHttpResponse)
*/
@Override
public String beforeBodyWrite(String body, MethodParameter returnType, MediaType selectedContentType,
Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request,
ServerHttpResponse response) {
response.getHeaders().set(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
return gson.toJson(new JsonPrimitive(body));
}
}
@@ -0,0 +1,49 @@
/**
*
*/
package de.bstly.we.controller.support;
import org.springframework.lang.Nullable;
import org.springframework.validation.AbstractBindingResult;
/**
*
* @author _bastler@bstly.de
*
*/
@SuppressWarnings("serial")
public class RequestBodyErrors extends AbstractBindingResult {
@Nullable
private final Object target;
/**
*
* @param target
* @param objectName
*/
public RequestBodyErrors(@Nullable Object target) {
super("request-body");
this.target = target;
}
/*
* @see org.springframework.validation.AbstractBindingResult#getTarget()
*/
@Override
public Object getTarget() {
return target;
}
/*
* @see
* org.springframework.validation.AbstractBindingResult#getActualFieldValue(java
* .lang.String)
*/
@Override
protected Object getActualFieldValue(String field) {
// Not necessary
return null;
}
}
@@ -0,0 +1,277 @@
/**
*
*/
package de.bstly.we.controller.support;
import java.time.Instant;
import java.util.List;
import java.util.Set;
import javax.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.google.gson.JsonObject;
import de.bstly.we.businesslogic.PermissionManager;
import de.bstly.we.businesslogic.PermissionMappingManager;
import de.bstly.we.businesslogic.PretixManager;
import de.bstly.we.businesslogic.QuotaManager;
import de.bstly.we.businesslogic.QuotaMappingManager;
import de.bstly.we.controller.model.ItemResultModel;
import de.bstly.we.model.Permission;
import de.bstly.we.model.PermissionMapping;
import de.bstly.we.model.QuotaMapping;
import de.bstly.we.security.model.LocalUserDetails;
import de.bstly.we.security.token.LocalAnonymousAuthenticationToken;
/**
*
* @author _bastler@bstly.de
*
*/
@Component
public class TokenSessionManager {
public static final String HTTP_SESSION_ATTRIBUTE_TOKENS = "tokens";
@Autowired
private PermissionMappingManager permissionMappingManager;
@Autowired
private PermissionManager permissionManager;
@Autowired
private QuotaMappingManager quotaMappingManager;
@Autowired
private QuotaManager quotaManager;
@Autowired
private PretixManager pretixManager;
/**
*
* @param userId
* @param token
* @return
*/
public List<PermissionMapping> getPermissionMappingsForToken(Long userId, String token) {
List<PermissionMapping> permissionMappings = Lists.newArrayList();
try {
JsonObject result = pretixManager.getCheckInItemBySecret(token);
if (result != null && result.get("secret").getAsString().equals(token)
&& result.getAsJsonArray("checkins").size() < 1
&& "p".equals(result.get("order__status").getAsString())) {
int item = result.get("item").getAsInt();
permissionMappings.addAll(permissionMappingManager.getAllByItem(item));
}
} catch (Exception e) {
// ignore
}
return permissionMappings;
}
/**
*
* @param userId
* @param token
* @return
*/
public List<Permission> getPermissionsForToken(Long userId, String token) {
List<Permission> permissions = Lists.newArrayList();
try {
JsonObject orderPosition = pretixManager.getCheckInItemBySecret(token);
if (orderPosition != null && orderPosition.get("secret").getAsString().equals(token)
&& orderPosition.getAsJsonArray("checkins").size() < 1
&& "p".equals(orderPosition.get("order__status").getAsString())) {
int item = orderPosition.get("item").getAsInt();
Instant lastPaymentDate = pretixManager
.getLastPaymentDateForOrder(orderPosition.get("order").getAsString());
if (lastPaymentDate == null) {
throw new Exception("This should not happen!");
}
permissions.addAll(permissionManager.getForItem(userId, item,
orderPosition.get("answers").getAsJsonArray(), lastPaymentDate));
}
} catch (Exception e) {
// ignore
e.printStackTrace();
}
return permissions;
}
/**
*
* @param userId
* @param token
* @return
*/
public List<QuotaMapping> getQuotaMappingsForToken(Long userId, String token) {
List<QuotaMapping> quotaMappings = Lists.newArrayList();
try {
JsonObject result = pretixManager.getCheckInItemBySecret(token);
if (result != null && result.get("secret").getAsString().equals(token)
&& result.getAsJsonArray("checkins").size() < 1
&& "p".equals(result.get("order__status").getAsString())) {
int item = result.get("item").getAsInt();
quotaMappings.addAll(quotaMappingManager.getAllByItem(item));
}
} catch (Exception e) {
// ignore
}
return quotaMappings;
}
/**
*
* @param userId
* @param tokens
* @return
*/
public ItemResultModel applyTokens(Long userId, Set<String> tokens) {
ItemResultModel itemResultModel = new ItemResultModel();
List<PermissionMapping> permissionMappings = Lists.newArrayList();
List<QuotaMapping> quotaMappings = Lists.newArrayList();
for (String token : tokens) {
try {
JsonObject result = pretixManager.redeem(token);
if ("ok".equals(result.get("status").getAsString())) {
JsonObject position = result.get("position").getAsJsonObject();
int item = position.get("item").getAsInt();
Instant lastPaymentDate = pretixManager
.getLastPaymentDateForOrder(position.get("order").getAsString());
if (lastPaymentDate == null) {
throw new Exception("This should not happen!");
}
permissionManager.applyItem(userId, item,
position.get("answers").getAsJsonArray(), lastPaymentDate);
permissionMappings.addAll(permissionMappingManager.getAllByItem(item));
quotaManager.applyItem(userId, item);
quotaMappings.addAll(quotaMappingManager.getAllByItem(item));
}
} catch (Exception e) {
// ignore
}
}
itemResultModel.setPermissionMappings(permissionMappings);
itemResultModel.setQuotaMappings(quotaMappings);
return itemResultModel;
}
/**
*
* @param session
* @return
*/
public Set<String> getTokenFromSession(HttpSession session) {
Set<String> tokens = Sets.newHashSet();
Object sessionAttribute = session.getAttribute(HTTP_SESSION_ATTRIBUTE_TOKENS);
if (sessionAttribute != null && sessionAttribute instanceof String) {
for (String token : ((String) sessionAttribute).split(",")) {
if (StringUtils.hasText(token)) {
tokens.add(token);
}
}
}
return tokens;
}
/**
*
* @param secret
* @return
*/
public void addTokenToSession(String secret, HttpSession session) {
String tokens = "";
Object sessionAttribute = session.getAttribute(HTTP_SESSION_ATTRIBUTE_TOKENS);
if (sessionAttribute != null && sessionAttribute instanceof String) {
tokens = (String) sessionAttribute;
}
if (StringUtils.hasLength(tokens)) {
tokens += "," + secret;
} else {
tokens = secret;
}
session.setAttribute(HTTP_SESSION_ATTRIBUTE_TOKENS, tokens);
}
/**
*
* @param secret
* @return
*/
public void removeTokenFromSession(String secret, HttpSession session) {
String tokens = "";
Object sessionAttribute = session.getAttribute(HTTP_SESSION_ATTRIBUTE_TOKENS);
if (sessionAttribute != null && sessionAttribute instanceof String) {
for (String token : ((String) sessionAttribute).split(",")) {
if (!token.equals(secret)) {
if (StringUtils.hasLength(tokens)) {
tokens += "," + secret;
} else {
tokens = secret;
}
}
}
}
session.setAttribute(HTTP_SESSION_ATTRIBUTE_TOKENS, tokens);
}
/**
*
* @param secret
* @return
*/
public void removeTokensFromSession(HttpSession session) {
session.setAttribute(HTTP_SESSION_ATTRIBUTE_TOKENS, null);
}
/**
*
* @param auth
* @param details
* @return
*/
protected Authentication createNewAuth(Authentication auth, LocalUserDetails details) {
Authentication newAuth = null;
if (auth instanceof UsernamePasswordAuthenticationToken) {
newAuth = new UsernamePasswordAuthenticationToken(details, auth.getCredentials(),
details.getAuthorities());
} else {
newAuth = new LocalAnonymousAuthenticationToken(details);
}
if (!auth.isAuthenticated()) {
newAuth.setAuthenticated(false);
}
return newAuth;
}
}
@@ -0,0 +1,101 @@
/**
*
*/
package de.bstly.we.controller.validation;
import java.util.ArrayList;
import java.util.List;
import org.passay.CharacterRule;
import org.passay.EnglishCharacterData;
import org.passay.LengthRule;
import org.passay.PasswordData;
import org.passay.PasswordValidator;
import org.passay.Rule;
import org.passay.RuleResult;
import org.passay.RuleResultDetail;
import org.passay.WhitespaceRule;
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.businesslogic.SystemPropertyManager;
import de.bstly.we.controller.model.PasswordModel;
/**
*
* @author _bastler@bstly.de
*
*/
@Component
public class PasswordModelValidator implements Validator {
@Autowired
private SystemPropertyManager systemPropertyManager;
public static final String SYSTEM_PROPERTY_PASSWORD_RULE_WHITESPACE = "password.rule.whitespace";
public static final String SYSTEM_PROPERTY_PASSWORD_RULE_LENGTH = "password.rule.length";
public static final String SYSTEM_PROPERTY_PASSWORD_RULE_UPPERCASE = "password.rule.uppercase";
public static final String SYSTEM_PROPERTY_PASSWORD_RULE_DIGIT = "password.rule.digit";
public static final String SYSTEM_PROPERTY_PASSWORD_RULE_SPECIAL = "password.rule.special";
/*
* @see org.springframework.validation.Validator#supports(java.lang.Class)
*/
@Override
public boolean supports(Class<?> clazz) {
return clazz.isAssignableFrom(PasswordModel.class);
}
/*
*
* @see org.springframework.validation.Validator#validate(java.lang.Object,
* org.springframework.validation.Errors)
*/
@Override
public void validate(Object target, Errors errors) {
PasswordModel passwordModel = (PasswordModel) target;
List<Rule> rules = new ArrayList<Rule>();
if (systemPropertyManager.getBoolean(SYSTEM_PROPERTY_PASSWORD_RULE_WHITESPACE, true)) {
rules.add(new WhitespaceRule());
}
int length = systemPropertyManager.getInteger(SYSTEM_PROPERTY_PASSWORD_RULE_LENGTH, 8);
if (length > 0) {
rules.add(new LengthRule(length, 4096));
}
int uppercase = systemPropertyManager.getInteger(SYSTEM_PROPERTY_PASSWORD_RULE_UPPERCASE, 1);
if (uppercase > 0) {
rules.add(new CharacterRule(EnglishCharacterData.UpperCase, uppercase));
}
int digit = systemPropertyManager.getInteger(SYSTEM_PROPERTY_PASSWORD_RULE_DIGIT, 1);
if (digit > 0) {
rules.add(new CharacterRule(EnglishCharacterData.Digit, digit));
}
int special = systemPropertyManager.getInteger(SYSTEM_PROPERTY_PASSWORD_RULE_SPECIAL, 1);
if (special > 0) {
rules.add(new CharacterRule(EnglishCharacterData.Special, special));
}
PasswordValidator validator = new PasswordValidator(rules);
PasswordData password = new PasswordData(passwordModel.getPassword());
RuleResult result = validator.validate(password);
if (!result.isValid()) {
for (RuleResultDetail ruleResultDetail : result.getDetails()) {
errors.rejectValue("password", ruleResultDetail.getErrorCode());
}
}
if (!passwordModel.getPassword().equals(passwordModel.getPassword2())) {
errors.rejectValue("password2", "NOT_MATCH");
}
}
}
@@ -0,0 +1,53 @@
/**
*
*/
package de.bstly.we.controller.validation;
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.businesslogic.PermissionMappingManager;
import de.bstly.we.model.PermissionMapping;
/**
*
* @author _bastler@bstly.de
*
*/
@Component
public class PermissionMappingValidator implements Validator {
@Autowired
private PermissionMappingManager permissionMappingManager;
/*
* @see org.springframework.validation.Validator#supports(java.lang.Class)
*/
@Override
public boolean supports(Class<?> clazz) {
return clazz.isAssignableFrom(PermissionMapping.class);
}
/*
*
* @see org.springframework.validation.Validator#validate(java.lang.Object,
* org.springframework.validation.Errors)
*/
@Override
public void validate(Object target, Errors errors) {
PermissionMapping permissionMapping = (PermissionMapping) target;
for (String name : permissionMapping.getNames())
if (permissionMappingManager.exists(permissionMapping.getItem(), name)) {
errors.rejectValue("item", "ALREADY_EXISTS");
errors.rejectValue("names." + name, "ALREADY_EXISTS");
}
if (permissionMapping.getLifetime() <= 0) {
errors.rejectValue("lifetime", "TOO_SHORT");
}
}
}
@@ -0,0 +1,54 @@
/**
*
*/
package de.bstly.we.controller.validation;
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.businesslogic.QuotaMappingManager;
import de.bstly.we.model.QuotaMapping;
/**
*
* @author _bastler@bstly.de
*
*/
@Component
public class QuotaMappingValidator implements Validator {
@Autowired
private QuotaMappingManager quotaMappingManager;
/*
* @see org.springframework.validation.Validator#supports(java.lang.Class)
*/
@Override
public boolean supports(Class<?> clazz) {
return clazz.isAssignableFrom(QuotaMapping.class);
}
/*
*
* @see org.springframework.validation.Validator#validate(java.lang.Object,
* org.springframework.validation.Errors)
*/
@Override
public void validate(Object target, Errors errors) {
QuotaMapping quotaMapping = (QuotaMapping) target;
for (Integer item : quotaMapping.getItems()) {
if (quotaMappingManager.exists(item, quotaMapping.getName())) {
errors.rejectValue("item", "ALREADY_EXISTS");
errors.rejectValue("name", "ALREADY_EXISTS");
}
}
if (quotaMapping.getValue() <= 0) {
errors.rejectValue("value", "TOO_SHORT");
}
}
}
@@ -0,0 +1,59 @@
/**
*
*/
package de.bstly.we.controller.validation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;
import de.bstly.we.model.UserAlias;
/**
* @author _bastler@bstly.de
*
*/
@Component
public class UserAliasValidator implements Validator {
@Autowired
private UserModelValidator userModelValidator;
/*
* @see org.springframework.validation.Validator#supports(java.lang.Class)
*/
@Override
public boolean supports(Class<?> clazz) {
return clazz.isAssignableFrom(UserAlias.class);
}
/*
* @see org.springframework.validation.Validator#validate(java.lang.Object,
* org.springframework.validation.Errors)
*/
@Override
public void validate(Object target, Errors errors) {
UserAlias userAlias = (UserAlias) target;
if (!StringUtils.hasText(userAlias.getAlias())) {
errors.rejectValue("alias", "REQUIRED");
return;
}
if (userAlias.getTarget() == null) {
errors.rejectValue("target", "REQUIRED");
return;
}
if (userAlias.getVisibility() == null) {
errors.rejectValue("visibility", "REQUIRED");
return;
}
userModelValidator.validateUsername(userAlias.getAlias(), "alias", errors);
}
}
@@ -0,0 +1,73 @@
/**
*
*/
package de.bstly.we.controller.validation;
import org.apache.commons.validator.routines.DomainValidator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;
import de.bstly.we.businesslogic.UserDomainManager;
import de.bstly.we.model.UserDomain;
/**
* @author _bastler@bstly.de
*
*/
@Component
public class UserDomainValidator implements Validator {
private DomainValidator domainValidator = DomainValidator.getInstance();
@Autowired
private UserDomainManager userDomainManager;
/*
* @see org.springframework.validation.Validator#supports(java.lang.Class)
*/
@Override
public boolean supports(Class<?> clazz) {
return clazz.isAssignableFrom(UserDomain.class);
}
/*
* @see org.springframework.validation.Validator#validate(java.lang.Object,
* org.springframework.validation.Errors)
*/
@Override
public void validate(Object target, Errors errors) {
UserDomain userDomain = (UserDomain) target;
if (!StringUtils.hasText(userDomain.getDomain())) {
errors.rejectValue("domain", "REQUIRED");
return;
}
if (!domainValidator.isValid(userDomain.getDomain())) {
errors.rejectValue("domain", "NOT_VALID");
return;
}
UserDomain existingDomain = userDomainManager.getByDomain(userDomain.getDomain());
if (existingDomain != null && (userDomain.getId() == null
|| !(existingDomain.getId().equals(userDomain.getId())))) {
errors.rejectValue("domain", "NOT_VALID");
return;
}
if (userDomain.getTarget() == null) {
errors.rejectValue("target", "REQUIRED");
return;
}
if (userDomain.getVisibility() == null) {
errors.rejectValue("visibility", "REQUIRED");
return;
}
}
}
@@ -0,0 +1,91 @@
/**
*
*/
package de.bstly.we.controller.validation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;
import de.bstly.we.businesslogic.SystemPropertyManager;
import de.bstly.we.businesslogic.UserAliasManager;
import de.bstly.we.businesslogic.UserManager;
import de.bstly.we.controller.model.UserModel;
/**
*
* @author _bastler@bstly.de
*
*/
@Component
public class UserModelValidator implements Validator {
public static final String RESERVED_USERNAMES = "usernames.reserved";
protected static final String localPart = "^[a-zA-Z0-9_!#$%&'*+/=?`{|}~^-]+(?:\\\\.[A-Z0-9_!#$%&'*+/=?`{|}~^-]+)*$";
@Autowired
private UserManager userManager;
@Autowired
private UserAliasManager userAliasManager;
@Autowired
private SystemPropertyManager systemPropertyManager;
/*
* @see org.springframework.validation.Validator#supports(java.lang.Class)
*/
@Override
public boolean supports(Class<?> clazz) {
return clazz.isAssignableFrom(UserModel.class);
}
/*
*
* @see org.springframework.validation.Validator#validate(java.lang.Object,
* org.springframework.validation.Errors)
*/
@Override
public void validate(Object target, Errors errors) {
UserModel userModel = (UserModel) target;
if (!StringUtils.hasText(userModel.getUsername())) {
errors.rejectValue("username", "REQUIRED");
return;
}
validateUsername(userModel.getUsername(), "username", errors);
}
/**
*
* @param username
* @param field
* @param errors
*/
public void validateUsername(String username, String field, Errors errors) {
for (String systemUsername : systemPropertyManager.get(RESERVED_USERNAMES, "").split(",")) {
if (StringUtils.hasText(systemUsername)
&& (username.toLowerCase().equals(systemUsername)
|| username.toLowerCase().matches(systemUsername))) {
errors.rejectValue(field, "NOT_VALID");
break;
}
}
if (userManager.getByUsername(username) != null) {
errors.rejectValue(field, "NOT_VALID");
return;
}
if (userAliasManager.getByAlias(username) != null) {
errors.rejectValue(field, "NOT_VALID");
return;
}
if (!username.matches(localPart)) {
errors.rejectValue(field, "NOT_VALID");
}
}
}
@@ -0,0 +1,157 @@
/**
*
*/
package de.bstly.we.controller.validation;
import java.time.Instant;
import java.time.format.DateTimeParseException;
import java.util.List;
import org.apache.commons.validator.routines.DoubleValidator;
import org.apache.commons.validator.routines.EmailValidator;
import org.apache.commons.validator.routines.UrlValidator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;
import com.google.common.collect.Lists;
import com.querydsl.core.BooleanBuilder;
import de.bstly.we.businesslogic.SystemProfileFieldManager;
import de.bstly.we.model.ProfileFieldType;
import de.bstly.we.model.QUserProfileField;
import de.bstly.we.model.SystemProfileField;
import de.bstly.we.model.UserProfileField;
import de.bstly.we.repository.UserProfileFieldRepository;
/**
* @author _bastler@bstly.de
*
*/
@Component
public class UserProfileFieldValidator implements Validator {
@Autowired
private SystemProfileFieldManager systemProfileFieldManager;
@Autowired
private UserProfileFieldRepository userProfileFieldRepository;
private QUserProfileField qUserProfileField = QUserProfileField.userProfileField;
private DoubleValidator doubleValidator = DoubleValidator.getInstance();
private EmailValidator emailValidator = EmailValidator.getInstance();
private UrlValidator urlValidator = new UrlValidator(UrlValidator.ALLOW_ALL_SCHEMES);
private List<String> validBoolean = Lists.newArrayList("true", "True", "TRUE", "1", "false",
"False", "FALSE", "0");
/*
* @see org.springframework.validation.Validator#supports(java.lang.Class)
*/
@Override
public boolean supports(Class<?> clazz) {
return clazz.isAssignableFrom(UserProfileField.class);
}
/*
* @see org.springframework.validation.Validator#validate(java.lang.Object,
* org.springframework.validation.Errors)
*/
@Override
public void validate(Object target, Errors errors) {
UserProfileField userProfileField = (UserProfileField) target;
if (userProfileField.getName() == null || userProfileField.getName().length() < 3) {
errors.rejectValue("name", "TOO_SHORT");
} else if (userProfileField.getName().length() > 255) {
errors.rejectValue("name", "TOO_LONG");
}
SystemProfileField systemProfileField = systemProfileFieldManager
.get(userProfileField.getName());
if (systemProfileField != null) {
if (!systemProfileField.getType().equals(userProfileField.getType())) {
errors.rejectValue("type", "INVALID_TYPE", userProfileField.getName());
return;
}
if (systemProfileField.isUniqueValue()) {
BooleanBuilder builder = new BooleanBuilder();
builder.and(qUserProfileField.name.eq(userProfileField.getName()));
if (userProfileField.getTarget() != null) {
builder.and(qUserProfileField.target.ne(userProfileField.getTarget()));
}
if (ProfileFieldType.BLOB.equals(userProfileField.getType())) {
if (userProfileField.getBlob() == null) {
errors.rejectValue("blob", "NOT_SPECIFIED", userProfileField.getName());
return;
}
builder.and(qUserProfileField.blob.eq(userProfileField.getBlob()));
} else if (userProfileField.getValue() == null) {
errors.rejectValue("value", "NOT_SPECIFIED", userProfileField.getName());
} else {
builder.and(qUserProfileField.value.eq(userProfileField.getValue()));
}
if (userProfileFieldRepository.exists(builder.getValue())) {
errors.rejectValue("value", "NOT_VALID", userProfileField.getName());
return;
}
}
}
switch (userProfileField.getType()) {
case BOOL:
if (!validBoolean.contains(userProfileField.getValue())) {
errors.rejectValue("value", "INVALID_BOOLEAN", userProfileField.getName());
}
break;
case DATE:
try {
Instant.parse(userProfileField.getValue());
} catch (DateTimeParseException e) {
errors.rejectValue("value", "INVALID_DATE", userProfileField.getName());
}
break;
case DATETIME:
try {
Instant.parse(userProfileField.getValue());
} catch (DateTimeParseException e) {
errors.rejectValue("value", "INVALID_DATE", userProfileField.getName());
}
break;
case TIME:
try {
Instant.parse(userProfileField.getValue());
} catch (DateTimeParseException e) {
errors.rejectValue("value", "INVALID_DATE", userProfileField.getName());
}
break;
case EMAIL:
if (!emailValidator.isValid(userProfileField.getValue())) {
errors.rejectValue("value", "INVALID_EMAIL", userProfileField.getName());
}
break;
case NUMBER:
if (!doubleValidator.isValid(userProfileField.getValue())) {
errors.rejectValue("value", "INVALID_NUMBER", userProfileField.getName());
}
break;
case TEXT:
if (userProfileField.getValue() != null && userProfileField.getValue().length() > 255) {
errors.rejectValue("value", "TOO_LONG", userProfileField.getName());
}
break;
case URL:
if (!urlValidator.isValid(userProfileField.getValue())) {
errors.rejectValue("value", "INVALID_URL", userProfileField.getName());
}
break;
case BLOB:
break;
}
}
}
@@ -0,0 +1,63 @@
/**
*
*/
package de.bstly.we.event;
import org.springframework.context.ApplicationEvent;
import de.bstly.we.model.AbstractModel;
/**
* @author Lurkars
*
*/
public class AbstractModelEvent extends ApplicationEvent {
/**
* default serialVersionUID
*/
private static final long serialVersionUID = 1L;
private AbstractModelEventType type;
private AbstractModel model;
/**
*
* @param type
* @param model
*/
public AbstractModelEvent(AbstractModelEventType type, AbstractModel model) {
super(model);
this.type = type;
this.model = model;
}
/**
* @return the type
*/
public AbstractModelEventType getType() {
return type;
}
/**
* @param type the type to set
*/
public void setType(AbstractModelEventType type) {
this.type = type;
}
/**
* @return the model
*/
public AbstractModel getModel() {
return model;
}
/**
* @param model the model to set
*/
public void setModel(AbstractModel model) {
this.model = model;
}
}
@@ -0,0 +1,14 @@
/**
*
*/
package de.bstly.we.event;
/**
* @author Lurkars
*
*/
public enum AbstractModelEventType {
PRE_PERSIST, PRE_UPDATE, PRE_REMOVE, POST_PERSIST, POST_UPDATE, POST_REMOVE, POST_LOAD
}
@@ -0,0 +1,12 @@
/**
*
*/
package de.bstly.we.model;
/**
* @author Lurkars
*
*/
public interface AbstractModel {
}
+123
View File
@@ -0,0 +1,123 @@
/**
*
*/
package de.bstly.we.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.Table;
/**
*
* @author _bastler@bstly.de
*
*/
@Entity
@Table(name = "permissions")
public class Permission implements UserData {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Long id;
@Column(name = "name", nullable = false)
private String name;
@Column(name = "target", nullable = false)
private Long target;
@Column(name = "addon", columnDefinition = "boolean default false")
private boolean addon;
@Column(name = "starts", nullable = true)
private Instant starts;
@Column(name = "expires")
private Instant expires;
/**
* @return the id
*/
public Long getId() {
return id;
}
/**
* @param id the id to set
*/
public void setId(Long id) {
this.id = id;
}
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}
/**
* @return the target
*/
public Long getTarget() {
return target;
}
/**
* @param target the target to set
*/
public void setTarget(Long target) {
this.target = target;
}
/**
* @return the addon
*/
public boolean isAddon() {
return addon;
}
/**
* @param addon the addon to set
*/
public void setAddon(boolean addon) {
this.addon = addon;
}
/**
* @return the starts
*/
public Instant getStarts() {
return starts;
}
/**
* @param starts the starts to set
*/
public void setStarts(Instant starts) {
this.starts = starts;
}
/**
* @return the expires
*/
public Instant getExpires() {
return expires;
}
/**
* @param expires the expires to set
*/
public void setExpires(Instant expires) {
this.expires = expires;
}
}
+214
View File
@@ -0,0 +1,214 @@
/**
*
*/
package de.bstly.we.model;
import java.time.temporal.ChronoUnit;
import java.util.Set;
import javax.persistence.AttributeConverter;
import javax.persistence.CollectionTable;
import javax.persistence.Column;
import javax.persistence.Convert;
import javax.persistence.Converter;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import org.hibernate.annotations.LazyCollection;
import org.hibernate.annotations.LazyCollectionOption;
/**
*
* @author _bastler@bstly.de
*
*/
@Entity
@Table(name = "permission_mappings")
public class PermissionMapping {
public static final ChronoUnit DEFAULT_LIFETIME_UNIT = ChronoUnit.DAYS;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Long id;
@Column(name = "product")
private String product;
@Column(name = "item", nullable = false)
private Integer item;
@ElementCollection
@LazyCollection(LazyCollectionOption.FALSE)
@CollectionTable(name = "permission_mappings_names")
private Set<String> names;
@Column(name = "addon", columnDefinition = "boolean default false")
private boolean addon;
@Column(name = "lifetime")
private Long lifetime;
@Column(name = "lifetime_unit")
@Convert(converter = ChronoUnitConverter.class)
private ChronoUnit lifetimeUnit = DEFAULT_LIFETIME_UNIT;
@Column(name = "lifetime_round", columnDefinition = "boolean default false")
private boolean lifetimeRound;
@Column(name = "starts_question")
private String startsQuestion;
@Column(name = "expires_question")
private String expiresQuestion;
/**
* @return the id
*/
public Long getId() {
return id;
}
/**
* @param id the id to set
*/
public void setId(Long id) {
this.id = id;
}
/**
* @return the product
*/
public String getProduct() {
return product;
}
/**
* @param product the product to set
*/
public void setProduct(String product) {
this.product = product;
}
/**
* @return the item
*/
public Integer getItem() {
return item;
}
/**
* @param item the item to set
*/
public void setItem(Integer item) {
this.item = item;
}
/**
* @return the names
*/
public Set<String> getNames() {
return names;
}
/**
* @param names the names to set
*/
public void setNames(Set<String> names) {
this.names = names;
}
/**
* @return the addon
*/
public boolean isAddon() {
return addon;
}
/**
* @param addon the addon to set
*/
public void setAddon(boolean addon) {
this.addon = addon;
}
/**
* @return the lifetime
*/
public Long getLifetime() {
return lifetime;
}
/**
* @param lifetime the lifetime to set
*/
public void setLifetime(Long lifetime) {
this.lifetime = lifetime;
}
/**
* @return the lifetimeUnit
*/
public ChronoUnit getLifetimeUnit() {
return lifetimeUnit;
}
/**
* @param lifetimeUnit the lifetimeUnit to set
*/
public void setLifetimeUnit(ChronoUnit lifetimeUnit) {
this.lifetimeUnit = lifetimeUnit;
}
/**
* @return the lifetimeRound
*/
public boolean isLifetimeRound() {
return lifetimeRound;
}
/**
* @param lifetimeRound the lifetimeRound to set
*/
public void setLifetimeRound(boolean lifetimeRound) {
this.lifetimeRound = lifetimeRound;
}
/**
* @return the startsQuestion
*/
public String getStartsQuestion() {
return startsQuestion;
}
/**
* @param startsQuestion the startsQuestion to set
*/
public void setStartsQuestion(String startsQuestion) {
this.startsQuestion = startsQuestion;
}
/**
* @return the expiresQuestion
*/
public String getExpiresQuestion() {
return expiresQuestion;
}
/**
* @param expiresQuestion the expiresQuestion to set
*/
public void setExpiresQuestion(String expiresQuestion) {
this.expiresQuestion = expiresQuestion;
}
@Converter
public static class ChronoUnitConverter implements AttributeConverter<ChronoUnit, String> {
@Override
public String convertToDatabaseColumn(ChronoUnit chronoUnit) {
return chronoUnit.name();
}
@Override
public ChronoUnit convertToEntityAttribute(String value) {
return ChronoUnit.valueOf(value);
}
}
}
@@ -0,0 +1,88 @@
/**
*
*/
package de.bstly.we.model;
import java.time.Instant;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
/**
*
* @author _bastler@bstly.de
*
*/
@Entity
@Table(name = "persistent_logins")
public class PersistentLogin {
@Column(name = "username", length = 64, nullable = false)
private String username;
@Id
@Column(name = "series", length = 64)
private String series;
@Column(name = "token", length = 64, nullable = false)
private String token;
@Column(name = "last_used", nullable = false)
private Instant last_used;
/**
* @return the username
*/
public String getUsername() {
return username;
}
/**
* @param username the username to set
*/
public void setUsername(String username) {
this.username = username;
}
/**
* @return the series
*/
public String getSeries() {
return series;
}
/**
* @param series the series to set
*/
public void setSeries(String series) {
this.series = series;
}
/**
* @return the token
*/
public String getToken() {
return token;
}
/**
* @param token the token to set
*/
public void setToken(String token) {
this.token = token;
}
/**
* @return the last_used
*/
public Instant getLast_used() {
return last_used;
}
/**
* @param last_used the last_used to set
*/
public void setLast_used(Instant last_used) {
this.last_used = last_used;
}
}
@@ -0,0 +1,14 @@
/**
*
*/
package de.bstly.we.model;
/**
* @author _bastler@bstly.de
*
*/
public enum ProfileFieldType {
TEXT, NUMBER, DATE, URL, EMAIL, BOOL, BLOB, DATETIME, TIME
}
@@ -0,0 +1,120 @@
/**
*
*/
package de.bstly.we.model;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
/**
* @author _bastler@bstly.de
*
*/
@Entity
@Table(name = "quotas")
public class Quota implements UserData {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", updatable = false)
private Long id;
@Column(name = "target", nullable = false)
private Long target;
@Column(name = "name", nullable = false)
private String name;
@Column(name = "value", nullable = false)
private long value;
@Column(name = "unit", nullable = true)
private String unit;
@Column(name = "disposable", columnDefinition = "boolean default false")
private boolean disposable;
/**
* @return the id
*/
public Long getId() {
return id;
}
/**
* @param id the id to set
*/
public void setId(Long id) {
this.id = id;
}
/**
* @return the target
*/
public Long getTarget() {
return target;
}
/**
* @param target the target to set
*/
public void setTarget(Long target) {
this.target = target;
}
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}
/**
* @return the value
*/
public long getValue() {
return value;
}
/**
* @param value the value to set
*/
public void setValue(long value) {
this.value = value;
}
/**
* @return the unit
*/
public String getUnit() {
return unit;
}
/**
* @param unit the unit to set
*/
public void setUnit(String unit) {
this.unit = unit;
}
/**
* @return the disposable
*/
public boolean isDisposable() {
return disposable;
}
/**
* @param disposable the disposable to set
*/
public void setDisposable(boolean disposable) {
this.disposable = disposable;
}
}
@@ -0,0 +1,164 @@
/**
*
*/
package de.bstly.we.model;
import java.util.Set;
import javax.persistence.CollectionTable;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import org.hibernate.annotations.LazyCollection;
import org.hibernate.annotations.LazyCollectionOption;
/**
*
* @author _bastler@bstly.de
*
*/
@Entity
@Table(name = "quota_mappings")
public class QuotaMapping {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", updatable = false)
private Long id;
@ElementCollection
@LazyCollection(LazyCollectionOption.FALSE)
@CollectionTable(name = "quota_mappings_products")
private Set<String> products;
@ElementCollection
@LazyCollection(LazyCollectionOption.FALSE)
@CollectionTable(name = "quota_mappings_items")
private Set<Integer> items;
@Column(name = "name", nullable = false)
private String name;
@Column(name = "value", nullable = false)
private long value;
@Column(name = "unit", nullable = true)
private String unit;
@Column(name = "append", columnDefinition = "boolean default false")
private boolean append;
@Column(name = "disposable", columnDefinition = "boolean default false")
private boolean disposable;
/**
* @return the id
*/
public Long getId() {
return id;
}
/**
* @param id the id to set
*/
public void setId(Long id) {
this.id = id;
}
/**
* @return the products
*/
public Set<String> getProducts() {
return products;
}
/**
* @param products the products to set
*/
public void setProducts(Set<String> products) {
this.products = products;
}
/**
* @return the items
*/
public Set<Integer> getItems() {
return items;
}
/**
* @param items the items to set
*/
public void setItems(Set<Integer> items) {
this.items = items;
}
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}
/**
* @return the value
*/
public long getValue() {
return value;
}
/**
* @param value the value to set
*/
public void setValue(long value) {
this.value = value;
}
/**
* @return the unit
*/
public String getUnit() {
return unit;
}
/**
* @param unit the unit to set
*/
public void setUnit(String unit) {
this.unit = unit;
}
/**
* @return the append
*/
public boolean isAppend() {
return append;
}
/**
* @param append the append to set
*/
public void setAppend(boolean append) {
this.append = append;
}
/**
* @return the disposable
*/
public boolean isDisposable() {
return disposable;
}
/**
* @param disposable the disposable to set
*/
public void setDisposable(boolean disposable) {
this.disposable = disposable;
}
}
@@ -0,0 +1,12 @@
/**
*
*/
package de.bstly.we.model;
/**
* @author _bastler@bstly.de
*
*/
public interface SecondFactor extends UserData {
}
@@ -0,0 +1,69 @@
/**
*
*/
package de.bstly.we.model;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
/**
* @author _bastler@bstly.de
*
*/
@Entity
@Table(name = "system_profile_fields")
public class SystemProfileField {
@Id
@Column(name = "name", nullable = false)
private String name;
@Column(name = "type", nullable = false)
private ProfileFieldType type;
@Column(name = "unique_value", columnDefinition = "boolean default false")
private boolean uniqueValue;
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}
/**
* @return the type
*/
public ProfileFieldType getType() {
return type;
}
/**
* @param type the type to set
*/
public void setType(ProfileFieldType type) {
this.type = type;
}
/**
* @return the uniqueValue
*/
public boolean isUniqueValue() {
return uniqueValue;
}
/**
* @param uniqueValue the uniqueValue to set
*/
public void setUniqueValue(boolean uniqueValue) {
this.uniqueValue = uniqueValue;
}
}
+73
View File
@@ -0,0 +1,73 @@
/**
*
*/
package de.bstly.we.model;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Lob;
import javax.persistence.Table;
/**
*
* @author _bastler@bstly.de
*
*/
@Entity
@Table(name = "system_properties")
public class SystemProperty {
@Id
@Column(name = "id")
private String key;
@Lob
@Column(name = "value")
private String value;
/**
*
*/
public SystemProperty() {
super();
}
/**
* @param key
* @param value
*/
public SystemProperty(String key, String value) {
super();
this.key = key;
this.value = value;
}
/**
* @return the key
*/
public String getKey() {
return key;
}
/**
* @param key the key to set
*/
public void setKey(String key) {
this.key = key;
}
/**
* @return the value
*/
public String getValue() {
return value;
}
/**
* @param value the value to set
*/
public void setValue(String value) {
this.value = value;
}
}
+156
View File
@@ -0,0 +1,156 @@
/**
*
*/
package de.bstly.we.model;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import com.fasterxml.jackson.annotation.JsonIgnore;
/**
*
* @author _bastler@bstly.de
*
*/
@Entity
@Table(name = "users", uniqueConstraints = @UniqueConstraint(columnNames = { "username" }))
public class User implements UserData {
@Id
@Column(name = "id", updatable = false, unique = true, nullable = false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "username", unique = true, nullable = false)
private String username;
@JsonIgnore
@Column(name = "password", nullable = false)
private String passwordHash;
@Column(name = "disabled", columnDefinition = "boolean default false")
private boolean disabled;
@Column(name = "locked", columnDefinition = "boolean default false")
private boolean locked;
@Column(name = "status", nullable = false)
private UserStatus status;
@Column(name = "secret")
private String secret;
@Column(name = "reset_token")
private String resetToken;
/**
* @return the id
*/
public Long getId() {
return id;
}
/**
* @param id the id to set
*/
public void setId(Long id) {
this.id = id;
}
/**
* @return the username
*/
public String getUsername() {
return username;
}
/**
* @param username the username to set
*/
public void setUsername(String username) {
this.username = username;
}
/**
* @return the passwordHash
*/
public String getPasswordHash() {
return passwordHash;
}
/**
* @param passwordHash the passwordHash to set
*/
public void setPasswordHash(String passwordHash) {
this.passwordHash = passwordHash;
}
/**
* @return the disabled
*/
public boolean isDisabled() {
return disabled;
}
/**
* @param disabled the disabled to set
*/
public void setDisabled(boolean disabled) {
this.disabled = disabled;
}
/**
* @return the locked
*/
public boolean isLocked() {
return locked;
}
/**
* @param locked the locked to set
*/
public void setLocked(boolean locked) {
this.locked = locked;
}
/**
* @return the status
*/
public UserStatus getStatus() {
return status;
}
/**
* @param status the status to set
*/
public void setStatus(UserStatus status) {
this.status = status;
}
/**
* @return the secret
*/
public String getSecret() {
return secret;
}
/**
* @param secret the secret to set
*/
public void setSecret(String secret) {
this.secret = secret;
}
/**
* @return the resetToken
*/
public String getResetToken() {
return resetToken;
}
/**
* @param resetToken the resetToken to set
*/
public void setResetToken(String resetToken) {
this.resetToken = resetToken;
}
}
@@ -0,0 +1,89 @@
/**
*
*/
package de.bstly.we.model;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
/**
* @author _bastler@bstly.de
*
*/
@Entity
@Table(name = "aliases", uniqueConstraints = @UniqueConstraint(columnNames = { "alias" }))
public class UserAlias implements UserData {
@Id
@Column(name = "id", updatable = false, unique = true, nullable = false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "target", nullable = false)
private Long target;
@Column(name = "alias", unique = true, nullable = false)
private String alias;
@Column(name = "visibility", nullable = false)
private Visibility visibility = Visibility.PROTECTED;
/**
* @return the id
*/
public Long getId() {
return id;
}
/**
* @param id the id to set
*/
public void setId(Long id) {
this.id = id;
}
/**
* @return the target
*/
public Long getTarget() {
return target;
}
/**
* @param target the target to set
*/
public void setTarget(Long target) {
this.target = target;
}
/**
* @return the alias
*/
public String getAlias() {
return alias;
}
/**
* @param alias the alias to set
*/
public void setAlias(String alias) {
this.alias = alias;
}
/**
* @return the visibility
*/
public Visibility getVisibility() {
return visibility;
}
/**
* @param visibility the visibility to set
*/
public void setVisibility(Visibility visibility) {
this.visibility = visibility;
}
}
@@ -0,0 +1,12 @@
/**
*
*/
package de.bstly.we.model;
/**
* @author _bastler@bstly.de
*
*/
public interface UserData {
}
@@ -0,0 +1,120 @@
/**
*
*/
package de.bstly.we.model;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
/**
* @author _bastler@bstly.de
*
*/
@Entity
@Table(name = "domains", uniqueConstraints = @UniqueConstraint(columnNames = { "domain" }))
public class UserDomain implements UserData {
@Id
@Column(name = "id", updatable = false, unique = true, nullable = false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "target", nullable = false)
private Long target;
@Column(name = "domain", unique = true, nullable = false)
private String domain;
@Column(name = "visibility", nullable = false)
private Visibility visibility = Visibility.PROTECTED;
@Column(name = "secret")
private String secret;
@Column(name = "validated", columnDefinition = "boolean default false")
private boolean validated;
/**
* @return the id
*/
public Long getId() {
return id;
}
/**
* @param id the id to set
*/
public void setId(Long id) {
this.id = id;
}
/**
* @return the target
*/
public Long getTarget() {
return target;
}
/**
* @param target the target to set
*/
public void setTarget(Long target) {
this.target = target;
}
/**
* @return the domain
*/
public String getDomain() {
return domain;
}
/**
* @param domain the domain to set
*/
public void setDomain(String domain) {
this.domain = domain;
}
/**
* @return the visibility
*/
public Visibility getVisibility() {
return visibility;
}
/**
* @param visibility the visibility to set
*/
public void setVisibility(Visibility visibility) {
this.visibility = visibility;
}
/**
* @return the secret
*/
public String getSecret() {
return secret;
}
/**
* @param secret the secret to set
*/
public void setSecret(String secret) {
this.secret = secret;
}
/**
* @return the validated
*/
public boolean isValidated() {
return validated;
}
/**
* @param validated the validated to set
*/
public void setValidated(boolean validated) {
this.validated = validated;
}
}
@@ -0,0 +1,208 @@
/**
*
*/
package de.bstly.we.model;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.IdClass;
import javax.persistence.Lob;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import de.bstly.we.model.UserProfileField.UserProfileFieldId;
/**
* @author _bastler@bstly.de
*
*/
@Entity
@IdClass(UserProfileFieldId.class)
@Table(name = "profile_fields", uniqueConstraints = @UniqueConstraint(columnNames = { "target",
"name" }))
public class UserProfileField implements UserData {
@Id
@Column(name = "name", nullable = false)
private String name;
@Id
@Column(name = "target", nullable = false)
private Long target;
@Column(name = "value", nullable = true)
private String value;
@Lob
@Column(name = "blob_value", nullable = true)
private String blob;
@Column(name = "type", nullable = false)
private ProfileFieldType type;
@Column(name = "visibility", nullable = false)
private Visibility visibility;
@Column(name = "order_index", nullable = true)
private Integer index = 0;
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}
/**
* @return the target
*/
public Long getTarget() {
return target;
}
/**
* @param target the target to set
*/
public void setTarget(Long target) {
this.target = target;
}
/**
* @return the value
*/
public String getValue() {
return value;
}
/**
* @param value the value to set
*/
public void setValue(String value) {
this.value = value;
}
/**
* @return the blob
*/
public String getBlob() {
return blob;
}
/**
* @param blob the blob to set
*/
public void setBlob(String blob) {
this.blob = blob;
}
/**
* @return the type
*/
public ProfileFieldType getType() {
return type;
}
/**
* @param type the type to set
*/
public void setType(ProfileFieldType type) {
this.type = type;
}
/**
* @return the visibility
*/
public Visibility getVisibility() {
return visibility;
}
/**
* @param visibility the visibility to set
*/
public void setVisibility(Visibility visibility) {
this.visibility = visibility;
}
/**
* @return the index
*/
public Integer getIndex() {
return index;
}
/**
* @param index the index to set
*/
public void setIndex(Integer index) {
this.index = index;
}
/**
*
* @author _bastler@bstly.de
*
*/
public static class UserProfileFieldId implements Serializable {
/**
* default serialVersionUID
*/
private static final long serialVersionUID = 1L;
private Long target;
private String name;
/**
* @return the target
*/
public Long getTarget() {
return target;
}
/**
* @param target the target to set
*/
public void setTarget(Long target) {
this.target = target;
}
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}
/*
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (obj instanceof UserProfileFieldId) {
UserProfileFieldId userProfileFieldId = (UserProfileFieldId) obj;
return this.name.equals(userProfileFieldId.getName())
&& this.target.equals(userProfileFieldId.getTarget());
}
return false;
}
/*
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
return this.name.hashCode() * this.target.hashCode();
}
}
}
@@ -0,0 +1,14 @@
/**
*
*/
package de.bstly.we.model;
/**
* @author _bastler@bstly.de
*
*/
public enum UserStatus {
NORMAL, SLEEP, PURGE
}
@@ -0,0 +1,128 @@
/**
*
*/
package de.bstly.we.model;
import java.util.List;
import javax.persistence.CollectionTable;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import org.hibernate.annotations.LazyCollection;
import org.hibernate.annotations.LazyCollectionOption;
/**
* @author _bastler@bstly.de
*
*/
@Entity
@Table(name = "user_totps", uniqueConstraints = @UniqueConstraint(columnNames = { "target" }))
public class UserTotp implements SecondFactor {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Long id;
private Long target;
private boolean enabled;
@Column(name = "totp_secret", nullable = false)
private String secret;
@Column(name = "totp_qr_data", nullable = false)
private String qrData;
@ElementCollection
@LazyCollection(LazyCollectionOption.FALSE)
@CollectionTable(name = "user_totps_recovery_codes")
private List<String> recoveryCodes;
/**
* @return the id
*/
public Long getId() {
return id;
}
/**
* @param id the id to set
*/
public void setId(Long id) {
this.id = id;
}
/**
* @return the target
*/
public Long getTarget() {
return target;
}
/**
* @param target the target to set
*/
public void setTarget(Long target) {
this.target = target;
}
/**
* @return the enabled
*/
public boolean isEnabled() {
return enabled;
}
/**
* @param enabled the enabled to set
*/
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
/**
* @return the secret
*/
public String getSecret() {
return secret;
}
/**
* @param secret the secret to set
*/
public void setSecret(String secret) {
this.secret = secret;
}
/**
* @return the qrData
*/
public String getQrData() {
return qrData;
}
/**
* @param qrData the qrData to set
*/
public void setQrData(String qrData) {
this.qrData = qrData;
}
/**
* @return the recoveryCodes
*/
public List<String> getRecoveryCodes() {
return recoveryCodes;
}
/**
* @param recoveryCodes the recoveryCodes to set
*/
public void setRecoveryCodes(List<String> recoveryCodes) {
this.recoveryCodes = recoveryCodes;
}
}
@@ -0,0 +1,14 @@
/**
*
*/
package de.bstly.we.model;
/**
* @author _bastler@bstly.de
*
*/
public enum Visibility {
PRIVATE, PROTECTED, PUBLIC
}
@@ -0,0 +1,21 @@
/**
*
*/
package de.bstly.we.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.querydsl.QuerydslPredicateExecutor;
import org.springframework.stereotype.Repository;
import de.bstly.we.model.PermissionMapping;
/**
*
* @author _bastler@bstly.de
*
*/
@Repository
public interface PermissionMappingRepository
extends JpaRepository<PermissionMapping, Long>, QuerydslPredicateExecutor<PermissionMapping> {
}
@@ -0,0 +1,21 @@
/**
*
*/
package de.bstly.we.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.querydsl.QuerydslPredicateExecutor;
import org.springframework.stereotype.Repository;
import de.bstly.we.model.Permission;
/**
*
* @author _bastler@bstly.de
*
*/
@Repository
public interface PermissionRepository
extends JpaRepository<Permission, Long>, QuerydslPredicateExecutor<Permission> {
}
@@ -0,0 +1,21 @@
/**
*
*/
package de.bstly.we.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.querydsl.QuerydslPredicateExecutor;
import org.springframework.stereotype.Repository;
import de.bstly.we.model.QuotaMapping;
/**
*
* @author _bastler@bstly.de
*
*/
@Repository
public interface QuotaMappingRepository
extends JpaRepository<QuotaMapping, Long>, QuerydslPredicateExecutor<QuotaMapping> {
}
@@ -0,0 +1,20 @@
/**
*
*/
package de.bstly.we.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.querydsl.QuerydslPredicateExecutor;
import org.springframework.stereotype.Repository;
import de.bstly.we.model.Quota;
/**
*
* @author _bastler@bstly.de
*
*/
@Repository
public interface QuotaRepository extends JpaRepository<Quota, Long>, QuerydslPredicateExecutor<Quota> {
}
@@ -0,0 +1,21 @@
/**
*
*/
package de.bstly.we.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.querydsl.QuerydslPredicateExecutor;
import org.springframework.stereotype.Repository;
import de.bstly.we.model.SystemProfileField;
/**
*
* @author _bastler@bstly.de
*
*/
@Repository
public interface SystemProfileFieldRepository extends JpaRepository<SystemProfileField, String>,
QuerydslPredicateExecutor<SystemProfileField> {
}
@@ -0,0 +1,21 @@
/**
*
*/
package de.bstly.we.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.querydsl.QuerydslPredicateExecutor;
import org.springframework.stereotype.Repository;
import de.bstly.we.model.SystemProperty;
/**
*
* @author _bastler@bstly.de
*
*/
@Repository
public interface SystemPropertyRepository
extends JpaRepository<SystemProperty, String>, QuerydslPredicateExecutor<SystemProperty> {
}
@@ -0,0 +1,21 @@
/**
*
*/
package de.bstly.we.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.querydsl.QuerydslPredicateExecutor;
import org.springframework.stereotype.Repository;
import de.bstly.we.model.UserAlias;
/**
*
* @author _bastler@bstly.de
*
*/
@Repository
public interface UserAliasRepository
extends JpaRepository<UserAlias, Long>, QuerydslPredicateExecutor<UserAlias> {
}
@@ -0,0 +1,21 @@
/**
*
*/
package de.bstly.we.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.querydsl.QuerydslPredicateExecutor;
import org.springframework.stereotype.Repository;
import de.bstly.we.model.UserDomain;
/**
*
* @author _bastler@bstly.de
*
*/
@Repository
public interface UserDomainRepository
extends JpaRepository<UserDomain, Long>, QuerydslPredicateExecutor<UserDomain> {
}
@@ -0,0 +1,23 @@
/**
*
*/
package de.bstly.we.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.querydsl.QuerydslPredicateExecutor;
import org.springframework.stereotype.Repository;
import de.bstly.we.model.UserProfileField;
import de.bstly.we.model.UserProfileField.UserProfileFieldId;
/**
*
* @author _bastler@bstly.de
*
*/
@Repository
public interface UserProfileFieldRepository
extends JpaRepository<UserProfileField, UserProfileFieldId>,
QuerydslPredicateExecutor<UserProfileField> {
}
@@ -0,0 +1,20 @@
/**
*
*/
package de.bstly.we.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.querydsl.QuerydslPredicateExecutor;
import org.springframework.stereotype.Repository;
import de.bstly.we.model.User;
/**
*
* @author _bastler@bstly.de
*
*/
@Repository
public interface UserRepository extends JpaRepository<User, Long>, QuerydslPredicateExecutor<User> {
}
@@ -0,0 +1,20 @@
/**
*
*/
package de.bstly.we.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.querydsl.QuerydslPredicateExecutor;
import org.springframework.stereotype.Repository;
import de.bstly.we.model.UserTotp;
/**
*
* @author _bastler@bstly.de
*
*/
@Repository
public interface UserTotpRepository extends JpaRepository<UserTotp, Long>, QuerydslPredicateExecutor<UserTotp> {
}
@@ -0,0 +1,60 @@
/**
*
*/
package de.bstly.we.security;
import java.io.IOException;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.http.HttpStatus;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
import org.springframework.security.web.util.matcher.RequestMatcher;
import com.google.common.collect.Lists;
/**
*
* @author _bastler@bstly.de
*
*/
public class LocalAuthenticationEntryPoint extends LoginUrlAuthenticationEntryPoint {
private List<RequestMatcher> requestMatchers = Lists.newArrayList();
/**
*
* @param loginUrl
*/
public LocalAuthenticationEntryPoint(String loginFormUrl) {
super(loginFormUrl);
};
/*
* @see
* org.springframework.security.web.AuthenticationEntryPoint#commence(javax.
* servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse,
* org.springframework.security.core.AuthenticationException)
*/
@Override
public void commence(HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException) throws IOException, ServletException {
for (RequestMatcher matcher : requestMatchers) {
if (matcher.matches(request)) {
super.commence(request, response, authException);
return;
}
}
response.setStatus(HttpStatus.FORBIDDEN.value());
}
public void addRequestMatcher(RequestMatcher requestMatcher) {
this.requestMatchers.add(requestMatcher);
}
}
@@ -0,0 +1,133 @@
/**
*
*/
package de.bstly.we.security;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken;
import de.bstly.we.security.businesslogic.SecondFactorProvider;
import de.bstly.we.security.businesslogic.SecondFactorProviderManager;
import de.bstly.we.security.model.LocalUserDetails;
import de.bstly.we.security.token.LocalAnonymousAuthenticationToken;
import de.bstly.we.security.token.LocalSecondFactorAuthenticationToken;
/**
*
* @author _bastler@bstly.de
*
*/
public class LocalAuthenticationProvider extends DaoAuthenticationProvider {
@Autowired
private SecondFactorProviderManager secondFactorProviderManager;
/*
*
* @see org.springframework.security.authentication.dao.
* AbstractUserDetailsAuthenticationProvider#authenticate(org.springframework.
* security.core.Authentication)
*/
@Override
public Authentication authenticate(Authentication auth) throws AuthenticationException {
if (auth instanceof UsernamePasswordAuthenticationToken) {
auth = super.authenticate(auth);
if (auth.getPrincipal() instanceof LocalUserDetails) {
LocalUserDetails details = (LocalUserDetails) auth.getPrincipal();
if (!secondFactorProviderManager.getEnabled(details.getUserId()).isEmpty()) {
PreAuthenticatedAuthenticationToken newAuth = new PreAuthenticatedAuthenticationToken(
details, "", AuthorityUtils.createAuthorityList("ROLE_PRE_AUTH_USER"));
newAuth.setAuthenticated(false);
return newAuth;
}
return new UsernamePasswordAuthenticationToken(details, auth.getCredentials(),
details.getAuthorities());
}
} else if (auth instanceof LocalSecondFactorAuthenticationToken) {
LocalSecondFactorAuthenticationToken secondFactorAuth = (LocalSecondFactorAuthenticationToken) auth;
if (auth.getPrincipal() instanceof LocalUserDetails) {
LocalUserDetails details = (LocalUserDetails) auth.getPrincipal();
SecondFactorProvider<?> provider = secondFactorProviderManager
.getProvider(secondFactorAuth.getProvider());
if (provider == null) {
throw new SecondFactorAuthenticationException(
"invalid provider: " + secondFactorAuth.getProvider(), details);
}
if (!provider.isEnabled(details.getUserId())) {
throw new SecondFactorAuthenticationException(
"provider is disabled: " + secondFactorAuth.getProvider(), details);
}
if (provider.validate(details.getUserId(), secondFactorAuth.getCode())) {
return new UsernamePasswordAuthenticationToken(details, auth.getCredentials(),
details.getAuthorities());
} else {
PreAuthenticatedAuthenticationToken newAuth = new PreAuthenticatedAuthenticationToken(
details, "", auth.getAuthorities());
newAuth.setAuthenticated(false);
return newAuth;
}
}
}
return auth;
}
public boolean supports(Class<?> authentication) {
return (UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication))
|| (LocalSecondFactorAuthenticationToken.class.isAssignableFrom(authentication))
|| (LocalAnonymousAuthenticationToken.class.isAssignableFrom(authentication));
}
/**
*
* @author _bastler@bstly.de
*
*/
public static class SecondFactorAuthenticationException
extends InsufficientAuthenticationException {
private LocalUserDetails principal;
/**
* serialVersionUID
*/
private static final long serialVersionUID = 1L;
/**
* @param msg
*/
public SecondFactorAuthenticationException(String message, LocalUserDetails principal) {
super(message);
this.principal = principal;
}
/**
* @return the principal
*/
public LocalUserDetails getPrincipal() {
return principal;
}
/**
* @param principal the principal to set
*/
public void setPrincipal(LocalUserDetails principal) {
this.principal = principal;
}
}
}
@@ -0,0 +1,49 @@
/**
*
*/
package de.bstly.we.security;
import javax.servlet.http.HttpServletRequest;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.rememberme.PersistentTokenBasedRememberMeServices;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
/**
*
* @author _bastler@bstly.de
*
*/
public class LocalRememberMeServices extends PersistentTokenBasedRememberMeServices {
/**
* @param key
* @param userDetailsService
* @param tokenRepository
*/
public LocalRememberMeServices(String key, UserDetailsService userDetailsService,
PersistentTokenRepository tokenRepository) {
super(key, userDetailsService, tokenRepository);
}
/*
*
* @see org.springframework.security.web.authentication.rememberme.
* AbstractRememberMeServices#rememberMeRequested(javax.servlet.http.
* HttpServletRequest, java.lang.String)
*/
@Override
protected boolean rememberMeRequested(HttpServletRequest request, String parameter) {
Object value = request.getAttribute(parameter);
if (value != null) {
String paramValue = value.toString();
if (paramValue.equalsIgnoreCase("true") || paramValue.equalsIgnoreCase("on")
|| paramValue.equalsIgnoreCase("yes") || paramValue.equals("1")) {
return true;
}
}
return super.rememberMeRequested(request, parameter);
}
}

Some files were not shown because too many files have changed in this diff Show More