Prechádzať zdrojové kódy

half of 8th labs: REST API; 9th labs: PDF generation, Scheduling, ReCaptcha and sending Email

m_sudra 3 rokov pred
rodič
commit
0d60b12d30
22 zmenil súbory, kde vykonal 405 pridanie a 64 odobranie
  1. 42 0
      wpfat_exercises/pom.xml
  2. 31 0
      wpfat_exercises/src/main/java/pl/sudra/configuration/EmailManagerConfiguration.java
  3. 3 4
      wpfat_exercises/src/main/java/pl/sudra/configuration/SecurityConfiguration.java
  4. 2 0
      wpfat_exercises/src/main/java/pl/sudra/configuration/SpringConfiguration.java
  5. 6 1
      wpfat_exercises/src/main/java/pl/sudra/configuration/SpringInit.java
  6. 14 5
      wpfat_exercises/src/main/java/pl/sudra/controller/AppUserController.java
  7. 37 0
      wpfat_exercises/src/main/java/pl/sudra/controller/AppUserRESTController.java
  8. 29 0
      wpfat_exercises/src/main/java/pl/sudra/controller/PdfController.java
  9. 10 10
      wpfat_exercises/src/main/java/pl/sudra/domain/Address.java
  10. 5 0
      wpfat_exercises/src/main/java/pl/sudra/domain/AppUser.java
  11. 3 0
      wpfat_exercises/src/main/java/pl/sudra/domain/Pesel.java
  12. 3 0
      wpfat_exercises/src/main/java/pl/sudra/repository/AppUserRepository.java
  13. 1 0
      wpfat_exercises/src/main/java/pl/sudra/service/AppUserService.java
  14. 14 0
      wpfat_exercises/src/main/java/pl/sudra/service/AppUserServiceImpl.java
  15. 5 0
      wpfat_exercises/src/main/java/pl/sudra/service/EmailService.java
  16. 23 0
      wpfat_exercises/src/main/java/pl/sudra/service/EmailServiceImpl.java
  17. 12 0
      wpfat_exercises/src/main/java/pl/sudra/service/PdfService.java
  18. 50 0
      wpfat_exercises/src/main/java/pl/sudra/service/PdfServiceImpl.java
  19. 6 0
      wpfat_exercises/src/main/java/pl/sudra/service/ReCaptchaService.java
  20. 52 0
      wpfat_exercises/src/main/java/pl/sudra/service/ReCaptchaServiceImpl.java
  21. 12 1
      wpfat_exercises/src/main/webapp/appUser.jsp
  22. 45 43
      wpfat_exercises/src/main/webapp/login.jsp

+ 42 - 0
wpfat_exercises/pom.xml

@@ -81,6 +81,48 @@
             <artifactId>spring-security-taglibs</artifactId>
             <version>6.0.2</version>
         </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.dataformat</groupId>
+            <artifactId>jackson-dataformat-xml</artifactId>
+            <version>2.14.2</version>
+        </dependency>
+        <dependency>
+            <groupId>org.json</groupId>
+            <artifactId>json</artifactId>
+            <version>20230227</version>
+        </dependency>
+        <dependency>
+            <groupId>com.itextpdf</groupId>
+            <artifactId>itextpdf</artifactId>
+            <version>5.5.13.3</version>
+        </dependency>
+        <!-- for reCaptcha utils -->
+        <dependency>
+            <groupId>jakarta.json</groupId>
+            <artifactId>jakarta.json-api</artifactId>
+            <version>2.1.0</version>
+        </dependency>
+        <dependency>
+            <groupId>org.glassfish</groupId>
+            <artifactId>jakarta.json</artifactId>
+            <version>2.0.1</version>
+        </dependency>
+        <!-- for sending emails -->
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-context-support</artifactId>
+            <version>6.0.7</version>
+        </dependency>
+        <dependency>
+            <groupId>jakarta.mail</groupId>
+            <artifactId>jakarta.mail-api</artifactId>
+            <version>2.1.1</version>
+        </dependency>
+        <dependency>
+            <groupId>com.sun.mail</groupId>
+            <artifactId>jakarta.mail</artifactId>
+            <version>2.0.1</version>
+        </dependency>
     </dependencies>
 
 </project>

