Skip to content
Snippets Groups Projects
Commit e40137de authored by Marnuri Nitish -'s avatar Marnuri Nitish -
Browse files

Add authentication and implement manage user functionality

parent 3eb4f9f8
No related branches found
No related tags found
No related merge requests found
Showing
with 306 additions and 94 deletions
package polish_community_group_11.polish_community.admin.controllers;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;
import polish_community_group_11.polish_community.admin.models.AdminBoard;
import polish_community_group_11.polish_community.admin.models.ManageUser;
import polish_community_group_11.polish_community.admin.services.AdminService;
import polish_community_group_11.polish_community.register.models.User;
import polish_community_group_11.polish_community.register.services.UserService;
@RestController
public class AdminApiController {
private final AdminService adminService;
private final UserService userService;
private Authentication authentication;
public AdminApiController(AdminService adminService) {
public AdminApiController(AdminService adminService, UserService userService) {
this.adminService = adminService;
this.userService = userService;
}
@PutMapping("admin/edit/role/{role_name}")
public void changeUserRole(@PathVariable("role_name") String role_name,
@ModelAttribute ManageUser user){
adminService.updateUserRole(user,role_name);
@PutMapping("/admin/edit/{user_id}/role")
public ResponseEntity<Void> changeUserRole(@PathVariable("user_id") int user_id,
@RequestBody String role_name) {
authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication.getAuthorities().stream().anyMatch(
a -> a.getAuthority().equals("ROLE_ADMIN"))) {
if (role_name == null || role_name.trim().isEmpty()) {
return ResponseEntity.badRequest().build();
}
try {
User user = userService.findById(user_id);
if (user == null) {
return ResponseEntity.notFound().build();
}
adminService.updateUserRole(user, role_name);
return ResponseEntity.ok().build();
} catch (Exception e) {
return ResponseEntity.internalServerError().build();
}
} else {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
}
}
@DeleteMapping("admin/delete/{user_id}")
public void removeUser(@PathVariable("user_id") int user_id){
adminService.deleteUser(user_id);
@PutMapping("/admin/edit/{user_id}/enabled")
public ResponseEntity<Void> enableOrDisableUser(
@PathVariable("user_id") int user_id, @RequestParam Boolean enabled) {
authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication.getAuthorities().stream().anyMatch(
a -> a.getAuthority().equals("ROLE_ADMIN"))) {
try {
User user = userService.findById(user_id);
if (user == null) {
return ResponseEntity.notFound().build(); // User not found
}
adminService.enableOrDisableUser(user, enabled);
return ResponseEntity.ok().build();
} catch (IllegalArgumentException e) {
// Invalid boolean or other illegal arguments
return ResponseEntity.badRequest().build();
} catch (Exception e) {
return ResponseEntity.internalServerError().build();
}
} else {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
}
}
@GetMapping("/admin/get/{user_id}")
public ResponseEntity<User> getUser(@PathVariable("user_id") int user_id) {
try {
User user = userService.findById(user_id);
if (user == null) {
return ResponseEntity.notFound().build(); // User not found
}
return ResponseEntity.ok(user);
} catch (Exception e) {
return ResponseEntity.badRequest().build();
}
}
}
package polish_community_group_11.polish_community.admin.controllers;
import org.apache.coyote.BadRequestException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.servlet.ModelAndView;
import polish_community_group_11.polish_community.admin.services.AdminService;
import polish_community_group_11.polish_community.register.services.RoleService;
import java.sql.SQLException;
import java.util.List;
@Controller
public class AdminController {
private AdminService adminService;
public AdminController(AdminService adminService) {
private final AdminService adminService;
private final RoleService roleService;
private Authentication authentication;
public AdminController(AdminService adminService, RoleService roleService) {
this.adminService = adminService;
this.roleService = roleService;
}
@GetMapping("admin/userInfo")
public ModelAndView getFirstAdminUsers() throws SQLException {
public ModelAndView getFirstAdminUsers() throws SQLException, BadRequestException {
ModelAndView mav = new ModelAndView("admin/userManage");
mav.addObject("usersAdminInfo",adminService.getUserManagementInfo());
authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication.getAuthorities().stream().anyMatch(
a -> a.getAuthority().equals("ROLE_ADMIN")))
{
mav.addObject("usersAdminInfo",adminService.getUserManagementInfo());
mav.addObject("roles",roleService.findAllRoles());
}
else{
throw new BadRequestException("User is not admin");
}
return mav;
}
@GetMapping("admin")
public ModelAndView getAdminDashboard() throws SQLException {
public ModelAndView getAdminDashboard() throws SQLException, BadRequestException {
ModelAndView mav = new ModelAndView("admin/adminBoard");
mav.addObject("adminBoard",adminService.getBoardManagementInfo());
authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication.getAuthorities().stream().anyMatch(
a -> a.getAuthority().equals("ROLE_ADMIN"))){
mav.addObject("adminBoard",adminService.getBoardManagementInfo());
}
else{
throw new BadRequestException("User is not admin");
}
return mav;
}
}
......@@ -2,6 +2,7 @@ package polish_community_group_11.polish_community.admin.dao;
import polish_community_group_11.polish_community.admin.models.AdminBoard;
import polish_community_group_11.polish_community.admin.models.ManageUser;
import polish_community_group_11.polish_community.register.models.User;
import java.sql.SQLException;
import java.util.List;
......@@ -9,6 +10,5 @@ import java.util.List;
public interface AdminRepository {
List<ManageUser> getUserManagementInfo() throws SQLException;
AdminBoard getBoardManagementInfo() throws SQLException;
int updateUserRole(ManageUser user);
void deleteUser(int userId);
int updateUserRole(User user);
}
......@@ -8,6 +8,7 @@ import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;
import polish_community_group_11.polish_community.admin.models.AdminBoard;
import polish_community_group_11.polish_community.admin.models.ManageUser;
import polish_community_group_11.polish_community.register.models.User;
import java.sql.SQLException;
import java.time.DateTimeException;
......@@ -48,13 +49,14 @@ public class AdminRepositoryImpl implements AdminRepository {
}
public List<ManageUser> getUserManagementInfo() throws SQLException {
String sql="select u.id, u.fullname, u.email, u.enabled, rol.role_name from users u" +
String sql="select u.id, u.fullname, u.email, u.enabled,u.role_id, rol.role_name from users u" +
" left join user_roles u_rol" +
" on u.id = u_rol.user_id" +
" join roles rol" +
" on u.role_id = rol.id" +
" order by u.id asc" +
" limit 10";
" order by u.id asc";
// +
// " limit 10";
List<ManageUser> users=null;
try{
users=jdbc.query(sql, adminManageUserMapper);
......@@ -95,13 +97,20 @@ public class AdminRepositoryImpl implements AdminRepository {
return dashboard;
}
public int updateUserRole(ManageUser user){
String sql="UPDATE users SET role_id=? WHERE id =?";
return jdbc.update(sql,user.getRole_id(),user.getId());
}
public int updateUserRole(User user){
// Validate input to ensure no null values are passed
if (user == null || user.getId() <= 0 || user.getRoleId() <= 0) {
throw new IllegalArgumentException("Invalid user or role details.");
}
// SQL query for updating the user's role and enabled status
String sql = "UPDATE users SET role_id = ?, enabled = ? WHERE id = ?";
public void deleteUser(int userId){
String sql="DELETE FROM users WHERE id =?";
jdbc.update(sql,userId);
try {
// Perform the update operation
int rowsUpdated = jdbc.update(sql, user.getRoleId(), user.getEnabled(), user.getId());
return rowsUpdated;
} catch (DataAccessException e) {
throw new RuntimeException("Database error occurred while updating user role.", e);
}
}
}
......@@ -2,6 +2,7 @@ package polish_community_group_11.polish_community.admin.services;
import polish_community_group_11.polish_community.admin.models.AdminBoard;
import polish_community_group_11.polish_community.admin.models.ManageUser;
import polish_community_group_11.polish_community.register.models.User;
import java.sql.SQLException;
import java.util.List;
......@@ -9,6 +10,6 @@ import java.util.List;
public interface AdminService {
List<ManageUser> getUserManagementInfo() throws SQLException;
AdminBoard getBoardManagementInfo() throws SQLException;
void updateUserRole(ManageUser user,String roleName);
void deleteUser(int userId);
void updateUserRole(User user, String roleName);
void enableOrDisableUser(User user, Boolean enabled);
}
......@@ -4,6 +4,7 @@ import org.springframework.stereotype.Service;
import polish_community_group_11.polish_community.admin.dao.AdminRepository;
import polish_community_group_11.polish_community.admin.models.AdminBoard;
import polish_community_group_11.polish_community.admin.models.ManageUser;
import polish_community_group_11.polish_community.register.models.User;
import java.sql.SQLException;
import java.util.List;
......@@ -22,17 +23,20 @@ public class AdminServiceImpl implements AdminService {
return adminRepository.getBoardManagementInfo();
}
public void updateUserRole(ManageUser user, String roleName){
boolean needsUpdate=roleName.toLowerCase().equals(user.getRole().toLowerCase())?
false:true;
public void updateUserRole(User user, String roleName){
int newRoleId=roleName.toLowerCase().contains("admin")?1:2;
boolean needsUpdate=user.getRoleId()==newRoleId?false:true;
if(needsUpdate){
int updatedRoleId=roleName.toLowerCase().equals("admin")?1:2;
user.setRole_id(updatedRoleId);
user.setRoleId(newRoleId);
adminRepository.updateUserRole(user);
}
}
public void deleteUser(int userId){
adminRepository.deleteUser(userId);
public void enableOrDisableUser(User user, Boolean enabled){
boolean needsUpdate=(enabled==user.getEnabled())?false:true;
if(needsUpdate){
user.setEnabled(enabled);
adminRepository.updateUserRole(user);
}
}
}
......@@ -55,7 +55,7 @@ public class EventRepositoryImpl implements EventRepository {
// Method to retrieve all events from the database
public List<Event> getAllEvents() {
String sql = "select * from event";
String sql = "select * from event order by event_id desc";
return jdbc.query(sql, eventItemMapper);
}
......
......@@ -117,6 +117,7 @@ public class UserRepositoryImpl implements UserRepository {
user.setDateOfBirth(rs.getObject("dob", LocalDate.class));
user.setRoleId(rs.getInt("role_id"));
user.setOrganization(rs.getString("organization"));
user.setEnabled(rs.getBoolean("enabled"));
return user;
}, id);
} catch (EmptyResultDataAccessException e) {
......
package polish_community_group_11.polish_community.register.models;
import lombok.Getter;
import lombok.Setter;
import java.time.LocalDate;
import java.util.List;
@Getter
@Setter
public class User {
private int id;
private String email;
......@@ -11,7 +16,7 @@ public class User {
private LocalDate dob; // use LocalDate for dob
private int roleId;
private String organization;
private Boolean enabled;
// getters and setters
public int getId() {
......
......@@ -17,24 +17,45 @@
.statistics {
display: flex;
justify-content: center;
gap: 20px;
gap: 1rem;
margin-bottom: 20px;
}
.statistics .stat strong{
font-size: 1.5rem;
}
.statistics .stat aside{
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.statistics .stat {
display: flex;
justify-content: center;
gap:1rem;
align-items: center;
background-color: #f9f9f9;
border: 1px solid #ddd;
border-radius: 8px;
padding: 10px 20px;
padding: 1rem 2rem;
height: 8rem;
width: 15.8rem;
text-align: center;
font-size: 16px;
font-size: 1rem;
color: #333;
}
i{
font-size: 2rem;
}
.dashboard {
display: flex;
flex-wrap: wrap;
gap: 20px;
gap: 1.2rem;
justify-content: center;
}
......@@ -42,8 +63,9 @@
background-color: #fff;
border: 1px solid #ddd;
border-radius: 8px;
padding: 20px;
width: 250px;
padding: 2rem;
width: 21.3rem;
height: 12rem;
text-align: center;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
transition: transform 0.2s;
......
table {
width: 100%;
border-collapse: collapse;
padding: 20px;
}
section{
padding: 2rem;
}
.table-wrap{
border-radius: 10px;
}
th, td {
padding: 10px;
border: 1px solid #ccc;
......@@ -11,14 +19,25 @@ th {
background-color: #f4f4f4;
}
.btn {
padding: 5px 10px;
padding: 10px 20px;
margin: 5px;
cursor: pointer;
border: none;
background-color: #4CAF50;
color: white;
background-color: var(--primary-color);
color: var(--secondary-color);
border-radius: 5px;
}
.btn-disable {
background-color: #f44336;
}
select {
width: 6rem;
padding: 10px;
border: 1px solid #ccc;
border-radius: 5px;
}
option {
padding: 5px 10px;
}
\ No newline at end of file
......@@ -6,7 +6,7 @@
}
button {
padding: 10px 15px;
padding: 1rem 1rem;
border: none;
font-size: 14px;
cursor: pointer;
......@@ -86,6 +86,5 @@ input[type="checkbox" i] {
#delete-button{
visibility: hidden;
float: right;
margin: 5px 0;
/*margin: 5px 0;*/
}
\ No newline at end of file
// Function to enable or disable a user
function toggleUserEnabled(userId, enable) {
//check current status and do the alternate
enable = enable !== true;
const url = `/admin/edit/${userId}/enabled?enabled=${enable}`;
// Use Fetch API to send the PUT request
fetch(url, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
credentials:"include"
})
.then(response => {
if (response.ok) {
// Reload the page to reflect the changes
location.reload();
} else {
alert('Failed to update user status.');
}
})
.catch(error => {
console.error('Error:', error);
alert('Error occurred while updating user status.');
});
}
function updateUserRole(userId){
const roleSelect = document.getElementById('roleDdl');
const selectedValue = roleSelect.value;
const url = `/admin/edit/${userId}/role`;
// Use Fetch API to send the PUT request
fetch(url, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
credentials:"include",
body:JSON.stringify(selectedValue)
})
.then(response => {
if (response.ok) {
// Reload the page to reflect the changes
location.reload();
} else {
alert('Failed to update user role.');
}
})
.catch(error => {
console.error('Error:', error);
alert('Error occurred while updating user role.');
});
}
......@@ -13,22 +13,34 @@
</div>
<div class="statistics">
<div class="stat">Total Users: <span th:text="*{adminBoard.getTotalNoOfUsers()}"></span></div>
<div class="stat">Total Posts: <span th:text="*{adminBoard.getTotalPosts()}"></span></div>
<div class="stat">Upcoming Events: <span th:text="*{adminBoard.getUpcomingEvents()}"></span></div>
<div class="stat">New Comments: <span th:text="*{adminBoard.getNewComments()}"></span></div>
<div class="stat"><i class="bi bi-people"></i>
<aside><p> Total Users</p><strong><span th:text="*{adminBoard.getTotalNoOfUsers()}"></span></strong></p></aside>
</div>
<div class="stat"><p><i class="bi bi-file-earmark-text"></i>
<aside><p> Total Posts</p><strong><span th:text="*{adminBoard.getTotalPosts()}"></span></strong></p></aside>
</div>
<div class="stat"><p><i class="bi bi-calendar-week"></i>
<aside><p> Upcoming Events</p><strong><span th:text="*{adminBoard.getUpcomingEvents()}"></span></strong></p>
</aside>
</div>
<div class="stat"><p><i class="bi bi-chat-left-dots"></i>
<aside><p> New Comments</p><strong><span th:text="*{adminBoard.getNewComments()}"></span></strong></p>
</aside>
</div>
</div>
<div class="dashboard">
<div class="card">
<h3>Manage Users</h3>
<p>View and manage user accounts</p>
<a th:href="@{/admin/userInfo}"><button>Manage</button></a>
<a th:href="@{/admin/userInfo}">
<button>Manage</button>
</a>
</div>
<div class="card">
<h3>Content Moderation</h3>
<p>Review and moderate community content</p>
<h3>Feeds Management</h3>
<p>Review and manage community feeds</p>
<button>Manage</button>
</div>
......@@ -51,8 +63,8 @@
</div>
<div class="card">
<h3>Site Settings</h3>
<p>Configure website settings and preferences</p>
<h3>News Management</h3>
<p>Create and manage community news</p>
<button>Manage</button>
</div>
</div>
......
......@@ -2,43 +2,47 @@
<html xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{layout/layout}">
<head>
<title>Manage Users</title>
<!-- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css">-->
<!-- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css">-->
<link rel="stylesheet" href="/css/admin/userManageStyles.css">
<script src="/js/admin/admin.js" defer></script>
</head>
<section layout:fragment="content">
<h2>User Management</h2>
<table>
<thead>
<tr>
<th>ID</th>
<th>Full Name</th>
<th>Email</th>
<th>Role</th>
<th>Enabled</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr th:each="user : ${usersAdminInfo}">
<td th:text="${user.id}"></td>
<td th:text="${user.fullName}"></td>
<td th:text="${user.email}"></td>
<td th:text="${user.role}"></td>
<td>
<span th:text="${user.enabled ? 'Enabled' : 'Disabled'}"></span>
</td>
<td>
<a th:href="@{/user/edit/{id}(id=${user.id})}" class="btn">Edit</a>
<button th:if="${user.enabled}" th:onclick="|location.href='/user/disable/{id}'|"
class="btn btn-disable" th:text="'Disable'">Disable</button>
<button th:if="${!user.enabled}" th:onclick="|location.href='/user/enable/{id}'|"
class="btn" th:text="'Enable'">Enable</button>
</td>
</tr>
</tbody>
</table>
<div class="table-wrap">
<table>
<thead>
<tr>
<th>ID</th>
<th>Full Name</th>
<th>Email</th>
<th>Role</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr th:each="user : ${usersAdminInfo}">
<td th:text="${user.id}"></td>
<td th:text="${user.fullName}"></td>
<td th:text="${user.email}"></td>
<td th:field="${user.role}">
<select id="roleDdl" th:onchange="|updateUserRole(${user.id})|">
<option th:selected="${role.name==user.role}" th:each="role : ${roles}"
th:text="${role.name}"></option>
</select>
</td>
<td>
<button id="btn-enable-disable"
class="btn"
th:onclick="|toggleUserEnabled(${user.id}, ${user.enabled})|">
<span th:text="${user.enabled ? 'Disable' : 'Enable'}"></span>
</button>
</td>
</tr>
</tbody>
</table>
</div>
</section>
</html>
......@@ -12,7 +12,9 @@
<div th:replace="~{infoHeadingFragment/infoHeadingFragment :: breadcrumb}"></div>
<div class="title-section">
<h1 id="category-name"></h1>
<div class="buttons">
<button id="delete-button" disabled>Delete</button>
<button id="edit-mode-button">Edit</button>
<a id="addInfo">
<button id="add-new-information">
......@@ -22,9 +24,9 @@
</a>
</div>
</div>
<div id="headings-container" class="headings-container">
<!-- i will render headings dynamically added here from js -->
</div>
<button id="delete-button" disabled>Delete</button>
</section>
</html>
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment