cavecomm/src/utilities.cpp

632 lines
28 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#ifndef UTILITIES_CPP
#define UTILITIES_CPP
#include <string>
#include <map>
#include <iostream>
#include <random>
#include <utility>
#include <vector>
#include <iomanip>
#include <stdexcept>
#include <chrono>
#include <thread>
#include <cmath>
#include <openssl/sha.h>
#include <pqxx/pqxx>
#include "crow.h"
#include "crow/middlewares/cookie_parser.h"
#include "cpp/opportunisticsecuresmtpclient.hpp"
#include "cpp/htmlmessage.hpp"
#include "emailTemplateCollection.cpp"
#include "templateConstCollection.cpp"
using namespace jed_utils::cpp;
using namespace DatabaseStatementConstCollection;
using namespace TemplateConstCollection;
/*
* Utility Manager
*/
namespace Utilities {
const static std::unordered_map<std::string, std::string> HTML_URL_CODES = {{"%20", " "}, {"%21", "!"}, {"%22", "\""}, {"%23", "#"}, {"%24", "$"}, {"%25", "%"}, {"%26", "&"}, {"%27", "'"}, {"%28", "("}, {"%29", ")"}, {"%2A", "*"}, {"%2B", "+"}, {"%2C", ","}, {"%2D", "-"}, {"%2E", "."}, {"%2F", "/"}, {"%30", "0"}, {"%31", "1"}, {"%32", "2"}, {"%33", "3"}, {"%34", "4"}, {"%35", "5"}, {"%36", "6"}, {"%37", "7"}, {"%38", "8"}, {"%39", "9"}, {"%3A", ":"}, {"%3B", ";"}, {"%3C", "<"}, {"%3D", "="}, {"%3E", ">"}, {"%3F", "?"}, {"%40", "@"}, {"%5B", "["}, {"%5C", "\\"}, {"%5D", "]"}, {"%5E", "^"}, {"%5F", "_"}, {"%60", "`"}, {"%7B", "{"}, {"%7C", "|"}, {"%7D", "}"}, {"%7E", "~"}, {"%7F", " "}, {"%80", ""}, {"%82", ""}, {"%83", "ƒ"}, {"%84", ""}, {"%85", ""}, {"%86", ""}, {"%87", ""}, {"%88", "ˆ"}, {"%89", ""}, {"%8A", "Š"}, {"%8B", ""}, {"%8C", "Œ"}, {"%8E", "Ž"}, {"%91", ""}, {"%92", ""}, {"%93", ""}, {"%94", ""}, {"%95", ""}, {"%96", ""}, {"%97", ""}, {"%98", "˜"}, {"%99", ""}, {"%9A", "š"}, {"%9B", ""}, {"%9C", "œ"}, {"%9E", "ž"}, {"%9F", "Ÿ"}, {"%A1", "¡"}, {"%A2", "¢"}, {"%A3", "£"}, {"%A4", "¤"}, {"%A5", "¥"}, {"%A6", "¦"}, {"%A7", "§"}, {"%A8", "¨"}, {"%A9", "©"}, {"%AA", "ª"}, {"%AB", "«"}, {"%AC", "¬"}, {"%AE", "®"}, {"%AF", "¯"}, {"%B0", "°"}, {"%B1", "±"}, {"%B2", "²"}, {"%B3", "³"}, {"%B4", "´"}, {"%B5", "µ"}, {"%B6", ""}, {"%B7", "·"}, {"%B8", "¸"}, {"%B9", "¹"}, {"%BA", "º"}, {"%BB", "»"}, {"%BC", "¼"}, {"%BD", "½"}, {"%BE", "¾"}, {"%BF", "¿"}, {"%C0", "À"}, {"%C1", "Á"}, {"%C2", "Â"}, {"%C3", "Ã"}, {"%C4", "Ä"}, {"%C5", "Å"}, {"%C6", "Æ"}, {"%C7", "Ç"}, {"%C8", "È"}, {"%C9", "É"}, {"%CA", "Ê"}, {"%CB", "Ë"}, {"%CC", "Ì"}, {"%CD", "Í"}, {"%CE", "Î"}, {"%CF", "Ï"}, {"%D0", "Ð"}, {"%D1", "Ñ"}, {"%D2", "Ò"}, {"%D3", "Ó"}, {"%D4", "Ô"}, {"%D5", "Õ"}, {"%D6", "Ö"}, {"%D7", "×"}, {"%D8", "Ø"}, {"%D9", "Ù"}, {"%DA", "Ú"}, {"%DB", "Û"}, {"%DC", "Ü"}, {"%DD", "Ý"}, {"%DE", "Þ"}, {"%DF", "ß"}, {"%E0", "à"}, {"%E1", "á"}, {"%E2", "â"}, {"%E3", "ã"}, {"%E4", "ä"}, {"%E5", "å"}, {"%E6", "æ"}, {"%E7", "ç"}, {"%E8", "è"}, {"%E9", "é"}, {"%EA", "ê"}, {"%EB", "ë"}, {"%EC", "ì"}, {"%ED", "í"}, {"%EE", "î"}, {"%EF", "ï"}, {"%F0", "ð"}, {"%F1", "ñ"}, {"%F2", "ò"}, {"%F3", "ó"}, {"%F4", "ô"}, {"%F5", "õ"}, {"%F6", "ö"}, {"%F7", "÷"}, {"%F8", "ø"}, {"%F9", "ù"}, {"%FA", "ú"}, {"%FB", "û"}, {"%FC", "ü"}, {"%FD", "ý"}, {"%FE", "þ"}, {"%FF", "ÿ"}};
const static int SALT_SIZE = 32;
const static std::string SALT_CHAR_SET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
const static std::string MODULE_NAME_BRUTE_FORCE_MITIGATION_CLEANER = "bruteForceMitigationCleaner";
const static std::string MODULE_NAME_FREELANCER_RESET_KEY_CLEANER = "freelancerResetKeyCleaner";
/*
* Takes string to split it into a vector based on a given delimiter
*/
std::vector<std::string> splitStringIntoVector(const std::string& stringToSplit, char delimiter) {
std::vector<std::string> splitVector;
std::istringstream stringStream(stringToSplit);
while (!stringStream.eof()) {
std::string splitResult;
std::getline( stringStream, splitResult, delimiter);
splitVector.push_back(splitResult);
}
return splitVector;
}
std::string trimFromDelimiter(std::string stringToTrim, char delimiter) {
std::size_t position = stringToTrim.find(delimiter);
if (position != std::string::npos)
return stringToTrim.substr(0, position);
return stringToTrim;
}
/*
* Checks if a given string is a valid number
*/
bool checkIfStrIsNumber(const std::string& numberString) {
try {
std::stod(numberString);
}
catch (const std::invalid_argument& ia) {
return false;
}
return true;
}
/*
* Struct representing the configuration file
*/
struct config {
std::string configPath = "cavecomm.conf";
std::string databaseConnectionString;
std::string emailAddress;
std::string emailPassword;
std::string emailServerAddress;
int emailServerPort = 587;
std::string emailAddressDisplay = "Cavecomm Automated Management System";
std::string sslCrtPath;
std::string sslKeyPath;
std::string domain;
bool regularTaskExecution = true;
int regularTaskExecutionIntervalSeconds = 900;
std::unordered_map<std::string, bool> regularTaskExecutionModules = {
{MODULE_NAME_BRUTE_FORCE_MITIGATION_CLEANER, false},
{MODULE_NAME_FREELANCER_RESET_KEY_CLEANER, false}
};
int itemsPerPage = 20;
int bruteForceMitigationLockSeconds = 900;
int bruteForceMitigationAttempts = 5;
/*
* validates existence of mandatory variables in config
* returns 0 if successful else 1
*/
int checkMandatoryVariables() const {
if (
emailAddress.empty()
|| emailPassword.empty()
|| emailServerAddress.empty()
|| databaseConnectionString.empty()
|| sslCrtPath.empty()
|| sslKeyPath.empty()
|| domain.empty()
)
return 1;
return 0;
}
/*
* Parses the config file and fills the struct.
* returns 0 if successful else 1
*/
int readConfigFile(){
int errorLevel = 0;
std::ifstream configFile(configPath);
std::cout << "Loading Configuration: " << configPath << std::endl;
if (configFile.good()) {
bool sanityCheckStart = true;
std::string line;
while (std::getline(configFile, line))
{
if (sanityCheckStart) {
if (line.find("#configstart#") != std::string::npos) {
sanityCheckStart = false;
continue;
}
else {
errorLevel = 1;
std::cout << "ERROR: Config file is invalid" << std::endl;
break;
}
}
else {
if (line.size() <= 1)
continue;
}
if (line.find("#configend#") != std::string::npos)
break;
if (line.at(0) == '#') {
std::cout << "COMMENT: ";
std::cout << line << std::endl;
}
else {
std::cout << "CONFIG: ";
std::vector<std::string> lineVector = Utilities::splitStringIntoVector(line, '=');
if (lineVector.size() == 2) {
std::cout << lineVector.at(0) << " - " << lineVector.at(1) << std::endl;
std::string lineString = trimFromDelimiter(lineVector.at(1), ';');
if (lineString.empty())
continue;
if (lineVector.at(0) == "emailAddress") {
emailAddress = lineString;
continue;
}
if (lineVector.at(0) == "emailPassword") {
emailPassword = lineString;
continue;
}
if (lineVector.at(0) == "emailServerAddress") {
emailServerAddress = lineString;
continue;
}
if (lineVector.at(0) == "emailServerPort") {
emailServerPort = std::stoi(lineString);
continue;
}
if (lineVector.at(0) == "emailAddressDisplay") {
emailAddressDisplay = lineString;
continue;
}
if (lineVector.at(0) == "databaseConnectionString") {
databaseConnectionString = lineString;
continue;
}
if (lineVector.at(0) == "sslCrtPath") {
sslCrtPath = lineString;
continue;
}
if (lineVector.at(0) == "sslKeyPath") {
sslKeyPath = lineString;
continue;
}
if (lineVector.at(0) == "domain") {
domain = lineString;
continue;
}
if (lineVector.at(0) == "regularTaskExecution") {
regularTaskExecution = (lineString == "true");
continue;
}
if (lineVector.at(0) == "regularTaskExecutionIntervalSeconds") {
regularTaskExecutionIntervalSeconds = std::stoi(lineString);
continue;
}
if (lineVector.at(0) == "regularTaskExecutionModules") {
std::vector<std::string> modules = Utilities::splitStringIntoVector(lineString, '|');
for (const std::string& module : modules) {
regularTaskExecutionModules.at(module) = true;
}
continue;
}
if (lineVector.at(0) == "itemsPerPage") {
itemsPerPage = std::stoi(lineString);
continue;
}
if (lineVector.at(0) == "bruteForceMitigationLockSeconds") {
bruteForceMitigationLockSeconds = std::stoi(lineString);
continue;
}
if (lineVector.at(0) == "bruteForceMitigationAttempts") {
bruteForceMitigationAttempts = std::stoi(lineString);
continue;
}
}
}
}
}
else {
errorLevel = 1;
}
if (errorLevel == 0)
errorLevel = checkMandatoryVariables();
return errorLevel;
}
};
/*
* Struct representing a freelancers template
*/
struct templateItem {
std::string name;
std::string content;
std::string contactdata;
std::string contactinformation;
std::string currencypreference;
std::string priceupfront;
std::string priceondeliver;
/*
* Parses a decoded request body string and fills the struct
*/
void parseRequestBodyIntoItem(const std::string& requestBody) {
std::vector<std::string> splitPostRequestBody = Utilities::splitStringIntoVector(requestBody, '&');
for (const std::string& item : splitPostRequestBody) {
std::vector<std::string> splitItem = Utilities::splitStringIntoVector(item, '=');
if (splitItem[0] == "templatename")
name = splitItem[1];
if (splitItem[0] == "templatecontent")
content = splitItem[1];
if (splitItem[0] == "templatecontactdata")
contactdata = splitItem[1];
if (splitItem[0] == "templatecontactinformation")
contactinformation = splitItem[1];
if (splitItem[0] == "templatecurrencypreference")
currencypreference = splitItem[1];
if (splitItem[0] == "templatepriceupfront")
priceupfront = splitItem[1];
if (splitItem[0] == "templatepriceondeliver")
priceondeliver = splitItem[1];
}
if (name.empty())
name = "unnamed";
if (!checkIfStrIsNumber(priceupfront))
priceupfront = "0";
if (!checkIfStrIsNumber(priceondeliver))
priceondeliver = "0";
}
void outputItem() {
std::cout << name << " " << content << " " << contactdata << " " << contactinformation << " " << currencypreference
<< " " << priceupfront << "-" << priceondeliver << " " << std::endl;
}
};
/*
* Takes String and cuts from the start-up to the length of valueName
*/
std::string extractSingleValueFromRequestBody(const std::string& responseBody, const std::string& valueName) {
return responseBody.substr(valueName.length() + 1, responseBody.length());
}
/*
* replaces a string with another string within a string
*/
void replaceString(std::string &stringToProcess, const std::string& from, const std::string& to) {
std::size_t stringPosition = stringToProcess.find(from);
while (stringPosition != std::string::npos) {
stringToProcess.replace(stringToProcess.find(from), std::string(from).size(), to);
stringPosition = stringToProcess.find(from);
}
}
/*
* decodes html coded chars
*/
void decodeString(std::string &stringToDecode) {
replaceString(stringToDecode, "+", " ");
for(const auto & it : HTML_URL_CODES) {
replaceString(stringToDecode, it.first, it.second);
}
}
/*
* Sends an HTML Email using CPP-SMTPClient-library
* return 0 at success, 1 at client fail, 2 at critical fail.
*/
int sendEmail(const config& configuration, const std::string& destinationEmail, std::string emailSubject, std::string htmlBody){
OpportunisticSecureSMTPClient client(configuration.emailServerAddress, configuration.emailServerPort);
client.setCredentials(Credential(configuration.emailAddress, configuration.emailPassword));
try {
const MessageAddress from(configuration.emailAddress, configuration.emailAddressDisplay);
const auto to = { MessageAddress(destinationEmail) };
const auto subject = std::move(emailSubject);
const auto body = std::move(htmlBody);
const std::vector<MessageAddress> cc = {};
const std::vector<MessageAddress> bcc = {};
const std::vector<Attachment> attachments = {};
HTMLMessage msg(from, to, subject, body, cc, bcc, attachments);
int err_no = client.sendMail(msg);
if (err_no != 0) {
std::cerr << client.getCommunicationLog() << '\n';
std::string errorMessage = OpportunisticSecureSMTPClient::getErrorMessage(err_no);
std::cerr << "An error occurred: " << errorMessage
<< " (error no: " << err_no << ")" << '\n';
return 1;
}
std::cout << client.getCommunicationLog() << '\n';
std::cout << "Operation completed!" << std::endl;
}
catch (std::invalid_argument &err) {
std::cerr << err.what() << std::endl;
return 2;
}
return 0;
}
/*
* Sends a Password Reset Email
* return 0 at success, 1 at client fail, 2 at critical fail.
*/
int sendPasswordResetEmail(const config& configuration, const std::string& email, const std::string& passwordResetKey) {
std::string emailContent = EmailTemplateCollection::passwordResetEmail(configuration.domain, email, passwordResetKey);
return sendEmail(configuration, email, EmailTemplateCollection::PASSWORD_RESET_EMAIL_SUBJECT, emailContent);
}
std::string createHashSha512(const std::string& str){
unsigned char hash[SHA512_DIGEST_LENGTH];
SHA512_CTX sha512;
SHA512_Init(&sha512);
SHA512_Update(&sha512, str.c_str(), str.size());
SHA512_Final(hash, &sha512);
std::stringstream ss;
for(int i = 0; i < SHA512_DIGEST_LENGTH; i++){
ss << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>( hash[i] );
}
return ss.str();
}
std::string createHashSha256(const std::string& str){
unsigned char hash[SHA256_DIGEST_LENGTH];
SHA512_CTX sha256;
SHA512_Init(&sha256);
SHA512_Update(&sha256, str.c_str(), str.size());
SHA512_Final(hash, &sha256);
std::stringstream ss;
for(int i = 0; i < SHA256_DIGEST_LENGTH; i++){
ss << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>( hash[i] );
}
return ss.str();
}
/*
* Generates a salt using Mersenne Twister
*/
std::string generateSalt() {
std::random_device randomDevice;
std::mt19937 saltGenerator(randomDevice());
std::uniform_int_distribution<> distribution(0, SALT_CHAR_SET.size() - 1);
std::string salt;
for (int i = 0; i < SALT_SIZE; i++) {
salt += SALT_CHAR_SET[distribution(saltGenerator)];
}
return salt;
}
/*
* Hashes a given password with a given salt
*/
std::string hashPassword(const std::string& pwsalt, const std::string& password) {
return createHashSha512(pwsalt + password);
}
/*
* Gets The Alias
* takes configuration
* returns crow::json::wvalue with the Alias
*/
crow::json::wvalue getAlias(const Utilities::config& configuration, const std::string& alias) {
std::string decodedAlias = alias;
decodeString(decodedAlias);
pqxx::connection databaseConnection(configuration.databaseConnectionString);
Database::prepareStatement(databaseConnection, ID_SELECT_ALIAS);
pqxx::result resultAlias = Database::executePreparedStatement_SELECT_ALIAS(databaseConnection, decodedAlias);
crow::json::wvalue resultJsonAlias;
if (!resultAlias.empty())
resultJsonAlias = Database::convertResultRowToJSON(resultAlias);
else
resultJsonAlias["route"] = "/"; //If the alias does not exist redirect back to the index.
return resultJsonAlias;
}
/*
* Gets The freelancer listing
* takes configuration
* returns crow::json::wvalue with the Freelancer profile listing
*/
crow::json::wvalue getFreelancerListing(const Utilities::config& configuration, int page) {
pqxx::connection databaseConnection(configuration.databaseConnectionString);
pqxx::result result;
if (configuration.itemsPerPage == 0)
result = Database::executeStatement_SELECT_FREELANCERS_WITHCOMMISSIONSSTATE(databaseConnection);
else {
Database::prepareStatement(databaseConnection, ID_SELECT_FREELANCERS_WITHCOMMISSIONSSTATE_LIMITED_AND_OFFSET);
result = Database::executePreparedStatement_SELECT_FREELANCERS_WITHCOMMISSIONSSTATE_LIMITED_AND_OFFSET(databaseConnection, configuration.itemsPerPage, configuration.itemsPerPage * (page - 1));
}
return Database::convertResultToJSON(result, "freelancerProfiles");
}
/*
* Gets a vector<int> with the appropriate pagination for the configuration.itemsPerPage
* takes configuration
* returns vector<int>
*/
std::vector<int> getFreelancerIndexPagination(const Utilities::config& configuration) {
pqxx::connection databaseConnection(configuration.databaseConnectionString);
pqxx::result freelancerCountResult = Database::executeStatement_SELECT_FREELANCERS_COUNT(databaseConnection);
double freelancerCount = std::stoi(freelancerCountResult.at(0).at(0).c_str());
int pageCount = ceil(freelancerCount / configuration.itemsPerPage);
std::vector<int> pagination;
for (int i = 1; i <= pageCount; ++i) {
pagination.push_back(i);
}
return pagination;
}
/*
* Checks if freelancer is logged in
* Takes config, the loginkey and freelancerid taken from the secure cookie
* returns true if logged in
*/
bool checkFreelancerLoginState(const Utilities::config& configuration, const std::string& loginKey, const std::string& freelancerEmail) {
bool loggedIn = false;
//check if freelancer exists
pqxx::connection databaseConnection(configuration.databaseConnectionString);
Database::prepareStatement(databaseConnection, ID_SELECT_CHECK_FREELANCER_LOGIN_STATE);
pqxx::result checkLoginKey = Database::executePreparedStatement_SELECT_CHECK_FREELANCER_LOGIN_STATE(databaseConnection, freelancerEmail, loginKey);
int checkLoginKeyExtracted = std::stoi(checkLoginKey.at(0).at(0).c_str());
if (checkLoginKeyExtracted == 1)
loggedIn = true;
return loggedIn;
}
/*
* Generates a hash based on a combination of 2 random salts
*/
std::string generateRandomHashValueSHA512() {
return createHashSha512(generateSalt() + generateSalt());
}
/*
* Generates a hash based on a combination of 2 random salts
*/
std::string generateRandomHashValueSHA256() {
return createHashSha256(generateSalt() + generateSalt());
}
/*
* Generates a secure cookie
*/
std::string generateSecureCookie(const std::string& value, bool stayLoggedIn) {
std:: string secureCookieValue = value;
secureCookieValue += "; HttpOnly"; // avoid JS from Accessing cookie
secureCookieValue += "; Secure"; // set cookie to be secure
secureCookieValue += "; Path=/";
if (stayLoggedIn)
secureCookieValue += "; Expires=Fri, 31 Dec 9999 23:59:59 GMT"; //max value since cookies can't be set to never expire else it will simply be a session cookie
return secureCookieValue;
}
/*
* Generates the value to create a secure cookie with the value representing a logged-in session
*/
std::string generateSecureCookieLoginKeyValue(const std::string& loginKeyValue, bool stayLoggedIn) {
return generateSecureCookie(loginKeyValue, stayLoggedIn);
}
/*
* generates the value to create a secure cookie with the value representing a logged-in FreelancerID
*/
std::string generateSecureCookieFreelancerEmailValue(const std::string& freelancerEmailValue, bool stayLoggedIn) {
return generateSecureCookie(freelancerEmailValue, stayLoggedIn);
}
/*
* Generates a cookie that is expired contains no relevant information.
*/
std::string generateExpiredCookie() {
return "EXPIRED; HttpOnly; Secure; Path=/; Max-Age=0";
}
/*
* checks if the given cookiecontext contains a valid logged in cookie
* takes configuration and crow::CookieParser::context
*/
bool checkCookieLoginState(const Utilities::config& configuration, const crow::CookieParser::context& ctx) {
bool loginValid = false;
std::string loginKey = ctx.get_cookie(COOKIE_LOGIN_KEY);
std::string freelancerEmail = ctx.get_cookie(COOKIE_FREELANCER_EMAIL);
if (!freelancerEmail.empty() && !loginKey.empty())
if (Utilities::checkFreelancerLoginState(configuration, loginKey, freelancerEmail))
loginValid = true;
return loginValid;
}
/*
* increments the login lock out attempts and if they have reached the set limit set expiration
*/
void loginLockOutIncrement(const Utilities::config& configuration, pqxx::connection &connection, const std::string& emailAddress) {
Database::prepareStatements(connection, {
ID_INSERT_LOGIN_LOCK_OUT,
ID_UPDATE_INCREMENT_LOGIN_LOCK_OUT_ATTEMPTS,
ID_SELECT_CHECK_LOGIN_LOCK_OUT_ATTEMPTS,
ID_UPDATE_EXPIRATION_LOGIN_LOCK_OUT
});
Database::executePreparedStatement_INSERT_LOGIN_LOCK_OUT(connection, emailAddress);
Database::executePreparedStatement_UPDATE_INCREMENT_LOGIN_LOCK_OUT_ATTEMPTS(connection, emailAddress);
pqxx::result loginAttemptsCheck = Database::executePreparedStatement_CHECK_LOGIN_LOCK_OUT_ATTEMPTS(connection, emailAddress, configuration.bruteForceMitigationAttempts);
std::string loginAttemptsCheckExtracted = loginAttemptsCheck.at(0).at(0).c_str();
//a true false evaluation by postgresql delivers t or f
if (loginAttemptsCheckExtracted == "t") {
Database::executePreparedStatement_UPDATE_EXPIRATION_LOGIN_LOCK_OUT(connection, emailAddress, configuration.bruteForceMitigationLockSeconds);
}
}
/*
* Gets the freelancer templates and converts them into a wvalue JSON under the name "templates"
* takes config and freelancer email
*/
crow::json::wvalue getFreelancerTemplates(const Utilities::config& configuration, const std::string& emailAddress) {
crow::json::wvalue resultJsonFreelancerTemplate;
pqxx::connection databaseConnection(configuration.databaseConnectionString);
Database::prepareStatements(databaseConnection, {
ID_SELECT_FREELANCER_ID,
ID_SELECT_FREELANCER_TEMPLATES
});
pqxx::result idResult = Database::executePreparedStatement_SELECT_FREELANCER_ID(databaseConnection, emailAddress);
if (!idResult.empty())
{
int freelancerID = std::stoi(idResult.at(0).at(0).c_str());
pqxx::result resultFreelancerTemplates = Database::executePreparedStatement_SELECT_FREELANCER_TEMPLATES(databaseConnection, freelancerID);
resultJsonFreelancerTemplate = Database::convertResultToJSON(resultFreelancerTemplates, "templates");
}
return resultJsonFreelancerTemplate;
}
/*
* Gets the freelancer alias and converts them into a wvalue JSON under the name "alias"
* takes config and freelancer email
*/
crow::json::wvalue getFreelancerAlias(const Utilities::config& configuration, const std::string& emailAddress) {
crow::json::wvalue resultJsonFreelancerAlias;
pqxx::connection databaseConnection(configuration.databaseConnectionString);
Database::prepareStatement(databaseConnection, ID_SELECT_FREELANCER_ALIAS);
pqxx::result aliasResult = Database::executePreparedStatement_SELECT_FREELANCER_ALIAS(databaseConnection, emailAddress);
resultJsonFreelancerAlias = Database::convertResultToJSON(aliasResult, "alias");
return resultJsonFreelancerAlias;
}
/*
* Deletes a freelancers alias
* takes config the alias name and the freelancers email
*/
void deleteFreelancerAlias(const Utilities::config& configuration, const std::string& aliasName, const std::string& emailAddress) {
pqxx::connection databaseConnection(configuration.databaseConnectionString);
Database::prepareStatement(databaseConnection, ID_DELETE_FREELANCER_ALIAS);
Database::executePreparedStatement_DELETE_FREELANCER_ALIAS(databaseConnection, aliasName, emailAddress);
}
/*
* Generates an alias route to the freelancers profile
* takes a freelancers name
*/
std::string generateAliasRouteFreelancer(const std::string& freelancerName) {
return "/customer/" + freelancerName;
}
/*
* Generates an alias route to the freelancers template
* takes a freelancers and a templates name
*/
std::string generateAliasRouteFreelancerTemplate(const std::string& freelancerName, const std::string& templateName) {
return "/customer/" + freelancerName + "/template/" + templateName;
}
}
#endif