handlers: permisison check for all pages + retrieve user-specific permissions for pages (if any)

This commit is contained in:
Albert S. 2019-05-03 15:59:29 +02:00
parent 9c0dfd170e
commit 7d1cae24a9
24 changed files with 171 additions and 37 deletions

View File

@ -77,3 +77,18 @@ QueryOption Handler::queryOption(const Request &r) const
return result; return result;
} }
Response Handler::handle(const Request &r)
{
if(!canAccess(this->userSession->user.permissions))
{
return errorResponse("Permission denied", accessErrorMessage());
}
return handleRequest(r);
}
Permissions Handler::effectivePermissions(std::string page)
{
return this->database->createPermissionsDao()->find(page, this->userSession->user.login).value_or(this->userSession->user.permissions);
}

View File

@ -18,6 +18,8 @@ protected:
Session *userSession; Session *userSession;
UrlProvider *urlProvider; UrlProvider *urlProvider;
//TODO: may not to find a better place for this method
Permissions effectivePermissions(std::string page);
QueryOption queryOption(const Request &r) const; QueryOption queryOption(const Request &r) const;
public: public:
Handler(Template &templ, Database &db, Session &userSession, UrlProvider &provider, ICache &cache) Handler(Template &templ, Database &db, Session &userSession, UrlProvider &provider, ICache &cache)
@ -28,7 +30,19 @@ public:
this->urlProvider = &provider; this->urlProvider = &provider;
this->cache = &cache; this->cache = &cache;
} }
virtual Response handle(const Request &r) = 0;
virtual Response handle(const Request &r);
virtual Response handleRequest(const Request &r)
{
return this->errorResponse("Invalid action", "This action is not implemented yet");
}
virtual bool canAccess(const Permissions &perms) {
return false;
}
virtual std::string accessErrorMessage() {
return "No permission for this action";
}
void setGeneralVars(TemplatePage &page); void setGeneralVars(TemplatePage &page);
virtual ~Handler() { } virtual ~Handler() { }
Response errorResponse(std::string errortitle, std::string errormessage, int status = 200); Response errorResponse(std::string errortitle, std::string errormessage, int status = 200);

View File

@ -21,7 +21,7 @@ SOFTWARE.
#include "handlerallcategories.h" #include "handlerallcategories.h"
#include "../urlprovider.h" #include "../urlprovider.h"
#include "../logger.h" #include "../logger.h"
Response HandlerAllCategories::handle(const Request &r) Response HandlerAllCategories::handleRequest(const Request &r)
{ {
auto categoryDao = this->database->createCategoryDao(); auto categoryDao = this->database->createCategoryDao();
QueryOption qo = queryOption(r); QueryOption qo = queryOption(r);
@ -42,3 +42,13 @@ Response HandlerAllCategories::handle(const Request &r)
response.setStatus(200); response.setStatus(200);
return response; return response;
} }
std::string HandlerAllCategories::accessErrorMessage()
{
return "You don't have permission to list all categories";
}
bool HandlerAllCategories::canAccess(const Permissions &perms)
{
return perms.canSeeCategoryList();
}

View File

@ -9,7 +9,9 @@ class HandlerAllCategories : public Handler
public: public:
HandlerAllCategories(); HandlerAllCategories();
using Handler::Handler; using Handler::Handler;
Response handle(const Request &r) override; Response handleRequest(const Request &r) override;
std::string accessErrorMessage() override;
bool canAccess(const Permissions &perms) override;
}; };
#endif // HANDLERALLCATEGORIES_H #endif // HANDLERALLCATEGORIES_H

View File

@ -20,9 +20,7 @@ SOFTWARE.
*/ */
#include "handlerallpages.h" #include "handlerallpages.h"
Response HandlerAllPages::handleRequest(const Request &r)
Response HandlerAllPages::handle(const Request &r)
{ {
try try
{ {
@ -49,3 +47,14 @@ Response HandlerAllPages::handle(const Request &r)
} }
} }
std::string HandlerAllPages::accessErrorMessage()
{
return "You don't permissions to list all pages";
}
bool HandlerAllPages::canAccess(const Permissions &perms)
{
return perms.canSeePageList();
}

View File

@ -7,7 +7,9 @@ class HandlerAllPages : public Handler
public: public:
HandlerAllPages(); HandlerAllPages();
using Handler::Handler; using Handler::Handler;
Response handle(const Request &r) override; Response handleRequest(const Request &r) override;
std::string accessErrorMessage() override;
bool canAccess(const Permissions &perms) override;
}; };
#endif // HANDLERALLPAGES_H #endif // HANDLERALLPAGES_H

View File

@ -21,7 +21,7 @@ SOFTWARE.
#include "handlercategory.h" #include "handlercategory.h"
Response HandlerCategory::handle(const Request &r) Response HandlerCategory::handleRequest(const Request &r)
{ {
try try
{ {
@ -49,3 +49,13 @@ Response HandlerCategory::handle(const Request &r)
return errorResponse("Error", "An unknown error occured"); return errorResponse("Error", "An unknown error occured");
} }
} }
std::string HandlerCategory::accessErrorMessage()
{
return "You don't have permission to view categories";
}
bool HandlerCategory::canAccess(const Permissions &perms)
{
return perms.canRead(); //TODO: we may need a more specific permission
}

