Permission: split permission "player" from "control"

Some users want certain clients to fully control playback, but do not
want them to be able to trigger database update.

Closes https://github.com/MusicPlayerDaemon/MPD/issues/1124
This commit is contained in:
Max Kellermann 2021-10-14 14:16:34 +02:00
parent 8ad17d25ef
commit 9a766f4cd9
5 changed files with 41 additions and 30 deletions

1
NEWS
View File

@ -24,6 +24,7 @@ ver 0.23 (not yet released)
- snapcast: new plugin - snapcast: new plugin
* tags * tags
- new tags "ComposerSort", "Ensemble", "Movement", "MovementNumber", and "Location" - new tags "ComposerSort", "Ensemble", "Movement", "MovementNumber", and "Location"
* split permission "player" from "control"
* new build-time dependency: libfmt * new build-time dependency: libfmt
ver 0.22.11 (2021/08/24) ver 0.22.11 (2021/08/24)

View File

@ -639,6 +639,9 @@ By default, all clients are unauthenticated and have a full set of permissions.
- Allows reading of the database, displaying the current playlist, and current status of :program:`MPD`. - Allows reading of the database, displaying the current playlist, and current status of :program:`MPD`.
* - **add** * - **add**
- Allows adding songs and loading playlists. - Allows adding songs and loading playlists.
* - **player**
- Allows any player and queue manipulation (start/pause/stop
playback etc.).
* - **control** * - **control**
- Allows all other player and playlist manipulations. - Allows all other player and playlist manipulations.
* - **admin** * - **admin**

View File

@ -41,6 +41,7 @@ static constexpr struct {
} permission_names[] = { } permission_names[] = {
{ "read", PERMISSION_READ }, { "read", PERMISSION_READ },
{ "add", PERMISSION_ADD }, { "add", PERMISSION_ADD },
{ "player", PERMISSION_PLAYER },
{ "control", PERMISSION_CONTROL }, { "control", PERMISSION_CONTROL },
{ "admin", PERMISSION_ADMIN }, { "admin", PERMISSION_ADMIN },
{ nullptr, 0 }, { nullptr, 0 },
@ -75,6 +76,11 @@ static unsigned parsePermissions(const char *string)
if (!i.empty()) if (!i.empty())
permission |= ParsePermission(i); permission |= ParsePermission(i);
/* for backwards compatiblity with MPD 0.22 and older,
"control" implies "play" */
if (permission & PERMISSION_CONTROL)
permission |= PERMISSION_PLAYER;
return permission; return permission;
} }

View File

@ -29,6 +29,7 @@ static constexpr unsigned PERMISSION_READ = 1;
static constexpr unsigned PERMISSION_ADD = 2; static constexpr unsigned PERMISSION_ADD = 2;
static constexpr unsigned PERMISSION_CONTROL = 4; static constexpr unsigned PERMISSION_CONTROL = 4;
static constexpr unsigned PERMISSION_ADMIN = 8; static constexpr unsigned PERMISSION_ADMIN = 8;
static constexpr unsigned PERMISSION_PLAYER = 16;
int int
getPermissionFromPassword(const char *password, unsigned *permission) noexcept; getPermissionFromPassword(const char *password, unsigned *permission) noexcept;

View File

