Logins + sessions working
This commit is contained in:
@@ -6,7 +6,6 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="/">home</a></li>
|
|
||||||
<li><a id="loginLink" href="/login">login</a></li>
|
<li><a id="loginLink" href="/login">login</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
|
|||||||
@@ -18,6 +18,25 @@ async function like(id) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function post() {
|
||||||
|
const postbox = document.getElementById('newpost');
|
||||||
|
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append('post', postbox.value);
|
||||||
|
|
||||||
|
const result = await fetch('/post', {
|
||||||
|
method: 'POST',
|
||||||
|
body: formData
|
||||||
|
});
|
||||||
|
|
||||||
|
if (result.status < 200 || result.status >= 400) {
|
||||||
|
alert("you have been silenced by the server and your post did not go through");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
window.location.href = "/";
|
||||||
|
}
|
||||||
|
|
||||||
async function register() {
|
async function register() {
|
||||||
const usernameBox = document.getElementById('username');
|
const usernameBox = document.getElementById('username');
|
||||||
const passwordBox = document.getElementById('password');
|
const passwordBox = document.getElementById('password');
|
||||||
@@ -48,7 +67,6 @@ async function login() {
|
|||||||
formData.append('username', usernameBox.value);
|
formData.append('username', usernameBox.value);
|
||||||
formData.append('password', passwordBox.value);
|
formData.append('password', passwordBox.value);
|
||||||
|
|
||||||
console.log(formData);
|
|
||||||
|
|
||||||
const result = await fetch('/login', {
|
const result = await fetch('/login', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
@@ -57,8 +75,6 @@ async function login() {
|
|||||||
|
|
||||||
if (result.status < 200 || result.status >= 400) {
|
if (result.status < 200 || result.status >= 400) {
|
||||||
alert("for some reason the server hates you and didn't let you log into your account");
|
alert("for some reason the server hates you and didn't let you log into your account");
|
||||||
console.log(result.status);
|
|
||||||
console.log(result.content);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,13 +94,19 @@ async function checkLoginStatus() {
|
|||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', async function() {
|
document.addEventListener('DOMContentLoaded', async function() {
|
||||||
|
|
||||||
if (window.location.pathname == "/" && window.fetch) {
|
if (window.fetch) {
|
||||||
// We know the fetch API exists, so hide the stuff that doesn't rely on it
|
// We know the fetch API exists, so hide the stuff that doesn't rely on it
|
||||||
|
|
||||||
const form = document.getElementById("postbox-form");
|
const form = document.getElementById("postbox-form");
|
||||||
|
if (!form) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
form.style.display = 'none';
|
form.style.display = 'none';
|
||||||
|
|
||||||
const postbox = document.getElementById("postbox");
|
const postbox = document.getElementById("postbox");
|
||||||
|
if (!postbox) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const userStatus = await checkLoginStatus();
|
const userStatus = await checkLoginStatus();
|
||||||
|
|
||||||
@@ -98,8 +120,20 @@ document.addEventListener('DOMContentLoaded', async function() {
|
|||||||
const helperText = document.createElement("p");
|
const helperText = document.createElement("p");
|
||||||
helperText.textContent = "You're posting as " + userStatus;
|
helperText.textContent = "You're posting as " + userStatus;
|
||||||
postbox.appendChild(helperText);
|
postbox.appendChild(helperText);
|
||||||
|
|
||||||
const textArea = document.createElement("textarea");
|
const textArea = document.createElement("textarea");
|
||||||
|
textArea.id = "newpost";
|
||||||
postbox.appendChild(textArea);
|
postbox.appendChild(textArea);
|
||||||
|
|
||||||
|
const postButton = document.createElement("button");
|
||||||
|
postButton.textContent = "Post";
|
||||||
|
postButton.id = "postbutton"
|
||||||
|
postButton.onclick = post;
|
||||||
|
postbox.appendChild(postButton);
|
||||||
|
|
||||||
|
const loginLink = document.getElementById("loginLink");
|
||||||
|
loginLink.textContent = "hello, " + userStatus + "!";
|
||||||
|
loginLink.href = "/profile/" + userStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ int main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
svr.Get("/script.js", [&script](const httplib::Request& request, httplib::Response& response) {
|
svr.Get("/script.js", [&script](const httplib::Request& request, httplib::Response& response) {
|
||||||
response.set_content(script, "text/css");
|
response.set_content(script, "text/javascript");
|
||||||
});
|
});
|
||||||
|
|
||||||
svr.Get("/login", [&login](const httplib::Request& request, httplib::Response& response) {
|
svr.Get("/login", [&login](const httplib::Request& request, httplib::Response& response) {
|
||||||
@@ -93,13 +93,52 @@ int main() {
|
|||||||
response.set_content("<p>wrong password lmao</p><img src='https://media.tenor.com/wWX7upr7SvwAAAAM/byuntear-cat.gif' alt='your stupid lol'>", "text/html");
|
response.set_content("<p>wrong password lmao</p><img src='https://media.tenor.com/wWX7upr7SvwAAAAM/byuntear-cat.gif' alt='your stupid lol'>", "text/html");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
response.status = 400;
|
||||||
|
response.set_content("<p>that username doesn't exist</p>", "text/html");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
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.Post("/register", [&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()) {
|
||||||
|
response.status = 400;
|
||||||
|
response.set_content("<p>that username already exists</p>", "text/html");
|
||||||
|
return;
|
||||||
} else {
|
} else {
|
||||||
if (username.empty()) {
|
if (username.empty()) {
|
||||||
response.status = 400;
|
response.status = 400;
|
||||||
response.set_content("<p>hey you can't have an empty username!!!!1!!!1! >:(</p>", "text/html");
|
response.set_content("<p>hey you can't have an empty username!!!!1!!!1! >:(</p>", "text/html");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// register on the fly, same as make_post currently does
|
|
||||||
User newUser{0, username, bcrypt::generateHash(password)};
|
User newUser{0, username, bcrypt::generateHash(password)};
|
||||||
database.addUser(newUser);
|
database.addUser(newUser);
|
||||||
user = newUser;
|
user = newUser;
|
||||||
@@ -152,6 +191,7 @@ int main() {
|
|||||||
|
|
||||||
svr.Get("/posts/:id", [&headerTop, &headerBottom, &footer, &e404, &database, &data_mutex](const httplib::Request& request, httplib::Response& response) {
|
svr.Get("/posts/:id", [&headerTop, &headerBottom, &footer, &e404, &database, &data_mutex](const httplib::Request& request, httplib::Response& response) {
|
||||||
std::string postId = request.path_params.at("id");
|
std::string postId = request.path_params.at("id");
|
||||||
|
std::lock_guard<std::mutex> lock(data_mutex);
|
||||||
try {
|
try {
|
||||||
uint64_t postIdNum = std::stoll(postId);
|
uint64_t postIdNum = std::stoll(postId);
|
||||||
std::optional<Post> post = database.getPost(postIdNum);
|
std::optional<Post> post = database.getPost(postIdNum);
|
||||||
@@ -174,6 +214,7 @@ int main() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// endpoint to be used by HTML forms
|
||||||
svr.Post("/make_post", [&database, &data_mutex](const httplib::Request& request, httplib::Response& response) {
|
svr.Post("/make_post", [&database, &data_mutex](const httplib::Request& request, httplib::Response& response) {
|
||||||
|
|
||||||
std::string username = request.get_param_value("username");
|
std::string username = request.get_param_value("username");
|
||||||
@@ -213,6 +254,32 @@ int main() {
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// endpoint to be used in Javascript
|
||||||
|
svr.Post("/post", [&database, &data_mutex](const httplib::Request& request, httplib::Response& response) {
|
||||||
|
try {
|
||||||
|
std::lock_guard<std::mutex> lock(data_mutex);
|
||||||
|
std::string post = request.form.get_field("post");
|
||||||
|
|
||||||
|
std::optional<User> user = getLoggedInUser(request, database);
|
||||||
|
if (!user.has_value()) {
|
||||||
|
response.status = 401;
|
||||||
|
response.set_content("<p>you're not logged in, so you can't post</p>", "text/html");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
database.addPost(Post(post, user->id));
|
||||||
|
response.status = 200;
|
||||||
|
response.set_content("OK", "text/text");
|
||||||
|
|
||||||
|
} 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");
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
response.status = 500;
|
||||||
|
response.set_content("<p>there was an error :( it is: " + std::string(e.what()) + "</p>", "text/html");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
svr.Post("/like", [&database, &data_mutex](const httplib::Request& request, httplib::Response& response) {
|
svr.Post("/like", [&database, &data_mutex](const httplib::Request& request, httplib::Response& response) {
|
||||||
try {
|
try {
|
||||||
std::string username = request.form.get_field("username");
|
std::string username = request.form.get_field("username");
|
||||||
@@ -233,14 +300,16 @@ int main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
svr.Get("/me", [&database, &data_mutex](const httplib::Request& request, httplib::Response& response) {
|
svr.Get("/me", [&database, &data_mutex](const httplib::Request& request, httplib::Response& response) {
|
||||||
|
std::lock_guard<std::mutex> lock(data_mutex);
|
||||||
std::optional<User> user = getLoggedInUser(request, database);
|
std::optional<User> user = getLoggedInUser(request, database);
|
||||||
|
response.set_header("Cache-Control", "no-store");
|
||||||
|
|
||||||
if (!user.has_value()) {
|
if (!user.has_value()) {
|
||||||
response.set_header("X-Logged-In", "false");
|
response.set_header("X-Logged-In", "false");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
response.set_header("X-Logged-In", "false");
|
response.set_header("X-Logged-In", "true");
|
||||||
response.set_header("X-Username", user->name);
|
response.set_header("X-Username", user->name);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user