View File

@ -7,7 +7,9 @@ class HandlerCategory : public Handler
public: public:
HandlerCategory(); HandlerCategory();
using Handler::Handler; using Handler::Handler;
Response handle(const Request &r) override; Response handleRequest(const Request &r) override;
std::string accessErrorMessage() override;
bool canAccess(const Permissions &perms) override;
}; };
#endif // HANDLERCATEGORY_H #endif // HANDLERCATEGORY_H

View File

@ -21,7 +21,7 @@ SOFTWARE.
#include "handlerdefault.h" #include "handlerdefault.h"
Response HandlerDefault::handle(const Request &r) Response HandlerDefault::handleRequest(const Request &r)
{ {
return Response::redirectTemporarily(this->urlProvider->index()); return Response::redirectTemporarily(this->urlProvider->index());
} }
@ -30,3 +30,8 @@ HandlerDefault::~HandlerDefault()
{ {
} }
bool HandlerDefault::canAccess(const Permissions &perms)
{
return true;
}

View File

@ -5,9 +5,10 @@
class HandlerDefault : public Handler class HandlerDefault : public Handler
{ {
public: public:
Response handle(const Request &r) override; Response handleRequest(const Request &r) override;
~HandlerDefault() override; ~HandlerDefault() override;
using Handler::Handler; using Handler::Handler;
bool canAccess(const Permissions &perms) override;
}; };
#endif // HANDLERDEFAULT_H #endif // HANDLERDEFAULT_H

View File

@ -23,11 +23,28 @@ SOFTWARE.
#include "../htmllink.h" #include "../htmllink.h"
#include "../logger.h" #include "../logger.h"
#include "../database/exceptions.h" #include "../database/exceptions.h"
Response HandlerHistory::handle(const Request &r) Response HandlerHistory::handleRequest(const Request &r)
{ {
QueryOption qo = queryOption(r); QueryOption qo = queryOption(r);
std::string page = r.get("page"); std::string page = r.get("page");
if(page.empty())
{
if(!this->userSession->user.permissions.canSeeGlobalHistory())
{
return errorResponse("Permission denied", "You can't see the changes history on this wiki", 403);
}
}
else
{
Permissions perms = effectivePermissions(page);
if(!perms.canSeePageHistory())
{
return errorResponse("Permission denied", "You cannot see the changes history of this page", 403);
}
}
unsigned int count = 0; unsigned int count = 0;
std::vector<Revision> resultList; std::vector<Revision> resultList;
auto revisionDao = this->database->createRevisionDao(); auto revisionDao = this->database->createRevisionDao();
@ -104,3 +121,10 @@ Response HandlerHistory::handle(const Request &r)
response.setStatus(200); response.setStatus(200);
return response; return response;
} }
bool HandlerHistory::canAccess(const Permissions &perms)
{
return true; //This is a lie but we need to this a little more fine grained here, which we do in the handleRequest
}

View File

@ -8,7 +8,8 @@ class HandlerHistory : public Handler
public: public:
HandlerHistory(); HandlerHistory();
using Handler::Handler; using Handler::Handler;
Response handle(const Request &r) override; Response handleRequest(const Request &r) override;
bool canAccess(const Permissions &perms) override;
}; };
#endif // HANDLERHISTORY_H #endif // HANDLERHISTORY_H

View File

@ -21,7 +21,12 @@ SOFTWARE.
#include "handlerinvalidaction.h" #include "handlerinvalidaction.h"
Response HandlerInvalidAction::handle(const Request &r) Response HandlerInvalidAction::handleRequest(const Request &r)
{ {
return errorResponse("Invalid action", "No action defined for this action"); return errorResponse("Invalid action", "No action defined for this action");
} }
bool HandlerInvalidAction::canAccess(const Permissions &perms)
{
return true;
}

View File

@ -5,8 +5,9 @@
class HandlerInvalidAction : public Handler class HandlerInvalidAction : public Handler
{ {
public: public:
Response handle(const Request &r) override; Response handleRequest(const Request &r) override;
~HandlerInvalidAction() override { } ~HandlerInvalidAction() override { }
bool canAccess(const Permissions &perms) override;
using Handler::Handler; using Handler::Handler;
}; };

View File

@ -66,7 +66,7 @@ std::vector<char> HandlerLogin::pbkdf5(std::string password, const std::vector<c
} }
Response HandlerLogin::handle(const Request &r) Response HandlerLogin::handleRequest(const Request &r)
{ {
auto createErrorReesponse = [&]() { return errorResponse("Login error", "The supplied credenetials are incorrect"); }; auto createErrorReesponse = [&]() { return errorResponse("Login error", "The supplied credenetials are incorrect"); };
@ -85,6 +85,10 @@ Response HandlerLogin::handle(const Request &r)
{ {
return createErrorReesponse(); return createErrorReesponse();
} }
if(!user->enabled)
{
return errorResponse("Login failed", "The user account has been disabled");
}
auto hashresult = pbkdf5(password, user.value().salt); auto hashresult = pbkdf5(password, user.value().salt);
//TODO: timing attack //TODO: timing attack
@ -121,3 +125,8 @@ Response HandlerLogin::handle(const Request &r)
result.setBody(loginTemplatePage.render()); result.setBody(loginTemplatePage.render());
return result; return result;
} }
bool HandlerLogin::canAccess(const Permissions &perms)
{
return true;
}

