From d183c6bef9faac329da82c11117853350e724e61 Mon Sep 17 00:00:00 2001 From: Gautam Govind Date: Wed, 12 Mar 2025 05:45:57 +0530 Subject: [PATCH 1/2] Revert "refctored blogpostcontroller and blogpostservice" This reverts commit 9f0311e1c62b5659efa0402ecd6bb4d14cb869fa. --- pom.xml | 10 ++ .../config/SecurityConfig.java | 1 + .../controller/BlogPostController.java | 110 ++++++++------ .../controller/UserController.java | 7 +- .../service/BlogPostService.java | 71 ++++++--- src/main/resources/application.properties | 2 +- .../resources/templates/categoryResults.html | 116 +++++--------- src/main/resources/templates/dashboard.html | 40 ----- src/main/resources/templates/header.html | 10 +- src/main/resources/templates/manage.html | 111 ++++++++++++-- .../resources/templates/searchResults.html | 10 +- .../resources/templates/user-details.html | 142 ++++++++++++++++-- 12 files changed, 411 insertions(+), 219 deletions(-) delete mode 100644 src/main/resources/templates/dashboard.html diff --git a/pom.xml b/pom.xml index dd7f620..2fc0a69 100644 --- a/pom.xml +++ b/pom.xml @@ -71,6 +71,16 @@ spring-security-test test + + org.springframework.boot + spring-boot-starter + + + org.springframework.boot + spring-boot-devtools + runtime + true + diff --git a/src/main/java/com/example/LoginPlusSecurity/config/SecurityConfig.java b/src/main/java/com/example/LoginPlusSecurity/config/SecurityConfig.java index 2e98765..263417f 100644 --- a/src/main/java/com/example/LoginPlusSecurity/config/SecurityConfig.java +++ b/src/main/java/com/example/LoginPlusSecurity/config/SecurityConfig.java @@ -28,6 +28,7 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti .logout(logout -> logout .logoutUrl("/logout") .logoutSuccessUrl("/login?logout") + .deleteCookies("JSESSIONID") .permitAll() ); return http.build(); diff --git a/src/main/java/com/example/LoginPlusSecurity/controller/BlogPostController.java b/src/main/java/com/example/LoginPlusSecurity/controller/BlogPostController.java index 27893fc..e52cac5 100644 --- a/src/main/java/com/example/LoginPlusSecurity/controller/BlogPostController.java +++ b/src/main/java/com/example/LoginPlusSecurity/controller/BlogPostController.java @@ -3,6 +3,7 @@ import java.security.Principal; import org.springframework.data.domain.Page; +import org.springframework.http.HttpStatus; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; @@ -10,6 +11,7 @@ import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.server.ResponseStatusException; import com.example.LoginPlusSecurity.model.BlogPost; import com.example.LoginPlusSecurity.repository.BlogPostRepository; @@ -25,16 +27,15 @@ public class BlogPostController { private final BlogPostRepository blogPostRepository; private final CommentRepository commentRepository; - public BlogPostController(BlogPostService blogPostService, - CategoryRepository categoryRepository, - BlogPostRepository blogPostRepository, - CommentRepository commentRepository) { + + public BlogPostController(BlogPostService blogPostService, CategoryRepository categoryRepository, BlogPostRepository blogPostRepository, CommentRepository commentRepository) { this.blogPostService = blogPostService; this.categoryRepository = categoryRepository; this.blogPostRepository = blogPostRepository; this.commentRepository = commentRepository; } + @GetMapping("/admin/manage") public String home() { return "manage"; @@ -42,55 +43,83 @@ public String home() { @GetMapping("/") public String showHomePage(@RequestParam(defaultValue = "latest") String filter, - @RequestParam(defaultValue = "0") int page, - Model model) { - return paginateAndRenderHomePage(blogPostService.homepageSorting(page, 5, filter), filter, page, model, "home"); - } - - @GetMapping("/search") - public String searchBlogPosts(@RequestParam String query, - @RequestParam(defaultValue = "latest") String filter, @RequestParam(defaultValue = "0") int page, Model model) { - Page blogPosts = blogPostService.titleSorting(query, page, 5, filter); // Reuse service method + + int size = 5; + Page blogPosts = blogPostService.homepageSorting(page, size, filter); model.addAttribute("blogPosts", blogPosts.getContent()); + model.addAttribute("categories", categoryRepository.findAll()); model.addAttribute("currentPage", page); model.addAttribute("totalPages", blogPosts.getTotalPages()); - model.addAttribute("query", query); // Ensure query is passed to the template - model.addAttribute("filter", filter); // Ensure filter is passed for UI consistency - return "searchResults"; // Consistent with other endpoints + model.addAttribute("filter", filter); + return "home"; } - + + @GetMapping("/search") + public String searchBlogPosts(@RequestParam("query") String query, + @RequestParam(defaultValue = "latest") String filter, + @RequestParam(defaultValue = "0") int page, + Model model) { + int size = 5; // Fixed size + Page blogPosts = blogPostService.titleSorting(query, page, size, filter); + model.addAttribute("blogPosts", blogPosts.getContent()); + model.addAttribute("currentPage", page); + model.addAttribute("totalPages", blogPosts.getTotalPages()); + model.addAttribute("query", query); + model.addAttribute("filter", filter); + return "searchResults"; + } + @GetMapping("/category/{id}") public String getBlogPostsByCategory(@PathVariable("id") Long categoryId, - @RequestParam(defaultValue = "latest") String filter, - @RequestParam(defaultValue = "0") int page, - Model model) { - Page blogPosts = blogPostService.categorySorting(categoryId, page, 5, filter); - String categoryName = categoryRepository.getCategoryNameById(categoryId); - model.addAttribute("categoryName", categoryName); + @RequestParam(defaultValue = "latest") String filter, + @RequestParam(defaultValue = "0") int page, + Model model) { + int size = 5; // Fixed size + Page blogPosts = blogPostService.categorySorting(categoryId, page, size, filter); + String categoryName = categoryRepository.getCategoryNameById(categoryId); // Fetch category name + model.addAttribute("blogPosts", blogPosts.getContent()); + model.addAttribute("currentPage", page); + model.addAttribute("totalPages", blogPosts.getTotalPages()); model.addAttribute("filterCategoryId", categoryId); - return paginateAndRenderHomePage(blogPosts, filter, page, model, "categoryResults"); + model.addAttribute("categoryName", categoryName); // Add category name to the model + model.addAttribute("filter", filter); + return "categoryResults"; } + + @GetMapping("/page/{pageNumber}") public String showPaginatedHomePage(@PathVariable int pageNumber, - @RequestParam(defaultValue = "latest") String sortBy, + @ModelAttribute("sortBy") String sortBy, Model model) { - return paginateAndRenderHomePage(blogPostService.homepageSorting(pageNumber, 5, sortBy), sortBy, pageNumber, model, "home"); + int size = 5; + Page blogPosts = blogPostService.homepageSorting(pageNumber, size, sortBy); + model.addAttribute("blogPosts", blogPosts.getContent()); + model.addAttribute("currentPage", pageNumber); + model.addAttribute("totalPages", blogPosts.getTotalPages()); + model.addAttribute("sortBy", sortBy); + return "home"; } + @GetMapping("/blog/{slug}") public String viewBlogPost(@PathVariable String slug, Model model) { - BlogPost blogPost = blogPostService.findBySlug(slug); - blogPost.setViews(blogPost.getViews() + 1); - blogPostRepository.save(blogPost); // Update view count - model.addAttribute("blogPost", blogPost); - model.addAttribute("comments", commentRepository.findByBlogPostId(blogPost.getId())); - return "viewBlog"; + try { + BlogPost blogPost = blogPostService.findBySlug(slug); + blogPost.setViews(blogPost.getViews() + 1); + blogPostRepository.save(blogPost); // Save updated view count + model.addAttribute("blogPost", blogPost); + model.addAttribute("comments", commentRepository.findByBlogPostId(blogPost.getId())); + return "viewBlog"; + } catch (RuntimeException e) { + throw new ResponseStatusException(HttpStatus.NOT_FOUND, e.getMessage()); + } } + @GetMapping("/admin/blog/create") public String showCreateBlogForm(Model model) { model.addAttribute("blogPost", new BlogPost()); @@ -98,20 +127,11 @@ public String showCreateBlogForm(Model model) { return "createBlog"; } + @PostMapping("/admin/blog/create") public String createBlogPost(@ModelAttribute BlogPost blogPost, Principal principal) { - blogPost.setAuthorName(principal.getName()); // Set logged-in user's name + blogPost.setAuthorName(principal.getName()); // Fetch the logged-in user's name blogPostService.saveBlogPost(blogPost); - return "redirect:/"; - } - - // Helper method for pagination setup - private String paginateAndRenderHomePage(Page blogPosts, String filter, int page, Model model, String viewName) { - model.addAttribute("blogPosts", blogPosts.getContent()); - model.addAttribute("currentPage", page); - model.addAttribute("totalPages", blogPosts.getTotalPages()); - model.addAttribute("categories", categoryRepository.findAll()); - model.addAttribute("filter", filter); - return viewName; + return "redirect:/"; // } -} +} \ No newline at end of file diff --git a/src/main/java/com/example/LoginPlusSecurity/controller/UserController.java b/src/main/java/com/example/LoginPlusSecurity/controller/UserController.java index d02478f..c7769dd 100644 --- a/src/main/java/com/example/LoginPlusSecurity/controller/UserController.java +++ b/src/main/java/com/example/LoginPlusSecurity/controller/UserController.java @@ -25,9 +25,14 @@ public String getUserDetails(@PathVariable String username, Model model) { if (user.isPresent()) { model.addAttribute("user", user.get()); return "user-details"; - } else { + } + else { model.addAttribute("error", "User not found"); return "error"; } } +// @GetMapping("") +// public String userProfile() { +// +// } } diff --git a/src/main/java/com/example/LoginPlusSecurity/service/BlogPostService.java b/src/main/java/com/example/LoginPlusSecurity/service/BlogPostService.java index 9c13f0f..a06c834 100644 --- a/src/main/java/com/example/LoginPlusSecurity/service/BlogPostService.java +++ b/src/main/java/com/example/LoginPlusSecurity/service/BlogPostService.java @@ -18,49 +18,78 @@ public BlogPostService(BlogPostRepository blogPostRepository) { this.blogPostRepository = blogPostRepository; } + public Page homepageSorting(int page, int size, String sortBy) { - Pageable pageable = createPageable(page, size, sortBy); + Sort sort; + switch (sortBy) { + case "oldest": + sort = Sort.by("creationDate").ascending(); + break; + case "views": + sort = Sort.by("views").descending(); + break; + default: // latest + sort = Sort.by("creationDate").descending(); + } + Pageable pageable = PageRequest.of(page, size, sort); return blogPostRepository.findAll(pageable); } public Page titleSorting(String query, int page, int size, String sortBy) { - Pageable pageable = createPageable(page, size, sortBy); + Sort sort; + switch (sortBy) { + case "oldest": + sort = Sort.by("creationDate").ascending(); + break; + case "views": + sort = Sort.by("views").descending(); + break; + default: // latest blog + sort = Sort.by("creationDate").descending(); + } + Pageable pageable = PageRequest.of(page, size, sort); return blogPostRepository.findByTitleContainingIgnoreCase(query, pageable); } public Page categorySorting(Long categoryId, int page, int size, String sortBy) { - Pageable pageable = createPageable(page, size, sortBy); + Sort sort; + switch (sortBy) { + case "oldest": + sort = Sort.by("creationDate").ascending(); + break; + case "views": + sort = Sort.by("views").descending(); + break; + default: // latest blogs + sort = Sort.by("creationDate").descending(); + } + Pageable pageable = PageRequest.of(page, size, sort); return blogPostRepository.findByCategoryId(categoryId, pageable); } + + + public void saveBlogPost(BlogPost blogPost) { - blogPost.setSlug(generateSlug(blogPost.getTitle())); + String slug = generateSlug(blogPost.getTitle()); + blogPost.setSlug(slug); blogPostRepository.save(blogPost); } + public BlogPost findBySlug(String slug) { return blogPostRepository.findBySlug(slug) .orElseThrow(() -> new RuntimeException("Blog post not found!")); } - private String generateSlug(String title) { - return title.toLowerCase() - .replaceAll("[^a-z0-9\\s-]", "") - .trim() - .replaceAll("\\s+", "-") - .replaceAll("^-|-$", ""); - } - private Pageable createPageable(int page, int size, String sortBy) { - Sort sort = getSortOrder(sortBy); - return PageRequest.of(page, size, sort); + private String generateSlug(String title) { + String slug = title.toLowerCase() // Convert to lowercase + .replaceAll("[^a-z0-9\\s-]", "") // Remove invalid characters + .trim() // Remove leading and trailing spaces + .replaceAll("\\s+", "-"); // Replace spaces with "-" + return slug.replaceAll("^-|-$", ""); // Remove leading/trailing "-" } - private Sort getSortOrder(String sortBy) { - return switch (sortBy) { - case "oldest" -> Sort.by("creationDate").ascending(); - case "views" -> Sort.by("views").descending(); - default -> Sort.by("creationDate").descending(); // Default to latest - }; - } + } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 8a5b2e1..135eeb7 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -6,7 +6,7 @@ server.port=9595 # DataSource configuration spring.datasource.url=jdbc:mysql://localhost:3306/loginsecurity spring.datasource.username=root -spring.datasource.password=0000 +spring.datasource.password=Root@2025 spring.main.allow-circular-references=true # JPA and Hibernate configuration diff --git a/src/main/resources/templates/categoryResults.html b/src/main/resources/templates/categoryResults.html index a8ddd9e..79c8472 100644 --- a/src/main/resources/templates/categoryResults.html +++ b/src/main/resources/templates/categoryResults.html @@ -11,26 +11,10 @@ margin: 20px; gap: 20px; } - .sidebar { - width: 20%; - border-right: 1px solid #ddd; - padding: 10px; - } - .category-link { - display: block; - padding: 5px; - color: #333; - text-decoration: none; - transition: color 0.3s ease; - } - .category-link:hover { - color: #4CAF50; /* Change color on hover */ - } - .category-link.active-category { - font-weight: bold; /* Highlight active category */ - } .main-content { - width: 80%; + width: 100%; + margin: auto; + max-width: 800px; } .filter-options { display: flex; @@ -73,70 +57,48 @@ - -
- -
- - - - - -
-

Blogs in

- - -
- Sort By: - Latest - Oldest - Most Viewed -
+
+

Blogs in

- -
-

No blogs available in this category.

-
-

-

Author:

-

- Read More -
-
+ +
+ Sort By: + Latest + Oldest + Most Viewed +
- -
+
+ + - diff --git a/src/main/resources/templates/dashboard.html b/src/main/resources/templates/dashboard.html deleted file mode 100644 index e7c94d2..0000000 --- a/src/main/resources/templates/dashboard.html +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - Dashboard - - -

Welcome to the Dashboard

- - -
-

Hello, User!

-
- - -
-

Admin Panel

-

Only admins can see this content.

-
- - -
-

User Area

-

This section is for regular users.

-
- - -
-

Common Area

-

This is visible to both Admins and Users.

-
- - -
- Logout -
- - diff --git a/src/main/resources/templates/header.html b/src/main/resources/templates/header.html index 37573cf..4b3156d 100644 --- a/src/main/resources/templates/header.html +++ b/src/main/resources/templates/header.html @@ -1,5 +1,6 @@ + + +
@@ -96,9 +99,10 @@
- + + \ No newline at end of file diff --git a/src/main/resources/templates/manage.html b/src/main/resources/templates/manage.html index 636d59b..2db0707 100644 --- a/src/main/resources/templates/manage.html +++ b/src/main/resources/templates/manage.html @@ -2,21 +2,104 @@ Manage Blogs + -

Blog Management

- - - +
+

Blog Management

+
+ +
+ + + +
diff --git a/src/main/resources/templates/searchResults.html b/src/main/resources/templates/searchResults.html index 5d5158d..e4594ac 100644 --- a/src/main/resources/templates/searchResults.html +++ b/src/main/resources/templates/searchResults.html @@ -45,15 +45,9 @@ margin-top: 20px; } .pagination a { - color: #4CAF50; /* Green */ - text-decoration: underline; - transition: color 0.3s ease; - } - - .pagination a:hover { - color: #388E3C; /* Slightly darker green on hover */ + margin: 0 10px; + text-decoration: none; } - diff --git a/src/main/resources/templates/user-details.html b/src/main/resources/templates/user-details.html index 54c7d78..7706ee3 100644 --- a/src/main/resources/templates/user-details.html +++ b/src/main/resources/templates/user-details.html @@ -1,15 +1,139 @@ + - User Details + User Details + + -

User Details

-
-

Name:

-

Email:

-

Role:

-

Description: No description available

-
+
+

+
+ +
+
+ +
+
+

User Details

+

Name:

+

Email:

+

Role:

+
+ +
+

Blogs by

+
    +
  • + +
  • +
+
+ + Manage Blogs + Go Back to Dashboard +
- + + \ No newline at end of file From b8247612040a51dbe53351d161dbebcc409cf74e Mon Sep 17 00:00:00 2001 From: Gautam Govind <117900869+Programmer-govind@users.noreply.github.com> Date: Thu, 13 Mar 2025 11:16:06 +0530 Subject: [PATCH 2/2] Update README.md --- README.md | 116 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 115 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 865b6ea..cacdc46 100644 --- a/README.md +++ b/README.md @@ -1 +1,115 @@ -# BlogWithFirebase \ No newline at end of file +## 🌟 Blog Application with Firebase + +A dynamic and user-friendly **Blog Application** built with modern web technologies. This platform enables users to create, manage, and explore engaging blog posts, offering seamless functionality and an elegant design. Currently Blogs can be uploaded by Admins only while Users can view and comment on the blogs. + +--- + +## 🖥️ Features + +- **User-Friendly Interface**: Intuitive and responsive design for all devices. +- **Authentication**: + - Login/Logout functionality. + - Role-based access (Admin/User). +- **Blog Management**: + - Create, update, and delete blog posts. + - Display blogs with proper formatting and conditional image rendering. +- **Dashboard**: + - Lists all blogs with titles, authors, excerpts, and "Read More" links. + - Automatically handles anonymous users and login prompts. +- **15+ Categories to Upload Blogs** +- **Searching & Sorting Feature (Latest, Oldest, Most Viewed)** +- **User Comments & View Count** +- **Thymeleaf Integration**: + - Dynamic server-side rendering with Thymeleaf. +- **Secure Access**: + - Authorization checks ensure that only authenticated users can access certain pages. + +--- + +## 🛠️ Tech Stack + +- **Frontend**: + - HTML5, CSS3 + - Thymeleaf (for server-side templating) + - Font Awesome (for icons) +- **Backend**: + - Java Spring Boot +- **Database**: + - MySQL +- **Build Tool**: + - Maven +- **Spring Security** + +--- + +## 🚀 Installation and Setup + +1. **Clone the Repository**: + ```bash + git clone https://github.com/Programmer-govind/BlogWithFirebase.git + cd BlogWithFireBase + ``` + +2. **Configure the Database**: + - Create a database in MySQL (e.g., `blog_app`). + - Update the database credentials in `application.properties`: + ```properties + spring.datasource.url=jdbc:mysql://localhost:3306/blog_app + spring.datasource.username=your-username + spring.datasource.password=your-password + ``` + +3. **Run the Application**: + ```bash + mvn spring-boot:run + ``` + +4. **Access the Application**: + Open your browser and navigate to: + ``` + http://localhost:9595 + ``` + +--- + +## 📸 Screenshots + +### Dashboard +![Dashboard Screenshot](https://github.com/user-attachments/assets/b3d6de5a-9807-4cd0-adb4-76a877c283f5) + +### User Profile +![User Profile](https://github.com/user-attachments/assets/208daf01-2a33-43c9-80ea-29ba2de5046b) + + +### Blog Management +![Blog Management Screenshot](https://github.com/user-attachments/assets/71a12767-ad7a-4a90-bc30-c3dfc178da2d) + + +--- + +## 🤝 Contributing + +Contributions are welcome! If you'd like to contribute, please: +1. Fork the repository. +2. Create a feature branch: + ```bash + git checkout -b feature/your-feature + ``` +3. Commit your changes: + ```bash + git commit -m "Add your feature" + ``` +4. Push to your branch: + ```bash + git push origin feature/your-feature + ``` +5. Create a pull request. + +--- + +## ✨ Acknowledgments + +- Thanks to **Spring Boot** for making backend development smooth and efficient. +- Inspired by modern blogging platforms to provide an elegant user experience. + +---