diff --git a/.classpath b/.classpath index 5ce7901..bbe97e5 100644 --- a/.classpath +++ b/.classpath @@ -1,19 +1,6 @@ - - - - - - - - - - - - - - + diff --git a/.gitignore b/.gitignore index 9963bb8..9751548 100644 --- a/.gitignore +++ b/.gitignore @@ -1,186 +1,6 @@ -### Vert.x ### -.vertx/ - -### Eclipse ### - -.metadata -bin/ -tmp/ -*.tmp -*.bak -*.swp -*~.nib -local.properties -.settings/ -.loadpath -.recommenders - -# External tool builders -.externalToolBuilders/ - -# Locally stored "Eclipse launch configurations" -*.launch - -# PyDev specific (Python IDE for Eclipse) -*.pydevproject - -# CDT-specific (C/C++ Development Tooling) -.cproject - -# Java annotation processor (APT) -.factorypath - -# PDT-specific (PHP Development Tools) -.buildpath - -# sbteclipse plugin -.target - -# Tern plugin -.tern-project - -# TeXlipse plugin -.texlipse - -# STS (Spring Tool Suite) -.springBeans - -# Code Recommenders -.recommenders/ - -# Scala IDE specific (Scala & Java development for Eclipse) -.cache-main -.scala_dependencies -.worksheet - -### Intellij+iml ### -# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm -# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 - -# User-specific stuff: -.idea/**/workspace.xml -.idea/**/tasks.xml -.idea/dictionaries - -# Sensitive or high-churn files: -.idea/**/dataSources/ -.idea/**/dataSources.ids -.idea/**/dataSources.xml -.idea/**/dataSources.local.xml -.idea/**/sqlDataSources.xml -.idea/**/dynamic.xml -.idea/**/uiDesigner.xml - -# Gradle: -.idea/**/gradle.xml -.idea/**/libraries - -# CMake -cmake-buildTool-debug/ - -# Mongo Explorer plugin: -.idea/**/mongoSettings.xml - -## File-based project format: -*.iws - -## Plugin-specific files: - -# IntelliJ -/out/ - -# mpeltonen/sbt-idea plugin -.idea_modules/ - -# JIRA plugin -atlassian-ide-plugin.xml - -# Cursive Clojure plugin -.idea/replstate.xml - -# Crashlytics plugin (for Android Studio and IntelliJ) -com_crashlytics_export_strings.xml -crashlytics.properties -crashlytics-buildTool.properties -fabric.properties - -### Intellij+iml Patch ### -# Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023 - -*.iml -modules.xml +## C++ shit +/bin +cavecomm +.idea/.gitignore .idea/misc.xml -*.ipr - -### macOS ### -*.DS_Store -.AppleDouble -.LSOverride - -# Icon must end with two \r -Icon - -# Thumbnails -._* - -# Files that might appear in the root of a volume -.DocumentRevisions-V100 -.fseventsd -.Spotlight-V100 -.TemporaryItems -.Trashes -.VolumeIcon.icns -.com.apple.timemachine.donotpresent - -# Directories potentially created on remote AFP share -.AppleDB -.AppleDesktop -Network Trash Folder -Temporary Items -.apdisk - -### Maven ### -target/ -pom.xml.tag -pom.xml.releaseBackup -pom.xml.versionsBackup -pom.xml.next -release.properties -dependency-reduced-pom.xml -buildNumber.properties -.mvn/timing.properties - -# Avoid ignoring Maven wrapper jar file (.jar files are usually ignored) -!/.mvn/wrapper/maven-wrapper.jar - -### Gradle ### -.gradle -/buildTool/ - -# Ignore Gradle GUI config -gradle-app.setting - -# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) -!gradle-wrapper.jar - -# Cache of project -.gradletasknamecache - -# # Work around https://youtrack.jetbrains.com/issue/IDEA-116898 -# gradle/wrapper/gradle-wrapper.properties - -### NetBeans ### -nbproject/private/ -buildTool/ -nbbuild/ -dist/ -nbdist/ -.nb-gradle/ - -### VisualStudioCode ### -.vscode/* -!.vscode/settings.json -!.vscode/tasks.json -!.vscode/launch.json -!.vscode/extensions.json -.idea/ +.idea/vcs.xml diff --git a/.project b/.project index 27c1859..a694246 100644 --- a/.project +++ b/.project @@ -6,12 +6,12 @@ - org.eclipse.jdt.core.javabuilder + org.eclipse.buildship.core.gradleprojectbuilder - org.eclipse.buildship.core.gradleprojectbuilder + org.eclipse.jdt.core.javabuilder @@ -20,4 +20,15 @@ org.eclipse.jdt.core.javanature org.eclipse.buildship.core.gradleprojectnature + + + 1678524602691 + + 30 + + org.eclipse.core.resources.regexFilterMatcher + node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__ + + + diff --git a/CavecommDatabaseBase.sql b/CavecommDatabaseBase.sql deleted file mode 100644 index 59320cc..0000000 --- a/CavecommDatabaseBase.sql +++ /dev/null @@ -1,41 +0,0 @@ -CREATE DATABASE cavecommdatabase; - -\connect cavecommdatabase - -CREATE SCHEMA public; - -CREATE TABLE public.commissions ( - requestid integer NOT NULL, - customeremailaddress text NOT NULL, - freelancer character varying(64) NOT NULL, - templatename character varying(64) DEFAULT 'N/A'::character varying NOT NULL, - currencypreference character varying(6) NOT NULL, - priceupfront numeric DEFAULT 0 NOT NULL, - priceondeliver numeric DEFAULT 0 NOT NULL, - requestdescription text DEFAULT 'N/A'::text NOT NULL, - accepted boolean, - upfrontinvoiceid character varying(64) DEFAULT 'N/A'::character varying NOT NULL, - ondeliverinvoiceid character varying(64) DEFAULT 'N/A'::character varying NOT NULL, - upfrontpaid boolean DEFAULT false NOT NULL, - ondeliverpaid boolean DEFAULT false NOT NULL -); - - -COMMENT ON COLUMN public.commissions.accepted IS 'null = undecided'; - -CREATE SEQUENCE public.commissions_requestid_seq - AS integer - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; - - -ALTER TABLE public.commissions_requestid_seq OWNER TO testuser; - -ALTER SEQUENCE public.commissions_requestid_seq OWNED BY public.commissions.requestid; - -ALTER TABLE ONLY public.commissions ALTER COLUMN requestid SET DEFAULT nextval('public.commissions_requestid_seq'::regclass); - -SELECT pg_catalog.setval('public.commissions_requestid_seq', 1, false); diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..c86aee3 --- /dev/null +++ b/Makefile @@ -0,0 +1,27 @@ +.POSIX: +INC=-I/home/user/project/resources/boost_1_81_0 -L/home/user/project/resources/boost_1_81_0/stage/lib +SRCFILES = src/main.cpp + +db: + sudo -u postgres createuser -P -e cavecommadmin + sudo -u postgres createdb --owner=cavecommadmin cavecomm 'contains all the information for the cavecomm instance on this device' + sudo -u postgres psql -c "GRANT ALL PRIVILEGES ON DATABASE cavecomm TO cavecommadmin;" + sudo -u postgres psql -c "CREATE TABLE requests( id INT PRIMARY KEY GENERATED ALWAYS AS IDENTITY, customerEmailAddress text, freelancer text, templateName text, currencyPreference varchar(6), priceUpFront decimal, priceOnDeliver decimal, requestDescription text, accepted boolean, upFrontInvoiceID text, onDeliverInvoiceID text, upFrontPaid boolean, onDeliverPaid boolean); " cavecomm + sudo -u postgres psql -c "ALTER TABLE requests OWNER TO cavecommadmin" cavecomm + +dbclean: + sudo -u postgres sh -c 'dropdb cavecomm ; dropuser cavecommadmin' + +all: + rm -r bin cavecomm + g++ $(INC) -o cavecomm $(SRCFILES) -lpqxx -lfmt -pthread + +build: + g++ $(INC) -o cavecomm $(SRCFILES) -lpqxx -lfmt -pthread + +release: + mkdir bin + g++ $(INC) -o bin/cavecomm $(SRCFILES) -lpqxx -lfmt -pthread + +clean: + rm -r bin cavecomm diff --git a/README.adoc b/README.adoc deleted file mode 100644 index acdaee6..0000000 --- a/README.adoc +++ /dev/null @@ -1,32 +0,0 @@ -= Starter - -image:https://img.shields.io/badge/vert.x-4.3.8-purple.svg[link="https://vertx.io"] - -This application was generated using http://start.vertx.io - -== Building - -To launch your tests: -``` -./gradlew clean test -``` - -To package your application: -``` -./gradlew clean assemble -``` - -To run your application: -``` -./gradlew clean run -``` - -== Help - -* https://vertx.io/docs/[Vert.x Documentation] -* https://stackoverflow.com/questions/tagged/vert.x?sort=newest&pageSize=15[Vert.x Stack Overflow] -* https://groups.google.com/forum/?fromgroups#!forum/vertx[Vert.x User Group] -* https://discord.gg/6ry7aqPWXy[Vert.x Discord] -* https://gitter.im/eclipse-vertx/vertx-users[Vert.x Gitter] - - diff --git a/README.md b/README.md index dc2fe10..429fe7e 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,11 @@ -# cavecomm -Cavemanon's custom commissioning service \ No newline at end of file +## Installation + +Depends on: + +https://packages.debian.org/bullseye/libpqxx-dev +https://packages.debian.org/bullseye/libfmt-dev +https://crowcpp.org + +**TODO: Write this** + diff --git a/build.gradle.kts b/build.gradle.kts deleted file mode 100644 index 0cd2b88..0000000 --- a/build.gradle.kts +++ /dev/null @@ -1,63 +0,0 @@ -import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar -import org.gradle.api.tasks.testing.logging.TestLogEvent.* - -plugins { - java - application - id("com.github.johnrengelman.shadow") version "7.1.2" -} - -group = "com.cavecomm" -version = "1.0.0-SNAPSHOT" - -repositories { - mavenCentral() -} - -val vertxVersion = "4.3.8" -val junitJupiterVersion = "5.9.1" - -val mainVerticleName = "cavecomm.MainVerticle" -val launcherClassName = "io.vertx.core.Launcher" - -val watchForChange = "src/**/*" -val doOnChange = "${projectDir}/gradlew classes" - -application { - mainClass.set(launcherClassName) -} - -dependencies { - implementation(platform("io.vertx:vertx-stack-depchain:$vertxVersion")) - implementation("io.vertx:vertx-web") - implementation("io.vertx:vertx-pg-client") - implementation("io.vertx:vertx-web-sstore-cookie") - implementation("io.vertx:vertx-auth-oauth2") - implementation("com.ongres.scram:client:2.1") - testImplementation("io.vertx:vertx-unit") - testImplementation("junit:junit:4.13.2") -} - -java { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 -} - -tasks.withType { - archiveClassifier.set("fat") - manifest { - attributes(mapOf("Main-Verticle" to mainVerticleName)) - } - mergeServiceFiles() -} - -tasks.withType { - useJUnit() - testLogging { - events = setOf(PASSED, SKIPPED, FAILED) - } -} - -tasks.withType { - args = listOf("run", mainVerticleName, "--redeploy=$watchForChange", "--launcher-class=$launcherClassName", "--on-redeploy=$doOnChange") -} diff --git a/build/classes/java/main/cavecomm/Database.class b/build/classes/java/main/cavecomm/Database.class deleted file mode 100644 index fda5961..0000000 Binary files a/build/classes/java/main/cavecomm/Database.class and /dev/null differ diff --git a/build/classes/java/main/cavecomm/HandlerCollection.class b/build/classes/java/main/cavecomm/HandlerCollection.class deleted file mode 100644 index d2f1223..0000000 Binary files a/build/classes/java/main/cavecomm/HandlerCollection.class and /dev/null differ diff --git a/build/classes/java/main/cavecomm/MainVerticle.class b/build/classes/java/main/cavecomm/MainVerticle.class deleted file mode 100644 index 029a676..0000000 Binary files a/build/classes/java/main/cavecomm/MainVerticle.class and /dev/null differ diff --git a/build/classes/java/test/cavecomm/TestMainVerticle.class b/build/classes/java/test/cavecomm/TestMainVerticle.class deleted file mode 100644 index 56a8194..0000000 Binary files a/build/classes/java/test/cavecomm/TestMainVerticle.class and /dev/null differ diff --git a/build/reports/tests/test/classes/cavecomm.TestMainVerticle.html b/build/reports/tests/test/classes/cavecomm.TestMainVerticle.html deleted file mode 100644 index 12f2033..0000000 --- a/build/reports/tests/test/classes/cavecomm.TestMainVerticle.html +++ /dev/null @@ -1,106 +0,0 @@ - - - - - -Test results - Class cavecomm.TestMainVerticle - - - - - -
-