View File

@ -11,8 +11,9 @@ private:
std::vector<char> pbkdf5(std::string password, const std::vector<char> &salt); std::vector<char> pbkdf5(std::string password, const std::vector<char> &salt);
public: public:
HandlerLogin(); HandlerLogin();
Response handle(const Request &r) override; Response handleRequest(const Request &r) override;
~HandlerLogin() override { } ~HandlerLogin() override { }
bool canAccess(const Permissions &perms) override;
using Handler::Handler; using Handler::Handler;
}; };

View File

@ -18,6 +18,7 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
*/ */
#include <optional>
#include "handlerpage.h" #include "handlerpage.h"
@ -92,3 +93,5 @@ void HandlerPage::setPageVars(TemplatePage &page, std::string pagename)
} }

View File

@ -11,7 +11,7 @@ protected:
public: public:
Response handle(const Request &r) override; Response handle(const Request &r) override;
virtual Response handleRequest(PageDao &pageDao, std::string pagename, const Request &r) =0; virtual Response handleRequest(PageDao &pageDao, std::string pagename, const Request &r) = 0;
~HandlerPage() override { } ~HandlerPage() override { }
using Handler::Handler; using Handler::Handler;

View File

@ -21,6 +21,21 @@ SOFTWARE.
#include "handlerpagedelete.h" #include "handlerpagedelete.h"
#include "../database/exceptions.h" #include "../database/exceptions.h"
bool HandlerPageDelete::pageMustExist()
{
return true;
}
bool HandlerPageDelete::canAccess(std::string page)
{
return effectivePermissions(page).canDelete();
}
std::string HandlerPageDelete::accessErrorMessage()
{
return "You don't have permission to delete pages";
}
Response HandlerPageDelete::handleRequest(PageDao &pageDao, std::string pagename, const Request &r) Response HandlerPageDelete::handleRequest(PageDao &pageDao, std::string pagename, const Request &r)
{ {
try try

View File

@ -4,20 +4,11 @@
class HandlerPageDelete : public HandlerPage class HandlerPageDelete : public HandlerPage
{ {
bool pageMustExist() override bool pageMustExist() override;
{
return true;
}
bool canAccess(std::string page) override bool canAccess(std::string page) override;
{
return this->userSession->user.permissions.canDelete();
}
std::string accessErrorMessage() override std::string accessErrorMessage() override;
{
return "You don't have permission to delete pages";
}
public: public:
Response handleRequest(PageDao &pageDao, std::string pagename, const Request &r) override; Response handleRequest(PageDao &pageDao, std::string pagename, const Request &r) override;
using HandlerPage::HandlerPage; using HandlerPage::HandlerPage;

View File

@ -26,7 +26,12 @@ SOFTWARE.
bool HandlerPageView::canAccess(std::string page) bool HandlerPageView::canAccess(std::string page)
{ {
return this->userSession->user.permissions.canRead(); return effectivePermissions(page).canRead();
}
std::string HandlerPageView::accessErrorMessage()
{
return "You don't have permission to view this page";
} }
std::string HandlerPageView::createIndexContent(IParser &parser, std::string content) std::string HandlerPageView::createIndexContent(IParser &parser, std::string content)

View File

@ -9,10 +9,7 @@ class HandlerPageView : public HandlerPage
{ {
protected: protected:
bool canAccess(std::string page) override; bool canAccess(std::string page) override;
std::string accessErrorMessage() override std::string accessErrorMessage() override;
{
return "You don't have permission to view this page";
}
std::string createIndexContent(IParser &parser, std::string content); std::string createIndexContent(IParser &parser, std::string content);
public: public:

View File

@ -19,7 +19,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
*/ */
#include "handlersearch.h" #include "handlersearch.h"
Response HandlerSearch::handle(const Request &r) Response HandlerSearch::handleRequest(const Request &r)
{ {
Response response; Response response;
std::string q = r.get("q"); std::string q = r.get("q");
@ -61,3 +61,13 @@ Response HandlerSearch::handle(const Request &r)
} }
bool HandlerSearch::canAccess(const Permissions &perms)
{
return perms.canSearch();
}
std::string HandlerSearch::accessErrorMessage()
{
return "You are not allowed to search this wiki";
}

View File

@ -7,7 +7,9 @@ class HandlerSearch : public Handler
public: public:
HandlerSearch(); HandlerSearch();
using Handler::Handler; using Handler::Handler;
Response handle(const Request &r) override; Response handleRequest(const Request &r) override;
bool canAccess(const Permissions &perms) override;
std::string accessErrorMessage();
}; };
#endif // HANDLERSEARCH_H #endif // HANDLERSEARCH_H