implement login + logout routes and templates

+ Added route: GET `/login` via `aurweb.routers.auth.login_get`
+ Added route: POST `/login` via `aurweb.routers.auth.login_post`
+ Added route: GET `/logout` via `aurweb.routers.auth.logout`
+ Added route: POST `/logout` via `aurweb.routers.auth.logout_post`
* Modify archdev-navbar.html template to toggle displays on auth state
+ Added login.html template

Signed-off-by: Kevin Morris <kevr@0cost.org>
This commit is contained in:
Kevin Morris 2020-12-31 20:44:59 -08:00
parent 56f2798279
commit 5d4a5deddf
5 changed files with 313 additions and 3 deletions

View file

@ -11,7 +11,7 @@ import aurweb.config
from aurweb.auth import BasicAuthBackend
from aurweb.db import get_engine
from aurweb.routers import html, sso, errors
from aurweb.routers import auth, html, sso, errors
routes = set()
@ -42,6 +42,7 @@ async def app_startup():
# Add application routes.
app.include_router(sso.router)
app.include_router(html.router)
app.include_router(auth.router)
# Initialize the database engine and ORM.
get_engine()

85
aurweb/routers/auth.py Normal file
View file

@ -0,0 +1,85 @@
from datetime import datetime
from http import HTTPStatus
from fastapi import APIRouter, Form, Request
from fastapi.responses import HTMLResponse, RedirectResponse
import aurweb.config
from aurweb.models.user import User
from aurweb.templates import make_context, render_template
router = APIRouter()
def login_template(request: Request, next: str, errors: list = None):
""" Provide login-specific template context to render_template. """
context = make_context(request, "Login", next)
context["errors"] = errors
context["url_base"] = f"{request.url.scheme}://{request.url.netloc}"
return render_template("login.html", context)
@router.get("/login", response_class=HTMLResponse)
async def login_get(request: Request, next: str = "/"):
""" Homepage route. """
return login_template(request, next)
@router.post("/login", response_class=HTMLResponse)
async def login_post(request: Request,
next: str = Form(...),
user: str = Form(default=str()),
passwd: str = Form(default=str()),
remember_me: bool = Form(default=False)):
from aurweb.db import session
user = session.query(User).filter(User.Username == user).first()
if not user:
return login_template(request, next,
errors=["Bad username or password."])
cookie_timeout = 0
if remember_me:
cookie_timeout = aurweb.config.getint(
"options", "persistent_cookie_timeout")
_, sid = user.login(request, passwd, cookie_timeout)
if not _:
return login_template(request, next,
errors=["Bad username or password."])
login_timeout = aurweb.config.getint("options", "login_timeout")
expires_at = int(datetime.utcnow().timestamp()
+ max(cookie_timeout, login_timeout))
response = RedirectResponse(url=next,
status_code=int(HTTPStatus.SEE_OTHER))
response.set_cookie("AURSID", sid, expires=expires_at)
return response
@router.get("/logout")
async def logout(request: Request, next: str = "/"):
""" A GET and POST route for logging out.
@param request FastAPI request
@param next Route to redirect to
"""
if request.user.is_authenticated():
request.user.logout(request)
# Use 303 since we may be handling a post request, that'll get it
# to redirect to a get request.
response = RedirectResponse(url=next,
status_code=int(HTTPStatus.SEE_OTHER))
response.delete_cookie("AURSID")
response.delete_cookie("AURTZ")
return response
@router.post("/logout")
async def logout_post(request: Request, next: str = "/"):
return await logout(request=request, next=next)