diff --git a/INSTALL.md b/INSTALL.md
index 5d923e06..7ff70afc 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -132,8 +132,8 @@ If a setting is not present in the configuration file, a hardcoded default value
You can define which authentication backend to be used thanks to the `authentication-backend` option:
* `internal` (default): _LMS_ uses an internal database to store users and their associated passwords (salted and hashed using [Bcrypt](https://en.wikipedia.org/wiki/Bcrypt)). Only the admin user can create, edit or remove other users.
-* `PAM`: the authentication request is forwarded to PAM (see the [default configuration file](conf/pam/lms)).
-* `http-headers`: _LMS_ uses a configurable HTTP header field, typically set by a reverse proxy to handle [SSO](https://en.wikipedia.org/wiki/Single_sign-on), to extract the login name. You can customize the field to be used using the `http-headers-user-field` option.
+* `PAM`: the user/password authentication request is forwarded to PAM (see the [default configuration file](conf/pam/lms)).
+* `http-headers`: _LMS_ uses a configurable HTTP header field, typically set by a reverse proxy to handle [SSO](https://en.wikipedia.org/wiki/Single_sign-on), to extract the login name. You can customize the field to be used using the `http-headers-login-field` option.
__Note__: the first created user is the admin user
diff --git a/approot/messages.xml b/approot/messages.xml
index 28dff4ae..ee2a721c 100644
--- a/approot/messages.xml
+++ b/approot/messages.xml
@@ -28,7 +28,6 @@
Artist not found
Error occured!
-Deployment error
Go home
Release not found
You are not allowed to perform this operation
diff --git a/approot/messages_fr.xml b/approot/messages_fr.xml
index 641029b3..4e4c9af7 100644
--- a/approot/messages_fr.xml
+++ b/approot/messages_fr.xml
@@ -28,7 +28,6 @@
Cet artiste n'existe pas
Une erreur est survenue!
-Erreur de déploiement
Retour à l'accueil
Cet album n'existe pas
Vous n'avez pas les droits pour effectuer cette opération
diff --git a/conf/lms.conf b/conf/lms.conf
index fc38a121..e4c00109 100644
--- a/conf/lms.conf
+++ b/conf/lms.conf
@@ -40,7 +40,7 @@ acousticbrainz-api-url = "https://acousticbrainz.org/api/v1/";
# Authentication
# Available backends: "internal", "PAM", "http-headers"
authentication-backend = "internal";
-http-headers-user-field = "X-Forwarded-User";
+http-headers-login-field = "X-Forwarded-User";
# Max entries in the login throttler (1 entry per IP address. For IPv6, the whole /64 block is used)
login-throttler-max-entries = 10000;
diff --git a/src/libs/auth/impl/http-headers/HttpHeadersEnvService.cpp b/src/libs/auth/impl/http-headers/HttpHeadersEnvService.cpp
index 4d24085a..93f0b584 100644
--- a/src/libs/auth/impl/http-headers/HttpHeadersEnvService.cpp
+++ b/src/libs/auth/impl/http-headers/HttpHeadersEnvService.cpp
@@ -29,7 +29,7 @@ namespace Auth
{
HttpHeadersEnvService::HttpHeadersEnvService()
- : _fieldName {Service::get()->getString("http-headers-field-name", "X-Forwarded-User")}
+ : _fieldName {Service::get()->getString("http-headers-login-field", "X-Forwarded-User")}
{
LMS_LOG(AUTH, INFO) << "Using http header field = '" << _fieldName << "'";
}
@@ -37,7 +37,21 @@ namespace Auth
HttpHeadersEnvService::CheckResult
HttpHeadersEnvService::processEnv(Database::Session& session, const Wt::WEnvironment& env)
{
- const std::string loginName { env.headerValue(_fieldName)};
+ const std::string loginName {env.headerValue(_fieldName)};
+ if (loginName.empty())
+ return {CheckResult::State::Denied};
+
+ LMS_LOG(AUTH, DEBUG) << "Extracted login name = '" << loginName << "' from HTTP header";
+
+ const Database::IdType userId {getOrCreateUser(session, loginName)};
+ onUserAuthenticated(session, userId);
+ return {CheckResult::State::Granted, userId};
+ }
+
+ HttpHeadersEnvService::CheckResult
+ HttpHeadersEnvService::processRequest(Database::Session& session, const Wt::Http::Request& request)
+ {
+ const std::string loginName {request.headerValue(_fieldName)};
if (loginName.empty())
return {CheckResult::State::Denied};
diff --git a/src/libs/auth/impl/http-headers/HttpHeadersEnvService.hpp b/src/libs/auth/impl/http-headers/HttpHeadersEnvService.hpp
index 2f74d0de..1295f182 100644
--- a/src/libs/auth/impl/http-headers/HttpHeadersEnvService.hpp
+++ b/src/libs/auth/impl/http-headers/HttpHeadersEnvService.hpp
@@ -31,6 +31,7 @@ namespace Auth
private:
CheckResult processEnv(Database::Session& session, const Wt::WEnvironment& env) override;
+ CheckResult processRequest(Database::Session& session, const Wt::Http::Request& request) override;
std::string _fieldName;
};
diff --git a/src/libs/auth/include/auth/IEnvService.hpp b/src/libs/auth/include/auth/IEnvService.hpp
index 336432e3..02a6d4e2 100644
--- a/src/libs/auth/include/auth/IEnvService.hpp
+++ b/src/libs/auth/include/auth/IEnvService.hpp
@@ -34,6 +34,11 @@ namespace Wt
class WEnvironment;
}
+namespace Wt::Http
+{
+ class Request;
+}
+
namespace Auth
{
class IEnvService
@@ -56,6 +61,7 @@ namespace Auth
};
virtual CheckResult processEnv(Database::Session& session, const Wt::WEnvironment& env) = 0;
+ virtual CheckResult processRequest(Database::Session& session, const Wt::Http::Request& request) = 0;
};
std::unique_ptr createEnvService(std::string_view backendName);
diff --git a/src/libs/subsonic/impl/RequestContext.hpp b/src/libs/subsonic/impl/RequestContext.hpp
index cd41100b..6d599513 100644
--- a/src/libs/subsonic/impl/RequestContext.hpp
+++ b/src/libs/subsonic/impl/RequestContext.hpp
@@ -22,8 +22,8 @@
#include
#include
-#include
+#include "database/Types.hpp"
namespace Database
{
@@ -32,14 +32,12 @@ namespace Database
namespace API::Subsonic
{
-
struct RequestContext
{
const Wt::Http::ParameterMap& parameters;
Database::Session& dbSession;
- std::string userName;
+ Database::IdType userId;
std::string clientName;
};
-
}
diff --git a/src/libs/subsonic/impl/Stream.cpp b/src/libs/subsonic/impl/Stream.cpp
index 625224e5..29085c83 100644
--- a/src/libs/subsonic/impl/Stream.cpp
+++ b/src/libs/subsonic/impl/Stream.cpp
@@ -81,7 +81,7 @@ getStreamParameters(RequestContext& context)
}
{
- const User::pointer user {User::getByLoginName(context.dbSession, context.userName)};
+ const User::pointer user {User::getById(context.dbSession, context.userId)};
if (!user)
throw UserNotAuthorizedError {};
diff --git a/src/libs/subsonic/impl/SubsonicResource.cpp b/src/libs/subsonic/impl/SubsonicResource.cpp
index 6c922a21..70ba40ba 100644
--- a/src/libs/subsonic/impl/SubsonicResource.cpp
+++ b/src/libs/subsonic/impl/SubsonicResource.cpp
@@ -26,6 +26,7 @@
#include
#include "auth/IPasswordService.hpp"
+#include "auth/IEnvService.hpp"
#include "cover/ICoverArtGrabber.hpp"
#include "database/Artist.hpp"
#include "database/Cluster.hpp"
@@ -209,14 +210,33 @@ static
void
checkUserIsMySelfOrAdmin(RequestContext& context, const std::string& username)
{
- if (username != context.userName)
- {
- User::pointer currentUser {User::getByLoginName(context.dbSession, context.userName)};
- if (!currentUser)
- throw RequestedDataNotFoundError {};
+ User::pointer currentUser {User::getById(context.dbSession, context.userId)};
+ if (!currentUser)
+ throw RequestedDataNotFoundError {};
- if (!currentUser->isAdmin())
- throw UserNotAuthorizedError {};
+ if (currentUser->getLoginName() != username && !currentUser->isAdmin())
+ throw UserNotAuthorizedError {};
+}
+
+static
+void
+checkUserIsAdmin(RequestContext& context)
+{
+ LMS_LOG(API_SUBSONIC, DEBUG) << "Check user is admin";
+
+ auto transaction {context.dbSession.createSharedTransaction()};
+
+ User::pointer currentUser {User::getById(context.dbSession, context.userId)};
+ if (!currentUser)
+ {
+ LMS_LOG(API_SUBSONIC, DEBUG) << "NOT FOUND";
+ throw RequestedDataNotFoundError {};
+ }
+
+ if (!currentUser->isAdmin())
+ {
+ LMS_LOG(API_SUBSONIC, DEBUG) << "NOT ADMIN";
+ throw UserNotAuthorizedError {};
}
}
@@ -327,7 +347,6 @@ trackToResponseNode(const Track::pointer& track, Session& dbSession, const User:
trackResponse.setAttribute("coverArt", IdToString({Id::Type::Track, track.id()}));
const std::vector& artists {track->getArtists({TrackArtistLinkType::Artist})};
- LMS_LOG(API_SUBSONIC, DEBUG) << "Artists count = " << artists.size();
if (!artists.empty())
{
trackResponse.setAttribute("artist", getArtistNames(artists));
@@ -573,7 +592,7 @@ handleCreatePlaylistRequest(RequestContext& context)
auto transaction {context.dbSession.createUniqueTransaction()};
- User::pointer user {User::getByLoginName(context.dbSession, context.userName)};
+ User::pointer user {User::getById(context.dbSession, context.userId)};
if (!user)
throw UserNotAuthorizedError {};
@@ -629,12 +648,12 @@ handleCreateUserRequest(RequestContext& context)
}
auto removeCreatedUser {[&]()
- {
- auto transaction {context.dbSession.createUniqueTransaction()};
- User::pointer user {User::getById(context.dbSession, userId)};
- if (user)
- user.remove();
- }};
+ {
+ auto transaction {context.dbSession.createUniqueTransaction()};
+ User::pointer user {User::getById(context.dbSession, userId)};
+ if (user)
+ user.remove();
+ }};
try
{
@@ -664,7 +683,7 @@ handleDeletePlaylistRequest(RequestContext& context)
auto transaction {context.dbSession.createUniqueTransaction()};
- User::pointer user {User::getByLoginName(context.dbSession, context.userName)};
+ User::pointer user {User::getById(context.dbSession, context.userId)};
if (!user)
throw UserNotAuthorizedError {};
@@ -687,16 +706,16 @@ handleDeleteUserRequest(RequestContext& context)
{
std::string username {getMandatoryParameterAs(context.parameters, "username")};
- // cannot delete ourself
- if (username == context.userName)
- throw UserNotAuthorizedError {};
-
auto transaction {context.dbSession.createUniqueTransaction()};
User::pointer user {User::getByLoginName(context.dbSession, username)};
if (!user)
throw RequestedDataNotFoundError {};
+ // cannot delete ourself
+ if (user.id() == context.userId)
+ throw UserNotAuthorizedError {};
+
user.remove();
return Response::createOkResponse(context);
@@ -726,7 +745,7 @@ handleGetRandomSongsRequest(RequestContext& context)
auto transaction {context.dbSession.createSharedTransaction()};
- User::pointer user {User::getByLoginName(context.dbSession, context.userName)};
+ User::pointer user {User::getById(context.dbSession, context.userId)};
if (!user)
throw UserNotAuthorizedError {};
@@ -758,7 +777,7 @@ handleGetAlbumListRequestCommon(const RequestContext& context, bool id3)
auto transaction {context.dbSession.createSharedTransaction()};
- User::pointer user {User::getByLoginName(context.dbSession, context.userName)};
+ User::pointer user {User::getById(context.dbSession, context.userId)};
if (!user)
throw UserNotAuthorizedError {};
@@ -860,7 +879,7 @@ handleGetAlbumRequest(RequestContext& context)
if (!release)
throw RequestedDataNotFoundError {};
- User::pointer user {User::getByLoginName(context.dbSession, context.userName)};
+ User::pointer user {User::getById(context.dbSession, context.userId)};
if (!user)
throw UserNotAuthorizedError {};
@@ -892,7 +911,7 @@ handleGetArtistRequest(RequestContext& context)
if (!artist)
throw RequestedDataNotFoundError {};
- User::pointer user {User::getByLoginName(context.dbSession, context.userName)};
+ User::pointer user {User::getById(context.dbSession, context.userId)};
if (!user)
throw UserNotAuthorizedError {};
@@ -943,7 +962,7 @@ handleGetArtistInfoRequestCommon(RequestContext& context, bool id3)
{
auto transaction {context.dbSession.createSharedTransaction()};
- User::pointer user {User::getByLoginName(context.dbSession, context.userName)};
+ User::pointer user {User::getById(context.dbSession, context.userId)};
if (!user)
throw UserNotAuthorizedError {};
@@ -987,7 +1006,7 @@ handleGetArtistsRequest(RequestContext& context)
auto transaction {context.dbSession.createSharedTransaction()};
- User::pointer user {User::getByLoginName(context.dbSession, context.userName)};
+ User::pointer user {User::getById(context.dbSession, context.userId)};
if (!user)
throw UserNotAuthorizedError {};
@@ -1031,7 +1050,7 @@ handleGetMusicDirectoryRequest(RequestContext& context)
auto transaction {context.dbSession.createSharedTransaction()};
- User::pointer user {User::getByLoginName(context.dbSession, context.userName)};
+ User::pointer user {User::getById(context.dbSession, context.userId)};
if (!user)
throw UserNotAuthorizedError {};
@@ -1137,7 +1156,7 @@ handleGetIndexesRequest(RequestContext& context)
auto transaction {context.dbSession.createSharedTransaction()};
- User::pointer user {User::getByLoginName(context.dbSession, context.userName)};
+ User::pointer user {User::getById(context.dbSession, context.userId)};
if (!user)
throw UserNotAuthorizedError {};
@@ -1190,7 +1209,7 @@ handleGetSimilarSongsRequestCommon(RequestContext& context, bool id3)
if (!artist)
throw RequestedDataNotFoundError {};
- const User::pointer user {User::getByLoginName(context.dbSession, context.userName)};
+ const User::pointer user {User::getById(context.dbSession, context.userId)};
if (!user)
throw UserNotAuthorizedError {};
@@ -1239,7 +1258,7 @@ handleGetStarredRequestCommon(RequestContext& context, bool id3)
{
auto transaction {context.dbSession.createSharedTransaction()};
- User::pointer user {User::getByLoginName(context.dbSession, context.userName)};
+ User::pointer user {User::getById(context.dbSession, context.userId)};
if (!user)
throw UserNotAuthorizedError {};
@@ -1313,7 +1332,7 @@ handleGetPlaylistRequest(RequestContext& context)
auto transaction {context.dbSession.createSharedTransaction()};
- User::pointer user {User::getByLoginName(context.dbSession, context.userName)};
+ User::pointer user {User::getById(context.dbSession, context.userId)};
if (!user)
throw UserNotAuthorizedError {};
@@ -1339,7 +1358,7 @@ handleGetPlaylistsRequest(RequestContext& context)
{
auto transaction {context.dbSession.createSharedTransaction()};
- User::pointer user {User::getByLoginName(context.dbSession, context.userName)};
+ User::pointer user {User::getById(context.dbSession, context.userId)};
if (!user)
throw UserNotAuthorizedError {};
@@ -1376,7 +1395,7 @@ handleGetSongsByGenreRequest(RequestContext& context)
if (!cluster)
throw RequestedDataNotFoundError {};
- User::pointer user {User::getByLoginName(context.dbSession, context.userName)};
+ User::pointer user {User::getById(context.dbSession, context.userId)};
if (!user)
throw UserNotAuthorizedError {};
@@ -1446,7 +1465,7 @@ handleSearchRequestCommon(RequestContext& context, bool id3)
auto transaction {context.dbSession.createSharedTransaction()};
- User::pointer user {User::getByLoginName(context.dbSession, context.userName)};
+ User::pointer user {User::getById(context.dbSession, context.userId)};
if (!user)
throw UserNotAuthorizedError {};
@@ -1528,7 +1547,7 @@ handleStarRequest(RequestContext& context)
auto transaction {context.dbSession.createSharedTransaction()};
- User::pointer user {User::getByLoginName(context.dbSession, context.userName)};
+ User::pointer user {User::getById(context.dbSession, context.userId)};
if (!user)
throw UserNotAuthorizedError {};
@@ -1584,7 +1603,7 @@ handleUnstarRequest(RequestContext& context)
auto transaction {context.dbSession.createSharedTransaction()};
- User::pointer user {User::getByLoginName(context.dbSession, context.userName)};
+ User::pointer user {User::getById(context.dbSession, context.userId)};
if (!user)
throw RequestedDataNotFoundError {};
@@ -1631,7 +1650,7 @@ handleScrobble(RequestContext& context)
auto transaction {context.dbSession.createUniqueTransaction()};
- User::pointer user {User::getByLoginName(context.dbSession, context.userName)};
+ User::pointer user {User::getById(context.dbSession, context.userId)};
if (!user)
throw RequestedDataNotFoundError {};
@@ -1707,7 +1726,7 @@ handleUpdatePlaylistRequest(RequestContext& context)
auto transaction {context.dbSession.createUniqueTransaction()};
- User::pointer user {User::getByLoginName(context.dbSession, context.userName)};
+ User::pointer user {User::getById(context.dbSession, context.userId)};
if (!user)
throw UserNotAuthorizedError {};
@@ -1756,7 +1775,7 @@ handleGetBookmarks(RequestContext& context)
{
auto transaction {context.dbSession.createSharedTransaction()};
- User::pointer user {User::getByLoginName(context.dbSession, context.userName)};
+ User::pointer user {User::getById(context.dbSession, context.userId)};
if (!user)
throw UserNotAuthorizedError {};
@@ -1790,7 +1809,7 @@ handleCreateBookmark(RequestContext& context)
auto transaction {context.dbSession.createUniqueTransaction()};
- const User::pointer user {User::getByLoginName(context.dbSession, context.userName)};
+ const User::pointer user {User::getById(context.dbSession, context.userId)};
if (!user)
throw UserNotAuthorizedError {};
@@ -1821,7 +1840,7 @@ handleDeleteBookmark(RequestContext& context)
auto transaction {context.dbSession.createUniqueTransaction()};
- const User::pointer user {User::getByLoginName(context.dbSession, context.userName)};
+ const User::pointer user {User::getById(context.dbSession, context.userId)};
if (!user)
throw UserNotAuthorizedError {};
@@ -1995,6 +2014,39 @@ static std::unordered_map mediaRetrieval
{"getCoverArt", handleGetCoverArt},
};
+static
+Database::IdType
+authenticateUser(const Wt::Http::Request &request, const ClientInfo& clientInfo, Session& dbSession)
+{
+ if (auto *authEnvService {Service<::Auth::IEnvService>::get()})
+ {
+ const auto checkResult {authEnvService->processRequest(dbSession, request)};
+ if (checkResult.state != ::Auth::IEnvService::CheckResult::State::Granted)
+ throw UserNotAuthorizedError {};
+
+ return *checkResult.userId;
+ }
+ else if (auto *authPasswordService {Service<::Auth::IPasswordService>::get()})
+ {
+ const auto checkResult {authPasswordService->checkUserPassword(dbSession,
+ boost::asio::ip::address::from_string(request.clientAddress()),
+ clientInfo.user, clientInfo.password)};
+
+ switch (checkResult.state)
+ {
+ case Auth::IPasswordService::CheckResult::State::Granted:
+ return *checkResult.userId;
+ break;
+ case Auth::IPasswordService::CheckResult::State::Denied:
+ throw WrongUsernameOrPasswordError {};
+ case Auth::IPasswordService::CheckResult::State::Throttled:
+ throw LoginThrottledGenericError {};
+ }
+ }
+
+ throw InternalErrorGenericError {"No service avalaible to authenticate user"};
+}
+
void
SubsonicResource::handleRequest(const Wt::Http::Request &request, Wt::Http::Response &response)
{
@@ -2024,21 +2076,8 @@ SubsonicResource::handleRequest(const Wt::Http::Request &request, Wt::Http::Resp
Session& dbSession {_db.getTLSSession()};
- const Auth::IPasswordService::CheckResult checkResult {Service::get()->checkUserPassword(dbSession,
- boost::asio::ip::address::from_string(request.clientAddress()),
- clientInfo.user, clientInfo.password)};
-
- switch (checkResult.state)
- {
- case Auth::IPasswordService::CheckResult::State::Granted:
- break;
- case Auth::IPasswordService::CheckResult::State::Denied:
- throw WrongUsernameOrPasswordError {};
- case Auth::IPasswordService::CheckResult::State::Throttled:
- throw LoginThrottledGenericError {};
- }
-
- RequestContext requestContext {parameters, dbSession, clientInfo.user, clientInfo.name};
+ const Database::IdType userId {authenticateUser(request, clientInfo, dbSession)};
+ RequestContext requestContext {parameters, dbSession, userId, clientInfo.name};
auto itEntryPoint {requestEntryPoints.find(requestPath)};
if (itEntryPoint != requestEntryPoints.end())
@@ -2047,13 +2086,7 @@ SubsonicResource::handleRequest(const Wt::Http::Request &request, Wt::Http::Resp
itEntryPoint->second.checkFunc();
if (itEntryPoint->second.mustBeAdmin)
- {
- auto transaction {dbSession.createSharedTransaction()};
-
- User::pointer user {User::getByLoginName(dbSession, clientInfo.user)};
- if (!user || !user->isAdmin())
- throw UserNotAuthorizedError {};
- }
+ checkUserIsAdmin(requestContext);
Response resp {(itEntryPoint->second.func)(requestContext)};
diff --git a/src/lms/ui/LmsApplication.cpp b/src/lms/ui/LmsApplication.cpp
index 861b3501..f86906ee 100644
--- a/src/lms/ui/LmsApplication.cpp
+++ b/src/lms/ui/LmsApplication.cpp
@@ -65,6 +65,19 @@ static constexpr const char* defaultPath {"/releases"};
std::unique_ptr
LmsApplication::create(const Wt::WEnvironment& env, Database::Db& db, LmsApplicationGroupContainer& appGroups)
{
+ if (auto *authEnvService {Service<::Auth::IEnvService>::get()})
+ {
+ const auto checkResult {authEnvService->processEnv(db.getTLSSession(), env)};
+ if (checkResult.state != ::Auth::IEnvService::CheckResult::State::Granted)
+ {
+ LMS_LOG(UI, ERROR) << "Cannot authenticate user from environment!";
+ // return a blank page
+ return std::make_unique(env);
+ }
+
+ return std::make_unique(env, db, appGroups, checkResult.userId);
+ }
+
return std::make_unique(env, db, appGroups);
}
@@ -121,10 +134,12 @@ LmsApplication::getUserLoginName()
LmsApplication::LmsApplication(const Wt::WEnvironment& env,
Database::Db& db,
- LmsApplicationGroupContainer& appGroups)
-: Wt::WApplication {env},
- _db {db},
- _appGroups {appGroups}
+ LmsApplicationGroupContainer& appGroups,
+ std::optional userId)
+: Wt::WApplication {env}
+, _db {db}
+, _appGroups {appGroups}
+, _authenticatedUser {userId ? std::make_optional(UserAuthInfo {*userId, false}) : std::nullopt}
{
try
{
@@ -181,23 +196,12 @@ LmsApplication::init()
// Handle Media Scanner events and other session events
enableUpdates(true);
- if (Service<::Auth::IEnvService>::exists())
- processEnvAuth();
+ if (_authenticatedUser)
+ {
+ onUserLoggedIn();
+ }
else if (Service<::Auth::IPasswordService>::exists())
processPasswordAuth();
- else
- throw LmsException {"No auth service available!"};
-}
-
-void
-LmsApplication::processEnvAuth()
-{
- const auto checkResult {Service<::Auth::IEnvService>::get()->processEnv(getDbSession(), wApp->environment())};
- if (checkResult.state != ::Auth::IEnvService::CheckResult::State::Granted)
- throw DeploymentException {};
-
- _authenticatedUser = {*checkResult.userId, false};
- onUserLoggedIn();
}
void
diff --git a/src/lms/ui/LmsApplication.hpp b/src/lms/ui/LmsApplication.hpp
index 453007a2..2fdd8d10 100644
--- a/src/lms/ui/LmsApplication.hpp
+++ b/src/lms/ui/LmsApplication.hpp
@@ -60,7 +60,7 @@ class LmsApplication : public Wt::WApplication
{
public:
- LmsApplication(const Wt::WEnvironment& env, Database::Db& db, LmsApplicationGroupContainer& appGroups);
+ LmsApplication(const Wt::WEnvironment& env, Database::Db& db, LmsApplicationGroupContainer& appGroups, std::optional userId = std::nullopt);
~LmsApplication();
static std::unique_ptr create(const Wt::WEnvironment& env, Database::Db& db, LmsApplicationGroupContainer& appGroups);
@@ -110,7 +110,6 @@ class LmsApplication : public Wt::WApplication
void init();
void setTheme();
- void processEnvAuth();
void processPasswordAuth();
void handleException(LmsApplicationException& e);
void goHomeAndQuit();
diff --git a/src/lms/ui/LmsApplicationException.hpp b/src/lms/ui/LmsApplicationException.hpp
index 3acdde67..61ef2dbd 100644
--- a/src/lms/ui/LmsApplicationException.hpp
+++ b/src/lms/ui/LmsApplicationException.hpp
@@ -31,12 +31,6 @@ class LmsApplicationException : public LmsException
LmsApplicationException(const Wt::WString& error) : LmsException {error.toUTF8()} {}
};
-class DeploymentException : public LmsApplicationException
-{
- public:
- DeploymentException() : LmsApplicationException {Wt::WString::tr("Lms.Error.deployment-error")} {}
-};
-
class ArtistNotFoundException : public LmsApplicationException
{
public: