67 lines
1.7 KiB
C++
67 lines
1.7 KiB
C++
#include "common/Auth.h"
|
|
|
|
#include "common/Crypto.h"
|
|
|
|
#include <drogon/drogon.h>
|
|
|
|
namespace visione::auth
|
|
{
|
|
std::optional<std::string> bearerToken(const drogon::HttpRequestPtr &request)
|
|
{
|
|
const auto header = request->getHeader("Authorization");
|
|
constexpr std::string_view prefix = "Bearer ";
|
|
if (!header.starts_with(prefix))
|
|
{
|
|
return std::nullopt;
|
|
}
|
|
return header.substr(prefix.size());
|
|
}
|
|
|
|
std::optional<UserContext> authenticate(const drogon::HttpRequestPtr &request)
|
|
{
|
|
const auto token = bearerToken(request);
|
|
if (!token)
|
|
{
|
|
return std::nullopt;
|
|
}
|
|
|
|
auto db = drogon::app().getDbClient();
|
|
const auto result = db->execSqlSync(
|
|
"SELECT u.id, u.email, COALESCE(MIN(r.name), 'citizen') AS role "
|
|
"FROM api_tokens t "
|
|
"JOIN users u ON u.id = t.user_id "
|
|
"LEFT JOIN user_roles ur ON ur.user_id = u.id "
|
|
"LEFT JOIN roles r ON r.id = ur.role_id "
|
|
"WHERE t.token_hash = ? AND t.revoked_at IS NULL "
|
|
"AND t.expires_at > NOW() AND u.banned = FALSE "
|
|
"GROUP BY u.id, u.email",
|
|
crypto::hashSecret(*token));
|
|
|
|
if (result.empty())
|
|
{
|
|
return std::nullopt;
|
|
}
|
|
|
|
const auto &row = result[0];
|
|
return UserContext{row["id"].as<long long>(),
|
|
row["email"].as<std::string>(),
|
|
row["role"].as<std::string>()};
|
|
}
|
|
|
|
bool hasRole(const UserContext &user, const std::string &role)
|
|
{
|
|
return user.role == role;
|
|
}
|
|
|
|
bool canManageReports(const UserContext &user)
|
|
{
|
|
return user.role == "admin" || user.role == "operator";
|
|
}
|
|
|
|
bool isAdmin(const UserContext &user)
|
|
{
|
|
return user.role == "admin";
|
|
}
|
|
} // namespace visione::auth
|
|
|