+ 31 - 0
wpfat_exercises/src/main/java/pl/sudra/configuration/EmailManagerConfiguration.java

@@ -0,0 +1,31 @@
+package pl.sudra.configuration;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.mail.javamail.JavaMailSender;
+import org.springframework.mail.javamail.JavaMailSenderImpl;
+import java.util.Properties;
+
+@Configuration
+public class EmailManagerConfiguration {
+
+    @Bean
+    public JavaMailSender getJavaMailSender() {
+        JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
+        mailSender.setHost("smtp.gmail.com");
+        mailSender.setPort(587); //SSL config
+
+        mailSender.setUsername("mateusz.sudra.21@gmail.com");
+        mailSender.setPassword("jupjlcrapzgpxwah");
+
+        Properties props = mailSender.getJavaMailProperties();
+        props.put("mail.transport.protocol", "smtp");
+        props.put("mail.smtp.auth", "true");
+        props.put("mail.smtp.starttls.enable", "true");
+        props.put("mail.debug", "true");
+        props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
+
+        return mailSender;
+    }
+}
+

+ 3 - 4
wpfat_exercises/src/main/java/pl/sudra/configuration/SecurityConfiguration.java

@@ -4,7 +4,6 @@ import jakarta.annotation.Resource;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
-import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
 import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
 import org.springframework.security.config.annotation.web.builders.HttpSecurity;
 import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
@@ -12,8 +11,6 @@ import org.springframework.security.core.userdetails.User;
 import org.springframework.security.core.userdetails.UserDetails;
 import org.springframework.security.core.userdetails.UserDetailsService;
 import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
-import org.springframework.security.crypto.factory.PasswordEncoderFactories;
-import org.springframework.security.crypto.password.NoOpPasswordEncoder;
 import org.springframework.security.crypto.password.PasswordEncoder;
 import org.springframework.security.provisioning.InMemoryUserDetailsManager;
 import org.springframework.security.web.SecurityFilterChain;
@@ -22,7 +19,8 @@ import org.springframework.web.filter.CharacterEncodingFilter;
 
 @Configuration
 @EnableWebSecurity
