Removed not that useful config options
This commit is contained in:
@@ -19,8 +19,6 @@ OpenSubsonic is an initiative to patch and extend the legacy Subsonic API. You'l
|
|||||||
_LMS_ supports the [API Key Authentication](https://opensubsonic.netlify.app/docs/extensions/apikeyauth/) method. Each user has to generate their own API key on the settings page to use the Subsonic API.
|
_LMS_ supports the [API Key Authentication](https://opensubsonic.netlify.app/docs/extensions/apikeyauth/) method. Each user has to generate their own API key on the settings page to use the Subsonic API.
|
||||||
If a client's login screen has no dedicated API key field, enter the API key as the password instead.
|
If a client's login screen has no dedicated API key field, enter the API key as the password instead.
|
||||||
|
|
||||||
__Note__: the legacy Subsonic authentication methods can be disabled using the `lms.conf` file.
|
|
||||||
|
|
||||||
## Extra fields
|
## Extra fields
|
||||||
The following extra fields are implemented:
|
The following extra fields are implemented:
|
||||||
* `Album` response:
|
* `Album` response:
|
||||||
|
|||||||
@@ -54,11 +54,9 @@
|
|||||||
<div class="card mt-3">
|
<div class="card mt-3">
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
${tr:Lms.Settings.subsonic-token}
|
${tr:Lms.Settings.subsonic-token}
|
||||||
${<if-has-subsonic-token-usage>}
|
|
||||||
<button type="button" class="btn btn-sm p-0" data-bs-toggle="tooltip" data-bs-placement="right" title="${tr:Lms.Settings.subsonic-token-usage}">
|
<button type="button" class="btn btn-sm p-0" data-bs-toggle="tooltip" data-bs-placement="right" title="${tr:Lms.Settings.subsonic-token-usage}">
|
||||||
<i class="fa fa-fw fa-info-circle" aria-hidden="true"></i>
|
<i class="fa fa-fw fa-info-circle" aria-hidden="true"></i>
|
||||||
</button>
|
</button>
|
||||||
${</if-has-subsonic-token-usage>}
|
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="input-group mb-3">
|
<div class="input-group mb-3">
|
||||||
|
|||||||
@@ -84,12 +84,6 @@ login-throttler-max-entries = 10000;
|
|||||||
# API
|
# API
|
||||||
api-subsonic = true;
|
api-subsonic = true;
|
||||||
|
|
||||||
# Enable or disable user/password authentication (params 'u' and 'p')
|
|
||||||
api-subsonic-support-password-auth = true;
|
|
||||||
|
|
||||||
# Enable or disable token/salt authentication (params 'u', 's' and 't')
|
|
||||||
api-subsonic-support-token-auth = true;
|
|
||||||
|
|
||||||
# List of clients for whom open subsonic extensions and extra fields are disabled
|
# List of clients for whom open subsonic extensions and extra fields are disabled
|
||||||
api-open-subsonic-disabled-clients = ("DSub");
|
api-open-subsonic-disabled-clients = ("DSub");
|
||||||
|
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ namespace lms::api::subsonic::utils
|
|||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
AuthenticationRequest parseAndValidateAuthenticationRequest(const Wt::Http::ParameterMap& parameters, const SubsonicResourceConfig& config)
|
AuthenticationRequest parseAndValidateAuthenticationRequest(const Wt::Http::ParameterMap& parameters)
|
||||||
{
|
{
|
||||||
const std::optional<std::string> user{ getParameterAs<std::string>(parameters, "u") };
|
const std::optional<std::string> user{ getParameterAs<std::string>(parameters, "u") };
|
||||||
const std::optional<std::string> password{ getParameterAs<std::string>(parameters, "p") };
|
const std::optional<std::string> password{ getParameterAs<std::string>(parameters, "p") };
|
||||||
@@ -70,12 +70,6 @@ namespace lms::api::subsonic::utils
|
|||||||
|
|
||||||
const bool passwordAuthRequested{ password.has_value() };
|
const bool passwordAuthRequested{ password.has_value() };
|
||||||
const bool tokenAuthRequested{ token.has_value() || salt.has_value() };
|
const bool tokenAuthRequested{ token.has_value() || salt.has_value() };
|
||||||
const bool passwordAuthAttempted{ passwordAuthRequested || (user.has_value() && !tokenAuthRequested) };
|
|
||||||
|
|
||||||
if (!config.supportPasswordAuthentication && passwordAuthAttempted)
|
|
||||||
throw ProvidedAuthenticationMechanismNotSupportedError{};
|
|
||||||
if (!config.supportTokenAuthentication && tokenAuthRequested)
|
|
||||||
throw ProvidedAuthenticationMechanismNotSupportedError{};
|
|
||||||
|
|
||||||
if (passwordAuthRequested && tokenAuthRequested)
|
if (passwordAuthRequested && tokenAuthRequested)
|
||||||
throw MultipleConflictingAuthenticationMechanismsProvidedError{};
|
throw MultipleConflictingAuthenticationMechanismsProvidedError{};
|
||||||
@@ -130,9 +124,9 @@ namespace lms::api::subsonic::utils
|
|||||||
throw UserNotAuthorizedError{};
|
throw UserNotAuthorizedError{};
|
||||||
}
|
}
|
||||||
|
|
||||||
db::UserId authenticateUser(const Wt::Http::Request& request, db::Session& session, const SubsonicResourceConfig& config)
|
db::UserId authenticateUser(const Wt::Http::Request& request, db::Session& session)
|
||||||
{
|
{
|
||||||
const AuthenticationRequest authRequest{ parseAndValidateAuthenticationRequest(request.getParameterMap(), config) };
|
const AuthenticationRequest authRequest{ parseAndValidateAuthenticationRequest(request.getParameterMap()) };
|
||||||
|
|
||||||
const auto clientAddress{ boost::asio::ip::make_address(request.clientAddress()) };
|
const auto clientAddress{ boost::asio::ip::make_address(request.clientAddress()) };
|
||||||
auto& authTokenService{ *core::Service<auth::IAuthTokenService>::get() };
|
auto& authTokenService{ *core::Service<auth::IAuthTokenService>::get() };
|
||||||
|
|||||||
@@ -28,8 +28,6 @@
|
|||||||
#include "database/objects/User.hpp"
|
#include "database/objects/User.hpp"
|
||||||
#include "database/objects/UserId.hpp"
|
#include "database/objects/UserId.hpp"
|
||||||
|
|
||||||
#include "SubsonicResourceConfig.hpp"
|
|
||||||
|
|
||||||
namespace lms::db
|
namespace lms::db
|
||||||
{
|
{
|
||||||
class Session;
|
class Session;
|
||||||
@@ -58,7 +56,7 @@ namespace lms::api::subsonic::utils
|
|||||||
using AuthenticationRequest = std::variant<PasswordAuthentication, TokenAuthentication, ApiKeyAuthentication>;
|
using AuthenticationRequest = std::variant<PasswordAuthentication, TokenAuthentication, ApiKeyAuthentication>;
|
||||||
|
|
||||||
// Throws on error
|
// Throws on error
|
||||||
AuthenticationRequest parseAndValidateAuthenticationRequest(const Wt::Http::ParameterMap& parameters, const SubsonicResourceConfig& config);
|
AuthenticationRequest parseAndValidateAuthenticationRequest(const Wt::Http::ParameterMap& parameters);
|
||||||
|
|
||||||
// Checks token == hex(md5(apiKey + salt)), case insensitive
|
// Checks token == hex(md5(apiKey + salt)), case insensitive
|
||||||
bool checkAuthToken(std::string_view apiKey, std::string_view salt, std::string_view token);
|
bool checkAuthToken(std::string_view apiKey, std::string_view salt, std::string_view token);
|
||||||
@@ -67,5 +65,5 @@ namespace lms::api::subsonic::utils
|
|||||||
db::User::pointer getUserFromUserId(db::Session& session, db::UserId userId);
|
db::User::pointer getUserFromUserId(db::Session& session, db::UserId userId);
|
||||||
|
|
||||||
// Throws on error
|
// Throws on error
|
||||||
db::UserId authenticateUser(const Wt::Http::Request& request, db::Session& session, const SubsonicResourceConfig& config);
|
db::UserId authenticateUser(const Wt::Http::Request& request, db::Session& session);
|
||||||
} // namespace lms::api::subsonic::utils
|
} // namespace lms::api::subsonic::utils
|
||||||
|
|||||||
@@ -415,6 +415,6 @@ namespace lms::api::subsonic
|
|||||||
|
|
||||||
db::UserId SubsonicResource::authenticateUser(const Wt::Http::Request& request)
|
db::UserId SubsonicResource::authenticateUser(const Wt::Http::Request& request)
|
||||||
{
|
{
|
||||||
return utils::authenticateUser(request, _db.getTLSSession(), _config);
|
return utils::authenticateUser(request, _db.getTLSSession());
|
||||||
}
|
}
|
||||||
} // namespace lms::api::subsonic
|
} // namespace lms::api::subsonic
|
||||||
|
|||||||
@@ -43,8 +43,6 @@ namespace lms::api::subsonic
|
|||||||
{
|
{
|
||||||
return SubsonicResourceConfig{
|
return SubsonicResourceConfig{
|
||||||
.openSubsonicDisabledClients = readOpenSubsonicDisabledClients(config),
|
.openSubsonicDisabledClients = readOpenSubsonicDisabledClients(config),
|
||||||
.supportPasswordAuthentication = config.getBool("api-subsonic-support-password-auth", true),
|
|
||||||
.supportTokenAuthentication = config.getBool("api-subsonic-support-token-auth", true)
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
} // namespace lms::api::subsonic
|
} // namespace lms::api::subsonic
|
||||||
@@ -32,8 +32,6 @@ namespace lms::api::subsonic
|
|||||||
struct SubsonicResourceConfig
|
struct SubsonicResourceConfig
|
||||||
{
|
{
|
||||||
std::unordered_set<std::string> openSubsonicDisabledClients;
|
std::unordered_set<std::string> openSubsonicDisabledClients;
|
||||||
bool supportPasswordAuthentication;
|
|
||||||
bool supportTokenAuthentication;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
SubsonicResourceConfig readSubsonicResourceConfig(core::IConfig& _config);
|
SubsonicResourceConfig readSubsonicResourceConfig(core::IConfig& _config);
|
||||||
|
|||||||
@@ -47,7 +47,6 @@ namespace lms::api::subsonic
|
|||||||
ServerMustUpgrade = 30,
|
ServerMustUpgrade = 30,
|
||||||
WrongUsernameOrPassword = 40,
|
WrongUsernameOrPassword = 40,
|
||||||
TokenAuthenticationNotSupportedForLDAPUsers = 41,
|
TokenAuthenticationNotSupportedForLDAPUsers = 41,
|
||||||
ProvidedAuthenticationMechanismNotSupported = 42,
|
|
||||||
MultipleConflictingAuthenticationMechanismsProvided = 43,
|
MultipleConflictingAuthenticationMechanismsProvided = 43,
|
||||||
InvalidAPIkey = 44,
|
InvalidAPIkey = 44,
|
||||||
UserNotAuthorized = 50,
|
UserNotAuthorized = 50,
|
||||||
@@ -131,19 +130,6 @@ namespace lms::api::subsonic
|
|||||||
std::string getMessage() const override { return "Token authentication not supported for LDAP users."; }
|
std::string getMessage() const override { return "Token authentication not supported for LDAP users."; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class ProvidedAuthenticationMechanismNotSupportedError : public Error
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ProvidedAuthenticationMechanismNotSupportedError()
|
|
||||||
: Error{ Code::ProvidedAuthenticationMechanismNotSupported } {}
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::string getMessage() const override
|
|
||||||
{
|
|
||||||
return "Provided authentication mechanism not supported.";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class MultipleConflictingAuthenticationMechanismsProvidedError : public Error
|
class MultipleConflictingAuthenticationMechanismsProvidedError : public Error
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -24,27 +24,6 @@
|
|||||||
|
|
||||||
namespace lms::api::subsonic::utils::tests
|
namespace lms::api::subsonic::utils::tests
|
||||||
{
|
{
|
||||||
namespace
|
|
||||||
{
|
|
||||||
const SubsonicResourceConfig bothMechanismsSupported{
|
|
||||||
.openSubsonicDisabledClients = {},
|
|
||||||
.supportPasswordAuthentication = true,
|
|
||||||
.supportTokenAuthentication = true,
|
|
||||||
};
|
|
||||||
|
|
||||||
const SubsonicResourceConfig noneSupported{
|
|
||||||
.openSubsonicDisabledClients = {},
|
|
||||||
.supportPasswordAuthentication = false,
|
|
||||||
.supportTokenAuthentication = false,
|
|
||||||
};
|
|
||||||
|
|
||||||
const SubsonicResourceConfig passwordUnsupported{
|
|
||||||
.openSubsonicDisabledClients = {},
|
|
||||||
.supportPasswordAuthentication = false,
|
|
||||||
.supportTokenAuthentication = true,
|
|
||||||
};
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
// Reference values from the Subsonic API documentation (apiKey = "sesame", salt = "c19b2d")
|
// Reference values from the Subsonic API documentation (apiKey = "sesame", salt = "c19b2d")
|
||||||
TEST(AuthUtils, checkAuthToken_ValidToken)
|
TEST(AuthUtils, checkAuthToken_ValidToken)
|
||||||
{
|
{
|
||||||
@@ -73,66 +52,59 @@ namespace lms::api::subsonic::utils::tests
|
|||||||
|
|
||||||
TEST(AuthUtils, parseAndValidateAuthenticationRequest_apiKeyOnly)
|
TEST(AuthUtils, parseAndValidateAuthenticationRequest_apiKeyOnly)
|
||||||
{
|
{
|
||||||
const auto request{ parseAndValidateAuthenticationRequest({ { "apiKey", { "apiKey" } } }, bothMechanismsSupported) };
|
const auto request{ parseAndValidateAuthenticationRequest({ { "apiKey", { "apiKey" } } }) };
|
||||||
ASSERT_TRUE(std::holds_alternative<ApiKeyAuthentication>(request));
|
ASSERT_TRUE(std::holds_alternative<ApiKeyAuthentication>(request));
|
||||||
EXPECT_EQ(std::get<ApiKeyAuthentication>(request).apiKey, "apiKey");
|
EXPECT_EQ(std::get<ApiKeyAuthentication>(request).apiKey, "apiKey");
|
||||||
|
|
||||||
EXPECT_THROW(parseAndValidateAuthenticationRequest({}, bothMechanismsSupported), RequiredParameterMissingError);
|
EXPECT_THROW(parseAndValidateAuthenticationRequest({}), RequiredParameterMissingError);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(AuthUtils, parseAndValidateAuthenticationRequest_password)
|
TEST(AuthUtils, parseAndValidateAuthenticationRequest_password)
|
||||||
{
|
{
|
||||||
const auto request{ parseAndValidateAuthenticationRequest({ { "u", { "user" } }, { "p", { "password" } } }, bothMechanismsSupported) };
|
const auto request{ parseAndValidateAuthenticationRequest({ { "u", { "user" } }, { "p", { "password" } } }) };
|
||||||
ASSERT_TRUE(std::holds_alternative<PasswordAuthentication>(request));
|
ASSERT_TRUE(std::holds_alternative<PasswordAuthentication>(request));
|
||||||
EXPECT_EQ(std::get<PasswordAuthentication>(request).user, "user");
|
EXPECT_EQ(std::get<PasswordAuthentication>(request).user, "user");
|
||||||
EXPECT_EQ(std::get<PasswordAuthentication>(request).password, "password");
|
EXPECT_EQ(std::get<PasswordAuthentication>(request).password, "password");
|
||||||
|
|
||||||
EXPECT_THROW(parseAndValidateAuthenticationRequest({ { "p", { "password" } } }, bothMechanismsSupported), RequiredParameterMissingError); // missing u
|
EXPECT_THROW(parseAndValidateAuthenticationRequest({ { "p", { "password" } } }), RequiredParameterMissingError); // missing u
|
||||||
EXPECT_THROW(parseAndValidateAuthenticationRequest({ { "u", { "user" } } }, bothMechanismsSupported), RequiredParameterMissingError); // missing p
|
EXPECT_THROW(parseAndValidateAuthenticationRequest({ { "u", { "user" } } }), RequiredParameterMissingError); // missing p
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(AuthUtils, parseAndValidateAuthenticationRequest_token)
|
TEST(AuthUtils, parseAndValidateAuthenticationRequest_token)
|
||||||
{
|
{
|
||||||
const auto request{ parseAndValidateAuthenticationRequest({ { "u", { "user" } }, { "t", { "token" } }, { "s", { "salt" } } }, bothMechanismsSupported) };
|
const auto request{ parseAndValidateAuthenticationRequest({ { "u", { "user" } }, { "t", { "token" } }, { "s", { "salt" } } }) };
|
||||||
ASSERT_TRUE(std::holds_alternative<TokenAuthentication>(request));
|
ASSERT_TRUE(std::holds_alternative<TokenAuthentication>(request));
|
||||||
EXPECT_EQ(std::get<TokenAuthentication>(request).user, "user");
|
EXPECT_EQ(std::get<TokenAuthentication>(request).user, "user");
|
||||||
EXPECT_EQ(std::get<TokenAuthentication>(request).token, "token");
|
EXPECT_EQ(std::get<TokenAuthentication>(request).token, "token");
|
||||||
EXPECT_EQ(std::get<TokenAuthentication>(request).salt, "salt");
|
EXPECT_EQ(std::get<TokenAuthentication>(request).salt, "salt");
|
||||||
|
|
||||||
EXPECT_THROW(parseAndValidateAuthenticationRequest({ { "t", { "token" } }, { "s", { "salt" } } }, bothMechanismsSupported), RequiredParameterMissingError); // missing u
|
EXPECT_THROW(parseAndValidateAuthenticationRequest({ { "t", { "token" } }, { "s", { "salt" } } }), RequiredParameterMissingError); // missing u
|
||||||
EXPECT_THROW(parseAndValidateAuthenticationRequest({ { "u", { "user" } }, { "s", { "salt" } } }, bothMechanismsSupported), RequiredParameterMissingError); // missing t
|
EXPECT_THROW(parseAndValidateAuthenticationRequest({ { "u", { "user" } }, { "s", { "salt" } } }), RequiredParameterMissingError); // missing t
|
||||||
EXPECT_THROW(parseAndValidateAuthenticationRequest({ { "u", { "user" } }, { "t", { "token" } } }, bothMechanismsSupported), RequiredParameterMissingError); // missing s
|
EXPECT_THROW(parseAndValidateAuthenticationRequest({ { "u", { "user" } }, { "t", { "token" } } }), RequiredParameterMissingError); // missing s
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(AuthUtils, parseAndValidateAuthenticationRequest_conflicts)
|
TEST(AuthUtils, parseAndValidateAuthenticationRequest_conflicts)
|
||||||
{
|
{
|
||||||
// password + token
|
// password + token
|
||||||
EXPECT_THROW(parseAndValidateAuthenticationRequest({ { "u", { "user" } }, { "p", { "password" } }, { "t", { "token" } }, { "s", { "salt" } } }, bothMechanismsSupported), MultipleConflictingAuthenticationMechanismsProvidedError);
|
EXPECT_THROW(parseAndValidateAuthenticationRequest({ { "u", { "user" } }, { "p", { "password" } }, { "t", { "token" } }, { "s", { "salt" } } }), MultipleConflictingAuthenticationMechanismsProvidedError);
|
||||||
// apiKey + password
|
// apiKey + password
|
||||||
EXPECT_THROW(parseAndValidateAuthenticationRequest({ { "u", { "user" } }, { "p", { "password" } }, { "apiKey", { "apiKey" } } }, bothMechanismsSupported), MultipleConflictingAuthenticationMechanismsProvidedError);
|
EXPECT_THROW(parseAndValidateAuthenticationRequest({ { "u", { "user" } }, { "p", { "password" } }, { "apiKey", { "apiKey" } } }), MultipleConflictingAuthenticationMechanismsProvidedError);
|
||||||
// apiKey + token
|
// apiKey + token
|
||||||
EXPECT_THROW(parseAndValidateAuthenticationRequest({ { "u", { "user" } }, { "t", { "token" } }, { "s", { "salt" } }, { "apiKey", { "apiKey" } } }, bothMechanismsSupported), MultipleConflictingAuthenticationMechanismsProvidedError);
|
EXPECT_THROW(parseAndValidateAuthenticationRequest({ { "u", { "user" } }, { "t", { "token" } }, { "s", { "salt" } }, { "apiKey", { "apiKey" } } }), MultipleConflictingAuthenticationMechanismsProvidedError);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(AuthUtils, parseAndValidateAuthenticationRequest_mechanismNotSupported)
|
TEST(AuthUtils, parseAndValidateAuthenticationRequest_usernameOnlyRequiresPassword)
|
||||||
{
|
{
|
||||||
EXPECT_THROW(parseAndValidateAuthenticationRequest({ { "u", { "user" } }, { "p", { "password" } } }, noneSupported), ProvidedAuthenticationMechanismNotSupportedError);
|
EXPECT_THROW(parseAndValidateAuthenticationRequest({ { "u", { "user" } } }), RequiredParameterMissingError); // missing p
|
||||||
EXPECT_THROW(parseAndValidateAuthenticationRequest({ { "u", { "user" } }, { "t", { "token" } }, { "s", { "salt" } } }, noneSupported), ProvidedAuthenticationMechanismNotSupportedError);
|
|
||||||
EXPECT_NO_THROW(parseAndValidateAuthenticationRequest({ { "apiKey", { "apiKey" } } }, noneSupported)); // apiKey is unaffected by these two flags
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(AuthUtils, parseAndValidateAuthenticationRequest_usernameOnlyTreatedAsPasswordAttempt)
|
|
||||||
{
|
|
||||||
EXPECT_THROW(parseAndValidateAuthenticationRequest({ { "u", { "user" } } }, passwordUnsupported), ProvidedAuthenticationMechanismNotSupportedError);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(AuthUtils, parseAndValidateAuthenticationRequest_apiKeyWithPartialPassword)
|
TEST(AuthUtils, parseAndValidateAuthenticationRequest_apiKeyWithPartialPassword)
|
||||||
{
|
{
|
||||||
EXPECT_THROW(parseAndValidateAuthenticationRequest({ { "p", { "password" } }, { "apiKey", { "apiKey" } } }, bothMechanismsSupported), RequiredParameterMissingError); // missing u
|
EXPECT_THROW(parseAndValidateAuthenticationRequest({ { "p", { "password" } }, { "apiKey", { "apiKey" } } }), RequiredParameterMissingError); // missing u
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(AuthUtils, parseAndValidateAuthenticationRequest_apiKeyWithPartialToken)
|
TEST(AuthUtils, parseAndValidateAuthenticationRequest_apiKeyWithPartialToken)
|
||||||
{
|
{
|
||||||
EXPECT_THROW(parseAndValidateAuthenticationRequest({ { "s", { "salt" } }, { "apiKey", { "apiKey" } } }, bothMechanismsSupported), RequiredParameterMissingError); // missing u
|
EXPECT_THROW(parseAndValidateAuthenticationRequest({ { "s", { "salt" } }, { "apiKey", { "apiKey" } } }), RequiredParameterMissingError); // missing u
|
||||||
}
|
}
|
||||||
} // namespace lms::api::subsonic::utils::tests
|
} // namespace lms::api::subsonic::utils::tests
|
||||||
|
|||||||
@@ -27,7 +27,6 @@
|
|||||||
#include <Wt/WString.h>
|
#include <Wt/WString.h>
|
||||||
#include <Wt/WTemplateFormView.h>
|
#include <Wt/WTemplateFormView.h>
|
||||||
|
|
||||||
#include "core/IConfig.hpp"
|
|
||||||
#include "core/Service.hpp"
|
#include "core/Service.hpp"
|
||||||
#include "core/UUID.hpp"
|
#include "core/UUID.hpp"
|
||||||
|
|
||||||
@@ -185,11 +184,6 @@ namespace lms::ui
|
|||||||
auto* t{ addNew<Wt::WTemplate>(Wt::WString::tr("Lms.Settings.subsonic.template.key")) };
|
auto* t{ addNew<Wt::WTemplate>(Wt::WString::tr("Lms.Settings.subsonic.template.key")) };
|
||||||
t->addFunction("tr", &Wt::WTemplate::Functions::tr);
|
t->addFunction("tr", &Wt::WTemplate::Functions::tr);
|
||||||
|
|
||||||
{
|
|
||||||
core::IConfig& config{ *core::Service<core::IConfig>::get() };
|
|
||||||
t->setCondition("if-has-subsonic-token-usage", config.getBool("api-subsonic-support-password-auth", true) || config.getBool("api-subsonic-support-token-auth", true));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string currentToken;
|
std::string currentToken;
|
||||||
{
|
{
|
||||||
auto transaction{ LmsApp->getDbSession().createReadTransaction() };
|
auto transaction{ LmsApp->getDbSession().createReadTransaction() };
|
||||||
|
|||||||
Reference in New Issue
Block a user