Add some functionality

new handler for me
This commit is contained in:
2026-05-04 21:08:56 +03:00
parent c3f6d71c71
commit 45f506a087
8 changed files with 102 additions and 10 deletions
BIN
View File
Binary file not shown.
+9 -1
View File
@@ -8,7 +8,7 @@
#include "repo/user_repository.hpp"
#include "security/password_hasher.hpp"
#include "security/session_token_service.hpp"
#include "service/auto_service.hpp"
#include "service/auth_service.hpp"
#include "util/time_utils.hpp"
#include "util/validation.hpp"
@@ -52,6 +52,14 @@ int Application::run() const {
HealthController health_controller;
AuthController auth_controller(auth_service);
drogon::app().registerHandler(
"/me",
[&auth_controller](const drogon::HttpRequestPtr &req,
std::function<void(const drogon::HttpResponsePtr &)> &&callback) {
auth_controller.me(req, std::move(callback));
},
{ drogon::Get });
drogon::app().registerHandler(
"/login",
[&auth_controller](const drogon::HttpRequestPtr &req,
+41 -7
View File
@@ -1,13 +1,47 @@
#include "http/controllers/auth_controller.hpp"
#include "service/auth_errors.hpp"
#include "service/auto_service.hpp"
#include "service/auth_service.hpp"
#include <drogon/drogon.h>
#include <json/json.h>
AuthController::AuthController(AuthService &auth_service)
: auto_servise_(auth_service) {}
: auth_servise_(auth_service) {}
void AuthController::me(const drogon::HttpRequestPtr &req,
std::function<void(const drogon::HttpResponsePtr &)> &&callback) const {
const auto session_token = req->getCookie("sid");
try {
const auto user = auth_servise_.authenticate_by_session_token(session_token);
Json::Value body;
body["id"] = static_cast<Json::Int64>(user.id);
body["email"] = user.email;
auto response = drogon::HttpResponse::newHttpJsonResponse(body);
response->setStatusCode(drogon::k200OK);
callback(response);
} catch(const UnauthorizedError &ex) {
Json::Value error;
error["error"]["code"] = "unauthorized";
error["error"]["message"] = ex.what();
auto response = drogon::HttpResponse::newHttpJsonResponse(error);
response->setStatusCode(drogon::k401Unauthorized);
callback(response);
} catch(const std::exception &e) {
Json::Value error;
error["error"]["code"] = "internal_error";
error["error"]["message"] = "Internal server error";
auto response = drogon::HttpResponse::newHttpJsonResponse(error);
response->setStatusCode(drogon::k500InternalServerError);
callback(response);
;
}
}
void AuthController::login(const drogon::HttpRequestPtr &req,
std::function<void(const drogon::HttpResponsePtr &)> &&callback) const {
@@ -17,13 +51,13 @@ void AuthController::login(const drogon::HttpRequestPtr
error["error"]["code"] = "invalid_request";
error["error"]["message"] = "Expected JSON body with email and password";
auto responce = drogon::HttpResponse::newHttpJsonResponse(error);
responce->setStatusCode(drogon::k400BadRequest);
callback(responce);
auto response = drogon::HttpResponse::newHttpJsonResponse(error);
response->setStatusCode(drogon::k400BadRequest);
callback(response);
return;
}
try {
const auto result = auto_servise_.login(LoginCommand{
const auto result = auth_servise_.login(LoginCommand{
.email = (*json)["email"].asString(),
.password = (*json)["password"].asString(),
});
@@ -91,7 +125,7 @@ void AuthController::register_user(
}
try {
const auto result = auto_servise_.register_user(RegisterCommand{
const auto result = auth_servise_.register_user(RegisterCommand{
.email = (*json)["email"].asString(),
.password = (*json)["password"].asString(),
});
+4 -1
View File
@@ -15,10 +15,13 @@ public:
void login(const drogon::HttpRequestPtr &req,
std::function<void(const drogon::HttpResponsePtr &)> &&callback) const;
void me(const drogon::HttpRequestPtr &req,
std::function<void(const drogon::HttpResponsePtr &)> &&callback) const;
private:
bool isValidAuthJson(const std::shared_ptr<Json::Value> &req) const;
bool isValidLoginJson(const std::shared_ptr<Json::Value> &req) const;
private:
AuthService &auto_servise_;
AuthService &auth_servise_;
};
+4
View File
@@ -26,6 +26,10 @@ SessionTokenPair SessionTokenService::generate() const {
return SessionTokenPair{ .raw_token = raw_token, .token_hash = token_hash };
}
std::string SessionTokenService::hash_token(std::string_view raw_token) const {
return sha256_hex(std::string{ raw_token });
}
std::string SessionTokenService::generate_random_token() {
unsigned char buffer[kTokenSizeBytes];
if(RAND_bytes(buffer, sizeof(buffer)) != 1) {
+2
View File
@@ -9,6 +9,8 @@ class SessionTokenService {
public:
SessionTokenPair generate() const;
std::string hash_token(std::string_view raw_token) const;
private:
static std::string generate_random_token();
static std::string sha256_hex(const std::string &input);
+35 -1
View File
@@ -6,7 +6,7 @@
#include "util/time_utils.hpp"
#include "util/validation.hpp"
#include <service/auto_service.hpp>
#include <service/auth_service.hpp>
#include <stdexcept>
AuthService::AuthService(UserRepository &users, SessionRepository &session,
@@ -32,6 +32,40 @@ void AuthService::validateData(std::string_view email, std::string_view password
throw EmailAlreadyExistsError("Email already exists");
}
}
CurrentUserResult AuthService::authenticate_by_session_token(std::string_view raw_token) const {
if(raw_token.empty()) {
throw UnauthorizedError("Unauthorized");
}
const auto token_hash = token_service_.hash_token(raw_token);
const auto session = sessions_.find_by_token_hash(token_hash);
if(!session.has_value()) {
throw UnauthorizedError("Unauthorized");
}
if(session->revoked_at.has_value()) {
throw UnauthorizedError("Unauthorized");
}
const auto now = now_utc_iso8601();
if(session->expires_at <= now) {
throw UnauthorizedError("Session expired");
}
const auto user = users_.find_by_id(session->user_id);
if(!user.has_value() || !user->is_active) {
throw UnauthorizedError("Unauthorized");
}
return CurrentUserResult{
.id = user->id,
.email = user->email,
};
}
LoginResult AuthService::login(const LoginCommand &command) const {
const auto email = normalize_email(command.email);
// validateData(email, command.password);
@@ -27,6 +27,11 @@ struct RegisterResult {
std::string email;
};
struct CurrentUserResult {
std::int64_t id{};
std::string email;
};
class AuthService {
public:
AuthService(UserRepository &users, SessionRepository &session, PasswordHasher &password_hasher,
@@ -35,6 +40,8 @@ public:
RegisterResult register_user(const RegisterCommand &command) const;
LoginResult login(const LoginCommand &loginCommand) const;
CurrentUserResult authenticate_by_session_token(std::string_view raw_token) const;
private:
void validateData(std::string_view email, std::string_view password) const;