Class cavecomm.TestMainVerticle

- -
- - - - - -
-
- - - - - - - -
-
-
1
-

tests

-
-
-
-
0
-

failures

-
-
-
-
0
-

ignored

-
-
-
-
0.689s
-

duration

-
-
-
-
-
-
100%
-

successful

-
-
-
-
- -
-

Tests

- - - - - - - - - - - - - -
TestDurationResult
verticle_deployed0.689spassed
-
-
-

Standard output

- -
HTTP server started on port 8888
-
-
-
-
- -
- - diff --git a/build/reports/tests/test/css/base-style.css b/build/reports/tests/test/css/base-style.css deleted file mode 100644 index 4afa73e..0000000 --- a/build/reports/tests/test/css/base-style.css +++ /dev/null @@ -1,179 +0,0 @@ - -body { - margin: 0; - padding: 0; - font-family: sans-serif; - font-size: 12pt; -} - -body, a, a:visited { - color: #303030; -} - -#content { - padding-left: 50px; - padding-right: 50px; - padding-top: 30px; - padding-bottom: 30px; -} - -#content h1 { - font-size: 160%; - margin-bottom: 10px; -} - -#footer { - margin-top: 100px; - font-size: 80%; - white-space: nowrap; -} - -#footer, #footer a { - color: #a0a0a0; -} - -#line-wrapping-toggle { - vertical-align: middle; -} - -#label-for-line-wrapping-toggle { - vertical-align: middle; -} - -ul { - margin-left: 0; -} - -h1, h2, h3 { - white-space: nowrap; -} - -h2 { - font-size: 120%; -} - -ul.tabLinks { - padding-left: 0; - padding-top: 10px; - padding-bottom: 10px; - overflow: auto; - min-width: 800px; - width: auto !important; - width: 800px; -} - -ul.tabLinks li { - float: left; - height: 100%; - list-style: none; - padding-left: 10px; - padding-right: 10px; - padding-top: 5px; - padding-bottom: 5px; - margin-bottom: 0; - -moz-border-radius: 7px; - border-radius: 7px; - margin-right: 25px; - border: solid 1px #d4d4d4; - background-color: #f0f0f0; -} - -ul.tabLinks li:hover { - background-color: #fafafa; -} - -ul.tabLinks li.selected { - background-color: #c5f0f5; - border-color: #c5f0f5; -} - -ul.tabLinks a { - font-size: 120%; - display: block; - outline: none; - text-decoration: none; - margin: 0; - padding: 0; -} - -ul.tabLinks li h2 { - margin: 0; - padding: 0; -} - -div.tab { -} - -div.selected { - display: block; -} - -div.deselected { - display: none; -} - -div.tab table { - min-width: 350px; - width: auto !important; - width: 350px; - border-collapse: collapse; -} - -div.tab th, div.tab table { - border-bottom: solid #d0d0d0 1px; -} - -div.tab th { - text-align: left; - white-space: nowrap; - padding-left: 6em; -} - -div.tab th:first-child { - padding-left: 0; -} - -div.tab td { - white-space: nowrap; - padding-left: 6em; - padding-top: 5px; - padding-bottom: 5px; -} - -div.tab td:first-child { - padding-left: 0; -} - -div.tab td.numeric, div.tab th.numeric { - text-align: right; -} - -span.code { - display: inline-block; - margin-top: 0em; - margin-bottom: 1em; -} - -span.code pre { - font-size: 11pt; - padding-top: 10px; - padding-bottom: 10px; - padding-left: 10px; - padding-right: 10px; - margin: 0; - background-color: #f7f7f7; - border: solid 1px #d0d0d0; - min-width: 700px; - width: auto !important; - width: 700px; -} - -span.wrapped pre { - word-wrap: break-word; - white-space: pre-wrap; - word-break: break-all; -} - -label.hidden { - display: none; -} \ No newline at end of file diff --git a/build/reports/tests/test/css/style.css b/build/reports/tests/test/css/style.css deleted file mode 100644 index 3dc4913..0000000 --- a/build/reports/tests/test/css/style.css +++ /dev/null @@ -1,84 +0,0 @@ - -#summary { - margin-top: 30px; - margin-bottom: 40px; -} - -#summary table { - border-collapse: collapse; -} - -#summary td { - vertical-align: top; -} - -.breadcrumbs, .breadcrumbs a { - color: #606060; -} - -.infoBox { - width: 110px; - padding-top: 15px; - padding-bottom: 15px; - text-align: center; -} - -.infoBox p { - margin: 0; -} - -.counter, .percent { - font-size: 120%; - font-weight: bold; - margin-bottom: 8px; -} - -#duration { - width: 125px; -} - -#successRate, .summaryGroup { - border: solid 2px #d0d0d0; - -moz-border-radius: 10px; - border-radius: 10px; -} - -#successRate { - width: 140px; - margin-left: 35px; -} - -#successRate .percent { - font-size: 180%; -} - -.success, .success a { - color: #008000; -} - -div.success, #successRate.success { - background-color: #bbd9bb; - border-color: #008000; -} - -.failures, .failures a { - color: #b60808; -} - -.skipped, .skipped a { - color: #c09853; -} - -div.failures, #successRate.failures { - background-color: #ecdada; - border-color: #b60808; -} - -ul.linkList { - padding-left: 0; -} - -ul.linkList li { - list-style: none; - margin-bottom: 5px; -} diff --git a/build/reports/tests/test/index.html b/build/reports/tests/test/index.html deleted file mode 100644 index d68db33..0000000 --- a/build/reports/tests/test/index.html +++ /dev/null @@ -1,133 +0,0 @@ - - - - - -Test results - Test Summary - - - - - -
-

Test Summary

-
- - - - - -
-
- - - - - - - -
-
-
1
-

tests

-
-
-
-
0
-

failures

-
-
-
-
0
-

ignored

-
-
-
-
0.689s
-

duration

-
-
-
-
-
-
100%
-

successful

-
-
-
-
- -
-

Packages

- - - - - - - - - - - - - - - - - - - - - -
PackageTestsFailuresIgnoredDurationSuccess rate
-cavecomm -1000.689s100%
-
-
-

Classes

- - - - - - - - - - - - - - - - - - - - - -
ClassTestsFailuresIgnoredDurationSuccess rate
-cavecomm.TestMainVerticle -1000.689s100%
-
-
- -
- - diff --git a/build/reports/tests/test/js/report.js b/build/reports/tests/test/js/report.js deleted file mode 100644 index 83bab4a..0000000 --- a/build/reports/tests/test/js/report.js +++ /dev/null @@ -1,194 +0,0 @@ -(function (window, document) { - "use strict"; - - var tabs = {}; - - function changeElementClass(element, classValue) { - if (element.getAttribute("className")) { - element.setAttribute("className", classValue); - } else { - element.setAttribute("class", classValue); - } - } - - function getClassAttribute(element) { - if (element.getAttribute("className")) { - return element.getAttribute("className"); - } else { - return element.getAttribute("class"); - } - } - - function addClass(element, classValue) { - changeElementClass(element, getClassAttribute(element) + " " + classValue); - } - - function removeClass(element, classValue) { - changeElementClass(element, getClassAttribute(element).replace(classValue, "")); - } - - function initTabs() { - var container = document.getElementById("tabs"); - - tabs.tabs = findTabs(container); - tabs.titles = findTitles(tabs.tabs); - tabs.headers = findHeaders(container); - tabs.select = select; - tabs.deselectAll = deselectAll; - tabs.select(0); - - return true; - } - - function getCheckBox() { - return document.getElementById("line-wrapping-toggle"); - } - - function getLabelForCheckBox() { - return document.getElementById("label-for-line-wrapping-toggle"); - } - - function findCodeBlocks() { - var spans = document.getElementById("tabs").getElementsByTagName("span"); - var codeBlocks = []; - for (var i = 0; i < spans.length; ++i) { - if (spans[i].className.indexOf("code") >= 0) { - codeBlocks.push(spans[i]); - } - } - return codeBlocks; - } - - function forAllCodeBlocks(operation) { - var codeBlocks = findCodeBlocks(); - - for (var i = 0; i < codeBlocks.length; ++i) { - operation(codeBlocks[i], "wrapped"); - } - } - - function toggleLineWrapping() { - var checkBox = getCheckBox(); - - if (checkBox.checked) { - forAllCodeBlocks(addClass); - } else { - forAllCodeBlocks(removeClass); - } - } - - function initControls() { - if (findCodeBlocks().length > 0) { - var checkBox = getCheckBox(); - var label = getLabelForCheckBox(); - - checkBox.onclick = toggleLineWrapping; - checkBox.checked = false; - - removeClass(label, "hidden"); - } - } - - function switchTab() { - var id = this.id.substr(1); - - for (var i = 0; i < tabs.tabs.length; i++) { - if (tabs.tabs[i].id === id) { - tabs.select(i); - break; - } - } - - return false; - } - - function select(i) { - this.deselectAll(); - - changeElementClass(this.tabs[i], "tab selected"); - changeElementClass(this.headers[i], "selected"); - - while (this.headers[i].firstChild) { - this.headers[i].removeChild(this.headers[i].firstChild); - } - - var h2 = document.createElement("H2"); - - h2.appendChild(document.createTextNode(this.titles[i])); - this.headers[i].appendChild(h2); - } - - function deselectAll() { - for (var i = 0; i < this.tabs.length; i++) { - changeElementClass(this.tabs[i], "tab deselected"); - changeElementClass(this.headers[i], "deselected"); - - while (this.headers[i].firstChild) { - this.headers[i].removeChild(this.headers[i].firstChild); - } - - var a = document.createElement("A"); - - a.setAttribute("id", "ltab" + i); - a.setAttribute("href", "#tab" + i); - a.onclick = switchTab; - a.appendChild(document.createTextNode(this.titles[i])); - - this.headers[i].appendChild(a); - } - } - - function findTabs(container) { - return findChildElements(container, "DIV", "tab"); - } - - function findHeaders(container) { - var owner = findChildElements(container, "UL", "tabLinks"); - return findChildElements(owner[0], "LI", null); - } - - function findTitles(tabs) { - var titles = []; - - for (var i = 0; i < tabs.length; i++) { - var tab = tabs[i]; - var header = findChildElements(tab, "H2", null)[0]; - - header.parentNode.removeChild(header); - - if (header.innerText) { - titles.push(header.innerText); - } else { - titles.push(header.textContent); - } - } - - return titles; - } - - function findChildElements(container, name, targetClass) { - var elements = []; - var children = container.childNodes; - - for (var i = 0; i < children.length; i++) { - var child = children.item(i); - - if (child.nodeType === 1 && child.nodeName === name) { - if (targetClass && child.className.indexOf(targetClass) < 0) { - continue; - } - - elements.push(child); - } - } - - return elements; - } - - // Entry point. - - window.onload = function() { - initTabs(); - initControls(); - }; -} (window, window.document)); \ No newline at end of file diff --git a/build/reports/tests/test/packages/cavecomm.html b/build/reports/tests/test/packages/cavecomm.html deleted file mode 100644 index 4b1debc..0000000 --- a/build/reports/tests/test/packages/cavecomm.html +++ /dev/null @@ -1,103 +0,0 @@ - - - - - -Test results - Package cavecomm - - - - - -
-

Package cavecomm

- -
- - - - - -
-
- - - - - - - -
-
-
1
-

tests

-
-
-
-
0
-

failures

-
-
-
-
0
-

ignored

-
-
-
-
0.689s
-

duration

-
-
-
-
-
-
100%
-

successful

-
-
-
-
- -
-

Classes

- - - - - - - - - - - - - - - - - - - -
ClassTestsFailuresIgnoredDurationSuccess rate
-TestMainVerticle -1000.689s100%
-
-
- -
- - diff --git a/build/test-results/test/TEST-cavecomm.TestMainVerticle.xml b/build/test-results/test/TEST-cavecomm.TestMainVerticle.xml deleted file mode 100644 index 23fc850..0000000 --- a/build/test-results/test/TEST-cavecomm.TestMainVerticle.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - diff --git a/build/test-results/test/binary/output.bin b/build/test-results/test/binary/output.bin deleted file mode 100644 index 7314df7..0000000 --- a/build/test-results/test/binary/output.bin +++ /dev/null @@ -1 +0,0 @@ -"HTTP server started on port 8888 diff --git a/build/test-results/test/binary/output.bin.idx b/build/test-results/test/binary/output.bin.idx deleted file mode 100644 index d29f03b..0000000 Binary files a/build/test-results/test/binary/output.bin.idx and /dev/null differ diff --git a/build/test-results/test/binary/results.bin b/build/test-results/test/binary/results.bin deleted file mode 100644 index dd25aa8..0000000 Binary files a/build/test-results/test/binary/results.bin and /dev/null differ diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index e708b1c..0000000 Binary files a/gradle/wrapper/gradle-wrapper.jar and /dev/null differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index d2880ba..0000000 --- a/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,5 +0,0 @@ -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.2-bin.zip -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew deleted file mode 100644 index 4f906e0..0000000 --- a/gradlew +++ /dev/null @@ -1,185 +0,0 @@ -#!/usr/bin/env sh - -# -# Copyright 2015 the original author or authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -############################################################################## -## -## Gradle start up script for UN*X -## -############################################################################## - -# Attempt to set APP_HOME -# Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null - -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" - -warn () { - echo "$*" -} - -die () { - echo - echo "$*" - echo - exit 1 -} - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; -esac - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD="java" - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." -fi - -# Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi -fi - -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi - -# For Cygwin or MSYS, switch paths to Windows format before running java -if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi - # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" - fi - i=`expr $i + 1` - done - case $i in - 0) set -- ;; - 1) set -- "$args0" ;; - 2) set -- "$args0" "$args1" ;; - 3) set -- "$args0" "$args1" "$args2" ;; - 4) set -- "$args0" "$args1" "$args2" "$args3" ;; - 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac -fi - -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=`save "$@"` - -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" - -exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat deleted file mode 100644 index 107acd3..0000000 --- a/gradlew.bat +++ /dev/null @@ -1,89 +0,0 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem - -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/settings.gradle.kts b/settings.gradle.kts deleted file mode 100644 index 43b7efd..0000000 --- a/settings.gradle.kts +++ /dev/null @@ -1 +0,0 @@ -rootProject.name = "cavecomm" diff --git a/setupdb.sh b/setupdb.sh new file mode 100644 index 0000000..3db8adb --- /dev/null +++ b/setupdb.sh @@ -0,0 +1,47 @@ +#!/bin/sh +sudo -u postgres createuser -P -e cavecomm +sudo -u postgres createdb --owner=cavecomm cavecomm 'contains all the information for the cavecomm instance on this device' +sudo -u postgres psql -c "GRANT ALL PRIVILEGES ON DATABASE cavecomm TO cavecomm;" +sudo -u postgres psql -c "CREATE TABLE requests( + id INT PRIMARY KEY GENERATED ALWAYS AS IDENTITY, + customerEmailAddress text, + freelancerID INT, + templateID INT, + currencyPreference varchar(6), + priceUpFront decimal, + priceOnDeliver decimal, + requestDescription text, + accepted boolean, + upFrontInvoiceID text, + onDeliverInvoiceID text, + upFrontPaid boolean, + onDeliverPaid boolean + ); +" cavecomm + +sudo -u postgres psql -c "CREATE TABLE freelancers( + id INT PRIMARY KEY GENERATED ALWAYS AS IDENTITY, + emailAddress text, + name text, + generalInformation text, + basicInformation text, + stripeAccountInformation text, + commissionLimit int + ); +" cavecomm + +sudo -u postgres psql -c "CREATE TABLE templates( + id INT PRIMARY KEY GENERATED ALWAYS AS IDENTITY, + freelancerID int, + name text, + content text + ); +" cavecomm + +sudo -u postgres psql -c "CREATE TABLE cryptoWallets( + id INT PRIMARY KEY GENERATED ALWAYS AS IDENTITY, + freelancerID int, + name text, + walletAddress text + ); +" cavecomm diff --git a/spec/buildchart.sh b/spec/buildchart.sh old mode 100755 new mode 100644 diff --git a/spec/spec.md b/spec/spec.md index 3a1d590..05c0f6b 100644 --- a/spec/spec.md +++ b/spec/spec.md @@ -97,7 +97,8 @@ TODO: Figure out what to do for this. # HTML Templates -HTML Templates are the raw HTML that is used, and filled in, by variable data provided by the system. Templates should be wrote and saved on the file system of the hosting computer, and loaded upon start up. These loaded templates should be filled in with data provided by the system, then the assembled HTML should be given as a response to users. +HTML Templates are the raw HTML that is used, and filled in, by variable data provided by the system. Templates should be wrote and saved on the file system of the hosting computer, and loaded upon start up. These loaded templates should be filled in with data provided by the system, then the assembled HTML should be given as a response to users. +The Templates should utilize purely lower-case variable names. # Payment Verification diff --git a/src/README.md b/src/README.md new file mode 100644 index 0000000..11bc130 --- /dev/null +++ b/src/README.md @@ -0,0 +1,5 @@ +Depends on: + +https://packages.debian.org/bullseye/libpqxx-dev +https://packages.debian.org/bullseye/libfmt-dev +https://crowcpp.org diff --git a/src/database.cpp b/src/database.cpp new file mode 100644 index 0000000..09655f3 --- /dev/null +++ b/src/database.cpp @@ -0,0 +1,205 @@ +#include +#include +#include +#include +#include +#include "crow.h" + + +/* + * Database Manager + */ +namespace Database { + //Valid names for the JSON + const static std::string JSON_ITEM_NAMES[] = {"id", "customerEmailAddress", "freelancer", "templateName", "currencyPreference", "priceUpFront", "priceOnDeliver", "requestDescription", "accepted", "upFrontInvoiceID", "onDeliverInvoiceID", "upFrontPaid", "onDeliverPaid"}; + + /* + * Name and Statement for prepared statement to insert an item into Requests + * Takes the name of the freelancer and the template and resolves them to create the request + * todo:validate + * todo:createAlternative + */ + const static std::string PREPARED_STATEMENT_INSERT_ITEM_IN_REQUESTS = "insertItemInRequests"; + const static std::string SQL_STATEMENT_INSERT_ITEM_IN_REQUESTS = "INSERT INTO requests(id, customerEmailAddress, freelancerid , templateid , currencyPreference, priceUpFront, priceOnDeliver, requestDescription, accepted, upFrontInvoiceID, onDeliverInvoiceID, upFrontPaid, onDeliverPaid) VALUES(DEFAULT, $1, (select id from freelancers where name = $2), (select id from templates where name = $3), $4, $5, $6, $7, $8, $9, $10, $11, $12 );"; + + /* + * Name and Statement for prepared statement to select an item based on a given ID + * Case for boolean return values because the default return value is f/t instead of 0/1 or false/true + * todo:validate + */ + const static std::string PREPARED_STATEMENT_SELECT_ITEM_BY_ID = "selectItemByID"; + const static std::string SQL_STATEMENT_SELECT_ITEM_BY_ID = "SELECT requests.id , customerEmailAddress, freelancers.name, templates.name, currencyPreference, priceUpFront, priceOnDeliver, requestDescription, (CASE WHEN requests.accepted THEN 1 ELSE 0 END) AS accepted, upFrontInvoiceID, onDeliverInvoiceID, (CASE WHEN requests.upFrontPaid THEN 1 ELSE 0 END) AS upFrontPaid, (CASE WHEN requests.onDeliverPaid THEN 1 ELSE 0 END) AS onDeliverPaid FROM requests INNER JOIN freelancers ON freelancers.id=requests.freelancerID INNER JOIN templates ON templates.id=requests.templateID WHERE requests.id=$1;"; + + /* + * Name and Statement for prepared statement to select a freelancer based on a given id + */ + const static std::string PREPARED_STATEMENT_SELECT_FREELANCER = "selectFreelancer"; + const static std::string SQL_STATEMENT_SELECT_FREELANCER = "select id, name, generalinformation, basicinformation from freelancers WHERE id=$1;"; + + /* + * Name and Statement for prepared statement to select a freelancers templates based on a given freelancer id + */ + const static std::string PREPARED_STATEMENT_SELECT_FREELANCER_TEMPLATES = "selectFreelancerTemplates"; + const static std::string SQL_STATEMENT_SELECT_FREELANCER_TEMPLATES = "select id, name, content from templates where freelancerid = $1 order by id;"; + + /* + * Selects freelancers, their basicInfo and if the commissions are closed/open ordered by name. + * Delivers if the commission limit has been reached and if the commissions are closed based on the accepted/completed state of the freelancers requests + */ + const static std::string SQL_Statement_SELECT_FREELANCERS_WITHCOMMISSIONSSTATE = "select id, name, basicInformation , (case when (commissionlimit <= (select count(*) as requestCount from requests where requests.accepted = true and requests.completed = false and requests.freelancerid = freelancers.id group by freelancers.id)) then 'Closed' else 'Open' end) as commissionsclosed from freelancers order by name;"; + + /* + * Struct Representing an item in Requests + */ + struct requestsItem { + int id; + std::string customerEmailAddress; + std::string freelancer; + std::string freelancerid; + std::string templateName; + std::string templateNameid; + std::string currencyPreference; + std::string priceUpFront; + std::string priceOnDeliver; + std::string requestDescription; + bool accepted; + std::string upFrontInvoiceID; + std::string onDeliverInvoiceID; + bool upFrontPaid; + bool onDeliverPaid; + + /* + * Parses a JSON and fills the Item with the delivered values + */ + void insertJsonIntoItem(crow::json::rvalue itemJson){ + if (itemJson.has(JSON_ITEM_NAMES[0])) id = itemJson[JSON_ITEM_NAMES[0]].i(); + if (itemJson.has(JSON_ITEM_NAMES[1])) customerEmailAddress = itemJson[JSON_ITEM_NAMES[1]].s(); + if (itemJson.has(JSON_ITEM_NAMES[2])) freelancer = itemJson[JSON_ITEM_NAMES[2]].s(); + if (itemJson.has(JSON_ITEM_NAMES[3])) templateName = itemJson[JSON_ITEM_NAMES[3]].s(); + if (itemJson.has(JSON_ITEM_NAMES[4])) currencyPreference = itemJson[JSON_ITEM_NAMES[4]].s(); + if (itemJson.has(JSON_ITEM_NAMES[5])) priceUpFront = itemJson[JSON_ITEM_NAMES[5]].s(); + if (itemJson.has(JSON_ITEM_NAMES[6])) priceOnDeliver = itemJson[JSON_ITEM_NAMES[6]].s(); + if (itemJson.has(JSON_ITEM_NAMES[7])) requestDescription = itemJson[JSON_ITEM_NAMES[7]].s(); + if (itemJson.has(JSON_ITEM_NAMES[8])) accepted = itemJson[JSON_ITEM_NAMES[8]].b(); + if (itemJson.has(JSON_ITEM_NAMES[9])) upFrontInvoiceID = itemJson[JSON_ITEM_NAMES[9]].s(); + if (itemJson.has(JSON_ITEM_NAMES[10])) onDeliverInvoiceID = itemJson[JSON_ITEM_NAMES[10]].s(); + if (itemJson.has(JSON_ITEM_NAMES[11])) upFrontPaid = itemJson[JSON_ITEM_NAMES[11]].b(); + if (itemJson.has(JSON_ITEM_NAMES[12])) onDeliverPaid = itemJson[JSON_ITEM_NAMES[12]].b(); + } + }; + + /* + * Executes an SQL query and returns results + * Takes an open pqxx::connection + */ + pqxx::result executeSQL(pqxx::connection &connection, std::string sqlQuery) { + pqxx::work work(connection); + pqxx::result result = work.exec(sqlQuery); + work.commit(); + return result; + } + + /* + * Executes the prepared statement INSERT_ITEM_IN_REQUESTS + * Takes an open pqxx::connection and the requestsItem to insert + */ + pqxx::result executePreparedStatement_INSERT_ITEM_IN_REQUESTS(pqxx::connection &connection, requestsItem item) { + connection.prepare(PREPARED_STATEMENT_INSERT_ITEM_IN_REQUESTS, SQL_STATEMENT_INSERT_ITEM_IN_REQUESTS); + pqxx::work work(connection); + pqxx::result result = work.exec_prepared(PREPARED_STATEMENT_INSERT_ITEM_IN_REQUESTS, + item.customerEmailAddress, item.freelancer, item.templateName, + item.currencyPreference, item.priceUpFront, item.priceOnDeliver, + item.requestDescription, item.accepted, item.upFrontInvoiceID, + item.onDeliverInvoiceID, item.upFrontPaid, item.onDeliverPaid); + work.commit(); + return result; + } + + /* + * Executes the prepared statement SELECT_ITEM_BY_ID + * Takes an open pqxx::connection + */ + pqxx::result executeStatement_SELECT_FREELANCERS_WITHCOMMISSIONSSTATE(pqxx::connection &connection) { + pqxx::work work(connection); + pqxx::result result = work.exec(SQL_Statement_SELECT_FREELANCERS_WITHCOMMISSIONSSTATE); + work.commit(); + return result; + } + + /* + * Executes the prepared statement SELECT_ITEM_BY_ID + * Takes an open pqxx::connection and the id to select by + */ + pqxx::result executePreparedStatement_SELECT_ITEM_BY_ID(pqxx::connection &connection, int id) { + connection.prepare(PREPARED_STATEMENT_SELECT_ITEM_BY_ID, SQL_STATEMENT_SELECT_ITEM_BY_ID); + pqxx::work work(connection); + pqxx::result result = work.exec_prepared(PREPARED_STATEMENT_SELECT_ITEM_BY_ID, id); + work.commit(); + return result; + } + + /* + * Executes the prepared statement SELECT_FREELANCER + * Takes an open pqxx::connection and the id to select by + */ + pqxx::result executePreparedStatement_SELECT_FREELANCER(pqxx::connection &connection, int freelancerID) { + connection.prepare(PREPARED_STATEMENT_SELECT_FREELANCER, SQL_STATEMENT_SELECT_FREELANCER); + pqxx::work work(connection); + pqxx::result result = work.exec_prepared(PREPARED_STATEMENT_SELECT_FREELANCER, freelancerID); + work.commit(); + return result; + } + + /* + * Executes the prepared statement SELECT_FREELANCER_TEMPLATES + * Takes an open pqxx::connection and the id to select by + */ + pqxx::result executePreparedStatement_SELECT_FREELANCER_TEMPLATES(pqxx::connection &connection, int freelancerID) { + connection.prepare(PREPARED_STATEMENT_SELECT_FREELANCER_TEMPLATES, SQL_STATEMENT_SELECT_FREELANCER_TEMPLATES); + pqxx::work work(connection); + pqxx::result result = work.exec_prepared(PREPARED_STATEMENT_SELECT_FREELANCER_TEMPLATES, freelancerID); + work.commit(); + return result; + } + + + + /* + * parses the result and returns a JSON + * Takes a result and optionally the desired row + * !the result delivers only lowercase column names, either the templates are appropriately changed + * or a validation is performed at conversion. + */ + crow::json::wvalue convertResultRowToJSON(pqxx::result &result, int row = 0){ + crow::json::wvalue returnJson; + for (int i = 0; i < result.columns(); ++i) { + returnJson[result.column_name(i)] = result.at(row).at(i).c_str(); + } + return returnJson; + } + + /* + * parses the result and returns a JSON + * parses it fully and returns a JSON containing it at the top or below a variable + * takes the result and optionally a name for the top level variable + */ + crow::json::wvalue convertResultToJSON(pqxx::result &result, std::string jsonName = ""){ + std::vector jsonVector; + for (int row = 0; row < result.size(); ++row) { + crow::json::wvalue jsonVectorItem; + for (int i = 0; i < result.columns(); ++i) { + jsonVectorItem[result.column_name(i)] = result.at(row).at(i).c_str(); + } + jsonVector.push_back(jsonVectorItem); + } + crow::json::wvalue returnJson; + if (jsonName != ""){ + returnJson[jsonName] = crow::json::wvalue(jsonVector); + } + else + { + returnJson = crow::json::wvalue(jsonVector); + } + return returnJson; + } +} \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..328b4c6 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,150 @@ +#include "crow.h" +#include +#include +#include +#include "database.cpp" + +using namespace std; + +int main() { + crow::SimpleApp app; + + // CROW_ROUTE(app, "/test.json") + // ([](){ + // pqxx::connection db("postgresql://cavecommadmin:cavecomm@localhost:5432/cavecomm"); + // pqxx::work work(db); + // pqxx::result result = work.exec("SELECT * from public.requests;"); + // work.commit(); + // return crow::json::wvalue x({{"message", rows[0][0].as();}}); + // }); + + string databaseURI = "postgresql://cavecommadmin:cavecomm@localhost:5432/cavecomm"; + + + /* + * Freelancer Profile listing for customers + */ + CROW_ROUTE(app, "/") + ([databaseURI]() { + pqxx::connection databaseConnection(databaseURI); + pqxx::result result = Database::executeStatement_SELECT_FREELANCERS_WITHCOMMISSIONSSTATE(databaseConnection); + + auto page = crow::mustache::load("customerIndex_FreelancerListing.html"); + crow::json::wvalue resultJson = Database::convertResultToJSON(result, "freelancerProfiles"); + + crow::mustache::context ctx(resultJson); + return page.render(ctx); + }); + + /* + * Freelancer Profile Page for customers + */ + CROW_ROUTE(app, "/customer//") + ([databaseURI](string freelancerName, int freelancerID) { + pqxx::connection databaseConnection(databaseURI); + pqxx::result resultFreelancer = Database::executePreparedStatement_SELECT_FREELANCER(databaseConnection, freelancerID); + + string freelancerHTML = "customer_FreelancerListing_NOTFOUND.html"; + //crow::json::wvalue resultJsonFreelancer; + crow::json::wvalue resultJsonFreelancerTemplate; + + if (resultFreelancer.size() != 0){ + freelancerHTML = "customer_FreelancerListing.html"; + //resultJsonFreelancer = Database::convertResultRowToJSON(resultFreelancer); + pqxx::result resultFreelancerTemplates = Database::executePreparedStatement_SELECT_FREELANCER_TEMPLATES(databaseConnection, freelancerID); + resultJsonFreelancerTemplate = Database::convertResultToJSON(resultFreelancerTemplates, "templates"); + } + + auto page = crow::mustache::load(freelancerHTML); + crow::mustache::context ctx(resultJsonFreelancerTemplate); + + if (resultFreelancer.size() != 0){ + /* + * puts freelancer data into context + * todo::solve this with less hardcoding + */ + for (int i = 0; i < resultFreelancer.columns(); ++i) { + string freelancerColumn = resultFreelancer.column_name(i); + ctx["freelancer" + freelancerColumn] = resultFreelancer.at(0).at(i).c_str(); + } + } + + ctx["freelancerid"] = freelancerID; + ctx["selectedfreelancername"] = freelancerName; + + return page.render(ctx); + }); + + + + + + + + + CROW_ROUTE(app, "/getEntry/") + ([databaseURI](int entry) { + pqxx::connection databaseConnection(databaseURI); + pqxx::result result = Database::executePreparedStatement_SELECT_ITEM_BY_ID(databaseConnection, entry); + + auto page = crow::mustache::load("test.html"); + + + + crow::json::wvalue resultJson = Database::convertResultRowToJSON(result); + crow::mustache::context ctx(resultJson); + + return page.render(ctx); + + + }); + + CROW_ROUTE(app, "/testRequest") + ([databaseURI]() { + Database::requestsItem item; + + item.customerEmailAddress = "test@testmail.com"; + item.freelancer = "michael"; + item.templateName = "coding"; + item.currencyPreference = "XMR"; + item.priceUpFront = "0.36"; + item.priceOnDeliver = "0.36"; + item.requestDescription = "This is a test"; + item.accepted = stoi("0"); + item.upFrontInvoiceID = "12424242424"; + item.onDeliverInvoiceID = "329532532532"; + item.upFrontPaid = stoi("0"); + item.onDeliverPaid = stoi("0"); + + pqxx::connection databaseConnection(databaseURI); + Database::executePreparedStatement_INSERT_ITEM_IN_REQUESTS(databaseConnection, item); + + return crow::response(200); + }); + + CROW_ROUTE(app, "/newRequest") + .methods("POST"_method) + ([databaseURI](const crow::request &req) { + auto jsonBody = crow::json::load(req.body); + + if (!jsonBody) + return crow::response(crow::status::BAD_REQUEST); + + /* + * Example CURL to insert into DB: + * Price must be delivered as a string to avoid unnecessary conversion to double which would lead to the addition to a database of the value 0.359999999999999999999999999 instead of 0.36. + * curl -H "Content-Type: application/json" -H "Accept: application/json" -d '{"customerEmailAddress":"2@testmail.com","freelancer":"nick","templateName":"coding","currencyPreference":"XMR","priceUpFront":"0.36","priceOnDeliver":"0.36","requestDescription":"This is a test","accepted":false,"upFrontInvoiceID":"12424242424","onDeliverInvoiceID":"329532532532","upFrontPaid":false,"onDeliverPaid":false}' http://0.0.0.0:18080/newRequest + */ + Database::requestsItem item; + item.insertJsonIntoItem(jsonBody); + + pqxx::connection databaseConnection(databaseURI); + Database::executePreparedStatement_INSERT_ITEM_IN_REQUESTS(databaseConnection, item); + + return crow::response(200); + }); + + + //set the port, set the app to run on multiple threads, and run the app + app.port(18080).multithreaded().run(); +} diff --git a/src/main/java/cavecomm/Database.java b/src/main/java/cavecomm/Database.java deleted file mode 100644 index 3ee3bf0..0000000 --- a/src/main/java/cavecomm/Database.java +++ /dev/null @@ -1,83 +0,0 @@ -package cavecomm; - -import io.vertx.core.Vertx; -import io.vertx.ext.web.RoutingContext; -import io.vertx.pgclient.PgConnectOptions; -import io.vertx.pgclient.PgPool; -import io.vertx.sqlclient.PoolOptions; -import io.vertx.sqlclient.Row; -import io.vertx.sqlclient.RowSet; -import io.vertx.sqlclient.SqlClient; - -public class Database { - public static final int OUTPUT_DATATYPE_JSON = 0; - public static final int OUTPUT_DATATYPE_HTML = 1; - public static final int OUTPUT_DATATYPE_NONE = 2; - - private final PgConnectOptions connectOptions; - private final PoolOptions poolOptions; - private final Vertx vertx; - - private SqlClient client; - - public Database(Vertx vertx, int port, String host, String database, String user, String password) { - this.vertx = vertx; - //Sets up the database Connection - connectOptions = new PgConnectOptions() - .setPort(port) - .setHost(host) - .setDatabase(database) - .setUser(user) - .setPassword(password); - poolOptions = new PoolOptions(); - } - - //Executes an SQL query - //requires further consideration of the Handling. - public void executeQuery(String query) - { - createClient(); - client - .query(query) - .execute(ar -> { - if (ar.succeeded()) { - RowSet result = ar.result(); - //test output - for (Row r : result) { - - System.out.println("row: " + r.getString("testcolumn1")); - } - } else { - System.out.println("Failure: " + ar.cause().getMessage()); - } - closeClient(); - }); - } - - //Executes an SQL query while delivering a context to handle the data - //context output is a JSON - public void executeQuery(String query, RoutingContext rc, int outputDataType) - { - createClient(); - client - .query(query) - .execute(ar -> { - switch (outputDataType) { - case OUTPUT_DATATYPE_JSON -> HandlerCollection.outputJSON(ar, rc); - case OUTPUT_DATATYPE_HTML -> HandlerCollection.outputHTML(ar, rc); - } - - closeClient(); - }); - } - private void createClient() - { - client = PgPool.client(vertx, connectOptions, poolOptions); - } - private void closeClient() - { - System.out.println("Client Closing"); - client.close(); - } - -} diff --git a/src/main/java/cavecomm/HandlerCollection.java b/src/main/java/cavecomm/HandlerCollection.java deleted file mode 100644 index 3caaddf..0000000 --- a/src/main/java/cavecomm/HandlerCollection.java +++ /dev/null @@ -1,47 +0,0 @@ -package cavecomm; - -import io.vertx.core.AsyncResult; -import io.vertx.core.json.JsonArray; -import io.vertx.ext.web.RoutingContext; -import io.vertx.sqlclient.Row; -import io.vertx.sqlclient.RowSet; - -//Class collecting Handlers to be used instead of Complex Lmabdas -public final class HandlerCollection { - private HandlerCollection() { - } - - //returns a response containing the query result as a JSON - public static void outputJSON(AsyncResult> ar, RoutingContext rc) { - if (ar.succeeded()) { - RowSet result = ar.result(); - //dump RowSet into jsonArray - JsonArray jsonArray = new JsonArray(); - for (Row r : result) { - jsonArray.add(r.toJson()); - } - //sets the header to json - rc.response().putHeader("Content-Type", "application/json; charset=UTF8") - .end(jsonArray.encode()); - } else { - System.out.println("Failure: " + ar.cause().getMessage()); - } - } - - //Potentially unnecessary to exist as its own handler - public static void outputHTML(AsyncResult> ar, RoutingContext rc) { - if (ar.succeeded()) { - RowSet result = ar.result(); - //dump RowSet into jsonArray - JsonArray jsonArray = new JsonArray(); - for (Row r : result) { - jsonArray.add(r.toJson()); - } - //sets the header to html - rc.response().putHeader("Content-Type", "text/html; charset=UTF8") - .end(jsonArray.encodePrettily()); - } else { - System.out.println("Failure: " + ar.cause().getMessage()); - } - } -} diff --git a/src/main/java/cavecomm/MainVerticle.java b/src/main/java/cavecomm/MainVerticle.java deleted file mode 100644 index e23ebb6..0000000 --- a/src/main/java/cavecomm/MainVerticle.java +++ /dev/null @@ -1,77 +0,0 @@ -package cavecomm; - -import io.vertx.core.AbstractVerticle; -import io.vertx.core.MultiMap; -import io.vertx.core.json.JsonObject; -import io.vertx.ext.web.Router; - -public class MainVerticle extends AbstractVerticle { - @Override - public void start() throws Exception { - - //Template Engine / HTML Assembler - // - //TODO: actually make this work, for some reason io.vertx.ext.web.handler.TemplateEngine doesn't exist even though it does: https://vertx.io/docs/apidocs/io/vertx/ext/web/handler/package-summary.html - io.vertx.ext.web.handler.TemplateEngine engine = io.vertx.reactivex.ext.web.templ.freemarker.FreeMarkerTemplateEngine.create(); - io.vertx.ext.web.handler.TemplateHandler templateHandler = io.vertx.ext.web.handler.TemplateHandler.create(engine); - - // Create a Routeir - Router router = Router.router(vertx); - // Mount the handler for all incoming requests at every path and HTTP method - - Database db = new Database( - vertx, - 5432, - "localhost", - "testdb", - "testuser", - "123"); - - - router.get("/jsonTest").handler(rc -> { - db.executeQuery("SELECT * FROM testtable", rc, Database.OUTPUT_DATATYPE_JSON); - } - ); - - router.get("/htmlTest").handler(rc -> { - db.executeQuery("SELECT * FROM testtable", rc, Database.OUTPUT_DATATYPE_HTML); - } - ); - - router.get("/dynamic/*").handler(templateHandler); - - - - - - router.route().handler(context -> { - // Get the address of the request - String address = context.request().connection().remoteAddress().toString(); - // Get the query parameter "name" - MultiMap queryParams = context.queryParams(); - String name = queryParams.contains("name") ? queryParams.get("name") : "unknown"; - - - // Write a json response - context.json( - new JsonObject() - .put("cavecomm", name) - .put("address", address) - .put("message", "Hello World") - ); - }); - - // Create the HTTP server - vertx.createHttpServer() - // Handle every request using the router - .requestHandler(router) - // Start listening - .listen(8888) - // Print the port - .onSuccess(server -> - System.out.println( - "HTTP server started on port " + server.actualPort() - ) - ); - } -} diff --git a/src/test/java/cavecomm/TestMainVerticle.java b/src/test/java/cavecomm/TestMainVerticle.java deleted file mode 100644 index 347d39d..0000000 --- a/src/test/java/cavecomm/TestMainVerticle.java +++ /dev/null @@ -1,30 +0,0 @@ -package cavecomm; - -import io.vertx.core.Vertx; -import io.vertx.ext.unit.Async; -import io.vertx.ext.unit.TestContext; -import io.vertx.ext.unit.junit.RunTestOnContext; -import io.vertx.ext.unit.junit.VertxUnitRunner; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; - -@RunWith(VertxUnitRunner.class) -public class TestMainVerticle { - - @Rule - public RunTestOnContext rule = new RunTestOnContext(); - - @Before - public void deploy_verticle(TestContext testContext) { - Vertx vertx = rule.vertx(); - vertx.deployVerticle(new MainVerticle(), testContext.asyncAssertSuccess()); - } - - @Test - public void verticle_deployed(TestContext testContext) throws Throwable { - Async async = testContext.async(); - async.complete(); - } -} diff --git a/templates/customerIndex_FreelancerListing.html b/templates/customerIndex_FreelancerListing.html new file mode 100644 index 0000000..3cefb14 --- /dev/null +++ b/templates/customerIndex_FreelancerListing.html @@ -0,0 +1,39 @@ + + + + + + +

Freelancer Profiles

+ + + + + + + {{#freelancerProfiles}} + + + + + + {{/freelancerProfiles}} +
FreelancerBasic InformationCommission State
{{name}}{{basicinformation}}{{commissionsclosed}}
+ + \ No newline at end of file diff --git a/templates/customer_FreelancerListing.html b/templates/customer_FreelancerListing.html new file mode 100644 index 0000000..e7df187 --- /dev/null +++ b/templates/customer_FreelancerListing.html @@ -0,0 +1,41 @@ + + + + + + +

Freelancer: {{freelancername}}

+
Basic Profile:
+
{{freelancerbasicinformation}}
+
+
Detailed Profile:
+
{{freelancergeneralinformation}}
+
+ Return to freelancer selection +
+ + {{#templates}} + + + + + {{/templates}} +
{{name}}{{content}}
+ + \ No newline at end of file diff --git a/templates/customer_FreelancerListing_NOTFOUND.html b/templates/customer_FreelancerListing_NOTFOUND.html new file mode 100644 index 0000000..a55fa7d --- /dev/null +++ b/templates/customer_FreelancerListing_NOTFOUND.html @@ -0,0 +1,26 @@ + + + + + + +

Freelancer: {{selectedfreelancername}} Could not be found!

+

Return to freelancer selection

+ + \ No newline at end of file diff --git a/templates/test.html b/templates/test.html new file mode 100644 index 0000000..118adb7 --- /dev/null +++ b/templates/test.html @@ -0,0 +1,13 @@ +

id: {{id}}

+

customerEmailAddress: {{customeremailaddress}}

+

freelancer: {{freelancer}}

+

templateName: {{templatename}}

+

currencyPreference: {{currencypreference}}

+

priceUpFront: {{priceupfront}}

+

priceOnDeliver: {{priceondeliver}}

+

requestDescription: {{requestdescription}}

+

upFrontInvoiceID: {{upfrontinvoiceid}}

+

onDeliverInvoiceID: {{ondeliverinvoiceid}}

+

upFrontPaid: {{upfrontpaid}}

+

onDeliverPaid: {{ondeliverpaid}}

+

accepted: {{accepted}}