@ -91,21 +91,21 @@ static constexpr struct command commands[] = {
{ "albumart", PERMISSION_READ, 2, 2, handle_album_art }, { "albumart", PERMISSION_READ, 2, 2, handle_album_art },
{ "binarylimit", PERMISSION_NONE, 1, 1, handle_binary_limit }, { "binarylimit", PERMISSION_NONE, 1, 1, handle_binary_limit },
{ "channels", PERMISSION_READ, 0, 0, handle_channels }, { "channels", PERMISSION_READ, 0, 0, handle_channels },
{ "clear", PERMISSION_CONTROL, 0, 0, handle_clear }, { "clear", PERMISSION_PLAYER, 0, 0, handle_clear },
{ "clearerror", PERMISSION_CONTROL, 0, 0, handle_clearerror }, { "clearerror", PERMISSION_PLAYER, 0, 0, handle_clearerror },
{ "cleartagid", PERMISSION_ADD, 1, 2, handle_cleartagid }, { "cleartagid", PERMISSION_ADD, 1, 2, handle_cleartagid },
{ "close", PERMISSION_NONE, -1, -1, handle_close }, { "close", PERMISSION_NONE, -1, -1, handle_close },
{ "commands", PERMISSION_NONE, 0, 0, handle_commands }, { "commands", PERMISSION_NONE, 0, 0, handle_commands },
{ "config", PERMISSION_ADMIN, 0, 0, handle_config }, { "config", PERMISSION_ADMIN, 0, 0, handle_config },
{ "consume", PERMISSION_CONTROL, 1, 1, handle_consume }, { "consume", PERMISSION_PLAYER, 1, 1, handle_consume },
#ifdef ENABLE_DATABASE #ifdef ENABLE_DATABASE
{ "count", PERMISSION_READ, 1, -1, handle_count }, { "count", PERMISSION_READ, 1, -1, handle_count },
#endif #endif
{ "crossfade", PERMISSION_CONTROL, 1, 1, handle_crossfade }, { "crossfade", PERMISSION_PLAYER, 1, 1, handle_crossfade },
{ "currentsong", PERMISSION_READ, 0, 0, handle_currentsong }, { "currentsong", PERMISSION_READ, 0, 0, handle_currentsong },
{ "decoders", PERMISSION_READ, 0, 0, handle_decoders }, { "decoders", PERMISSION_READ, 0, 0, handle_decoders },
{ "delete", PERMISSION_CONTROL, 1, 1, handle_delete }, { "delete", PERMISSION_PLAYER, 1, 1, handle_delete },
{ "deleteid", PERMISSION_CONTROL, 1, 1, handle_deleteid }, { "deleteid", PERMISSION_PLAYER, 1, 1, handle_deleteid },
{ "delpartition", PERMISSION_ADMIN, 1, 1, handle_delpartition }, { "delpartition", PERMISSION_ADMIN, 1, 1, handle_delpartition },
{ "disableoutput", PERMISSION_ADMIN, 1, 1, handle_disableoutput }, { "disableoutput", PERMISSION_ADMIN, 1, 1, handle_disableoutput },
{ "enableoutput", PERMISSION_ADMIN, 1, 1, handle_enableoutput }, { "enableoutput", PERMISSION_ADMIN, 1, 1, handle_enableoutput },
@ -137,25 +137,25 @@ static constexpr struct command commands[] = {
{ "listplaylists", PERMISSION_READ, 0, 0, handle_listplaylists }, { "listplaylists", PERMISSION_READ, 0, 0, handle_listplaylists },
{ "load", PERMISSION_ADD, 1, 2, handle_load }, { "load", PERMISSION_ADD, 1, 2, handle_load },
{ "lsinfo", PERMISSION_READ, 0, 1, handle_lsinfo }, { "lsinfo", PERMISSION_READ, 0, 1, handle_lsinfo },
{ "mixrampdb", PERMISSION_CONTROL, 1, 1, handle_mixrampdb }, { "mixrampdb", PERMISSION_PLAYER, 1, 1, handle_mixrampdb },
{ "mixrampdelay", PERMISSION_CONTROL, 1, 1, handle_mixrampdelay }, { "mixrampdelay", PERMISSION_PLAYER, 1, 1, handle_mixrampdelay },
#ifdef ENABLE_DATABASE #ifdef ENABLE_DATABASE
{ "mount", PERMISSION_ADMIN, 2, 2, handle_mount }, { "mount", PERMISSION_ADMIN, 2, 2, handle_mount },
#endif #endif
{ "move", PERMISSION_CONTROL, 2, 2, handle_move }, { "move", PERMISSION_PLAYER, 2, 2, handle_move },
{ "moveid", PERMISSION_CONTROL, 2, 2, handle_moveid }, { "moveid", PERMISSION_PLAYER, 2, 2, handle_moveid },
{ "moveoutput", PERMISSION_ADMIN, 1, 1, handle_moveoutput }, { "moveoutput", PERMISSION_ADMIN, 1, 1, handle_moveoutput },
{ "newpartition", PERMISSION_ADMIN, 1, 1, handle_newpartition }, { "newpartition", PERMISSION_ADMIN, 1, 1, handle_newpartition },
{ "next", PERMISSION_CONTROL, 0, 0, handle_next }, { "next", PERMISSION_PLAYER, 0, 0, handle_next },
{ "notcommands", PERMISSION_NONE, 0, 0, handle_not_commands }, { "notcommands", PERMISSION_NONE, 0, 0, handle_not_commands },
{ "outputs", PERMISSION_READ, 0, 0, handle_devices }, { "outputs", PERMISSION_READ, 0, 0, handle_devices },
{ "outputset", PERMISSION_ADMIN, 3, 3, handle_outputset }, { "outputset", PERMISSION_ADMIN, 3, 3, handle_outputset },
{ "partition", PERMISSION_READ, 1, 1, handle_partition }, { "partition", PERMISSION_READ, 1, 1, handle_partition },
{ "password", PERMISSION_NONE, 1, 1, handle_password }, { "password", PERMISSION_NONE, 1, 1, handle_password },
{ "pause", PERMISSION_CONTROL, 0, 1, handle_pause }, { "pause", PERMISSION_PLAYER, 0, 1, handle_pause },
{ "ping", PERMISSION_NONE, 0, 0, handle_ping }, { "ping", PERMISSION_NONE, 0, 0, handle_ping },
{ "play", PERMISSION_CONTROL, 0, 1, handle_play }, { "play", PERMISSION_PLAYER, 0, 1, handle_play },
{ "playid", PERMISSION_CONTROL, 0, 1, handle_playid }, { "playid", PERMISSION_PLAYER, 0, 1, handle_playid },
{ "playlist", PERMISSION_READ, 0, 0, handle_playlist }, { "playlist", PERMISSION_READ, 0, 0, handle_playlist },
{ "playlistadd", PERMISSION_CONTROL, 2, 2, handle_playlistadd }, { "playlistadd", PERMISSION_CONTROL, 2, 2, handle_playlistadd },
{ "playlistclear", PERMISSION_CONTROL, 1, 1, handle_playlistclear }, { "playlistclear", PERMISSION_CONTROL, 1, 1, handle_playlistclear },
@ -167,17 +167,17 @@ static constexpr struct command commands[] = {
{ "playlistsearch", PERMISSION_READ, 1, -1, handle_playlistsearch }, { "playlistsearch", PERMISSION_READ, 1, -1, handle_playlistsearch },
{ "plchanges", PERMISSION_READ, 1, 2, handle_plchanges }, { "plchanges", PERMISSION_READ, 1, 2, handle_plchanges },
{ "plchangesposid", PERMISSION_READ, 1, 2, handle_plchangesposid }, { "plchangesposid", PERMISSION_READ, 1, 2, handle_plchangesposid },
{ "previous", PERMISSION_CONTROL, 0, 0, handle_previous }, { "previous", PERMISSION_PLAYER, 0, 0, handle_previous },
{ "prio", PERMISSION_CONTROL, 2, -1, handle_prio }, { "prio", PERMISSION_PLAYER, 2, -1, handle_prio },
{ "prioid", PERMISSION_CONTROL, 2, -1, handle_prioid }, { "prioid", PERMISSION_PLAYER, 2, -1, handle_prioid },
{ "random", PERMISSION_CONTROL, 1, 1, handle_random }, { "random", PERMISSION_PLAYER, 1, 1, handle_random },
{ "rangeid", PERMISSION_ADD, 2, 2, handle_rangeid }, { "rangeid", PERMISSION_ADD, 2, 2, handle_rangeid },
{ "readcomments", PERMISSION_READ, 1, 1, handle_read_comments }, { "readcomments", PERMISSION_READ, 1, 1, handle_read_comments },
{ "readmessages", PERMISSION_READ, 0, 0, handle_read_messages }, { "readmessages", PERMISSION_READ, 0, 0, handle_read_messages },
{ "readpicture", PERMISSION_READ, 2, 2, handle_read_picture }, { "readpicture", PERMISSION_READ, 2, 2, handle_read_picture },
{ "rename", PERMISSION_CONTROL, 2, 2, handle_rename }, { "rename", PERMISSION_CONTROL, 2, 2, handle_rename },
{ "repeat", PERMISSION_CONTROL, 1, 1, handle_repeat }, { "repeat", PERMISSION_PLAYER, 1, 1, handle_repeat },
{ "replay_gain_mode", PERMISSION_CONTROL, 1, 1, { "replay_gain_mode", PERMISSION_PLAYER, 1, 1,
handle_replay_gain_mode }, handle_replay_gain_mode },
{ "replay_gain_status", PERMISSION_READ, 0, 0, { "replay_gain_status", PERMISSION_READ, 0, 0,
handle_replay_gain_status }, handle_replay_gain_status },
@ -189,22 +189,22 @@ static constexpr struct command commands[] = {
{ "searchadd", PERMISSION_ADD, 1, -1, handle_searchadd }, { "searchadd", PERMISSION_ADD, 1, -1, handle_searchadd },
{ "searchaddpl", PERMISSION_CONTROL, 2, -1, handle_searchaddpl }, { "searchaddpl", PERMISSION_CONTROL, 2, -1, handle_searchaddpl },
#endif #endif
{ "seek", PERMISSION_CONTROL, 2, 2, handle_seek }, { "seek", PERMISSION_PLAYER, 2, 2, handle_seek },
{ "seekcur", PERMISSION_CONTROL, 1, 1, handle_seekcur }, { "seekcur", PERMISSION_PLAYER, 1, 1, handle_seekcur },
{ "seekid", PERMISSION_CONTROL, 2, 2, handle_seekid }, { "seekid", PERMISSION_PLAYER, 2, 2, handle_seekid },
{ "sendmessage", PERMISSION_CONTROL, 2, 2, handle_send_message }, { "sendmessage", PERMISSION_CONTROL, 2, 2, handle_send_message },
{ "setvol", PERMISSION_CONTROL, 1, 1, handle_setvol }, { "setvol", PERMISSION_PLAYER, 1, 1, handle_setvol },
{ "shuffle", PERMISSION_CONTROL, 0, 1, handle_shuffle }, { "shuffle", PERMISSION_PLAYER, 0, 1, handle_shuffle },
{ "single", PERMISSION_CONTROL, 1, 1, handle_single }, { "single", PERMISSION_PLAYER, 1, 1, handle_single },
{ "stats", PERMISSION_READ, 0, 0, handle_stats }, { "stats", PERMISSION_READ, 0, 0, handle_stats },
{ "status", PERMISSION_READ, 0, 0, handle_status }, { "status", PERMISSION_READ, 0, 0, handle_status },
#ifdef ENABLE_SQLITE #ifdef ENABLE_SQLITE
{ "sticker", PERMISSION_ADMIN, 3, -1, handle_sticker }, { "sticker", PERMISSION_ADMIN, 3, -1, handle_sticker },
#endif #endif
{ "stop", PERMISSION_CONTROL, 0, 0, handle_stop }, { "stop", PERMISSION_PLAYER, 0, 0, handle_stop },
{ "subscribe", PERMISSION_READ, 1, 1, handle_subscribe }, { "subscribe", PERMISSION_READ, 1, 1, handle_subscribe },
{ "swap", PERMISSION_CONTROL, 2, 2, handle_swap }, { "swap", PERMISSION_PLAYER, 2, 2, handle_swap },
{ "swapid", PERMISSION_CONTROL, 2, 2, handle_swapid }, { "swapid", PERMISSION_PLAYER, 2, 2, handle_swapid },
{ "tagtypes", PERMISSION_NONE, 0, -1, handle_tagtypes }, { "tagtypes", PERMISSION_NONE, 0, -1, handle_tagtypes },
{ "toggleoutput", PERMISSION_ADMIN, 1, 1, handle_toggleoutput }, { "toggleoutput", PERMISSION_ADMIN, 1, 1, handle_toggleoutput },
#ifdef ENABLE_DATABASE #ifdef ENABLE_DATABASE
@ -213,7 +213,7 @@ static constexpr struct command commands[] = {
{ "unsubscribe", PERMISSION_READ, 1, 1, handle_unsubscribe }, { "unsubscribe", PERMISSION_READ, 1, 1, handle_unsubscribe },
{ "update", PERMISSION_CONTROL, 0, 1, handle_update }, { "update", PERMISSION_CONTROL, 0, 1, handle_update },
{ "urlhandlers", PERMISSION_READ, 0, 0, handle_urlhandlers }, { "urlhandlers", PERMISSION_READ, 0, 0, handle_urlhandlers },
{ "volume", PERMISSION_CONTROL, 1, 1, handle_volume }, { "volume", PERMISSION_PLAYER, 1, 1, handle_volume },
}; };
static constexpr unsigned num_commands = std::size(commands); static constexpr unsigned num_commands = std::size(commands);