Create new Template

+minor refactoring
This commit is contained in:
Tina_Azure 2023-05-15 17:52:16 +02:00
parent 09406b0852
commit 383db248b7
7 changed files with 238 additions and 8 deletions

View File

@ -548,6 +548,33 @@ namespace Database {
work.commit();
}
/*
* Executes the prepared statement INSERT_FREELANCER_TEMPLATE
* Takes an open pqxx::connection and the strings name, content, contactdata, contactinformation, currencypreference, priceupfront, priceondeliver, freelancerEmail
* returns errorLevel
* 0 = no error
* 1 = query error
* 2 = critical error
*/
int executePreparedStatement_INSERT_FREELANCER_TEMPLATE(pqxx::connection &connection, const std::string& name, const std::string& content, const std::string& contactdata, const std::string& contactinformation, const std::string& currencypreference, const std::string& priceupfront, const std::string& priceondeliver, const std::string& freelancerEmail) {
try {
pqxx::work work(connection);
work.exec_prepared(PREPARED_STATEMENT_INSERT_FREELANCER_TEMPLATE, name, content, contactdata, contactinformation, currencypreference, priceupfront, priceondeliver, freelancerEmail);
work.commit();
}
catch (pqxx::sql_error const &e) {
std::cerr
<< "Database error: " << e.what() << std::endl
<< "Query was: " << e.query() << std::endl;
return 1;
}
catch (std::exception const &e) {
std::cerr << e.what() << std::endl;
return 2;
}
return 0;
}
/*
* Prepares a statement based on ID
* Takes an open pqxx::connection, the statement id

View File

@ -186,6 +186,13 @@ namespace DatabaseStatementConstCollection {
const static std::string PREPARED_STATEMENT_UPDATE_EXPIRATION_LOGIN_LOCK_OUT = "updateExpirationLoginLockOut";
const static std::string SQL_STATEMENT_UPDATE_EXPIRATION_LOGIN_LOCK_OUT = "update loginlockout set (attempts, expiration) = (0, CURRENT_TIMESTAMP + make_interval(secs => $2)) where email = $1;";
/*
* Name and Statement for prepared statement to try to add a new template to a freelancer
* $1-8 -> name, content, contactdata, contactinformation, currencypreference, priceupfront, priceondeliver, emailaddress
*/
const static std::string PREPARED_STATEMENT_INSERT_FREELANCER_TEMPLATE = "insertFreelancerTemplate";
const static std::string SQL_STATEMENT_INSERT_FREELANCER_TEMPLATE = "INSERT INTO templates(freelancerid, name, content, contactdata, contactinformation, currencypreference, priceupfront, priceondeliver) VALUES((select freelancers.id from freelancers where emailaddress = $8), $1, $2, $3, $4, $5, $6, $7);";
/*
* IDs of prepared statements
*/
@ -218,6 +225,7 @@ namespace DatabaseStatementConstCollection {
const static int ID_INSERT_LOGIN_LOCK_OUT = 26;
const static int ID_SELECT_CHECK_LOGIN_LOCK_OUT_ATTEMPTS = 27;
const static int ID_UPDATE_EXPIRATION_LOGIN_LOCK_OUT = 28;
const static int ID_INSERT_FREELANCER_TEMPLATE = 29;
/*
* Easy access to prepared statements via prepared statement name
@ -251,7 +259,8 @@ namespace DatabaseStatementConstCollection {
{PREPARED_STATEMENT_UPDATE_INCREMENT_LOGIN_LOCK_OUT_ATTEMPTS, SQL_STATEMENT_UPDATE_INCREMENT_LOGIN_LOCK_OUT_ATTEMPTS},
{PREPARED_STATEMENT_INSERT_LOGIN_LOCK_OUT, SQL_STATEMENT_INSERT_LOGIN_LOCK_OUT},
{PREPARED_STATEMENT_SELECT_CHECK_LOGIN_LOCK_OUT_ATTEMPTS, SQL_STATEMENT_SELECT_CHECK_LOGIN_LOCK_OUT_ATTEMPTS},
{PREPARED_STATEMENT_UPDATE_EXPIRATION_LOGIN_LOCK_OUT, SQL_STATEMENT_UPDATE_EXPIRATION_LOGIN_LOCK_OUT}
{PREPARED_STATEMENT_UPDATE_EXPIRATION_LOGIN_LOCK_OUT, SQL_STATEMENT_UPDATE_EXPIRATION_LOGIN_LOCK_OUT},
{PREPARED_STATEMENT_INSERT_FREELANCER_TEMPLATE, SQL_STATEMENT_INSERT_FREELANCER_TEMPLATE}
};
/*
* Easy access to prepared statement name via int
@ -285,7 +294,8 @@ namespace DatabaseStatementConstCollection {
{ID_UPDATE_INCREMENT_LOGIN_LOCK_OUT_ATTEMPTS, PREPARED_STATEMENT_UPDATE_INCREMENT_LOGIN_LOCK_OUT_ATTEMPTS},
{ID_INSERT_LOGIN_LOCK_OUT, PREPARED_STATEMENT_INSERT_LOGIN_LOCK_OUT},
{ID_SELECT_CHECK_LOGIN_LOCK_OUT_ATTEMPTS, PREPARED_STATEMENT_SELECT_CHECK_LOGIN_LOCK_OUT_ATTEMPTS},
{ID_UPDATE_EXPIRATION_LOGIN_LOCK_OUT, PREPARED_STATEMENT_UPDATE_EXPIRATION_LOGIN_LOCK_OUT}
{ID_UPDATE_EXPIRATION_LOGIN_LOCK_OUT, PREPARED_STATEMENT_UPDATE_EXPIRATION_LOGIN_LOCK_OUT},
{ID_INSERT_FREELANCER_TEMPLATE, PREPARED_STATEMENT_INSERT_FREELANCER_TEMPLATE}
};
/*

View File

@ -1,7 +1,6 @@
#include <vector>
#include <string>
#include <thread>
#include <map>
#include <pqxx/pqxx>
@ -144,7 +143,7 @@ int main(int argc, char *argv[]) {
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
//the commission-state
if (resultCommissionState.empty() || stoi(resultCommissionState.at(0).at(0).c_str()) == 1)
commissionState = true;
}
@ -230,7 +229,7 @@ int main(int argc, char *argv[]) {
pqxx::result resultCommissionState = Database::executePreparedStatement_SELECT_FREELANCER_COMMISSION_STATE(databaseConnection, newRequest.freelancerID);
//the commissionstate
//the commission-state
if (resultCommissionState.empty() || stoi(resultCommissionState.at(0).at(0).c_str()) == 1) {
ctx[MUSTACHE_ERROR_COMMISSIONS_CLOSED] = true;
}
@ -639,7 +638,7 @@ int main(int argc, char *argv[]) {
});
/*
* Page for freelancer to create/delete/edit Templates
* Page for freelancer to create/select Templates
*/
CROW_ROUTE(app, "/freelancer/templateManagement")
([&, configuration](const crow::request& getRequest ) {
@ -655,7 +654,81 @@ int main(int argc, char *argv[]) {
});
/*
* Page for freelancer to create/delete/edit Templates
* Page for freelancer to create new Template
*/
CROW_ROUTE(app, "/freelancer/templateManagement/template/new")
([&, configuration](const crow::request& getRequest ) {
auto& cookieCtx = app.get_context<crow::CookieParser>(getRequest);
crow::mustache::context ctx;
if (Utilities::checkCookieLoginState(configuration, cookieCtx)) {
ctx[MUSTACHE_COOKIE_LOGGED_IN] = true;
}
auto page = crow::mustache::load(TEMPLATE_FREELANCER_TEMPLATE_MANAGEMENT_CREATE_NEW);
return page.render(ctx);
});
/*
* Page for freelancer to create new Template fulfilment
*/
CROW_ROUTE(app, "/freelancer/templateManagement/template/new/fulfilment").methods("POST"_method)
([&, configuration](const crow::request& postRequest ) {
auto& cookieCtx = app.get_context<crow::CookieParser>(postRequest);
crow::mustache::context ctx;
if (Utilities::checkCookieLoginState(configuration, cookieCtx)) {
ctx[MUSTACHE_COOKIE_LOGGED_IN] = true;
string name, content, contactdata, contactinformation, currencypreference, priceupfront, priceondeliver;
string postRequestBody = postRequest.body;
Utilities::decodeString(postRequestBody);
vector<string> splitPostRequestBody = Utilities::splitStringIntoVector(postRequestBody, '&');
for (const string& item : splitPostRequestBody) {
vector<string> splitItem = Utilities::splitStringIntoVector(item, '=');
if (splitItem.at(0) == "templatename")
name = splitItem.at(1);
if (splitItem.at(0) == "templatecontent")
content = splitItem.at(1);
if (splitItem.at(0) == "templatecontactdata")
contactdata = splitItem.at(1);
if (splitItem.at(0) == "templatecontactinformation")
contactinformation = splitItem.at(1);
if (splitItem.at(0) == "templatecurrencypreference")
currencypreference = splitItem.at(1);
if (splitItem.at(0) == "templatepriceupfront")
priceupfront = splitItem.at(1);
if (splitItem.at(0) == "templatepriceondeliver")
priceondeliver = splitItem.at(1);
}
if (!Utilities::checkIfStrIsNumber(priceupfront))
priceupfront = "0";
if (!Utilities::checkIfStrIsNumber(priceondeliver))
priceondeliver = "0";
pqxx::connection databaseConnection(configuration.databaseConnectionString);
Database::prepareStatement(databaseConnection, ID_INSERT_FREELANCER_TEMPLATE);
int errorLevel = Database::executePreparedStatement_INSERT_FREELANCER_TEMPLATE(
databaseConnection, name, content, contactdata, contactinformation, currencypreference, priceupfront, priceondeliver, cookieCtx.get_cookie(COOKIE_FREELANCER_EMAIL));
if (errorLevel == 0) {
ctx["templatename"] = name;
ctx["contactdata"] = contactdata;
ctx["contactinformation"] = contactinformation;
ctx["currencypreference"] = currencypreference;
ctx["priceupfront"] = priceupfront;
ctx["priceondeliver"] = priceondeliver;
ctx["content"] = content;
}
else {
ctx[MUSTACHE_FREELANCER_TEMPLATE_CREATION_ERROR] = true;
}
}
auto page = crow::mustache::load(TEMPLATE_FREELANCER_TEMPLATE_MANAGEMENT_CREATE_NEW_FULFILMENT);
return page.render(ctx);
});
/*
* Page for freelancer to view/delete/edit a Template
*/
CROW_ROUTE(app, "/freelancer/templateManagement/template/<string>").methods("POST"_method)
([&, configuration](const crow::request& postRequest, string templateName ) {
@ -695,7 +768,23 @@ int main(int argc, char *argv[]) {
return page.render(ctx);
});
/*
* Execute Template Operation
* todo:implement
*/
CROW_ROUTE(app, "/freelancer/templateManagement/fulfilment").methods("POST"_method)
([&, configuration](const crow::request& postRequest ) {
auto& cookieCtx = app.get_context<crow::CookieParser>(postRequest);
cout << postRequest.body << endl;
crow::mustache::context ctx;
if (Utilities::checkCookieLoginState(configuration, cookieCtx)) {
ctx = Utilities::getFreelancerTemplates(configuration, cookieCtx.get_cookie(COOKIE_FREELANCER_EMAIL));
ctx["freelanceremail"] = cookieCtx.get_cookie(COOKIE_FREELANCER_EMAIL);
ctx[MUSTACHE_COOKIE_LOGGED_IN] = true;
}
auto page = crow::mustache::load(TEMPLATE_FREELANCER_TEMPLATE_MANAGEMENT);
return page.render(ctx);
});

View File

@ -26,6 +26,8 @@ namespace TemplateConstCollection {
const static std::string TEMPLATE_FREELANCER_PROFILE = "freelancer_Profile.html";
const static std::string TEMPLATE_FREELANCER_TEMPLATE_MANAGEMENT = "freelancer_Template_Management.html";
const static std::string TEMPLATE_FREELANCER_TEMPLATE_MANAGEMENT_FULFILMENT = "freelancer_Template_Management_Fulfilment.html";
const static std::string TEMPLATE_FREELANCER_TEMPLATE_MANAGEMENT_CREATE_NEW = "freelancer_Template_Management_Create_New.html";
const static std::string TEMPLATE_FREELANCER_TEMPLATE_MANAGEMENT_CREATE_NEW_FULFILMENT = "freelancer_Template_Management_Create_New_Fulfilment.html";
//Mustache Error/Success variable names
const static std::string MUSTACHE_ERROR_COMMISSIONS_CLOSED = "ERROR_COMMISSIONS_CLOSED";
@ -54,6 +56,7 @@ namespace TemplateConstCollection {
const static std::string MUSTACHE_RESET_SUCCESS = "RESET_SUCCESS";
const static std::string MUSTACHE_LOGIN_SUCCESS = "LOGIN_SUCCESS";
const static std::string MUSTACHE_FREELANCER_TEMPLATE_OPERATION_ERROR_NO_TEMPLATE = "TEMPLATE_OPERATION_ERROR_NO_TEMPLATE";
const static std::string MUSTACHE_FREELANCER_TEMPLATE_CREATION_ERROR = "TEMPLATE_CREATION_ERROR";
//Mustache Cookie variable names
const static std::string MUSTACHE_COOKIE_LOGGED_IN = "COOKIE_LOGGED_IN";

View File

@ -522,5 +522,18 @@ namespace Utilities {
}
return resultJsonFreelancerTemplate;
}
/*
* 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;
}
}
#endif

View File

@ -0,0 +1,38 @@
<!DOCTYPE html>
<html>
<head>
{{> templateIncludes/style.css.html}}
</head>
<body>
{{^COOKIE_LOGGED_IN}}
Please Log in.
{{/COOKIE_LOGGED_IN}}
{{#COOKIE_LOGGED_IN}}
<br>
<form action="/freelancer/templateManagement/template/new/fulfilment" method="post">
<label for="templatename">Template Name:</label> <input type="text" id="templatename" name="templatename" value=""><br>
<label for="templatecontactdata">Contact Data:</label> <input type="text" id="templatecontactdata" name="templatecontactdata" value=""><br>
<label for="templatecontactinformation">Contact Information: </label> <input type="text" id="templatecontactinformation" name="templatecontactinformation" value=""><br>
<label for="templatecurrencypreference">Prefered Currency: </label> <input type="text" id="templatecurrencypreference" name="templatecurrencypreference" value=""><br>
<label for="templatepriceupfront">Upfront payment: </label> <input type="text" id="templatepriceupfront" name="templatepriceupfront" value=""><br>
<label for="templatepriceondeliver">On Delivery Payment: </label> <input type="text" id="templatepriceondeliver" name="templatepriceondeliver" value=""><br>
<label for="templatecontent">Description: </label> <textarea id="templatecontent" name="templatecontent" value=""></textarea><br>
<button type="submit" class="button">Create new Template</button>
</form>
<br>
{{/COOKIE_LOGGED_IN}}
<br>
<form action="/freelancer/profile" method="get">
<button type="submit" class="button">Return to profile</button>
</form>
<form action="/freelancer/templateManagement" method="get">
<button type="submit" class="button">Return to Template Management</button>
</form>
<br>
{{> templateIncludes/returnToIndexButton.html.html}}
</body>
</html>

View File

@ -0,0 +1,50 @@
<!DOCTYPE html>
<html>
<head>
{{> templateIncludes/style.css.html}}
</head>
<body>
{{^COOKIE_LOGGED_IN}}
Please Log in.
{{/COOKIE_LOGGED_IN}}
{{#COOKIE_LOGGED_IN}}
{{^TEMPLATE_CREATION_ERROR}}
<h2>Template Successfully Created</h2>
<h3>Template: {{templatename}}</h3>
<div>Contact Information:</div>
<div>
{{contactdata}}<br>
{{contactinformation}}
</div>
<br>
<div>Payment Information:</div>
<div>
Prefered Currency: {{currencypreference}}<br>
Price: Upfront: {{priceupfront}} - On Delivery: {{priceondeliver}}<br>
</div>
<br>
<div>Description:</div>
<div>{{content}}</div>
{{/TEMPLATE_CREATION_ERROR}}
{{#TEMPLATE_CREATION_ERROR}}
Unable to create Template
<form action="/freelancer/templateManagement/template/new" method="get">
<button type="submit" class="button">Create New Template</button>
</form>
{{/TEMPLATE_CREATION_ERROR}}
{{/COOKIE_LOGGED_IN}}
<br>
<form action="/freelancer/profile" method="get">
<button type="submit" class="button">Return to profile</button>
</form>
<form action="/freelancer/templateManagement" method="get">
<button type="submit" class="button">Return to Template Management</button>
</form>
<br>
{{> templateIncludes/returnToIndexButton.html.html}}
</body>
</html>