Commit 2794d1ed authored by Markus Mößler's avatar Markus Mößler
Browse files

added endpoints for registration, login and logout, as well as xsrf cookie handling

parent 4f7f2562
Loading
Loading
Loading
Loading
+99 −1
Original line number Diff line number Diff line
@@ -28,6 +28,12 @@ import tornado.web
import tornado.locks
import unicodedata

import json
import logging
# Configure logging
logging.basicConfig(level=logging.DEBUG,
                    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')

from tornado.options import define, options

define("port", default=8888, help="run on the given port", type=int)
@@ -67,6 +73,10 @@ class Application(tornado.web.Application):
            (r"/auth/login", AuthLoginHandler),
            (r"/auth/logout", AuthLogoutHandler),
            (r"/tornado-backend/message", APIHandler),
            (r"/tornado-backend/register", AuthorRegisterHandler),
            (r"/tornado-backend/login", AuthorLoginHandler),
            (r"/tornado-backend/logout", AuthLogoutHandler),
            (r"/tornado-backend/get-user-role", GetUserRoleHandler),
        ]
        settings = dict(
            blog_title="Tornado Blog",
@@ -126,6 +136,11 @@ class BaseHandler(tornado.web.RequestHandler):
        return results[0]

    async def prepare(self):

        # Ensure XSRF cookie is set with a correct path
        if not self.get_secure_cookie("_xsrf"):
            self.xsrf_token  # This will set the _xsrf cookie

        # get_current_user cannot be a coroutine, so set
        # self.current_user in prepare instead.
        # user_id = self.get_signed_cookie("blogdemo_user")
@@ -302,6 +317,89 @@ class APIHandler(tornado.web.RequestHandler):
        self.write({"message": "Hello from Tornado Backend!"})


class AuthorRegisterHandler(BaseHandler):
    async def post(self):
        logging.info(f"Hello from registration handler!")
        # Parse JSON data from request body
        data = json.loads(self.request.body)
        email = data.get("email")
        name = data.get("name")
        password = data.get("password")                                
        hashed_password = await tornado.ioloop.IOLoop.current().run_in_executor(
            None,
            bcrypt.hashpw,
            tornado.escape.utf8(password),
            bcrypt.gensalt(),
        )        
        author = await self.queryone(
            "INSERT INTO authors (email, name, hashed_password) "
            "VALUES (%s, %s, %s) RETURNING id",
            email,
            name,
            tornado.escape.to_unicode(hashed_password),
        )
        self.write({"message": "Author registered successfully"})
    

class AuthorLoginHandler(BaseHandler):
    async def get(self):
        if not await self.any_author_exists():
            self.status(404)
            self.write({"message": "No author exists"})
        else:
            self.write({"message": "Authors exists"})

    async def post(self):
        try:
            data = json.loads(self.request.body)
            email = data.get("email")
            password = data.get("password")
            
            author = await self.queryone(
                "SELECT * FROM authors WHERE email = %s", email
            )
        except NoResultError:
            self.status(404)
            self.write({"message": "Author does not exist"})
            return
        
        password_equal = await tornado.ioloop.IOLoop.current().run_in_executor(
            None,
            bcrypt.checkpw,
            tornado.escape.utf8(password),
            tornado.escape.utf8(author.hashed_password),
        )
        if password_equal:
            # self.set_signed_cookie("blogdemo_user", str(author.id))
            self.set_secure_cookie("blogdemo_user", str(author.id))
            # self.set_cookie("blogdemo_user", str(author.id))
            self.set_status(200)
            self.write({"message": "Login successful"})                
        else:
            self.set_status(401)
            self.write({"message": "Incorrect email or password"})                


class AuthLogoutHandler(BaseHandler):
    def get(self):
        self.clear_cookie("blogdemo_user")
        self.write({"message": "Logout successful"}) 


class GetUserRoleHandler(BaseHandler): 
    async def get(self):
        user_id = self.get_secure_cookie("blogdemo_user")
        logging.info(user_id)
        if user_id:
            user_role = "author"
            self.write({"role": user_role})
        else:
            # self.set_status(401)
            self.write({"message": "Not logged in!"})
            self.finish() 
        return


async def main():
    tornado.options.parse_command_line()