forked from chookspace/chookchat
start work on persistent login
This commit is contained in:
@@ -15,13 +15,35 @@
|
||||
#include "generated/header_top.h"
|
||||
#include "generated/header_bottom.h"
|
||||
#include "generated/footer.h"
|
||||
#include "generated/login.h"
|
||||
#include "generated/style.h"
|
||||
#include "generated/script.h"
|
||||
|
||||
std::optional<User> getLoggedInUser(const httplib::Request& request, Database& database) {
|
||||
if (!request.has_header("Cookie")) {
|
||||
return {};
|
||||
}
|
||||
|
||||
std::string cookieHeader = request.get_header_value("Cookie");
|
||||
const std::string key = "session=";
|
||||
|
||||
size_t pos = cookieHeader.find(key);
|
||||
if (pos == std::string::npos) {
|
||||
return {};
|
||||
}
|
||||
pos += key.length();
|
||||
|
||||
size_t end = cookieHeader.find(';', pos);
|
||||
std::string token = cookieHeader.substr(pos, end == std::string::npos ? std::string::npos : end - pos);
|
||||
|
||||
return database.getUserByToken(token);
|
||||
}
|
||||
|
||||
int main() {
|
||||
const bin2cpp::File& headerTopFile = bin2cpp::getHeader_topHtmlFile();
|
||||
const bin2cpp::File& headerBottomFile = bin2cpp::getHeader_bottomHtmlFile();
|
||||
const bin2cpp::File& footerfile = bin2cpp::getFooterHtmlFile();
|
||||
const bin2cpp::File& loginfile = bin2cpp::getLoginHtmlFile();
|
||||
const bin2cpp::File& e404file = bin2cpp::getE404HtmlFile();
|
||||
const bin2cpp::File& stylefile = bin2cpp::getStyleCssFile();
|
||||
const bin2cpp::File& scriptfile = bin2cpp::getScriptJsFile();
|
||||
@@ -29,6 +51,7 @@ int main() {
|
||||
std::string headerTop{headerTopFile.getBuffer(), headerTopFile.getSize()};
|
||||
std::string headerBottom{headerBottomFile.getBuffer(), headerBottomFile.getSize()};
|
||||
std::string footer{footerfile.getBuffer(), footerfile.getSize()};
|
||||
std::string login{loginfile.getBuffer(), loginfile.getSize()};
|
||||
std::string e404{e404file.getBuffer(), e404file.getSize()};
|
||||
std::string style{stylefile.getBuffer(), stylefile.getSize()};
|
||||
std::string script{scriptfile.getBuffer(), scriptfile.getSize()};
|
||||
@@ -47,6 +70,62 @@ int main() {
|
||||
response.set_content(script, "text/css");
|
||||
});
|
||||
|
||||
svr.Get("/login", [&login](const httplib::Request& request, httplib::Response& response) {
|
||||
response.set_content(login, "text/html");
|
||||
});
|
||||
|
||||
svr.Get("/login.html", [&login](const httplib::Request& request, httplib::Response& response) {
|
||||
response.set_content(login, "text/html");
|
||||
});
|
||||
|
||||
svr.Post("/login", [&database, &data_mutex](const httplib::Request& request, httplib::Response& response) {
|
||||
std::string username = request.form.get_field("username");
|
||||
std::string password = request.form.get_field("password");
|
||||
|
||||
std::lock_guard<std::mutex> lock(data_mutex);
|
||||
|
||||
try {
|
||||
std::optional<User> user = database.getUserByName(username);
|
||||
|
||||
if (user.has_value()) {
|
||||
if (!bcrypt::validatePassword(password, user->passwordHash)) {
|
||||
response.status = 401;
|
||||
response.set_content("<p>wrong password lmao</p>", "text/html");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (username.empty()) {
|
||||
response.status = 400;
|
||||
response.set_content("<p>hey you can't have an empty username!!!!1!!!1! >:(</p>", "text/html");
|
||||
return;
|
||||
}
|
||||
// register on the fly, same as make_post currently does
|
||||
User newUser{0, username, bcrypt::generateHash(password)};
|
||||
database.addUser(newUser);
|
||||
user = newUser;
|
||||
}
|
||||
|
||||
std::optional<std::string> token = database.createNewToken(user->id);
|
||||
if (!token.has_value()) {
|
||||
response.status = 500;
|
||||
response.set_content("<p>couldn't create a session, sorry</p>", "text/html");
|
||||
return;
|
||||
}
|
||||
|
||||
// HttpOnly so script.js can't read/leak it, SameSite=Lax so it
|
||||
// isn't sent on cross-site POSTs (basic CSRF mitigation),
|
||||
// Max-Age matches the 30 day expiry stored in the DB
|
||||
response.set_header(
|
||||
"Set-Cookie",
|
||||
"session=" + *token + "; Path=/; HttpOnly; SameSite=Lax; Max-Age=2592000"
|
||||
);
|
||||
response.set_redirect("/");
|
||||
} catch (const std::runtime_error& e) {
|
||||
response.status = 500;
|
||||
response.set_content("<p>there was an error :( it is: " + std::string(e.what()) + "</p>", "text/html");
|
||||
}
|
||||
});
|
||||
|
||||
svr.Get("/", [&headerTop, &headerBottom, &footer, &database, &data_mutex](const httplib::Request& request, httplib::Response& response) {
|
||||
|
||||
std::stringstream ss;
|
||||
|
||||
Reference in New Issue
Block a user