diff --git a/.gitignore b/.gitignore index df70f27..e83e0cb 100644 --- a/.gitignore +++ b/.gitignore @@ -22,7 +22,7 @@ gradle-app.setting /.project # Maven build files -/target +target/ # Compiled class file *.class diff --git a/Dockerfile b/Dockerfile index f51d8c7..0006ead 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,8 +1,28 @@ -FROM tomcat:8-jdk8-corretto +# install Linux https://docs.docker.com/engine/install/ubuntu/#install-using-the-repository +# Docker desktop https://docs.docker.com/desktop/install/ubuntu/ +# https://hub.docker.com/_/tomcat/tags +FROM tomcat:9.0-jdk11-corretto-al2 +# FROM tomcat:8.5.97-jdk17-corretto-al2 +# FROM tomcat:8.5.97-jdk11-corretto-al2 +# FROM tomcat:8.5.97-jdk8-corretto-al2 +# FROM tomcat:8-jdk8-corretto + # https://hub.docker.com/layers/library/tomcat/7.0.109-jdk8-openjdk/images/sha256-489823486120d076cb576640c5819c6fa54948f470b46c54f02b48f462eb2c23 + +ARG APP_WAR_FILE_VERSION +ENV APP_WAR_FILE_VERSION=$APP_WAR_FILE_VERSION +ENV APP_WAR_FILE="Attendance" +ENV APP_WAR_FILE_PATH="build/libs/$APP_WAR_FILE-${APP_WAR_FILE_VERSION}" LABEL org.nz.itlatinos.image.authors="aleonrangel@outlook.co.nz" LABEL maintainer="andres.nz" -ENV APP_WAR_FILE="AttendanceApp-0.0.1.war" +LABEL war.version="$APP_WAR_FILE_VERSION" +LABEL docker.image.build.command="docker build --build-arg APP_WAR_FILE_VERSION=$APP_WAR_FILE_VERSION --tag aleon1220/soa:latest ." +RUN printf "WAR version is $APP_WAR_FILE-$APP_WAR_FILE_VERSION" +RUN printf "Path to war file $APP_WAR_FILE_PATH" # Tomcat Custom settings -COPY "build/libs/$APP_WAR_FILE" /usr/local/tomcat/webapps/ \ No newline at end of file +# RUN echo ${PWD} && ls -lR # Debugging +# USER 1000 # considered permissions issue +COPY ${APP_WAR_FILE_PATH}.war /usr/local/tomcat/webapps +# COPY build/libs/AttendanceApp-0.7.2 /usr/local/tomcat/webapps/ +# https://forums.docker.com/t/docker-build-multistage-failed-to-compute-cache-key/134316/20 \ No newline at end of file diff --git a/README.md b/README.md index 05531be..e6ee956 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,17 @@ - [Attendance WebApp](#attendance-webapp) - [Introduction](#introduction) - [GitHub Reports](#github-reports) + - [GitHub Reports](#github-reports) - [Security warnings](#security-warnings) - [GitHub Vulnerability report](#github-vulnerability-report) + - [GitHub Vulnerability report](#github-vulnerability-report) - [Attendance WebApp Architecture (re-architected)](#attendance-webapp-architecture-re-architected) - [2018-Attendance WebApp high level Architecture](#2018-attendance-webapp-high-level-architecture) - [Attendance WebApp UI](#attendance-webapp-ui) - [Refer to the Wiki for details on the project](#refer-to-the-wiki-for-details-on-the-project) -- [Project general guidelines](#project-general-guidelines) -- [Setup](#setup) - - [Build WebApp](#build-webapp) - - [Gradle Build Web Package](#gradle-build-web-package) +- [Quickstart](#quickstart) +- [Local Setup](#local-setup) + - [Project general guidelines](#project-general-guidelines) - [Maven Build](#maven-build) - [Gradle Test suite](#gradle-test-suite) - [Use 1Password CLI to inject the secrets](#use-1password-cli-to-inject-the-secrets) @@ -22,6 +23,7 @@ - [Docker execution](#docker-execution) - [Docker-compose](#docker-compose) - [Editing project diagrams](#editing-project-diagrams) +- [References](#references) # Attendance WebApp @@ -40,6 +42,7 @@ The idea is that you have a short timeframe to submit a random generated code by The application is a proof of concept for Service orientation and Service interoperability in the cloud ## GitHub Reports +### GitHub Reports ### Security warnings > Security Warnings to check GitHub found 2 vulnerabilities on aleon1220/multi-cloud-WebApp-Attendance's default branch (2 moderate). @@ -47,6 +50,8 @@ To find out more, visit: [This project security report](https://github.com/aleon1220/multi-cloud-WebApp-Attendance/security) ### GitHub Vulnerability report https://github.com/aleon1220/multi-cloud-WebApp-Attendance/security/dependabot +### GitHub Vulnerability report +https://github.com/aleon1220/multi-cloud-WebApp-Attendance/security/dependabot ## Attendance WebApp Architecture (re-architected) @@ -73,16 +78,39 @@ https://github.com/aleon1220/multi-cloud-WebApp-Attendance/security/dependabot [95f44386]: https://github.com/aleon1220/multi-cloud-AttendWebApp/wiki/4-Architecture-and-Technical-Design "Project Wiki" -# Project general guidelines +# Quickstart +- A Bash script has `runme.sh` been created to automate the local development. +Cleans, builds and executes the docker-compose stack locally. Provides a version number for the app found in the build.gradle file + +```bash +./runme.sh clean ; ./runme.sh build ; ./runme.sh run +``` + +- Gradle Build Web Package +build and test the WebArchive file. Generates the .WAR file in `build/libs/*.war` +``` bash +gradle clean build --console plain --warning-mode all +``` +- Gradle Check the generated version from the build.gradle.kts +```bash +gradle getAppversion +``` +- Run WebApp +Run the tomcat server with the latest pre-built WAR web Archive file +Run from [Docker Hub](https://hub.docker.com/repository/docker/aleon1220/soa/general) +```bash +docker run --interactive --tty --detach --publish 8080:8080 --name attendance_webapp_container aleon1220/soa:latest +``` + +# Local Setup +> Tested in Win11 with WSL, Github codespaces and Linux Ubuntu 22 + +## Project general guidelines 1. Installation process: project a Java project JEE. Import in any IDE and build with gradle or maven. Build docker image and run 2. Software dependencies: dependencies are described in pom.xml file 3. Latest releases by using git tags 4. API references. API docs - -# Setup -> Tested in Win11 with WSL, Github codespaces and Linux Ubuntu 22 - - Clone repo HTTPS ```bash git clone https://github.com/aleon1220/multi-cloud-WebApp-Attendance.git @@ -94,13 +122,6 @@ git clone git@github.com:aleon1220/multi-cloud-WebApp-Attendance.git - open repo in chosen IDE IDEs can be Eclipse, IntelliJ (suggested) or use online IDE (Github codespaces) -## Build WebApp -### Gradle Build Web Package -- Pack the WebArchive file. Generate the .WAR file -``` bash -gradle clean build --console plain --warning-mode all -``` - ### Maven Build > maven has been deprecated and moved to [maven](./maven) @@ -132,11 +153,11 @@ op inject -i .env.tpl -o .env - Build the app image with Docker. Deploy .WAR file in Tomcat refer to https://hub.docker.com/_/tomcat ```bash -docker build --tag aleon1220/soa:latest . +docker build --build-arg APP_WAR_FILE_VERSION=$APP_WAR_FILE_VERSION --tag aleon1220/soa:$APP_WAR_FILE_VERSION . ``` #### Available Tomcat versions -Use the tag latest or a particular version e.g. aleon1220/soa:v2 or aleon1220/soa:latest +if you need to edit the Dockerfile and upgrade the servlet container Tomcat version - 7.0.109 = `TOMCAT_VERSION_DOCKER_TAG="7.0.109-jdk8-openjdk"` - 9.0.78 = `TOMCAT_VERSION_DOCKER_TAG="9.0.78-jre8"` @@ -144,22 +165,19 @@ Use the tag latest or a particular version e.g. aleon1220/soa:v2 or aleon1220/so ### Container Execution #### Docker execution -##### Run from [Docker Hub](https://hub.docker.com/repository/docker/aleon1220/soa/general) +### Execute WebApp Container Execution +#### Docker execution by image version Test the immutable webapp from Docker ```bash -docker run -itd --publish 8080:8080 --name attendance_webapp_container aleon1220/soa:latest +docker run --interactive --tty --detach --publish 8080:8080 --name $APP_WAR_FILE_VERSION aleon1220/soa:$APP_WAR_FILE_VERSION ``` -##### local build & Run +##### local development & executions Test the container webapp after building the image locally ```bash -docker build --tag aleon1220/soa:latest . -docker run -itd --publish 8080:8080 --name attendance_webapp_container aleon1220/soa:latest -``` -Run the tomcat server with the pre-built WAR web Archive file -```bash -docker run -itd --publish 8080:8080 aleon1220/soa:latest +docker run --interactive --tty --detach --publish 8080:8080 --name attendance_webapp_container aleon1220/soa:$APP_WAR_FILE_VERSION ``` +- Get the name of the running container - get the name of the running container ``` bash CONTAINER_NAME=$(docker container ls --all --filter publish=8080 --format "{{.Names}}") @@ -180,6 +198,10 @@ docker rm $(docker container ls --all --quiet) ```bash op inject -i .env.tpl -o .env ``` +- single variable- inject the secrets for Testing docker-compose +```bash +op inject -i .env.tpl -o .env +``` - single variable ```bash export LDAP_ADMIN_PASS=$(op read "op://uqbpxejq7gifvi6mg3c7xxokre/jvuj7juvlxlg7delckucvidqhi/password") diff --git a/build.gradle.kts b/build.gradle.kts index 77956b3..3f90bb2 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,7 +1,5 @@ import org.gradle.api.tasks.testing.logging.TestLogEvent -/* - * file generated by Gradle 'init' task. @Incubating APIs subject to change - */ +import java.net.InetAddress plugins { java @@ -19,46 +17,117 @@ repositories { } dependencies { - implementation("org.primefaces.extensions:primefaces-extensions:6.0.0") - implementation("org.primefaces:primefaces:6.0") - implementation("com.sun.faces:jsf-api:2.2.12") - implementation("com.sun.faces:jsf-impl:2.2.12") - implementation("javax.json:javax.json-api:1.1") - implementation("javax.ws.rs:javax.ws.rs-api:2.1") - implementation("com.sun.jersey:jersey-client:1.19.4") - implementation("com.google.code.gson:gson:2.8.9") - implementation("org.apache.httpcomponents:httpclient:4.5.3") - implementation("org.glassfish.jersey.core:jersey-common:2.22.2") - implementation("javax.servlet:javax.servlet-api:3.1.0") - // https://mvnrepository.com/artifact/com.google.zxing/javase + // https://www.primefaces.org + // https://primefaces.github.io/primefaces + // https://mvnrepository.com/artifact/org.primefaces/primefaces + implementation("org.primefaces:primefaces:14.0.0-RC1") + // https://mvnrepository.com/artifact/org.primefaces.extensions/primefaces-extensions + implementation("org.primefaces.extensions:primefaces-extensions:14.0.0-RC1") + + // JSF runtime + // https://mvnrepository.com/artifact/org.apache.myfaces.core/myfaces-api + // implementation("org.apache.myfaces.core:myfaces-api:4.0.1") // API https://myfaces.apache.org + // implementation("org.apache.myfaces.core:myfaces-impl:4.0.1") // Faces Implementation + // implementation("org.apache.poi:poi:3.17") // apache POI DataExporter (Excel or XML) + // implementation("com.rometools:rome:1.9.0") // FeedReader + // implementation("net.sf.barcode4j:barcode4j-light:2.3.0") // barcode4j-light + // implementation("net.glxn.qrgen:qrgen:1.4") // qrgen QR Code support for Barcode + // implementation("com.googlecode.owasp-java-html-sanitizer:owasp-java-html-sanitizer:20220608.1") + + // Jakarta EE + // https://mvnrepository.com/artifact/jakarta.enterprise/jakarta.enterprise.cdi-api + // implementation("jakarta.enterprise:jakarta.enterprise.cdi-api:4.0.1") + // implementation("jakarta.ws.rs:jakarta.ws.rs-api:3.1.0") + implementation("org.apache.httpcomponents:httpclient:4.5.13") + // https://mvnrepository.com/artifact/jakarta.ws.rs/jakarta.ws.rs-api + // https://mvnrepository.com/artifact/org.glassfish.jersey.core/jersey-client + implementation("org.glassfish.jersey.core:jersey-client:3.1.5") + // implementation("org.glassfish.jersey.core:jersey-common:2.22.2") + // https://github.com/google/gson library JSON serialization/deserialization + implementation("com.google.code.gson:gson:2.10.1") + // https://mvnrepository.com/artifact/jakarta.json/jakarta.json-api + implementation("jakarta.json:jakarta.json-api:2.1.3") + // https://bitbucket.org/snakeyaml/snakeyaml/wiki/Documentation + // https://mavenlibs.com/maven/dependency/org.yaml/snakeyaml + implementation("org.yaml:snakeyaml:2.1") + // QRFunctions implementation("com.google.zxing:javase:3.5.1") implementation("com.google.zxing:core:3.5.1") - testImplementation("org.junit.jupiter:junit-jupiter-api:5.8.2") - testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.8.2") - testImplementation("io.jsonwebtoken:jjwt:0.9.1") // dependency below only needed if using the Java 8 version of @Generated (through "jdk8") on Java 9 or later - implementation("javax.annotation:javax.annotation-api:1.3.2") - implementation("io.github.threeten-jaxb:threeten-jaxb-core:2.1.0") // Use Java Date/Time API instead of clunky GregorianCalendar class - implementation("com.graphql-java-kickstart:graphql-webclient-spring-boot-starter:2.0.1") - implementation("com.graphql-java:graphql-java:20.7") - implementation("com.graphql-java-generator:graphql-java-runtime:1.18") - // JUnit 4 framework for unit testing - testImplementation("junit:junit:4.13.2") + // implementation("io.github.threeten-jaxb:threeten-jaxb-core:2.1.0") // Use Java Date/Time API. Clunky GregorianCalendar class + // TESTING // JUnit Jupiter API and Engine for unit testing + testImplementation("org.junit.jupiter:junit-jupiter-api:5.8.2") + testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.8.2") testImplementation("org.junit.jupiter:junit-jupiter-api:5.7.0") testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.7.0") - // Mockito for mocking in tests + // Mocking in tests testImplementation("org.mockito:mockito-core:4.5.1") + // JWT Authentication + testImplementation("io.jsonwebtoken:jjwt:0.9.1") // https://central.sonatype.com/artifact/com.unboundid/unboundid-ldapsdk implementation("com.unboundid:unboundid-ldapsdk:6.0.11") - // https://github.com/google/gson library JSON serialization/deserialization - implementation("com.google.code.gson:gson:2.10.1") + implementation("com.kstruct:gethostname4j:1.0.0") } group = "soa.nz.aut" -version = "0.0.1" +version = "0.7.7" description = "Student Attendance WebApp" -java.sourceCompatibility = JavaVersion.VERSION_17 +// java.sourceCompatibility = JavaVersion.VERSION_17 + +fun setWarVersion() { + // function body + project.version?.let { version -> + println("WAR Version is $version") + System.setProperty("APP_WAR_FILE_VERSION", version.toString()) + println("For local testing do \n APP_WAR_FILE_VERSION=" + version) + println("Append to the .env file with \n") + println("printf \"\$APP_WAR_FILE_VERSION \\n\" >> .env") + } +} + +fun getAppVersion() { + println(version) +} + +fun getWarpackageVersion() { + val hostname_local = System.getenv("HOSTNAME") ?: "localhost" + val hostname = InetAddress.getLocalHost().getHostName() + + // Define the page names + val pages = listOf( + "01-login.xhtml", + "02-attendance.xhtml", + "03-attendanceOK.xhtml", + "04-lecturerHome.xhtml", + "05-adminStaff.xhtml", + "06-Reports.xhtml", + "07-StudentManagement.xhtml", + "08-ClassManagement.xhtml", + "09-UserManagement.xhtml", + "home.xhtml", + "404-attendanceError.xhtml", + "404-loginError.xhtml", + "home.xhtml", + "index.xhtml" + ) + // function body + project.version?.let { version -> + println("WAR Version is $version") + println("Set env variable with") + println("export APP_WAR_FILE_VERSION=" + version.toString()) + println("http://" + hostname + ":8080/Attendance-"+ version.toString()) + } + // Print URLs for each page + pages.forEach { page -> + println("http://$hostname:8080/Attendance-$version/$page") + } +} + +tasks.register("getProjectInfo") { + description = "Obtains detailed info about the java web project" + getWarpackageVersion() +} tasks.war { archiveBaseName.set("Attendance") @@ -68,6 +137,9 @@ tasks.war { // classpath(fileTree("additionalLibs")) // adds a file-set to the WEB-INF/lib dir. // classpath(moreLibs) // adds a configuration to the WEB-INF/lib dir. // webXml = file("src/someWeb.xml") // copies a file to WEB-INF/web.xml + doLast{ + setWarVersion() + } } tasks { @@ -107,7 +179,7 @@ tasks.register("searchOpenLDAP") { // https://plugins.gradle.org/plugin/com.github.bjornvester.wsdl2java // https://www.w3schools.com/xml/tempconvert.asmx?WSDL wsdl2java { - // wsdlDir.set(layout.projectDirectory.dir("src/main/resources/wsdl")) + // https://plugins.gradle.org/plugin/com.github.bjornvester.wsdl2java bindingFile.set(layout.projectDirectory.file("src/main/bindings/bindings.xjb")) includes.set( @@ -115,10 +187,4 @@ wsdl2java { "src/main/resources/wsdl/NumberConversion.wsdl" ) ) - // includesWithOptions.set( - // mapOf( - // "**/ServiceTemp.wsdl" to listOf("-wsdlLocation", "https://www.w3schools.com/xml/tempconvert.asmx?WSDL") - // ) - // ) - // default output directory $buildDir/generated/sources/wsdl2java/java } \ No newline at end of file diff --git a/maven/pom.xml b/maven/pom.xml index fcf029f..6ff9cad 100644 --- a/maven/pom.xml +++ b/maven/pom.xml @@ -21,7 +21,7 @@ org.primefaces.extensions primefaces-extensions - 6.0.0 + 8.0.0 @@ -90,7 +90,7 @@ org.apache.httpcomponents httpclient - 4.5.3 + 4.5.13 @@ -129,10 +129,10 @@ 1.8 - 4.12 + 4.14 3.1.0 2.2.12 - 6.0 + 8.0 3.3 UTF-8 0.7.0 diff --git a/project-diagrams.drawio b/project-diagrams.drawio index abac217..5ba84aa 100644 --- a/project-diagrams.drawio +++ b/project-diagrams.drawio @@ -1,41 +1,41 @@ - + - + - - + + - - + + - + - + - + - + - - + + - + - + @@ -44,7 +44,7 @@ - + @@ -53,12 +53,12 @@ - + - + @@ -76,7 +76,7 @@ - + @@ -91,59 +91,167 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -157,9 +265,6 @@ - - - @@ -168,20 +273,20 @@ - + - + - + - + @@ -189,39 +294,39 @@ - + - - + + - - + + - - + + - - + + - + - + @@ -229,191 +334,441 @@ - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - - + + - - + + - - + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + - + - + - + - + - + - - - + + + - + - + - + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + - - + + - - + + - - + + - - - - - - - - - - + + - - + + - - + + - - + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + - - + + + + - - + + - + + + + - - + + - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + @@ -430,24 +785,162 @@ - + - + - + - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + diff --git a/runme.sh b/runme.sh new file mode 100755 index 0000000..3cb523c --- /dev/null +++ b/runme.sh @@ -0,0 +1,62 @@ +#!/bin/bash +set -e + +# Array avoids word splitting issues +COMMANDS=(build run clean test help) +export APP_WAR_FILE_VERSION=$(gradle getAppVersion --quiet) || true +command=$1 + +print_usage() { + printf "Usage: %s [options] Available commands: \n\n" $0 + printf "\t %s " "${COMMANDS[@]}" + printf "\n\n Script tested in Linux Bash 5.1.16 \n\n" + printf "This OS bash version is: \n\n" + bash --version || true +} + +# Function to handle invalid command +invalid_command() { + printf "Invalid command: %s \n\n" $1 + print_usage + exit 1 +} + +# build +export APP_WAR_FILE_VERSION=$(gradle getAppVersion --quiet) || true +version="$APP_WAR_FILE_VERSION" + +build() { + gradle clean war --warn || true + docker build --build-arg APP_WAR_FILE_VERSION=$version --tag aleon1220/soa:$version . || true +} + +run() { + printf "Executing webapp Locally \n\n" || true + docker run --interactive --tty --detach --publish 8080:8080 --name $version aleon1220/soa:$version || true + printf "Executing Java Webapp version %s\n" $version +} + +clean() { + printf "Executing local CLEAN-UP\n\n" + gradle clean || true + docker kill $version + docker rm $version + docker image rm aleon1220/soa:$version + printf "docker clean up completed \n\n" +} + +test() { + printf "Executing TESTING \n\n" + gradle test || true +} + +help() { + printf "Help Function Java WebApp Attendance Class \n\n" + print_usage +} + +if [[ " ${COMMANDS[@]} " = *" $command "* ]]; then + "$command" "$@" || true +else + invalid_command "$command" +fi diff --git a/src/main/java/bean/AttendanceBean.java b/src/main/java/bean/AttendanceBean.java index 3e3d20e..f513625 100644 --- a/src/main/java/bean/AttendanceBean.java +++ b/src/main/java/bean/AttendanceBean.java @@ -5,17 +5,9 @@ package bean; -import javax.annotation.PostConstruct; -import javax.faces.bean.ManagedBean; -import javax.faces.bean.SessionScoped; -import javax.faces.event.ActionEvent; - import java.util.ArrayList; -import java.util.Arrays; import java.util.List; -@ManagedBean(name = "attendanceGenerate") -@SessionScoped public class AttendanceBean { private String attendanceCode; @@ -24,7 +16,6 @@ public class AttendanceBean { private List classes; private String randomCode; - @PostConstruct public void init() { // invokes service class to populate classes classes = new ArrayList(); @@ -39,20 +30,6 @@ public void init() { // } } - public String generateAttendanceCode() { - - int[] numbers = new int[6]; - // Generates 10 Random Numbers in the range 1 - 20 - for (int i = 0; i < numbers.length; i++) { - numbers[i] = (int) (Math.random() * 9); - } // end for loop - System.out.println("Numbers Generated: " + Arrays.toString(numbers).replace(",", " -")); - setRandomCode(Arrays.toString(numbers)); - // Arrays.toString(numbers).replace(",", ""); - - return Arrays.toString(numbers).replace(",", " -"); - } - public String getClassName() { return className; } @@ -69,10 +46,6 @@ public void setClasses(List classes) { this.classes = classes; } - public void buttonAction(ActionEvent actionEvent) { - - } - public String getSelectedUser() { return selectedUser; } @@ -97,5 +70,4 @@ public void setRandomCode(String randomCode) { this.randomCode = randomCode; } } -// End of AttendanceBean.java - +// End of AttendanceBean.java \ No newline at end of file diff --git a/src/main/java/bean/Paper.java b/src/main/java/bean/Paper.java index 78dd2c7..82d8bea 100644 --- a/src/main/java/bean/Paper.java +++ b/src/main/java/bean/Paper.java @@ -1,16 +1,12 @@ /** * Class Paper reflects paper management UI - * class template */ package bean; -import javax.faces.bean.ManagedBean; - import com.google.gson.annotations.Expose; import com.google.gson.annotations.SerializedName; -@ManagedBean(name = "paper") public class Paper { @SerializedName("lecturerId") diff --git a/src/main/java/bean/MainMenu.java b/src/main/java/bean/PrimeComponentsFacade.java similarity index 65% rename from src/main/java/bean/MainMenu.java rename to src/main/java/bean/PrimeComponentsFacade.java index 2f32d66..62e3a88 100644 --- a/src/main/java/bean/MainMenu.java +++ b/src/main/java/bean/PrimeComponentsFacade.java @@ -5,14 +5,23 @@ package bean; -import javax.faces.bean.ManagedBean; -import javax.faces.bean.SessionScoped; - -@ManagedBean(name = "mainMenu") -@SessionScoped -public class MainMenu{ +public class PrimeComponentsFacade{ private String linkedPage; + private String valuedId; + + public PrimeComponentsFacade() { + String value = "some text"; + } + + public String getValuedId() { + String valuable = "extra text"; + return valuedId.concat(valuable); + } + + public void setValuedId(String valuedId) { + this.valuedId = valuedId; + } public void setLinkedPage(String linkedPage) { this.linkedPage = linkedPage; diff --git a/src/main/java/bean/UserBean.java b/src/main/java/bean/UserBean.java index bfad57a..5c1e25b 100644 --- a/src/main/java/bean/UserBean.java +++ b/src/main/java/bean/UserBean.java @@ -5,20 +5,10 @@ package bean; -import javax.faces.bean.ManagedBean; -import javax.faces.bean.SessionScoped; - -import com.google.gson.annotations.Expose; - import service.UserService; -@ManagedBean(name = "userBean") -@SessionScoped public class UserBean { - - @Expose private String id; - @Expose private String password; private String firstName; private String lastName; @@ -31,8 +21,19 @@ public class UserBean { private String refreshToken; private String tokenType; - // Login Method public String login() { + // LdapAuthenticator ldapAuthenticator = new LdapAuthenticator(); + // boolean isAuthenticated = ldapAuthenticator.authenticate(username, password); + boolean isAuthenticated = true; + + if (isAuthenticated) { + return "home"; // navigate to home page + } else { + return "404-loginError"; // stay on login page + } + } + + public String loginToken() { try { UserService userService = new UserService(); // System.out.println("userBean: print the name to see if it got it: "+getId()); @@ -41,24 +42,21 @@ public String login() { // System.out.println("UserBean checking value of response before if"); if (userService.createSession(IdToken).equals("ok")) { - setAccessToken(userService.getAccessToken()); setExpiresIn(userService.getExpiresIn().toString()); setIdToken(userService.getIdToken()); setRefreshToken(userService.getRefreshToken()); setTokenType(userService.getTokenType()); - - return "main"; - + return "06-Reports"; } else { - return "loginError"; + return "404-loginError"; } } catch (Exception e) { this.setReturnMsg(e.getMessage()); e.printStackTrace(); - System.out.println("UserBean. inside exception catch."); + System.out.println("UserBean. inside exception catch"); return "loginError"; } }// end of login method @@ -161,4 +159,4 @@ public String getLastName() { public void setLastName(String lastName) { this.lastName = lastName; } -}// End of UserBean.java +}// End of UserBean.java \ No newline at end of file diff --git a/src/main/java/entity/Authorization.java b/src/main/java/entity/Authorization.java index de7c42c..707fa60 100644 --- a/src/main/java/entity/Authorization.java +++ b/src/main/java/entity/Authorization.java @@ -7,19 +7,10 @@ public class Authorization { // names have to be the same from JSON to Java Object so that it works fine. - private ChallengeParameters challengeParameters; // @SerializedName("AuthenticationResult") // @Expose private AuthenticationResult authenticationResult; - public ChallengeParameters getChallengeParameters() { - return challengeParameters; - } - - public void setChallengeParameters(ChallengeParameters challengeParameters) { - this.challengeParameters = challengeParameters; - } - public AuthenticationResult getAuthenticationResult() { return authenticationResult; } diff --git a/src/main/java/entity/ChallengeParameters.java b/src/main/java/entity/ChallengeParameters.java deleted file mode 100644 index 33cf7c5..0000000 --- a/src/main/java/entity/ChallengeParameters.java +++ /dev/null @@ -1,9 +0,0 @@ - /** - * Class ChallengeParameters helps in creation of JSON to java object - */ - -package entity; - -public class ChallengeParameters { - -} diff --git a/src/main/java/entity/LoginReply.java b/src/main/java/entity/LoginReply.java deleted file mode 100644 index 7a7f253..0000000 --- a/src/main/java/entity/LoginReply.java +++ /dev/null @@ -1,41 +0,0 @@ - /** - * Class LoginReply uses gson to create the java object based on JSON - * builds the java object and overrides a toString method for testing purposes - */ - -package entity; - -import com.google.gson.annotations.Expose; -import com.google.gson.annotations.SerializedName; - -public class LoginReply { - - @SerializedName("ChallengeParameters") - @Expose - private ChallengeParameters challengeParameters; - @SerializedName("AuthenticationResult") - @Expose - private AuthenticationResult authenticationResult; - - public ChallengeParameters getChallengeParameters() { - return challengeParameters; - } - - public void setChallengeParameters(ChallengeParameters challengeParameters) { - this.challengeParameters = challengeParameters; - } - - public AuthenticationResult getAuthenticationResult() { - return authenticationResult; - } - - public void setAuthenticationResult(AuthenticationResult authenticationResult) { - this.authenticationResult = authenticationResult; - } - - @Override - public String toString() { - //return getClass()+"challenge"+challengeParameters+"data in authent"+authenticationResult.getIdToken(); - return getClass()+" Overriding method"; - } -} diff --git a/src/main/java/service/AttendanceService.java b/src/main/java/service/AttendanceService.java index b926217..b2ec810 100644 --- a/src/main/java/service/AttendanceService.java +++ b/src/main/java/service/AttendanceService.java @@ -1,27 +1,44 @@ - /** - * Class AttendanceService - * creates random code - */ +/** + * Class AttendanceService + * creates random code + */ package service; +import java.util.Arrays; + //Class is used to show invokations to entities MS public class AttendanceService { - + private String randomCode; public AttendanceService() { } - public String getRandomCode() { - return randomCode; - } + public String getRandomCode() { + return randomCode; + } + + public String setrandomCode(String randomCode) { + return this.randomCode = randomCode; + } + + public String generateAttendanceCode() { + var randomCode = ""; + // Generates 10 Random Numbers in the range 1 - 50 + int[] numbers = new int[49]; + + for (int i = 0; i < numbers.length; i++) { + numbers[i] = (int) (Math.random() * 9); + } // end for loop - public String setrandomCode(String randomCode) { - return this.randomCode = randomCode; - } + randomCode = Arrays.toString(numbers).replace(",", " -"); + System.out.println("Numbers Generated: " + randomCode); + + return randomCode; + } } -//End of AttendanceService Class \ No newline at end of file +// End of AttendanceService Class \ No newline at end of file diff --git a/src/main/java/service/ClassDropDownView.java b/src/main/java/service/ClassDropDownView.java index 7090fe8..3d21f60 100644 --- a/src/main/java/service/ClassDropDownView.java +++ b/src/main/java/service/ClassDropDownView.java @@ -8,18 +8,11 @@ import java.io.Serializable; import java.util.HashMap; import java.util.Map; -import javax.annotation.PostConstruct; -import javax.faces.application.FacesMessage; -import javax.faces.bean.ManagedBean; -import javax.faces.bean.ViewScoped; -import javax.faces.context.FacesContext; - -@ManagedBean -@ViewScoped +import jakarta.annotation.PostConstruct; public class ClassDropDownView implements Serializable { /** - * + * Populates values */ private static final long serialVersionUID = 1L; private Map> data = new HashMap>(); @@ -90,12 +83,6 @@ public void onCountryChange() { } public void displayLocation() { - FacesMessage msg; - if(city != null && country != null) - msg = new FacesMessage("Selected", city + " of " + country); - else - msg = new FacesMessage(FacesMessage.SEVERITY_ERROR, "Invalid", "City is not selected."); - - FacesContext.getCurrentInstance().addMessage(null, msg); + System.out.println("Java Faces display message in the browser"); } } \ No newline at end of file diff --git a/src/main/java/service/MicroServicesInvoker.java b/src/main/java/service/MicroServicesInvoker.java deleted file mode 100644 index 53e569b..0000000 --- a/src/main/java/service/MicroServicesInvoker.java +++ /dev/null @@ -1,18 +0,0 @@ - /** - * Class MicroServicesInvoker for extended functionality - * class template - */ - -package service; - -public class MicroServicesInvoker { - - public void obtainClassName() { - - } - - public void obtainLecturerName() { - - } - -} diff --git a/src/main/java/service/UserService.java b/src/main/java/service/UserService.java index c0921dc..777a987 100644 --- a/src/main/java/service/UserService.java +++ b/src/main/java/service/UserService.java @@ -13,22 +13,18 @@ import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.UriBuilder; -import com.sun.jersey.api.client.Client; -import com.sun.jersey.api.client.WebResource; -import com.sun.jersey.api.client.config.ClientConfig; -import com.sun.jersey.api.client.config.DefaultClientConfig; -import org.apache.http.client.ClientProtocolException; -import com.sun.jersey.api.client.ClientResponse; +import jakarta.ws.rs.core.MediaType; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonObject; import bean.UserBean; -import entity.*; - +import jakarta.ws.rs.client.Client; +import jakarta.ws.rs.client.ClientBuilder; +import jakarta.ws.rs.client.Invocation; +import jakarta.ws.rs.client.WebTarget; +import jakarta.ws.rs.core.Response; public class UserService { UserBean user = new UserBean(); private String accessToken; @@ -43,7 +39,6 @@ public String obtainIdToken(String id, String password) { try { // 1-open connection and send user and password as a POST method - URL url = new URL("https://ctpoixww04.execute-api.us-east-1.amazonaws.com/dev/login"); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setDoOutput(true); @@ -94,50 +89,37 @@ public String obtainIdToken(String id, String password) { } public String DeserializeJSON2Object(String receivedJSON) { - // 2-transform the JSON Response to Object, adding JSON Response to a Java Object - String replyJson = receivedJSON; - - Gson gson = new Gson(); - LoginReply loginReplyObject = gson.fromJson(replyJson, LoginReply.class); - - String extractedIdToken = loginReplyObject.getAuthenticationResult().getIdToken(); - - user.setToken(extractedIdToken); - setAccessToken(loginReplyObject.getAuthenticationResult().getAccessToken()); - setExpiresIn(loginReplyObject.getAuthenticationResult().getExpiresIn().toString()); - setIdToken(loginReplyObject.getAuthenticationResult().getIdToken()); - setRefreshToken(loginReplyObject.getAuthenticationResult().getRefreshToken()); - setTokenType(loginReplyObject.getAuthenticationResult().getTokenType()); - - return extractedIdToken; + System.out.println(receivedJSON); + System.out.println((this.getUserBeanAsJson(user))); + return receivedJSON; } public String createSession(String token) { //Create session method is a GET Rest invocation - //System.out.println("UserServ: creating session method"); - ClientConfig config = new DefaultClientConfig(); - //System.out.println("UserServ: creating client config"); - Client client = Client.create(config); - - //System.out.println("UserServ: creating session"); - - WebResource service = client.resource(UriBuilder.fromUri("https://ctpoixww04.execute-api.us-east-1.amazonaws.com").build()); - + var json_token = token; + Client configClient = ClientBuilder.newClient(); + var aws_api_uri = "https://ctpoixww04.execute-api.us-east-1.amazonaws.com"; + WebTarget webTarget = configClient.target(aws_api_uri); + // WebResource service = client.resource(UriBuilder.fromUri().build()); + // webTarget.path("dev").path("session").accept(MediaType.APPLICATION_JSON).header("Authorization", json_token); + Invocation.Builder request = webTarget + .request(MediaType.APPLICATION_JSON) + .header("Authorization", json_token); + + Response response = request.get(); // getting JSON data - System.out.println("User Service Create Session With JSON" + - service.path("dev").path("session").accept(MediaType.APPLICATION_JSON).header("Authorization", token).get(String.class)); - + System.out.println("Created Session With JSON token" + response); //validate if the result is {"username":"10295765","groups":"administrator"} then return OK otherwise return failed - String sessionResult = "ok"; return sessionResult; } - private String getJsonString(UserBean userBean) { + private String getUserBeanAsJson(UserBean userBean) { // Before converting to GSON check value of id Gson gson = null; gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create(); + userBean.toString(); return gson.toJson(userBean); } diff --git a/src/main/java/util/AuthenticateAD.java b/src/main/java/util/AuthenticateAD.java index f84dfca..8bda209 100644 --- a/src/main/java/util/AuthenticateAD.java +++ b/src/main/java/util/AuthenticateAD.java @@ -4,18 +4,21 @@ import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; -import java.util.*; - -import javax.naming.*; +import java.util.Hashtable; +import java.util.Properties; import java.util.regex.*; -import javax.naming.directory.*; -import javax.naming.ldap.InitialLdapContext; -import javax.naming.ldap.LdapContext; + +import com.unboundid.ldap.sdk.LDAPConnection; +import com.unboundid.ldap.sdk.LDAPException; +import com.unboundid.ldap.sdk.ResultCode; +import com.unboundid.ldap.sdk.SearchRequest; +import com.unboundid.ldap.sdk.SearchResult; +import com.unboundid.ldap.sdk.SearchResultEntry; +import com.unboundid.ldap.sdk.SearchScope; public class AuthenticateAD { /* - * you could use a secure connection such as LDAPS (LDAP over SSL/TLS) or - * StartTLS (LDAP over TLS) + * Use secure connection LDAPS (LDAP over SSL/TLS) or StartTLS (LDAP over TLS) * Use a secure password storage mechanism: Consider using a secure password * storage mechanism such as a password hash or a secure encryption algorithm * Handle errors and exceptions more robustly: The code currently catches and @@ -32,7 +35,8 @@ public class AuthenticateAD { * Use a more secure algorithm for searching the AD: The code currently uses the * `objectClass=*` search filter, which can be inefficient and may return a * large number of results. You could consider using a more specific search - * filter such as `(&(objectClass=user)(sAMAccountName=*))`, which only return user objects + * filter such as `(&(objectClass=user)(sAMAccountName=*))`, which only return + * user objects * reduce the amount of data transferred over the network * Use a more secure algorithm for binding to the AD: The code currently uses * the `bind` method to authenticate the user, which can be vulnerable to replay @@ -54,7 +58,8 @@ public class AuthenticateAD { private static String[] requiredAttributes; private static String[] ADSearchPaths; private static String accountSuffex; - private final static String contextFactory = "com.sun.jndi.ldap.LdapCtxFactory"; + private static final String LDAP_SERVER_HOST = "server.example.com"; + private static final int LDAP_SERVER_PORT = 389; // private final static String ldapURI = // "ldap://52.40.50.72:389/DC=corp,DC=local"; // private static String[] requiredAttributes = { @@ -85,14 +90,10 @@ public void readFromPropertiesFile() { private static void authenticateUserAndGetInfo(String user, String password) throws Exception { try { Hashtable env = new Hashtable(); - env.put(Context.INITIAL_CONTEXT_FACTORY, contextFactory); - env.put(Context.PROVIDER_URL, ldapURI); - env.put(Context.SECURITY_AUTHENTICATION, "simple"); - env.put(Context.SECURITY_PRINCIPAL, user); - env.put(Context.SECURITY_CREDENTIALS, password); - - DirContext ctx = new InitialDirContext(env); - + env.put("PROVIDER_URL", ldapURI); + env.put("SECURITY_AUTHENTICATION", "simple"); + env.put("SECURITY_PRINCIPAL", user); + env.put("SECURITY_CREDENTIALS", password); String filter = "(sAMAccountName=" + user + ")"; // default for search filter username if (user.contains("@")) // if user name is a email then @@ -102,34 +103,50 @@ private static void authenticateUserAndGetInfo(String user, String password) thr filter = "(userPrincipalName=" + user + ")"; } - SearchControls ctrl = new SearchControls(); - ctrl.setSearchScope(SearchControls.SUBTREE_SCOPE); - ctrl.setReturningAttributes(requiredAttributes); + // add a filter to scan in the AD - NamingEnumeration userInfo = null; - - Integer i = 0; - do { - userInfo = ctx.search(ADSearchPaths[i], filter, ctrl); - i++; - - } while (!userInfo.hasMore() && i < ADSearchPaths.length); + var userInfo = Object.class; + if (userInfo.equals("ListUsers")) { + System.out.println("Print Attributes found in AD for filter per user"); + } - if (userInfo.hasMore()) { + } catch (Exception e) { - SearchResult UserDetails = (SearchResult) userInfo.next(); - Attributes userAttr = UserDetails.getAttributes(); - System.out.println("adEmail = " + userAttr.get("userPrincipalName").get(0).toString()); - System.out.println("adFirstName = " + userAttr.get("givenName").get(0).toString()); - System.out.println("adLastName = " + userAttr.get("sn").get(0).toString()); - System.out.println("name = " + userAttr.get("cn").get(0).toString()); - System.out.println("AdFullName = " + userAttr.get("cn").get(0).toString()); - } + } + } - userInfo.close(); + public static void main(String[] args) { + String username = "uid=john.doe,ou=People,dc=example,dc=com"; + String password = "your_password_here"; - } catch (javax.naming.AuthenticationException e) { + try { + // Create an LDAP connection + LDAPConnection connection = new LDAPConnection(); + connection.connect(LDAP_SERVER_HOST, LDAP_SERVER_PORT); + + // Bind with the user's DN and password + connection.bind(username, password); + + // If successful, perform additional operations (e.g., retrieve user info) + // For example: + // SearchResultEntry entry = getUserInfo(connection, username); + // System.out.println("User DN: " + entry.getDN()); + + // Close the connection + connection.close(); + } catch (LDAPException e) { + System.err.println("LDAP authentication failed: " + e.getMessage()); + } + } + // Example method to retrieve user info (you can customize this) + private static SearchResultEntry getUserInfo(LDAPConnection connection, String userDN) throws LDAPException { + SearchRequest searchRequest = new SearchRequest(userDN, SearchScope.BASE, "(objectClass=*)"); + SearchResult searchResult = connection.search(searchRequest); + if (searchResult.getEntryCount() == 1) { + return searchResult.getSearchEntries().get(0); + } else { + throw new LDAPException(ResultCode.NO_SUCH_OBJECT, "User not found or multiple entries matched."); } } } \ No newline at end of file diff --git a/src/main/java/util/AuthenticateToken.java b/src/main/java/util/AuthenticateToken.java index 76e86d6..c6019c4 100644 --- a/src/main/java/util/AuthenticateToken.java +++ b/src/main/java/util/AuthenticateToken.java @@ -5,73 +5,60 @@ package util; -import javax.faces.application.FacesMessage; -import javax.faces.bean.ManagedBean; -import javax.faces.context.FacesContext; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.MultivaluedMap; -import javax.ws.rs.core.UriBuilder; - +import jakarta.ws.rs.client.Client; +import jakarta.ws.rs.client.ClientBuilder; +import jakarta.ws.rs.core.MultivaluedHashMap; +import jakarta.ws.rs.core.MultivaluedMap; +import jakarta.ws.rs.core.UriBuilderException; import com.google.gson.JsonObject; -import com.sun.jersey.api.client.Client; -import com.sun.jersey.api.client.ClientResponse; -import com.sun.jersey.api.client.WebResource; -import com.sun.jersey.api.client.config.ClientConfig; -import com.sun.jersey.api.client.config.DefaultClientConfig; -import com.sun.jersey.core.util.MultivaluedMapImpl; import service.UserService; -@ManagedBean public class AuthenticateToken { private String inputCode; private Integer progress; + /** + * @return XHTML page + */ public String confirmAttendance() { - - String replyFromMS = null; - + var replyFromMS = "03-attendanceOK"; UserService tok = new UserService(); String token = tok.obtainIdToken("10295765", "Value!12"); // 1-open connection and send user and password as a POST method - ClientConfig config = new DefaultClientConfig(); - - Client client = Client.create(config); - WebResource webResource = client.resource(UriBuilder - .fromUri("https://xgdeevdwh1.execute-api.us-east-1.amazonaws.com").path("addAttendance").build()); - // Passing parameters - // {"studentId": "246810","paperId": "COMP101","status": "present"} - - MultivaluedMap formData = new MultivaluedMapImpl(); - formData.add("studentId", "246810"); - formData.add("paperId", "COMP101"); - formData.add("status", "present"); - - JsonObject jsonPayLoad = new JsonObject(); - jsonPayLoad.addProperty("studentId", "246810"); - jsonPayLoad.addProperty("paperId", "COMP101"); - jsonPayLoad.addProperty("status", "present"); - - // ClientResponse response = - // webResource.accept(MediaType.APPLICATION_JSON).header("Authorization", - // token).post(ClientResponse.class, jsonPayLoad.toString()); - ClientResponse response = webResource.header("Authorization", token).post(ClientResponse.class, - jsonPayLoad.toString()); - replyFromMS = response.getEntity(String.class); - // webResource.path("addAttendance").accept(MediaType.APPLICATION_JSON).header("Authorization", - // token).post(String.class, jsonPayLoad.toString()); - - System.out.println("AttendanceRegisterResponse:" + response); + try { + Client config = ClientBuilder.newClient(); + // call microservice functionality to register attendance + // Client client = Client.create(config); + // WebResult webResource = + // client.resource(UriBuilder.fromUri("https://xgdeevdwh1.execute-api.us-east-1.amazonaws.com").path("addAttendance").build()); + // Params {"studentId": "246810","paperId": "COMP101","status": "present"} + + MultivaluedMap formData = new MultivaluedHashMap<>(); + formData.add("studentId", "246810"); + formData.add("paperId", "COMP101"); + formData.add("status", "present"); + + JsonObject jsonPayLoad = new JsonObject(); + jsonPayLoad.addProperty("studentId", "246810"); + jsonPayLoad.addProperty("paperId", "COMP101"); + jsonPayLoad.addProperty("status", "present"); + + // send JSON Payload to MicroService + + System.out.println("Attendance Register Response"); + } catch (IllegalArgumentException | UriBuilderException e) { + e.printStackTrace(); + } // invoke WS to confirm Attendance and validate - FacesContext context = FacesContext.getCurrentInstance(); - context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "CORRECT", "Attendance Registered!!!")); + System.out.println("Java Faces display message in the browser Attendance Registered!!!"); if (replyFromMS.isEmpty()) { - return "attendanceNOK.xhtml"; + return "404-attendanceError"; } else { - return "attendanceOK.xhtml"; + return "03-attendanceOK"; } } @@ -92,12 +79,12 @@ public void setProgress(Integer progress) { } public void onComplete() { - FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Time Ended")); + System.out.println("Time out!!!"); } public String onTimeout() { - FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Time Out")); - return "main.xhtml"; + System.out.println("Timeout Try again!!"); + return "index"; } public void cancel() { diff --git a/src/main/resources/img/logo.jpeg b/src/main/resources/img/logo.jpeg new file mode 100644 index 0000000..6c25e48 Binary files /dev/null and b/src/main/resources/img/logo.jpeg differ diff --git a/src/main/webapp/01-login.xhtml b/src/main/webapp/01-login.xhtml index ce0f56c..39d32bc 100644 --- a/src/main/webapp/01-login.xhtml +++ b/src/main/webapp/01-login.xhtml @@ -1,63 +1,32 @@ - - - - + + + Login Attendance System - - - - - - - - - - - - - - - - - - - - - - Login -

