mirror of
https://github.com/badaix/snapcast.git
synced 2025-06-19 19:21:43 +02:00
Read users and roles, remove JWT
This commit is contained in:
parent
9247588764
commit
42f4c39e6c
13 changed files with 144 additions and 68 deletions
|
@ -103,7 +103,7 @@ struct ClientSettings
|
||||||
/// Log settings
|
/// Log settings
|
||||||
struct Logging
|
struct Logging
|
||||||
{
|
{
|
||||||
/// The log sink (null,system,stdout,stderr,file:<filename>)
|
/// The log sink (null,system,stdout,stderr,file)
|
||||||
std::string sink;
|
std::string sink;
|
||||||
/// Log filter
|
/// Log filter
|
||||||
std::string filter{"*:info"};
|
std::string filter{"*:info"};
|
||||||
|
|
|
@ -6,7 +6,7 @@ set(SERVER_SOURCES
|
||||||
control_session_tcp.cpp
|
control_session_tcp.cpp
|
||||||
control_session_http.cpp
|
control_session_http.cpp
|
||||||
control_session_ws.cpp
|
control_session_ws.cpp
|
||||||
jwt.cpp
|
# jwt.cpp
|
||||||
snapserver.cpp
|
snapserver.cpp
|
||||||
server.cpp
|
server.cpp
|
||||||
stream_server.cpp
|
stream_server.cpp
|
||||||
|
|
|
@ -23,14 +23,12 @@
|
||||||
#include "common/aixlog.hpp"
|
#include "common/aixlog.hpp"
|
||||||
#include "common/base64.h"
|
#include "common/base64.h"
|
||||||
#include "common/utils/string_utils.hpp"
|
#include "common/utils/string_utils.hpp"
|
||||||
#include "jwt.hpp"
|
|
||||||
|
|
||||||
// 3rd party headers
|
// 3rd party headers
|
||||||
|
|
||||||
// standard headers
|
// standard headers
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <fstream>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <system_error>
|
#include <system_error>
|
||||||
|
|
||||||
|
@ -100,14 +98,15 @@ std::error_code make_error_code(AuthErrc errc)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
AuthInfo::AuthInfo(const ServerSettings& settings) : has_auth_info_(false), settings_(settings)
|
AuthInfo::AuthInfo(ServerSettings::Authorization settings) : has_auth_info_(false), settings_(std::move(settings))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ErrorCode AuthInfo::validateUser(const std::string& username, const std::optional<std::string>& password) const
|
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::User& user) { return user.name == username; });
|
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())
|
if (iter == settings_.users.end())
|
||||||
return ErrorCode{AuthErrc::unknown_user};
|
return ErrorCode{AuthErrc::unknown_user};
|
||||||
if (password.has_value() && (iter->password != password.value()))
|
if (password.has_value() && (iter->password != password.value()))
|
||||||
|
@ -120,12 +119,12 @@ ErrorCode AuthInfo::authenticate(const std::string& scheme, const std::string& p
|
||||||
{
|
{
|
||||||
std::string scheme_normed = utils::string::trim_copy(utils::string::tolower_copy(scheme));
|
std::string scheme_normed = utils::string::trim_copy(utils::string::tolower_copy(scheme));
|
||||||
std::string param_normed = utils::string::trim_copy(param);
|
std::string param_normed = utils::string::trim_copy(param);
|
||||||
if (scheme_normed == "bearer")
|
// if (scheme_normed == "bearer")
|
||||||
return authenticateBearer(param_normed);
|
// return authenticateBearer(param_normed);
|
||||||
else if (scheme_normed == "basic")
|
if (scheme_normed == "basic")
|
||||||
return authenticateBasic(param_normed);
|
return authenticateBasic(param_normed);
|
||||||
|
|
||||||
return {AuthErrc::auth_scheme_not_supported, "Scheme must be 'Basic' or 'Bearer'"};
|
return {AuthErrc::auth_scheme_not_supported, "Scheme must be 'Basic'"}; // or 'Bearer'"};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -151,7 +150,7 @@ ErrorCode AuthInfo::authenticateBasic(const std::string& credentials)
|
||||||
return ec;
|
return ec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
ErrorCode AuthInfo::authenticateBearer(const std::string& token)
|
ErrorCode AuthInfo::authenticateBearer(const std::string& token)
|
||||||
{
|
{
|
||||||
has_auth_info_ = false;
|
has_auth_info_ = false;
|
||||||
|
@ -198,6 +197,7 @@ ErrorOr<std::string> AuthInfo::getToken(const std::string& username, const std::
|
||||||
return ErrorCode{AuthErrc::failed_to_create_token};
|
return ErrorCode{AuthErrc::failed_to_create_token};
|
||||||
return token.value();
|
return token.value();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
bool AuthInfo::isExpired() const
|
bool AuthInfo::isExpired() const
|
||||||
|
@ -236,19 +236,25 @@ const std::string& AuthInfo::username() const
|
||||||
|
|
||||||
bool AuthInfo::hasPermission(const std::string& resource) const
|
bool AuthInfo::hasPermission(const std::string& resource) const
|
||||||
{
|
{
|
||||||
|
if (!settings_.enabled)
|
||||||
|
return true;
|
||||||
|
|
||||||
if (!hasAuthInfo())
|
if (!hasAuthInfo())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
auto iter = std::find_if(settings_.users.begin(), settings_.users.end(), [&](const ServerSettings::User& user) { return user.name == username_; });
|
const auto& user_iter = std::find_if(settings_.users.begin(), settings_.users.end(), [&](const auto& user) { return user.name == username_; });
|
||||||
if (iter == settings_.users.end())
|
if (user_iter == settings_.users.end())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
auto perm_iter = std::find_if(iter->permissions.begin(), iter->permissions.end(),
|
const auto& role = user_iter->role;
|
||||||
|
auto perm_iter = std::find_if(role->permissions.begin(), role->permissions.end(),
|
||||||
[&](const std::string& permission) { return utils::string::wildcardMatch(permission, resource); });
|
[&](const std::string& permission) { return utils::string::wildcardMatch(permission, resource); });
|
||||||
if (perm_iter != iter->permissions.end())
|
|
||||||
|
if (perm_iter != role->permissions.end())
|
||||||
{
|
{
|
||||||
LOG(DEBUG, LOG_TAG) << "Found permission for ressource '" << resource << "': '" << *perm_iter << "'\n";
|
LOG(DEBUG, LOG_TAG) << "Found permission for ressource '" << resource << "': '" << *perm_iter << "'\n";
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
This file is part of snapcast
|
||||||
Copyright (C) 2014-2024 Johannes Pohl
|
Copyright (C) 2014-2025 Johannes Pohl
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
This program is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -66,7 +66,7 @@ class AuthInfo
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/// c'tor
|
/// c'tor
|
||||||
explicit AuthInfo(const ServerSettings& settings);
|
explicit AuthInfo(ServerSettings::Authorization settings);
|
||||||
// explicit AuthInfo(std::string authheader);
|
// explicit AuthInfo(std::string authheader);
|
||||||
/// d'tor
|
/// d'tor
|
||||||
virtual ~AuthInfo() = default;
|
virtual ~AuthInfo() = default;
|
||||||
|
@ -80,14 +80,14 @@ public:
|
||||||
/// Authenticate with basic scheme
|
/// Authenticate with basic scheme
|
||||||
ErrorCode authenticateBasic(const std::string& credentials);
|
ErrorCode authenticateBasic(const std::string& credentials);
|
||||||
/// Authenticate with bearer scheme
|
/// Authenticate with bearer scheme
|
||||||
ErrorCode authenticateBearer(const std::string& token);
|
// ErrorCode authenticateBearer(const std::string& token);
|
||||||
/// Authenticate with basic or bearer scheme with an auth header
|
/// Authenticate with basic or bearer scheme with an auth header
|
||||||
ErrorCode authenticate(const std::string& auth);
|
ErrorCode authenticate(const std::string& auth);
|
||||||
/// Authenticate with scheme ("basic" or "bearer") and auth param
|
/// Authenticate with scheme ("basic" or "bearer") and auth param
|
||||||
ErrorCode authenticate(const std::string& scheme, const std::string& param);
|
ErrorCode authenticate(const std::string& scheme, const std::string& param);
|
||||||
|
|
||||||
/// @return JWS token for @p username and @p password
|
/// @return JWS token for @p username and @p password
|
||||||
ErrorOr<std::string> getToken(const std::string& username, const std::string& password) const;
|
// ErrorOr<std::string> getToken(const std::string& username, const std::string& password) const;
|
||||||
/// @return if the authenticated user has permission to access @p ressource
|
/// @return if the authenticated user has permission to access @p ressource
|
||||||
bool hasPermission(const std::string& resource) const;
|
bool hasPermission(const std::string& resource) const;
|
||||||
|
|
||||||
|
@ -99,7 +99,7 @@ private:
|
||||||
/// optional token expiration
|
/// optional token expiration
|
||||||
std::optional<std::chrono::system_clock::time_point> expires_;
|
std::optional<std::chrono::system_clock::time_point> expires_;
|
||||||
/// server configuration
|
/// server configuration
|
||||||
ServerSettings settings_;
|
ServerSettings::Authorization settings_;
|
||||||
|
|
||||||
/// Validate @p username and @p password
|
/// Validate @p username and @p password
|
||||||
/// @return true if username and password are correct
|
/// @return true if username and password are correct
|
||||||
|
|
|
@ -53,9 +53,9 @@ Request::Request(const Server& server, const std::string& method) : server_(serv
|
||||||
|
|
||||||
bool Request::hasPermission(const AuthInfo& authinfo) const
|
bool Request::hasPermission(const AuthInfo& authinfo) const
|
||||||
{
|
{
|
||||||
std::ignore = authinfo;
|
bool has_permission = authinfo.hasPermission(method());
|
||||||
return true;
|
LOG(INFO, LOG_TAG) << "Has permission for '" << method() << "': " << has_permission << "\n";
|
||||||
// return authinfo.hasPermission(method_);
|
return has_permission;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string& Request::method() const
|
const std::string& Request::method() const
|
||||||
|
@ -109,7 +109,7 @@ ControlRequestFactory::ControlRequestFactory(const Server& server)
|
||||||
add_request(std::make_shared<ServerGetStatusRequest>(server));
|
add_request(std::make_shared<ServerGetStatusRequest>(server));
|
||||||
add_request(std::make_shared<ServerDeleteClientRequest>(server));
|
add_request(std::make_shared<ServerDeleteClientRequest>(server));
|
||||||
add_request(std::make_shared<ServerAuthenticateRequest>(server));
|
add_request(std::make_shared<ServerAuthenticateRequest>(server));
|
||||||
add_request(std::make_shared<ServerGetTokenRequest>(server));
|
// add_request(std::make_shared<ServerGetTokenRequest>(server));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -877,7 +877,7 @@ void ServerAuthenticateRequest::execute(const jsonrpcpp::request_ptr& request, A
|
||||||
on_response(std::move(response), nullptr);
|
on_response(std::move(response), nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
ServerGetTokenRequest::ServerGetTokenRequest(const Server& server) : Request(server, "Server.GetToken")
|
ServerGetTokenRequest::ServerGetTokenRequest(const Server& server) : Request(server, "Server.GetToken")
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -911,3 +911,4 @@ void ServerGetTokenRequest::execute(const jsonrpcpp::request_ptr& request, AuthI
|
||||||
|
|
||||||
on_response(std::move(response), nullptr);
|
on_response(std::move(response), nullptr);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
|
@ -312,6 +312,7 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
/// "Server.GetToken" request
|
/// "Server.GetToken" request
|
||||||
class ServerGetTokenRequest : public Request
|
class ServerGetTokenRequest : public Request
|
||||||
{
|
{
|
||||||
|
@ -320,3 +321,4 @@ public:
|
||||||
explicit ServerGetTokenRequest(const Server& server);
|
explicit ServerGetTokenRequest(const Server& server);
|
||||||
void execute(const jsonrpcpp::request_ptr& request, AuthInfo& authinfo, const OnResponse& on_response) override;
|
void execute(const jsonrpcpp::request_ptr& request, AuthInfo& authinfo, const OnResponse& on_response) override;
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
|
@ -59,7 +59,7 @@ class ControlSession : public std::enable_shared_from_this<ControlSession>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/// ctor. Received message from the client are passed to ControlMessageReceiver
|
/// ctor. Received message from the client are passed to ControlMessageReceiver
|
||||||
ControlSession(ControlMessageReceiver* receiver, const ServerSettings& settings) : authinfo(settings), message_receiver_(receiver)
|
ControlSession(ControlMessageReceiver* receiver, const ServerSettings& settings) : authinfo(settings.auth), message_receiver_(receiver)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
virtual ~ControlSession() = default;
|
virtual ~ControlSession() = default;
|
||||||
|
|
|
@ -448,6 +448,7 @@ void ControlSessionHttp::on_read(beast::error_code ec, std::size_t bytes_transfe
|
||||||
auto authheader = req_[beast::http::field::authorization];
|
auto authheader = req_[beast::http::field::authorization];
|
||||||
if (!authheader.empty())
|
if (!authheader.empty())
|
||||||
{
|
{
|
||||||
|
LOG(INFO, LOG_TAG) << "Auth header: " << authheader << "\n";
|
||||||
auto ec = authinfo.authenticate(std::string{authheader});
|
auto ec = authinfo.authenticate(std::string{authheader});
|
||||||
if (ec)
|
if (ec)
|
||||||
{
|
{
|
||||||
|
|
|
@ -138,7 +138,20 @@ void Server::processRequest(const jsonrpcpp::request_ptr& request, AuthInfo& aut
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
req->execute(request, authinfo, on_response);
|
if (req->hasPermission(authinfo))
|
||||||
|
{
|
||||||
|
req->execute(request, authinfo, on_response);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::optional<jsonrpcpp::RequestException> e;
|
||||||
|
if (!authinfo.hasAuthInfo())
|
||||||
|
e.emplace(jsonrpcpp::Error("Unauthorized", 401), request->id());
|
||||||
|
else
|
||||||
|
e.emplace(jsonrpcpp::Error("Forbidden", 403), request->id());
|
||||||
|
auto response = std::make_shared<jsonrpcpp::RequestException>(e.value());
|
||||||
|
on_response(std::move(response), nullptr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (const jsonrpcpp::RequestException& e)
|
catch (const jsonrpcpp::RequestException& e)
|
||||||
{
|
{
|
||||||
|
@ -189,7 +202,7 @@ void Server::onMessageReceived(std::shared_ptr<ControlSession> controlSession, c
|
||||||
{
|
{
|
||||||
jsonrpcpp::request_ptr request = dynamic_pointer_cast<jsonrpcpp::Request>(entity);
|
jsonrpcpp::request_ptr request = dynamic_pointer_cast<jsonrpcpp::Request>(entity);
|
||||||
processRequest(request, controlSession->authinfo,
|
processRequest(request, controlSession->authinfo,
|
||||||
[this, controlSession, response_handler](jsonrpcpp::entity_ptr response, jsonrpcpp::notification_ptr notification)
|
[this, controlSession, response_handler](const jsonrpcpp::entity_ptr& response, const jsonrpcpp::notification_ptr& notification)
|
||||||
{
|
{
|
||||||
// if (controlSession->authinfo.hasAuthInfo())
|
// if (controlSession->authinfo.hasAuthInfo())
|
||||||
// {
|
// {
|
||||||
|
@ -226,8 +239,8 @@ void Server::onMessageReceived(std::shared_ptr<ControlSession> controlSession, c
|
||||||
{
|
{
|
||||||
jsonrpcpp::request_ptr request = dynamic_pointer_cast<jsonrpcpp::Request>(batch_entity);
|
jsonrpcpp::request_ptr request = dynamic_pointer_cast<jsonrpcpp::Request>(batch_entity);
|
||||||
processRequest(request, controlSession->authinfo,
|
processRequest(request, controlSession->authinfo,
|
||||||
[controlSession, response_handler, &responseBatch, ¬ificationBatch](jsonrpcpp::entity_ptr response,
|
[controlSession, response_handler, &responseBatch, ¬ificationBatch](const jsonrpcpp::entity_ptr& response,
|
||||||
jsonrpcpp::notification_ptr notification)
|
const jsonrpcpp::notification_ptr& notification)
|
||||||
{
|
{
|
||||||
if (response != nullptr)
|
if (response != nullptr)
|
||||||
responseBatch.add_ptr(response);
|
responseBatch.add_ptr(response);
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
// standard headers
|
// standard headers
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
@ -67,27 +68,58 @@ struct ServerSettings
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// User settings
|
/// Authorization settings
|
||||||
struct User
|
struct Authorization
|
||||||
{
|
{
|
||||||
/// c'tor
|
/// Role settings
|
||||||
explicit User(const std::string& user_permissions_password)
|
struct Role
|
||||||
{
|
{
|
||||||
std::string perm;
|
/// c'tor
|
||||||
name = utils::string::split_left(user_permissions_password, ':', perm);
|
Role() = default;
|
||||||
perm = utils::string::split_left(perm, ':', password);
|
|
||||||
permissions = utils::string::split(perm, ',');
|
|
||||||
}
|
|
||||||
|
|
||||||
/// user name
|
/// c'tor
|
||||||
std::string name;
|
explicit Role(const std::string& role_permissions)
|
||||||
/// permissions
|
{
|
||||||
std::vector<std::string> permissions;
|
std::string perm;
|
||||||
/// password
|
role = utils::string::split_left(role_permissions, ':', perm);
|
||||||
std::string password;
|
permissions = utils::string::split(perm, ',');
|
||||||
|
}
|
||||||
|
|
||||||
|
/// role name
|
||||||
|
std::string role;
|
||||||
|
/// permissions
|
||||||
|
std::vector<std::string> permissions;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// User settings
|
||||||
|
struct User
|
||||||
|
{
|
||||||
|
/// c'tor
|
||||||
|
explicit User(const std::string& user_password_role)
|
||||||
|
{
|
||||||
|
std::string perm;
|
||||||
|
name = utils::string::split_left(user_password_role, ':', perm);
|
||||||
|
password = utils::string::split_left(perm, ':', role_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// user name
|
||||||
|
std::string name;
|
||||||
|
/// password
|
||||||
|
std::string password;
|
||||||
|
/// role
|
||||||
|
std::string role_name;
|
||||||
|
/// role
|
||||||
|
std::shared_ptr<Role> role;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// is auth enabled
|
||||||
|
bool enabled{false};
|
||||||
|
/// users
|
||||||
|
std::vector<User> users;
|
||||||
|
/// roles
|
||||||
|
std::vector<std::shared_ptr<Role>> roles;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/// HTTP settings
|
/// HTTP settings
|
||||||
struct Http
|
struct Http
|
||||||
{
|
{
|
||||||
|
@ -163,7 +195,7 @@ struct ServerSettings
|
||||||
|
|
||||||
Server server; ///< Server settings
|
Server server; ///< Server settings
|
||||||
Ssl ssl; ///< SSL settings
|
Ssl ssl; ///< SSL settings
|
||||||
std::vector<User> users; ///< User settings
|
Authorization auth; ///< Auth settings
|
||||||
Http http; ///< HTTP settings
|
Http http; ///< HTTP settings
|
||||||
Tcp tcp; ///< TCP settings
|
Tcp tcp; ///< TCP settings
|
||||||
Stream stream; ///< Stream settings
|
Stream stream; ///< Stream settings
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
|
|
||||||
// local headers
|
// local headers
|
||||||
#include "common/popl.hpp"
|
#include "common/popl.hpp"
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cstddef>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#ifdef HAS_DAEMON
|
#ifdef HAS_DAEMON
|
||||||
#include "common/daemon.hpp"
|
#include "common/daemon.hpp"
|
||||||
|
@ -90,10 +92,10 @@ int main(int argc, char* argv[])
|
||||||
auto client_cert_opt =
|
auto client_cert_opt =
|
||||||
conf.add<Value<std::filesystem::path>>("", "ssl.client_cert", "List of client CA certificate files, can be configured multiple times", "");
|
conf.add<Value<std::filesystem::path>>("", "ssl.client_cert", "List of client CA certificate files, can be configured multiple times", "");
|
||||||
|
|
||||||
#if 0 // feature: users
|
// Users setting
|
||||||
// Users setting
|
conf.add<Value<bool>>("", "authorization.enabled", "enabled authorization", settings.auth.enabled, &settings.auth.enabled);
|
||||||
auto users_value = conf.add<Value<string>>("", "users.user", "<User nane>:<permissions>:<password>");
|
auto roles_value = conf.add<Value<string>>("", "authorization.role", "<Role name>:<permissions>");
|
||||||
#endif
|
auto users_value = conf.add<Value<string>>("", "authorization.user", "<User nane>:<password>:<role>");
|
||||||
|
|
||||||
// HTTP RPC settings
|
// HTTP RPC settings
|
||||||
conf.add<Value<bool>>("", "http.enabled", "enable HTTP Json RPC (HTTP POST and websockets)", settings.http.enabled, &settings.http.enabled);
|
conf.add<Value<bool>>("", "http.enabled", "enable HTTP Json RPC (HTTP POST and websockets)", settings.http.enabled, &settings.http.enabled);
|
||||||
|
@ -320,15 +322,37 @@ int main(int argc, char* argv[])
|
||||||
settings.stream.sources.push_back(sourceValue->value(n));
|
settings.stream.sources.push_back(sourceValue->value(n));
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0 // feature: users
|
if (settings.auth.enabled)
|
||||||
for (size_t n = 0; n < users_value->count(); ++n)
|
|
||||||
{
|
{
|
||||||
settings.users.emplace_back(users_value->value(n));
|
for (size_t n = 0; n < roles_value->count(); ++n)
|
||||||
LOG(DEBUG, LOG_TAG) << "User: " << settings.users.back().name
|
{
|
||||||
<< ", permissions: " << utils::string::container_to_string(settings.users.back().permissions)
|
settings.auth.roles.emplace_back(std::make_shared<ServerSettings::Authorization::Role>(roles_value->value(n)));
|
||||||
<< ", pw: " << settings.users.back().password << "\n";
|
const auto& role = settings.auth.roles.back();
|
||||||
|
LOG(DEBUG, LOG_TAG) << "Role: " << role->role << ", permissions: " << utils::string::container_to_string(role->permissions) << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
auto empty_role = std::make_shared<ServerSettings::Authorization::Role>();
|
||||||
|
for (size_t n = 0; n < users_value->count(); ++n)
|
||||||
|
{
|
||||||
|
settings.auth.users.emplace_back(users_value->value(n));
|
||||||
|
ServerSettings::Authorization::User& user = settings.auth.users.back();
|
||||||
|
if (user.role_name.empty())
|
||||||
|
{
|
||||||
|
user.role = empty_role;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const auto& role_iter =
|
||||||
|
find_if(settings.auth.roles.begin(), settings.auth.roles.end(), [&](const auto& role) { return role->role == user.role_name; });
|
||||||
|
if (role_iter != settings.auth.roles.end())
|
||||||
|
user.role = *role_iter;
|
||||||
|
}
|
||||||
|
if (user.role == nullptr)
|
||||||
|
throw SnapException("Role '" + user.role_name + "' for user '" + user.name + "' not found");
|
||||||
|
|
||||||
|
LOG(DEBUG, LOG_TAG) << "User: " << user.name << ", pw: " << user.password << ", role: " << user.role_name << "\n";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef HAS_DAEMON
|
#ifdef HAS_DAEMON
|
||||||
std::unique_ptr<Daemon> daemon;
|
std::unique_ptr<Daemon> daemon;
|
||||||
|
|
|
@ -20,7 +20,7 @@ set(TEST_SOURCES
|
||||||
${CMAKE_SOURCE_DIR}/common/base64.cpp
|
${CMAKE_SOURCE_DIR}/common/base64.cpp
|
||||||
${CMAKE_SOURCE_DIR}/common/utils/string_utils.cpp
|
${CMAKE_SOURCE_DIR}/common/utils/string_utils.cpp
|
||||||
${CMAKE_SOURCE_DIR}/server/authinfo.cpp
|
${CMAKE_SOURCE_DIR}/server/authinfo.cpp
|
||||||
${CMAKE_SOURCE_DIR}/server/jwt.cpp
|
# ${CMAKE_SOURCE_DIR}/server/jwt.cpp
|
||||||
${CMAKE_SOURCE_DIR}/server/streamreader/control_error.cpp
|
${CMAKE_SOURCE_DIR}/server/streamreader/control_error.cpp
|
||||||
${CMAKE_SOURCE_DIR}/server/streamreader/properties.cpp
|
${CMAKE_SOURCE_DIR}/server/streamreader/properties.cpp
|
||||||
${CMAKE_SOURCE_DIR}/server/streamreader/metadata.cpp)
|
${CMAKE_SOURCE_DIR}/server/streamreader/metadata.cpp)
|
||||||
|
|
|
@ -19,14 +19,10 @@
|
||||||
// prototype/interface header file
|
// prototype/interface header file
|
||||||
|
|
||||||
// local headers
|
// local headers
|
||||||
#include "common/aixlog.hpp"
|
|
||||||
#include "common/base64.h"
|
|
||||||
#include "common/error_code.hpp"
|
#include "common/error_code.hpp"
|
||||||
#include "common/stream_uri.hpp"
|
#include "common/stream_uri.hpp"
|
||||||
#include "common/utils/string_utils.hpp"
|
#include "common/utils/string_utils.hpp"
|
||||||
#include "server/authinfo.hpp"
|
// #include "server/jwt.hpp"
|
||||||
#include "server/jwt.hpp"
|
|
||||||
#include "server/server_settings.hpp"
|
|
||||||
#include "server/streamreader/control_error.hpp"
|
#include "server/streamreader/control_error.hpp"
|
||||||
#include "server/streamreader/properties.hpp"
|
#include "server/streamreader/properties.hpp"
|
||||||
|
|
||||||
|
@ -34,7 +30,7 @@
|
||||||
#include <catch2/catch_test_macros.hpp>
|
#include <catch2/catch_test_macros.hpp>
|
||||||
|
|
||||||
// standard headers
|
// standard headers
|
||||||
#include <chrono>
|
#include <iostream>
|
||||||
#include <regex>
|
#include <regex>
|
||||||
#include <system_error>
|
#include <system_error>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
@ -91,9 +87,9 @@ TEST_CASE("String utils")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
TEST_CASE("JWT")
|
TEST_CASE("JWT")
|
||||||
{
|
{
|
||||||
#if 0
|
|
||||||
/// ECDSA
|
/// ECDSA
|
||||||
{
|
{
|
||||||
const auto* key = "-----BEGIN EC PRIVATE KEY-----\n"
|
const auto* key = "-----BEGIN EC PRIVATE KEY-----\n"
|
||||||
|
@ -137,7 +133,6 @@ TEST_CASE("JWT")
|
||||||
REQUIRE(jwt.getIat().value() == std::chrono::seconds(1516239022));
|
REQUIRE(jwt.getIat().value() == std::chrono::seconds(1516239022));
|
||||||
REQUIRE(!jwt.getExp().has_value());
|
REQUIRE(!jwt.getExp().has_value());
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/// RSA keys
|
/// RSA keys
|
||||||
{
|
{
|
||||||
|
@ -220,6 +215,7 @@ TEST_CASE("JWT")
|
||||||
REQUIRE(!jwt.getExp().has_value());
|
REQUIRE(!jwt.getExp().has_value());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
TEST_CASE("Uri")
|
TEST_CASE("Uri")
|
||||||
|
@ -688,7 +684,7 @@ TEST_CASE("WildcardMatch")
|
||||||
REQUIRE(!wildcardMatch("*get*erver*", "Server.getToken"));
|
REQUIRE(!wildcardMatch("*get*erver*", "Server.getToken"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
TEST_CASE("Auth")
|
TEST_CASE("Auth")
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
|
@ -735,3 +731,4 @@ TEST_CASE("Auth")
|
||||||
REQUIRE(!auth.hasPermission("stream"));
|
REQUIRE(!auth.hasPermission("stream"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue