Skip to content

Commit

Permalink
Skipped login page if already logged in (#256)
Browse files Browse the repository at this point in the history
  • Loading branch information
WattsUp authored Jan 20, 2025
1 parent 75b61d0 commit bb7754f
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 40 deletions.
19 changes: 13 additions & 6 deletions nummus/controllers/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
if TYPE_CHECKING:
from collections.abc import Callable

import werkzeug

from nummus.controllers.base import Routes


Expand Down Expand Up @@ -77,21 +79,26 @@ def get_user(username: str) -> flask_login.UserMixin | flask_login.AnonymousUser


@login_exempt
def page_login() -> str:
def page_login() -> str | werkzeug.Response:
"""GET /login.
Returns:
HTML response
"""
next_url = flask.request.args.get("next")
if flask_login.current_user.is_authenticated:
# If already authenticated, skip login page
if next_url is None:
return flask.redirect(flask.url_for("dashboard.page"))
return flask.redirect(next_url)
return flask.render_template(
"auth/login.jinja",
next_url=next_url,
)


@login_exempt
def login() -> str | flask.Response:
def login() -> str | werkzeug.Response:
"""POST /h/login.
Returns:
Expand Down Expand Up @@ -124,18 +131,18 @@ def login() -> str | flask.Response:

next_url = form.get("next")
if next_url is None:
return common.redirect(flask.url_for("dashboard.page"))
return common.redirect(next_url)
return flask.redirect(flask.url_for("dashboard.page"))
return flask.redirect(next_url)


def logout() -> str | flask.Response:
def logout() -> str | werkzeug.Response:
"""POST /h/logout.
Returns:
HTML response
"""
flask_login.logout_user()
return common.redirect(flask.url_for("auth.page_login"))
return flask.redirect(flask.url_for("auth.page_login"))


ROUTES: Routes = {
Expand Down
16 changes: 0 additions & 16 deletions nummus/controllers/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -266,22 +266,6 @@ def overlay_swap(
return response


def redirect(
url: str,
) -> flask.Response:
"""Create a response to redirect to url.
Args:
url: URL to redirect to
Returns:
Response that causes a full page reload to URL
"""
response = flask.make_response("")
response.headers["HX-Redirect"] = url
return response


def error(e: str | Exception) -> str:
"""Convert exception into an readable error string.
Expand Down
44 changes: 37 additions & 7 deletions tests/controllers/test_auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ def test_login(self) -> None:
self.assertEqual(headers["Location"], url_login_next)

# With HX-Request, return OK with HX-Redirect
headers = {"HX-Request": "true"}
response, headers = self.web_get(endpoint, headers=headers)
send_headers = {"HX-Request": "true"}
response, headers = self.web_get(endpoint, headers=send_headers)
self.assertEqual(response, "")
self.assertIn(
"HX-Redirect",
Expand All @@ -81,17 +81,17 @@ def test_login(self) -> None:

# Do login
form = {}
response, _ = self.web_post("auth.login", data=form)
response, _ = self.web_post("auth.login", headers=send_headers, data=form)
self.assertIn("Password must not be blank", response)

# Wrong password
form = {"password": self.random_string()}
response, _ = self.web_post("auth.login", data=form)
response, _ = self.web_post("auth.login", headers=send_headers, data=form)
self.assertIn("Bad password", response)

# Good password no next, goes to dashboard
form = {"password": key}
response, headers = self.web_post("auth.login", data=form)
response, headers = self.web_post("auth.login", headers=send_headers, data=form)
self.assertEqual("", response)
self.assertIn(
"HX-Redirect",
Expand All @@ -102,7 +102,7 @@ def test_login(self) -> None:

# Good password with next
form = {"password": key, "next": url_next}
response, headers = self.web_post("auth.login", data=form)
response, headers = self.web_post("auth.login", headers=send_headers, data=form)
self.assertEqual("", response)
self.assertIn(
"HX-Redirect",
Expand All @@ -115,8 +115,38 @@ def test_login(self) -> None:
response, _ = self.web_get("dashboard.page")
self.assertIn("Net Worth", response)

# Login page while authenticated redirects to next
response, headers = self.web_get(
("auth.page_login", {"next": url_next}),
rc=HTTP_CODE_REDIRECT,
)
self.assertIn(url_next, response)
self.assertIn(
"Location",
headers,
msg=f"Response lack Location {response}",
)
self.assertEqual(headers["Location"], url_next)

# No next goes to dashboard
response, headers = self.web_get(
"auth.page_login",
rc=HTTP_CODE_REDIRECT,
)
self.assertIn(url_dashboard, response)
self.assertIn(
"Location",
headers,
msg=f"Response lack Location {response}",
)
self.assertEqual(headers["Location"], url_dashboard)

# Logging out should redirect to login page
response, headers = self.web_post("auth.logout", data=form)
response, headers = self.web_post(
"auth.logout",
headers=send_headers,
data=form,
)
self.assertEqual("", response)
self.assertIn(
"HX-Redirect",
Expand Down
11 changes: 0 additions & 11 deletions tests/controllers/test_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -327,17 +327,6 @@ def visit_all_links(url: str, method: str, *, hx: bool = False) -> None:
for link in deletes:
visit_all_links(link, "DELETE", hx=True)

def test_redirect(self) -> None:
with self._flask_app.app_context():
url = self.random_string()
response = common.redirect(url)
self.assertIn(
"HX-Redirect",
response.headers,
msg=f"Response lack HX-Redirect {response}",
)
self.assertEqual(response.headers["HX-Redirect"], url)

def test_page(self) -> None:
_ = self._setup_portfolio()

Expand Down

0 comments on commit bb7754f

Please sign in to comment.