fileserver/src/server/server.cxx

88 lines
2.6 KiB
C++
Raw Normal View History

#include "server_internal.hxx"
std::shared_ptr<Token> Server::get_token(const std::string &token) {
std::shared_lock lock{token_lock};
const auto &entry = tokens.find(token);
if (entry == tokens.end())
return nullptr;
return entry->second;
}
std::shared_ptr<User> Server::get_user(std::uint64_t id) {
std::shared_lock lock{user_lock};
const auto &entry = users.find(id);
if (entry == users.end())
return nullptr;
return entry->second;
}
std::shared_ptr<User> Server::is_token_valid(const std::string &token) {
auto t = get_token(token);
if (!t)
return nullptr;
if (Token::clock::now() <= t->expire) {
t->refresh();
return t->user;
}
{
std::unique_lock lock{token_lock};
tokens.erase(token);
}
return nullptr;
}
void Server::logout_user(std::uint64_t id) {
std::unique_lock lock{token_lock};
for (auto it = tokens.begin(); it != tokens.end();) {
if (it->second->user->id == id)
tokens.erase(it++);
else
++it;
}
}
void Server::delete_user(const std::shared_ptr<User> &user) {
std::unique_lock lock{user_lock};
logout_user(user->id);
delete_node(user, 0, [](const std::string&){});
users.erase(user->id);
}
void Server::send_tfa_mail(const std::shared_ptr<User> &user) {
std::lock_guard lock{mail_otp_lock};
std::string code; code.reserve(10);
for (int i = 0; i < 10; ++i) {
auto j = auth_rng->next_byte();
while (j > 249) j = auth_rng->next_byte();
code.push_back('0' + (j%10));
}
mail_otp.emplace(code, std::make_pair(user->id, Token::clock::now() + std::chrono::minutes{10}));
send_mail(user->name, "MFileserver - TFA code", "Your code is: " + code + "\r\nIt is valid for 10 minutes");
}
bool Server::check_mail_code(const std::shared_ptr<User> &user, const std::string &code) {
std::lock_guard lock{mail_otp_lock};
auto now = Token::clock::now();
for (auto it = mail_otp.begin(); it != mail_otp.end();) {
if (now >= it->second.second)
mail_otp.erase(it++);
else
++it;
}
const auto &entry = mail_otp.find(code);
bool ok = entry != mail_otp.end() && entry->second.first == user->id;
if (ok)
mail_otp.erase(code);
return ok;
}
bool Server::check_tfa_code(const std::shared_ptr<User> &user, const std::string &code_str) {
Botan::OctetString secret{user->tfa_secret};
Botan::TOTP totp{secret};
try {
std::uint32_t code = std::stoul(code_str);
return totp.verify_totp(code, std::chrono::system_clock::now(), 1);
} catch (std::exception &_) {}
return false;
}