#include #include #include #include #include #include "crow.h" #include "crow/middlewares/cookie_parser.h" #include "database.cpp" #include "utilities.cpp" #include "regularTaskExecution.cpp" #include "templateConstCollection.cpp" using namespace std; using namespace TemplateConstCollection; 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 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](const crow::request& request) { int selectedPage = 1; if (!request.url_params.keys().empty()) { string selectedPageString = request.url_params.get("page"); if (!selectedPageString.empty()) selectedPage = stoi(selectedPageString); } auto page = crow::mustache::load(TEMPLATE_CUSTOMER_INDEX_FREELANCER_LISTING); crow::mustache::context ctx(Utilities::getFreelancerListing(configuration, selectedPage)); if (configuration.itemsPerPage > 0) { ctx[MUSTACHE_PAGINATION] = true; vector pages = Utilities::getFreelancerIndexPagination(configuration); ctx[MUSTACHE_PAGINATION_NUMBERS] = pages; if (selectedPage <= 1) ctx[MUSTACHE_PAGINATION_PREVIOUS] = 1; else ctx[MUSTACHE_PAGINATION_PREVIOUS] = selectedPage - 1; if (selectedPage >= pages.size()) ctx[MUSTACHE_PAGINATION_NEXT] = pages.size(); else ctx[MUSTACHE_PAGINATION_NEXT] = selectedPage + 1; } return page.render(ctx); }); /* * Freelancer Profile listing for customers */ CROW_ROUTE(app, "/@") ([configuration](string alias) { crow::mustache::context ctx(getAlias(configuration, alias)); auto page = crow::mustache::load(TEMPLATE_ALIAS_REDIRECT); return page.render(ctx); }); /* * Freelancer Profile Page for customers */ CROW_ROUTE(app, "/customer/").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 = TEMPLATE_CUSTOMER_FREELANCER_LISTING_NOT_FOUND; crow::json::wvalue resultJsonFreelancerTemplate; if (!resultFreelancer.empty()){ freelancerHTML = TEMPLATE_CUSTOMER_FREELANCER_LISTING; 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//template/").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); auto page = crow::mustache::load(TEMPLATE_CUSTOMER_FREELANCER_TEMPLATE); 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[MUSTACHE_ERROR_COMMISSIONS_CLOSED] = commissionState; return page.render(ctx); }); /* * Page for entry of request data */ CROW_ROUTE(app, "/customer//template//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); auto page = crow::mustache::load(TEMPLATE_CUSTOMER_FREELANCER_TEMPLATE_REQUEST); crow::mustache::context ctx(resultJsonTemplate); return page.render(ctx); }); /* * executes the creation of a new request. */ CROW_ROUTE(app, "/customer//template//request/fulfilment").methods("POST"_method) ([configuration](const crow::request& postRequest, string freelancerName, string templateName ) { pqxx::connection databaseConnection(configuration.databaseConnectionString); string templateHTML = TEMPLATE_CUSTOMER_FREELANCER_TEMPLATE_REQUEST_FULFILMENT_ERROR; Database::requestsItem newRequest; crow::mustache::context ctx; ctx["freelancername"] = freelancerName; ctx["templatename"] = templateName; string postRequestBody = postRequest.body.c_str(); Utilities::decodeString(postRequestBody); vector splitPostRequestBody = Utilities::splitStringIntoVector(postRequestBody, '&'); bool requestFillCompletion = false; for (const string& item : splitPostRequestBody) { vector 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[MUSTACHE_ERROR_COMMISSIONS_CLOSED] = true; } else { int resultInsertOperation = Database::executePreparedStatement_INSERT_ITEM_IN_REQUESTS(databaseConnection, newRequest); if (resultInsertOperation == 0) { templateHTML = TEMPLATE_CUSTOMER_FREELANCER_TEMPLATE_REQUEST_FULFILMENT; 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[MUSTACHE_ERROR_UNABLE_TO_CREATE_REQUEST] = true; } } } else { if (requestFillCompletion) ctx[MUSTACHE_ERROR_TEMPLATE_NOT_FOUND] = true; else ctx[MUSTACHE_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(getRequest); if (Utilities::checkCookieLoginState(configuration, ctx)) { std::string freelancerEmail = ctx.get_cookie("freelancerEmail"); pqxx::connection databaseConnection(configuration.databaseConnectionString); 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(getRequest); string templateHTML = TEMPLATE_FREELANCER_LOGIN; if (Utilities::checkCookieLoginState(configuration, ctx)) templateHTML = TEMPLATE_FREELANCER_REDIRECT_PROFILE; 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(TEMPLATE_FREELANCER_LOGIN_PASSWORD_RESET); 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 splitPostRequestBody = Utilities::splitStringIntoVector(postRequestBody, '&'); string email; for (const string& item : splitPostRequestBody) { vector 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(TEMPLATE_FREELANCER_LOGIN_PASSWORD_RESET_FULFILMENT); return page.render(ctx); }); /* * Page for freelancer to reset a password from a requested PasswordReset */ CROW_ROUTE(app, "/passwordreset/") ([&, 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[MUSTACHE_PASSWORD_RESET_DOES_NOT_EXIST] = true; } auto page = crow::mustache::load(TEMPLATE_PASSWORD_RESET); return page.render(ctx); }); /* * Page for fulfillment of password reset */ CROW_ROUTE(app, "/passwordreset//fulfilment").methods("POST"_method) ([&, configuration](const crow::request& postRequest, string passwordResetKey) { crow::mustache::context ctx; string postRequestBody = postRequest.body; Utilities::decodeString(postRequestBody); vector splitPostRequestBody = Utilities::splitStringIntoVector(postRequestBody, '&'); string password, passwordConfirmation; for (const string& item : splitPostRequestBody) { vector 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[MUSTACHE_RESET_SUCCESS] = true; ctx["freelanceremail"] = email; } else { ctx[MUSTACHE_RESET_ERROR] = true; if (errorLevel == 1) ctx[MUSTACHE_RESET_ERROR_QUERY] = true; if (errorLevel == 2) ctx[MUSTACHE_RESET_ERROR_CRITICAL] = true; } } else { ctx[MUSTACHE_PASSWORD_RESET_EXPIRED] = true; } } else { if (password.empty()) ctx[MUSTACHE_PASSWORD_EMPTY] = true; if (freelancerEmail.empty()) ctx[MUSTACHE_PASSWORD_RESET_DOES_NOT_EXIST] = true; if (password.compare(passwordConfirmation) != 0) ctx[MUSTACHE_PASSWORD_RESET_PASS_CONFIRMATION] = true; } auto page = crow::mustache::load(TEMPLATE_PASSWORD_RESET_FULFILMENT); 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 splitPostRequestBody = Utilities::splitStringIntoVector(postRequestBody, '&'); string email, password; bool stayLoggedIn; for (const string& item : splitPostRequestBody) { vector 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, ID_SELECT_CHECK_LOGIN_LOCK_OUT, ID_SELECT_GET_LOGIN_LOCK_OUT_MINUTES }); pqxx::result checkloginLockedOut = Database::executePreparedStatement_SELECT_CHECK_LOGIN_LOCK_OUT(databaseConnection, email); string checkloginLockedOutExtracted = checkloginLockedOut.at(0).at(0).c_str(); if (checkloginLockedOutExtracted != "true") { 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(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[MUSTACHE_LOGIN_SUCCESS] = true; } else { ctx[MUSTACHE_LOGIN_ERROR] = true; ctx[MUSTACHE_LOGIN_ERROR_LOGIN_DATA_INVALID] = true; Utilities::loginLockOutIncrement(configuration, databaseConnection, email); } } else { ctx[MUSTACHE_LOGIN_ERROR] = true; ctx[MUSTACHE_LOGIN_ERROR_LOGIN_DATA_INVALID] = true; } } else { pqxx::result loginLockOutInMinutes = Database::executePreparedStatement_SELECT_GET_LOGIN_LOCK_OUT_MINUTES(databaseConnection, email); ctx[MUSTACHE_LOGIN_ERROR] = true; ctx[MUSTACHE_LOGIN_ERROR_LOCKED_OUT] = true; ctx[MUSTACHE_LOGIN_ERROR_LOCKED_OUT_MINUTES] = loginLockOutInMinutes.at(0).at(0).c_str(); } } else { ctx[MUSTACHE_LOGIN_ERROR] = true; ctx[MUSTACHE_LOGIN_ERROR_EMAIL_PASS_NOT_FILLED] = true; } auto page = crow::mustache::load(TEMPLATE_FREELANCER_LOGIN_FULFILMENT); 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(getRequest); string loginKey = ctx.get_cookie("loginKey"); string freelancerEmail = ctx.get_cookie("freelancerEmail"); string templateHTML = TEMPLATE_FREELANCER_SIGN_UP; if (!freelancerEmail.empty() && !loginKey.empty()) { if (Utilities::checkFreelancerLoginState(configuration, loginKey, freelancerEmail)) templateHTML = TEMPLATE_FREELANCER_REDIRECT_PROFILE; } 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 splitPostRequestBody = Utilities::splitStringIntoVector(postRequestBody, '&'); string name, email, password, passwordConfirmation; bool requestFillCompletion = false; for (const string& item : splitPostRequestBody) { vector 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[MUSTACHE_REGISTRATION_SUCCESS] = true; ctx["freelancername"] = name; ctx["freelanceremail"] = email; } else { ctx[MUSTACHE_REGISTRATION_ERROR] = true; if (errorLevel == 1) ctx[MUSTACHE_REGISTRATION_ERROR_QUERY] = true; if (errorLevel == 2) ctx[MUSTACHE_REGISTRATION_ERROR_CRITICAL] = true; } } else { ctx[MUSTACHE_REGISTRATION_ERROR] = true; ctx["freelanceremail"] = email; ctx[MUSTACHE_REGISTRATION_ERROR_EMAIL_ALREADY_IN_USE] = true; } } else { ctx[MUSTACHE_REGISTRATION_ERROR] = true; if (password.compare(passwordConfirmation) != 0) ctx[MUSTACHE_REGISTRATION_ERROR_PASS_CONFIRMATION] = true; ctx[MUSTACHE_REGISTRATION_ERROR_EMAIL_NAME_PASS_NOT_FILLED] = true; } auto page = crow::mustache::load(TEMPLATE_FREELANCER_SIGN_UP_FULFILMENT); 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.ssl_file(configuration.sslCrtPath, configuration.sslKeyPath); app.port(18080).multithreaded().run(); }