nu
This commit is contained in:
parent
e8864cc853
commit
1d42a9a623
9 changed files with 2122 additions and 542 deletions
|
|
@ -1,6 +1,7 @@
|
|||
#include "UserController.h"
|
||||
#include "../services/DatabaseService.h"
|
||||
#include <drogon/MultiPart.h>
|
||||
#include <drogon/Cookie.h>
|
||||
#include <fstream>
|
||||
#include <random>
|
||||
#include <sstream>
|
||||
|
|
@ -51,18 +52,46 @@ namespace {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Helper to set httpOnly auth cookie
|
||||
void setAuthCookie(const HttpResponsePtr& resp, const std::string& token) {
|
||||
Cookie authCookie("auth_token", token);
|
||||
authCookie.setPath("/");
|
||||
authCookie.setHttpOnly(true);
|
||||
authCookie.setSecure(false); // Set to true in production with HTTPS
|
||||
authCookie.setMaxAge(86400); // 24 hours
|
||||
authCookie.setSameSite(Cookie::SameSite::kLax);
|
||||
resp->addCookie(authCookie);
|
||||
}
|
||||
|
||||
// Helper to clear auth cookie
|
||||
void clearAuthCookie(const HttpResponsePtr& resp) {
|
||||
Cookie authCookie("auth_token", "");
|
||||
authCookie.setPath("/");
|
||||
authCookie.setHttpOnly(true);
|
||||
authCookie.setMaxAge(0); // Expire immediately
|
||||
resp->addCookie(authCookie);
|
||||
}
|
||||
}
|
||||
|
||||
UserInfo UserController::getUserFromRequest(const HttpRequestPtr &req) {
|
||||
UserInfo user;
|
||||
std::string auth = req->getHeader("Authorization");
|
||||
|
||||
if (auth.empty() || auth.substr(0, 7) != "Bearer ") {
|
||||
return user;
|
||||
// First try to get from cookie
|
||||
std::string token = req->getCookie("auth_token");
|
||||
|
||||
// Fallback to Authorization header for API clients
|
||||
if (token.empty()) {
|
||||
std::string auth = req->getHeader("Authorization");
|
||||
if (!auth.empty() && auth.substr(0, 7) == "Bearer ") {
|
||||
token = auth.substr(7);
|
||||
}
|
||||
}
|
||||
|
||||
if (!token.empty()) {
|
||||
AuthService::getInstance().validateToken(token, user);
|
||||
}
|
||||
|
||||
std::string token = auth.substr(7);
|
||||
AuthService::getInstance().validateToken(token, user);
|
||||
return user;
|
||||
}
|
||||
|
||||
|
|
@ -168,9 +197,10 @@ void UserController::login(const HttpRequestPtr &req,
|
|||
[callback, username](bool success, const std::string& token, const UserInfo& user) {
|
||||
if (success) {
|
||||
LOG_INFO << "Login successful for user: " << username;
|
||||
|
||||
Json::Value resp;
|
||||
resp["success"] = true;
|
||||
resp["token"] = token;
|
||||
// Don't send token in body for cookie-based auth
|
||||
resp["user"]["id"] = static_cast<Json::Int64>(user.id);
|
||||
resp["user"]["username"] = user.username;
|
||||
resp["user"]["isAdmin"] = user.isAdmin;
|
||||
|
|
@ -179,8 +209,11 @@ void UserController::login(const HttpRequestPtr &req,
|
|||
resp["user"]["bio"] = user.bio;
|
||||
resp["user"]["avatarUrl"] = user.avatarUrl;
|
||||
resp["user"]["pgpOnlyEnabledAt"] = user.pgpOnlyEnabledAt;
|
||||
resp["user"]["colorCode"] = user.colorCode; // Use colorCode for consistency with database field name
|
||||
callback(jsonResp(resp));
|
||||
resp["user"]["colorCode"] = user.colorCode;
|
||||
|
||||
auto response = jsonResp(resp);
|
||||
setAuthCookie(response, token);
|
||||
callback(response);
|
||||
} else {
|
||||
LOG_WARN << "Login failed for user: " << username;
|
||||
callback(jsonError(token.empty() ? "Invalid credentials" : token, k401Unauthorized));
|
||||
|
|
@ -195,6 +228,22 @@ void UserController::login(const HttpRequestPtr &req,
|
|||
}
|
||||
}
|
||||
|
||||
void UserController::logout(const HttpRequestPtr &req,
|
||||
std::function<void(const HttpResponsePtr &)> &&callback) {
|
||||
try {
|
||||
Json::Value resp;
|
||||
resp["success"] = true;
|
||||
resp["message"] = "Logged out successfully";
|
||||
|
||||
auto response = jsonResp(resp);
|
||||
clearAuthCookie(response);
|
||||
callback(response);
|
||||
} catch (const std::exception& e) {
|
||||
LOG_ERROR << "Exception in logout: " << e.what();
|
||||
callback(jsonError("Internal server error"));
|
||||
}
|
||||
}
|
||||
|
||||
void UserController::pgpChallenge(const HttpRequestPtr &req,
|
||||
std::function<void(const HttpResponsePtr &)> &&callback) {
|
||||
try {
|
||||
|
|
@ -264,7 +313,7 @@ void UserController::pgpVerify(const HttpRequestPtr &req,
|
|||
if (success) {
|
||||
Json::Value resp;
|
||||
resp["success"] = true;
|
||||
resp["token"] = token;
|
||||
// Don't send token in body for cookie-based auth
|
||||
resp["user"]["id"] = static_cast<Json::Int64>(user.id);
|
||||
resp["user"]["username"] = user.username;
|
||||
resp["user"]["isAdmin"] = user.isAdmin;
|
||||
|
|
@ -273,8 +322,11 @@ void UserController::pgpVerify(const HttpRequestPtr &req,
|
|||
resp["user"]["bio"] = user.bio;
|
||||
resp["user"]["avatarUrl"] = user.avatarUrl;
|
||||
resp["user"]["pgpOnlyEnabledAt"] = user.pgpOnlyEnabledAt;
|
||||
resp["user"]["colorCode"] = user.colorCode; // Add colorCode to PGP login response
|
||||
callback(jsonResp(resp));
|
||||
resp["user"]["colorCode"] = user.colorCode;
|
||||
|
||||
auto response = jsonResp(resp);
|
||||
setAuthCookie(response, token);
|
||||
callback(response);
|
||||
} else {
|
||||
callback(jsonError("Invalid signature", k401Unauthorized));
|
||||
}
|
||||
|
|
@ -782,7 +834,7 @@ void UserController::updateColor(const HttpRequestPtr &req,
|
|||
AuthService::getInstance().updateUserColor(user.id, newColor,
|
||||
[callback, user](bool success, const std::string& error, const std::string& finalColor) {
|
||||
if (success) {
|
||||
// Fetch updated user info and generate new token with updated color
|
||||
// Fetch updated user info
|
||||
AuthService::getInstance().fetchUserInfo(user.id,
|
||||
[callback, finalColor](bool fetchSuccess, const UserInfo& updatedUser) {
|
||||
if (fetchSuccess) {
|
||||
|
|
@ -792,13 +844,16 @@ void UserController::updateColor(const HttpRequestPtr &req,
|
|||
Json::Value resp;
|
||||
resp["success"] = true;
|
||||
resp["color"] = finalColor;
|
||||
resp["token"] = newToken; // Return new token with updated color
|
||||
resp["user"]["id"] = static_cast<Json::Int64>(updatedUser.id);
|
||||
resp["user"]["username"] = updatedUser.username;
|
||||
resp["user"]["isAdmin"] = updatedUser.isAdmin;
|
||||
resp["user"]["isStreamer"] = updatedUser.isStreamer;
|
||||
resp["user"]["colorCode"] = updatedUser.colorCode;
|
||||
callback(jsonResp(resp));
|
||||
|
||||
auto response = jsonResp(resp);
|
||||
// Update auth cookie with new token
|
||||
setAuthCookie(response, newToken);
|
||||
callback(response);
|
||||
} else {
|
||||
// Color was updated but couldn't fetch full user info
|
||||
Json::Value resp;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue