From 08df6527be62e9939ef3c0a0396bdac74c3b6e67 Mon Sep 17 00:00:00 2001 From: Michael Tremer Date: Sat, 1 Sep 2018 13:50:21 +0100 Subject: [PATCH] Refactor authentication Signed-off-by: Michael Tremer --- Makefile.am | 6 ++++ src/web/__init__.py | 7 +++-- src/web/auth.py | 67 ++++++++++++++++++++++++++++++++++++++++ src/web/handlers_base.py | 60 ----------------------------------- 4 files changed, 77 insertions(+), 63 deletions(-) create mode 100644 src/web/auth.py diff --git a/Makefile.am b/Makefile.am index 0e4719e7..2eae162e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -74,6 +74,7 @@ backenddir = $(pythondir)/ipfire web_PYTHON = \ src/web/__init__.py \ + src/web/auth.py \ src/web/blog.py \ src/web/download.py \ src/web/handlers.py \ @@ -103,6 +104,11 @@ templates_DATA = \ templatesdir = $(datadir)/templates +templates_auth_DATA = \ + src/templates/auth/login.html + +templates_authdir = $(templatesdir)/auth + templates_blog_DATA = \ src/templates/blog/author.html \ src/templates/blog/base.html \ diff --git a/src/web/__init__.py b/src/web/__init__.py index 6c3d5479..1089ed8f 100644 --- a/src/web/__init__.py +++ b/src/web/__init__.py @@ -10,6 +10,7 @@ import ipfire from handlers import * +from . import auth from . import blog from . import download from . import location @@ -79,8 +80,8 @@ class Application(tornado.web.Application): tornado.web.Application.__init__(self, **settings) authentication_handlers = [ - (r"/login", LoginHandler), - (r"/logout", LogoutHandler), + (r"/login", auth.LoginHandler), + (r"/logout", auth.LogoutHandler), ] self.add_handlers(r"(dev|www)\.ipfire\.(at|org)", [ @@ -130,7 +131,7 @@ class Application(tornado.web.Application): # RSS Feed (r"/feed.xml", blog.FeedHandler), - ]) + ] + authentication_handlers) # downloads.ipfire.org self.add_handlers(r"downloads?(\.dev)?\.ipfire\.org", [ diff --git a/src/web/auth.py b/src/web/auth.py new file mode 100644 index 00000000..795a05c9 --- /dev/null +++ b/src/web/auth.py @@ -0,0 +1,67 @@ +#!/usr/bin/python + +import logging +import tornado.web + +from . import handlers_base as base + +class AuthenticationMixin(object): + def login(self, username, password): + # Find account + account = self.backend.accounts.find_account(username) + if not account: + raise tornado.web.HTTPError(401, "Unknown user: %s" % username) + + # Check credentials + if not account.check_password(password): + raise tornado.web.HTTPError(401, "Invalid password for %s" % account) + + # User has logged in, create a session + session_id, session_expires = self.backend.accounts.create_session( + account, self.request.host) + + # Check if a new session was created + if not session_id: + raise tornado.web.HTTPError(500, "Could not create session") + + # Send session cookie to the client + self.set_cookie("session_id", session_id, + domain=self.request.host, expires=session_expires) + + def logout(self): + session_id = self.get_cookie("session_id") + if not session_id: + return + + success = self.backend.accounts.destroy_session(session_id, self.request.host) + if success: + self.clear_cookie("session_id") + + + +class LoginHandler(AuthenticationMixin, base.BaseHandler): + def get(self): + next = self.get_argument("next", None) + + self.render("auth/login.html", next=next) + + def post(self): + username = self.get_argument("username") + password = self.get_argument("password") + + with self.db.transaction(): + self.login(username, password) + + # Determine the page we should redirect to + next = self.get_argument("next", None) + + return self.redirect(next or "/") + + +class LogoutHandler(AuthenticationMixin, base.BaseHandler): + def get(self): + with self.db.transaction(): + self.logout() + + # Get back to the start page + self.redirect("/") diff --git a/src/web/handlers_base.py b/src/web/handlers_base.py index d75b0509..d435c1c8 100644 --- a/src/web/handlers_base.py +++ b/src/web/handlers_base.py @@ -109,43 +109,6 @@ class BaseHandler(tornado.web.RequestHandler): return account - def login(self, username, password): - # Find account - account = self.backend.accounts.find_account(username) - if not account: - logging.warning(401, "unknown account: %s" % username) - return False - - # Check credentials - if not account.check_password(password): - logging.warning("invalid password for %s" % account) - return False - - # User has logged in, create a session - session_id, session_expires = self.backend.accounts.create_session(account, - self.request.host) - - # Check if a new session was created - if not session_id: - logging.warning("Could not create session") - return False - - # Send session cookie to the client - self.set_cookie("session_id", session_id, - domain=self.request.host, expires=session_expires) - - return True - - def logout(self): - session_id = self.get_cookie("session_id") - - if not session_id: - return - - success = self.backend.accounts.destroy_session(session_id, self.request.host) - if success: - self.clear_cookie("session_id") - @property def backend(self): return self.application.backend @@ -195,29 +158,6 @@ class BaseHandler(tornado.web.RequestHandler): return self.backend.talk -class LoginHandler(BaseHandler): - def get(self): - self.render("auth/login.html") - - def post(self): - username = self.get_argument("username") - password = self.get_argument("password") - - if not self.login(username, password): - raise tornado.web.HTTPError(401) - - next = self.get_argument("next", "/") - return self.redirect(next) - - -class LogoutHandler(BaseHandler): - def get(self): - self.logout() - - # Get back to the start page - self.redirect("/") - - class NotFoundHandler(BaseHandler): def prepare(self): # Raises 404 as soon as it is called -- 2.39.2