Skip to content

Commit 654af60

Browse files
authored
allow to disable certain operations (#302)
1 parent a32d55f commit 654af60

51 files changed

Lines changed: 1256 additions & 646 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

ChangeLog.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
- Add ability to combine Play and Pause buttons
44
- Allow specifying explicit null for optional request parameters
55
- Limit client config id to 64 characters
6+
- Don't stop on first invalid config property
7+
- Allow to limit client operations (e.g. playlist modification)
68
- Fix various issues in API documentation
79
- Fix view height initialization on mobile browsers
810
### foobar2000

cpp/server/client_config_controller.cpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55

66
namespace msrv {
77

8-
ClientConfigController::ClientConfigController(Request* request, const char* appName)
9-
: ControllerBase(request), appName_(appName)
8+
ClientConfigController::ClientConfigController(Request* request, SettingsDataPtr settings, const char* appName)
9+
: ControllerBase(request), settings_(std::move(settings)), appName_(appName)
1010
{
1111
}
1212

@@ -24,6 +24,8 @@ ResponsePtr ClientConfigController::getConfig()
2424

2525
void ClientConfigController::setConfig()
2626
{
27+
checkPermissions();
28+
2729
auto path = getFilePath();
2830
fs::create_directories(path.parent_path());
2931
auto data = request()->postData.dump(2);
@@ -33,6 +35,8 @@ void ClientConfigController::setConfig()
3335

3436
void ClientConfigController::removeConfig()
3537
{
38+
checkPermissions();
39+
3640
auto path = getFilePath();
3741
boost::system::error_code ec;
3842
fs::remove(path, ec);
@@ -58,12 +62,15 @@ Path ClientConfigController::getFilePath()
5862
return configDir / MSRV_PATH_LITERAL("clientconfig") / pathFromUtf8(id + ".json");
5963
}
6064

61-
void ClientConfigController::defineRoutes(Router* router, WorkQueue* workQueue, const char* appName)
65+
void ClientConfigController::defineRoutes(
66+
Router* router, WorkQueue* workQueue, SettingsDataPtr settings, const char* appName)
6267
{
6368
auto routes = router->defineRoutes<ClientConfigController>();
64-
routes.createWith([=](Request* r) { return new ClientConfigController(r, appName); });
69+
70+
routes.createWith([=](Request* r) { return new ClientConfigController(r, settings, appName); });
6571
routes.useWorkQueue(workQueue);
6672
routes.setPrefix("api/clientconfig");
73+
6774
routes.get(":id", &ClientConfigController::getConfig);
6875
routes.post(":id", &ClientConfigController::setConfig);
6976
routes.post("remove/:id", &ClientConfigController::removeConfig);

cpp/server/client_config_controller.hpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,24 @@ class Router;
1111
class ClientConfigController : public ControllerBase
1212
{
1313
public:
14-
ClientConfigController(Request* request, const char* appName);
14+
ClientConfigController(Request* request, SettingsDataPtr settings, const char* appName);
1515
~ClientConfigController() = default;
1616

1717
ResponsePtr getConfig();
1818
void setConfig();
1919
void removeConfig();
2020

21-
static void defineRoutes(Router* router, WorkQueue* workQueue, const char* appName);
21+
static void defineRoutes(Router* router, WorkQueue* workQueue, SettingsDataPtr settings, const char* appName);
2222

2323
private:
2424
Path getFilePath();
2525

26+
void checkPermissions()
27+
{
28+
settings_->ensurePermissions(ApiPermissions::CHANGE_CLIENT_CONFIG);
29+
}
30+
31+
SettingsDataPtr settings_;
2632
const char* appName_;
2733
};
2834

cpp/server/core_types.hpp

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@ enum class Switch
2020

2121
struct Range
2222
{
23-
Range() = default;
23+
Range() : offset(0), count(0) { }
2424

25-
Range(int32_t offsetVal, int32_t countVal = 1)
25+
explicit Range(int32_t offsetVal, int32_t countVal = 1)
2626
: offset(offsetVal), count(countVal)
2727
{
2828
}
@@ -44,14 +44,30 @@ class InvalidRequestException : public std::runtime_error
4444
{
4545
}
4646

47-
InvalidRequestException(const std::string& str)
47+
explicit InvalidRequestException(const std::string& str)
4848
: std::runtime_error(str)
4949
{
5050
}
5151

5252
~InvalidRequestException() = default;
5353
};
5454

55+
class OperationForbiddenException : public std::runtime_error
56+
{
57+
public:
58+
OperationForbiddenException()
59+
: std::runtime_error("operation is not allowed by current configuration")
60+
{
61+
}
62+
63+
explicit OperationForbiddenException(const std::string& str)
64+
: std::runtime_error(str)
65+
{
66+
}
67+
68+
~OperationForbiddenException() = default;
69+
};
70+
5571
template<typename T>
5672
struct MallocDeleter
5773
{

cpp/server/deadbeef/plugin.cpp

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,15 @@
77
#define CONF_AUTH_USER MSRV_PROJECT_ID ".auth_user"
88
#define CONF_AUTH_PASSWORD MSRV_PROJECT_ID ".auth_password"
99

10+
#define CONF_PERM_CHANGE_PLAYLISTS MSRV_PROJECT_ID ".permissions.change_playlists"
11+
#define CONF_PERM_CHANGE_OUTPUT MSRV_PROJECT_ID ".permissions.change_output"
12+
#define CONF_PERM_CHANGE_CLIENT_CONFIG MSRV_PROJECT_ID ".permissions.change_client_config"
13+
1014
namespace msrv::player_deadbeef {
1115

1216
DB_misc_t PluginWrapper::definition_;
13-
1417
DeadbeefLogger* PluginWrapper::logger_;
15-
1618
Plugin* PluginWrapper::instance_;
17-
1819
char PluginWrapper::licenseText_[] = MSRV_LICENSE_TEXT;
1920

2021
const char PluginWrapper::configDialog_[] =
@@ -23,7 +24,10 @@ const char PluginWrapper::configDialog_[] =
2324
"property \"Music directories\" entry " CONF_MUSIC_DIRS " \"\";"
2425
"property \"Require authentication\" checkbox " CONF_AUTH_REQUIRED " 0;"
2526
"property \"User\" entry " CONF_AUTH_USER " \"\";"
26-
"property \"Password\" password " CONF_AUTH_PASSWORD " \"\";";
27+
"property \"Password\" password " CONF_AUTH_PASSWORD " \"\";"
28+
"property \"Allow changing playlists\" checkbox " CONF_PERM_CHANGE_PLAYLISTS " 1;"
29+
"property \"Allow changing output device\" checkbox " CONF_PERM_CHANGE_OUTPUT " 1;"
30+
"property \"Allow changing default web interface configuration\" checkbox " CONF_PERM_CHANGE_CLIENT_CONFIG " 1;";
2731

2832
Plugin::Plugin()
2933
: player_(),
@@ -56,6 +60,7 @@ void Plugin::reconfigure()
5660
settings->authRequired = authRequired_;
5761
settings->authUser = authUser_;
5862
settings->authPassword = authPassword_;
63+
settings->permissions = permissions_;
5964

6065
settings->loadAll(MSRV_PLAYER_DEADBEEF);
6166

@@ -73,13 +78,15 @@ bool Plugin::refreshSettings()
7378
auto authRequired = ddbApi->conf_get_int(CONF_AUTH_REQUIRED, 0) != 0;
7479
auto authUser = ddbApi->conf_get_str_fast(CONF_AUTH_USER, "");
7580
auto authPassword = ddbApi->conf_get_str_fast(CONF_AUTH_PASSWORD, "");
81+
auto permissions = getPermissionsFromConfig();
7682

7783
if (port_ == port &&
7884
allowRemote_ == allowRemote &&
7985
musicDirs_ == musicDirs &&
8086
authRequired_ == authRequired &&
8187
authUser_ == authUser &&
82-
authPassword_ == authPassword)
88+
authPassword_ == authPassword &&
89+
permissions_ == permissions)
8390
{
8491
return false;
8592
}
@@ -90,10 +97,27 @@ bool Plugin::refreshSettings()
9097
authRequired_ = authRequired;
9198
authUser_ = authUser;
9299
authPassword_ = authPassword;
100+
permissions_ = permissions;
93101

94102
return true;
95103
}
96104

105+
ApiPermissions Plugin::getPermissionsFromConfig()
106+
{
107+
auto result = ApiPermissions::NONE;
108+
109+
if (ddbApi->conf_get_int(CONF_PERM_CHANGE_PLAYLISTS, 1))
110+
result |= ApiPermissions::CHANGE_PLAYLISTS;
111+
112+
if (ddbApi->conf_get_int(CONF_PERM_CHANGE_OUTPUT, 1))
113+
result |= ApiPermissions::CHANGE_OUTPUT;
114+
115+
if (ddbApi->conf_get_int(CONF_PERM_CHANGE_CLIENT_CONFIG, 1))
116+
result |= ApiPermissions::CHANGE_CLIENT_CONFIG;
117+
118+
return result;
119+
}
120+
97121
void Plugin::handleMessage(uint32_t id, uintptr_t ctx, uint32_t p1, uint32_t p2)
98122
{
99123
switch (id)

cpp/server/deadbeef/plugin.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ class Plugin
3030
void handleMessage(uint32_t id, uintptr_t ctx, uint32_t p1, uint32_t p2);
3131

3232
private:
33+
static ApiPermissions getPermissionsFromConfig();
34+
3335
void handleConfigChanged();
3436
void handlePluginsLoaded();
3537
bool refreshSettings();
@@ -45,6 +47,7 @@ class Plugin
4547
bool authRequired_ = false;
4648
std::string authUser_;
4749
std::string authPassword_;
50+
ApiPermissions permissions_ = ApiPermissions::ALL;
4851

4952
MSRV_NO_COPY_AND_ASSIGN(Plugin);
5053
};

cpp/server/defines.hpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,12 @@
1414
#define MSRV_ENUM_FLAGS(Type, Base) \
1515
inline bool hasFlags(Type target, Type flags) \
1616
{ return (static_cast<Base>(target) & static_cast<Base>(flags)) == static_cast<Base>(flags); } \
17-
\
17+
inline Type setFlags(Type current, Type flags, bool set) \
18+
{ \
19+
return static_cast<Type>(set \
20+
? (static_cast<Base>(current) | static_cast<Base>(flags)) \
21+
: (static_cast<Base>(current) & ~static_cast<Base>(flags))); \
22+
} \
1823
inline Type operator|(Type first, Type second) \
1924
{ return static_cast<Type>(static_cast<Base>(first) | static_cast<Base>(second)); } \
2025
\

cpp/server/foobar2000/CMakeLists.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,18 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /d2notypeopt")
1111
set(
1212
FOOBAR2000_PLUGIN_SOURCES
1313
common.hpp
14+
main_prefs_page.cpp main_prefs_page.hpp
15+
permissions_prefs_page.cpp permissions_prefs_page.hpp
1416
player.hpp
1517
player_control.cpp
1618
player_misc.cpp
1719
player_options.cpp player_options.hpp
1820
player_playlists.cpp
1921
playlist_mapping.cpp playlist_mapping.hpp
2022
plugin.cpp plugin.hpp
23+
prefs_page.cpp prefs_page.hpp
2124
resource.h resource.rc
2225
settings.cpp settings.hpp
23-
settings_page.cpp settings_page.hpp
2426
utils.cpp utils.hpp
2527
)
2628

0 commit comments

Comments
 (0)