diff --git a/src/main/java/com/example/clientproject/data/events/Events.java b/src/main/java/com/example/clientproject/data/events/Events.java new file mode 100644 index 0000000000000000000000000000000000000000..9a48c0f240a2a3424636102ebb43032dc90fbdc4 --- /dev/null +++ b/src/main/java/com/example/clientproject/data/events/Events.java @@ -0,0 +1,27 @@ +package com.example.clientproject.data.events; + +import com.example.clientproject.data.logs.Logs; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.persistence.*; +import java.util.Set; + +/** + * Entity object for events which trigger a log + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +@Entity +public class Events { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private long eventId; + private String eventName; + + @OneToMany(cascade=CascadeType.ALL, orphanRemoval = true) + @JoinColumn(name="Event_Id", nullable = false) + private Set<Logs> logs; +} diff --git a/src/main/java/com/example/clientproject/data/events/EventsRepo.java b/src/main/java/com/example/clientproject/data/events/EventsRepo.java new file mode 100644 index 0000000000000000000000000000000000000000..69b5d3e7e6f63065aa47be3b3b4c22f9dc518445 --- /dev/null +++ b/src/main/java/com/example/clientproject/data/events/EventsRepo.java @@ -0,0 +1,19 @@ +package com.example.clientproject.data.events; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; + +import java.util.Optional; + +/** + * Repository for the "Events" Entity + */ +public interface EventsRepo extends JpaRepository<Events, Long> { + /** + * Find an event by its name + * @param name - the name to search by + * @return - the event as an optional + */ + @Query("select e from Events e where e.eventName = ?1") + Optional<Events> findByEventName(String name); +} diff --git a/src/main/java/com/example/clientproject/data/logs/Logs.java b/src/main/java/com/example/clientproject/data/logs/Logs.java new file mode 100644 index 0000000000000000000000000000000000000000..190fee8fbbb18c4ad103465226f9b7d8ea95c39b --- /dev/null +++ b/src/main/java/com/example/clientproject/data/logs/Logs.java @@ -0,0 +1,43 @@ +package com.example.clientproject.data.logs; + +import com.example.clientproject.data.converters.TinyIntToBoolean; +import com.example.clientproject.data.events.Events; +import com.example.clientproject.data.users.Users; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.persistence.*; + +/** + * Entity object for logs + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +@Entity +public class Logs { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private long logId; + private String logDetails; + private String logDateTime; + @Convert(converter = TinyIntToBoolean.class) + private boolean logSuperAdmin; + + @ManyToOne + @JoinColumn(name="User_Id", nullable=false) + private Users user; + + @ManyToOne + @JoinColumn(name="Event_Id", nullable=false) + private Events event; + + public Logs(String details, String dateTime, boolean superAdmin, Users aUser, Events aEvent) { + logDetails = details; + logDateTime = dateTime; + logSuperAdmin = superAdmin; + user = aUser; + event = aEvent; + } +} diff --git a/src/main/java/com/example/clientproject/data/logs/LogsRepo.java b/src/main/java/com/example/clientproject/data/logs/LogsRepo.java new file mode 100644 index 0000000000000000000000000000000000000000..7c5921939f46b8b1e27c720ec86bcebd05f78158 --- /dev/null +++ b/src/main/java/com/example/clientproject/data/logs/LogsRepo.java @@ -0,0 +1,43 @@ +package com.example.clientproject.data.logs; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; + +import java.util.List; + +/** + * JPA Repo for the Logs entity + */ +public interface LogsRepo extends JpaRepository<Logs, Long> { + /** + * Find all the logs from a specific date time + * @param dateTime - the datetime to search by + * @return - list of logs from that date time + */ + @Query("select l from Logs l where l.logDateTime like ?1") + List<Logs> findByDateTime(String dateTime); + + /** + * Find all the logs for a specific event + * @param eventId - the id of the event to search by + * @return - a list of logs with that event + */ + @Query("select l from Logs l where l.event.eventId = ?1") + List<Logs> findByEventId(long eventId); + + /** + * Find all the logs for a specific user + * @param userId - the id of the user to search by + * @return - a list of all the logs for that user + */ + @Query("select l from Logs l where l.user.userId = ?1") + List<Logs> findByUserId(long userId); + + /** + * Find all the logs by a specific super admin status + * @param superAdminStatus - the status to search by + * @return - a list of the logs found + */ + @Query("select l from Logs l where l.logSuperAdmin = ?1") + List<Logs> findBySuperAdminStatus(boolean superAdminStatus); +} diff --git a/src/main/java/com/example/clientproject/data/users/Users.java b/src/main/java/com/example/clientproject/data/users/Users.java index f5c48347b44bafc85413a54965026fa739ca0a3f..96803f2a5639b05db74eb3b6e8c01ea9e8933e8f 100644 --- a/src/main/java/com/example/clientproject/data/users/Users.java +++ b/src/main/java/com/example/clientproject/data/users/Users.java @@ -1,5 +1,6 @@ package com.example.clientproject.data.users; +import com.example.clientproject.data.logs.Logs; import com.example.clientproject.data.shops.Shops; import com.example.clientproject.data.userStampBoards.UserStampBoards; import com.example.clientproject.data.tags.Tags; @@ -91,6 +92,10 @@ public class Users { ) private List<Tags> favouriteTags; + @OneToMany(cascade=CascadeType.ALL, orphanRemoval = true) + @JoinColumn(name="User_Id", nullable=false) + private Set<Logs> logs; + public String toString(){ return "User:" + this.getUserFirstName(); } diff --git a/src/main/java/com/example/clientproject/service/LoggingService.java b/src/main/java/com/example/clientproject/service/LoggingService.java new file mode 100644 index 0000000000000000000000000000000000000000..aa453854b260c560b6cfa466c2f51a590796ebf5 --- /dev/null +++ b/src/main/java/com/example/clientproject/service/LoggingService.java @@ -0,0 +1,65 @@ +package com.example.clientproject.service; + +import com.example.clientproject.data.events.Events; +import com.example.clientproject.data.logs.Logs; +import com.example.clientproject.data.logs.LogsRepo; +import com.example.clientproject.service.Utils.JWTUtils; +import org.springframework.stereotype.Service; + +import javax.servlet.http.HttpSession; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; + +/** + * Service for all logging based methods + */ +@Service +public class LoggingService { + LogsRepo logsRepo; + JWTUtils jwtUtils; + + /** + * Constructor + * @param aLogsRepo - object of type LogsRepo + * @param aJWTUtils - object of type JWTUtils + */ + public LoggingService(LogsRepo aLogsRepo, JWTUtils aJWTUtils) { + jwtUtils = aJWTUtils; + logsRepo = aLogsRepo; + } + + /** + * Method for logging an event + * @param event - the event + * @param session - the session + * @param details - details of the event + */ + public void logEvent(Events event, HttpSession session, String details) { + // Instantiate a flagging variable + boolean superAdminStatus; + // If the session attribute "superAdmin" doesn't exist (super admin not logged in) + if (session.getAttribute("superAdmin") == null) { + // Set the flag to false + superAdminStatus = false; + // Else + } else { + // Set the flag to the state of the session attribute + superAdminStatus = (boolean) session.getAttribute("superAdmin"); + } + + // Instantiate a DateTimeFormatter with the correct format + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + + // Create a new Log object + Logs newLog = new Logs( + details, + LocalDateTime.now().format(formatter), + superAdminStatus, + jwtUtils.getLoggedInUserRow(session).get(), + event + ); + + // Save the new log + logsRepo.save(newLog); + } +} diff --git a/src/main/java/com/example/clientproject/service/Utils/JWTUtils.java b/src/main/java/com/example/clientproject/service/Utils/JWTUtils.java index d306113a8480c918eac69b7ef4174fd44fea8149..fbfe4c7b5129cad9e9d647de706badee3c9ade66 100644 --- a/src/main/java/com/example/clientproject/service/Utils/JWTUtils.java +++ b/src/main/java/com/example/clientproject/service/Utils/JWTUtils.java @@ -1,5 +1,7 @@ package com.example.clientproject.service.Utils; +import com.example.clientproject.data.userPermissions.UserPermissions; +import com.example.clientproject.data.userPermissions.UserPermissionsRepo; import com.example.clientproject.data.users.Users; import com.example.clientproject.data.users.UsersRepo; import io.jsonwebtoken.Claims; @@ -23,9 +25,11 @@ import java.util.Optional; public class JWTUtils { private UsersRepo usersRepo; + private UserPermissionsRepo userPermRepo; - public JWTUtils(UsersRepo ausersRepo){ - usersRepo = ausersRepo; + public JWTUtils(UsersRepo aUsersRepo, UserPermissionsRepo aUserPermsRepo){ + usersRepo = aUsersRepo; + userPermRepo = aUserPermsRepo; } private String SECRET_KEY; @@ -91,6 +95,14 @@ public class JWTUtils { jwtTimeToLive // used to calculate expiration (claim = exp) ); + List<UserPermissions> userPermList = userPermRepo.findByUserId(userId); + for (UserPermissions u: userPermList) { + if (u.getAdminType().getAdminTypeId() == 3) { + setSuperAdmin(session, true); + break; + } + } + session.setAttribute("loginCredJWT", jwt); return jwt.toString(); } @@ -131,6 +143,14 @@ public class JWTUtils { } public void logOutUser(HttpSession session){ + if ((boolean) session.getAttribute("superAdmin")) { + setSuperAdmin(session, false); + } + session.removeAttribute("loginCredJWT"); } + + public void setSuperAdmin(HttpSession session, boolean status) { + session.setAttribute("superAdmin", status); + } } diff --git a/src/main/resources/database/WeekFourERD.png b/src/main/resources/database/WeekFourERD.png new file mode 100644 index 0000000000000000000000000000000000000000..7247c10a046662acc5b072479ae00e84b30652e2 Binary files /dev/null and b/src/main/resources/database/WeekFourERD.png differ diff --git a/src/main/resources/database/schema.sql b/src/main/resources/database/schema.sql index c7736a3642b0816130bf6b9e4ac6353037abd22a..e6b2422c12bacce036e9266c887f6e59328dda43 100644 --- a/src/main/resources/database/schema.sql +++ b/src/main/resources/database/schema.sql @@ -255,6 +255,41 @@ CREATE TABLE IF NOT EXISTS `mydb`.`Socials` ( ENGINE = InnoDB; + +-- ----------------------------------------------------- +-- Table `mydb`.`Events` +-- ----------------------------------------------------- +CREATE TABLE IF NOT EXISTS `mydb`.`Events` ( + `Event_Id` INT NOT NULL AUTO_INCREMENT, + `Event_Name` VARCHAR(45) NOT NULL, + PRIMARY KEY(`Event_Id`)) +ENGINE = InnoDB; + + +-- ----------------------------------------------------- +-- Table `mydb`.`Logs` +-- ----------------------------------------------------- +CREATE TABLE IF NOT EXISTS `mydb`.`Logs` ( + `Log_Id` INT NOT NULL AUTO_INCREMENT, + `Event_Id` INT NOT NULL, + `User_Id` INT NOT NULL, + `Log_Details` VARCHAR(150) NOT NULL, + `Log_Date_Time` DATETIME NOT NULL, + `Log_Super_Admin` TINYINT NOT NULL, + PRIMARY KEY(`Log_Id`, `Event_Id`, `User_Id`), + CONSTRAINT `fk_Events1` + FOREIGN KEY (`Event_Id`) + REFERENCES `mydb`.`Events` (`Event_Id`) + ON UPDATE NO ACTION + ON DELETE NO ACTION, + CONSTRAINT `fk_Users1` + FOREIGN KEY (`User_Id`) + REFERENCES `mydb`.`Users` (`User_Id`) + ON UPDATE NO ACTION + ON DELETE NO ACTION + ) +ENGINE = InnoDB; + INSERT INTO two_factor_methods (`Two_Factor_Method_Id`, `Two_Factor_Method_Name`) VALUES (1, 'None'); diff --git a/src/test/resources/schema-test-h2.sql b/src/test/resources/schema-test-h2.sql index a1344bb0431691788e75d4dcff4331aa471ff961..b18fac5af9a72b7a7362d6d9a74d38f7071d3331 100644 --- a/src/test/resources/schema-test-h2.sql +++ b/src/test/resources/schema-test-h2.sql @@ -265,6 +265,40 @@ CREATE TABLE IF NOT EXISTS `User_Stamp_Boards` ( ENGINE = InnoDB; +-- ----------------------------------------------------- +-- Table `Events` +-- ----------------------------------------------------- +CREATE TABLE IF NOT EXISTS `Events` ( + `Event_Id` INT NOT NULL AUTO_INCREMENT, + `Event_Name` VARCHAR(45) NOT NULL, + PRIMARY KEY(`Event_Id`)) + ENGINE = InnoDB; + + +-- ----------------------------------------------------- +-- Table `Logs` +-- ----------------------------------------------------- +CREATE TABLE IF NOT EXISTS `Logs` ( + `Log_Id` INT NOT NULL AUTO_INCREMENT, + `Event_Id` INT NOT NULL, + `User_Id` INT NOT NULL, + `Log_Details` VARCHAR(150), + `Log_Date_Time` DATETIME NOT NULL, + `Log_Super_Admin` TINYINT NOT NULL, + PRIMARY KEY(`Log_Id`, `Event_Id`, `User_Id`), + CONSTRAINT `fk_Events1` + FOREIGN KEY (`Event_Id`) + REFERENCES `Events` (`Event_Id`) + ON UPDATE NO ACTION + ON DELETE NO ACTION, + CONSTRAINT `fk_Users1` + FOREIGN KEY (`User_Id`) + REFERENCES `Users` (`User_Id`) + ON UPDATE NO ACTION + ON DELETE NO ACTION +) + ENGINE = InnoDB; + INSERT INTO two_factor_methods (`Two_Factor_Method_Id`, `Two_Factor_Method_Name`) VALUES (1, 'None'); INSERT INTO two_factor_methods (`Two_Factor_Method_Id`, `Two_Factor_Method_Name`) VALUES (2, 'GAuth'); @@ -284,4 +318,17 @@ INSERT INTO Admin_Types (Admin_Type_Id, Admin_Type_Name) VALUES (1,'User'); INSERT INTO Admin_Types (Admin_Type_Id, Admin_Type_Name) VALUES (2,'Business Admin'); INSERT INTO Admin_Types (Admin_Type_Id, Admin_Type_Name) VALUES (3,'Super Admin'); -INSERT INTO Tags (Tag_Name) VALUES ('Football'); \ No newline at end of file +INSERT INTO Tags (Tag_Name) VALUES ('Football'); + +INSERT INTO Events (Event_Name) VALUES ('New Account Created'); +INSERT INTO Events (Event_Name) VALUES ('Failed Login'); +INSERT INTO Events (Event_Name) VALUES ('Successful Login'); +INSERT INTO Events (Event_Name) VALUES ('User Details Changed'); +INSERT INTO Events (Event_Name) VALUES ('User Removed'); +INSERT INTO Events (Event_Name) VALUES ('New Shop'); +INSERT INTO Events (Event_Name) VALUES ('Deleted Shop'); +INSERT INTO Events (Event_Name) VALUES ('New Favourite Business'); +INSERT INTO Events (Event_Name) VALUES ('New Shop User'); +INSERT INTO Events (Event_Name) VALUES ('Shop Details Changed'); +INSERT INTO Events (Event_Name) VALUES ('Shop Activity Toggled'); +INSERT INTO Events (Event_Name) VALUES ('Image Inserted'); \ No newline at end of file