From d2c1bd5c4062a94d609999ff70821b13f608f2e3 Mon Sep 17 00:00:00 2001
From: Jodicd
Date: Sun, 14 Feb 2021 14:01:31 -0600
Subject: [PATCH 01/15] JM - Intial Commit
---
README-Jodi.md | 3 +++
1 file changed, 3 insertions(+)
create mode 100644 README-Jodi.md
diff --git a/README-Jodi.md b/README-Jodi.md
new file mode 100644
index 00000000..63b6d5ac
--- /dev/null
+++ b/README-Jodi.md
@@ -0,0 +1,3 @@
+# Jodi Mitchell
+
+This is my Readme for my first commit.
From 4c4d279dad5df976daaa0c1529f51b30495db6d0 Mon Sep 17 00:00:00 2001
From: Jodicd
Date: Tue, 16 Feb 2021 13:10:38 -0600
Subject: [PATCH 02/15] Added Sprint2 Tasks
---
pom.xml | 12 --
.../activeUsers/ActiveUserDeleteCommand.java | 38 ++++
.../ValidateActiveUserCommand.java | 41 ++++
.../employees/ActiveEmployeeExistsQuery.java | 21 ++
.../employees/EmployeeCreateCommand.java | 89 +++++++++
.../employees/EmployeeDeleteCommand.java | 42 ++++
.../commands/employees/EmployeeQuery.java | 41 ++++
.../employees/EmployeeSignInCommand.java | 108 ++++++++++
.../employees/EmployeeUpdateCommand.java | 80 ++++++++
.../employees/helpers/EmployeeHelper.java | 34 ++++
.../controllers/BaseRestController.java | 89 +++++++++
.../controllers/BaseRouteController.java | 117 +++++++++++
.../EmployeeDetailRouteController.java | 145 ++++++++++++++
.../controllers/EmployeeRestController.java | 100 ++++++++++
.../controllers/MainMenuRouteController.java | 44 +++++
.../ProductDetailRouteController.java | 62 +++++-
.../ProductListingRouteController.java | 31 ++-
.../controllers/ProductRestController.java | 49 ++++-
.../controllers/SignInRestController.java | 34 ++++
.../controllers/SignInRouteController.java | 89 +++++++++
.../enums/QueryParameterMessages.java | 45 +++++
.../enums/QueryParameterNames.java | 3 +-
.../controllers/enums/ViewModelNames.java | 6 +-
.../controllers/enums/ViewNames.java | 5 +-
.../uark/registerapp/models/api/Employee.java | 145 ++++++++++++++
.../models/api/EmployeeSignIn.java | 28 +++
.../registerapp/models/api/EmployeeType.java | 55 ++++++
.../models/entities/ActiveUserEntity.java | 91 +++++++++
.../models/entities/EmployeeEntity.java | 164 ++++++++++++++++
.../models/enums/EmployeeClassification.java | 58 ++++++
.../repositories/ActiveUserRepository.java | 13 ++
.../repositories/EmployeeRepository.java | 15 ++
src/main/resources/static/images/Sign-Out.png | Bin 0 -> 417 bytes
.../static/scripts/employeeDetail.js | 184 ++++++++++++++++++
src/main/resources/static/scripts/mainMenu.js | 43 ++++
src/main/resources/static/scripts/master.js | 26 +++
src/main/resources/static/scripts/signIn.js | 43 ++++
src/main/resources/static/styles/master.css | 18 ++
.../resources/templates/employeeDetail.html | 104 ++++++++++
src/main/resources/templates/mainMenu.html | 62 ++++++
.../resources/templates/productDetail.html | 10 +-
.../resources/templates/productListing.html | 6 +-
src/main/resources/templates/signIn.html | 41 ++++
43 files changed, 2396 insertions(+), 35 deletions(-)
create mode 100644 src/main/java/edu/uark/registerapp/commands/activeUsers/ActiveUserDeleteCommand.java
create mode 100644 src/main/java/edu/uark/registerapp/commands/activeUsers/ValidateActiveUserCommand.java
create mode 100644 src/main/java/edu/uark/registerapp/commands/employees/ActiveEmployeeExistsQuery.java
create mode 100644 src/main/java/edu/uark/registerapp/commands/employees/EmployeeCreateCommand.java
create mode 100644 src/main/java/edu/uark/registerapp/commands/employees/EmployeeDeleteCommand.java
create mode 100644 src/main/java/edu/uark/registerapp/commands/employees/EmployeeQuery.java
create mode 100644 src/main/java/edu/uark/registerapp/commands/employees/EmployeeSignInCommand.java
create mode 100644 src/main/java/edu/uark/registerapp/commands/employees/EmployeeUpdateCommand.java
create mode 100644 src/main/java/edu/uark/registerapp/commands/employees/helpers/EmployeeHelper.java
create mode 100644 src/main/java/edu/uark/registerapp/controllers/BaseRestController.java
create mode 100644 src/main/java/edu/uark/registerapp/controllers/BaseRouteController.java
create mode 100644 src/main/java/edu/uark/registerapp/controllers/EmployeeDetailRouteController.java
create mode 100644 src/main/java/edu/uark/registerapp/controllers/EmployeeRestController.java
create mode 100644 src/main/java/edu/uark/registerapp/controllers/MainMenuRouteController.java
create mode 100644 src/main/java/edu/uark/registerapp/controllers/SignInRestController.java
create mode 100644 src/main/java/edu/uark/registerapp/controllers/SignInRouteController.java
create mode 100644 src/main/java/edu/uark/registerapp/controllers/enums/QueryParameterMessages.java
create mode 100644 src/main/java/edu/uark/registerapp/models/api/Employee.java
create mode 100644 src/main/java/edu/uark/registerapp/models/api/EmployeeSignIn.java
create mode 100644 src/main/java/edu/uark/registerapp/models/api/EmployeeType.java
create mode 100644 src/main/java/edu/uark/registerapp/models/entities/ActiveUserEntity.java
create mode 100644 src/main/java/edu/uark/registerapp/models/entities/EmployeeEntity.java
create mode 100644 src/main/java/edu/uark/registerapp/models/enums/EmployeeClassification.java
create mode 100644 src/main/java/edu/uark/registerapp/models/repositories/ActiveUserRepository.java
create mode 100644 src/main/java/edu/uark/registerapp/models/repositories/EmployeeRepository.java
create mode 100644 src/main/resources/static/images/Sign-Out.png
create mode 100644 src/main/resources/static/scripts/employeeDetail.js
create mode 100644 src/main/resources/static/scripts/mainMenu.js
create mode 100644 src/main/resources/static/scripts/signIn.js
create mode 100644 src/main/resources/templates/employeeDetail.html
create mode 100644 src/main/resources/templates/mainMenu.html
create mode 100644 src/main/resources/templates/signIn.html
diff --git a/pom.xml b/pom.xml
index 330a0022..1f4ec523 100644
--- a/pom.xml
+++ b/pom.xml
@@ -46,18 +46,6 @@
commons-lang3
-
-
-
org.springframework.boot
spring-boot-devtools
diff --git a/src/main/java/edu/uark/registerapp/commands/activeUsers/ActiveUserDeleteCommand.java b/src/main/java/edu/uark/registerapp/commands/activeUsers/ActiveUserDeleteCommand.java
new file mode 100644
index 00000000..ccd22837
--- /dev/null
+++ b/src/main/java/edu/uark/registerapp/commands/activeUsers/ActiveUserDeleteCommand.java
@@ -0,0 +1,38 @@
+package edu.uark.registerapp.commands.activeUsers;
+
+import java.util.Optional;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import edu.uark.registerapp.commands.VoidCommandInterface;
+import edu.uark.registerapp.models.entities.ActiveUserEntity;
+import edu.uark.registerapp.models.repositories.ActiveUserRepository;
+
+@Service
+public class ActiveUserDeleteCommand implements VoidCommandInterface {
+ @Transactional
+ @Override
+ public void execute() {
+ final Optional activeUserEntity =
+ this.activeUserRepository.findBySessionKey(this.sessionKey);
+
+ if (activeUserEntity.isPresent()) {
+ this.activeUserRepository.delete(activeUserEntity.get());
+ }
+ }
+
+ // Properties
+ private String sessionKey;
+ public String getSessionKey() {
+ return this.sessionKey;
+ }
+ public ActiveUserDeleteCommand setSessionKey(final String sessionKey) {
+ this.sessionKey = sessionKey;
+ return this;
+ }
+
+ @Autowired
+ private ActiveUserRepository activeUserRepository;
+}
diff --git a/src/main/java/edu/uark/registerapp/commands/activeUsers/ValidateActiveUserCommand.java b/src/main/java/edu/uark/registerapp/commands/activeUsers/ValidateActiveUserCommand.java
new file mode 100644
index 00000000..d04784cb
--- /dev/null
+++ b/src/main/java/edu/uark/registerapp/commands/activeUsers/ValidateActiveUserCommand.java
@@ -0,0 +1,41 @@
+package edu.uark.registerapp.commands.activeUsers;
+
+import java.util.Optional;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import edu.uark.registerapp.commands.ResultCommandInterface;
+import edu.uark.registerapp.commands.exceptions.UnauthorizedException;
+import edu.uark.registerapp.models.entities.ActiveUserEntity;
+import edu.uark.registerapp.models.repositories.ActiveUserRepository;
+
+@Service
+public class ValidateActiveUserCommand implements ResultCommandInterface {
+ @Override
+ public ActiveUserEntity execute() {
+ final Optional activeUserEntity =
+ this.activeUserRepository.findBySessionKey(this.sessionKey);
+
+ if (!activeUserEntity.isPresent()) {
+ throw new UnauthorizedException();
+ }
+
+ return activeUserEntity.get();
+ }
+
+ // Properties
+ private String sessionKey;
+
+ public String getSessionKey() {
+ return this.sessionKey;
+ }
+
+ public ValidateActiveUserCommand setSessionKey(final String sessionKey) {
+ this.sessionKey = sessionKey;
+ return this;
+ }
+
+ @Autowired
+ private ActiveUserRepository activeUserRepository;
+}
diff --git a/src/main/java/edu/uark/registerapp/commands/employees/ActiveEmployeeExistsQuery.java b/src/main/java/edu/uark/registerapp/commands/employees/ActiveEmployeeExistsQuery.java
new file mode 100644
index 00000000..9581f662
--- /dev/null
+++ b/src/main/java/edu/uark/registerapp/commands/employees/ActiveEmployeeExistsQuery.java
@@ -0,0 +1,21 @@
+package edu.uark.registerapp.commands.employees;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import edu.uark.registerapp.commands.VoidCommandInterface;
+import edu.uark.registerapp.commands.exceptions.NotFoundException;
+import edu.uark.registerapp.models.repositories.EmployeeRepository;
+
+@Service
+public class ActiveEmployeeExistsQuery implements VoidCommandInterface {
+ @Override
+ public void execute() {
+ if (!this.employeeRepository.existsByIsActive(true)) {
+ throw new NotFoundException("Employee");
+ }
+ }
+
+ @Autowired
+ private EmployeeRepository employeeRepository;
+}
diff --git a/src/main/java/edu/uark/registerapp/commands/employees/EmployeeCreateCommand.java b/src/main/java/edu/uark/registerapp/commands/employees/EmployeeCreateCommand.java
new file mode 100644
index 00000000..0da298fb
--- /dev/null
+++ b/src/main/java/edu/uark/registerapp/commands/employees/EmployeeCreateCommand.java
@@ -0,0 +1,89 @@
+package edu.uark.registerapp.commands.employees;
+
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import edu.uark.registerapp.commands.ResultCommandInterface;
+import edu.uark.registerapp.commands.employees.helpers.EmployeeHelper;
+import edu.uark.registerapp.commands.exceptions.UnprocessableEntityException;
+import edu.uark.registerapp.models.api.Employee;
+import edu.uark.registerapp.models.entities.EmployeeEntity;
+import edu.uark.registerapp.models.enums.EmployeeClassification;
+import edu.uark.registerapp.models.repositories.EmployeeRepository;
+
+@Service
+public class EmployeeCreateCommand implements ResultCommandInterface {
+ @Override
+ public Employee execute() {
+ this.validateProperties();
+
+ if (this.isInitialEmployee) {
+ this.apiEmployee.setClassification(
+ EmployeeClassification.GENERAL_MANAGER.getClassification());
+ }
+
+ // Create a new ENTITY object from the API object details.
+ final EmployeeEntity employeeEntity =
+ this.employeeRepository.save(new EmployeeEntity(this.apiEmployee));
+
+ // Synchronize information generated by the database upon INSERT.
+ this.apiEmployee.setId(employeeEntity.getId());
+ // Only send the password over the network when modifying the database.
+ this.apiEmployee.setPassword(StringUtils.EMPTY);
+ this.apiEmployee.setCreatedOn(employeeEntity.getCreatedOn());
+ this.apiEmployee.setEmployeeId(
+ EmployeeHelper.padEmployeeId(
+ employeeEntity.getEmployeeId()));
+
+ return this.apiEmployee;
+ }
+
+ // Helper methods
+ private void validateProperties() {
+ if (StringUtils.isBlank(this.apiEmployee.getFirstName())) {
+ throw new UnprocessableEntityException("first name");
+ }
+ if (StringUtils.isBlank(this.apiEmployee.getLastName())) {
+ throw new UnprocessableEntityException("last name");
+ }
+ if (StringUtils.isBlank(this.apiEmployee.getPassword())) {
+ throw new UnprocessableEntityException("password");
+ }
+
+ if (!this.isInitialEmployee
+ && (EmployeeClassification.map(this.apiEmployee.getClassification()) == EmployeeClassification.NOT_DEFINED)) {
+
+ throw new UnprocessableEntityException("classification");
+ }
+ }
+
+ // Properties
+ private Employee apiEmployee;
+ public Employee getApiEmployee() {
+ return this.apiEmployee;
+ }
+ public EmployeeCreateCommand setApiEmployee(final Employee apiEmployee) {
+ this.apiEmployee = apiEmployee;
+ return this;
+ }
+
+ private boolean isInitialEmployee;
+ public boolean getIsInitialEmployee() {
+ return this.isInitialEmployee;
+ }
+ public EmployeeCreateCommand setIsInitialEmployee(
+ final boolean isInitialEmployee
+ ) {
+
+ this.isInitialEmployee = isInitialEmployee;
+ return this;
+ }
+
+ @Autowired
+ private EmployeeRepository employeeRepository;
+
+ public EmployeeCreateCommand() {
+ this.isInitialEmployee = false;
+ }
+}
diff --git a/src/main/java/edu/uark/registerapp/commands/employees/EmployeeDeleteCommand.java b/src/main/java/edu/uark/registerapp/commands/employees/EmployeeDeleteCommand.java
new file mode 100644
index 00000000..da485479
--- /dev/null
+++ b/src/main/java/edu/uark/registerapp/commands/employees/EmployeeDeleteCommand.java
@@ -0,0 +1,42 @@
+package edu.uark.registerapp.commands.employees;
+
+import java.util.Optional;
+import java.util.UUID;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import edu.uark.registerapp.commands.VoidCommandInterface;
+import edu.uark.registerapp.commands.exceptions.NotFoundException;
+import edu.uark.registerapp.models.entities.EmployeeEntity;
+import edu.uark.registerapp.models.repositories.EmployeeRepository;
+
+@Service
+public class EmployeeDeleteCommand implements VoidCommandInterface {
+ @Transactional
+ @Override
+ public void execute() {
+ final Optional employeeEntity =
+ this.employeeRepository.findById(this.employeeId);
+
+ if (!employeeEntity.isPresent()) { // No record with the associated record ID exists in the database.
+ throw new NotFoundException("Product");
+ }
+
+ this.employeeRepository.delete(employeeEntity.get());
+ }
+
+ // Properties
+ private UUID employeeId;
+ public UUID getEmployeeId() {
+ return this.employeeId;
+ }
+ public EmployeeDeleteCommand setEmployeeId(final UUID productId) {
+ this.employeeId = productId;
+ return this;
+ }
+
+ @Autowired
+ private EmployeeRepository employeeRepository;
+}
diff --git a/src/main/java/edu/uark/registerapp/commands/employees/EmployeeQuery.java b/src/main/java/edu/uark/registerapp/commands/employees/EmployeeQuery.java
new file mode 100644
index 00000000..0fcfb8e8
--- /dev/null
+++ b/src/main/java/edu/uark/registerapp/commands/employees/EmployeeQuery.java
@@ -0,0 +1,41 @@
+package edu.uark.registerapp.commands.employees;
+
+import java.util.Optional;
+import java.util.UUID;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import edu.uark.registerapp.commands.ResultCommandInterface;
+import edu.uark.registerapp.commands.exceptions.NotFoundException;
+import edu.uark.registerapp.models.api.Employee;
+import edu.uark.registerapp.models.entities.EmployeeEntity;
+import edu.uark.registerapp.models.repositories.EmployeeRepository;
+
+@Service
+public class EmployeeQuery implements ResultCommandInterface {
+ @Override
+ public Employee execute() {
+ final Optional employeeEntity =
+ this.employeeRepository.findById(this.employeeId);
+
+ if (employeeEntity.isPresent()) {
+ return new Employee(employeeEntity.get());
+ } else {
+ throw new NotFoundException("Employee");
+ }
+ }
+
+ // Properties
+ private UUID employeeId;
+ public UUID getEmployeeId() {
+ return this.employeeId;
+ }
+ public EmployeeQuery setEmployeeId(final UUID employeeId) {
+ this.employeeId = employeeId;
+ return this;
+ }
+
+ @Autowired
+ private EmployeeRepository employeeRepository;
+}
diff --git a/src/main/java/edu/uark/registerapp/commands/employees/EmployeeSignInCommand.java b/src/main/java/edu/uark/registerapp/commands/employees/EmployeeSignInCommand.java
new file mode 100644
index 00000000..ad757154
--- /dev/null
+++ b/src/main/java/edu/uark/registerapp/commands/employees/EmployeeSignInCommand.java
@@ -0,0 +1,108 @@
+package edu.uark.registerapp.commands.employees;
+
+import java.util.Arrays;
+import java.util.Optional;
+
+import javax.transaction.Transactional;
+
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import edu.uark.registerapp.commands.ResultCommandInterface;
+import edu.uark.registerapp.commands.employees.helpers.EmployeeHelper;
+import edu.uark.registerapp.commands.exceptions.UnauthorizedException;
+import edu.uark.registerapp.commands.exceptions.UnprocessableEntityException;
+import edu.uark.registerapp.models.api.Employee;
+import edu.uark.registerapp.models.api.EmployeeSignIn;
+import edu.uark.registerapp.models.entities.ActiveUserEntity;
+import edu.uark.registerapp.models.entities.EmployeeEntity;
+import edu.uark.registerapp.models.repositories.ActiveUserRepository;
+import edu.uark.registerapp.models.repositories.EmployeeRepository;
+
+@Service
+public class EmployeeSignInCommand implements ResultCommandInterface {
+ @Override
+ public Employee execute() {
+ this.validateProperties();
+
+ return new Employee(this.SignInEmployee());
+ }
+
+ // Helper methods
+ private void validateProperties() {
+ if (StringUtils.isBlank(this.employeeSignIn.getEmployeeId())) {
+ throw new UnprocessableEntityException("employee ID");
+ }
+ try {
+ Integer.parseInt(this.employeeSignIn.getEmployeeId());
+ } catch (final NumberFormatException e) {
+ throw new UnprocessableEntityException("employee ID");
+ }
+ if (StringUtils.isBlank(this.employeeSignIn.getPassword())) {
+ throw new UnprocessableEntityException("password");
+ }
+ }
+
+ @Transactional
+ private EmployeeEntity SignInEmployee() {
+ final Optional employeeEntity =
+ this.employeeRepository.findByEmployeeId(
+ Integer.parseInt(this.employeeSignIn.getEmployeeId()));
+
+ if (!employeeEntity.isPresent()
+ || !Arrays.equals(
+ employeeEntity.get().getPassword(),
+ EmployeeHelper.hashPassword(this.employeeSignIn.getPassword()))
+ ) {
+
+ throw new UnauthorizedException();
+ }
+
+ final Optional activeUserEntity =
+ this.activeUserRepository
+ .findByEmployeeId(employeeEntity.get().getId());
+
+ if (!activeUserEntity.isPresent()) {
+ this.activeUserRepository.save(
+ (new ActiveUserEntity())
+ .setSessionKey(this.sessionId)
+ .setEmployeeId(employeeEntity.get().getId())
+ .setClassification(
+ employeeEntity.get().getClassification())
+ .setName(
+ employeeEntity.get().getFirstName()
+ .concat(" ")
+ .concat(employeeEntity.get().getLastName())));
+ } else {
+ this.activeUserRepository.save(
+ activeUserEntity.get().setSessionKey(this.sessionId));
+ }
+
+ return employeeEntity.get();
+ }
+
+ // Properties
+ private EmployeeSignIn employeeSignIn;
+ public EmployeeSignIn getEmployeeSignIn() {
+ return this.employeeSignIn;
+ }
+ public EmployeeSignInCommand setEmployeeSignIn(final EmployeeSignIn employeeSignIn) {
+ this.employeeSignIn = employeeSignIn;
+ return this;
+ }
+
+ private String sessionId;
+ public String getSessionId() {
+ return this.sessionId;
+ }
+ public EmployeeSignInCommand setSessionId(final String sessionId) {
+ this.sessionId = sessionId;
+ return this;
+ }
+
+ @Autowired
+ private EmployeeRepository employeeRepository;
+ @Autowired
+ private ActiveUserRepository activeUserRepository;
+}
diff --git a/src/main/java/edu/uark/registerapp/commands/employees/EmployeeUpdateCommand.java b/src/main/java/edu/uark/registerapp/commands/employees/EmployeeUpdateCommand.java
new file mode 100644
index 00000000..0fd64d7a
--- /dev/null
+++ b/src/main/java/edu/uark/registerapp/commands/employees/EmployeeUpdateCommand.java
@@ -0,0 +1,80 @@
+package edu.uark.registerapp.commands.employees;
+
+import java.util.Optional;
+import java.util.UUID;
+
+import javax.transaction.Transactional;
+
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import edu.uark.registerapp.commands.ResultCommandInterface;
+import edu.uark.registerapp.commands.exceptions.NotFoundException;
+import edu.uark.registerapp.commands.exceptions.UnprocessableEntityException;
+import edu.uark.registerapp.models.api.Employee;
+import edu.uark.registerapp.models.entities.EmployeeEntity;
+import edu.uark.registerapp.models.enums.EmployeeClassification;
+import edu.uark.registerapp.models.repositories.EmployeeRepository;
+
+@Service
+public class EmployeeUpdateCommand implements ResultCommandInterface {
+ @Override
+ public Employee execute() {
+ this.validateProperties();
+
+ this.updateEmployeeEntity();
+
+ return this.apiEmployee;
+ }
+
+ // Helper methods
+ private void validateProperties() {
+ if (StringUtils.isBlank(this.apiEmployee.getFirstName())) {
+ throw new UnprocessableEntityException("first name");
+ }
+ if (StringUtils.isBlank(this.apiEmployee.getLastName())) {
+ throw new UnprocessableEntityException("last name");
+ }
+ if (EmployeeClassification.map(this.apiEmployee.getClassification()) == EmployeeClassification.NOT_DEFINED) {
+ throw new UnprocessableEntityException("classification");
+ }
+ }
+
+ @Transactional
+ private void updateEmployeeEntity() {
+ final Optional queriedEmployeeEntity =
+ this.employeeRepository.findById(this.employeeId);
+
+ if (!queriedEmployeeEntity.isPresent()) {
+ throw new NotFoundException("Employee"); // No record with the associated record ID exists in the database.
+ }
+
+ this.apiEmployee = queriedEmployeeEntity.get()
+ .synchronize(this.apiEmployee); // Synchronize any incoming changes for UPDATE to the database.
+
+ this.employeeRepository.save(queriedEmployeeEntity.get()); // Write, via an UPDATE, any changes to the database.
+ }
+
+ // Properties
+ private UUID employeeId;
+ public UUID getEmployeeId() {
+ return this.employeeId;
+ }
+ public EmployeeUpdateCommand setEmployeeId(final UUID employeeId) {
+ this.employeeId = employeeId;
+ return this;
+ }
+
+ private Employee apiEmployee;
+ public Employee getApiEmployee() {
+ return this.apiEmployee;
+ }
+ public EmployeeUpdateCommand setApiEmployee(final Employee apiEmployee) {
+ this.apiEmployee = apiEmployee;
+ return this;
+ }
+
+ @Autowired
+ private EmployeeRepository employeeRepository;
+}
diff --git a/src/main/java/edu/uark/registerapp/commands/employees/helpers/EmployeeHelper.java b/src/main/java/edu/uark/registerapp/commands/employees/helpers/EmployeeHelper.java
new file mode 100644
index 00000000..e6f54d73
--- /dev/null
+++ b/src/main/java/edu/uark/registerapp/commands/employees/helpers/EmployeeHelper.java
@@ -0,0 +1,34 @@
+package edu.uark.registerapp.commands.employees.helpers;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+import org.apache.commons.lang3.StringUtils;
+
+public class EmployeeHelper {
+ public static String padEmployeeId(final int employeeId) {
+ final String employeeIdAsString = Integer.toString(employeeId);
+
+ return ((employeeIdAsString.length() < EMPLOYEE_ID_MAXIMUM_LENGTH)
+ ? StringUtils.leftPad(
+ employeeIdAsString,
+ EMPLOYEE_ID_MAXIMUM_LENGTH,
+ "0")
+ : employeeIdAsString);
+ }
+
+ public static byte[] hashPassword(final String password) {
+ try {
+ final MessageDigest messageDigest =
+ MessageDigest.getInstance("SHA-256");
+
+ messageDigest.update(password.getBytes());
+
+ return messageDigest.digest();
+ } catch (final NoSuchAlgorithmException e) {
+ return new byte[0];
+ }
+ }
+
+ private static final int EMPLOYEE_ID_MAXIMUM_LENGTH = 5;
+}
diff --git a/src/main/java/edu/uark/registerapp/controllers/BaseRestController.java b/src/main/java/edu/uark/registerapp/controllers/BaseRestController.java
new file mode 100644
index 00000000..0f39f55f
--- /dev/null
+++ b/src/main/java/edu/uark/registerapp/controllers/BaseRestController.java
@@ -0,0 +1,89 @@
+package edu.uark.registerapp.controllers;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import edu.uark.registerapp.commands.activeUsers.ValidateActiveUserCommand;
+import edu.uark.registerapp.commands.exceptions.ConflictException;
+import edu.uark.registerapp.commands.exceptions.NotFoundException;
+import edu.uark.registerapp.commands.exceptions.UnauthorizedException;
+import edu.uark.registerapp.commands.exceptions.UnprocessableEntityException;
+import edu.uark.registerapp.controllers.enums.QueryParameterMessages;
+import edu.uark.registerapp.controllers.enums.QueryParameterNames;
+import edu.uark.registerapp.controllers.enums.ViewNames;
+import edu.uark.registerapp.models.api.ApiResponse;
+import edu.uark.registerapp.models.entities.ActiveUserEntity;
+import edu.uark.registerapp.models.enums.EmployeeClassification;
+
+public class BaseRestController extends BaseController {
+ protected ApiResponse redirectSessionNotActive(
+ final HttpServletResponse response
+ ) {
+
+ response.setStatus(HttpStatus.FOUND.value());
+ return (new ApiResponse())
+ .setRedirectUrl(
+ ViewNames.SIGN_IN.getRoute().concat(
+ this.buildInitialQueryParameter(
+ QueryParameterNames.ERROR_CODE.getValue(),
+ QueryParameterMessages.SESSION_NOT_ACTIVE.getKeyAsString())));
+ }
+
+ protected ApiResponse redirectUserNotElevated(
+ final HttpServletRequest request,
+ final HttpServletResponse response
+ ) {
+
+ return this.redirectUserNotElevated(request, response, ViewNames.MAIN_MENU.getRoute());
+ }
+
+ protected ApiResponse redirectUserNotElevated(
+ final HttpServletRequest request,
+ final HttpServletResponse response,
+ final String redirectRoute
+ ) {
+
+ try {
+ final ActiveUserEntity activeUserEntity =
+ this.validateActiveUserCommand
+ .setSessionKey(request.getSession().getId())
+ .execute();
+
+ if (activeUserEntity == null) {
+ return this.redirectSessionNotActive(response);
+ } else if (!EmployeeClassification.isElevatedUser(activeUserEntity.getClassification())) {
+ response.setStatus(HttpStatus.FOUND.value());
+
+ return (new ApiResponse())
+ .setRedirectUrl(
+ redirectRoute.concat(
+ this.buildInitialQueryParameter(
+ QueryParameterNames.ERROR_CODE.getValue(),
+ QueryParameterMessages.NO_PERMISSIONS_FOR_ACTION.getKeyAsString())));
+ }
+ } catch (final UnauthorizedException e) {
+ return this.redirectSessionNotActive(response);
+ }
+
+ return new ApiResponse();
+ }
+
+ @ExceptionHandler({
+ ConflictException.class,
+ NotFoundException.class,
+ UnauthorizedException.class,
+ UnprocessableEntityException.class
+ })
+ public @ResponseBody ApiResponse handleError(final Exception e) {
+ return (new ApiResponse()).setErrorMessage(e.getMessage());
+ }
+
+ // Properties
+ @Autowired
+ private ValidateActiveUserCommand validateActiveUserCommand;
+}
diff --git a/src/main/java/edu/uark/registerapp/controllers/BaseRouteController.java b/src/main/java/edu/uark/registerapp/controllers/BaseRouteController.java
new file mode 100644
index 00000000..58774f84
--- /dev/null
+++ b/src/main/java/edu/uark/registerapp/controllers/BaseRouteController.java
@@ -0,0 +1,117 @@
+package edu.uark.registerapp.controllers;
+
+import java.util.Map;
+import java.util.Optional;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.servlet.ModelAndView;
+
+import edu.uark.registerapp.commands.activeUsers.ValidateActiveUserCommand;
+import edu.uark.registerapp.commands.exceptions.UnauthorizedException;
+import edu.uark.registerapp.controllers.enums.ViewModelNames;
+import edu.uark.registerapp.controllers.enums.QueryParameterMessages;
+import edu.uark.registerapp.controllers.enums.QueryParameterNames;
+import edu.uark.registerapp.controllers.enums.ViewNames;
+import edu.uark.registerapp.models.entities.ActiveUserEntity;
+import edu.uark.registerapp.models.enums.EmployeeClassification;
+
+public abstract class BaseRouteController extends BaseController {
+ protected ModelAndView setErrorMessageFromQueryString(
+ ModelAndView modelAndView,
+ final Map queryParameters
+ ) {
+
+ if (!queryParameters.containsKey(QueryParameterNames.ERROR_CODE.getValue())) {
+ return modelAndView;
+ }
+
+ try {
+ modelAndView =
+ this.setErrorMessageFromQueryString(
+ modelAndView,
+ Integer.parseInt(
+ queryParameters.get(
+ QueryParameterNames.ERROR_CODE.getValue())));
+ } catch (final NumberFormatException e) { }
+
+ return modelAndView;
+ }
+ protected ModelAndView setErrorMessageFromQueryString(
+ final ModelAndView modelAndView,
+ final Optional errorCode
+ ) {
+
+ if (!errorCode.isPresent()) {
+ return modelAndView;
+ }
+
+ return this.setErrorMessageFromQueryString(modelAndView, errorCode.get());
+ }
+
+ protected Optional getCurrentUser(
+ final HttpServletRequest request
+ ) {
+
+ try {
+ return Optional.of(
+ this.validateActiveUserCommand
+ .setSessionKey(request.getSession().getId())
+ .execute());
+ } catch (final UnauthorizedException e) {
+ return Optional.ofNullable(null);
+ }
+ }
+
+ protected ModelAndView buildInvalidSessionResponse() {
+ return new ModelAndView(
+ REDIRECT_PREPEND.concat(
+ ViewNames.SIGN_IN.getRoute().concat(
+ this.buildInitialQueryParameter(
+ QueryParameterNames.ERROR_CODE.getValue(),
+ QueryParameterMessages.SESSION_NOT_ACTIVE.getKeyAsString()))));
+ }
+
+ protected boolean isElevatedUser(final ActiveUserEntity activeUserEntity) {
+ return EmployeeClassification.isElevatedUser(
+ activeUserEntity.getClassification());
+ }
+
+ protected ModelAndView buildNoPermissionsResponse() {
+ return this.buildNoPermissionsResponse(ViewNames.MAIN_MENU.getRoute());
+ }
+
+ protected ModelAndView buildNoPermissionsResponse(final String redirectRoute) {
+ return new ModelAndView(
+ REDIRECT_PREPEND.concat(
+ redirectRoute.concat(
+ this.buildInitialQueryParameter(
+ QueryParameterNames.ERROR_CODE.getValue(),
+ QueryParameterMessages.NO_PERMISSIONS_TO_VIEW.getKeyAsString()))));
+ }
+
+ protected static final String REDIRECT_PREPEND = "redirect:";
+
+ // Helper methods
+ private ModelAndView setErrorMessageFromQueryString(
+ final ModelAndView modelAndView,
+ final int errorCode
+ ) {
+
+ final String errorMessage = QueryParameterMessages.mapMessage(errorCode);
+
+ if (!StringUtils.isBlank(errorMessage)) {
+ modelAndView.addObject(
+ ViewModelNames.ERROR_MESSAGE.getValue(),
+ errorMessage);
+ }
+
+ return modelAndView;
+ }
+
+ // Properties
+ @Autowired
+ private ValidateActiveUserCommand validateActiveUserCommand;
+}
diff --git a/src/main/java/edu/uark/registerapp/controllers/EmployeeDetailRouteController.java b/src/main/java/edu/uark/registerapp/controllers/EmployeeDetailRouteController.java
new file mode 100644
index 00000000..01397b4c
--- /dev/null
+++ b/src/main/java/edu/uark/registerapp/controllers/EmployeeDetailRouteController.java
@@ -0,0 +1,145 @@
+package edu.uark.registerapp.controllers;
+
+import java.util.Map;
+import java.util.Optional;
+import java.util.UUID;
+
+import javax.servlet.http.HttpServletRequest;
+
+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 org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.servlet.ModelAndView;
+
+import edu.uark.registerapp.commands.employees.ActiveEmployeeExistsQuery;
+import edu.uark.registerapp.commands.employees.EmployeeQuery;
+import edu.uark.registerapp.commands.exceptions.NotFoundException;
+import edu.uark.registerapp.controllers.enums.ViewModelNames;
+import edu.uark.registerapp.controllers.enums.ViewNames;
+import edu.uark.registerapp.models.api.Employee;
+import edu.uark.registerapp.models.api.EmployeeType;
+import edu.uark.registerapp.models.entities.ActiveUserEntity;
+
+@Controller
+@RequestMapping(value = "/employeeDetail")
+public class EmployeeDetailRouteController extends BaseRouteController {
+ @RequestMapping(method = RequestMethod.GET)
+ public ModelAndView start(
+ @RequestParam final Map queryParameters,
+ final HttpServletRequest request
+ ) {
+
+ final boolean activeUserExists = this.activeUserExists();
+
+ if (activeUserExists) {
+ final Optional activeUserEntity =
+ this.getCurrentUser(request);
+
+ if (!activeUserEntity.isPresent()) {
+ return this.buildInvalidSessionResponse();
+ } else if (!this.isElevatedUser(activeUserEntity.get())) {
+ return this.buildNoPermissionsResponse();
+ }
+ }
+
+ return this.buildStartResponse(!activeUserExists, queryParameters);
+ }
+
+ @RequestMapping(value = "/{employeeId}", method = RequestMethod.GET)
+ public ModelAndView startWithEmployee(
+ @PathVariable final UUID employeeId,
+ @RequestParam final Map queryParameters,
+ final HttpServletRequest request
+ ) {
+
+ final Optional activeUserEntity =
+ this.getCurrentUser(request);
+
+ if (!activeUserEntity.isPresent()) {
+ return this.buildInvalidSessionResponse();
+ } else if (!this.isElevatedUser(activeUserEntity.get())) {
+ return this.buildNoPermissionsResponse();
+ }
+
+ return this.buildStartResponse(employeeId, queryParameters);
+ }
+
+ // Helper methods
+ private boolean activeUserExists() {
+ try {
+ this.activeEmployeeExistsQuery.execute();
+ return true;
+ } catch (final NotFoundException e) {
+ return false;
+ }
+ }
+
+ private ModelAndView buildStartResponse(
+ final boolean isInitialEmployee,
+ final Map queryParameters
+ ) {
+
+ return this.buildStartResponse(
+ isInitialEmployee,
+ (new UUID(0, 0)),
+ queryParameters);
+ }
+
+ private ModelAndView buildStartResponse(
+ final UUID employeeId,
+ final Map queryParameters
+ ) {
+
+ return this.buildStartResponse(false, employeeId, queryParameters);
+ }
+
+ private ModelAndView buildStartResponse(
+ final boolean isInitialEmployee,
+ final UUID employeeId,
+ final Map queryParameters
+ ) {
+
+ ModelAndView modelAndView =
+ this.setErrorMessageFromQueryString(
+ new ModelAndView(ViewNames.EMPLOYEE_DETAIL.getViewName()),
+ queryParameters);
+
+ if (employeeId.equals(new UUID(0, 0))) {
+ modelAndView.addObject(
+ ViewModelNames.EMPLOYEE.getValue(),
+ (new Employee()).setIsInitialEmployee(isInitialEmployee));
+ } else {
+ try {
+ modelAndView.addObject(
+ ViewModelNames.EMPLOYEE.getValue(),
+ this.employeeQuery
+ .setEmployeeId(employeeId)
+ .execute()
+ .setIsInitialEmployee(isInitialEmployee));
+ } catch (final Exception e) {
+ modelAndView.addObject(
+ ViewModelNames.ERROR_MESSAGE.getValue(),
+ e.getMessage());
+ modelAndView.addObject(
+ ViewModelNames.EMPLOYEE.getValue(),
+ (new Employee()).setIsInitialEmployee(isInitialEmployee));
+ }
+ }
+
+ modelAndView.addObject(
+ ViewModelNames.EMPLOYEE_TYPES.getValue(),
+ EmployeeType.allEmployeeTypes());
+
+ return modelAndView;
+ }
+
+ // Properties
+ @Autowired
+ private EmployeeQuery employeeQuery;
+
+ @Autowired
+ private ActiveEmployeeExistsQuery activeEmployeeExistsQuery;
+}
diff --git a/src/main/java/edu/uark/registerapp/controllers/EmployeeRestController.java b/src/main/java/edu/uark/registerapp/controllers/EmployeeRestController.java
new file mode 100644
index 00000000..f9569b14
--- /dev/null
+++ b/src/main/java/edu/uark/registerapp/controllers/EmployeeRestController.java
@@ -0,0 +1,100 @@
+package edu.uark.registerapp.controllers;
+
+import java.util.UUID;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.RestController;
+
+import edu.uark.registerapp.commands.employees.ActiveEmployeeExistsQuery;
+import edu.uark.registerapp.commands.employees.EmployeeCreateCommand;
+import edu.uark.registerapp.commands.employees.EmployeeUpdateCommand;
+import edu.uark.registerapp.commands.exceptions.NotFoundException;
+import edu.uark.registerapp.controllers.enums.QueryParameterNames;
+import edu.uark.registerapp.controllers.enums.ViewNames;
+import edu.uark.registerapp.models.api.ApiResponse;
+import edu.uark.registerapp.models.api.Employee;
+
+@RestController
+@RequestMapping(value = "/api/employee")
+public class EmployeeRestController extends BaseRestController {
+ @RequestMapping(value = "/", method = RequestMethod.POST)
+ public @ResponseBody ApiResponse createEmployee(
+ @RequestBody final Employee employee,
+ final HttpServletRequest request,
+ final HttpServletResponse response
+ ) {
+
+ boolean isInitialEmployee = false;
+ ApiResponse canCreateEmployeeResponse;
+
+ try {
+ this.activeEmployeeExistsQuery.execute();
+
+ canCreateEmployeeResponse =
+ this.redirectUserNotElevated(request, response);
+ } catch (final NotFoundException e) {
+ isInitialEmployee = true;
+ canCreateEmployeeResponse = new ApiResponse();
+ }
+
+ if (!canCreateEmployeeResponse.getRedirectUrl().equals(StringUtils.EMPTY)) {
+ return canCreateEmployeeResponse;
+ }
+
+ final Employee createdEmployee =
+ this.employeeCreateCommand
+ .setApiEmployee(employee)
+ .setIsInitialEmployee(isInitialEmployee)
+ .execute();
+
+ if (isInitialEmployee) {
+ createdEmployee
+ .setRedirectUrl(
+ ViewNames.SIGN_IN.getRoute().concat(
+ this.buildInitialQueryParameter(
+ QueryParameterNames.EMPLOYEE_ID.getValue(),
+ createdEmployee.getEmployeeId())));
+ }
+
+ return createdEmployee.setIsInitialEmployee(isInitialEmployee);
+ }
+
+ @RequestMapping(value = "/{employeeId}", method = RequestMethod.PATCH)
+ public @ResponseBody ApiResponse updateEmployee(
+ @PathVariable final UUID employeeId,
+ @RequestBody final Employee employee,
+ final HttpServletRequest request,
+ final HttpServletResponse response
+ ) {
+
+ final ApiResponse elevatedUserResponse =
+ this.redirectUserNotElevated(request, response);
+ if (!elevatedUserResponse.getRedirectUrl().equals(StringUtils.EMPTY)) {
+ return elevatedUserResponse;
+ }
+
+ return this.employeeUpdateCommand
+ .setEmployeeId(employeeId)
+ .setApiEmployee(employee)
+ .execute();
+ }
+
+ // Properties
+ @Autowired
+ private EmployeeCreateCommand employeeCreateCommand;
+
+ @Autowired
+ private EmployeeUpdateCommand employeeUpdateCommand;
+
+ @Autowired
+ private ActiveEmployeeExistsQuery activeEmployeeExistsQuery;
+}
diff --git a/src/main/java/edu/uark/registerapp/controllers/MainMenuRouteController.java b/src/main/java/edu/uark/registerapp/controllers/MainMenuRouteController.java
new file mode 100644
index 00000000..7f28f3be
--- /dev/null
+++ b/src/main/java/edu/uark/registerapp/controllers/MainMenuRouteController.java
@@ -0,0 +1,44 @@
+package edu.uark.registerapp.controllers;
+
+import java.util.Map;
+import java.util.Optional;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.servlet.ModelAndView;
+
+import edu.uark.registerapp.controllers.enums.ViewModelNames;
+import edu.uark.registerapp.controllers.enums.ViewNames;
+import edu.uark.registerapp.models.entities.ActiveUserEntity;
+
+@Controller
+@RequestMapping(value = "/mainMenu")
+public class MainMenuRouteController extends BaseRouteController {
+ @RequestMapping(method = RequestMethod.GET)
+ public ModelAndView start(
+ @RequestParam final Map queryParameters,
+ final HttpServletRequest request
+ ) {
+
+ final Optional activeUserEntity =
+ this.getCurrentUser(request);
+ if (!activeUserEntity.isPresent()) {
+ return this.buildInvalidSessionResponse();
+ }
+
+ ModelAndView modelAndView =
+ this.setErrorMessageFromQueryString(
+ new ModelAndView(ViewNames.MAIN_MENU.getViewName()),
+ queryParameters);
+
+ modelAndView.addObject(
+ ViewModelNames.IS_ELEVATED_USER.getValue(),
+ this.isElevatedUser(activeUserEntity.get()));
+
+ return modelAndView;
+ }
+}
diff --git a/src/main/java/edu/uark/registerapp/controllers/ProductDetailRouteController.java b/src/main/java/edu/uark/registerapp/controllers/ProductDetailRouteController.java
index f6f35713..f6c4edc2 100644
--- a/src/main/java/edu/uark/registerapp/controllers/ProductDetailRouteController.java
+++ b/src/main/java/edu/uark/registerapp/controllers/ProductDetailRouteController.java
@@ -1,35 +1,81 @@
package edu.uark.registerapp.controllers;
+import java.util.Map;
+import java.util.Optional;
import java.util.UUID;
+import javax.servlet.http.HttpServletRequest;
+
import org.apache.commons.lang3.StringUtils;
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 org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
import edu.uark.registerapp.commands.products.ProductQuery;
import edu.uark.registerapp.controllers.enums.ViewModelNames;
import edu.uark.registerapp.controllers.enums.ViewNames;
import edu.uark.registerapp.models.api.Product;
+import edu.uark.registerapp.models.entities.ActiveUserEntity;
+import edu.uark.registerapp.models.enums.EmployeeClassification;
@Controller
@RequestMapping(value = "/productDetail")
-public class ProductDetailRouteController {
+public class ProductDetailRouteController extends BaseRouteController {
@RequestMapping(method = RequestMethod.GET)
- public ModelAndView start() {
- return (new ModelAndView(ViewNames.PRODUCT_DETAIL.getViewName()))
- .addObject(
- ViewModelNames.PRODUCT.getValue(),
- (new Product()).setLookupCode(StringUtils.EMPTY).setCount(0));
+ public ModelAndView start(
+ @RequestParam final Map queryParameters,
+ final HttpServletRequest request
+ ) {
+ final Optional activeUserEntity =
+ this.getCurrentUser(request);
+ if (!activeUserEntity.isPresent()) {
+ return this.buildInvalidSessionResponse();
+ } else if (!this.isElevatedUser(activeUserEntity.get())) {
+ return this.buildNoPermissionsResponse(
+ ViewNames.PRODUCT_LISTING.getRoute());
+ }
+
+ final ModelAndView modelAndView =
+ this.setErrorMessageFromQueryString(
+ new ModelAndView(ViewNames.PRODUCT_DETAIL.getViewName()),
+ queryParameters);
+
+ modelAndView.addObject(
+ ViewModelNames.IS_ELEVATED_USER.getValue(),
+ true);
+ modelAndView.addObject(
+ ViewModelNames.PRODUCT.getValue(),
+ (new Product()).setLookupCode(StringUtils.EMPTY).setCount(0));
+
+ return modelAndView;
}
@RequestMapping(value = "/{productId}", method = RequestMethod.GET)
- public ModelAndView startWithProduct(@PathVariable final UUID productId) {
+ public ModelAndView startWithProduct(
+ @PathVariable final UUID productId,
+ @RequestParam final Map queryParameters,
+ final HttpServletRequest request
+ ) {
+
+ final Optional activeUserEntity =
+ this.getCurrentUser(request);
+ if (!activeUserEntity.isPresent()) {
+ return this.buildInvalidSessionResponse();
+ }
+
final ModelAndView modelAndView =
- new ModelAndView(ViewNames.PRODUCT_DETAIL.getViewName());
+ this.setErrorMessageFromQueryString(
+ new ModelAndView(ViewNames.PRODUCT_DETAIL.getViewName()),
+ queryParameters);
+
+ modelAndView.addObject(
+ ViewModelNames.IS_ELEVATED_USER.getValue(),
+ EmployeeClassification.isElevatedUser(
+ activeUserEntity.get().getClassification()));
try {
modelAndView.addObject(
diff --git a/src/main/java/edu/uark/registerapp/controllers/ProductListingRouteController.java b/src/main/java/edu/uark/registerapp/controllers/ProductListingRouteController.java
index 3c2a1178..ed9a3414 100644
--- a/src/main/java/edu/uark/registerapp/controllers/ProductListingRouteController.java
+++ b/src/main/java/edu/uark/registerapp/controllers/ProductListingRouteController.java
@@ -1,23 +1,46 @@
package edu.uark.registerapp.controllers;
+import java.util.Map;
+import java.util.Optional;
+
+import javax.servlet.http.HttpServletRequest;
+
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
import edu.uark.registerapp.commands.products.ProductsQuery;
import edu.uark.registerapp.controllers.enums.ViewModelNames;
import edu.uark.registerapp.controllers.enums.ViewNames;
import edu.uark.registerapp.models.api.Product;
+import edu.uark.registerapp.models.entities.ActiveUserEntity;
@Controller
-@RequestMapping(value = "/")
-public class ProductListingRouteController {
+@RequestMapping(value = "/productListing")
+public class ProductListingRouteController extends BaseRouteController {
@RequestMapping(method = RequestMethod.GET)
- public ModelAndView showProductListing() {
+ public ModelAndView showProductListing(
+ @RequestParam final Map queryParameters,
+ final HttpServletRequest request
+ ) {
+
+ final Optional activeUserEntity =
+ this.getCurrentUser(request);
+ if (!activeUserEntity.isPresent()) {
+ return buildInvalidSessionResponse();
+ }
+
ModelAndView modelAndView =
- new ModelAndView(ViewNames.PRODUCT_LISTING.getViewName());
+ this.setErrorMessageFromQueryString(
+ new ModelAndView(ViewNames.PRODUCT_LISTING.getViewName()),
+ queryParameters);
+
+ modelAndView.addObject(
+ ViewModelNames.IS_ELEVATED_USER.getValue(),
+ this.isElevatedUser(activeUserEntity.get()));
try {
modelAndView.addObject(
diff --git a/src/main/java/edu/uark/registerapp/controllers/ProductRestController.java b/src/main/java/edu/uark/registerapp/controllers/ProductRestController.java
index 0c6c5f62..9f1be30f 100644
--- a/src/main/java/edu/uark/registerapp/controllers/ProductRestController.java
+++ b/src/main/java/edu/uark/registerapp/controllers/ProductRestController.java
@@ -2,6 +2,10 @@
import java.util.UUID;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
@@ -13,17 +17,30 @@
import edu.uark.registerapp.commands.products.ProductCreateCommand;
import edu.uark.registerapp.commands.products.ProductDeleteCommand;
import edu.uark.registerapp.commands.products.ProductUpdateCommand;
+import edu.uark.registerapp.controllers.enums.ViewNames;
import edu.uark.registerapp.models.api.ApiResponse;
import edu.uark.registerapp.models.api.Product;
@RestController
@RequestMapping(value = "/api/product")
-public class ProductRestController {
+public class ProductRestController extends BaseRestController {
@RequestMapping(value = "/", method = RequestMethod.POST)
public @ResponseBody ApiResponse createProduct(
- @RequestBody final Product product
+ @RequestBody final Product product,
+ final HttpServletRequest request,
+ final HttpServletResponse response
) {
+ final ApiResponse elevatedUserResponse =
+ this.redirectUserNotElevated(
+ request,
+ response,
+ ViewNames.PRODUCT_LISTING.getRoute());
+
+ if (!elevatedUserResponse.getRedirectUrl().equals(StringUtils.EMPTY)) {
+ return elevatedUserResponse;
+ }
+
return this.productCreateCommand
.setApiProduct(product)
.execute();
@@ -32,9 +49,21 @@ public class ProductRestController {
@RequestMapping(value = "/{productId}", method = RequestMethod.PUT)
public @ResponseBody ApiResponse updateProduct(
@PathVariable final UUID productId,
- @RequestBody final Product product
+ @RequestBody final Product product,
+ final HttpServletRequest request,
+ final HttpServletResponse response
) {
+ final ApiResponse elevatedUserResponse =
+ this.redirectUserNotElevated(
+ request,
+ response,
+ ViewNames.PRODUCT_LISTING.getRoute());
+
+ if (!elevatedUserResponse.getRedirectUrl().equals(StringUtils.EMPTY)) {
+ return elevatedUserResponse;
+ }
+
return this.productUpdateCommand
.setProductId(productId)
.setApiProduct(product)
@@ -43,9 +72,21 @@ public class ProductRestController {
@RequestMapping(value = "/{productId}", method = RequestMethod.DELETE)
public @ResponseBody ApiResponse deleteProduct(
- @PathVariable final UUID productId
+ @PathVariable final UUID productId,
+ final HttpServletRequest request,
+ final HttpServletResponse response
) {
+ final ApiResponse elevatedUserResponse =
+ this.redirectUserNotElevated(
+ request,
+ response,
+ ViewNames.PRODUCT_LISTING.getRoute());
+
+ if (!elevatedUserResponse.getRedirectUrl().equals(StringUtils.EMPTY)) {
+ return elevatedUserResponse;
+ }
+
this.productDeleteCommand
.setProductId(productId)
.execute();
diff --git a/src/main/java/edu/uark/registerapp/controllers/SignInRestController.java b/src/main/java/edu/uark/registerapp/controllers/SignInRestController.java
new file mode 100644
index 00000000..8ec7ef25
--- /dev/null
+++ b/src/main/java/edu/uark/registerapp/controllers/SignInRestController.java
@@ -0,0 +1,34 @@
+package edu.uark.registerapp.controllers;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.RestController;
+
+import edu.uark.registerapp.commands.activeUsers.ActiveUserDeleteCommand;
+import edu.uark.registerapp.controllers.enums.ViewNames;
+import edu.uark.registerapp.models.api.ApiResponse;
+
+@RestController
+@RequestMapping(value = "/api")
+public class SignInRestController extends BaseRestController {
+ @RequestMapping(value="/signOut", method = RequestMethod.DELETE)
+ public @ResponseBody ApiResponse removeActiveUser(
+ final HttpServletRequest request
+ ) {
+
+ this.activeUserDeleteCommand
+ .setSessionKey(request.getSession().getId())
+ .execute();
+
+ return (new ApiResponse())
+ .setRedirectUrl(ViewNames.SIGN_IN.getRoute());
+ }
+
+ // Properties
+ @Autowired
+ private ActiveUserDeleteCommand activeUserDeleteCommand;
+}
diff --git a/src/main/java/edu/uark/registerapp/controllers/SignInRouteController.java b/src/main/java/edu/uark/registerapp/controllers/SignInRouteController.java
new file mode 100644
index 00000000..749ace20
--- /dev/null
+++ b/src/main/java/edu/uark/registerapp/controllers/SignInRouteController.java
@@ -0,0 +1,89 @@
+package edu.uark.registerapp.controllers;
+
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.MediaType;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.servlet.ModelAndView;
+
+import edu.uark.registerapp.commands.employees.ActiveEmployeeExistsQuery;
+import edu.uark.registerapp.commands.employees.EmployeeSignInCommand;
+import edu.uark.registerapp.commands.exceptions.NotFoundException;
+import edu.uark.registerapp.controllers.enums.QueryParameterNames;
+import edu.uark.registerapp.controllers.enums.ViewModelNames;
+import edu.uark.registerapp.controllers.enums.ViewNames;
+import edu.uark.registerapp.models.api.EmployeeSignIn;
+
+@Controller
+@RequestMapping(value = "/")
+public class SignInRouteController extends BaseRouteController {
+ @RequestMapping(method = RequestMethod.GET)
+ public ModelAndView showSignIn(
+ @RequestParam final Map queryParameters
+ ) {
+
+ try {
+ this.activeEmployeeExistsQuery.execute();
+ } catch (NotFoundException e) {
+ return new ModelAndView(
+ REDIRECT_PREPEND.concat(
+ ViewNames.EMPLOYEE_DETAIL.getRoute()));
+ }
+
+ ModelAndView modelAndView =
+ this.setErrorMessageFromQueryString(
+ new ModelAndView(ViewNames.SIGN_IN.getViewName()),
+ queryParameters);
+
+ if (queryParameters.containsKey(QueryParameterNames.EMPLOYEE_ID.getValue())) {
+ modelAndView.addObject(
+ ViewModelNames.EMPLOYEE_ID.getValue(),
+ queryParameters.get(QueryParameterNames.EMPLOYEE_ID.getValue()));
+ }
+
+ return modelAndView;
+ }
+
+ @RequestMapping(method = RequestMethod.POST, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
+ public ModelAndView performSignIn(
+ EmployeeSignIn employeeSignIn,
+ HttpServletRequest request
+ ) {
+
+ try {
+ this.employeeSignInCommand
+ .setSessionId(request.getSession().getId())
+ .setEmployeeSignIn(employeeSignIn)
+ .execute();
+ } catch (Exception e) {
+ ModelAndView modelAndView =
+ new ModelAndView(ViewNames.SIGN_IN.getViewName());
+
+ modelAndView.addObject(
+ ViewModelNames.ERROR_MESSAGE.getValue(),
+ e.getMessage());
+ modelAndView.addObject(
+ ViewModelNames.EMPLOYEE_ID.getValue(),
+ employeeSignIn.getEmployeeId());
+
+ return modelAndView;
+ }
+
+ return new ModelAndView(
+ REDIRECT_PREPEND.concat(
+ ViewNames.MAIN_MENU.getRoute()));
+ }
+
+ // Properties
+ @Autowired
+ private EmployeeSignInCommand employeeSignInCommand;
+
+ @Autowired
+ private ActiveEmployeeExistsQuery activeEmployeeExistsQuery;
+}
diff --git a/src/main/java/edu/uark/registerapp/controllers/enums/QueryParameterMessages.java b/src/main/java/edu/uark/registerapp/controllers/enums/QueryParameterMessages.java
new file mode 100644
index 00000000..3f1bed87
--- /dev/null
+++ b/src/main/java/edu/uark/registerapp/controllers/enums/QueryParameterMessages.java
@@ -0,0 +1,45 @@
+package edu.uark.registerapp.controllers.enums;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public enum QueryParameterMessages {
+ NOT_DEFINED(-1, ""),
+ SESSION_NOT_ACTIVE(1001, "The current user's session is no longer active."),
+ NO_PERMISSIONS_TO_VIEW(1101, "You do not have permission to view this resource."),
+ NO_PERMISSIONS_FOR_ACTION(1102, "You do not have permission to perform this action.");
+
+ public int getKey() {
+ return this.key;
+ }
+ public String getKeyAsString() {
+ return Integer.toString(this.key);
+ }
+ public String getMessage() {
+ return this.message;
+ }
+
+ public static String mapMessage(final int key) {
+ if (valueMap == null) {
+ valueMap = new HashMap();
+
+ for (final QueryParameterMessages status : QueryParameterMessages.values()) {
+ valueMap.put(status.getKey(), status.getMessage());
+ }
+ }
+
+ return (valueMap.containsKey(key)
+ ? valueMap.get(key)
+ : QueryParameterMessages.NOT_DEFINED.getMessage());
+ }
+
+ private int key;
+ private String message;
+
+ private static Map valueMap = null;
+
+ private QueryParameterMessages(final int key, final String message) {
+ this.key = key;
+ this.message = message;
+ }
+}
diff --git a/src/main/java/edu/uark/registerapp/controllers/enums/QueryParameterNames.java b/src/main/java/edu/uark/registerapp/controllers/enums/QueryParameterNames.java
index 988a9c79..d20b0100 100644
--- a/src/main/java/edu/uark/registerapp/controllers/enums/QueryParameterNames.java
+++ b/src/main/java/edu/uark/registerapp/controllers/enums/QueryParameterNames.java
@@ -2,7 +2,8 @@
public enum QueryParameterNames {
NOT_DEFINED(""),
- ERROR_CODE("errorCode");
+ ERROR_CODE("errorCode"),
+ EMPLOYEE_ID("employeeId");
public String getValue() {
return value;
diff --git a/src/main/java/edu/uark/registerapp/controllers/enums/ViewModelNames.java b/src/main/java/edu/uark/registerapp/controllers/enums/ViewModelNames.java
index 7c39b102..fefde2fd 100644
--- a/src/main/java/edu/uark/registerapp/controllers/enums/ViewModelNames.java
+++ b/src/main/java/edu/uark/registerapp/controllers/enums/ViewModelNames.java
@@ -3,8 +3,12 @@
public enum ViewModelNames {
NOT_DEFINED(""),
ERROR_MESSAGE("errorMessage"),
+ IS_ELEVATED_USER("isElevatedUser"),
PRODUCTS("products"), // Product listing
- PRODUCT("product"); // Product detail
+ PRODUCT("product"), // Product detail
+ EMPLOYEE_ID("employeeId"), // Sign in
+ EMPLOYEE("employee"), // Employee detail
+ EMPLOYEE_TYPES("employeeTypes");
public String getValue() {
return value;
diff --git a/src/main/java/edu/uark/registerapp/controllers/enums/ViewNames.java b/src/main/java/edu/uark/registerapp/controllers/enums/ViewNames.java
index cd1a1246..3e3e2ca2 100644
--- a/src/main/java/edu/uark/registerapp/controllers/enums/ViewNames.java
+++ b/src/main/java/edu/uark/registerapp/controllers/enums/ViewNames.java
@@ -1,8 +1,11 @@
package edu.uark.registerapp.controllers.enums;
public enum ViewNames {
+ SIGN_IN("signIn", "/"),
+ MAIN_MENU("mainMenu"),
PRODUCT_DETAIL("productDetail"),
- PRODUCT_LISTING("productListing", "/");
+ EMPLOYEE_DETAIL("employeeDetail"),
+ PRODUCT_LISTING("productListing");
public String getRoute() {
return this.route;
diff --git a/src/main/java/edu/uark/registerapp/models/api/Employee.java b/src/main/java/edu/uark/registerapp/models/api/Employee.java
new file mode 100644
index 00000000..6e313bfc
--- /dev/null
+++ b/src/main/java/edu/uark/registerapp/models/api/Employee.java
@@ -0,0 +1,145 @@
+package edu.uark.registerapp.models.api;
+
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.UUID;
+
+import org.apache.commons.lang3.StringUtils;
+
+import edu.uark.registerapp.commands.employees.helpers.EmployeeHelper;
+import edu.uark.registerapp.models.entities.EmployeeEntity;
+
+public class Employee extends ApiResponse {
+ private UUID id;
+ public UUID getId() {
+ return this.id;
+ }
+ public Employee setId(final UUID id) {
+ this.id = id;
+ return this;
+ }
+
+ private String employeeId;
+ public String getEmployeeId() {
+ return this.employeeId;
+ }
+ public Employee setEmployeeId(final int employeeId) {
+ this.employeeId = EmployeeHelper.padEmployeeId(employeeId);
+ return this;
+ }
+ public Employee setEmployeeId(final String employeeId) {
+ this.employeeId = employeeId;
+ return this;
+ }
+
+ private String firstName;
+ public String getFirstName() {
+ return this.firstName;
+ }
+ public Employee setFirstName(final String firstName) {
+ this.firstName = firstName;
+ return this;
+ }
+
+ private String lastName;
+ public String getLastName() {
+ return this.lastName;
+ }
+ public Employee setLastName(final String lastName) {
+ this.lastName = lastName;
+ return this;
+ }
+
+ private String password;
+ public String getPassword() {
+ return this.password;
+ }
+ public Employee setPassword(final String password) {
+ this.password = password;
+ return this;
+ }
+
+ private boolean isActive;
+ public boolean getIsActive() {
+ return this.isActive;
+ }
+ public Employee setIsActive(final boolean isActive) {
+ this.isActive = isActive;
+ return this;
+ }
+
+ private int classification;
+ public int getClassification() {
+ return this.classification;
+ }
+ public Employee setClassification(final int classification) {
+ this.classification = classification;
+ return this;
+ }
+
+ private UUID managerId;
+ public UUID getManagerId() {
+ return this.managerId;
+ }
+ public Employee setManagerId(final UUID managerId) {
+ this.managerId = managerId;
+ return this;
+ }
+
+ private String createdOn;
+ public String getCreatedOn() {
+ return this.createdOn;
+ }
+ public Employee setCreatedOn(final String createdOn) {
+ this.createdOn = createdOn;
+ return this;
+ }
+ public Employee setCreatedOn(final LocalDateTime createdOn) {
+ this.createdOn =
+ createdOn.format(DateTimeFormatter.ofPattern("MM/dd/yyyy"));
+
+ return this;
+ }
+
+ private boolean isInitialEmployee;
+ public boolean getIsInitialEmployee() {
+ return this.isInitialEmployee;
+ }
+ public Employee setIsInitialEmployee(final boolean isInitialEmployee) {
+ this.isInitialEmployee = isInitialEmployee;
+ return this;
+ }
+
+ public Employee() {
+ super();
+
+ this.isActive = true;
+ this.id = new UUID(0, 0);
+ this.classification = -1;
+ this.isInitialEmployee = false;
+ this.managerId = new UUID(0, 0);
+ this.lastName = StringUtils.EMPTY;
+ this.password = StringUtils.EMPTY;
+ this.firstName = StringUtils.EMPTY;
+ this.employeeId = StringUtils.EMPTY;
+
+ this.setCreatedOn(LocalDateTime.now());
+ }
+
+ public Employee(final EmployeeEntity employeeEntity) {
+ super(false);
+
+ this.isInitialEmployee = false;
+ this.id = employeeEntity.getId();
+ this.password = StringUtils.EMPTY;
+ this.isActive = employeeEntity.getIsActive();
+ this.lastName = employeeEntity.getLastName();
+ this.firstName = employeeEntity.getFirstName();
+ this.managerId = employeeEntity.getManagerId();
+ this.classification = employeeEntity.getClassification();
+ this.employeeId =
+ EmployeeHelper.padEmployeeId(employeeEntity.getEmployeeId());
+
+ this.setCreatedOn(employeeEntity.getCreatedOn());
+ }
+}
diff --git a/src/main/java/edu/uark/registerapp/models/api/EmployeeSignIn.java b/src/main/java/edu/uark/registerapp/models/api/EmployeeSignIn.java
new file mode 100644
index 00000000..e01e4f6c
--- /dev/null
+++ b/src/main/java/edu/uark/registerapp/models/api/EmployeeSignIn.java
@@ -0,0 +1,28 @@
+package edu.uark.registerapp.models.api;
+
+import org.apache.commons.lang3.StringUtils;
+
+public class EmployeeSignIn {
+ private String employeeId;
+ public String getEmployeeId() {
+ return this.employeeId;
+ }
+ public EmployeeSignIn setEmployeeId(final String employeeId) {
+ this.employeeId = employeeId;
+ return this;
+ }
+
+ private String password;
+ public String getPassword() {
+ return this.password;
+ }
+ public EmployeeSignIn setPassword(final String password) {
+ this.password = password;
+ return this;
+ }
+
+ public EmployeeSignIn() {
+ this.password = StringUtils.EMPTY;
+ this.employeeId = StringUtils.EMPTY;
+ }
+}
diff --git a/src/main/java/edu/uark/registerapp/models/api/EmployeeType.java b/src/main/java/edu/uark/registerapp/models/api/EmployeeType.java
new file mode 100644
index 00000000..fa9e8421
--- /dev/null
+++ b/src/main/java/edu/uark/registerapp/models/api/EmployeeType.java
@@ -0,0 +1,55 @@
+package edu.uark.registerapp.models.api;
+
+import org.apache.commons.lang3.StringUtils;
+
+import edu.uark.registerapp.models.enums.EmployeeClassification;
+
+public class EmployeeType {
+ private int classification;
+ public int getClassification() {
+ return this.classification;
+ }
+ public EmployeeType setClassification(final int classification) {
+ this.classification = classification;
+ return this;
+ }
+
+ private String displayLabel;
+
+ public String getDisplayLabel() {
+ return this.displayLabel;
+ }
+
+ public EmployeeType setDisplayLabel(final String displayLabel) {
+ this.displayLabel = displayLabel;
+ return this;
+ }
+
+ public static EmployeeType[] allEmployeeTypes() {
+ final EmployeeClassification[] employeeClassifications =
+ EmployeeClassification.values();
+ final EmployeeType[] employeeTypes =
+ new EmployeeType[employeeClassifications.length];
+
+ for (int i = 0; i < employeeClassifications.length; i++) {
+ employeeTypes[i] = new EmployeeType(employeeClassifications[i]);
+ }
+
+ return employeeTypes;
+ }
+
+ public EmployeeType() {
+ this(-1, StringUtils.EMPTY);
+ }
+
+ public EmployeeType(final EmployeeClassification employeeClassification) {
+ this(
+ employeeClassification.getClassification(),
+ employeeClassification.getDisplayLabel());
+ }
+
+ public EmployeeType(final int classification, final String displayLabel) {
+ this.displayLabel = displayLabel;
+ this.classification = classification;
+ }
+}
diff --git a/src/main/java/edu/uark/registerapp/models/entities/ActiveUserEntity.java b/src/main/java/edu/uark/registerapp/models/entities/ActiveUserEntity.java
new file mode 100644
index 00000000..6eba3528
--- /dev/null
+++ b/src/main/java/edu/uark/registerapp/models/entities/ActiveUserEntity.java
@@ -0,0 +1,91 @@
+package edu.uark.registerapp.models.entities;
+
+import java.time.LocalDateTime;
+import java.util.UUID;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+import org.apache.commons.lang3.StringUtils;
+import org.hibernate.annotations.Generated;
+import org.hibernate.annotations.GenerationTime;
+
+@Entity
+@Table(name="activeuser")
+public class ActiveUserEntity {
+ @Id
+ @Column(name="id", updatable = false)
+ @GeneratedValue(strategy=GenerationType.AUTO)
+ private final UUID id;
+
+ public UUID getId() {
+ return this.id;
+ }
+
+ @Column(name = "employeeid")
+ private UUID employeeId;
+
+ public UUID getEmployeeId() {
+ return this.employeeId;
+ }
+
+ public ActiveUserEntity setEmployeeId(final UUID employeeId) {
+ this.employeeId = employeeId;
+ return this;
+ }
+
+ @Column(name = "name")
+ private String name;
+
+ public String getName() {
+ return this.name;
+ }
+
+ public ActiveUserEntity setName(final String name) {
+ this.name = name;
+ return this;
+ }
+
+ @Column(name = "classification")
+ private int classification;
+
+ public int getClassification() {
+ return this.classification;
+ }
+
+ public ActiveUserEntity setClassification(final int classification) {
+ this.classification = classification;
+ return this;
+ }
+
+ @Column(name = "sessionkey")
+ private String sessionKey;
+
+ public String getSessionKey() {
+ return this.sessionKey;
+ }
+
+ public ActiveUserEntity setSessionKey(final String sessionKey) {
+ this.sessionKey = sessionKey;
+ return this;
+ }
+
+ @Column(name="createdon", insertable=false, updatable = false)
+ @Generated(GenerationTime.INSERT)
+ private LocalDateTime createdOn;
+ public LocalDateTime getCreatedOn() {
+ return this.createdOn;
+ }
+
+ public ActiveUserEntity() {
+ this.id = new UUID(0, 0);
+ this.classification = -1;
+ this.name = StringUtils.EMPTY;
+ this.employeeId = new UUID(0, 0);
+ this.sessionKey = StringUtils.EMPTY;
+ }
+}
diff --git a/src/main/java/edu/uark/registerapp/models/entities/EmployeeEntity.java b/src/main/java/edu/uark/registerapp/models/entities/EmployeeEntity.java
new file mode 100644
index 00000000..324e5b31
--- /dev/null
+++ b/src/main/java/edu/uark/registerapp/models/entities/EmployeeEntity.java
@@ -0,0 +1,164 @@
+package edu.uark.registerapp.models.entities;
+
+import java.time.LocalDateTime;
+import java.util.UUID;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+import org.apache.commons.lang3.StringUtils;
+import org.hibernate.annotations.Generated;
+import org.hibernate.annotations.GenerationTime;
+
+import edu.uark.registerapp.commands.employees.helpers.EmployeeHelper;
+import edu.uark.registerapp.models.api.Employee;
+
+@Entity
+@Table(name="employee")
+public class EmployeeEntity {
+ @Id
+ @Column(name="id", updatable = false)
+ @GeneratedValue(strategy=GenerationType.AUTO)
+ private final UUID id;
+
+ public UUID getId() {
+ return this.id;
+ }
+
+ @Column(name = "employeeid", insertable = false, updatable = false)
+ @Generated(GenerationTime.INSERT)
+ private int employeeId;
+
+ public int getEmployeeId() {
+ return this.employeeId;
+ }
+
+ @Column(name = "firstname")
+ private String firstName;
+
+ public String getFirstName() {
+ return this.firstName;
+ }
+
+ public EmployeeEntity setFirstName(final String firstName) {
+ this.firstName = firstName;
+ return this;
+ }
+
+ @Column(name = "lastname")
+ private String lastName;
+
+ public String getLastName() {
+ return this.lastName;
+ }
+
+ public EmployeeEntity setLastName(final String lastName) {
+ this.lastName = lastName;
+ return this;
+ }
+
+ @Column(name = "password")
+ private byte[] password;
+
+ public byte[] getPassword() {
+ return this.password;
+ }
+
+ public EmployeeEntity setPassword(final byte[] password) {
+ this.password = password;
+ return this;
+ }
+
+ @Column(name = "active")
+ private boolean isActive;
+
+ public boolean getIsActive() {
+ return this.isActive;
+ }
+
+ public EmployeeEntity setIsActive(final boolean isActive) {
+ this.isActive = isActive;
+ return this;
+ }
+
+ @Column(name = "classification")
+ private int classification;
+
+ public int getClassification() {
+ return this.classification;
+ }
+
+ public EmployeeEntity setClassification(final int classification) {
+ this.classification = classification;
+ return this;
+ }
+
+ @Column(name = "managerid")
+ private UUID managerId;
+
+ public UUID getManagerId() {
+ return this.managerId;
+ }
+
+ public EmployeeEntity setManagerId(final UUID managerId) {
+ this.managerId = managerId;
+ return this;
+ }
+
+ @Column(name = "createdon", insertable = false, updatable = false)
+ @Generated(GenerationTime.INSERT)
+ private LocalDateTime createdOn;
+
+ public LocalDateTime getCreatedOn() {
+ return this.createdOn;
+ }
+
+ public Employee synchronize(final Employee apiEmployee) {
+ this.setIsActive(apiEmployee.getIsActive());
+ this.setLastName(apiEmployee.getLastName());
+ this.setFirstName(apiEmployee.getFirstName());
+ this.setClassification(apiEmployee.getClassification());
+ if (apiEmployee.getManagerId() != null) {
+ this.setManagerId(apiEmployee.getManagerId());
+ }
+ if (!StringUtils.isBlank(apiEmployee.getPassword())) {
+ this.setPassword(
+ EmployeeHelper.hashPassword(
+ apiEmployee.getPassword()));
+ }
+
+ apiEmployee.setId(this.getId());
+ apiEmployee.setCreatedOn(this.getCreatedOn());
+ apiEmployee.setEmployeeId(this.getEmployeeId());
+
+ return apiEmployee;
+ }
+
+ public EmployeeEntity() {
+ this.employeeId = -1;
+ this.isActive = false;
+ this.id = new UUID(0, 0);
+ this.classification = -1;
+ this.password = new byte[0];
+ this.managerId = new UUID(0, 0);
+ this.lastName = StringUtils.EMPTY;
+ this.firstName = StringUtils.EMPTY;
+ }
+
+ public EmployeeEntity(final Employee apiEmployee) {
+ this.id = new UUID(0, 0);
+ this.isActive = apiEmployee.getIsActive();
+ this.lastName = apiEmployee.getLastName();
+ this.firstName = apiEmployee.getFirstName();
+ this.classification = apiEmployee.getClassification();
+ this.password = EmployeeHelper.hashPassword(apiEmployee.getPassword());
+ this.managerId = (
+ (apiEmployee.getManagerId() != null)
+ ? apiEmployee.getManagerId()
+ : new UUID(0, 0));
+ }
+}
diff --git a/src/main/java/edu/uark/registerapp/models/enums/EmployeeClassification.java b/src/main/java/edu/uark/registerapp/models/enums/EmployeeClassification.java
new file mode 100644
index 00000000..751c80ef
--- /dev/null
+++ b/src/main/java/edu/uark/registerapp/models/enums/EmployeeClassification.java
@@ -0,0 +1,58 @@
+package edu.uark.registerapp.models.enums;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public enum EmployeeClassification {
+ NOT_DEFINED(-1, "Not Selected"),
+ CASHIER(101, "Cashier"),
+ SHIFT_MANAGER(501, "Shift Manager"),
+ GENERAL_MANAGER(701, "General Manager");
+
+ public int getClassification() {
+ return this.classification;
+ }
+
+ public String getDisplayLabel() {
+ return this.displayLabel;
+ }
+
+ public static EmployeeClassification map(final int key) {
+ if (valueMap == null) {
+ valueMap = new HashMap();
+
+ for (final EmployeeClassification employeeClassification : EmployeeClassification.values()) {
+ valueMap.put(
+ employeeClassification.getClassification(),
+ employeeClassification);
+ }
+ }
+
+ return ((valueMap.containsKey(key)
+ ? valueMap.get(key)
+ : EmployeeClassification.NOT_DEFINED));
+ }
+
+ public static boolean isElevatedUser(final int classification) {
+ final EmployeeClassification employeeClassification =
+ EmployeeClassification.map(classification);
+
+ return (
+ (employeeClassification == EmployeeClassification.GENERAL_MANAGER)
+ || (employeeClassification == EmployeeClassification.SHIFT_MANAGER));
+ }
+
+ private int classification;
+ private String displayLabel;
+
+ private static Map valueMap = null;
+
+ private EmployeeClassification(
+ final int classification,
+ final String displayLabel
+ ) {
+
+ this.displayLabel = displayLabel;
+ this.classification = classification;
+ }
+}
diff --git a/src/main/java/edu/uark/registerapp/models/repositories/ActiveUserRepository.java b/src/main/java/edu/uark/registerapp/models/repositories/ActiveUserRepository.java
new file mode 100644
index 00000000..53746cee
--- /dev/null
+++ b/src/main/java/edu/uark/registerapp/models/repositories/ActiveUserRepository.java
@@ -0,0 +1,13 @@
+package edu.uark.registerapp.models.repositories;
+
+import java.util.Optional;
+import java.util.UUID;
+
+import org.springframework.data.repository.CrudRepository;
+
+import edu.uark.registerapp.models.entities.ActiveUserEntity;
+
+public interface ActiveUserRepository extends CrudRepository {
+ Optional findByEmployeeId(UUID employeeId);
+ Optional findBySessionKey(String sessionKey);
+}
diff --git a/src/main/java/edu/uark/registerapp/models/repositories/EmployeeRepository.java b/src/main/java/edu/uark/registerapp/models/repositories/EmployeeRepository.java
new file mode 100644
index 00000000..8ba4b81f
--- /dev/null
+++ b/src/main/java/edu/uark/registerapp/models/repositories/EmployeeRepository.java
@@ -0,0 +1,15 @@
+package edu.uark.registerapp.models.repositories;
+
+import java.util.Optional;
+import java.util.UUID;
+
+import org.springframework.data.repository.CrudRepository;
+
+import edu.uark.registerapp.models.entities.EmployeeEntity;
+
+public interface EmployeeRepository extends CrudRepository {
+ boolean existsByIsActive(boolean isActive);
+ boolean existsByEmployeeId(int employeeId);
+ Optional findById(UUID id);
+ Optional findByEmployeeId(int employeeId);
+}
diff --git a/src/main/resources/static/images/Sign-Out.png b/src/main/resources/static/images/Sign-Out.png
new file mode 100644
index 0000000000000000000000000000000000000000..82fe8695ab00a4cdbd2b3f95f065fd7acbd108ec
GIT binary patch
literal 417
zcmV;S0bc%zP)7GIp>_a(3m+}_QaKE&z3o3q#8Dyh{QRup`m9ZI--K<7}2X0QOT_6(UfB~
zfFo0iTM!k^g5q{n0XmBNtqSl%ad9?U37>C(0R|XgKr-NscF2HNf}kBL;Dz{~wmv|?
zI=>#2+PS61|;Y%W<1K>^~fyX^@&QOFD-2!R*p^-#O=;bI$z%Lh{J>>1jl;00000
LNkvXXu0mjf0)eri
literal 0
HcmV?d00001
diff --git a/src/main/resources/static/scripts/employeeDetail.js b/src/main/resources/static/scripts/employeeDetail.js
new file mode 100644
index 00000000..b5d7d2f8
--- /dev/null
+++ b/src/main/resources/static/scripts/employeeDetail.js
@@ -0,0 +1,184 @@
+let hideEmployeeSavedAlertTimer = undefined;
+
+document.addEventListener("DOMContentLoaded", () => {
+ document.getElementById("saveButton")
+ .addEventListener("click", saveActionClick);
+
+ const employeeFirstNameEditElement =
+ getEmployeeFirstNameEditElement();
+ employeeFirstNameEditElement.focus();
+ employeeFirstNameEditElement.select();
+});
+
+// Save
+function saveActionClick(event) {
+ if (!validateSave()) {
+ return;
+ }
+
+ const saveActionElement = event.target;
+ saveActionElement.disabled = true;
+
+ const employeeId = getEmployeeId();
+ const employeeIdIsDefined = (employeeId.trim() !== "");
+ const saveActionUrl = ("/api/employee/"
+ + (employeeIdIsDefined ? employeeId : ""));
+ const saveEmployeeRequest = {
+ id: employeeId,
+ managerId: getEmployeeManagerId(),
+ lastName: getEmployeeLastNameEditElement().value,
+ password: getEmployeePasswordEditElement().value,
+ firstName: getEmployeeFirstNameEditElement().value,
+ classification: getEmployeeTypeSelectElement().value
+ };
+
+ if (employeeIdIsDefined) {
+ ajaxPatch(saveActionUrl, saveEmployeeRequest, (callbackResponse) => {
+ saveActionElement.disabled = false;
+
+ if (isSuccessResponse(callbackResponse)) {
+ completeSaveAction(callbackResponse);
+ }
+ });
+ } else {
+ ajaxPost(saveActionUrl, saveEmployeeRequest, (callbackResponse) => {
+ saveActionElement.disabled = false;
+
+ if (isSuccessResponse(callbackResponse)) {
+ completeSaveAction(callbackResponse);
+ }
+ });
+ }
+}
+
+function validateSave() {
+ const firstNameEditElement = getEmployeeFirstNameEditElement();
+ if (firstNameEditElement.value.trim() === "") {
+ displayError("Please provide a valid employee first name.");
+ firstNameEditElement.focus();
+ firstNameEditElement.select();
+ return false;
+ }
+
+ const lastNameEditElement = getEmployeeLastNameEditElement();
+ if (lastNameEditElement.value.trim() === "") {
+ displayError("Please provide a valid employee last name.");
+ lastNameEditElement.focus();
+ lastNameEditElement.select();
+ return false;
+ }
+
+ const passwordEditElement = getEmployeePasswordEditElement();
+ if (passwordEditElement.value.trim() === "") {
+ displayError("Please provide a valid employee password.");
+ passwordEditElement.focus();
+ passwordEditElement.select();
+ return false;
+ }
+
+ if (passwordEditElement.value !== getEmployeeConfirmPassword()) {
+ displayError("Passwords do not match.");
+ passwordEditElement.focus()
+ passwordEditElement.select();
+ return false;
+ }
+
+ const employeeTypeSelectElement = getEmployeeTypeSelectElement();
+ if (!employeeTypeSelectElement.closest("tr").classList.contains("hidden")) {
+ if (employeeTypeSelectElement.value <= 0) {
+ displayError("Please provide a valid employee Type.");
+ employeeTypeSelectElement.focus();
+ return false;
+ }
+ }
+
+ return true;
+}
+
+function completeSaveAction(callbackResponse) {
+ if (callbackResponse.data == null) {
+ return;
+ }
+
+ if ((callbackResponse.data.redirectUrl != null)
+ && (callbackResponse.data.redirectUrl !== "")) {
+
+ window.location.replace(callbackResponse.data.redirectUrl);
+ return;
+ }
+
+ displayEmployeeSavedAlertModal();
+
+ const employeeEmployeeIdElement = getEmployeeEmployeeIdElement();
+ const employeeEmployeeIdRowElement = employeeEmployeeIdElement.closest("tr");
+ if (employeeEmployeeIdRowElement.classList.contains("hidden")) {
+ setEmployeeId(callbackResponse.data.id);
+ employeeEmployeeIdElement.value = callbackResponse.data.employeeId;
+ employeeEmployeeIdRowElement.classList.remove("hidden");
+ }
+}
+
+function displayEmployeeSavedAlertModal() {
+ if (hideEmployeeSavedAlertTimer) {
+ clearTimeout(hideEmployeeSavedAlertTimer);
+ }
+
+ const savedAlertModalElement = getSavedAlertModalElement();
+ savedAlertModalElement.style.display = "none";
+ savedAlertModalElement.style.display = "block";
+
+ hideEmployeeSavedAlertTimer = setTimeout(hideEmployeeSavedAlertModal, 1200);
+}
+
+function hideEmployeeSavedAlertModal() {
+ if (hideEmployeeSavedAlertTimer) {
+ clearTimeout(hideEmployeeSavedAlertTimer);
+ }
+
+ getSavedAlertModalElement().style.display = "none";
+}
+// End save
+
+//Getters and setters
+function getEmployeeId() {
+ return document.getElementById("employeeId").value;
+}
+function setEmployeeId(employeeId) {
+ document.getElementById("employeeId").value = employeeId;
+}
+
+function getEmployeeManagerId() {
+ return document.getElementById("employeeManagerId").value;
+}
+
+function getEmployeeEmployeeId() {
+ return getEmployeeEmployeeIdElement().value;
+}
+function getEmployeeEmployeeIdElement() {
+ return document.getElementById("employeeEmployeeId");
+}
+
+function getSavedAlertModalElement() {
+ return document.getElementById("employeeSavedAlertModal");
+}
+
+function getEmployeeFirstNameEditElement() {
+ return document.getElementById("employeeFirstName");
+}
+
+function getEmployeeLastNameEditElement() {
+ return document.getElementById("employeeLastName");
+}
+
+function getEmployeePasswordEditElement() {
+ return document.getElementById("employeePassword");
+}
+
+function getEmployeeConfirmPassword() {
+ return document.getElementById("employeeConfirmPassword").value;
+}
+
+function getEmployeeTypeSelectElement() {
+ return document.getElementById("employeeType");
+}
+//End getters and setters
diff --git a/src/main/resources/static/scripts/mainMenu.js b/src/main/resources/static/scripts/mainMenu.js
new file mode 100644
index 00000000..3b16c3f7
--- /dev/null
+++ b/src/main/resources/static/scripts/mainMenu.js
@@ -0,0 +1,43 @@
+document.addEventListener("DOMContentLoaded", function(event) {
+ getStartTransactionActionElement().addEventListener(
+ "click",
+ () => { displayError("Functionality has not yet been implemented."); });
+
+ getViewProductsActionElement().addEventListener(
+ "click",
+ () => { window.location.assign("/productListing"); });
+
+ getCreateEmployeeActionElement().addEventListener(
+ "click",
+ () => { window.location.assign("/employeeDetail"); });
+
+ getProductSalesReportActionElement().addEventListener(
+ "click",
+ () => { displayError("Functionality has not yet been implemented."); });
+
+ getCashierSalesReportActionElement().addEventListener(
+ "click",
+ () => { displayError("Functionality has not yet been implemented."); });
+});
+
+// Getters and setters
+function getViewProductsActionElement() {
+ return document.getElementById("viewProductsButton");
+}
+
+function getCreateEmployeeActionElement() {
+ return document.getElementById("createEmployeeButton");
+}
+
+function getStartTransactionActionElement() {
+ return document.getElementById("startTransactionButton");
+}
+
+function getProductSalesReportActionElement() {
+ return document.getElementById("productSalesReportButton");
+}
+
+function getCashierSalesReportActionElement() {
+ return document.getElementById("cashierSalesReportButton");
+}
+// End getters and setters
diff --git a/src/main/resources/static/scripts/master.js b/src/main/resources/static/scripts/master.js
index 88b039d0..c61d3563 100644
--- a/src/main/resources/static/scripts/master.js
+++ b/src/main/resources/static/scripts/master.js
@@ -1,3 +1,10 @@
+document.addEventListener("DOMContentLoaded", () => {
+ const signOutActionElement = getSignOutActionElement();
+ if (signOutActionElement != null) {
+ signOutActionElement.addEventListener("click", signOutActionClickHandler);
+ }
+});
+
// AJAX
function ajaxGet(resourceRelativeUri, callback) {
return ajax(resourceRelativeUri, "GET", null, callback);
@@ -158,6 +165,10 @@ function displayError(errorMessage) {
// End display error message
//Getters and setters
+function getSignOutActionElement() {
+ return document.getElementById("signOutImage");
+}
+
function getErrorMessageContainerElement() {
return document.getElementById("error");
}
@@ -166,3 +177,18 @@ function getErrorMessageDisplayElement() {
return document.getElementById("errorMessage");
}
// End getters and setters
+
+//Sign out
+function signOutActionClickHandler() {
+ ajaxDelete("/api/signOut", (callbackResponse) => {
+ if ((callbackResponse.data != null)
+ && (callbackResponse.data.redirectUrl != null)
+ && (callbackResponse.data.redirectUrl !== "")) {
+
+ window.location.replace(callbackResponse.data.redirectUrl);
+ } else {
+ window.location.replace("/");
+ }
+ });
+}
+//End sign out
\ No newline at end of file
diff --git a/src/main/resources/static/scripts/signIn.js b/src/main/resources/static/scripts/signIn.js
new file mode 100644
index 00000000..e7b14144
--- /dev/null
+++ b/src/main/resources/static/scripts/signIn.js
@@ -0,0 +1,43 @@
+document.addEventListener("DOMContentLoaded", function(event) {
+ const employeeIdEditElement = getEmployeeIdEditElement();
+ employeeIdEditElement.focus();
+ employeeIdEditElement.select();
+});
+
+function validateForm() {
+ const employeeIdEditElement = getEmployeeIdEditElement();
+ if (isNaN(Number(employeeIdEditElement.value))
+ || (Number(employeeIdEditElement.value) <= 0)) {
+
+ displayError("Please provide a valid employee ID.");
+
+ employeeIdEditElement.focus();
+ employeeIdEditElement.select();
+
+ return false;
+ }
+
+ const passwordEditElement = getPasswordEditElement();
+ if ((passwordEditElement.value == null)
+ || (passwordEditElement.value.trim() === "")) {
+
+ displayError("Please provide a valid password. It may not be blank.");
+
+ passwordEditElement.focus();
+ passwordEditElement.select();
+
+ return false;
+ }
+
+ return true;
+}
+
+//Getters and setters
+function getPasswordEditElement() {
+ return document.getElementById("password");
+}
+
+function getEmployeeIdEditElement() {
+ return document.getElementById("employeeId");
+}
+//End getters and setters
diff --git a/src/main/resources/static/styles/master.css b/src/main/resources/static/styles/master.css
index 2b060e6d..f35bb48a 100644
--- a/src/main/resources/static/styles/master.css
+++ b/src/main/resources/static/styles/master.css
@@ -30,6 +30,24 @@ td.hidden {
display: none
}
+div.footer {
+ left: 0;
+ right: 0;
+ bottom: 0;
+ position: absolute;
+}
+
+img.footer {
+ z-index: 1;
+ height: 50px;
+ text-decoration: none;
+ display: inline-block;
+ cursor: pointer;
+ position: fixed;
+ right: 20;
+ bottom: 20;
+}
+
div.inputContent,
form.inputContent {
display: inline-block;
diff --git a/src/main/resources/templates/employeeDetail.html b/src/main/resources/templates/employeeDetail.html
new file mode 100644
index 00000000..85b4cb05
--- /dev/null
+++ b/src/main/resources/templates/employeeDetail.html
@@ -0,0 +1,104 @@
+
+
+
+ Register - Employee
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Employee
+ Saved
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/resources/templates/mainMenu.html b/src/main/resources/templates/mainMenu.html
new file mode 100644
index 00000000..706fc531
--- /dev/null
+++ b/src/main/resources/templates/mainMenu.html
@@ -0,0 +1,62 @@
+
+
+
+ Register - Main Menu
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/resources/templates/productDetail.html b/src/main/resources/templates/productDetail.html
index ac183115..453d1041 100644
--- a/src/main/resources/templates/productDetail.html
+++ b/src/main/resources/templates/productDetail.html
@@ -34,20 +34,20 @@
| Lookup Code: |
-
+
|
| Count: |
-
+
|
-
+
@@ -68,6 +68,10 @@
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/templates/productListing.html b/src/main/resources/templates/productListing.html
index c4b758ae..6c374f83 100644
--- a/src/main/resources/templates/productListing.html
+++ b/src/main/resources/templates/productListing.html
@@ -22,7 +22,7 @@
diff --git a/src/main/resources/templates/signIn.html b/src/main/resources/templates/signIn.html
new file mode 100644
index 00000000..6f4c3994
--- /dev/null
+++ b/src/main/resources/templates/signIn.html
@@ -0,0 +1,41 @@
+
+
+