University Attendance System

- - Attendance - -
- - Username ID - - Passcode - - -
- -
-
- -
-
-
-
-
-

- Info: - Enter Username - password -

-
-
-
-
- - - +
+ + + +

Training Session Attendance System

+ Attendance + + + + + + + + + + + + +

+ Information: Enter the username and password provided to you. +

+
+
+ \ No newline at end of file diff --git a/src/main/webapp/02-attendance.xhtml b/src/main/webapp/02-attendance.xhtml new file mode 100644 index 0000000..7346011 --- /dev/null +++ b/src/main/webapp/02-attendance.xhtml @@ -0,0 +1,56 @@ + + + + + Training Session Attendance + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+
+ diff --git a/src/main/webapp/03-attendanceOK.xhtml b/src/main/webapp/03-attendanceOK.xhtml index 1ced167..6608e6c 100644 --- a/src/main/webapp/03-attendanceOK.xhtml +++ b/src/main/webapp/03-attendanceOK.xhtml @@ -1,39 +1,37 @@ - - - - + + + Attendance Successfully Registered - - - + + - - - - - - - - - attendance OK - - -
-
-
-
-
- -
- -
- -
+ + + + + + attendance OK + +
- - - \ No newline at end of file +
+ diff --git a/src/main/webapp/04-lecturerHome.xhtml b/src/main/webapp/04-lecturerHome.xhtml index ec02cba..8735e74 100644 --- a/src/main/webapp/04-lecturerHome.xhtml +++ b/src/main/webapp/04-lecturerHome.xhtml @@ -1,21 +1,18 @@ - - + + - Login Attendance System + Attendance System Lecturer Trainer - - Register Attendance - - - + + -

