The encryption is temporary.
I have a quite unreadable error with all the instances execSqlAsync function.
The error is:
In template: invalid operands to binary expression ('std::stringstream' (aka 'basic_stringstream<char>') and 'std::exception') error occurred here in instantiation of function template specialization 'drogon::orm::Field::as<std::exception>' requested here in instantiation of function template specialization 'drogon::orm::internal::CallbackHolder<(lambda at /Users/<br>
41:13)>::makeValue<std::exception>' requested here in instantiation of function template specialization 'drogon::orm::internal::CallbackHolder<(lambda at /Users/
<br>
41:13)>::run<1UL>' requested here in instantiation of function template specialization 'drogon::orm::internal::CallbackHolder<(lambda at <br>
41:13)>::run<true>' requested here in instantiation of member function 'drogon::orm::internal::CallbackHolder<(lambda at /Users/<br>
41:13)>::execCallback' requested here in instantiation of function template specialization 'drogon::orm::internal::CallbackHolder<(lambda at /Users/<br>
41:13)>::CallbackHolder<(lambda at patr... in instantiation of function template specialization 'drogon::orm::internal::SqlBinder::operator>><(lambda at
<br>
server/AuthController.cpp:41:13), drogon::orm::internal::FunctionTraits<(lambda at /U... in instantiation of function template specialization 'drogon::orm::DbClient::execSqlAsync<(lambda at <br> server/AuthController.cpp:35:13), (lambda at /<br> server/A... candidate template ignored: deduced conflicting types for parameter '_CharT' ('char' vs. 'std::exception') candidate template ignored: could not match 'uniform_int_distribution<_IT>' against 'std::exception' candidate template ignored: could not match '_CharT[_Np]' against 'std::exception' candidate template ignored: could not match 'unsigned char[_Np]' against 'std::exception' candidate template ignored: could not match 'signed char[_Np]' against 'std::exception' candidate template ignored: could not match 'basic_string<_CharT, _Traits, _Allocator>' against 'std::exception' candidate template ignored: could not match 'bitset<_Size>' against 'std::exception' candidate template ignored: requirement 'integral_constant<bool, false>::value' was not satisfied [with _Stream = std::stringstream &, _Tp = std::exception &] candidate template ignored: could not match '__iom_t7<_MoneyT>' against 'std::exception' candidate template ignored: could not match '__iom_t9<_CharT>' against 'std::exception'
And here is the code:
#include "AuthController.h"
#include <drogon/drogon.h>
#include <drogon/orm/DbClient.h>
#include <algorithm>
using namespace drogon;
using namespace drogon::orm;
// Simple Caesar Cipher function
std::string caesarCipher(const std::string& text, int shift) {
std::string result = text;
std::transform(result.begin(), result.end(), result.begin(),
[shift](char c) -> char {
if (c >= 'a' && c <= 'z')
return 'a' + (c - 'a' + shift) % 26;
else if (c >= 'A' && c <= 'Z')
return 'A' + (c - 'A' + shift) % 26;
else
return c;
});
return result;
}
void AuthController::signup(const HttpRequestPtr &req, std::function<void(const HttpResponsePtr &)> &&callback) {
auto json = req->getJsonObject();
std::string username = json->get("username", "").asString();
std::string password = json->get("password", "").asString();
// Encrypt the password using Caesar cipher
std::string encryptedPassword = caesarCipher(password, 3);
auto client = drogon::app().getDbClient().get();
client->execSqlAsync(
"INSERT INTO users (username, password_hash) VALUES ($1, $2)",
[callback](const Result &result) {
auto response = HttpResponse::newHttpResponse();
response->setStatusCode(HttpStatusCode::k200OK);
response->setBody("Signup successful");
callback(response);
},
[callback](const std::exception &e) { // Correct exception handling
auto response = HttpResponse::newHttpResponse();
response->setStatusCode(HttpStatusCode::k500InternalServerError);
response->setBody(e.what());
callback(response);
},
username, encryptedPassword);
}
void AuthController::login(const HttpRequestPtr &req, std::function<void(const HttpResponsePtr &)> &&callback) {
auto json = req->getJsonObject();
std::string username = json->get("username", "").asString();
std::string password = json->get("password", "").asString();
auto client = drogon::app().getDbClient();
client.get()->execSqlAsync(
"SELECT password_hash FROM users WHERE username = $1",
[password, callback](const Result &result) {
std::shared_ptr<HttpResponse> response;
if (!result.empty()) {
std::string storedHash = result[0]["password_hash"].as<std::string>();
std::string decryptedPassword = caesarCipher(storedHash, -3);
if (decryptedPassword == password) {
response = HttpResponse::newHttpResponse();
response->setStatusCode(k200OK);
response->setBody("Login successful");
} else {
response = HttpResponse::newHttpResponse();
response->setStatusCode(k401Unauthorized);
response->setBody("Login failed");
}
} else {
response = HttpResponse::newHttpResponse();
response->setStatusCode(k401Unauthorized);
response->setBody("User not found");
}
callback(response);
},
[callback](const std::exception &e) {
auto resp = HttpResponse::newHttpResponse();
resp->setStatusCode(k500InternalServerError);
resp->setBody(e.what());
callback(resp);
},
username);
}
Remember to post link to library you are using.
After I was able to google this library and inspecting documentation solution is clear:
ENG 08 1 Database DbClient · drogonframework/drogon Wiki · GitHub
After the execution of sql is successful, the execution result is wrapped by the Result class and passed to the user through the result callback function; if there is any exception in the sql execution, the exception callback function is executed, and the user can obtain the exception information from the DrogonDbException object.
Let us give an example:
clientPtr->execSqlAsync("select * from users where org_name=$1", [](const drogon::orm::Result &result) { std::cout << result.size() << " rows selected!" << std::endl; int i = 0; for (auto row : result) { std::cout << i++ << ": user name is " << row["user_name"].as<std::string>() << std::endl; } }, [](const DrogonDbException &e) { std::cerr << "error:" << e.base().what() << std::endl; }, "default");
so you should your code this way:
[callback](const DrogonDbException &e) { // Correct exception handling
auto response = HttpResponse::newHttpResponse();
response->setStatusCode(HttpStatusCode::k500InternalServerError);
response->setBody(e.base().what());
callback(response);
},
Offtopic:
This part of code:
response->setBody(e.base().what());
May look handy at first glance, but can be also security threat, since it can leak confidential information about structure of you database. This way it could be easier for attacker to discover weaknesses in your software (like SQL injection).