Refactored namespaces
This commit is contained in:
@@ -19,7 +19,7 @@ target_include_directories(lmsauth PRIVATE
|
||||
)
|
||||
|
||||
target_link_libraries(lmsauth PRIVATE
|
||||
lmsutils
|
||||
lmscore
|
||||
lmsdatabase
|
||||
)
|
||||
|
||||
|
||||
@@ -23,11 +23,11 @@
|
||||
#include "database/Db.hpp"
|
||||
#include "database/Session.hpp"
|
||||
#include "database/User.hpp"
|
||||
#include "utils/ILogger.hpp"
|
||||
#include "core/ILogger.hpp"
|
||||
|
||||
namespace Auth
|
||||
namespace lms::auth
|
||||
{
|
||||
using namespace Database;
|
||||
using namespace db;
|
||||
|
||||
AuthServiceBase::AuthServiceBase(Db& db)
|
||||
: _db{ db }
|
||||
|
||||
@@ -22,25 +22,25 @@
|
||||
#include <string_view>
|
||||
#include "database/UserId.hpp"
|
||||
|
||||
namespace Database
|
||||
namespace lms::db
|
||||
{
|
||||
class Db;
|
||||
class Session;
|
||||
}
|
||||
|
||||
namespace Auth
|
||||
namespace lms::auth
|
||||
{
|
||||
class AuthServiceBase
|
||||
{
|
||||
protected:
|
||||
AuthServiceBase(Database::Db& db);
|
||||
AuthServiceBase(db::Db& db);
|
||||
|
||||
Database::UserId getOrCreateUser(std::string_view loginName);
|
||||
void onUserAuthenticated(Database::UserId userId);
|
||||
db::UserId getOrCreateUser(std::string_view loginName);
|
||||
void onUserAuthenticated(db::UserId userId);
|
||||
|
||||
Database::Session& getDbSession();
|
||||
db::Session& getDbSession();
|
||||
|
||||
private:
|
||||
Database::Db& _db;
|
||||
db::Db& _db;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -27,45 +27,45 @@
|
||||
#include "database/AuthToken.hpp"
|
||||
#include "database/Session.hpp"
|
||||
#include "database/User.hpp"
|
||||
#include "utils/Exception.hpp"
|
||||
#include "utils/ILogger.hpp"
|
||||
#include "core/Exception.hpp"
|
||||
#include "core/ILogger.hpp"
|
||||
|
||||
namespace Auth
|
||||
namespace lms::auth
|
||||
{
|
||||
|
||||
std::unique_ptr<IAuthTokenService> createAuthTokenService(Database::Db& db, std::size_t maxThrottlerEntries)
|
||||
std::unique_ptr<IAuthTokenService> createAuthTokenService(db::Db& db, std::size_t maxThrottlerEntries)
|
||||
{
|
||||
return std::make_unique<AuthTokenService>(db, maxThrottlerEntries);
|
||||
}
|
||||
|
||||
static const Wt::Auth::SHA1HashFunction sha1Function;
|
||||
|
||||
AuthTokenService::AuthTokenService(Database::Db& db, std::size_t maxThrottlerEntries)
|
||||
AuthTokenService::AuthTokenService(db::Db& db, std::size_t maxThrottlerEntries)
|
||||
: AuthServiceBase {db}
|
||||
, _loginThrottler {maxThrottlerEntries}
|
||||
{
|
||||
}
|
||||
|
||||
std::string
|
||||
AuthTokenService::createAuthToken(Database::UserId userId, const Wt::WDateTime& expiry)
|
||||
AuthTokenService::createAuthToken(db::UserId userId, const Wt::WDateTime& expiry)
|
||||
{
|
||||
const std::string secret {Wt::WRandom::generateId(32)};
|
||||
const std::string secretHash {sha1Function.compute(secret, {})};
|
||||
|
||||
Database::Session& session {getDbSession()};
|
||||
db::Session& session {getDbSession()};
|
||||
|
||||
auto transaction {session.createWriteTransaction()};
|
||||
|
||||
Database::User::pointer user {Database::User::find(session, userId)};
|
||||
db::User::pointer user {db::User::find(session, userId)};
|
||||
if (!user)
|
||||
throw Exception {"User deleted"};
|
||||
|
||||
Database::AuthToken::pointer authToken {session.create<Database::AuthToken>(secretHash, expiry, user)};
|
||||
db::AuthToken::pointer authToken {session.create<db::AuthToken>(secretHash, expiry, user)};
|
||||
|
||||
LMS_LOG(UI, DEBUG, "Created auth token for user '" << user->getLoginName() << "', expiry = " << expiry.toString());
|
||||
|
||||
if (user->getAuthTokensCount() >= 50)
|
||||
Database::AuthToken::removeExpiredTokens(session, Wt::WDateTime::currentDateTime());
|
||||
db::AuthToken::removeExpiredTokens(session, Wt::WDateTime::currentDateTime());
|
||||
|
||||
return secret;
|
||||
}
|
||||
@@ -75,10 +75,10 @@ namespace Auth
|
||||
{
|
||||
const std::string secretHash {sha1Function.compute(std::string {secret}, {})};
|
||||
|
||||
Database::Session& session {getDbSession()};
|
||||
db::Session& session {getDbSession()};
|
||||
auto transaction {session.createWriteTransaction()};
|
||||
|
||||
Database::AuthToken::pointer authToken {Database::AuthToken::find(session, secretHash)};
|
||||
db::AuthToken::pointer authToken {db::AuthToken::find(session, secretHash)};
|
||||
if (!authToken)
|
||||
return std::nullopt;
|
||||
|
||||
@@ -127,17 +127,17 @@ namespace Auth
|
||||
}
|
||||
|
||||
void
|
||||
AuthTokenService::clearAuthTokens(Database::UserId userId)
|
||||
AuthTokenService::clearAuthTokens(db::UserId userId)
|
||||
{
|
||||
Database::Session& session {getDbSession()};
|
||||
db::Session& session {getDbSession()};
|
||||
|
||||
auto transaction {session.createWriteTransaction()};
|
||||
|
||||
Database::User::pointer user {Database::User::find(session, userId)};
|
||||
db::User::pointer user {db::User::find(session, userId)};
|
||||
if (!user)
|
||||
throw Exception {"User deleted"};
|
||||
|
||||
user.modify()->clearAuthTokens();
|
||||
}
|
||||
|
||||
} // namespace Auth
|
||||
} // namespace lms::auth
|
||||
|
||||
@@ -25,17 +25,17 @@
|
||||
#include "AuthServiceBase.hpp"
|
||||
#include "LoginThrottler.hpp"
|
||||
|
||||
namespace Database
|
||||
namespace lms::db
|
||||
{
|
||||
class Session;
|
||||
}
|
||||
|
||||
namespace Auth
|
||||
namespace lms::auth
|
||||
{
|
||||
class AuthTokenService : public IAuthTokenService, public AuthServiceBase
|
||||
{
|
||||
public:
|
||||
AuthTokenService(Database::Db& db, std::size_t maxThrottlerEntries);
|
||||
AuthTokenService(db::Db& db, std::size_t maxThrottlerEntries);
|
||||
|
||||
AuthTokenService(const AuthTokenService&) = delete;
|
||||
AuthTokenService& operator=(const AuthTokenService&) = delete;
|
||||
@@ -44,8 +44,8 @@ namespace Auth
|
||||
|
||||
private:
|
||||
AuthTokenProcessResult processAuthToken(const boost::asio::ip::address& clientAddress, std::string_view tokenValue) override;
|
||||
std::string createAuthToken(Database::UserId userId, const Wt::WDateTime& expiry) override;
|
||||
void clearAuthTokens(Database::UserId userId) override;
|
||||
std::string createAuthToken(db::UserId userId, const Wt::WDateTime& expiry) override;
|
||||
void clearAuthTokens(db::UserId userId) override;
|
||||
|
||||
std::optional<AuthTokenService::AuthTokenProcessResult::AuthTokenInfo> processAuthToken(std::string_view secret);
|
||||
|
||||
|
||||
@@ -22,10 +22,10 @@
|
||||
#include "services/auth/Types.hpp"
|
||||
#include "http-headers/HttpHeadersEnvService.hpp"
|
||||
|
||||
namespace Auth
|
||||
namespace lms::auth
|
||||
{
|
||||
std::unique_ptr<IEnvService>
|
||||
createEnvService(std::string_view backendName, Database::Db& db)
|
||||
createEnvService(std::string_view backendName, db::Db& db)
|
||||
{
|
||||
if (backendName == "http-headers")
|
||||
return std::make_unique<HttpHeadersEnvService>(db);
|
||||
|
||||
@@ -17,104 +17,97 @@
|
||||
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* This file contains some classes in order to get info from file using the libavconv */
|
||||
/* This file contains some classes in order to get info from file using the libavconv */
|
||||
|
||||
#include "LoginThrottler.hpp"
|
||||
|
||||
#include "utils/ILogger.hpp"
|
||||
#include "utils/Random.hpp"
|
||||
#include "core/ILogger.hpp"
|
||||
#include "core/Random.hpp"
|
||||
|
||||
namespace Auth {
|
||||
|
||||
static
|
||||
boost::asio::ip::address_v6
|
||||
getAddressWithMask(const boost::asio::ip::address_v6& address, std::size_t prefix)
|
||||
namespace lms::auth
|
||||
{
|
||||
assert(prefix % 8 == 0);
|
||||
namespace
|
||||
{
|
||||
boost::asio::ip::address_v6 getAddressWithMask(const boost::asio::ip::address_v6& address, std::size_t prefix)
|
||||
{
|
||||
assert(prefix % 8 == 0);
|
||||
|
||||
std::array<uint8_t, 16> truncatedBytes;
|
||||
std::array<uint8_t, 16> truncatedBytes;
|
||||
|
||||
auto bytes {address.to_bytes()};
|
||||
std::copy(std::cbegin(bytes), std::next(std::cbegin(bytes), prefix / 8), truncatedBytes.begin());
|
||||
auto bytes{ address.to_bytes() };
|
||||
std::copy(std::cbegin(bytes), std::next(std::cbegin(bytes), prefix / 8), truncatedBytes.begin());
|
||||
|
||||
return boost::asio::ip::address_v6 {truncatedBytes};
|
||||
}
|
||||
return boost::asio::ip::address_v6{ truncatedBytes };
|
||||
}
|
||||
|
||||
static
|
||||
boost::asio::ip::address
|
||||
getAddressToThrottle(const boost::asio::ip::address& address)
|
||||
{
|
||||
return address.is_v6() ? getAddressWithMask(address.to_v6(), 64) : address;
|
||||
}
|
||||
boost::asio::ip::address getAddressToThrottle(const boost::asio::ip::address& address)
|
||||
{
|
||||
return address.is_v6() ? getAddressWithMask(address.to_v6(), 64) : address;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
LoginThrottler::removeOutdatedEntries()
|
||||
{
|
||||
const Wt::WDateTime now {Wt::WDateTime::currentDateTime()};
|
||||
void LoginThrottler::removeOutdatedEntries()
|
||||
{
|
||||
const Wt::WDateTime now{ Wt::WDateTime::currentDateTime() };
|
||||
|
||||
for (auto it {std::begin(_attemptsInfo)}; it != std::end(_attemptsInfo); )
|
||||
{
|
||||
if (it->second.nextAttempt <= now)
|
||||
it = _attemptsInfo.erase(it);
|
||||
else
|
||||
++it;
|
||||
}
|
||||
}
|
||||
for (auto it{ std::begin(_attemptsInfo) }; it != std::end(_attemptsInfo); )
|
||||
{
|
||||
if (it->second.nextAttempt <= now)
|
||||
it = _attemptsInfo.erase(it);
|
||||
else
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
LoginThrottler::onBadClientAttempt(const boost::asio::ip::address& address)
|
||||
{
|
||||
const boost::asio::ip::address clientAddress {getAddressToThrottle(address)};
|
||||
const Wt::WDateTime now {Wt::WDateTime::currentDateTime()};
|
||||
void LoginThrottler::onBadClientAttempt(const boost::asio::ip::address& address)
|
||||
{
|
||||
const boost::asio::ip::address clientAddress{ getAddressToThrottle(address) };
|
||||
const Wt::WDateTime now{ Wt::WDateTime::currentDateTime() };
|
||||
|
||||
if (_attemptsInfo.size() >= _maxEntries)
|
||||
removeOutdatedEntries();
|
||||
if (_attemptsInfo.size() >= _maxEntries)
|
||||
_attemptsInfo.erase(Random::pickRandom(_attemptsInfo));
|
||||
if (_attemptsInfo.size() >= _maxEntries)
|
||||
removeOutdatedEntries();
|
||||
if (_attemptsInfo.size() >= _maxEntries)
|
||||
_attemptsInfo.erase(core::random::pickRandom(_attemptsInfo));
|
||||
|
||||
AttemptInfo& attemptInfo {_attemptsInfo[address]};
|
||||
if (attemptInfo.nextAttempt.isValid())
|
||||
{
|
||||
assert(attemptInfo.nextAttempt <= now); // should not be called if throttled
|
||||
attemptInfo = {};
|
||||
}
|
||||
AttemptInfo& attemptInfo{ _attemptsInfo[address] };
|
||||
if (attemptInfo.nextAttempt.isValid())
|
||||
{
|
||||
assert(attemptInfo.nextAttempt <= now); // should not be called if throttled
|
||||
attemptInfo = {};
|
||||
}
|
||||
|
||||
attemptInfo.badConsecutiveAttemptCount += 1;
|
||||
attemptInfo.badConsecutiveAttemptCount += 1;
|
||||
|
||||
LMS_LOG(AUTH, DEBUG, "Registering bad attempt for '" << clientAddress.to_string() << "', consecutive bad attempts count = " << attemptInfo.badConsecutiveAttemptCount);
|
||||
if (attemptInfo.badConsecutiveAttemptCount >= _maxBadConsecutiveAttemptCount)
|
||||
{
|
||||
LMS_LOG(AUTH, DEBUG, "Throttling '" << clientAddress.to_string() << "'");
|
||||
attemptInfo.nextAttempt = now.addMSecs(std::chrono::duration_cast<std::chrono::milliseconds>(_throttlingDuration).count());
|
||||
}
|
||||
else
|
||||
{
|
||||
attemptInfo.nextAttempt = {};
|
||||
}
|
||||
}
|
||||
LMS_LOG(AUTH, DEBUG, "Registering bad attempt for '" << clientAddress.to_string() << "', consecutive bad attempts count = " << attemptInfo.badConsecutiveAttemptCount);
|
||||
if (attemptInfo.badConsecutiveAttemptCount >= _maxBadConsecutiveAttemptCount)
|
||||
{
|
||||
LMS_LOG(AUTH, DEBUG, "Throttling '" << clientAddress.to_string() << "'");
|
||||
attemptInfo.nextAttempt = now.addMSecs(std::chrono::duration_cast<std::chrono::milliseconds>(_throttlingDuration).count());
|
||||
}
|
||||
else
|
||||
{
|
||||
attemptInfo.nextAttempt = {};
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
LoginThrottler::onGoodClientAttempt(const boost::asio::ip::address& address)
|
||||
{
|
||||
const boost::asio::ip::address clientAddress {getAddressToThrottle(address)};
|
||||
void LoginThrottler::onGoodClientAttempt(const boost::asio::ip::address& address)
|
||||
{
|
||||
const boost::asio::ip::address clientAddress{ getAddressToThrottle(address) };
|
||||
|
||||
_attemptsInfo.erase(clientAddress);
|
||||
}
|
||||
_attemptsInfo.erase(clientAddress);
|
||||
}
|
||||
|
||||
bool
|
||||
LoginThrottler::isClientThrottled(const boost::asio::ip::address& address) const
|
||||
{
|
||||
const boost::asio::ip::address clientAddress {getAddressToThrottle(address)};
|
||||
bool LoginThrottler::isClientThrottled(const boost::asio::ip::address& address) const
|
||||
{
|
||||
const boost::asio::ip::address clientAddress{ getAddressToThrottle(address) };
|
||||
|
||||
auto it {_attemptsInfo.find(clientAddress)};
|
||||
if (it == _attemptsInfo.end())
|
||||
return false;
|
||||
auto it{ _attemptsInfo.find(clientAddress) };
|
||||
if (it == _attemptsInfo.end())
|
||||
return false;
|
||||
|
||||
if (!it->second.nextAttempt.isValid())
|
||||
return false;
|
||||
|
||||
return it->second.nextAttempt > Wt::WDateTime::currentDateTime();
|
||||
}
|
||||
|
||||
} // Auth
|
||||
if (!it->second.nextAttempt.isValid())
|
||||
return false;
|
||||
|
||||
return it->second.nextAttempt > Wt::WDateTime::currentDateTime();
|
||||
}
|
||||
}
|
||||
@@ -24,10 +24,10 @@
|
||||
|
||||
#include <Wt/WDateTime.h>
|
||||
|
||||
#include "utils/NetAddress.hpp"
|
||||
#include "utils/Exception.hpp"
|
||||
#include "core/NetAddress.hpp"
|
||||
#include "core/Exception.hpp"
|
||||
|
||||
namespace Auth
|
||||
namespace lms::auth
|
||||
{
|
||||
class LoginThrottler
|
||||
{
|
||||
|
||||
@@ -30,16 +30,15 @@
|
||||
#include "services/auth/Types.hpp"
|
||||
#include "database/Session.hpp"
|
||||
#include "database/User.hpp"
|
||||
#include "utils/Exception.hpp"
|
||||
#include "utils/ILogger.hpp"
|
||||
#include "core/Exception.hpp"
|
||||
#include "core/ILogger.hpp"
|
||||
|
||||
namespace Auth
|
||||
namespace lms::auth
|
||||
{
|
||||
|
||||
static const Wt::Auth::SHA1HashFunction sha1Function;
|
||||
|
||||
std::unique_ptr<IPasswordService>
|
||||
createPasswordService(std::string_view passwordAuthenticationBackend, Database::Db& db, std::size_t maxThrottlerEntries, IAuthTokenService& authTokenService)
|
||||
createPasswordService(std::string_view passwordAuthenticationBackend, db::Db& db, std::size_t maxThrottlerEntries, IAuthTokenService& authTokenService)
|
||||
{
|
||||
if (passwordAuthenticationBackend == "internal")
|
||||
return std::make_unique<InternalPasswordService>(db, maxThrottlerEntries, authTokenService);
|
||||
@@ -51,7 +50,7 @@ namespace Auth
|
||||
throw Exception {"Authentication backend '" + std::string {passwordAuthenticationBackend} + "' is not supported!"};
|
||||
}
|
||||
|
||||
PasswordServiceBase::PasswordServiceBase(Database::Db& db, std::size_t maxThrottlerEntries, IAuthTokenService& authTokenService)
|
||||
PasswordServiceBase::PasswordServiceBase(db::Db& db, std::size_t maxThrottlerEntries, IAuthTokenService& authTokenService)
|
||||
: AuthServiceBase {db}
|
||||
, _loginThrottler {maxThrottlerEntries}
|
||||
, _authTokenService {authTokenService}
|
||||
@@ -82,7 +81,7 @@ namespace Auth
|
||||
{
|
||||
_loginThrottler.onGoodClientAttempt(clientAddress);
|
||||
|
||||
const Database::UserId userId {getOrCreateUser(loginName)};
|
||||
const db::UserId userId {getOrCreateUser(loginName)};
|
||||
onUserAuthenticated(userId);
|
||||
return {CheckResult::State::Granted, userId};
|
||||
}
|
||||
@@ -93,5 +92,5 @@ namespace Auth
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace Auth
|
||||
} // namespace lms::auth
|
||||
|
||||
|
||||
@@ -25,19 +25,18 @@
|
||||
#include "AuthServiceBase.hpp"
|
||||
#include "LoginThrottler.hpp"
|
||||
|
||||
namespace Database
|
||||
namespace lms::db
|
||||
{
|
||||
class Db;
|
||||
class Session;
|
||||
}
|
||||
|
||||
namespace Auth
|
||||
namespace lms::auth
|
||||
{
|
||||
|
||||
class PasswordServiceBase : public IPasswordService, public AuthServiceBase
|
||||
{
|
||||
public:
|
||||
PasswordServiceBase(Database::Db& db, std::size_t maxThrottlerEntries, IAuthTokenService& authTokenService);
|
||||
PasswordServiceBase(db::Db& db, std::size_t maxThrottlerEntries, IAuthTokenService& authTokenService);
|
||||
|
||||
PasswordServiceBase(const PasswordServiceBase&) = delete;
|
||||
PasswordServiceBase& operator=(const PasswordServiceBase&) = delete;
|
||||
@@ -58,5 +57,4 @@ namespace Auth
|
||||
LoginThrottler _loginThrottler;
|
||||
IAuthTokenService& _authTokenService;
|
||||
};
|
||||
|
||||
} // namespace Auth
|
||||
}
|
||||
|
||||
@@ -21,15 +21,15 @@
|
||||
|
||||
#include <Wt/WEnvironment.h>
|
||||
|
||||
#include "utils/IConfig.hpp"
|
||||
#include "utils/ILogger.hpp"
|
||||
#include "utils/Service.hpp"
|
||||
#include "core/IConfig.hpp"
|
||||
#include "core/ILogger.hpp"
|
||||
#include "core/Service.hpp"
|
||||
|
||||
namespace Auth
|
||||
namespace lms::auth
|
||||
{
|
||||
HttpHeadersEnvService::HttpHeadersEnvService(Database::Db& db)
|
||||
HttpHeadersEnvService::HttpHeadersEnvService(db::Db& db)
|
||||
: AuthServiceBase{ db }
|
||||
, _fieldName{ Service<IConfig>::get()->getString("http-headers-login-field", "X-Forwarded-User") }
|
||||
, _fieldName{ core::Service<core::IConfig>::get()->getString("http-headers-login-field", "X-Forwarded-User") }
|
||||
{
|
||||
LMS_LOG(AUTH, INFO, "Using http header field = '" << _fieldName << "'");
|
||||
}
|
||||
@@ -42,7 +42,7 @@ namespace Auth
|
||||
|
||||
LMS_LOG(AUTH, DEBUG, "Extracted login name = '" << loginName << "' from HTTP header");
|
||||
|
||||
const Database::UserId userId{ getOrCreateUser(loginName) };
|
||||
const db::UserId userId{ getOrCreateUser(loginName) };
|
||||
onUserAuthenticated(userId);
|
||||
return { CheckResult::State::Granted, userId };
|
||||
}
|
||||
@@ -55,8 +55,8 @@ namespace Auth
|
||||
|
||||
LMS_LOG(AUTH, DEBUG, "Extracted login name = '" << loginName << "' from HTTP header");
|
||||
|
||||
const Database::UserId userId{ getOrCreateUser(loginName) };
|
||||
const db::UserId userId{ getOrCreateUser(loginName) };
|
||||
onUserAuthenticated(userId);
|
||||
return { CheckResult::State::Granted, userId };
|
||||
}
|
||||
} // namespace Auth
|
||||
} // namespace lms::auth
|
||||
|
||||
@@ -22,12 +22,12 @@
|
||||
#include "services/auth/IEnvService.hpp"
|
||||
#include "AuthServiceBase.hpp"
|
||||
|
||||
namespace Auth
|
||||
namespace lms::auth
|
||||
{
|
||||
class HttpHeadersEnvService : public IEnvService, public AuthServiceBase
|
||||
{
|
||||
public:
|
||||
HttpHeadersEnvService(Database::Db& db);
|
||||
HttpHeadersEnvService(db::Db& db);
|
||||
|
||||
private:
|
||||
CheckResult processEnv(const Wt::WEnvironment& env) override;
|
||||
@@ -36,5 +36,5 @@ namespace Auth
|
||||
std::string _fieldName;
|
||||
};
|
||||
|
||||
} // namespace Auth
|
||||
} // namespace lms::auth
|
||||
|
||||
|
||||
@@ -24,12 +24,12 @@
|
||||
#include "services/auth/Types.hpp"
|
||||
#include "database/Session.hpp"
|
||||
#include "database/User.hpp"
|
||||
#include "utils/Exception.hpp"
|
||||
#include "utils/ILogger.hpp"
|
||||
#include "core/Exception.hpp"
|
||||
#include "core/ILogger.hpp"
|
||||
|
||||
namespace Auth
|
||||
namespace lms::auth
|
||||
{
|
||||
InternalPasswordService::InternalPasswordService(Database::Db& db, std::size_t maxThrottlerEntries, IAuthTokenService& authTokenService)
|
||||
InternalPasswordService::InternalPasswordService(db::Db& db, std::size_t maxThrottlerEntries, IAuthTokenService& authTokenService)
|
||||
: PasswordServiceBase{ db, maxThrottlerEntries, authTokenService }
|
||||
{
|
||||
_validator.setMinimumLength(Wt::Auth::PasswordStrengthType::OneCharClass, 4);
|
||||
@@ -45,12 +45,12 @@ namespace Auth
|
||||
{
|
||||
LMS_LOG(AUTH, DEBUG, "Checking internal password for user '" << loginName << "'");
|
||||
|
||||
Database::User::PasswordHash passwordHash;
|
||||
db::User::PasswordHash passwordHash;
|
||||
{
|
||||
Database::Session& session{ getDbSession() };
|
||||
db::Session& session{ getDbSession() };
|
||||
auto transaction{ session.createReadTransaction() };
|
||||
|
||||
const Database::User::pointer user{ Database::User::find(session, loginName) };
|
||||
const db::User::pointer user{ db::User::find(session, loginName) };
|
||||
if (!user)
|
||||
{
|
||||
LMS_LOG(AUTH, DEBUG, "hashing random stuff");
|
||||
@@ -81,24 +81,24 @@ namespace Auth
|
||||
{
|
||||
switch (context.userType)
|
||||
{
|
||||
case Database::UserType::ADMIN:
|
||||
case Database::UserType::REGULAR:
|
||||
case db::UserType::ADMIN:
|
||||
case db::UserType::REGULAR:
|
||||
return _validator.evaluateStrength(std::string{ password }, context.loginName, "").isValid() ? PasswordAcceptabilityResult::OK : PasswordAcceptabilityResult::TooWeak;
|
||||
case Database::UserType::DEMO:
|
||||
case db::UserType::DEMO:
|
||||
return password == context.loginName ? PasswordAcceptabilityResult::OK : PasswordAcceptabilityResult::MustMatchLoginName;
|
||||
}
|
||||
|
||||
throw NotImplementedException{};
|
||||
}
|
||||
|
||||
void InternalPasswordService::setPassword(Database::UserId userId, std::string_view newPassword)
|
||||
void InternalPasswordService::setPassword(db::UserId userId, std::string_view newPassword)
|
||||
{
|
||||
const Database::User::PasswordHash passwordHash{ hashPassword(newPassword) };
|
||||
const db::User::PasswordHash passwordHash{ hashPassword(newPassword) };
|
||||
|
||||
Database::Session& session{ getDbSession() };
|
||||
db::Session& session{ getDbSession() };
|
||||
auto transaction{ session.createWriteTransaction() };
|
||||
|
||||
Database::User::pointer user{ Database::User::find(session, userId) };
|
||||
db::User::pointer user{ db::User::find(session, userId) };
|
||||
if (!user)
|
||||
throw Exception{ "User not found!" };
|
||||
|
||||
@@ -116,7 +116,7 @@ namespace Auth
|
||||
getAuthTokenService().clearAuthTokens(userId);
|
||||
}
|
||||
|
||||
Database::User::PasswordHash InternalPasswordService::hashPassword(std::string_view password) const
|
||||
db::User::PasswordHash InternalPasswordService::hashPassword(std::string_view password) const
|
||||
{
|
||||
const std::string salt{ Wt::WRandom::generateId(32) };
|
||||
|
||||
@@ -129,5 +129,5 @@ namespace Auth
|
||||
hashPassword(Wt::WRandom::generateId(32));
|
||||
}
|
||||
|
||||
} // namespace Auth
|
||||
} // namespace lms::auth
|
||||
|
||||
|
||||
@@ -26,23 +26,23 @@
|
||||
#include "PasswordServiceBase.hpp"
|
||||
#include "LoginThrottler.hpp"
|
||||
|
||||
namespace Auth
|
||||
namespace lms::auth
|
||||
{
|
||||
class IAuthTokenService;
|
||||
|
||||
class InternalPasswordService : public PasswordServiceBase
|
||||
{
|
||||
public:
|
||||
InternalPasswordService(Database::Db& db, std::size_t maxThrottlerEntries, IAuthTokenService& authTokenService);
|
||||
InternalPasswordService(db::Db& db, std::size_t maxThrottlerEntries, IAuthTokenService& authTokenService);
|
||||
|
||||
private:
|
||||
bool checkUserPassword(std::string_view loginName, std::string_view password) override;
|
||||
|
||||
bool canSetPasswords() const override;
|
||||
PasswordAcceptabilityResult checkPasswordAcceptability(std::string_view loginName, const PasswordValidationContext& context) const override;
|
||||
void setPassword(Database::UserId userId, std::string_view newPassword) override;
|
||||
void setPassword(db::UserId userId, std::string_view newPassword) override;
|
||||
|
||||
Database::User::PasswordHash hashPassword(std::string_view password) const;
|
||||
db::User::PasswordHash hashPassword(std::string_view password) const;
|
||||
void hashRandomPassword() const;
|
||||
|
||||
const Wt::Auth::BCryptHashFunction _hashFunc{ 7 }; // TODO parametrize this
|
||||
|
||||
@@ -28,9 +28,9 @@
|
||||
|
||||
#include "services/auth/Types.hpp"
|
||||
#include "database/Session.hpp"
|
||||
#include "utils/ILogger.hpp"
|
||||
#include "core/ILogger.hpp"
|
||||
|
||||
namespace Auth
|
||||
namespace lms::auth
|
||||
{
|
||||
namespace
|
||||
{
|
||||
@@ -191,10 +191,10 @@ namespace Auth
|
||||
throw NotImplementedException{};
|
||||
}
|
||||
|
||||
void PAMPasswordService::setPassword(Database::UserId, std::string_view)
|
||||
void PAMPasswordService::setPassword(db::UserId, std::string_view)
|
||||
{
|
||||
throw NotImplementedException{};
|
||||
}
|
||||
|
||||
} // namespace Auth
|
||||
} // namespace lms::auth
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
#include "PasswordServiceBase.hpp"
|
||||
|
||||
namespace Auth
|
||||
namespace lms::auth
|
||||
{
|
||||
class PAMPasswordService: public PasswordServiceBase
|
||||
{
|
||||
@@ -34,6 +34,6 @@ namespace Auth
|
||||
bool checkUserPassword(std::string_view loginName,std::string_view password) override;
|
||||
bool canSetPasswords() const override;
|
||||
PasswordAcceptabilityResult checkPasswordAcceptability(std::string_view loginName, const PasswordValidationContext& context) const override;
|
||||
void setPassword(Database::UserId userId, std::string_view newPassword) override;
|
||||
void setPassword(db::UserId userId, std::string_view newPassword) override;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -29,13 +29,13 @@
|
||||
|
||||
#include "database/UserId.hpp"
|
||||
|
||||
namespace Database
|
||||
namespace lms::db
|
||||
{
|
||||
class Db;
|
||||
class User;
|
||||
}
|
||||
|
||||
namespace Auth
|
||||
namespace lms::auth
|
||||
{
|
||||
class IAuthTokenService
|
||||
{
|
||||
@@ -54,7 +54,7 @@ namespace Auth
|
||||
|
||||
struct AuthTokenInfo
|
||||
{
|
||||
Database::UserId userId;
|
||||
db::UserId userId;
|
||||
Wt::WDateTime expiry;
|
||||
};
|
||||
|
||||
@@ -66,9 +66,9 @@ namespace Auth
|
||||
virtual AuthTokenProcessResult processAuthToken(const boost::asio::ip::address& clientAddress, std::string_view tokenValue) = 0;
|
||||
|
||||
// Returns a one time token
|
||||
virtual std::string createAuthToken(Database::UserId userid, const Wt::WDateTime& expiry) = 0;
|
||||
virtual void clearAuthTokens(Database::UserId userid) = 0;
|
||||
virtual std::string createAuthToken(db::UserId userid, const Wt::WDateTime& expiry) = 0;
|
||||
virtual void clearAuthTokens(db::UserId userid) = 0;
|
||||
};
|
||||
|
||||
std::unique_ptr<IAuthTokenService> createAuthTokenService(Database::Db& db, std::size_t maxThrottlerEntryCount);
|
||||
std::unique_ptr<IAuthTokenService> createAuthTokenService(db::Db& db, std::size_t maxThrottlerEntryCount);
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
#include "database/UserId.hpp"
|
||||
|
||||
namespace Database
|
||||
namespace lms::db
|
||||
{
|
||||
class Db;
|
||||
class Session;
|
||||
@@ -40,7 +40,7 @@ namespace Wt::Http
|
||||
class Request;
|
||||
}
|
||||
|
||||
namespace Auth
|
||||
namespace lms::auth
|
||||
{
|
||||
class IEnvService
|
||||
{
|
||||
@@ -58,12 +58,12 @@ namespace Auth
|
||||
};
|
||||
|
||||
State state {State::Denied};
|
||||
std::optional<Database::UserId> userId {};
|
||||
std::optional<db::UserId> userId {};
|
||||
};
|
||||
|
||||
virtual CheckResult processEnv(const Wt::WEnvironment& env) = 0;
|
||||
virtual CheckResult processRequest(const Wt::Http::Request& request) = 0;
|
||||
};
|
||||
|
||||
std::unique_ptr<IEnvService> createEnvService(std::string_view backendName, Database::Db& db);
|
||||
} // namespace Auth
|
||||
std::unique_ptr<IEnvService> createEnvService(std::string_view backendName, db::Db& db);
|
||||
} // namespace lms::auth
|
||||
|
||||
@@ -29,13 +29,13 @@
|
||||
#include "services/auth/Types.hpp"
|
||||
#include "database/UserId.hpp"
|
||||
|
||||
namespace Database
|
||||
namespace lms::db
|
||||
{
|
||||
class Db;
|
||||
class User;
|
||||
}
|
||||
|
||||
namespace Auth
|
||||
namespace lms::auth
|
||||
{
|
||||
|
||||
class IAuthTokenService;
|
||||
@@ -54,7 +54,7 @@ namespace Auth
|
||||
Throttled,
|
||||
};
|
||||
State state {State::Denied};
|
||||
std::optional<Database::UserId> userId {};
|
||||
std::optional<db::UserId> userId {};
|
||||
std::optional<Wt::WDateTime> expiry {};
|
||||
};
|
||||
virtual CheckResult checkUserPassword(const boost::asio::ip::address& clientAddress,
|
||||
@@ -70,9 +70,9 @@ namespace Auth
|
||||
MustMatchLoginName,
|
||||
};
|
||||
virtual PasswordAcceptabilityResult checkPasswordAcceptability(std::string_view password, const PasswordValidationContext& context) const = 0;
|
||||
virtual void setPassword(Database::UserId userId, std::string_view newPassword) = 0;
|
||||
virtual void setPassword(db::UserId userId, std::string_view newPassword) = 0;
|
||||
};
|
||||
|
||||
std::unique_ptr<IPasswordService> createPasswordService(std::string_view authPasswordBackend, Database::Db& db, std::size_t maxThrottlerEntryCount, IAuthTokenService& authTokenService);
|
||||
std::unique_ptr<IPasswordService> createPasswordService(std::string_view authPasswordBackend, db::Db& db, std::size_t maxThrottlerEntryCount, IAuthTokenService& authTokenService);
|
||||
}
|
||||
|
||||
|
||||
@@ -21,31 +21,31 @@
|
||||
|
||||
#include <string>
|
||||
#include "database/Types.hpp"
|
||||
#include "utils/Exception.hpp"
|
||||
#include "core/Exception.hpp"
|
||||
|
||||
namespace Auth
|
||||
namespace lms::auth
|
||||
{
|
||||
class Exception : public ::LmsException
|
||||
class Exception : public core::LmsException
|
||||
{
|
||||
using LmsException::LmsException;
|
||||
using core::LmsException::LmsException;
|
||||
};
|
||||
|
||||
class NotImplementedException : public Exception
|
||||
{
|
||||
public:
|
||||
NotImplementedException() : Auth::Exception {"Not implemented"} {}
|
||||
NotImplementedException() : Exception {"Not implemented"} {}
|
||||
};
|
||||
|
||||
class UserNotFoundException : public Exception
|
||||
{
|
||||
public:
|
||||
UserNotFoundException() : Auth::Exception {"User not found"} {}
|
||||
UserNotFoundException() : Exception {"User not found"} {}
|
||||
};
|
||||
|
||||
struct PasswordValidationContext
|
||||
{
|
||||
std::string loginName;
|
||||
Database::UserType userType;
|
||||
db::UserType userType;
|
||||
};
|
||||
|
||||
class PasswordException : public Exception
|
||||
|
||||
Reference in New Issue
Block a user