Welcome studentId @@ -44,13 +41,12 @@ - + - @@ -62,49 +58,10 @@
-
-
-
-
-
-
-
-
-
- -

- -
- +
-
- - - - -
diff --git a/src/main/webapp/05-universityStaff.xhtml b/src/main/webapp/05-adminStaff.xhtml similarity index 100% rename from src/main/webapp/05-universityStaff.xhtml rename to src/main/webapp/05-adminStaff.xhtml diff --git a/src/main/webapp/06-Reports.xhtml b/src/main/webapp/06-Reports.xhtml index 8bf628b..308f93f 100644 --- a/src/main/webapp/06-Reports.xhtml +++ b/src/main/webapp/06-Reports.xhtml @@ -6,7 +6,7 @@ xmlns="http://www.w3.org/1999/xhtml"> - Sign Up Attendance System + Reporting diff --git a/src/main/webapp/07-StudentManagement.xhtml b/src/main/webapp/07-StudentManagement.xhtml index 190ebed..771f557 100644 --- a/src/main/webapp/07-StudentManagement.xhtml +++ b/src/main/webapp/07-StudentManagement.xhtml @@ -1,31 +1,33 @@ - - + + - - - - - - + + + + + + - - - - - - - - - - - + + + + + + + + + + + - - \ No newline at end of file + + diff --git a/src/main/webapp/08-ClassManagement.xhtml b/src/main/webapp/08-ClassManagement.xhtml index eb4470d..e0aaa14 100644 --- a/src/main/webapp/08-ClassManagement.xhtml +++ b/src/main/webapp/08-ClassManagement.xhtml @@ -1,14 +1,12 @@ - - - - - - - - + + Class Management Attendance System + + - - - - \ No newline at end of file + + diff --git a/src/main/webapp/09-UserManagement.xhtml b/src/main/webapp/09-UserManagement.xhtml index 953aaf8..2eb1477 100644 --- a/src/main/webapp/09-UserManagement.xhtml +++ b/src/main/webapp/09-UserManagement.xhtml @@ -26,7 +26,6 @@ value="Generate Attendance" action="mainMenu" icon="ui-icon-info" - outcome="attendance" > @@ -35,7 +34,6 @@ diff --git a/src/main/webapp/10-CompositeServices.xhtml b/src/main/webapp/10-CompositeServices.xhtml deleted file mode 100644 index 5b5862c..0000000 --- a/src/main/webapp/10-CompositeServices.xhtml +++ /dev/null @@ -1,47 +0,0 @@ - - - - Composite Services Integration - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/main/webapp/404-attendanceError.xhtml b/src/main/webapp/404-attendanceError.xhtml deleted file mode 100644 index b59f635..0000000 --- a/src/main/webapp/404-attendanceError.xhtml +++ /dev/null @@ -1,108 +0,0 @@ - - - - - - - Error registering attendance - - - - -
- -
- - - - -
-

