mirror of
https://github.com/typesense/typesense.git
synced 2025-05-19 13:12:22 +08:00
Merge pull request #1475 from krunal1313/autodelete_expired_keys
remove expired API keys when specified
This commit is contained in:
commit
cfeab44614
@ -17,6 +17,7 @@ struct api_key_t {
|
||||
std::vector<std::string> actions;
|
||||
std::vector<std::string> collections;
|
||||
uint64_t expires_at;
|
||||
bool autodelete;
|
||||
|
||||
static constexpr const size_t PREFIX_LEN = 4;
|
||||
static constexpr const uint64_t FAR_FUTURE_TIMESTAMP = 64723363199; // year 4020
|
||||
@ -26,8 +27,9 @@ struct api_key_t {
|
||||
}
|
||||
|
||||
api_key_t(const std::string &value, const std::string &description, const std::vector<std::string> &actions,
|
||||
const std::vector<std::string> &collections, uint64_t expires_at) :
|
||||
value(value), description(description), actions(actions), collections(collections), expires_at(expires_at) {
|
||||
const std::vector<std::string> &collections, uint64_t expires_at, bool autodel=false) :
|
||||
value(value), description(description), actions(actions), collections(collections), expires_at(expires_at),
|
||||
autodelete(autodel) {
|
||||
|
||||
}
|
||||
|
||||
@ -45,6 +47,7 @@ struct api_key_t {
|
||||
description = key_obj["description"].get<std::string>();
|
||||
actions = key_obj["actions"].get<std::vector<std::string>>();
|
||||
collections = key_obj["collections"].get<std::vector<std::string>>();
|
||||
autodelete = key_obj["autodelete"].get<bool>();
|
||||
|
||||
// handle optional fields
|
||||
|
||||
@ -67,6 +70,7 @@ struct api_key_t {
|
||||
obj["actions"] = actions;
|
||||
obj["collections"] = collections;
|
||||
obj["expires_at"] = expires_at;
|
||||
obj["autodelete"] = autodelete;
|
||||
|
||||
return obj;
|
||||
}
|
||||
@ -119,6 +123,7 @@ private:
|
||||
|
||||
static bool regexp_match(const std::string& value, const std::string& regexp);
|
||||
|
||||
void remove_expired_keys();
|
||||
public:
|
||||
|
||||
static const size_t GENERATED_KEY_LEN = 32;
|
||||
@ -144,4 +149,6 @@ public:
|
||||
static bool add_item_to_params(std::map<std::string, std::string> &req_params,
|
||||
const nlohmann::detail::iteration_proxy_value<nlohmann::json::iterator>& item,
|
||||
bool overwrite);
|
||||
|
||||
void do_housekeeping();
|
||||
};
|
@ -416,4 +416,25 @@ bool AuthManager::add_item_to_params(std::map<std::string, std::string>& req_par
|
||||
return true;
|
||||
}
|
||||
|
||||
void AuthManager::remove_expired_keys() {
|
||||
const Option<std::vector<api_key_t>>& keys_op = list_keys();
|
||||
if(!keys_op.ok()) {
|
||||
LOG(ERROR) << keys_op.error();
|
||||
return;
|
||||
}
|
||||
|
||||
const std::vector<api_key_t>& keys = keys_op.get();
|
||||
for(const auto& key : keys) {
|
||||
if(key.autodelete && (uint64_t(std::time(0)) > key.expires_at)) {
|
||||
LOG(INFO) << "Deleting expired key " << key.value;
|
||||
auto delete_op = remove_key(key.id);
|
||||
if(!delete_op.ok()) {
|
||||
LOG(ERROR) << delete_op.error();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AuthManager::do_housekeeping() {
|
||||
remove_expired_keys();
|
||||
}
|
||||
|
@ -1787,6 +1787,10 @@ bool post_create_key(const std::shared_ptr<http_req>& req, const std::shared_ptr
|
||||
req_json["expires_at"] = api_key_t::FAR_FUTURE_TIMESTAMP;
|
||||
}
|
||||
|
||||
if(req_json.count("autodelete") == 0) {
|
||||
req_json["autodelete"] = false;
|
||||
}
|
||||
|
||||
const std::string &rand_key = (req_json.count("value") != 0) ?
|
||||
req_json["value"].get<std::string>() : req->metadata;
|
||||
|
||||
@ -1795,7 +1799,8 @@ bool post_create_key(const std::shared_ptr<http_req>& req, const std::shared_ptr
|
||||
req_json["description"].get<std::string>(),
|
||||
req_json["actions"].get<std::vector<std::string>>(),
|
||||
req_json["collections"].get<std::vector<std::string>>(),
|
||||
req_json["expires_at"].get<uint64_t>()
|
||||
req_json["expires_at"].get<uint64_t>(),
|
||||
req_json["autodelete"].get<bool>()
|
||||
);
|
||||
|
||||
const Option<api_key_t>& api_key_op = auth_manager.create_key(api_key);
|
||||
|
@ -48,6 +48,9 @@ void HouseKeeper::run() {
|
||||
LOG(INFO) << "Ran housekeeping for " << coll_names.size() << " collections.";
|
||||
}
|
||||
|
||||
//do housekeeping for authmanager
|
||||
CollectionManager::get_instance().getAuthManager().do_housekeeping();
|
||||
|
||||
prev_hnsw_repair_s = std::chrono::duration_cast<std::chrono::seconds>(
|
||||
std::chrono::system_clock::now().time_since_epoch()).count();
|
||||
}
|
||||
|
@ -464,4 +464,40 @@ TEST_F(AuthManagerTest, ValidateBadKeyProperties) {
|
||||
validate_op = api_key_t::validate(key_obj4);
|
||||
ASSERT_FALSE(validate_op.ok());
|
||||
ASSERT_STREQ("Key description must be a string.", validate_op.error().c_str());
|
||||
}
|
||||
|
||||
TEST_F(AuthManagerTest, AutoDeleteKeysOnExpiry) {
|
||||
auto list_op = auth_manager.list_keys();
|
||||
ASSERT_TRUE(list_op.ok());
|
||||
ASSERT_EQ(0, list_op.get().size());
|
||||
|
||||
//regular key(future ts)
|
||||
api_key_t api_key1("abcd", "test key 1", {"read", "write"}, {"collection1", "collection2"}, FUTURE_TS);
|
||||
|
||||
//key is expired (past ts)
|
||||
uint64_t PAST_TS = uint64_t(std::time(0)) - 100;
|
||||
api_key_t api_key2("wxyz", "test key 2", {"admin"}, {"*"}, PAST_TS, true);
|
||||
|
||||
auto insert_op = auth_manager.create_key(api_key1);
|
||||
ASSERT_TRUE(insert_op.ok());
|
||||
ASSERT_EQ(4, insert_op.get().value.size());
|
||||
|
||||
insert_op = auth_manager.create_key(api_key2);
|
||||
ASSERT_TRUE(insert_op.ok());
|
||||
ASSERT_EQ(4, insert_op.get().value.size());
|
||||
|
||||
list_op = auth_manager.list_keys();
|
||||
ASSERT_TRUE(list_op.ok());
|
||||
auto keys = list_op.get();
|
||||
ASSERT_EQ(2, keys.size());
|
||||
ASSERT_EQ("abcd", keys[0].value);
|
||||
ASSERT_EQ("wxyz", keys[1].value);
|
||||
|
||||
auth_manager.do_housekeeping();
|
||||
|
||||
list_op = auth_manager.list_keys();
|
||||
ASSERT_TRUE(list_op.ok());
|
||||
keys = list_op.get();
|
||||
ASSERT_EQ(1, keys.size());
|
||||
ASSERT_EQ("abcd", keys[0].value);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user