687 lines
33 KiB
C++
687 lines
33 KiB
C++
#include <vector>
|
|
#include <string>
|
|
#include <thread>
|
|
|
|
#include <pqxx/pqxx>
|
|
|
|
#include "crow.h"
|
|
#include "crow/middlewares/cookie_parser.h"
|
|
|
|
#include "database.cpp"
|
|
#include "utilities.cpp"
|
|
#include "regularTaskExecution.cpp"
|
|
|
|
using namespace std;
|
|
|
|
int main(int argc, char *argv[]) {
|
|
Utilities::config configuration;
|
|
if (argc > 1)
|
|
configuration.configPath = argv[1];
|
|
|
|
if (configuration.readConfigFile()) {
|
|
cout << "ERROR: Unable to read configuration file: " << configuration.configPath << endl;
|
|
cout << "Aborting Startup!" << endl;
|
|
return 1;
|
|
}
|
|
|
|
// Create app with Middleware
|
|
crow::App<crow::CookieParser> app;
|
|
|
|
// starts thread that executes modules
|
|
thread threadRegularExecution(RegularTaskExecution::regularExecution, configuration);
|
|
|
|
/*
|
|
* Freelancer Profile listing for customers
|
|
*/
|
|
CROW_ROUTE(app, "/").methods("POST"_method, "GET"_method)
|
|
([configuration]() {
|
|
auto page = crow::mustache::load("customerIndex_FreelancerListing.html");
|
|
crow::mustache::context ctx(Utilities::getFreelancerListing(configuration));
|
|
return page.render(ctx);
|
|
});
|
|
|
|
/*
|
|
* Freelancer Profile listing for customers
|
|
*/
|
|
CROW_ROUTE(app, "/@<string>")
|
|
([configuration](string alias) {
|
|
string redirectionHTML = "alias_Redirect.html";
|
|
crow::mustache::context ctx(getAlias(configuration, alias));
|
|
auto page = crow::mustache::load(redirectionHTML);
|
|
return page.render(ctx);
|
|
});
|
|
|
|
/*
|
|
* Freelancer Profile Page for customers
|
|
*/
|
|
CROW_ROUTE(app, "/customer/<string>").methods("POST"_method)
|
|
([configuration](const crow::request& postRequest, string freelancerName ) {
|
|
//Parses the request body and extracts the specified value
|
|
int freelancerID = stoi(Utilities::extractSingleValueFromRequestBody(postRequest.body.c_str(), "freelancerID"));
|
|
pqxx::connection databaseConnection(configuration.databaseConnectionString);
|
|
Database::prepareStatements(databaseConnection, {
|
|
ID_SELECT_FREELANCER,
|
|
ID_SELECT_FREELANCER_TEMPLATES
|
|
});
|
|
pqxx::result resultFreelancer = Database::executePreparedStatement_SELECT_FREELANCER(databaseConnection, freelancerID);
|
|
|
|
//error handling if invalid ID was delivered
|
|
string freelancerHTML = "customer_FreelancerListing_NOTFOUND.html";
|
|
|
|
crow::json::wvalue resultJsonFreelancerTemplate;
|
|
if (!resultFreelancer.empty()){
|
|
freelancerHTML = "customer_FreelancerListing.html";
|
|
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.empty()){
|
|
/*
|
|
* puts freelancer data into context
|
|
*/
|
|
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);
|
|
});
|
|
|
|
/*
|
|
* Page representing a freelancers Template
|
|
*/
|
|
CROW_ROUTE(app, "/customer/<string>/template/<string>").methods("POST"_method)
|
|
([configuration](const crow::request& postRequest, string freelancerName, string templateName ) {
|
|
int templateID = stoi(Utilities::extractSingleValueFromRequestBody(postRequest.body.c_str(), "templateID"));
|
|
|
|
pqxx::connection databaseConnection(configuration.databaseConnectionString);
|
|
Database::prepareStatements(databaseConnection, {
|
|
ID_SELECT_TEMPLATE,
|
|
ID_SELECT_FREELANCER_COMMISSION_STATE
|
|
});
|
|
pqxx::result resultTemplate = Database::executePreparedStatement_SELECT_TEMPLATE(databaseConnection, templateID);
|
|
|
|
crow::json::wvalue resultJsonTemplate = Database::convertResultRowToJSON(resultTemplate);
|
|
|
|
string templateHTML = "customer_Freelancer_Template.html";
|
|
auto page = crow::mustache::load(templateHTML);
|
|
|
|
crow::mustache::context ctx(resultJsonTemplate);
|
|
|
|
bool commissionState = false;
|
|
if (!resultTemplate.empty()) {
|
|
//use freelancerID based on SQL_STATEMENT_SELECT_TEMPLATE
|
|
pqxx::result resultCommissionState = Database::executePreparedStatement_SELECT_FREELANCER_COMMISSION_STATE(databaseConnection, stoi(resultTemplate.at(0).at(2).c_str()));
|
|
//the commissionstate
|
|
if (resultCommissionState.empty() || stoi(resultCommissionState.at(0).at(0).c_str()) == 1)
|
|
commissionState = true;
|
|
}
|
|
ctx["ERROR_COMMISSIONS_CLOSED"] = commissionState;
|
|
|
|
return page.render(ctx);
|
|
});
|
|
|
|
/*
|
|
* Page for entry of request data
|
|
*/
|
|
CROW_ROUTE(app, "/customer/<string>/template/<string>/request").methods("POST"_method)
|
|
([configuration](const crow::request& postRequest, string freelancerName, string templateName ) {
|
|
int templateID = stoi(Utilities::extractSingleValueFromRequestBody(postRequest.body.c_str(), "templateID"));
|
|
|
|
pqxx::connection databaseConnection(configuration.databaseConnectionString);
|
|
Database::prepareStatement(databaseConnection, ID_SELECT_TEMPLATE);
|
|
pqxx::result resultTemplate = Database::executePreparedStatement_SELECT_TEMPLATE(databaseConnection, templateID);
|
|
|
|
crow::json::wvalue resultJsonTemplate = Database::convertResultRowToJSON(resultTemplate);
|
|
|
|
string templateHTML = "customer_Freelancer_Template_Request.html";
|
|
auto page = crow::mustache::load(templateHTML);
|
|
|
|
crow::mustache::context ctx(resultJsonTemplate);
|
|
return page.render(ctx);
|
|
});
|
|
|
|
/*
|
|
* executes the creation of a new request.
|
|
*/
|
|
CROW_ROUTE(app, "/customer/<string>/template/<string>/request/fulfilment").methods("POST"_method)
|
|
([configuration](const crow::request& postRequest, string freelancerName, string templateName ) {
|
|
pqxx::connection databaseConnection(configuration.databaseConnectionString);
|
|
string templateHTML = "customer_Freelancer_Template_Request_Fulfilment_ERROR.html";
|
|
|
|
Database::requestsItem newRequest;
|
|
crow::mustache::context ctx;
|
|
|
|
ctx["freelancername"] = freelancerName;
|
|
ctx["templatename"] = templateName;
|
|
|
|
string postRequestBody = postRequest.body.c_str();
|
|
Utilities::decodeString(postRequestBody);
|
|
vector<string> splitPostRequestBody = Utilities::splitStringIntoVector(postRequestBody, '&');
|
|
bool requestFillCompletion = false;
|
|
for (const string& item : splitPostRequestBody) {
|
|
vector<string> splitItem = Utilities::splitStringIntoVector(item, '=');
|
|
if (splitItem.at(0) == "customername")
|
|
newRequest.customerName = splitItem.at(1);
|
|
if (splitItem.at(0) == "email")
|
|
newRequest.customerEmailAddress = splitItem.at(1);
|
|
if (splitItem.at(0) == "customercontactdetails")
|
|
newRequest.customerContactDetails = splitItem.at(1);
|
|
if (splitItem.at(0) == "requestdescription")
|
|
newRequest.requestDescription = splitItem.at(1);
|
|
if (splitItem.at(0) == "templateID")
|
|
newRequest.templateID = stoi(splitItem.at(1));
|
|
}
|
|
if (newRequest.customerName != "" && (newRequest.customerEmailAddress != "" || newRequest.customerContactDetails != "") && newRequest.requestDescription != "" )
|
|
requestFillCompletion = true;
|
|
|
|
ctx["templateid"] = newRequest.templateID;
|
|
|
|
Database::prepareStatements(databaseConnection, {
|
|
ID_SELECT_TEMPLATE_FLAT,
|
|
ID_SELECT_FREELANCER_COMMISSION_STATE,
|
|
ID_INSERT_ITEM_IN_REQUESTS,
|
|
ID_SELECT_FREELANCER_EMAIL
|
|
});
|
|
|
|
pqxx::result resultTemplate = Database::executePreparedStatement_SELECT_TEMPLATE_FLAT(databaseConnection, newRequest.templateID);
|
|
if (!resultTemplate.empty() && requestFillCompletion) {
|
|
for (int i = 0; i < resultTemplate.columns(); ++i) {
|
|
//freelancerid
|
|
newRequest.freelancerID = stoi(resultTemplate.at(0).at(0).c_str());
|
|
//currencypreference
|
|
newRequest.currencyPreference = resultTemplate.at(0).at(1).c_str();
|
|
//priceupfront
|
|
newRequest.priceUpFront = resultTemplate.at(0).at(2).c_str();
|
|
//priceondeliver
|
|
newRequest.priceOnDeliver = resultTemplate.at(0).at(3).c_str();
|
|
}
|
|
|
|
pqxx::result resultCommissionState = Database::executePreparedStatement_SELECT_FREELANCER_COMMISSION_STATE(databaseConnection, newRequest.freelancerID);
|
|
|
|
//the commissionstate
|
|
if (resultCommissionState.empty() || stoi(resultCommissionState.at(0).at(0).c_str()) == 1) {
|
|
ctx["ERROR_COMMISSIONS_CLOSED"] = true;
|
|
}
|
|
else {
|
|
int resultInsertOperation = Database::executePreparedStatement_INSERT_ITEM_IN_REQUESTS(databaseConnection, newRequest);
|
|
if (resultInsertOperation == 0) {
|
|
templateHTML = "customer_Freelancer_Template_Request_Fulfilment.html";
|
|
pqxx::result resultEmailAddress = Database::executePreparedStatement_SELECT_FREELANCER_EMAIL(databaseConnection, newRequest.freelancerID);
|
|
if (!resultEmailAddress.empty())
|
|
Utilities::sendEmail(configuration, resultEmailAddress.at(0).at(0).c_str(), "NEW REQUEST", newRequest.toJSONString());
|
|
}
|
|
else {
|
|
ctx["ERROR_UNABLE_TO_CREATE_REQUEST"] = true;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
if (requestFillCompletion)
|
|
ctx["ERROR_TEMPLATE_NOT_FOUND"] = true;
|
|
else
|
|
ctx["REQUEST_NOT_FILLED"] = true;
|
|
|
|
}
|
|
auto page = crow::mustache::load(templateHTML);
|
|
|
|
return page.render(ctx);
|
|
});
|
|
|
|
/*
|
|
* redirect to /freelancer/login
|
|
*/
|
|
CROW_ROUTE(app, "/login")
|
|
([](crow::response& res) {
|
|
res.redirect("/freelancer/login");
|
|
res.end();
|
|
});
|
|
|
|
/*
|
|
* redirect to /freelancer/logout
|
|
*/
|
|
CROW_ROUTE(app, "/logout")
|
|
([](crow::response& res) {
|
|
res.redirect("/freelancer/logout");
|
|
res.end();
|
|
});
|
|
|
|
/*
|
|
* Logs out a freelancer by replacing validation key and expiring cookies
|
|
*/
|
|
CROW_ROUTE(app, "/freelancer/logout")
|
|
([&, configuration](const crow::request& getRequest, crow::response& res) {
|
|
auto& ctx = app.get_context<crow::CookieParser>(getRequest);
|
|
pqxx::connection databaseConnection(configuration.databaseConnectionString);
|
|
string loginKey = ctx.get_cookie("loginKey");
|
|
string freelancerEmail = ctx.get_cookie("freelancerEmail");
|
|
if (!freelancerEmail.empty() && !loginKey.empty()) {
|
|
if (Utilities::checkFreelancerLoginState(configuration, loginKey, freelancerEmail)) {
|
|
Database::prepareStatement(databaseConnection, ID_UPDATE_LOGIN_VALIDATION_KEY);
|
|
Database::executePreparedStatement_UPDATE_LOGIN_VALIDATION_KEY(databaseConnection, "EXPIRED", freelancerEmail);
|
|
ctx.set_cookie("loginKey", Utilities::generateExpiredCookie());
|
|
ctx.set_cookie("freelancerEmail", Utilities::generateExpiredCookie());
|
|
}
|
|
}
|
|
res.redirect("/");
|
|
res.end();
|
|
});
|
|
|
|
|
|
/*
|
|
* Page for freelancer to log in
|
|
*/
|
|
CROW_ROUTE(app, "/freelancer/login")
|
|
([&,configuration](const crow::request& getRequest ) {
|
|
auto& ctx = app.get_context<crow::CookieParser>(getRequest);
|
|
string loginKey = ctx.get_cookie("loginKey");
|
|
string freelancerEmail = ctx.get_cookie("freelancerEmail");
|
|
string templateHTML = "freelancer_Login.html";
|
|
if (!freelancerEmail.empty() && !loginKey.empty()) {
|
|
if (Utilities::checkFreelancerLoginState(configuration, loginKey, freelancerEmail))
|
|
templateHTML = "freelancer_Redirect_Profile.html";
|
|
}
|
|
auto page = crow::mustache::load(templateHTML);
|
|
return page.render();
|
|
});
|
|
|
|
/*
|
|
* Page for freelancer to request a password reset email
|
|
*/
|
|
CROW_ROUTE(app, "/freelancer/login/passwordreset")
|
|
([]() {
|
|
auto page = crow::mustache::load("freelancer_Login_PasswordReset.html");
|
|
return page.render();
|
|
});
|
|
|
|
/*
|
|
* Page for freelancer password reset fulfilment
|
|
*/
|
|
CROW_ROUTE(app, "/freelancer/login/passwordreset/fulfilment")
|
|
([&, configuration](const crow::request& postRequest ) {
|
|
crow::mustache::context ctx;
|
|
string postRequestBody = postRequest.body;
|
|
Utilities::decodeString(postRequestBody);
|
|
vector<string> splitPostRequestBody = Utilities::splitStringIntoVector(postRequestBody, '&');
|
|
string email;
|
|
for (const string& item : splitPostRequestBody) {
|
|
vector<string> splitItem = Utilities::splitStringIntoVector(item, '=');
|
|
if (splitItem.at(0) == "freelanceremail")
|
|
email = splitItem.at(1);
|
|
}
|
|
|
|
if (!email.empty()) {
|
|
pqxx::connection databaseConnection(configuration.databaseConnectionString);
|
|
Database::prepareStatements(databaseConnection, {
|
|
ID_SELECT_CHECK_EMAIL_EXISTS,
|
|
ID_SELECT_CHECK_FREELANCER_RESET_KEY,
|
|
ID_DELETE_FREELANCER_RESET_KEY,
|
|
ID_INSERT_FREELANCER_RESET_KEY
|
|
});
|
|
pqxx::result checkFreelancerExists = Database::executePreparedStatement_SELECT_CHECK_EMAIL_EXISTS(databaseConnection, email);
|
|
int checkFreelancerExistsExtracted = stoi(checkFreelancerExists.at(0).at(0).c_str());
|
|
if (checkFreelancerExistsExtracted == 1) {
|
|
std::string passwordResetKey = Utilities::generateRandomHashValueSHA256();
|
|
|
|
pqxx::result checkFreelancerResetKeyExists = Database::executePreparedStatement_SELECT_CHECK_FREELANCER_RESET_KEY(databaseConnection, email);
|
|
int checkFreelancerResetKeyExistsExtracted = stoi(checkFreelancerResetKeyExists.at(0).at(0).c_str());
|
|
if (checkFreelancerResetKeyExistsExtracted > 0)
|
|
Database::executePreparedStatement_DELETE_FREELANCER_RESET_KEY(databaseConnection, email);
|
|
|
|
Database::executePreparedStatement_INSERT_FREELANCER_RESET_KEY(databaseConnection, email, passwordResetKey);
|
|
|
|
if (Utilities::sendPasswordResetEmail(configuration, email, passwordResetKey) == 0)
|
|
ctx["passwordresetmailsent"] = true;
|
|
}
|
|
ctx["resetemail"] = email;
|
|
}
|
|
auto page = crow::mustache::load("freelancer_Login_PasswordReset.html");
|
|
return page.render(ctx);
|
|
});
|
|
|
|
/*
|
|
* Page for freelancer to reset a password from a requested PasswordReset
|
|
*/
|
|
CROW_ROUTE(app, "/passwordreset/<string>")
|
|
([&, configuration](string passwordResetKey) {
|
|
crow::mustache::context ctx;
|
|
pqxx::connection databaseConnection(configuration.databaseConnectionString);
|
|
Database::prepareStatement(databaseConnection, ID_SELECT_FREELANCER_EMAIL_FROM_PASSWORD_RESET_KEY);
|
|
pqxx::result freelancerEmail = Database::executePreparedStatement_SELECT_FREELANCER_EMAIL_FROM_PASSWORD_RESET_KEY(databaseConnection, passwordResetKey);
|
|
if (!freelancerEmail.empty()) {
|
|
ctx["freelanceremail"] = freelancerEmail.at(0).at(0).c_str();
|
|
ctx["passwordresetkey"] = passwordResetKey;
|
|
}
|
|
else {
|
|
ctx["PASSWORD_RESET_DOES_NOT_EXIST"] = true;
|
|
}
|
|
auto page = crow::mustache::load("passwordReset.html");
|
|
return page.render(ctx);
|
|
});
|
|
|
|
/*
|
|
* Page for fulfillment of password reset
|
|
*/
|
|
CROW_ROUTE(app, "/passwordreset/<string>/fulfilment").methods("POST"_method)
|
|
([&, configuration](const crow::request& postRequest, string passwordResetKey) {
|
|
crow::mustache::context ctx;
|
|
string postRequestBody = postRequest.body;
|
|
Utilities::decodeString(postRequestBody);
|
|
vector<string> splitPostRequestBody = Utilities::splitStringIntoVector(postRequestBody, '&');
|
|
string password, passwordConfirmation;
|
|
for (const string& item : splitPostRequestBody) {
|
|
vector<string> splitItem = Utilities::splitStringIntoVector(item, '=');
|
|
if (splitItem.at(0) == "freelancerpassword")
|
|
password = splitItem.at(1);
|
|
if (splitItem.at(0) == "freelancerpasswordconfirmation")
|
|
passwordConfirmation = splitItem.at(1);
|
|
}
|
|
pqxx::connection databaseConnection(configuration.databaseConnectionString);
|
|
Database::prepareStatements(databaseConnection, {
|
|
ID_SELECT_FREELANCER_EMAIL_FROM_PASSWORD_RESET_KEY,
|
|
ID_SELECT_CHECK_FREELANCER_RESET_KEY_EXPIRED,
|
|
ID_DELETE_FREELANCER_RESET_KEY,
|
|
ID_UPDATE_FREELANCER_PASSWORD_HASH
|
|
});
|
|
pqxx::result freelancerEmail = Database::executePreparedStatement_SELECT_FREELANCER_EMAIL_FROM_PASSWORD_RESET_KEY(databaseConnection, passwordResetKey);
|
|
if (!freelancerEmail.empty() && !password.empty() && password.compare(passwordConfirmation) != 0) {
|
|
string email = freelancerEmail.at(0).at(0).c_str();
|
|
pqxx::result keyExpiration = Database::executePreparedStatement_SELECT_CHECK_FREELANCER_RESET_KEY_EXPIRED(databaseConnection, email);
|
|
if (stoi(keyExpiration.at(0).at(0).c_str()) == 0) {
|
|
Database::executePreparedStatement_DELETE_FREELANCER_RESET_KEY(databaseConnection, email);
|
|
string pwsalt = Utilities::generateSalt();
|
|
string pwhash = Utilities::hashPassword(pwsalt, password);
|
|
|
|
int errorLevel = Database::executePreparedStatement_UPDATE_FREELANCER_PASSWORD_HASH(databaseConnection, pwhash, pwsalt, email);
|
|
|
|
if (errorLevel == 0) {
|
|
ctx["RESET_SUCCESS"] = true;
|
|
ctx["freelanceremail"] = email;
|
|
}
|
|
else {
|
|
ctx["RESET_ERROR"] = true;
|
|
if (errorLevel == 1)
|
|
ctx["RESET_ERROR_QUERY"] = true;
|
|
if (errorLevel == 2)
|
|
ctx["RESET_ERROR_CRITICAL"] = true;
|
|
}
|
|
}
|
|
else {
|
|
ctx["PASSWORD_RESET_EXPIRED"] = true;
|
|
}
|
|
}
|
|
else {
|
|
if (password.empty())
|
|
ctx["PASSWORD_EMPTY"] = true;
|
|
if (freelancerEmail.empty())
|
|
ctx["PASSWORD_RESET_DOES_NOT_EXIST"] = true;
|
|
if (password.compare(passwordConfirmation) != 0)
|
|
ctx["PASSWORD_RESET_PASS_CONFIRMATION"] = true;
|
|
}
|
|
auto page = crow::mustache::load("passwordReset_Fulfillment.html");
|
|
return page.render(ctx);
|
|
});
|
|
|
|
/*
|
|
* Page for freelancer to log in fulfillment
|
|
*/
|
|
CROW_ROUTE(app, "/freelancer/login/fulfilment").methods("POST"_method)
|
|
([&, configuration](const crow::request& postRequest ) {
|
|
crow::mustache::context ctx;
|
|
string postRequestBody = postRequest.body;
|
|
Utilities::decodeString(postRequestBody);
|
|
vector<string> splitPostRequestBody = Utilities::splitStringIntoVector(postRequestBody, '&');
|
|
string email, password;
|
|
bool stayLoggedIn;
|
|
|
|
for (const string& item : splitPostRequestBody) {
|
|
vector<string> splitItem = Utilities::splitStringIntoVector(item, '=');
|
|
if (splitItem.at(0) == "freelanceremail")
|
|
email = splitItem.at(1);
|
|
if (splitItem.at(0) == "freelancerpassword")
|
|
password = splitItem.at(1);
|
|
if (splitItem.at(0) == "stayloggedin")
|
|
stayLoggedIn = !splitItem.at(1).empty(); //if checkbox not set result is empty ie stay logged in is false, if it is set result is "on" ie not empty ie stay logged in is true
|
|
}
|
|
|
|
//check if login data is complete
|
|
if (!email.empty() && !password.empty()){
|
|
//check if freelancer exists
|
|
pqxx::connection databaseConnection(configuration.databaseConnectionString);
|
|
Database::prepareStatements(databaseConnection, {
|
|
ID_SELECT_CHECK_EMAIL_EXISTS,
|
|
ID_SELECT_FREELANCER_SALT,
|
|
ID_SELECT_CHECK_HASH_VALID,
|
|
ID_UPDATE_LOGIN_VALIDATION_KEY
|
|
});
|
|
pqxx::result checkFreelancerExists = Database::executePreparedStatement_SELECT_CHECK_EMAIL_EXISTS(databaseConnection, email);
|
|
int checkFreelancerExistsExtracted = stoi(checkFreelancerExists.at(0).at(0).c_str());
|
|
if (checkFreelancerExistsExtracted == 1) {
|
|
pqxx::result freelancerSalt = Database::executePreparedStatement_SELECT_FREELANCER_SALT(databaseConnection, email);
|
|
string salt = freelancerSalt.at(0).at(0).c_str();
|
|
string hash = Utilities::hashPassword(salt, password);
|
|
pqxx::result checkFreelancerHash = Database::executePreparedStatement_SELECT_CHECK_HASH_VALID(databaseConnection, email, hash);
|
|
int checkFreelancerHashExtracted = stoi(checkFreelancerHash.at(0).at(0).c_str());
|
|
if (checkFreelancerHashExtracted == 1) {
|
|
//create secureCookie
|
|
auto& cookieCtx = app.get_context<crow::CookieParser>(postRequest);
|
|
std::string loginKeyValue = Utilities::generateRandomHashValueSHA512();
|
|
Database::executePreparedStatement_UPDATE_LOGIN_VALIDATION_KEY(databaseConnection, loginKeyValue, email);
|
|
std::string loginKeyCookieValue = Utilities::generateSecureCookieLoginKeyValue(loginKeyValue, stayLoggedIn);
|
|
std::string freelancerEmailCookieValue = Utilities::generateSecureCookieFreelancerEmailValue(email, stayLoggedIn);
|
|
cookieCtx.set_cookie("loginKey", loginKeyCookieValue);
|
|
cookieCtx.set_cookie("freelancerEmail",freelancerEmailCookieValue);
|
|
ctx["LOGIN_SUCCESS"] = true;
|
|
}
|
|
else {
|
|
ctx["LOGIN_ERROR"] = true;
|
|
ctx["LOGIN_ERROR_LOGIN_DATA_INVALID"] = true;
|
|
}
|
|
}
|
|
else {
|
|
ctx["LOGIN_ERROR"] = true;
|
|
ctx["LOGIN_ERROR_LOGIN_DATA_INVALID"] = true;
|
|
}
|
|
}
|
|
else {
|
|
ctx["LOGIN_ERROR"] = true;
|
|
ctx["LOGIN_ERROR_EMAIL_PASS_NOT_FILLED"] = true;
|
|
}
|
|
|
|
|
|
string templateHTML = "freelancer_Login_Fulfilment.html";
|
|
auto page = crow::mustache::load(templateHTML);
|
|
|
|
return page.render(ctx);
|
|
});
|
|
|
|
/*
|
|
* Page for freelancer to sign up
|
|
*/
|
|
CROW_ROUTE(app, "/freelancer/signup")
|
|
([&, configuration](const crow::request& getRequest ) {
|
|
auto& ctx = app.get_context<crow::CookieParser>(getRequest);
|
|
string loginKey = ctx.get_cookie("loginKey");
|
|
string freelancerEmail = ctx.get_cookie("freelancerEmail");
|
|
string templateHTML = "freelancer_Signup.html";
|
|
if (!freelancerEmail.empty() && !loginKey.empty()) {
|
|
if (Utilities::checkFreelancerLoginState(configuration, loginKey, freelancerEmail))
|
|
templateHTML = "freelancer_Redirect_Profile.html";
|
|
}
|
|
auto page = crow::mustache::load(templateHTML);
|
|
return page.render();
|
|
});
|
|
|
|
/*
|
|
* Page for freelancer to sign up fulfillment
|
|
*/
|
|
CROW_ROUTE(app, "/freelancer/signup/fulfilment").methods("POST"_method)
|
|
([configuration](const crow::request& postRequest ) {
|
|
crow::mustache::context ctx;
|
|
|
|
string postRequestBody = postRequest.body;
|
|
Utilities::decodeString(postRequestBody);
|
|
vector<string> splitPostRequestBody = Utilities::splitStringIntoVector(postRequestBody, '&');
|
|
|
|
string name, email, password, passwordConfirmation;
|
|
|
|
bool requestFillCompletion = false;
|
|
for (const string& item : splitPostRequestBody) {
|
|
vector<string> splitItem = Utilities::splitStringIntoVector(item, '=');
|
|
if (splitItem.at(0) == "freelancername")
|
|
name = splitItem.at(1);
|
|
if (splitItem.at(0) == "freelanceremail")
|
|
email = splitItem.at(1);
|
|
if (splitItem.at(0) == "freelancerpassword")
|
|
password = splitItem.at(1);
|
|
if (splitItem.at(0) == "freelancerpasswordconfirmation")
|
|
passwordConfirmation = splitItem.at(1);
|
|
}
|
|
|
|
//check if signup data is complete
|
|
if (!email.empty() && !name.empty() && !password.empty() && password.compare(passwordConfirmation) != 0)
|
|
requestFillCompletion = true;
|
|
|
|
if (requestFillCompletion) {
|
|
//check if email address hasn't been registered yet
|
|
pqxx::connection databaseConnection(configuration.databaseConnectionString);
|
|
Database::prepareStatements(databaseConnection, {
|
|
ID_SELECT_CHECK_EMAIL_EXISTS,
|
|
ID_INSERT_NEW_FREELANCER
|
|
});
|
|
pqxx::result checkResult = Database::executePreparedStatement_SELECT_CHECK_EMAIL_EXISTS(databaseConnection, email);
|
|
int checkResultExtracted = stoi(checkResult.at(0).at(0).c_str());
|
|
|
|
if (checkResultExtracted == 0) {
|
|
string pwsalt, pwhash;
|
|
pwsalt = Utilities::generateSalt();
|
|
pwhash = Utilities::hashPassword(pwsalt, password);
|
|
|
|
int errorLevel = Database::executePreparedStatement_INSERT_NEW_FREELANCER(databaseConnection, email, name, pwsalt, pwhash);
|
|
|
|
if (errorLevel == 0) {
|
|
ctx["REGISTRATION_SUCCESS"] = true;
|
|
ctx["freelancername"] = name;
|
|
ctx["freelanceremail"] = email;
|
|
}
|
|
else {
|
|
ctx["REGISTRATION_ERROR"] = true;
|
|
if (errorLevel == 1)
|
|
ctx["REGISTRATION_ERROR_QUERY"] = true;
|
|
if (errorLevel == 2)
|
|
ctx["REGISTRATION_ERROR_CRITICAL"] = true;
|
|
}
|
|
}
|
|
else {
|
|
ctx["REGISTRATION_ERROR"] = true;
|
|
ctx["freelanceremail"] = email;
|
|
ctx["REGISTRATION_ERROR_EMAIL_ALREADY_IN_USE"] = true;
|
|
}
|
|
}
|
|
else {
|
|
ctx["REGISTRATION_ERROR"] = true;
|
|
if (password.compare(passwordConfirmation) != 0)
|
|
ctx["REGISTRATION_ERROR_PASS_CONFIRMATION"] = true;
|
|
ctx["REGISTRATION_ERROR_EMAIL_NAME_PASS_NOT_FILLED"] = true;
|
|
}
|
|
|
|
string templateHTML = "freelancer_Signup_Fulfilment.html";
|
|
|
|
auto page = crow::mustache::load(templateHTML);
|
|
|
|
return page.render(ctx);
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*CROW_ROUTE(app, "/getEntry/<int>")
|
|
([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.ssl_file(configuration.sslCrtPath, configuration.sslKeyPath);
|
|
app.port(18080).multithreaded().run();
|
|
}
|