mirror of
https://github.com/KingDuckZ/kamokan.git
synced 2025-10-02 15:00:02 +00:00
Use the lua script to save new pasties.
I had to add a {store:} prefix, see this: https://stackoverflow.com/questions/38720084/generate-new-key-inside-evalsha
This commit is contained in:
parent
3dc644c91a
commit
6222f1e1b1
8 changed files with 78 additions and 42 deletions
|
@ -8,7 +8,6 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
add_library(${PROJECT_NAME} STATIC
|
add_library(${PROJECT_NAME} STATIC
|
||||||
response.cpp
|
response.cpp
|
||||||
submit_paste_response.cpp
|
submit_paste_response.cpp
|
||||||
num_to_token.cpp
|
|
||||||
index_response.cpp
|
index_response.cpp
|
||||||
pastie_response.cpp
|
pastie_response.cpp
|
||||||
ini_file.cpp
|
ini_file.cpp
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
local token = KEYS[1]
|
local token = KEYS[1]
|
||||||
local result = redis.call("HMGET", token, "pastie", "selfdes", "lang")
|
local token_prefix = ARGV[1]
|
||||||
|
local full_token = token_prefix .. token
|
||||||
|
local result = redis.call("HMGET", full_token, "pastie", "selfdes", "lang")
|
||||||
if false == result[1] then
|
if false == result[1] then
|
||||||
return redis.error_reply("PastieNotFound")
|
return redis.error_reply("PastieNotFound")
|
||||||
end
|
end
|
||||||
|
@ -7,7 +9,7 @@ end
|
||||||
local selfdes = 0
|
local selfdes = 0
|
||||||
local deleted = 0
|
local deleted = 0
|
||||||
if result[2] == 1 then
|
if result[2] == 1 then
|
||||||
deleted = redis.call("DEL", token)
|
deleted = redis.call("DEL", full_token)
|
||||||
selfdes = 1
|
selfdes = 1
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
function num_to_value (num)
|
local function num_to_token (num)
|
||||||
local retval = ""
|
local retval = ""
|
||||||
local running = true
|
local running = true
|
||||||
|
|
||||||
|
@ -12,18 +12,34 @@ function num_to_value (num)
|
||||||
return retval
|
return retval
|
||||||
end
|
end
|
||||||
|
|
||||||
paste_counter = KEYS[1]
|
local paste_counter_token = KEYS[1]
|
||||||
next_id = redis.call("INCR", paste_counter) - 1
|
local flooding_token = KEYS[2]
|
||||||
token = num_to_token(next_id)
|
|
||||||
text = ARGV[1]
|
local flooding_result = redis.call("GET", flooding_token)
|
||||||
ttl = ARGV[2]
|
if flooding_result then
|
||||||
lang = ARGV[3]
|
return redis.error_reply("UserFlooding")
|
||||||
selfdestruct = ARGV[4]
|
end
|
||||||
redis.call("HMSET", token,
|
|
||||||
"pastie", text,
|
local token_prefix = ARGV[1]
|
||||||
"max_ttl", ttl,
|
local text = ARGV[2]
|
||||||
"lang", lang,
|
local ttl = ARGV[3]
|
||||||
"selfdes", selfdestruct
|
local lang = ARGV[4]
|
||||||
|
local selfdestruct = ARGV[5]
|
||||||
|
local flood_wait = ARGV[6]
|
||||||
|
|
||||||
|
local next_id = redis.call("INCR", paste_counter_token) - 1
|
||||||
|
local token = num_to_token(next_id)
|
||||||
|
local saved = redis.call("HMSET", token_prefix .. token,
|
||||||
|
"pastie", text,
|
||||||
|
"max_ttl", ttl,
|
||||||
|
"lang", lang,
|
||||||
|
"selfdes", selfdestruct
|
||||||
)
|
)
|
||||||
|
if saved then
|
||||||
|
redis.call("SET", flooding_token, "")
|
||||||
|
redis.call("EXPIRE", flooding_token, flood_wait)
|
||||||
|
else
|
||||||
|
return redis.error_reply("PastieNotSaved")
|
||||||
|
end
|
||||||
|
|
||||||
return token
|
return token
|
||||||
|
|
|
@ -18,12 +18,12 @@
|
||||||
#include "storage.hpp"
|
#include "storage.hpp"
|
||||||
#include "settings_bag.hpp"
|
#include "settings_bag.hpp"
|
||||||
#include "incredis/incredis.hpp"
|
#include "incredis/incredis.hpp"
|
||||||
#include "num_to_token.hpp"
|
|
||||||
#include "duckhandy/stringize.h"
|
#include "duckhandy/stringize.h"
|
||||||
#include "spdlog.hpp"
|
#include "spdlog.hpp"
|
||||||
#include "truncated_string.hpp"
|
#include "truncated_string.hpp"
|
||||||
#include "string_conv.hpp"
|
#include "string_conv.hpp"
|
||||||
#include "lua_scripts_for_redis.hpp"
|
#include "lua_scripts_for_redis.hpp"
|
||||||
|
#include "redis_to_error_reason.hpp"
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <ciso646>
|
#include <ciso646>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
@ -32,6 +32,8 @@
|
||||||
|
|
||||||
namespace kamokan {
|
namespace kamokan {
|
||||||
namespace {
|
namespace {
|
||||||
|
const char g_token_prefix[] = "kamokan:{store:}";
|
||||||
|
|
||||||
redis::IncRedis make_incredis (const SettingsBag& parSettings) {
|
redis::IncRedis make_incredis (const SettingsBag& parSettings) {
|
||||||
using redis::IncRedis;
|
using redis::IncRedis;
|
||||||
|
|
||||||
|
@ -130,54 +132,64 @@ namespace kamokan {
|
||||||
const std::string& parRemoteIP
|
const std::string& parRemoteIP
|
||||||
) const {
|
) const {
|
||||||
using tawashi::ErrorReasons;
|
using tawashi::ErrorReasons;
|
||||||
using redis::RedisInt;
|
using boost::string_view;
|
||||||
|
using dhandy::lexical_cast;
|
||||||
|
|
||||||
if (not is_connected())
|
if (not is_connected())
|
||||||
return make_submission_result(ErrorReasons::RedisDisconnected);
|
return make_submission_result(ErrorReasons::RedisDisconnected);
|
||||||
|
|
||||||
assert(m_redis);
|
assert(m_redis);
|
||||||
auto& redis = *m_redis;
|
auto& redis = *m_redis;
|
||||||
if (redis.get(parRemoteIP)) {
|
|
||||||
//please wait and submit again
|
redis::Script retrieve = m_redis->command().make_script(string_view(g_save_script, g_save_script_size));
|
||||||
return make_submission_result(ErrorReasons::UserFlooding);
|
auto batch = m_redis->command().make_batch();
|
||||||
|
{
|
||||||
|
string_view paste_counter_token("{store:}paste_counter");
|
||||||
|
std::string prefix(g_token_prefix);
|
||||||
|
const auto expiry = lexical_cast<std::string>(parExpiry);
|
||||||
|
const auto self_des = string_view(parSelfDestruct ? "1" : "0");
|
||||||
|
const auto flood_wait = m_settings->as<string_view>("resubmit_wait");
|
||||||
|
retrieve.run(batch,
|
||||||
|
std::make_tuple(paste_counter_token, prefix + parRemoteIP),
|
||||||
|
std::make_tuple(prefix, parText, expiry, parLang, self_des, flood_wait)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
auto raw_replies = batch.replies();
|
||||||
|
auto statuslog = spdlog::get("statuslog");
|
||||||
|
if (raw_replies.empty()) {
|
||||||
|
statuslog->error("Received empty reply from redis");
|
||||||
|
return make_submission_result(ErrorReasons::UnknownReason);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto statuslog = spdlog::get("statuslog");
|
if (raw_replies.front().is_error()) {
|
||||||
|
statuslog->error("Received error reply from redis");
|
||||||
|
return make_submission_result(redis_to_error_reason(get_error_string(raw_replies.front())));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string token = get_string(raw_replies.front());
|
||||||
|
|
||||||
if (statuslog->should_log(spdlog::level::info)) {
|
if (statuslog->should_log(spdlog::level::info)) {
|
||||||
statuslog->info(
|
statuslog->info(
|
||||||
"Submitting pastie of size {} to redis -> \"{}\"",
|
"Saved pastie of size {} to redis token \"{}\" -> \"{}\"",
|
||||||
parText.size(),
|
parText.size(),
|
||||||
|
token,
|
||||||
tawashi::truncated_string(parText, 30)
|
tawashi::truncated_string(parText, 30)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
return make_submission_result(std::move(token));
|
||||||
const auto next_id = redis.incr("paste_counter");
|
|
||||||
std::string token = num_to_token(next_id);
|
|
||||||
assert(not token.empty());
|
|
||||||
if (redis.hmset(token,
|
|
||||||
"pastie", parText,
|
|
||||||
"max_ttl", dhandy::lexical_cast<std::string>(parExpiry),
|
|
||||||
"lang", parLang,
|
|
||||||
"selfdes", static_cast<RedisInt>(parSelfDestruct ? 1 : 0))
|
|
||||||
) {
|
|
||||||
redis.set(parRemoteIP, "");
|
|
||||||
redis.expire(parRemoteIP, m_settings->as<uint32_t>("resubmit_wait"));
|
|
||||||
if (redis.expire(token, parExpiry))
|
|
||||||
return make_submission_result(std::move(token));
|
|
||||||
}
|
|
||||||
|
|
||||||
return make_submission_result(ErrorReasons::PastieNotSaved);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Storage::retrieve_pastie (const boost::string_view& parToken, uint32_t parMaxTokenLen) const -> RetrievedPastie {
|
auto Storage::retrieve_pastie (const boost::string_view& parToken, uint32_t parMaxTokenLen) const -> RetrievedPastie {
|
||||||
|
using boost::string_view;
|
||||||
|
|
||||||
RetrievedPastie retval;
|
RetrievedPastie retval;
|
||||||
retval.valid_token = is_valid_token(parToken, parMaxTokenLen);
|
retval.valid_token = is_valid_token(parToken, parMaxTokenLen);
|
||||||
if (not retval.valid_token)
|
if (not retval.valid_token)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
redis::Script retrieve = m_redis->command().make_script(boost::string_view(g_load_script, g_load_script_size));
|
redis::Script retrieve = m_redis->command().make_script(string_view(g_load_script, g_load_script_size));
|
||||||
auto batch = m_redis->command().make_batch();
|
auto batch = m_redis->command().make_batch();
|
||||||
retrieve.run(batch, std::make_tuple(parToken), std::make_tuple());
|
retrieve.run(batch, std::make_tuple(parToken), std::make_tuple(string_view(g_token_prefix)));
|
||||||
auto raw_replies = batch.replies();
|
auto raw_replies = batch.replies();
|
||||||
if (raw_replies.empty())
|
if (raw_replies.empty())
|
||||||
return retval;
|
return retval;
|
||||||
|
|
|
@ -50,6 +50,12 @@ namespace kamokan {
|
||||||
return dhandy::lexical_cast<uint32_t>(parStr);
|
return dhandy::lexical_cast<uint32_t>(parStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
[[gnu::pure,gnu::always_inline]] inline
|
||||||
|
long long string_conv (boost::string_view parStr) {
|
||||||
|
return dhandy::lexical_cast<long long>(parStr);
|
||||||
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
inline
|
inline
|
||||||
std::string string_conv (boost::string_view parStr) {
|
std::string string_conv (boost::string_view parStr) {
|
||||||
|
|
|
@ -11,6 +11,7 @@ add_executable(${PROJECT_NAME}
|
||||||
test_index_response.cpp
|
test_index_response.cpp
|
||||||
test_submit_pastie.cpp
|
test_submit_pastie.cpp
|
||||||
fake_storage.cpp
|
fake_storage.cpp
|
||||||
|
num_to_token.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
target_include_directories(${PROJECT_NAME}
|
target_include_directories(${PROJECT_NAME}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue