WIP: feature/authenticator #22

Fechado
crtxcr quer aplicar o merge de 2 commits de feature/authenticator em master
4 arquivos alterados com 89 adições e 15 exclusões

Ver arquivo

@ -32,6 +32,7 @@ SOFTWARE.
#include "handlercategory.h"
#include "handlerhistory.h"
#include "handlerpagedelete.h"
#include "handlerusersettings.h"
std::unique_ptr<Handler> HandlerFactory::createHandler(const std::string &action, Session &userSession)
{
@ -75,6 +76,10 @@ std::unique_ptr<Handler> HandlerFactory::createHandler(const std::string &action
{
return produce<HandlerHistory>(userSession);
}
if(action == "usersettings")
{
return produce<HandlerUserSettings>(userSession);
}
return produce<HandlerInvalidAction>(userSession);
}

Ver arquivo

@ -0,0 +1,71 @@
#include "handlerusersettings.h"
#include "../authenticator.h"
#include "../random.h"
Response HandlerUserSettings::handleRequest(const Request &r)
{
if(r.getRequestMethod() == "POST")
{
if(r.post("do") == "submit")
{
std::string oldpassword = r.post("oldpassword");
std::string newpassword = r.post("newpassword");
std::string newpasswordconfirm = r.post("newpasswordconfirm");
if(newpassword != newpasswordconfirm)
{
//TODO: is not nice, users has to hit the back button...
return this->errorResponse("Passwords don't match", "The entered new passwords don't match");
}
auto userDao = this->database->createUserDao();
Authenticator authenticator(*userDao);
std::variant<User, AuthenticationError> authresult = authenticator.authenticate(this->userSession->user.login, oldpassword);
if(std::holds_alternative<AuthenticationError>(authresult))
{
return this->errorResponse("Invalid current password", "The old password you entered is invalid");
}
Random r;
std::vector<char> salt = r.getRandom(23);
User user = std::get<User>(authresult);
user.salt = salt;
user.password = authenticator.hash(newpassword, user.salt);
if(user.password.empty())
{
Logger::error() << "Authenticator pbkdf5 returned emptys hash";
return this->errorResponse("Error", "An error occured while trying to store new password");
}
try
{
userDao->save(user);
}
catch(const DatabaseException &e)
{
Logger::debug() << "Error saving user: " << e.what();
return errorResponse("Error", "A database error occured while trying to save user with new settings");
}
return Response::redirectTemporarily(this->urlProvider->userSettings());
}
}
TemplatePage &userSettingsPage = this->templ->getPage("usersettings");
setGeneralVars(userSettingsPage);
userSettingsPage.setVar("usersettingsurl", urlProvider->userSettings());
userSettingsPage.setVar("title", createPageTitle("User settings - " + this->userSession->user.login));
Response result;
result.setStatus(200);
result.setBody(userSettingsPage.render());
return result;
}
bool HandlerUserSettings::canAccess(const Permissions &perms)
{
return this->userSession->loggedIn;
}
std::string HandlerUserSettings::accessErrorMessage()
{
return "Only logged-in users can change their settings";
}

13
handlers/handlerusersettings.h Arquivo normal
Ver arquivo

@ -0,0 +1,13 @@
#ifndef HANDLERUSERSETTINGS_H
#define HANDLERUSERSETTINGS_H
#include "handler.h"
class HandlerUserSettings : public Handler
{
public:
using Handler::Handler;
Response handleRequest(const Request &r);
bool canAccess(const Permissions &perms);
std::string accessErrorMessage();
};
#endif // HANDLERUSERSETTINGS_H

Ver arquivo

@ -1,15 +0,0 @@
{qswiki:include:general_header}
<main id="content">
<h2>Login</h2>
Change your current password
<form action="{qswiki:var:userchangepwurl}" method="POST">
Current password: <input type="text" name="password" style="width: 25%;"></input><br>
New Password: <input type="password" name="newpassword" style="width: 25%;"></input><br>
Repeat password: <input type="password" name="newpassword2" style="width: 25%;"></input><br>
<button type="submit" name="do" value="submit">Submit</button>
<input type="hidden" name="csrf_token" value="{qswiki:var:csrf_token}"></input>
</form>
</main>
{qswiki:include:general_footer}