mirror of
https://github.com/badaix/snapcast.git
synced 2025-04-28 17:57:05 +02:00
Add "requiresAuthx" functions
This commit is contained in:
parent
f44a04f2c9
commit
863306d32a
4 changed files with 75 additions and 51 deletions
|
@ -98,16 +98,16 @@ std::error_code make_error_code(AuthErrc errc)
|
|||
}
|
||||
|
||||
|
||||
AuthInfo::AuthInfo(ServerSettings::Authorization settings) : is_authenticated_(false), settings_(std::move(settings))
|
||||
AuthInfo::AuthInfo(ServerSettings::Authorization auth_settings) : is_authenticated_(false), auth_settings_(std::move(auth_settings))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ErrorCode AuthInfo::validateUser(const std::string& username, const std::optional<std::string>& password) const
|
||||
{
|
||||
auto iter =
|
||||
std::find_if(settings_.users.begin(), settings_.users.end(), [&](const ServerSettings::Authorization::User& user) { return user.name == username; });
|
||||
if (iter == settings_.users.end())
|
||||
auto iter = std::find_if(auth_settings_.users.begin(), auth_settings_.users.end(),
|
||||
[&](const ServerSettings::Authorization::User& user) { return user.name == username; });
|
||||
if (iter == auth_settings_.users.end())
|
||||
return ErrorCode{AuthErrc::unknown_user};
|
||||
if (password.has_value() && (iter->password != password.value()))
|
||||
return ErrorCode{AuthErrc::wrong_password};
|
||||
|
@ -154,7 +154,7 @@ ErrorCode AuthInfo::authenticateBasic(const std::string& credentials)
|
|||
ErrorCode AuthInfo::authenticateBearer(const std::string& token)
|
||||
{
|
||||
is_authenticated_ = false;
|
||||
std::ifstream ifs(settings_.ssl.certificate);
|
||||
std::ifstream ifs(auth_settings_.ssl.certificate);
|
||||
std::string certificate((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>());
|
||||
Jwt jwt;
|
||||
if (!jwt.parse(token, certificate))
|
||||
|
@ -187,7 +187,7 @@ ErrorOr<std::string> AuthInfo::getToken(const std::string& username, const std::
|
|||
jwt.setIat(now);
|
||||
jwt.setExp(now + 10h);
|
||||
jwt.setSub(username);
|
||||
std::ifstream ifs(settings_.ssl.certificate_key);
|
||||
std::ifstream ifs(auth_settings_.ssl.certificate_key);
|
||||
std::string certificate_key((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>());
|
||||
if (!ifs.good())
|
||||
return ErrorCode{std::make_error_code(std::errc::io_error), "Failed to read private key file"};
|
||||
|
@ -215,6 +215,8 @@ bool AuthInfo::isExpired() const
|
|||
|
||||
bool AuthInfo::isAuthenticated() const
|
||||
{
|
||||
if (!auth_settings_.enabled)
|
||||
return true;
|
||||
return is_authenticated_;
|
||||
}
|
||||
|
||||
|
@ -236,14 +238,14 @@ const std::string& AuthInfo::username() const
|
|||
|
||||
bool AuthInfo::hasPermission(const std::string& resource) const
|
||||
{
|
||||
if (!settings_.enabled)
|
||||
if (!auth_settings_.enabled)
|
||||
return true;
|
||||
|
||||
if (!isAuthenticated())
|
||||
return false;
|
||||
|
||||
const auto& user_iter = std::find_if(settings_.users.begin(), settings_.users.end(), [&](const auto& user) { return user.name == username_; });
|
||||
if (user_iter == settings_.users.end())
|
||||
const auto& user_iter = std::find_if(auth_settings_.users.begin(), auth_settings_.users.end(), [&](const auto& user) { return user.name == username_; });
|
||||
if (user_iter == auth_settings_.users.end())
|
||||
return false;
|
||||
|
||||
const auto& role = user_iter->role;
|
||||
|
|
|
@ -66,7 +66,7 @@ class AuthInfo
|
|||
{
|
||||
public:
|
||||
/// c'tor
|
||||
explicit AuthInfo(ServerSettings::Authorization settings);
|
||||
explicit AuthInfo(ServerSettings::Authorization auth_settings);
|
||||
// explicit AuthInfo(std::string authheader);
|
||||
/// d'tor
|
||||
virtual ~AuthInfo() = default;
|
||||
|
@ -99,7 +99,7 @@ private:
|
|||
/// optional token expiration
|
||||
std::optional<std::chrono::system_clock::time_point> expires_;
|
||||
/// server configuration
|
||||
ServerSettings::Authorization settings_;
|
||||
ServerSettings::Authorization auth_settings_;
|
||||
|
||||
/// Validate @p username and @p password
|
||||
/// @return true if username and password are correct
|
||||
|
|
|
@ -55,9 +55,13 @@ Request::Request(const Server& server, const std::string& method) : server_(serv
|
|||
|
||||
bool Request::hasPermission(const AuthInfo& authinfo) const
|
||||
{
|
||||
bool has_permission = authinfo.hasPermission(method());
|
||||
LOG(INFO, LOG_TAG) << "Has permission for '" << method() << "': " << has_permission << "\n";
|
||||
return has_permission;
|
||||
if (!requiresAuthentication() && !requiresAuthorization())
|
||||
return true;
|
||||
|
||||
if (requiresAuthentication() && !authinfo.isAuthenticated())
|
||||
return false;
|
||||
|
||||
return authinfo.hasPermission(method());
|
||||
}
|
||||
|
||||
const std::string& Request::method() const
|
||||
|
@ -81,6 +85,15 @@ const ServerSettings& Request::getSettings() const
|
|||
return server_.settings_;
|
||||
}
|
||||
|
||||
bool Request::requiresAuthentication() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Request::requiresAuthorization() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
ControlRequestFactory::ControlRequestFactory(const Server& server)
|
||||
|
@ -891,6 +904,7 @@ void ServerAuthenticateRequest::execute(const jsonrpcpp::request_ptr& request, A
|
|||
on_response(std::move(response), nullptr);
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
ServerGetTokenRequest::ServerGetTokenRequest(const Server& server) : Request(server, "Server.GetToken")
|
||||
{
|
||||
|
@ -936,43 +950,28 @@ void GeneralGetRpcCommands::execute(const jsonrpcpp::request_ptr& request, AuthI
|
|||
{
|
||||
// clang-format off
|
||||
// Request: {"id":8,"jsonrpc":"2.0","method":"General.GetRPCCommands"}
|
||||
// Response: {"id":8,"jsonrpc":"2.0","result":{"major":2,"minor":0,"patch":0}}
|
||||
// Response: TODO
|
||||
// clang-format on
|
||||
|
||||
std::ignore = request;
|
||||
std::ignore = authinfo;
|
||||
std::ignore = on_response;
|
||||
Json result;
|
||||
Json commands = Json::array();
|
||||
|
||||
for (const auto& req : requests_)
|
||||
{
|
||||
Json jreq;
|
||||
jreq["method"] = req->method();
|
||||
jreq["hasPermission"] = req->hasPermission(authinfo);
|
||||
Json jperms;
|
||||
jperms["authentication"] = req->requiresAuthentication();
|
||||
jperms["authorization"] = req->requiresAuthorization();
|
||||
jreq["requires"] = jperms;
|
||||
commands.push_back(jreq);
|
||||
}
|
||||
Json result;
|
||||
result["commands"] = commands;
|
||||
|
||||
// for (const auto& [key, value]: request_map_)
|
||||
// {
|
||||
// key
|
||||
// }
|
||||
// // <major>: backwards incompatible change
|
||||
// result["major"] = 23;
|
||||
// // <minor>: feature addition to the API
|
||||
// result["minor"] = 0;
|
||||
// // <patch>: bugfix release
|
||||
// result["patch"] = 0;
|
||||
auto response = std::make_shared<jsonrpcpp::Response>(*request, result);
|
||||
on_response(std::move(response), nullptr);
|
||||
}
|
||||
|
||||
bool GeneralGetRpcCommands::hasPermission(const AuthInfo& authinfo) const
|
||||
{
|
||||
return authinfo.isAuthenticated();
|
||||
}
|
||||
|
||||
|
||||
void GeneralGetRpcCommands::setCommands(std::vector<std::shared_ptr<Request>> requests)
|
||||
{
|
||||
|
|
|
@ -57,6 +57,11 @@ public:
|
|||
/// @return true if the user has the permission for the request
|
||||
virtual bool hasPermission(const AuthInfo& authinfo) const;
|
||||
|
||||
/// @return user needs to be authenticated
|
||||
virtual bool requiresAuthentication() const;
|
||||
/// @return user needs authorization
|
||||
virtual bool requiresAuthorization() const;
|
||||
|
||||
/// @return the name of the method
|
||||
const std::string& method() const;
|
||||
|
||||
|
@ -68,7 +73,6 @@ protected:
|
|||
/// @return server settings
|
||||
const ServerSettings& getSettings() const;
|
||||
|
||||
|
||||
private:
|
||||
/// the server
|
||||
const Server& server_;
|
||||
|
@ -309,23 +313,16 @@ public:
|
|||
/// c'tor
|
||||
explicit ServerAuthenticateRequest(const Server& server);
|
||||
void execute(const jsonrpcpp::request_ptr& request, AuthInfo& authinfo, const OnResponse& on_response) override;
|
||||
};
|
||||
|
||||
bool requiresAuthentication() const override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/// "General.GetRpcCommands" request
|
||||
class GeneralGetRpcCommands : public Request
|
||||
{
|
||||
public:
|
||||
/// c'tor
|
||||
explicit GeneralGetRpcCommands(const Server& server);
|
||||
void execute(const jsonrpcpp::request_ptr& request, AuthInfo& authinfo, const OnResponse& on_response) override;
|
||||
bool hasPermission(const AuthInfo& authinfo) const override;
|
||||
|
||||
/// Set available @p requests
|
||||
void setCommands(std::vector<std::shared_ptr<Request>> requests);
|
||||
|
||||
private:
|
||||
std::vector<std::shared_ptr<Request>> requests_;
|
||||
bool requiresAuthorization() const override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
@ -339,3 +336,29 @@ public:
|
|||
void execute(const jsonrpcpp::request_ptr& request, AuthInfo& authinfo, const OnResponse& on_response) override;
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
/// "General.GetRpcCommands" request
|
||||
class GeneralGetRpcCommands : public Request
|
||||
{
|
||||
public:
|
||||
/// c'tor
|
||||
explicit GeneralGetRpcCommands(const Server& server);
|
||||
void execute(const jsonrpcpp::request_ptr& request, AuthInfo& authinfo, const OnResponse& on_response) override;
|
||||
|
||||
/// Set available @p requests
|
||||
void setCommands(std::vector<std::shared_ptr<Request>> requests);
|
||||
|
||||
bool requiresAuthentication() const override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool requiresAuthorization() const override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<std::shared_ptr<Request>> requests_;
|
||||
};
|
||||
|
|
Loading…
Add table
Reference in a new issue