Centralized demo account logic in the password auth service. ref #167
This commit is contained in:
@@ -80,16 +80,16 @@ namespace Auth
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
InternalPasswordService::isPasswordSecureEnough(std::string_view password, const PasswordValidationContext& context) const
|
||||
IPasswordService::PasswordAcceptabilityResult
|
||||
InternalPasswordService::checkPasswordAcceptability(std::string_view password, const PasswordValidationContext& context) const
|
||||
{
|
||||
switch (context.userType)
|
||||
{
|
||||
case Database::UserType::ADMIN:
|
||||
case Database::UserType::REGULAR:
|
||||
return _validator.evaluateStrength(std::string {password}, context.loginName, "").isValid();
|
||||
return _validator.evaluateStrength(std::string {password}, context.loginName, "").isValid() ? PasswordAcceptabilityResult::OK : PasswordAcceptabilityResult::TooWeak;
|
||||
case Database::UserType::DEMO:
|
||||
return true; // no constraint
|
||||
return password == context.loginName ? PasswordAcceptabilityResult::OK : PasswordAcceptabilityResult::MustMatchLoginName;
|
||||
}
|
||||
|
||||
throw NotImplementedException {};
|
||||
@@ -106,8 +106,15 @@ namespace Auth
|
||||
if (!user)
|
||||
throw Exception {"User not found!"};
|
||||
|
||||
if (!isPasswordSecureEnough(newPassword, PasswordValidationContext {user->getLoginName(), user->getType()} ))
|
||||
throw PasswordTooWeakException {};
|
||||
switch (checkPasswordAcceptability(newPassword, PasswordValidationContext {user->getLoginName(), user->getType()}))
|
||||
{
|
||||
case PasswordAcceptabilityResult::OK:
|
||||
break;
|
||||
case PasswordAcceptabilityResult::TooWeak:
|
||||
throw PasswordTooWeakException {};
|
||||
case PasswordAcceptabilityResult::MustMatchLoginName:
|
||||
throw PasswordMustMatchLoginNameException {};
|
||||
}
|
||||
|
||||
user.modify()->setPasswordHash(passwordHash);
|
||||
getAuthTokenService().clearAuthTokens(session, userId);
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace Auth
|
||||
std::string_view password) override;
|
||||
|
||||
bool canSetPasswords() const override;
|
||||
bool isPasswordSecureEnough(std::string_view loginName, const PasswordValidationContext& context) const override;
|
||||
PasswordAcceptabilityResult checkPasswordAcceptability(std::string_view loginName, const PasswordValidationContext& context) const override;
|
||||
void setPassword(Database::Session& session, Database::IdType userId, std::string_view newPassword) override;
|
||||
|
||||
Database::User::PasswordHash hashPassword(std::string_view password) const;
|
||||
|
||||
@@ -186,8 +186,8 @@ namespace Auth
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
PAMPasswordService::isPasswordSecureEnough(std::string_view, const PasswordValidationContext&) const
|
||||
IPasswordService::PasswordAcceptabilityResult
|
||||
PAMPasswordService::checkPasswordAcceptability(std::string_view, const PasswordValidationContext&) const
|
||||
{
|
||||
throw NotImplementedException {};
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace Auth
|
||||
std::string_view password) override;
|
||||
|
||||
bool canSetPasswords() const override;
|
||||
bool isPasswordSecureEnough(std::string_view loginName, const PasswordValidationContext& context) const override;
|
||||
PasswordAcceptabilityResult checkPasswordAcceptability(std::string_view loginName, const PasswordValidationContext& context) const override;
|
||||
void setPassword(Database::Session& session,
|
||||
Database::IdType userId,
|
||||
std::string_view newPassword) override;
|
||||
|
||||
@@ -56,15 +56,21 @@ namespace Auth
|
||||
std::optional<Database::IdType> userId {};
|
||||
std::optional<Wt::WDateTime> expiry {};
|
||||
};
|
||||
virtual CheckResult checkUserPassword(Database::Session& session,
|
||||
const boost::asio::ip::address& clientAddress,
|
||||
std::string_view loginName,
|
||||
std::string_view password) = 0;
|
||||
virtual CheckResult checkUserPassword(Database::Session& session,
|
||||
const boost::asio::ip::address& clientAddress,
|
||||
std::string_view loginName,
|
||||
std::string_view password) = 0;
|
||||
|
||||
virtual bool canSetPasswords() const = 0;
|
||||
virtual bool canSetPasswords() const = 0;
|
||||
|
||||
virtual bool isPasswordSecureEnough(std::string_view password, const PasswordValidationContext& context) const = 0;
|
||||
virtual void setPassword(Database::Session& session, Database::IdType userId, std::string_view newPassword) = 0;
|
||||
enum class PasswordAcceptabilityResult
|
||||
{
|
||||
OK,
|
||||
TooWeak,
|
||||
MustMatchLoginName,
|
||||
};
|
||||
virtual PasswordAcceptabilityResult checkPasswordAcceptability(std::string_view password, const PasswordValidationContext& context) const = 0;
|
||||
virtual void setPassword(Database::Session& session, Database::IdType userId, std::string_view newPassword) = 0;
|
||||
};
|
||||
|
||||
std::unique_ptr<IPasswordService> createPasswordService(std::string_view authPasswordBackend, std::size_t maxThrottlerEntryCount, IAuthTokenService& authTokenService);
|
||||
|
||||
@@ -36,16 +36,34 @@ namespace Auth
|
||||
NotImplementedException() : Auth::Exception {"Not implemented"} {}
|
||||
};
|
||||
|
||||
class UserNotFoundException : public Exception
|
||||
{
|
||||
public:
|
||||
UserNotFoundException() : Auth::Exception {"User not found"} {}
|
||||
};
|
||||
|
||||
struct PasswordValidationContext
|
||||
{
|
||||
std::string loginName;
|
||||
Database::UserType userType;
|
||||
};
|
||||
|
||||
class PasswordTooWeakException : public Exception
|
||||
class PasswordException : public Exception
|
||||
{
|
||||
public:
|
||||
PasswordTooWeakException() : Auth::Exception {"Password too weak"} {}
|
||||
using Exception::Exception;
|
||||
};
|
||||
|
||||
class PasswordTooWeakException : public PasswordException
|
||||
{
|
||||
public:
|
||||
PasswordTooWeakException() : PasswordException {"Password too weak"} {}
|
||||
};
|
||||
|
||||
class PasswordMustMatchLoginNameException : public PasswordException
|
||||
{
|
||||
public:
|
||||
PasswordMustMatchLoginNameException() : PasswordException {"Password must match login name"} {}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -559,11 +559,15 @@ handleChangePassword(RequestContext& context)
|
||||
|
||||
Service<Auth::IPasswordService>::get()->setPassword(context.dbSession, userId, password);
|
||||
}
|
||||
catch (Auth::PasswordTooWeakException&)
|
||||
catch (const Auth::PasswordMustMatchLoginNameException&)
|
||||
{
|
||||
throw PasswordMustMatchLoginNameGenericError {};
|
||||
}
|
||||
catch (const Auth::PasswordTooWeakException&)
|
||||
{
|
||||
throw PasswordTooWeakGenericError {};
|
||||
}
|
||||
catch (Auth::Exception& authException)
|
||||
catch (const Auth::Exception& authException)
|
||||
{
|
||||
throw UserNotAuthorizedError {};
|
||||
}
|
||||
@@ -658,6 +662,11 @@ handleCreateUserRequest(RequestContext& context)
|
||||
{
|
||||
Service<Auth::IPasswordService>::get()->setPassword(context.dbSession, userId, password);
|
||||
}
|
||||
catch (const Auth::PasswordMustMatchLoginNameException&)
|
||||
{
|
||||
removeCreatedUser();
|
||||
throw PasswordMustMatchLoginNameGenericError {};
|
||||
}
|
||||
catch (const Auth::PasswordTooWeakException&)
|
||||
{
|
||||
removeCreatedUser();
|
||||
@@ -1711,6 +1720,10 @@ handleUpdateUserRequest(RequestContext& context)
|
||||
{
|
||||
Service<::Auth::IPasswordService>()->setPassword(context.dbSession, userId, decodePasswordIfNeeded(*password));
|
||||
}
|
||||
catch (const Auth::PasswordMustMatchLoginNameException&)
|
||||
{
|
||||
throw PasswordMustMatchLoginNameGenericError {};
|
||||
}
|
||||
catch (const Auth::PasswordTooWeakException&)
|
||||
{
|
||||
throw PasswordTooWeakGenericError {};
|
||||
|
||||
@@ -152,6 +152,11 @@ class PasswordTooWeakGenericError : public GenericError
|
||||
std::string getMessage() const override { return "Password too weak"; }
|
||||
};
|
||||
|
||||
class PasswordMustMatchLoginNameGenericError : public GenericError
|
||||
{
|
||||
std::string getMessage() const override { return "Password must match login name"; }
|
||||
};
|
||||
|
||||
class DemoUserCannotChangePasswordGenericError : public GenericError
|
||||
{
|
||||
std::string getMessage() const override { return "Demo user cannot change its password"; }
|
||||
|
||||
Reference in New Issue
Block a user