feat(api): add auth HTTP controller with tests
这个提交包含在:
@@ -0,0 +1,75 @@
|
||||
#include "csp/controllers/auth_controller.h"
|
||||
|
||||
#include "csp/app_state.h"
|
||||
#include "csp/services/auth_service.h"
|
||||
|
||||
#include <drogon/HttpResponse.h>
|
||||
|
||||
namespace csp::controllers {
|
||||
|
||||
namespace {
|
||||
|
||||
drogon::HttpResponsePtr JsonError(drogon::HttpStatusCode code,
|
||||
const std::string& msg) {
|
||||
Json::Value j;
|
||||
j["ok"] = false;
|
||||
j["error"] = msg;
|
||||
auto resp = drogon::HttpResponse::newHttpJsonResponse(j);
|
||||
resp->setStatusCode(code);
|
||||
return resp;
|
||||
}
|
||||
|
||||
drogon::HttpResponsePtr JsonOk(const services::AuthResult& r) {
|
||||
Json::Value j;
|
||||
j["ok"] = true;
|
||||
j["user_id"] = r.user_id;
|
||||
j["token"] = r.token;
|
||||
j["expires_at"] = Json::Int64(r.expires_at);
|
||||
auto resp = drogon::HttpResponse::newHttpJsonResponse(j);
|
||||
resp->setStatusCode(drogon::k200OK);
|
||||
return resp;
|
||||
}
|
||||
|
||||
std::pair<std::string, std::string> ParseUsernamePassword(
|
||||
const drogon::HttpRequestPtr& req) {
|
||||
const auto json = req->getJsonObject();
|
||||
if (!json) throw std::runtime_error("body must be json");
|
||||
|
||||
const auto username = (*json).get("username", "").asString();
|
||||
const auto password = (*json).get("password", "").asString();
|
||||
|
||||
if (username.empty() || password.empty()) {
|
||||
throw std::runtime_error("username/password required");
|
||||
}
|
||||
return {username, password};
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void AuthController::registerUser(
|
||||
const drogon::HttpRequestPtr& req,
|
||||
std::function<void(const drogon::HttpResponsePtr&)>&& cb) {
|
||||
try {
|
||||
const auto [username, password] = ParseUsernamePassword(req);
|
||||
services::AuthService auth(AppState::Instance().db());
|
||||
const auto r = auth.Register(username, password);
|
||||
cb(JsonOk(r));
|
||||
} catch (const std::exception& e) {
|
||||
cb(JsonError(drogon::k400BadRequest, e.what()));
|
||||
}
|
||||
}
|
||||
|
||||
void AuthController::login(
|
||||
const drogon::HttpRequestPtr& req,
|
||||
std::function<void(const drogon::HttpResponsePtr&)>&& cb) {
|
||||
try {
|
||||
const auto [username, password] = ParseUsernamePassword(req);
|
||||
services::AuthService auth(AppState::Instance().db());
|
||||
const auto r = auth.Login(username, password);
|
||||
cb(JsonOk(r));
|
||||
} catch (const std::exception& e) {
|
||||
cb(JsonError(drogon::k400BadRequest, e.what()));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace csp::controllers
|
||||
在新工单中引用
屏蔽一个用户