diff --git a/Dockerfile b/Dockerfile index 9772fc0..fa7f4e0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,7 +7,7 @@ # # Then, build the image with: # -# docker build -f src/main/docker/Dockerfile.jvm -t quarkus/paypoint-backend-jvm . +# docker build -f src/main/docker/Dockerfile.jvm -t veenm/paypoint-backend-jvm . # # Then run the container using: # diff --git a/pom.xml b/pom.xml index b7e8470..ece7cfa 100644 --- a/pom.xml +++ b/pom.xml @@ -89,10 +89,17 @@ bcrypt 0.9.0 - + + + src/main/resources + + **/* + + + ${quarkus.platform.group-id} diff --git a/src/main/java/nl/veenm/paypoint/domain/AppUser.java b/src/main/java/nl/veenm/paypoint/domain/AppUser.java index 131542c..c9060b3 100644 --- a/src/main/java/nl/veenm/paypoint/domain/AppUser.java +++ b/src/main/java/nl/veenm/paypoint/domain/AppUser.java @@ -1,9 +1,6 @@ package nl.veenm.paypoint.domain; -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; +import jakarta.persistence.*; @Entity public class AppUser { @@ -17,6 +14,9 @@ public class AppUser { private String firstName; private String lastName; + @ManyToOne(cascade = CascadeType.ALL) + private Company company; + public Long getId() { return id; } @@ -73,6 +73,14 @@ public class AppUser { this.lastName = lastName; } + public Company getCompany() { + return company; + } + + public void setCompany(Company company) { + this.company = company; + } + @Override public String toString() { return "AppUser{" + diff --git a/src/main/java/nl/veenm/paypoint/domain/Appointment.java b/src/main/java/nl/veenm/paypoint/domain/Appointment.java index f87c1a3..81ec331 100644 --- a/src/main/java/nl/veenm/paypoint/domain/Appointment.java +++ b/src/main/java/nl/veenm/paypoint/domain/Appointment.java @@ -21,6 +21,9 @@ public class Appointment { @ManyToOne private Customer customer; + @ManyToOne + private Company company; + public Appointment(Long id, String title, String description, LocalDateTime startDate, int startHour, int startMinute, int endHour, int endMinute, int durationInMinutes) { this.id = id; this.title = title; @@ -117,6 +120,14 @@ public class Appointment { this.customer = customer; } + public Company getCompany() { + return company; + } + + public void setCompany(Company company) { + this.company = company; + } + @Override public String toString() { return "Appointment{" + diff --git a/src/main/java/nl/veenm/paypoint/domain/Company.java b/src/main/java/nl/veenm/paypoint/domain/Company.java new file mode 100644 index 0000000..96c40fa --- /dev/null +++ b/src/main/java/nl/veenm/paypoint/domain/Company.java @@ -0,0 +1,75 @@ +package nl.veenm.paypoint.domain; + +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; + +@Entity +public class Company { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + private String name; + private String email; + private String img_href; + private String address; + private String postal_code; + private String city; + + public void setId(Long id) { + this.id = id; + } + + public Long getId() { + return id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getImg_href() { + return img_href; + } + + public void setImg_href(String img_href) { + this.img_href = img_href; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + public String getPostal_code() { + return postal_code; + } + + public void setPostal_code(String postal_code) { + this.postal_code = postal_code; + } + + public String getCity() { + return city; + } + + public void setCity(String city) { + this.city = city; + } +} diff --git a/src/main/java/nl/veenm/paypoint/repository/AppointmentRepository.java b/src/main/java/nl/veenm/paypoint/repository/AppointmentRepository.java index 386f8e1..b101b04 100644 --- a/src/main/java/nl/veenm/paypoint/repository/AppointmentRepository.java +++ b/src/main/java/nl/veenm/paypoint/repository/AppointmentRepository.java @@ -3,8 +3,10 @@ package nl.veenm.paypoint.repository; import io.quarkus.hibernate.orm.panache.PanacheRepository; import jakarta.enterprise.context.ApplicationScoped; import nl.veenm.paypoint.domain.Appointment; +import nl.veenm.paypoint.domain.Company; import java.time.LocalDateTime; +import java.util.List; import java.util.Optional; @ApplicationScoped @@ -17,4 +19,8 @@ public class AppointmentRepository implements PanacheRepository { userId, now) .firstResultOptional(); } + + public List findMostRecentByCompanyId(Company company) { + return find("company = ?1", company).list(); + } } diff --git a/src/main/java/nl/veenm/paypoint/repository/CompanyRepository.java b/src/main/java/nl/veenm/paypoint/repository/CompanyRepository.java new file mode 100644 index 0000000..b05267d --- /dev/null +++ b/src/main/java/nl/veenm/paypoint/repository/CompanyRepository.java @@ -0,0 +1,14 @@ +package nl.veenm.paypoint.repository; + +import io.quarkus.hibernate.orm.panache.PanacheRepository; +import jakarta.enterprise.context.ApplicationScoped; +import nl.veenm.paypoint.domain.Appointment; +import nl.veenm.paypoint.domain.Company; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.Optional; + +@ApplicationScoped +public class CompanyRepository implements PanacheRepository { +} diff --git a/src/main/java/nl/veenm/paypoint/resource/AppointmentResource.java b/src/main/java/nl/veenm/paypoint/resource/AppointmentResource.java index 308b504..56a2971 100644 --- a/src/main/java/nl/veenm/paypoint/resource/AppointmentResource.java +++ b/src/main/java/nl/veenm/paypoint/resource/AppointmentResource.java @@ -1,23 +1,27 @@ package nl.veenm.paypoint.resource; -import jakarta.annotation.security.PermitAll; import jakarta.annotation.security.RolesAllowed; import jakarta.inject.Inject; +import jakarta.json.JsonNumber; import jakarta.ws.rs.*; import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; import nl.veenm.paypoint.domain.Appointment; import nl.veenm.paypoint.service.AppointmentService; +import org.eclipse.microprofile.jwt.JsonWebToken; import java.util.List; -@Path("/api/appointments") +@Path("/appointments") @RolesAllowed({"ADMIN", "USER"}) public class AppointmentResource { @Inject AppointmentService appointmentService; + @Inject + JsonWebToken jwt; + @GET @Produces(MediaType.APPLICATION_JSON) public List getAppointments() { @@ -28,8 +32,11 @@ public class AppointmentResource { @Produces(MediaType.APPLICATION_JSON) @Path("/date") public List getAppointmentsByDate(@QueryParam("start") String start) { - return appointmentService.getAppointmentsByDate(start); + JsonNumber companyIdJson = jwt.getClaim("company_id"); + Long companyId = companyIdJson.longValue(); + return appointmentService.getAppointmentsByDate(start, companyId); } + @GET @Produces(MediaType.APPLICATION_JSON) @Path("/recent/{id}") @@ -47,8 +54,9 @@ public class AppointmentResource { @POST @Consumes(MediaType.APPLICATION_JSON) public Response addAppointment(Appointment appointment) { - System.out.println(appointment); - appointmentService.add(appointment); + JsonNumber companyIdJson = jwt.getClaim("company_id"); + Long companyId = companyIdJson.longValue(); + appointmentService.add(appointment, companyId); return Response.ok().build(); } diff --git a/src/main/java/nl/veenm/paypoint/resource/CustomerResource.java b/src/main/java/nl/veenm/paypoint/resource/CustomerResource.java index 8692686..6a4e9da 100644 --- a/src/main/java/nl/veenm/paypoint/resource/CustomerResource.java +++ b/src/main/java/nl/veenm/paypoint/resource/CustomerResource.java @@ -14,7 +14,7 @@ import nl.veenm.paypoint.service.CustomerService; import java.util.List; -@Path("/api/customers") +@Path("/customers") @PermitAll() public class CustomerResource { @Inject diff --git a/src/main/java/nl/veenm/paypoint/service/AppointmentService.java b/src/main/java/nl/veenm/paypoint/service/AppointmentService.java index 35c5c6e..8dfaf75 100644 --- a/src/main/java/nl/veenm/paypoint/service/AppointmentService.java +++ b/src/main/java/nl/veenm/paypoint/service/AppointmentService.java @@ -5,11 +5,12 @@ import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; import jakarta.transaction.Transactional; import nl.veenm.paypoint.domain.Appointment; +import nl.veenm.paypoint.domain.Company; import nl.veenm.paypoint.repository.AppointmentRepository; +import nl.veenm.paypoint.repository.CompanyRepository; import java.time.LocalDate; import java.time.LocalDateTime; -import java.util.ArrayList; import java.util.List; @ApplicationScoped @@ -17,16 +18,14 @@ public class AppointmentService { @Inject AppointmentRepository appointmentRepository; + @Inject + CompanyRepository companyRepository; + @Inject EmailService emailService; - private List appointments; public AppointmentService() { - LocalDateTime now = LocalDateTime.now(); - appointments = new ArrayList<>(); - appointments.add(new Appointment(1L, "Knippen Mel", "", now, 12, 0, 13, 0, 60)); - appointments.add(new Appointment(2L, "Knippen Mel", "", now, 14, 0, 15, 0, 60)); } @Transactional @@ -35,20 +34,22 @@ public class AppointmentService { } @Transactional - public void add(Appointment appointment) { -// appointment.setStartDate(appointment.getStartDate().plusDays(1)); + public void add(Appointment appointment, Long companyId) { + Company company = companyRepository.findById(companyId); + appointment.setCompany(company); appointmentRepository.persist(appointment); emailService.stuurBevestiging(appointment); } @Transactional - public List getAppointmentsByDate(String start) { + public List getAppointmentsByDate(String start, Long companyId) { LocalDate date = LocalDate.parse(start); + Company company = companyRepository.findById(companyId); - LocalDateTime startOfDay = date.atStartOfDay(); // 00:00:00 - LocalDateTime endOfDay = date.atTime(23, 59, 59); // 23:59:59 + LocalDateTime startOfDay = date.atStartOfDay(); + LocalDateTime endOfDay = date.atTime(23, 59, 59); - return appointmentRepository.find("startDate BETWEEN ?1 AND ?2", startOfDay, endOfDay).list(); + return appointmentRepository.find("startDate BETWEEN ?1 AND ?2 AND company = ?3", startOfDay, endOfDay, company).list(); } @Transactional @@ -79,7 +80,7 @@ public class AppointmentService { } @Transactional - @Scheduled(cron = "0 0 0 * * ?") + @Scheduled(cron = "0 0 1 * * ?") public void sendReminder() { LocalDate date = LocalDate.now(); date = date.plusDays(1); @@ -99,4 +100,8 @@ public class AppointmentService { return appointmentRepository.findMostRecentByUserId(userId).orElse(null); } + public List getAppointmentsByCompany(Long companyId) { + Company company = companyRepository.findById(companyId); + return appointmentRepository.findMostRecentByCompanyId(company); + } } diff --git a/src/main/java/nl/veenm/paypoint/service/EmailService.java b/src/main/java/nl/veenm/paypoint/service/EmailService.java index 8191ba5..02a6e2b 100644 --- a/src/main/java/nl/veenm/paypoint/service/EmailService.java +++ b/src/main/java/nl/veenm/paypoint/service/EmailService.java @@ -4,6 +4,7 @@ import io.quarkus.mailer.Mail; import io.quarkus.mailer.Mailer; import jakarta.enterprise.context.ApplicationScoped; import nl.veenm.paypoint.domain.Appointment; +import nl.veenm.paypoint.domain.Company; import nl.veenm.paypoint.helper.EmailHelper; import java.time.LocalDateTime; @@ -20,9 +21,9 @@ public class EmailService { } public void stuurBevestiging(Appointment appointment) { - - String location = "
Groenestraat 29
6681DW Bemmel"; - String imageUrl = "https://hairstylingbydaan.nl/assets/img/Logo.png"; + Company company = appointment.getCompany(); + String location = String.format("
%s
%s %s", company.getAddress(), company.getPostal_code(), company.getCity()); + String imageUrl = appointment.getCompany().getImg_href(); String formattedDate = appointment.getStartDate().toLocalDate().format(DateTimeFormatter.ofPattern("dd MMMM yyyy", Locale.forLanguageTag("nl"))); String formattedHour = String.valueOf(appointment.getStartHour()).length() == 1 ? "0" + appointment.getStartHour() : String.valueOf(appointment.getStartHour()); @@ -115,15 +116,15 @@ public class EmailService { mailer.send(Mail.withHtml(recipient, subject, emailBody) .setFrom("Hairstyling By Daan ") + .setReplyTo(company.getEmail()) .addAttachment("afspraak.ics", EmailHelper.getIcs(dtStamp, date.toLocalDate(), formattedTime, formattedEndTime, location).getBytes(), "text/calendar")); } public void stuurVerwijdering(Appointment appointment) { - - String imageUrl = "https://hairstylingbydaan.nl/assets/img/Logo.png"; + Company company = appointment.getCompany(); + String imageUrl = company.getImg_href(); String formattedDate = appointment.getStartDate().toLocalDate().format(DateTimeFormatter.ofPattern("dd MMMM yyyy", Locale.forLanguageTag("nl"))); - // Bouw de HTML-inhoud van de e-mail String emailBody = """ @@ -200,9 +201,9 @@ public class EmailService { } public void stuurBewerking(Appointment appointment) { - - String location = "
Groenestraat 29
6681DW Bemmel"; - String imageUrl = "https://hairstylingbydaan.nl/assets/img/Logo.png"; + Company company = appointment.getCompany(); + String location = String.format("
%s
%s %s", company.getAddress(), company.getPostal_code(), company.getCity()); + String imageUrl = appointment.getCompany().getImg_href(); String formattedDate = appointment.getStartDate().toLocalDate().format(DateTimeFormatter.ofPattern("dd MMMM yyyy", Locale.forLanguageTag("nl"))); String formattedTime = String.format("%s:%s", appointment.getStartHour(), String.valueOf(appointment.getStartMinute()).length() == 1 ? "0" + appointment.getStartMinute() : appointment.getStartMinute()); @@ -284,13 +285,13 @@ public class EmailService { String subject = String.format(" Afspraak gewijzigd: %s", formattedDate); String recipient = appointment.getCustomer().getEmail(); - mailer.send(Mail.withHtml(recipient, subject, emailBody).setFrom("Hairstyling By Daan ")); + mailer.send(Mail.withHtml(recipient, subject, emailBody).setFrom(company.getEmail())); } public void stuurHerinnering(Appointment appointment) { - - String location = "
Groenestraat 29
6681DW Bemmel"; - String imageUrl = "https://hairstylingbydaan.nl/assets/img/Logo.png"; + Company company = appointment.getCompany(); + String location = String.format("
%s
%s %s", company.getAddress(), company.getPostal_code(), company.getCity()); + String imageUrl = appointment.getCompany().getImg_href(); String formattedDate = appointment.getStartDate().toLocalDate().format(DateTimeFormatter.ofPattern("dd MMMM yyyy", Locale.forLanguageTag("nl"))); String formattedTime = String.format("%s:%s", appointment.getStartHour(), String.valueOf(appointment.getStartMinute()).length() == 1 ? "0" + appointment.getStartMinute() : appointment.getStartMinute()); @@ -372,7 +373,7 @@ public class EmailService { String subject = String.format("Herinnering afspraak: %s", formattedDate); String recipient = appointment.getCustomer().getEmail(); - mailer.send(Mail.withHtml(recipient, subject, emailBody).setFrom("Hairstyling By Daan ")); + mailer.send(Mail.withHtml(recipient, subject, emailBody).setFrom("Hairstyling By Daan ").setReplyTo(company.getEmail())); } } diff --git a/src/main/java/nl/veenm/paypoint/service/TokenService.java b/src/main/java/nl/veenm/paypoint/service/TokenService.java index ce91d36..c25f340 100644 --- a/src/main/java/nl/veenm/paypoint/service/TokenService.java +++ b/src/main/java/nl/veenm/paypoint/service/TokenService.java @@ -18,6 +18,7 @@ public class TokenService { .claim("lastName", appUser.getLastName()) .claim("email", appUser.getEmail()) .claim("groups", appUser.getRole()) + .claim("company_id", appUser.getCompany().getId()) .sign(); } } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index e657f40..a6feb01 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -11,6 +11,7 @@ quarkus.hibernate-orm.log.sql=false quarkus.http.cors=true quarkus.http.cors.origins=${CORS_ORIGINS} quarkus.http.cors.methods=GET,POST,OPTIONS,DELETE,PUT +quarkus.http.root-path=/api # Mailer configuratie quarkus.mailer.from=${MAILER_FROM} @@ -19,6 +20,10 @@ quarkus.mailer.port=${MAILER_PORT} quarkus.mailer.username=${MAILER_USERNAME} quarkus.mailer.password=${MAILER_PASSWORD} quarkus.mailer.mock=false +#quarkus.http.port=8081 +#quarkus.http.ssl-port=443 +quarkus.http.ssl.certificate.key-store-file=keystore.jks +quarkus.http.ssl.certificate.key-store-password=password # JWT-instellingen mp.jwt.verify.issuer=PayPoint @@ -32,9 +37,14 @@ smallrye.jwt.sign.key.algorithm=RS256 # Token Levensduur (optioneel) smallrye.jwt.new-token.lifespan=3600 -quarkus.log.category."io.quarkus.security".level=DEBUG -mp.jwt.verify.claims.groups=groups -quarkus.log.category."io.smallrye.jwt".level=DEBUG +#quarkus.log.category."io.quarkus.security".level=DEBUG +#mp.jwt.verify.claims.groups=groups +#quarkus.log.category."io.smallrye.jwt".level=DEBUG +##quarkus.log.level=DEBUG +##quarkus.log.category."io.quarkus".level=DEBUG +#quarkus.log.category."io.quarkus.rest".level=DEBUG + +