Added an option ui-allow-downloads in lms.conf to enable/disable downloads, fixes #776

This commit is contained in:
emeric
2025-12-03 22:02:16 +01:00
parent 7feecb2027
commit 2d90281b11
13 changed files with 88 additions and 37 deletions
+2
View File
@@ -24,7 +24,9 @@
${<if-has-mbid>} ${<if-has-mbid>}
<li><a href="${mbid-link}" target="_blank" class="dropdown-item">${tr:Lms.Explore.musicbrainz-artist}</a></li> <li><a href="${mbid-link}" target="_blank" class="dropdown-item">${tr:Lms.Explore.musicbrainz-artist}</a></li>
${</if-has-mbid>} ${</if-has-mbid>}
${<if-has-download>}
<li>${download class="dropdown-item"}</li> <li>${download class="dropdown-item"}</li>
${</if-has-download>}
</ul> </ul>
</div> </div>
</div> </div>
+2
View File
@@ -65,7 +65,9 @@
<ul class="dropdown-menu" aria-labelledby="${id:more-btn}"> <ul class="dropdown-menu" aria-labelledby="${id:more-btn}">
<li>${play class="dropdown-item"}</li> <li>${play class="dropdown-item"}</li>
<li>${star class="dropdown-item"}</li> <li>${star class="dropdown-item"}</li>
${<if-has-download>}
<li>${download class="dropdown-item"}</li> <li>${download class="dropdown-item"}</li>
${</if-has-download>}
</ul> </ul>
</div> </div>
</div> </div>
+4
View File
@@ -27,7 +27,9 @@
${<if-has-mbid>} ${<if-has-mbid>}
<li><a href="${mbid-link}" target="_blank" class="dropdown-item">${tr:Lms.Explore.musicbrainz-release}</a></li> <li><a href="${mbid-link}" target="_blank" class="dropdown-item">${tr:Lms.Explore.musicbrainz-release}</a></li>
${</if-has-mbid>} ${</if-has-mbid>}
${<if-has-download>}
<li>${download class="dropdown-item"}</li> <li>${download class="dropdown-item"}</li>
${</if-has-download>}
<li>${release-info class="dropdown-item"}</li> <li>${release-info class="dropdown-item"}</li>
</ul> </ul>
</div> </div>
@@ -109,7 +111,9 @@
<li>${play-next class="dropdown-item"}</li> <li>${play-next class="dropdown-item"}</li>
<li>${play-last class="dropdown-item"}</li> <li>${play-last class="dropdown-item"}</li>
<li>${star class="dropdown-item"}</li> <li>${star class="dropdown-item"}</li>
${<if-has-download>}
<li>${download class="dropdown-item"}</li> <li>${download class="dropdown-item"}</li>
${</if-has-download>}
<li>${track-info class="dropdown-item"}</li> <li>${track-info class="dropdown-item"}</li>
${<if-has-lyrics>}<li>${track-lyrics class="dropdown-item"}</li>${</if-has-lyrics>} ${<if-has-lyrics>}<li>${track-lyrics class="dropdown-item"}</li>${</if-has-lyrics>}
</ul> </ul>
+2
View File
@@ -13,7 +13,9 @@
<ul class="dropdown-menu"> <ul class="dropdown-menu">
<li>${play-shuffled class="dropdown-item"}</li> <li>${play-shuffled class="dropdown-item"}</li>
<li>${play-last class="dropdown-item"}</li> <li>${play-last class="dropdown-item"}</li>
${<if-has-download>}
<li>${download class="dropdown-item"}</li> <li>${download class="dropdown-item"}</li>
${</if-has-download>}
${<if-has-delete>} ${<if-has-delete>}
<li>${delete class="dropdown-item"}</li> <li>${delete class="dropdown-item"}</li>
${</if-has-delete>} ${</if-has-delete>}
+2
View File
@@ -59,7 +59,9 @@
<li>${play-next class="dropdown-item"}</li> <li>${play-next class="dropdown-item"}</li>
<li>${play-last class="dropdown-item"}</li> <li>${play-last class="dropdown-item"}</li>
<li>${star class="dropdown-item"}</li> <li>${star class="dropdown-item"}</li>
${<if-has-download>}
<li>${download class="dropdown-item"}</li> <li>${download class="dropdown-item"}</li>
${</if-has-download>}
<li>${track-info class="dropdown-item"}</li> <li>${track-info class="dropdown-item"}</li>
${<if-has-lyrics>}<li>${track-lyrics class="dropdown-item"}</li>${</if-has-lyrics>} ${<if-has-lyrics>}<li>${track-lyrics class="dropdown-item"}</li>${</if-has-lyrics>}
</ul> </ul>
+6 -3
View File
@@ -113,9 +113,6 @@ artist-image-file-names = ("artist");
# Note: files named after the disc itself are always searched before the names in this list. # Note: files named after the disc itself are always searched before the names in this list.
medium-image-file-names = ("discsubtitle"); medium-image-file-names = ("discsubtitle");
# Playqueue max entry count
playqueue-max-entry-count = 1000;
# Internal tracing for profiling purposes. Enable only if necessary, as it incurs some runtime overhead! # Internal tracing for profiling purposes. Enable only if necessary, as it incurs some runtime overhead!
# Possible values are "disabled", "overview" or "detailed". # Possible values are "disabled", "overview" or "detailed".
# If enabled, data has to be dumped in the tracing view located in the admin menu # If enabled, data has to be dumped in the tracing view located in the admin menu
@@ -140,3 +137,9 @@ podcast-auto-download-episodes = true;
# Max age in days for auto-downloaded episodes before deletion # Max age in days for auto-downloaded episodes before deletion
podcast-auto-download-episodes-max-age-days = 30; podcast-auto-download-episodes-max-age-days = 30;
# Playqueue max entry count
ui-playqueue-max-entry-count = 1000;
# Allow downloads
ui-allow-downloads = true;
+29 -21
View File
@@ -26,9 +26,11 @@
#include <Wt/WServer.h> #include <Wt/WServer.h>
#include <Wt/WStackedWidget.h> #include <Wt/WStackedWidget.h>
#include "core/IConfig.hpp"
#include "core/ILogger.hpp" #include "core/ILogger.hpp"
#include "core/ITraceLogger.hpp" #include "core/ITraceLogger.hpp"
#include "core/Service.hpp" #include "core/Service.hpp"
#include "database/IDb.hpp" #include "database/IDb.hpp"
#include "database/IQueryPlanRecorder.hpp" #include "database/IQueryPlanRecorder.hpp"
#include "database/Session.hpp" #include "database/Session.hpp"
@@ -198,6 +200,31 @@ namespace lms::ui
return static_cast<LmsApplication*>(Wt::WApplication::instance()); return static_cast<LmsApplication*>(Wt::WApplication::instance());
} }
LmsApplication::LmsApplication(const Wt::WEnvironment& env, db::IDb& db, LmsApplicationManager& appManager, AuthenticationBackend authBackend)
: Wt::WApplication{ env }
, _db{ db }
, _appManager{ appManager }
, _authBackend{ authBackend }
, _areDownloadsEnabled(core::Service<core::IConfig>::get()->getBool("ui-allow-downloads", true))
{
try
{
init();
}
catch (LmsApplicationException& e)
{
LMS_LOG(UI, WARNING, "Caught a LmsApplication exception: " << e.what());
handleException(e);
}
catch (std::exception& e)
{
LMS_LOG(UI, ERROR, "Caught exception: " << e.what());
throw core::LmsException{ "Internal error" }; // Do not put details here at it may appear on the user rendered html
}
}
LmsApplication::~LmsApplication() = default;
db::IDb& LmsApplication::getDb() db::IDb& LmsApplication::getDb()
{ {
return _db; return _db;
@@ -240,30 +267,11 @@ namespace lms::ui
return _user->userLoginName; return _user->userLoginName;
} }
LmsApplication::LmsApplication(const Wt::WEnvironment& env, db::IDb& db, LmsApplicationManager& appManager, AuthenticationBackend authBackend) bool LmsApplication::areDownloadsEnabled() const
: Wt::WApplication{ env }
, _db{ db }
, _appManager{ appManager }
, _authBackend{ authBackend }
{ {
try return _areDownloadsEnabled;
{
init();
}
catch (LmsApplicationException& e)
{
LMS_LOG(UI, WARNING, "Caught a LmsApplication exception: " << e.what());
handleException(e);
}
catch (std::exception& e)
{
LMS_LOG(UI, ERROR, "Caught exception: " << e.what());
throw core::LmsException{ "Internal error" }; // Do not put details here at it may appear on the user rendered html
}
} }
LmsApplication::~LmsApplication() = default;
void LmsApplication::init() void LmsApplication::init()
{ {
LMS_SCOPED_TRACE_OVERVIEW("UI", "ApplicationInit"); LMS_SCOPED_TRACE_OVERVIEW("UI", "ApplicationInit");
+3
View File
@@ -70,6 +70,8 @@ namespace lms::ui
db::UserType getUserType() const; // user must be logged in prior this call db::UserType getUserType() const; // user must be logged in prior this call
std::string_view getUserLoginName() const; // user must be logged in prior this call std::string_view getUserLoginName() const; // user must be logged in prior this call
bool areDownloadsEnabled() const;
// Proxified scanner events // Proxified scanner events
scanner::Events& getScannerEvents() { return _scannerEvents; } scanner::Events& getScannerEvents() { return _scannerEvents; }
@@ -109,6 +111,7 @@ namespace lms::ui
Wt::Signal<> _preQuit; Wt::Signal<> _preQuit;
LmsApplicationManager& _appManager; LmsApplicationManager& _appManager;
const AuthenticationBackend _authBackend; const AuthenticationBackend _authBackend;
const bool _areDownloadsEnabled;
scanner::Events _scannerEvents; scanner::Events _scannerEvents;
struct UserAuthInfo struct UserAuthInfo
{ {
+7 -3
View File
@@ -114,7 +114,7 @@ namespace lms::ui
PlayQueue::PlayQueue() PlayQueue::PlayQueue()
: Template{ Wt::WString::tr("Lms.PlayQueue.template") } : Template{ Wt::WString::tr("Lms.PlayQueue.template") }
, _capacity{ core::Service<core::IConfig>::get()->getULong("playqueue-max-entry-count", 1000) } , _capacity{ core::Service<core::IConfig>::get()->getULong("ui-playqueue-max-entry-count", 1000) }
{ {
initTrackLists(); initTrackLists();
@@ -578,8 +578,12 @@ namespace lms::ui
} }
}); });
entry->bindNew<Wt::WPushButton>("download", Wt::WString::tr("Lms.Explore.download")) if (LmsApp->areDownloadsEnabled())
->setLink(Wt::WLink{ std::make_unique<DownloadTrackResource>(trackId) }); {
entry->setCondition("if-has-download", true);
entry->bindNew<Wt::WPushButton>("download", Wt::WString::tr("Lms.Explore.download"))
->setLink(Wt::WLink{ std::make_unique<DownloadTrackResource>(trackId) });
}
} }
void PlayQueue::enqueueRadioTracksIfNeeded() void PlayQueue::enqueueRadioTracksIfNeeded()
+7 -2
View File
@@ -168,8 +168,13 @@ namespace lms::ui
.connect([this] { .connect([this] {
_playQueueController.processCommand(PlayQueueController::Command::PlayOrAddLast, { _artistId }); _playQueueController.processCommand(PlayQueueController::Command::PlayOrAddLast, { _artistId });
}); });
bindNew<Wt::WPushButton>("download", Wt::WString::tr("Lms.Explore.download"))
->setLink(Wt::WLink{ std::make_unique<DownloadArtistResource>(_artistId) }); if (LmsApp->areDownloadsEnabled())
{
setCondition("if-has-download", true);
bindNew<Wt::WPushButton>("download", Wt::WString::tr("Lms.Explore.download"))
->setLink(Wt::WLink{ std::make_unique<DownloadArtistResource>(_artistId) });
}
{ {
auto isStarred{ [this] { return core::Service<feedback::IFeedbackService>::get()->isStarred(LmsApp->getUserId(), _artistId); } }; auto isStarred{ [this] { return core::Service<feedback::IFeedbackService>::get()->isStarred(LmsApp->getUserId(), _artistId); } };
+12 -4
View File
@@ -359,8 +359,12 @@ namespace lms::ui
_playQueueController.processCommand(PlayQueueController::Command::PlayOrAddLast, { _releaseId }); _playQueueController.processCommand(PlayQueueController::Command::PlayOrAddLast, { _releaseId });
}); });
bindNew<Wt::WPushButton>("download", Wt::WString::tr("Lms.Explore.download")) if (LmsApp->areDownloadsEnabled())
->setLink(Wt::WLink{ std::make_unique<DownloadReleaseResource>(_releaseId) }); {
setCondition("if-has-download", true);
bindNew<Wt::WPushButton>("download", Wt::WString::tr("Lms.Explore.download"))
->setLink(Wt::WLink{ std::make_unique<DownloadReleaseResource>(_releaseId) });
}
bindNew<Wt::WPushButton>("release-info", Wt::WString::tr("Lms.Explore.release-info")) bindNew<Wt::WPushButton>("release-info", Wt::WString::tr("Lms.Explore.release-info"))
->clicked() ->clicked()
@@ -527,8 +531,12 @@ namespace lms::ui
starBtn->clicked().connect([=] { toggle(); }); starBtn->clicked().connect([=] { toggle(); });
} }
entry->bindNew<Wt::WPushButton>("download", Wt::WString::tr("Lms.Explore.download")) if (LmsApp->areDownloadsEnabled())
->setLink(Wt::WLink{ std::make_unique<DownloadTrackResource>(trackId) }); {
entry->setCondition("if-has-download", true);
entry->bindNew<Wt::WPushButton>("download", Wt::WString::tr("Lms.Explore.download"))
->setLink(Wt::WLink{ std::make_unique<DownloadTrackResource>(trackId) });
}
entry->bindNew<Wt::WPushButton>("track-info", Wt::WString::tr("Lms.Explore.track-info")) entry->bindNew<Wt::WPushButton>("track-info", Wt::WString::tr("Lms.Explore.track-info"))
->clicked() ->clicked()
+6 -2
View File
@@ -299,8 +299,12 @@ namespace lms::ui::TrackListHelpers
starBtn->clicked().connect([=] { toggle(); }); starBtn->clicked().connect([=] { toggle(); });
} }
entry->bindNew<Wt::WPushButton>("download", Wt::WString::tr("Lms.Explore.download")) if (LmsApp->areDownloadsEnabled())
->setLink(Wt::WLink{ std::make_unique<DownloadTrackResource>(trackId) }); {
entry->setCondition("if-has-download", true);
entry->bindNew<Wt::WPushButton>("download", Wt::WString::tr("Lms.Explore.download"))
->setLink(Wt::WLink{ std::make_unique<DownloadTrackResource>(trackId) });
}
entry->bindNew<Wt::WPushButton>("track-info", Wt::WString::tr("Lms.Explore.track-info")) entry->bindNew<Wt::WPushButton>("track-info", Wt::WString::tr("Lms.Explore.track-info"))
->clicked() ->clicked()
+6 -2
View File
@@ -135,8 +135,12 @@ namespace lms::ui
_playQueueController.processCommand(PlayQueueController::Command::PlayOrAddLast, *trackListId); _playQueueController.processCommand(PlayQueueController::Command::PlayOrAddLast, *trackListId);
}); });
bindNew<Wt::WPushButton>("download", Wt::WString::tr("Lms.Explore.download")) if (LmsApp->areDownloadsEnabled())
->setLink(Wt::WLink{ std::make_unique<DownloadTrackListResource>(*trackListId) }); {
setCondition("if-has-download", true);
bindNew<Wt::WPushButton>("download", Wt::WString::tr("Lms.Explore.download"))
->setLink(Wt::WLink{ std::make_unique<DownloadTrackListResource>(*trackListId) });
}
if (trackList->getUserId() == LmsApp->getUserId()) if (trackList->getUserId() == LmsApp->getUserId())
{ {