- Se ha presentado un Error al publicar el aviso. Contacte a soporte - IT. -

-

-
-
-

- Suba el archivo en formato xlsx de los horarios de los abogados - para las distintas semanas. -

-
-
- - - -
-
- - -
- - -
-
- -
- This template downloaded from - free website templates -
-
- diff --git a/src/main/webapp/404-loginError.xhtml b/src/main/webapp/404-loginError.xhtml index 36cdbe3..3359fd3 100644 --- a/src/main/webapp/404-loginError.xhtml +++ b/src/main/webapp/404-loginError.xhtml @@ -1,29 +1,20 @@ - - + Login Error - - - -

Invalid UserName.

-

Please Verify user Id and password

-

An error authenticating the user was generated.

- Login Error - Go Back to Login Page - -
-
-
-
-
- -
- -
- -
+ + +

Invalid UserName

+

Please Verify user name and password

+

Error authenticating the user

+ Login Error + Go Back to Login Page + +
- - \ No newline at end of file + diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml index 7b5a5ad..2ca3492 100644 --- a/src/main/webapp/WEB-INF/web.xml +++ b/src/main/webapp/WEB-INF/web.xml @@ -1,34 +1,27 @@ - - - AttendanceWebApp - - login.xhtml - + xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" +> + + Class Attendance WebApp + Faces Servlet - javax.faces.webapp.FacesServlet + org.apache.myfaces.webapp.FacesServlet 1 - Faces Servlet *.xhtml - - State saving method: 'client' or 'server' (=default). See JSF Specification 2.5.2 - javax.faces.STATE_SAVING_METHOD - client - - - javax.servlet.jsp.jstl.fmt.localizationContext - resources.application - - com.sun.faces.config.ConfigureListener - + org.apache.myfaces.webapp.StartupServletContextListener + + + index.xhtml + \ No newline at end of file diff --git a/src/main/webapp/02-studentHome.xhtml b/src/main/webapp/home.xhtml similarity index 80% rename from src/main/webapp/02-studentHome.xhtml rename to src/main/webapp/home.xhtml index ec07e08..5eab12e 100644 --- a/src/main/webapp/02-studentHome.xhtml +++ b/src/main/webapp/home.xhtml @@ -1,4 +1,4 @@ - + - Generate Attendance System + Attendance System @@ -14,18 +14,12 @@ Generate Attendance Code -

