feat: expand platform management, admin controls, and learning workflows
这个提交包含在:
@@ -9,10 +9,12 @@
|
||||
#include "csp/services/problem_solution_runner.h"
|
||||
#include "csp/services/problem_workspace_service.h"
|
||||
#include "csp/services/submission_service.h"
|
||||
#include "csp/services/user_service.h"
|
||||
#include "http_auth.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <exception>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
namespace csp::controllers {
|
||||
@@ -47,6 +49,25 @@ int ParsePositiveInt(const std::string& s,
|
||||
return std::max(min_value, std::min(max_value, v));
|
||||
}
|
||||
|
||||
std::optional<int64_t> RequireAdminUserId(
|
||||
const drogon::HttpRequestPtr& req,
|
||||
std::function<void(const drogon::HttpResponsePtr&)>& cb) {
|
||||
std::string auth_error;
|
||||
const auto user_id = GetAuthedUserId(req, auth_error);
|
||||
if (!user_id.has_value()) {
|
||||
cb(JsonError(drogon::k401Unauthorized, auth_error));
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
services::UserService users(csp::AppState::Instance().db());
|
||||
const auto user = users.GetById(*user_id);
|
||||
if (!user.has_value() || user->username != "admin") {
|
||||
cb(JsonError(drogon::k403Forbidden, "admin only"));
|
||||
return std::nullopt;
|
||||
}
|
||||
return user_id;
|
||||
}
|
||||
|
||||
Json::Value BuildOpenApiSpec() {
|
||||
Json::Value root;
|
||||
root["openapi"] = "3.1.0";
|
||||
@@ -173,6 +194,8 @@ void MetaController::backendLogs(
|
||||
const drogon::HttpRequestPtr& req,
|
||||
std::function<void(const drogon::HttpResponsePtr&)>&& cb) {
|
||||
try {
|
||||
if (!RequireAdminUserId(req, cb).has_value()) return;
|
||||
|
||||
const int limit =
|
||||
ParsePositiveInt(req->getParameter("limit"), 100, 1, 500);
|
||||
const int running_limit =
|
||||
@@ -274,9 +297,11 @@ void MetaController::backendLogs(
|
||||
}
|
||||
|
||||
void MetaController::kbRefreshStatus(
|
||||
const drogon::HttpRequestPtr& /*req*/,
|
||||
const drogon::HttpRequestPtr& req,
|
||||
std::function<void(const drogon::HttpResponsePtr&)>&& cb) {
|
||||
try {
|
||||
if (!RequireAdminUserId(req, cb).has_value()) return;
|
||||
|
||||
const auto& runner = services::KbImportRunner::Instance();
|
||||
Json::Value payload;
|
||||
payload["running"] = runner.IsRunning();
|
||||
@@ -299,12 +324,7 @@ void MetaController::triggerKbRefresh(
|
||||
const drogon::HttpRequestPtr& req,
|
||||
std::function<void(const drogon::HttpResponsePtr&)>&& cb) {
|
||||
try {
|
||||
std::string auth_error;
|
||||
const auto user_id = GetAuthedUserId(req, auth_error);
|
||||
if (!user_id.has_value()) {
|
||||
cb(JsonError(drogon::k401Unauthorized, auth_error));
|
||||
return;
|
||||
}
|
||||
if (!RequireAdminUserId(req, cb).has_value()) return;
|
||||
|
||||
auto& runner = services::KbImportRunner::Instance();
|
||||
const bool started = runner.TriggerAsync("manual");
|
||||
@@ -332,12 +352,8 @@ void MetaController::triggerMissingSolutions(
|
||||
const drogon::HttpRequestPtr& req,
|
||||
std::function<void(const drogon::HttpResponsePtr&)>&& cb) {
|
||||
try {
|
||||
std::string auth_error;
|
||||
const auto user_id = GetAuthedUserId(req, auth_error);
|
||||
if (!user_id.has_value()) {
|
||||
cb(JsonError(drogon::k401Unauthorized, auth_error));
|
||||
return;
|
||||
}
|
||||
const auto user_id = RequireAdminUserId(req, cb);
|
||||
if (!user_id.has_value()) return;
|
||||
|
||||
int limit = 50000;
|
||||
int max_solutions = 3;
|
||||
|
||||
在新工单中引用
屏蔽一个用户