prepared file upload

This commit is contained in:
Jottyfan
2023-01-28 18:40:23 +01:00
parent e6e625306d
commit 9e7850a4a1
37 changed files with 625 additions and 76 deletions

View File

@@ -13,6 +13,7 @@ import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import de.jottyfan.camporganizer.module.camplist.CommonController;
@@ -34,6 +35,17 @@ public class AdminController extends CommonController {
@Value("${spring.mail.username}")
private String from;
@GetMapping("/admin")
public String getMain(Model model, HttpServletRequest request) {
super.setupSession(model, request);
return "/admin/main";
}
@GetMapping("/admin/main")
public String getMainDirectly() {
return "redirect:/admin/main";
}
@GetMapping("/admin/mail")
public String getMail(Model model, HttpServletRequest request) {
super.setupSession(model, request);
@@ -50,21 +62,44 @@ public class AdminController extends CommonController {
super.setupSession(model, request);
if (bindingResult.hasErrors()) {
for (ObjectError error : bindingResult.getAllErrors())
LOGGER.error("error {}: {}", error.getCode(), error.getDefaultMessage());
LOGGER.error("error {}: {}", error.getCode(), error.getDefaultMessage());
return "/admin/mail";
}
service.sendMail(bean);
return "redirect:/admin";
}
@GetMapping("/admin")
public String getMain(Model model, HttpServletRequest request) {
@GetMapping("/admin/document")
public String getDocuments(Model model, HttpServletRequest request) {
super.setupSession(model, request);
return "/admin/main";
model.addAttribute("documents", service.getAllDocuments());
return "/admin/document";
}
@GetMapping("/admin/main")
public String getMainDirectly() {
return "redirect:/admin/main";
@GetMapping("/admin/document/add")
public String prepareAddDocument(Model model, HttpServletRequest request) {
super.setupSession(model, request);
model.addAttribute("bean", new DocumentBean());
return "/admin/document_edit";
}
@GetMapping("/admin/document/edit/{id}")
public String prepareAddDocument(@PathVariable Integer id, Model model, HttpServletRequest request) {
super.setupSession(model, request);
model.addAttribute("bean", service.getDocument(id));
return "/admin/document_edit";
}
@PostMapping("/admin/document/update")
public String updateDocument(@Valid @ModelAttribute("bean") DocumentBean bean,
final BindingResult bindingResult, Model model, HttpServletRequest request) {
super.setupSession(model, request);
if (bindingResult.hasErrors()) {
for (ObjectError error : bindingResult.getAllErrors())
LOGGER.error("error {}: {}", error.getCode(), error.getDefaultMessage());
return "/admin/document_edit";
}
service.updateDocument(bean);
return "redirect:/admin/document";
}
}

View File

@@ -0,0 +1,186 @@
package de.jottyfan.camporganizer.module.admin;
import static de.jottyfan.camporganizer.db.jooq.Tables.T_DOCUMENT;
import static de.jottyfan.camporganizer.db.jooq.Tables.T_DOCUMENTROLE;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.jooq.DSLContext;
import org.jooq.DeleteConditionStep;
import org.jooq.Field;
import org.jooq.InsertResultStep;
import org.jooq.InsertReturningStep;
import org.jooq.Record5;
import org.jooq.SelectSeekStep1;
import org.jooq.UpdateConditionStep;
import org.jooq.exception.DataAccessException;
import org.jooq.impl.DSL;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import de.jottyfan.camporganizer.db.jooq.enums.EnumCamprole;
import de.jottyfan.camporganizer.db.jooq.enums.EnumDocument;
import de.jottyfan.camporganizer.db.jooq.enums.EnumFiletype;
import de.jottyfan.camporganizer.db.jooq.tables.records.TDocumentRecord;
import de.jottyfan.camporganizer.db.jooq.tables.records.TDocumentroleRecord;
import de.jottyfan.camporganizer.module.camplist.LambdaResultWrapper;
/**
*
* @author jotty
*
*/
@Repository
@Transactional(transactionManager = "transactionManager")
public class AdminRepository {
private static final Logger LOGGER = LogManager.getLogger(AdminRepository.class);
@Autowired
private DSLContext jooq;
/**
* get the document with that ID
*
* @param id the ID of the document
* @return the document
*/
public DocumentBean getDocument(Integer id) {
Field<EnumCamprole[]> ROLES = DSL.field("roles", EnumCamprole[].class);
SelectSeekStep1<Record5<Integer, String, EnumDocument, EnumFiletype, EnumCamprole[]>, Integer> sql = jooq
// @formatter:off
.select(T_DOCUMENT.PK,
T_DOCUMENT.NAME,
T_DOCUMENT.DOCTYPE,
T_DOCUMENT.FILETYPE,
DSL.arrayAgg(T_DOCUMENTROLE.CAMPROLE).as(ROLES))
.from(T_DOCUMENT)
.leftJoin(T_DOCUMENTROLE).on(T_DOCUMENTROLE.FK_DOCUMENT.eq(T_DOCUMENT.PK))
.where(T_DOCUMENT.PK.eq(id))
.groupBy(T_DOCUMENT.PK, T_DOCUMENT.NAME, T_DOCUMENT.DOCTYPE, T_DOCUMENT.FILETYPE)
.orderBy(T_DOCUMENT.PK);
// @formatter:on
LOGGER.debug(sql.toString());
Record5<Integer, String, EnumDocument, EnumFiletype, EnumCamprole[]> r = sql.fetchOne();
if (r != null ) {
DocumentBean bean = new DocumentBean();
bean.setPk(r.get(T_DOCUMENT.PK));
bean.setName(r.get(T_DOCUMENT.NAME));
bean.setDoctype(r.get(T_DOCUMENT.DOCTYPE));
bean.setFiletype(r.get(T_DOCUMENT.FILETYPE));
bean.setRoles(r.get(ROLES));
return bean;
}
return null;
}
/**
* get all documents from the database
*
* @return all documents
*/
public List<DocumentBean> getAllDocuments() {
Field<EnumCamprole[]> ROLES = DSL.field("roles", EnumCamprole[].class);
SelectSeekStep1<Record5<Integer, String, EnumDocument, EnumFiletype, EnumCamprole[]>, Integer> sql = jooq
// @formatter:off
.select(T_DOCUMENT.PK,
T_DOCUMENT.NAME,
T_DOCUMENT.DOCTYPE,
T_DOCUMENT.FILETYPE,
DSL.arrayAgg(T_DOCUMENTROLE.CAMPROLE).as(ROLES))
.from(T_DOCUMENT)
.leftJoin(T_DOCUMENTROLE).on(T_DOCUMENTROLE.FK_DOCUMENT.eq(T_DOCUMENT.PK))
.groupBy(T_DOCUMENT.PK, T_DOCUMENT.NAME, T_DOCUMENT.DOCTYPE, T_DOCUMENT.FILETYPE)
.orderBy(T_DOCUMENT.PK);
// @formatter:on
LOGGER.debug(sql.toString());
List<DocumentBean> list = new ArrayList<>();
for (Record5<Integer, String, EnumDocument, EnumFiletype, EnumCamprole[]> r : sql.fetch()) {
DocumentBean bean = new DocumentBean();
bean.setPk(r.get(T_DOCUMENT.PK));
bean.setName(r.get(T_DOCUMENT.NAME));
bean.setDoctype(r.get(T_DOCUMENT.DOCTYPE));
bean.setFiletype(r.get(T_DOCUMENT.FILETYPE));
bean.setRoles(r.get(ROLES));
list.add(bean);
}
return list;
}
/**
* upsert document in t_document
*
* @param document
* @throws DataAccessException
*/
public Integer upsert(DocumentBean bean) throws DataAccessException {
LambdaResultWrapper lrw = new LambdaResultWrapper();
jooq.transaction(c -> {
Integer pk = bean.getPk();
if (bean.getPk() != null) {
UpdateConditionStep<TDocumentRecord> sql = DSL.using(c)
// @formatter:off
.update(T_DOCUMENT)
.set(T_DOCUMENT.NAME, bean.getName())
.set(T_DOCUMENT.DOCTYPE, bean.getDoctype())
.set(T_DOCUMENT.DOCUMENT, bean.getDocument())
.set(T_DOCUMENT.FILETYPE, bean.getFiletype())
.where(T_DOCUMENT.PK.eq(bean.getPk()));
// @formatter:on
LOGGER.debug("{}", sql.toString());
lrw.add(sql.execute());
} else {
InsertResultStep<TDocumentRecord> sql = DSL.using(c)
// @formatter:off
.insertInto(T_DOCUMENT,
T_DOCUMENT.NAME,
T_DOCUMENT.DOCTYPE,
T_DOCUMENT.DOCUMENT,
T_DOCUMENT.FILETYPE)
.values(bean.getName(), bean.getDoctype(), bean.getDocument(), bean.getFiletype())
.returning(T_DOCUMENT.PK);
// @formatter:on
LOGGER.debug("{}", sql.toString());
pk = sql.fetchOne().get(T_DOCUMENT.PK);
lrw.add(1);
}
List<EnumCamprole> allEnums = Arrays.asList(EnumCamprole.values());
Set<EnumCamprole> removeCandidates = new HashSet<>();
removeCandidates.addAll(allEnums);
for (EnumCamprole role : bean.getRoles()) {
try {
InsertReturningStep<TDocumentroleRecord> sql = DSL.using(c)
// @formatter:off
.insertInto(T_DOCUMENTROLE,
T_DOCUMENTROLE.FK_DOCUMENT,
T_DOCUMENTROLE.CAMPROLE)
.values(pk, role)
.onConflict(T_DOCUMENTROLE.FK_DOCUMENT, T_DOCUMENTROLE.CAMPROLE)
.doNothing();
// @formatter:on
LOGGER.debug("{}", sql.toString());
lrw.add(sql.execute());
removeCandidates.remove(role);
} catch (IllegalArgumentException e) {
LOGGER.error(e);
}
}
DeleteConditionStep<TDocumentroleRecord> sql = DSL.using(c)
// @formatter:off
.deleteFrom(T_DOCUMENTROLE)
.where(T_DOCUMENTROLE.FK_DOCUMENT.eq(pk))
.and(T_DOCUMENTROLE.CAMPROLE.in(removeCandidates));
// @formatter:on
LOGGER.debug("{}", sql.toString());
lrw.add(sql.execute());
});
return lrw.getCounter();
}
}

View File

@@ -1,5 +1,7 @@
package de.jottyfan.camporganizer.module.admin;
import java.util.List;
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
@@ -19,8 +21,39 @@ public class AdminService {
@Autowired
private MailRepository mailRepository;
@Autowired
private AdminRepository adminRepository;
public void sendMail(@Valid MailBean bean) {
mailRepository.sendMail(bean);
}
/**
* get all documents
*
* @return a list of documents; an empty one at least
*/
public List<DocumentBean> getAllDocuments() {
return adminRepository.getAllDocuments();
}
/**
* get document from the database
*
* @param id the ID of the document
* @return the document or null
*/
public DocumentBean getDocument(Integer id) {
return adminRepository.getDocument(id);
}
/**
* upsert the document bean
*
* @param bean the bean
* @return the number of affected database lines
*/
public Integer updateDocument(@Valid DocumentBean bean) {
return adminRepository.upsert(bean);
}
}

View File

@@ -0,0 +1,107 @@
package de.jottyfan.camporganizer.module.admin;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.util.Base64;
import javax.servlet.http.Part;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import org.apache.commons.io.IOUtils;
import de.jottyfan.camporganizer.db.jooq.enums.EnumCamprole;
import de.jottyfan.camporganizer.db.jooq.enums.EnumDocument;
import de.jottyfan.camporganizer.db.jooq.enums.EnumFiletype;
/**
*
* @author jotty
*
*/
public class DocumentBean implements Serializable{
private static final long serialVersionUID = 1L;
private Integer pk;
@NotNull
private EnumDocument doctype;
@NotBlank
private String name;
private String document;
@NotNull
private EnumFiletype filetype;
@NotNull
private Part uploadfile;
private EnumCamprole[] roles;
public void encodeUpload() throws IOException {
if (uploadfile != null) {
InputStream inputStream = uploadfile.getInputStream();
byte[] bytes = IOUtils.toByteArray(inputStream);
if (bytes.length > 0) {
document = Base64.getEncoder().encodeToString(bytes);
} // not uploaded files should not be changed, so document must be kept as is
}
}
public Integer getPk() {
return pk;
}
public void setDoctype(EnumDocument doctype) {
this.doctype = doctype;
}
public EnumDocument getDoctype() {
return doctype;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setDocument(String document) {
this.document = document;
}
public String getDocument() {
return document;
}
public void setFiletype(EnumFiletype filetype) {
this.filetype = filetype;
}
public EnumFiletype getFiletype() {
return filetype;
}
public Part getUploadfile() {
return uploadfile;
}
public void setUploadfile(Part uploadfile) {
this.uploadfile = uploadfile;
}
public EnumCamprole[] getRoles() {
return roles;
}
public void setRoles(EnumCamprole[] roles) {
this.roles = roles;
}
/**
* @param pk the pk to set
*/
public void setPk(Integer pk) {
this.pk = pk;
}
}

View File

@@ -34,8 +34,8 @@ import de.jottyfan.camporganizer.db.jooq.tables.records.TPersonRecord;
*/
@Repository
@Transactional(transactionManager = "transactionManager")
public class BookingsGateway {
private static final Logger LOGGER = LogManager.getLogger(BookingsGateway.class);
public class BookingsRepository {
private static final Logger LOGGER = LogManager.getLogger(BookingsRepository.class);
@Autowired
private DSLContext jooq;

View File

@@ -16,7 +16,7 @@ import de.jottyfan.camporganizer.module.business.bookings.IBookingsService;
public class BookingsService implements IBookingsService {
@Autowired
private BookingsGateway bookingsGateway;
private BookingsRepository bookingsGateway;
@Override
public List<BookerBean> getBookers(String username) {

View File

@@ -33,8 +33,8 @@ import de.jottyfan.camporganizer.db.jooq.tables.records.TPersonRecord;
*/
@Repository
@Transactional(transactionManager = "transactionManager")
public class BusinessGateway {
private static final Logger LOGGER = LogManager.getLogger(BusinessGateway.class);
public class BusinessRepository {
private static final Logger LOGGER = LogManager.getLogger(BusinessRepository.class);
@Autowired
private DSLContext jooq;

View File

@@ -19,7 +19,7 @@ import de.jottyfan.camporganizer.module.business.business.IBusinessService;
@Service
public class BusinessService implements IBusinessService {
@Autowired
private BusinessGateway gateway;
private BusinessRepository gateway;
@Override
public String getCurrentUser(HttpServletRequest request) {

View File

@@ -32,8 +32,8 @@ import de.jottyfan.camporganizer.db.jooq.enums.EnumSex;
*/
@Repository
@Transactional(transactionManager = "transactionManager")
public class CampGateway {
private static final Logger LOGGER = LogManager.getLogger(CampGateway.class);
public class CampRepository {
private static final Logger LOGGER = LogManager.getLogger(CampRepository.class);
@Autowired
private DSLContext jooq;

View File

@@ -17,7 +17,7 @@ import de.jottyfan.camporganizer.module.business.camp.ICampService;
public class CampService implements ICampService {
@Autowired
private CampGateway campGateway;
private CampRepository campGateway;
@Override
public CampBean getCamp(Integer id, String username) {

View File

@@ -29,8 +29,8 @@ import de.jottyfan.camporganizer.db.jooq.tables.records.TSalesprofileRecord;
*/
@Repository
@Transactional(transactionManager = "transactionManager")
public class PrivilegesGateway {
private static final Logger LOGGER = LogManager.getLogger(PrivilegesGateway.class);
public class PrivilegesRepository {
private static final Logger LOGGER = LogManager.getLogger(PrivilegesRepository.class);
@Autowired
private DSLContext jooq;

View File

@@ -18,7 +18,7 @@ import de.jottyfan.camporganizer.module.business.privileges.IPrivilegesService;
@Service
public class PrivilegesService implements IPrivilegesService {
@Autowired
private PrivilegesGateway gateway;
private PrivilegesRepository gateway;
@Override
public Map<Integer, CampBean> getPrivileges() {

View File

@@ -13,7 +13,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import de.jottyfan.camporganizer.db.jooq.tables.records.VCampRecord;
import de.jottyfan.camporganizer.module.dashboard.DashboardGateway;
import de.jottyfan.camporganizer.module.dashboard.DashboardRepository;
/**
*
@@ -27,7 +27,7 @@ public class CamplistService {
private CamplistGateway gateway;
@Autowired
private DashboardGateway dashboardGateway;
private DashboardRepository dashboardGateway;
/**
* get all camps from the database and prepare them for the view

View File

@@ -38,8 +38,8 @@ import de.jottyfan.camporganizer.db.jooq.enums.EnumModule;
*/
@Repository
@Transactional(transactionManager = "transactionManager")
public class ConfirmationGateway {
private static final Logger LOGGER = LogManager.getLogger(ConfirmationGateway.class);
public class ConfirmationRepository {
private static final Logger LOGGER = LogManager.getLogger(ConfirmationRepository.class);
@Autowired
private DSLContext jooq;

View File

@@ -19,7 +19,7 @@ import de.jottyfan.camporganizer.module.confirmation.confirmation.IConfirmationS
@Service
public class ConfirmationService implements IConfirmationService {
@Autowired
private ConfirmationGateway gateway;
private ConfirmationRepository gateway;
@Override
public String getCurrentUser(HttpServletRequest request) {

View File

@@ -46,8 +46,8 @@ import de.jottyfan.camporganizer.module.mail.MailRepository;
*/
@Repository
@Transactional(transactionManager = "transactionManager")
public class PersonGateway {
private static final Logger LOGGER = LogManager.getLogger(PersonGateway.class);
public class PersonRepository {
private static final Logger LOGGER = LogManager.getLogger(PersonRepository.class);
@Autowired
private DSLContext jooq;

View File

@@ -15,7 +15,7 @@ import de.jottyfan.camporganizer.module.confirmation.person.IPersonService;
@Service
public class PersonService implements IPersonService {
@Autowired
private PersonGateway gateway;
private PersonRepository gateway;
@Override
public PersonBean getPerson(String username, Integer pk) {

View File

@@ -31,8 +31,8 @@ import de.jottyfan.camporganizer.module.camplist.LambdaResultWrapper;
*/
@Repository
@Transactional(transactionManager = "transactionManager")
public class DashboardGateway {
private static final Logger LOGGER = LogManager.getLogger(DashboardGateway.class);
public class DashboardRepository {
private static final Logger LOGGER = LogManager.getLogger(DashboardRepository.class);
@Autowired
private DSLContext jooq;

View File

@@ -30,8 +30,8 @@ import biweekly.property.Summary;
*/
@Repository
@Transactional(transactionManager = "transactionManager")
public class ICalGateway {
private static final Logger LOGGER = LogManager.getLogger(ICalGateway.class);
public class ICalRepository {
private static final Logger LOGGER = LogManager.getLogger(ICalRepository.class);
@Autowired
private DSLContext jooq;

View File

@@ -20,7 +20,7 @@ import de.jottyfan.camporganizer.module.ical.IICalService;
public class ICalService implements IICalService {
@Autowired
private ICalGateway gateway;
private ICalRepository gateway;
@Override
public Boolean generate(HttpServletResponse response) throws IOException {

View File

@@ -53,8 +53,8 @@ import de.jottyfan.camporganizer.module.camplist.LambdaResultWrapper;
*/
@Repository
@Transactional(transactionManager = "transactionManager")
public class RegistrationGateway {
private static final Logger LOGGER = LogManager.getLogger(RegistrationGateway.class);
public class RegistrationRepository {
private static final Logger LOGGER = LogManager.getLogger(RegistrationRepository.class);
@Autowired
private DSLContext jooq;

View File

@@ -17,7 +17,7 @@ public class RegistrationService {
private final static Logger LOGGER = LogManager.getLogger(RegistrationService.class);
@Autowired
private RegistrationGateway gateway;
private RegistrationRepository gateway;
@Autowired
private KeycloakRepository keycloak;

View File

@@ -6,7 +6,7 @@ import javax.validation.ConstraintValidatorContext;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.beans.factory.annotation.Autowired;
import de.jottyfan.camporganizer.module.registration.RegistrationGateway;
import de.jottyfan.camporganizer.module.registration.RegistrationRepository;
/**
*
@@ -19,7 +19,7 @@ public class UnusedUsernameValidator implements ConstraintValidator<UnusedUserna
private String message;
@Autowired
private RegistrationGateway gateway;
private RegistrationRepository gateway;
public void initialize(UnusedUsername uu) {
this.field = uu.field();