diff --git a/prototype/src/main/java/org/hso/ecommerce/components/AdminInitializer.java b/prototype/src/main/java/org/hso/ecommerce/components/AdminInitializer.java new file mode 100644 index 0000000..579bbe3 --- /dev/null +++ b/prototype/src/main/java/org/hso/ecommerce/components/AdminInitializer.java @@ -0,0 +1,36 @@ +package org.hso.ecommerce.components; + +import org.hso.ecommerce.entities.booking.PaymentMethod; +import org.hso.ecommerce.entities.user.User; +import org.hso.ecommerce.repos.user.UserRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; +import java.sql.Timestamp; +import java.util.Optional; + +@Component +public class AdminInitializer { + + @Autowired + private final UserRepository userRepository = null; + + @PostConstruct + public void init() { + Optional numberOfEmployees = userRepository.numberOfEmployees(); + if (numberOfEmployees.orElse(0) == 0) { + // create first admin user + User firstAdmin = new User(); + firstAdmin.created = new Timestamp(System.currentTimeMillis()); + firstAdmin.name = "admin"; + firstAdmin.defaultPayment = new PaymentMethod(); + firstAdmin.defaultPayment.creditCardNumber = ""; //set empty number + firstAdmin.email = "admin"; + firstAdmin.isActive = true; + firstAdmin.isEmployee = true; + firstAdmin.setPassword("admin"); + userRepository.save(firstAdmin); //save to DB + } + } +} diff --git a/prototype/src/main/java/org/hso/ecommerce/components/SlotInitializer.java b/prototype/src/main/java/org/hso/ecommerce/components/SlotInitializer.java index ce8c39b..72c4f8a 100644 --- a/prototype/src/main/java/org/hso/ecommerce/components/SlotInitializer.java +++ b/prototype/src/main/java/org/hso/ecommerce/components/SlotInitializer.java @@ -10,23 +10,21 @@ import javax.annotation.PostConstruct; @Component public class SlotInitializer { - @Autowired - private final SlotRepository slotRepository = null; + @Autowired + private final SlotRepository slotRepository = null; - // TODO: use values form cfg. - private final int NUM_SLOTS = 50; - - @PostConstruct - public void init() { - for (int i = 1; i <= NUM_SLOTS; i++) { - if (!slotRepository.findBySlotNum(i).isPresent()) { - Slot slotAdded = new Slot(); - slotAdded.slotNum = i; - slotRepository.save(slotAdded); - - System.out.println("Added Slot " + i + " to DB"); - } - } - } + // TODO: use values form cfg. + private final int NUM_SLOTS = 50; + @PostConstruct + public void init() { + for (int i = 1; i <= NUM_SLOTS; i++) { + if (!slotRepository.findBySlotNum(i).isPresent()) { + Slot slotAdded = new Slot(); + slotAdded.slotNum = i; + slotRepository.save(slotAdded); + System.out.println("Added Slot " + i + " to DB"); + } + } + } } diff --git a/prototype/src/main/java/org/hso/ecommerce/controller/RegisterController.java b/prototype/src/main/java/org/hso/ecommerce/controller/RegisterController.java index 36fcdef..008cd0b 100644 --- a/prototype/src/main/java/org/hso/ecommerce/controller/RegisterController.java +++ b/prototype/src/main/java/org/hso/ecommerce/controller/RegisterController.java @@ -26,8 +26,6 @@ public class RegisterController { @RequestParam("username") String username, @RequestParam("password") String password, @RequestParam("password2") String password2, @RequestParam("salutation") String salutation, @RequestParam("name") String name, @RequestParam("address") String address, - @RequestParam("type") String type, // TODO store - @RequestParam("ad") String ad, // TODO store HttpSession session) { Optional user = userRepository.findByEmail(username); if (user.isPresent()) { diff --git a/prototype/src/main/java/org/hso/ecommerce/controller/UserController.java b/prototype/src/main/java/org/hso/ecommerce/controller/UserController.java index 0855f0a..05280ab 100644 --- a/prototype/src/main/java/org/hso/ecommerce/controller/UserController.java +++ b/prototype/src/main/java/org/hso/ecommerce/controller/UserController.java @@ -3,6 +3,7 @@ package org.hso.ecommerce.controller; import org.hso.ecommerce.action.user.CreateDeliveryData; import org.hso.ecommerce.action.user.UpdateUserSettingsAction; import org.hso.ecommerce.api.RestServiceForDelivery; +import org.hso.ecommerce.entities.shop.Address; import org.hso.ecommerce.entities.shop.CustomerOrder; import org.hso.ecommerce.entities.user.User; import org.hso.ecommerce.repos.shop.CustomerOrderRepository; @@ -47,6 +48,9 @@ public class UserController { ) { long userId = (long) session.getAttribute("userId"); User user = userRepository.findById(userId).get(); + if(user.defaultDeliveryAddress == null){ + user.defaultDeliveryAddress = new Address(); + } model.addAttribute("user", user); return "user/settings"; diff --git a/prototype/src/main/java/org/hso/ecommerce/controller/cronjob/CronjobController.java b/prototype/src/main/java/org/hso/ecommerce/controller/cronjob/CronjobController.java index 0f54221..dbf7c6c 100644 --- a/prototype/src/main/java/org/hso/ecommerce/controller/cronjob/CronjobController.java +++ b/prototype/src/main/java/org/hso/ecommerce/controller/cronjob/CronjobController.java @@ -1,6 +1,7 @@ package org.hso.ecommerce.controller.cronjob; import java.sql.Timestamp; +import java.util.ArrayList; import java.util.Calendar; import java.util.Collections; import java.util.GregorianCalendar; @@ -37,6 +38,11 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import org.springframework.ui.Model; +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.RequestMapping; interface ICronjob { /** @@ -63,10 +69,22 @@ interface ICronjob { * @param controller Back-reference that allows to use repositories. */ void executeAt(Calendar time, CronjobController controller); + + /** + * Get a name for this cronjob, that can be presented to the user in the frontend. + * + * @return A german name of this cronjob. + */ + String getDisplayName(); } @Component class Reorder implements ICronjob { + @Override + public String getDisplayName() { + return "Nachbestellung"; + } + @Override public Calendar nextExecution(Calendar reference) { if (reference.get(Calendar.HOUR_OF_DAY) >= 8) { @@ -215,6 +233,7 @@ class ScheduledCronjob { } @Component +@RequestMapping("intern/cronjobs") class CronjobController { private static final Logger log = LoggerFactory.getLogger(CronjobController.class); @@ -328,4 +347,42 @@ class CronjobController { public void onPostConstruct() { new Thread(this::runCronjobExecutionLoop).start(); } + + class ManualCronjob { + public final String identifier; + public final String visibleName; + + public ManualCronjob(String identifier, String visibleName) { + this.identifier = identifier; + this.visibleName = visibleName; + } + } + + private List listAllCronjobs() { + ArrayList entries = new ArrayList<>(); + for (Entry job : cronjobs.entrySet()) { + entries.add(new ManualCronjob(job.getKey(), job.getValue().getDisplayName())); + } + return entries; + } + + @GetMapping("/") + public String cronjobOverview(Model model) { + model.addAttribute("jobs", listAllCronjobs()); + return "intern/cronjobs/index"; + } + + @PostMapping("/run/{identifier}") + public String runCronjob(Model model, @PathVariable("identifier") String identifier) { + ICronjob jobToExecute = cronjobs.get(identifier); + if (jobToExecute != null) { + jobToExecute.executeAt(new GregorianCalendar(), this); + model.addAttribute("info", + String.format("Der Cronjob \"%s\" wurde ausgeführt.", jobToExecute.getDisplayName())); + } else { + model.addAttribute("error", "Der Cronjob konnte nicht gefunden werden."); + } + model.addAttribute("jobs", listAllCronjobs()); + return "intern/cronjobs/index"; + } } diff --git a/prototype/src/main/java/org/hso/ecommerce/controller/intern/InternArticleController.java b/prototype/src/main/java/org/hso/ecommerce/controller/intern/InternArticleController.java index e799210..38b2222 100644 --- a/prototype/src/main/java/org/hso/ecommerce/controller/intern/InternArticleController.java +++ b/prototype/src/main/java/org/hso/ecommerce/controller/intern/InternArticleController.java @@ -22,6 +22,7 @@ import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.nio.file.Files; +import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; @@ -171,15 +172,22 @@ public class InternArticleController { if (imageID.isPresent()) { article.image = imageRepository.findImageById(imageID.get()); // add existing img to article } else { + + Path targetPath = Paths.get("./data/img/"); + if (Files.notExists(targetPath)) { + Files.createDirectories(targetPath); + } + // write new img file to disk - Files.newOutputStream(Paths.get("./data/img/", fileName)).write(imgFile.getBytes()); + Files.newOutputStream(Paths.get(targetPath.toString(), fileName)).write(imgFile.getBytes()); // create new img Image newImage = new Image(); newImage.path = "./data/img/" + fileName; // set new file to new img imageRepository.save(newImage); // save new img article.image = newImage; // set new img to article } - } catch (Exception e) { + } catch (IOException e) { + e.printStackTrace(); setDefaultImage(article); // if upload failed, reset to default img } } diff --git a/prototype/src/main/java/org/hso/ecommerce/controller/intern/customers/CustomersIndexController.java b/prototype/src/main/java/org/hso/ecommerce/controller/intern/customers/CustomersIndexController.java index d709948..336aabc 100644 --- a/prototype/src/main/java/org/hso/ecommerce/controller/intern/customers/CustomersIndexController.java +++ b/prototype/src/main/java/org/hso/ecommerce/controller/intern/customers/CustomersIndexController.java @@ -1,9 +1,5 @@ package org.hso.ecommerce.controller.intern.customers; -import java.util.List; - -import javax.servlet.http.HttpServletRequest; - import org.hso.ecommerce.controller.intern.accounting.AccountingController; import org.hso.ecommerce.controller.intern.accounting.AccountingController.ShortTemplateBookingResult; import org.hso.ecommerce.entities.booking.Booking; @@ -13,12 +9,13 @@ import org.hso.ecommerce.repos.booking.BookingRepository; import org.hso.ecommerce.repos.shop.CustomerOrderRepository; import org.hso.ecommerce.repos.user.UserRepository; import org.springframework.beans.factory.annotation.Autowired; - import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.*; +import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import java.util.List; import java.util.Optional; @Controller @@ -104,18 +101,18 @@ public class CustomersIndexController { ) { if (!password.equals(password2)) { request.setAttribute("error", "Passwörter stimmen nicht überein!"); - return "/intern/customers/id"; + return "intern/customers/id"; } User user = userRepository.findById(id).get(); if (!user.validatePassword(password)) { request.setAttribute("error", "Die Passwörter stimmen nicht mit dem Original überein!"); - return "/intern/customers/id"; + return "intern/customers/id"; } user.setPassword("12345"); userRepository.save(user); request.setAttribute("info", "Passwort wurde auf 12345 geändert!"); - return "/intern/customers/id"; + return "intern/customers/id"; } } diff --git a/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopArticleController.java b/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopArticleController.java index 18144f7..b1df109 100644 --- a/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopArticleController.java +++ b/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopArticleController.java @@ -16,6 +16,7 @@ import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; +import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; @@ -100,11 +101,18 @@ public class ShopArticleController { @PathVariable("id") Long id ) throws IOException { Article article = articleRepository.findArticleById(id); - + if(article.image != null) { - InputStream in = new FileInputStream(article.image.path); - response.setContentType(MediaType.IMAGE_JPEG_VALUE); - IOUtils.copy(in, response.getOutputStream()); + File file = new File(article.image.path); + File allowedPath = new File("./data/img/"); + + if (file.getCanonicalPath().startsWith(allowedPath.getCanonicalPath())) { + InputStream in = new FileInputStream(file); + response.setContentType(MediaType.IMAGE_JPEG_VALUE); + IOUtils.copy(in, response.getOutputStream()); + } else { + throw new RuntimeException("Got illegal file path. DB was modified."); + } } } } \ No newline at end of file diff --git a/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopCheckoutController.java b/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopCheckoutController.java index 8b0b1ba..981e4b7 100644 --- a/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopCheckoutController.java +++ b/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopCheckoutController.java @@ -109,7 +109,7 @@ public class ShopCheckoutController { ) { if (shoppingCart.getRevision() != cartRevision) { - request.setAttribute("error", "Der Warenkorb wurde zwischenzeitlich bearbeitet. Daher die Kaufvorgang nicht abgeschlossen werden. Bitte versuchen Sie es erneut."); + request.setAttribute("error", "Der Warenkorb wurde zwischenzeitlich bearbeitet. Daher konnte der Kaufvorgang nicht abgeschlossen werden. Bitte versuchen Sie es erneut."); response.setStatus(HttpServletResponse.SC_CONFLICT); return "shop/checkout"; } diff --git a/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopSearchController.java b/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopSearchController.java index 47b8acf..53d03fb 100644 --- a/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopSearchController.java +++ b/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopSearchController.java @@ -7,7 +7,9 @@ import org.hso.ecommerce.repos.shop.CategoryRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -45,6 +47,9 @@ public class ShopSearchController { return "error/404"; } - return "/shop/search"; + // Show term in search box + model.addAttribute("searchterm", term != null ? term : ""); + + return "shop/search"; } } \ No newline at end of file diff --git a/prototype/src/main/java/org/hso/ecommerce/repos/user/UserRepository.java b/prototype/src/main/java/org/hso/ecommerce/repos/user/UserRepository.java index 8b34eea..c48b9af 100644 --- a/prototype/src/main/java/org/hso/ecommerce/repos/user/UserRepository.java +++ b/prototype/src/main/java/org/hso/ecommerce/repos/user/UserRepository.java @@ -10,8 +10,9 @@ import java.util.Optional; @Repository public interface UserRepository extends JpaRepository { - @Query("SELECT c FROM User c WHERE c.email = :email") - Optional findByEmail(String email); + @Query("SELECT c FROM User c WHERE c.email = :email") + Optional findByEmail(String email); + + @Query("SELECT count(*) FROM User WHERE isEmployee = true") + Optional numberOfEmployees(); } - - diff --git a/prototype/src/main/resources/static/css/manual-cronjobs.css b/prototype/src/main/resources/static/css/manual-cronjobs.css new file mode 100644 index 0000000..19205d5 --- /dev/null +++ b/prototype/src/main/resources/static/css/manual-cronjobs.css @@ -0,0 +1,35 @@ +.alert { + display: block; + text-transform: uppercase; + background: #c0392b; + color: white; + animation: blinking 1s linear infinite; + overflow: hidden; +} + +.alert > span { + display: inline-block; + padding-left: 100%; + animation: marquee 10s linear infinite; + white-space: nowrap; +} + +@keyframes marquee { + 0% { transform: translateX(0); } + 100% { transform: translateX(-100%); } +} + +@keyframes blinking { + 60% { + color: white; + } + 75% { + color: #c0392b; + } + 85% { + color: #c0392b; + } + 100% { + color: white; + } +} diff --git a/prototype/src/main/resources/static/favicon.ico b/prototype/src/main/resources/static/favicon.ico new file mode 100644 index 0000000..327529b Binary files /dev/null and b/prototype/src/main/resources/static/favicon.ico differ diff --git a/prototype/src/main/resources/templates/fragments/header.html b/prototype/src/main/resources/templates/fragments/header.html index 349f72c..1b0b75c 100644 --- a/prototype/src/main/resources/templates/fragments/header.html +++ b/prototype/src/main/resources/templates/fragments/header.html @@ -11,7 +11,8 @@
- +
Login @@ -25,7 +26,10 @@
- Warenkorb () + Warenkorb + () + +
diff --git a/prototype/src/main/resources/templates/fragments/intern.html b/prototype/src/main/resources/templates/fragments/intern.html index 22de534..eee1c8d 100644 --- a/prototype/src/main/resources/templates/fragments/intern.html +++ b/prototype/src/main/resources/templates/fragments/intern.html @@ -47,6 +47,8 @@ +
  • Cronjobs
  • + diff --git a/prototype/src/main/resources/templates/intern/cronjobs/index.html b/prototype/src/main/resources/templates/intern/cronjobs/index.html new file mode 100644 index 0000000..ef7e681 --- /dev/null +++ b/prototype/src/main/resources/templates/intern/cronjobs/index.html @@ -0,0 +1,60 @@ + + + + + + + + Cronjobs + + + + + + + + +
    + +
    +

    Manuelle Ausführung von Cronjobs

    +
    + WARNUNG
    + Manuelles Triggern von Cronjobs kann zu unerwartetem Verhalten führen!
    + Diese Seite ist nur für Debugging-Zwecke gedacht. +
    + +

    + + + + + + + + + + + + +
    + +
    Cronjob
    +
    + +
    +
    +

    + +
    +
    +
    + + + diff --git a/prototype/src/main/resources/templates/intern/customers/id.html b/prototype/src/main/resources/templates/intern/customers/id.html index 30962fc..57263dc 100644 --- a/prototype/src/main/resources/templates/intern/customers/id.html +++ b/prototype/src/main/resources/templates/intern/customers/id.html @@ -23,7 +23,7 @@