-@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
+//@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
+@EnableMethodSecurity
 public class SecurityConfiguration {
     @Resource(name = "myAppUserDetailsService")
     private UserDetailsService userDetailsService;
@@ -78,6 +76,7 @@ public class SecurityConfiguration {
                         .requestMatchers("/exampleTwo").hasAnyAuthority("ROLE_STUDENT", "ROLE_ADMIN")
                         .requestMatchers("/exampleThree").hasRole("STUDENT")
                         .requestMatchers("/login*").anonymous()
+                        .requestMatchers("/appUserRest/*").anonymous()
                         .anyRequest().authenticated()
                 )
 //                .formLogin(form -> form

+ 2 - 0
wpfat_exercises/src/main/java/pl/sudra/configuration/SpringConfiguration.java

@@ -7,6 +7,7 @@ import org.springframework.context.annotation.ComponentScan;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.context.support.ReloadableResourceBundleMessageSource;
 import org.springframework.format.FormatterRegistry;
+import org.springframework.scheduling.annotation.EnableScheduling;
 import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
 import org.springframework.web.servlet.LocaleResolver;
 import org.springframework.web.servlet.config.annotation.EnableWebMvc;
@@ -28,6 +29,7 @@ import java.util.Locale;
 
 @Configuration
 @EnableWebMvc
+@EnableScheduling
 @ComponentScan("pl.sudra")
 //@Import({SecurityConfiguration.class})
 public class SpringConfiguration implements WebMvcConfigurer {

+ 6 - 1
wpfat_exercises/src/main/java/pl/sudra/configuration/SpringInit.java

@@ -10,7 +10,12 @@ import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatche
 public class SpringInit extends AbstractAnnotationConfigDispatcherServletInitializer {
 
     protected Class<?>[] getRootConfigClasses() {
-        return new Class[]{SecurityConfiguration.class, SpringConfiguration.class, HibernatePersistenceConfiguration.class};
+        return new Class[]{
+                SecurityConfiguration.class,
+                SpringConfiguration.class,
+                HibernatePersistenceConfiguration.class,
+                EmailManagerConfiguration.class
+        };
     }
 
     protected Class<?>[] getServletConfigClasses() {

+ 14 - 5
wpfat_exercises/src/main/java/pl/sudra/controller/AppUserController.java

@@ -12,9 +12,7 @@ import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestMethod;
 import pl.sudra.domain.AppUser;
-import pl.sudra.service.AppUserRoleService;
-import pl.sudra.service.AppUserService;
-import pl.sudra.service.AddressService;
+import pl.sudra.service.*;
 import pl.sudra.validator.AppUserValidator;
 
 @Controller
@@ -27,12 +25,21 @@ public class AppUserController {
     private AppUserRoleService appUserRoleService;
     @Autowired
     private AddressService addressService;
+    @Autowired
+    private EmailService emailService;
 
     @Autowired
     public AppUserController(AppUserService appUserService) {
         this.appUserService = appUserService;
     }
 
+    ReCaptchaService reCaptchaService;
+
+    @Autowired
+    public void setReCaptchaService(ReCaptchaService reCaptchaService) {
+        this.reCaptchaService = reCaptchaService;
+    }
+
     @RequestMapping(value = "/appUsers")
     public String showAppUsers(Model model, HttpServletRequest request) {
         int appUserId = ServletRequestUtils.getIntParameter(request, "appUserId", -1);
@@ -54,19 +61,21 @@ public class AppUserController {
     }
 
     @RequestMapping(value = "/addAppUser", method = RequestMethod.POST)
-    public String addAppUser(@Valid @ModelAttribute("appUser") AppUser appUser, BindingResult result, Model model) {
+    public String addAppUser(@Valid @ModelAttribute("appUser") AppUser appUser, BindingResult result, Model model, HttpServletRequest request) {
 
         System.out.println("First Name: " + appUser.getFirstName() +
                 " Last Name: " + appUser.getLastName() + " Tel.: " +
                 appUser.getTelephone() + " Email: " + appUser.getEmail());
 
         appUserValidator.validate(appUser, result);
-        if (result.getErrorCount() == 0) {
+
+        if (result.getErrorCount() == 0 && reCaptchaService.verify(request.getParameter("g-recaptcha-response"))) {
             if (appUser.getId() == 0)
                 appUserService.addAppUser(appUser);
             else
                 appUserService.editAppUser(appUser);
 
+            emailService.sendMail(appUser.getEmail(),"Hello in the app!", "Account created - confirmation email");
             return "redirect:appUsers";
         }
 

+ 37 - 0
wpfat_exercises/src/main/java/pl/sudra/controller/AppUserRESTController.java

@@ -0,0 +1,37 @@
+package pl.sudra.controller;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+import pl.sudra.domain.AppUser;
+import pl.sudra.repository.AppUserRepository;
+
+import java.util.List;
+
+@RestController
+@RequestMapping("appUserRest")
+public class AppUserRESTController {
+    private AppUserRepository appUserRepository;
+
+    @Autowired
+    public AppUserRESTController(AppUserRepository appUserRepository) {
+        this.appUserRepository = appUserRepository;
+    }
+
+    @GetMapping(value = "/{login}", produces = MediaType.APPLICATION_JSON_VALUE)
+    public AppUser getAppUserInJSON(@PathVariable String login) {
+        return appUserRepository.findByLogin(login);
+    }
+
+    @GetMapping(value = "/{login}.xml", produces = MediaType.APPLICATION_XML_VALUE)
+    public AppUser getAppUserInXML(@PathVariable String login) {
+        return appUserRepository.findByLogin(login);
+    }
+
+    @GetMapping
+    public ResponseEntity<List<AppUser>> getAll() {
+        return new ResponseEntity<>(appUserRepository.findAll(), HttpStatus.OK);
+    }
+}

+ 29 - 0
wpfat_exercises/src/main/java/pl/sudra/controller/PdfController.java

@@ -0,0 +1,29 @@
+package pl.sudra.controller;
+
+import jakarta.servlet.http.HttpServletResponse;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import pl.sudra.service.AppUserService;
+import pl.sudra.service.PdfService;
+
+@Controller
+public class PdfController {
+
+    private PdfService pdfService;
+    private AppUserService appUserService;
+
+    @Autowired
+    public PdfController(PdfService pdfService, AppUserService appUserService) {
+        this.pdfService = pdfService;
+        this.appUserService = appUserService;
+    }
+
+    @RequestMapping(value = "/generatePdf-{appUserId}", method = RequestMethod.GET)
+    public void generatePdf(@PathVariable Integer appUserId, HttpServletResponse response) {
+        pdfService.generatePdf(appUserService.getAppUser(appUserId), response);
+    }
+}
+

+ 10 - 10
wpfat_exercises/src/main/java/pl/sudra/domain/Address.java

@@ -16,9 +16,9 @@ public class Address {
     private String number;
     private String postalCode;
 
-    @OneToMany(mappedBy = "address")
-//    @JoinTable(name = "appuser_address", joinColumns = @JoinColumn(name = "appuser_id"), inverseJoinColumns = @JoinColumn(name = "address_id"))
-    private List<AppUser> appUserList;
+//    @OneToMany(mappedBy = "address")
+////    @JoinTable(name = "appuser_address", joinColumns = @JoinColumn(name = "appuser_id"), inverseJoinColumns = @JoinColumn(name = "address_id"))
+//    private List<AppUser> appUserList;
 
     public long getId() {
         return id;
@@ -60,11 +60,11 @@ public class Address {
         this.postalCode = postalCode;
     }
 
-    public List<AppUser> getAppUserList() {
-        return appUserList;
-    }
-
-    public void setAppUserList(List<AppUser> appUserList) {
-        this.appUserList = appUserList;
-    }
+//    public List<AppUser> getAppUserList() {
+//        return appUserList;
+//    }
+//
+//    public void setAppUserList(List<AppUser> appUserList) {
+//        this.appUserList = appUserList;
+//    }
 }

+ 5 - 0
wpfat_exercises/src/main/java/pl/sudra/domain/AppUser.java

@@ -1,5 +1,7 @@
 package pl.sudra.domain;
 
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonManagedReference;
 import jakarta.persistence.*;
 import jakarta.validation.constraints.NotNull;
 import jakarta.validation.constraints.Size;
@@ -34,6 +36,7 @@ public class AppUser {
     @Column(unique = true)
     private String login;
 
+    @JsonIgnore
     @NotNull
     private String password;
 
@@ -42,9 +45,11 @@ public class AppUser {
     @ManyToMany(fetch = FetchType.EAGER)
     private Set<AppUserRole> appUserRole = new HashSet<AppUserRole>(0);
 
+    @JsonManagedReference
     @OneToOne(cascade = CascadeType.ALL)
     private Pesel pesel;
 
+    @JsonManagedReference
     @ManyToOne
     private Address address;
 

+ 3 - 0
wpfat_exercises/src/main/java/pl/sudra/domain/Pesel.java

@@ -1,5 +1,7 @@
 package pl.sudra.domain;
 
+import com.fasterxml.jackson.annotation.JsonBackReference;
+import com.fasterxml.jackson.annotation.JsonIgnore;
 import jakarta.persistence.*;
 
 @Entity
@@ -10,6 +12,7 @@ public class Pesel {
 
     String PESEL;
 
+    @JsonBackReference
     @OneToOne(mappedBy="pesel")
     private AppUser appUser;
 

+ 3 - 0
wpfat_exercises/src/main/java/pl/sudra/repository/AppUserRepository.java

@@ -14,7 +14,10 @@ public interface AppUserRepository extends JpaRepository<AppUser, Long> {
     List<AppUser> findByLastName(String lastName);
 
     AppUser findById(long id);
+
     AppUser findByLogin(String Login);
 
+    List<AppUser> findAllByEnabledIsFalse();
+
 }
 

+ 1 - 0
wpfat_exercises/src/main/java/pl/sudra/service/AppUserService.java

@@ -22,4 +22,5 @@ public interface AppUserService {
 
     AppUser findByLogin(String login);
 
+    void activateInactiveAppUsers();
 }

+ 14 - 0
wpfat_exercises/src/main/java/pl/sudra/service/AppUserServiceImpl.java

@@ -1,6 +1,7 @@
 package pl.sudra.service;
 
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.security.crypto.password.PasswordEncoder;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
@@ -59,6 +60,19 @@ public class AppUserServiceImpl implements AppUserService {
     public AppUser findByLogin(String login) {
         return appUserRepository.findByLogin(login);
     }
+
+//    @Scheduled(fixedRate = 20 * 1000)
+    @Scheduled(cron = "0 * * * * ?")
+    public void activateInactiveAppUsers() {
+        String processName = "activating_inactive_users";
+        System.out.println("activating_inactive_users: ");
+        List<AppUser> appUsers = appUserRepository.findAllByEnabledIsFalse();
+        appUsers.forEach(appUser -> {
+            appUser.setEnabled(true);
+            appUserRepository.saveAndFlush(appUser);
+            System.out.println(appUser.getLogin());
+        });
+    }
 }
 
 

+ 5 - 0
wpfat_exercises/src/main/java/pl/sudra/service/EmailService.java

@@ -0,0 +1,5 @@
+package pl.sudra.service;
+
+public interface EmailService {
+    void sendMail(String receiver, String content, String subject);
+}

+ 23 - 0
wpfat_exercises/src/main/java/pl/sudra/service/EmailServiceImpl.java

@@ -0,0 +1,23 @@
+package pl.sudra.service;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.mail.MailException;
+import org.springframework.mail.SimpleMailMessage;
+import org.springframework.mail.javamail.JavaMailSender;
+import org.springframework.stereotype.Service;
+
+@Service
+public class EmailServiceImpl implements EmailService {
+
+    @Autowired
+    private JavaMailSender javaMailSender;
+
+    public void sendMail(String receiver, String content, String subject) throws MailException{
+        SimpleMailMessage mail = new SimpleMailMessage();
+        mail.setFrom("EmailAuthor-SpringApplication");
+        mail.setTo(receiver);
+        mail.setSubject(subject);
+        mail.setText(content);
+        javaMailSender.send(mail);
+    }
+}

+ 12 - 0
wpfat_exercises/src/main/java/pl/sudra/service/PdfService.java

@@ -0,0 +1,12 @@
+package pl.sudra.service;
+
+import jakarta.servlet.http.HttpServletResponse;
+import pl.sudra.domain.AppUser;
+
+public interface PdfService {
+    public void generatePdf(AppUser appUser, HttpServletResponse response);
+}
+
+
+
+

+ 50 - 0
wpfat_exercises/src/main/java/pl/sudra/service/PdfServiceImpl.java

@@ -0,0 +1,50 @@
+package pl.sudra.service;
+
+import com.itextpdf.text.Chunk;
+import com.itextpdf.text.Document;
+import com.itextpdf.text.DocumentException;
+import com.itextpdf.text.Paragraph;
+import com.itextpdf.text.pdf.PdfPTable;
+import com.itextpdf.text.pdf.PdfWriter;
+import jakarta.servlet.http.HttpServletResponse;
+import org.springframework.stereotype.Service;
+import pl.sudra.domain.AppUser;
+import java.io.IOException;
+import java.io.OutputStream;
+
+@Service
+public class PdfServiceImpl implements PdfService {
+
+    public void generatePdf(AppUser appUser, HttpServletResponse response) {
+        try {
+            OutputStream o = response.getOutputStream();
+            response.setCharacterEncoding("UTF-8");
+            response.setContentType("application/pdf");
+            response.setHeader("Content-Disposition", "inline; filename=" + appUser.getLogin() + ".pdf");
+            Document pdf = new Document();
+            PdfWriter.getInstance(pdf, o);
+            pdf.open();
+            pdf.add(new Paragraph("Pdf example - Spring Framework & iText library"));
+            pdf.add(new Paragraph(Chunk.NEWLINE));
+            PdfPTable table = new PdfPTable(2);
+            table.addCell("FirsName");
+            table.addCell(appUser.getFirstName());
+            table.addCell("LastName");
+            table.addCell(appUser.getLastName());
+            table.addCell("PESEL");
+            table.addCell(appUser.getPesel().getPESEL());
+            table.addCell("Login");
+            table.addCell(appUser.getLogin());
+            table.addCell("Email");
+            table.addCell(appUser.getEmail());
+            table.addCell("Active");
+            table.addCell(String.valueOf(appUser.isEnabled()));
+            pdf.add(table);
+            pdf.close();
+            o.close();
+        }catch (IOException | DocumentException e) {
+            e.printStackTrace();
+        }
+    }
+}
+

+ 6 - 0
wpfat_exercises/src/main/java/pl/sudra/service/ReCaptchaService.java

@@ -0,0 +1,6 @@
+package pl.sudra.service;
+
+public interface ReCaptchaService {
+    boolean verify(String captcha);
+}
+

+ 52 - 0
wpfat_exercises/src/main/java/pl/sudra/service/ReCaptchaServiceImpl.java

@@ -0,0 +1,52 @@
+package pl.sudra.service;
+
+import jakarta.json.Json;
+import jakarta.json.JsonObject;
+import jakarta.json.JsonReader;
+import org.springframework.stereotype.Service;
+
+import javax.net.ssl.HttpsURLConnection;
+import java.io.BufferedReader;
+import java.io.DataOutputStream;
+import java.io.InputStreamReader;
+import java.io.StringReader;
+import java.net.URL;
+
+@Service
+public class ReCaptchaServiceImpl implements ReCaptchaService {
+    private static final String URL = "https://www.google.com/recaptcha/api/siteverify";
+    private static final String GOOGLE_KEY = "6LcqrYQlAAAAAAdyX-4dWY-jGPPomTtWRd6pIpk6";
+
+    @Override
+    public boolean verify(String captcha) {
+        if (captcha == null || "".equals(captcha)) return false;
+        try {
+            URL obj = new URL(URL);
+            HttpsURLConnection con = (HttpsURLConnection) obj.openConnection();
+            con.setRequestMethod("POST");
+            String postParams = "secret=" + GOOGLE_KEY + "&response=" + captcha;
+            // Send post request
+            con.setDoOutput(true);
+            DataOutputStream wr = new DataOutputStream(con.getOutputStream());
+            wr.writeBytes(postParams);
+            wr.flush();
+            wr.close();
+            BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
+            String inputLine;
+            StringBuilder response = new StringBuilder();
+            while ((inputLine = in.readLine()) != null) {
+                response.append(inputLine);
+            }
+            in.close();
+            //parse JSON response and return 'success' value
+            JsonReader jsonReader = Json.createReader(new StringReader(response.toString()));
+            JsonObject jsonObject = jsonReader.readObject();
+            jsonReader.close();
+            return jsonObject.getBoolean("success");
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+}
+

+ 12 - 1
wpfat_exercises/src/main/webapp/appUser.jsp

@@ -4,7 +4,11 @@
 <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
 
 <html>
-<head><title><spring:message code="label.addAppUser"/></title></head>
+<head>
+    <title><spring:message code="label.addAppUser"/></title>
+    <!-- Captcha Google -->
+    <script src="https://www.google.com/recaptcha/api.js"></script>
+</head>
 <body>
 
 <div class="header">
@@ -77,6 +81,11 @@
             <td><form:input path="telephone"/></td>
             <td><form:errors path="telephone"/></td>
         </tr>
+        <tr>
+            <td colspan="3">
+                <div class="g-recaptcha" data-sitekey="6LcqrYQlAAAAAHEGNg4O9yPxxwgBTFYqAndYs6Js"></div>
+            </td>
+        </tr>
         <tr>
             <td colspan="2">
                 <c:if test="${appUser.id==0}">
@@ -101,6 +110,7 @@
             <th><spring:message code="label.telephone"/></th>
             <th>&nbsp;</th>
             <th>&nbsp;</th>
+            <th> </th>
         </tr>
         <c:forEach items="${appUserList}" var="appUser">
             <tr>
@@ -110,6 +120,7 @@
                 <td>${appUser.telephone}</td>
                 <td><a href="delete/${appUser.id}">delete</a></td>
                 <td><a href="appUsers?appUserId=${appUser.id}">edit</a></td>
+                <td><a href="generatePdf-${appUser.id}">pdf</a></td>
             </tr>
         </c:forEach>
     </table>

+ 45 - 43
wpfat_exercises/src/main/webapp/login.jsp

@@ -1,9 +1,16 @@
-<%@page contentType="text/html;charset=UTF-8" language="java" %>
-<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
+<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
 
 <html>
 <head>
     <title>Login Page</title>
+    <link href="<c:url value="/resources/loginPage.css" />" type="text/css" rel="stylesheet" >
+
+<%--    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-aFq/bzH65dt+w6FI2ooMVUpc+21e0SRygnTpmBvdBgSdnuTN7QbdgL+OapgHtvPp" crossorigin="anonymous">--%>
+    <%--    <link href="${pageContext.request.contextPath}/resources/bootstrap-5.3.0-alpha3-dist/css/bootstrap.min.css"--%>
+    <%--          rel="stylesheet" crossorigin="anonymous"/>--%>
+    <%--    <script href="/resources/bootstrap-5.3.0-alpha3-dist/js/bootstrap.bundle.min.js" crossorigin="anonymous"></script>--%>
     <style>
         .error {
             padding: 15px;
@@ -25,52 +32,47 @@
             vorder-color: #bce8f1;
         }
 
-        #login-box {
-            width: 300px;
-            padding: 20px;
-            margin: 10px auto;
-            background: #fff;
-            -webkit-border-radius: 2px;
-            -moz-border-radius: 2px;
-            border: 1px solid #000;
-        }
+        /*.login-box {*/
+        /*    width: 300px;*/
+        /*    padding: 20px;*/
+        /*    margin: 10px auto;*/
+        /*    background: #fff;*/
+        /*    -webkit-border-radius: 2px;*/
+        /*    -moz-border-radius: 2px;*/
+        /*    border: 1px solid #000;*/
+        /*}*/
     </style>
 </head>
-<body onload='document.loginForm.username.focus();'>
+<body onload='document.loginForm.login.focus();'>
 <h3>Spring Security Custom Login Page</h3>
-<div id="login-box">
-    <h3>Login with Username and Password</h3>
-
-    <c:if test="${not empty error}">
-        <div class="error">${error}</div>
-    </c:if>
-    <c:if test="${not empty msg}">
-        <div class="msg">${msg}</div>
-    </c:if>
 
-    <form name='loginForm' action="<c:url value='/login'/>" method='POST'>
-        <table>
-            <tr>
-                <td>AppUser:</td>
-                <td>
-                    <input type='text' name="login" value="">
-                </td>
-            </tr>
-            <tr>
-                <td>Password:</td>
-                <td>
-                    <input type='password' name="password">
-                </td>
-            </tr>
-            <tr>
-                <td colspan="2">
-                    <input name="submit" type="submit" value="submit"/>
-                <td/>
-            </tr>
-        </table>
+<div class="container">
+    <div class="row">
+        <%--        <div class="col-md-offset-5 col-md-3">--%>
+        <div class="login-box">
+            <h3 class="h3h3">Login with Username and Password</h3>
 
-        <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
-    </form>
+            <c:if test="${not empty error}">
+                <div class="error">${error}</div>
+            </c:if>
+            <c:if test="${not empty msg}">
+                <div class="msg">${msg}</div>
+            </c:if>
+            <form class="form-signin" name='loginForm' action="<c:url value='/login' />" method='POST'>
+                <input type="text" name='login' id="inputEmail" class="form-control" placeholder="Login" required
+                       autofocus/>
+                <input type="password" name='password' id="inputPassword" class="form-control" placeholder="Password"
+                       required/>
+                <div id="remember" class="checkbox">
+                    <label>
+                        <input type="checkbox" value="remember-me"> Remember me
+                    </label>
+                </div>
+                <button name="submit" class="btn btn-success" type="submit">Sign in</button>
+                <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
+            </form>
+        </div>
+    </div>
 </div>
 </body>
 </html>