Attendance System Date

Time and Date

-
-
-
- - for Lecture. - -
Generate a code to register attendance for this session. + Generate a code to register attendance for this session. Remember each student in the class has a time frame for 1 minute.

-
@@ -85,20 +77,11 @@
- -
-
-
-
-
- -
- -
+
diff --git a/src/main/webapp/img/attendanceOK.jpg b/src/main/webapp/img/attendanceOK.jpg new file mode 100644 index 0000000..2a1eb58 Binary files /dev/null and b/src/main/webapp/img/attendanceOK.jpg differ diff --git a/src/main/webapp/img/logo.jpeg b/src/main/webapp/img/logo.jpeg new file mode 100644 index 0000000..6c25e48 Binary files /dev/null and b/src/main/webapp/img/logo.jpeg differ diff --git a/src/main/webapp/index.xhtml b/src/main/webapp/index.xhtml new file mode 100644 index 0000000..ab7892c --- /dev/null +++ b/src/main/webapp/index.xhtml @@ -0,0 +1,37 @@ + + + + + Class Attendances System + + + +
+ + + + +
+ +

+ Manage and track class attendances with ease. + + The system allows the class to generate a random code to be entered. + the trainees have 30 seconds from the moment they login to register the attendance. +

+ +
+
+ + + +
+
+
+
+
+ diff --git a/src/test/java/attendance/student/TestStudent.java b/src/test/java/attendance/student/TestStudent.java index 3127141..99f3ee8 100644 --- a/src/test/java/attendance/student/TestStudent.java +++ b/src/test/java/attendance/student/TestStudent.java @@ -1,7 +1,5 @@ package attendance.student; -import javax.faces.bean.ManagedBean; - import org.junit.jupiter.api.Test; public class TestStudent { diff --git a/src/test/java/auth/ldap/TestLDAPAuthentication.java b/src/test/java/auth/ldap/TestLDAPAuthentication.java index 2efb1ce..a9ba66a 100644 --- a/src/test/java/auth/ldap/TestLDAPAuthentication.java +++ b/src/test/java/auth/ldap/TestLDAPAuthentication.java @@ -1,7 +1,7 @@ package auth.ldap; -import org.junit.Test; -import static org.junit.Assert.assertTrue; +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.Arrays; import java.util.List; diff --git a/src/test/java/auth/token/PostAuthenticationToken.java b/src/test/java/auth/token/PostAuthenticationToken.java index f6e3965..2f2a464 100644 --- a/src/test/java/auth/token/PostAuthenticationToken.java +++ b/src/test/java/auth/token/PostAuthenticationToken.java @@ -8,10 +8,10 @@ import java.net.MalformedURLException; import java.net.URL; -import javax.json.Json; -import javax.json.JsonArray; -import javax.json.JsonObject; -import javax.json.JsonReader; +import jakarta.json.Json; +import jakarta.json.JsonArray; +import jakarta.json.JsonObject; +import jakarta.json.JsonReader; public class PostAuthenticationToken { diff --git a/src/test/java/json/TestJSON2YAML.java b/src/test/java/json/TestJSON2YAML.java index cbd5d0f..bd99e8f 100644 --- a/src/test/java/json/TestJSON2YAML.java +++ b/src/test/java/json/TestJSON2YAML.java @@ -1,9 +1,13 @@ package json; import com.google.gson.Gson; + +import org.junit.jupiter.api.Test; import org.yaml.snakeyaml.Yaml; -import org.junit.Test; -import static org.junit.Assert.*; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; import java.util.Map; @@ -24,7 +28,7 @@ public void testJsonToYamlConversion() { // Assert that YAML output is not null or empty assertNotNull("YAML output should not be null", yamlOutput); - assertFalse("YAML output should not be empty", yamlOutput.isEmpty()); + assertFalse(yamlOutput.isBlank(), "YAML output should not be empty"); } // Test method to convert YAML to JSON @@ -42,7 +46,7 @@ public void testYamlToJsonConversion() { // Assert that JSON output is not null or empty assertNotNull("JSON output should not be null", jsonOutput); - assertFalse("JSON output should not be empty", jsonOutput.isEmpty()); + assertFalse(jsonOutput.isEmpty(), "JSON output should not be empty"); } // Test method to check if YAML output matches expected structure @@ -59,9 +63,9 @@ public void testYamlStructure() { String yamlOutput = yaml.dump(map); // Expected YAML structure - String expectedYaml = "name: John\nage: 30\n"; + String expectedYaml = "name:John\nage:30\n"; // Assert that the YAML output matches the expected structure - assertEquals("YAML output should match the expected structure", expectedYaml, yamlOutput); + assertEquals(expectedYaml, yamlOutput, "YAML output should match the expected structure"); } } diff --git a/src/test/java/json/TestJSONToken.java b/src/test/java/json/TestJSONToken.java index ef499a1..b47c55d 100644 --- a/src/test/java/json/TestJSONToken.java +++ b/src/test/java/json/TestJSONToken.java @@ -1,8 +1,8 @@ package json; -import javax.json.Json; -import javax.json.stream.JsonParser; -import javax.json.stream.JsonParser.Event; +import jakarta.json.Json; +import jakarta.json.stream.JsonParser; +import jakarta.json.stream.JsonParser.Event; import com.google.gson.Gson; import auth.login.LoginReply; diff --git a/src/test/java/ui/AttendanceGenerateTest.java b/src/test/java/ui/AttendanceGenerateTest.java index df73971..197368a 100644 --- a/src/test/java/ui/AttendanceGenerateTest.java +++ b/src/test/java/ui/AttendanceGenerateTest.java @@ -1,14 +1,14 @@ -import static org.junit.Assert.assertNotNull; +package ui; -import org.junit.Test; - -import bean.AttendanceBean; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import org.junit.jupiter.api.Test; +import service.AttendanceService; public class AttendanceGenerateTest { @Test public void testRandomCode() { - AttendanceBean at = new AttendanceBean(); - assertNotNull("data", at.generateAttendanceCode()); + AttendanceService attendanceSvc = new AttendanceService(); + assertNotNull("data", attendanceSvc.generateAttendanceCode()); } // testRandomCode() } diff --git a/src/test/java/ui/UILinks.java b/src/test/java/ui/UILinks.java new file mode 100644 index 0000000..1c76224 --- /dev/null +++ b/src/test/java/ui/UILinks.java @@ -0,0 +1,33 @@ +package ui; + +import java.io.IOException; +import java.nio.file.Paths; +import java.nio.file.Files; +import java.util.ArrayList; +import java.util.List; + +import org.junit.jupiter.api.Test; + +public class UILinks { + + /** + * Listing URLs + */ + @Test + public void ListAllXHTMLS() throws IOException{ + String webappPath = "/home/ws/code"; + List urls = new ArrayList<>(); + + Files.walk(Paths.get(webappPath)) + .filter(p -> p.toString().endsWith(".xhtml")) + .forEach(p -> { + String url = new StringBuilder("http://localhost:8080/Attendance-0.7.7/") + .append(p.toString().replace(webappPath, "")) + .toString(); + urls.add(url); + }); + + System.out.println(urls); + System.out.println("Total of XHTML files" + urls.size()); + } +} diff --git a/src/test/java/utilities/TestQRFunctions.java b/src/test/java/utilities/TestQRFunctions.java index c984d83..0a35306 100644 --- a/src/test/java/utilities/TestQRFunctions.java +++ b/src/test/java/utilities/TestQRFunctions.java @@ -1,11 +1,8 @@ package utilities; -import static org.junit.Assert.assertTrue; - import java.io.IOException; - -import org.junit.Test; - +import static org.junit.jupiter.api.Assertions.assertTrue; +import org.junit.jupiter.api.Test; import com.google.zxing.WriterException; import service.GenerateQRCode;