fix(fastapi): render Logged-in as page on authenticated /login

This was missed during the initial porting of the /login route.

Modifications:
-------------
- A form is now used for the [Logout] link and some css was
  needed to deal with positioning.

Closes #186

Signed-off-by: Kevin Morris <kevr@0cost.org>
This commit is contained in:
Kevin Morris 2021-11-29 19:39:27 -08:00
parent fd8d23a379
commit 9bfe2b07ba
No known key found for this signature in database
GPG key ID: F7E46DED420788F3
4 changed files with 104 additions and 79 deletions

View file

@ -24,7 +24,6 @@ async def login_template(request: Request, next: str, errors: list = None):
@router.get("/login", response_class=HTMLResponse)
@auth_required(False, login=False)
async def login_get(request: Request, next: str = "/"):
return await login_template(request, next)

View file

@ -5,81 +5,95 @@
<div id="dev-login" class="box">
<h2>AUR {% trans %}Login{% endtrans %}</h2>
{% if request.url.scheme == "http" and config.getboolean("options", "disable_http_login") %}
{% set https_login = url_base.replace("http://", "https://") + "/login" %}
<p>
{{ "HTTP login is disabled. Please %sswitch to HTTPs%s if you want to login."
| tr
| format(
'<a href="%s">' | format(https_login),
"</a>")
| safe
}}
</p>
{% elif request.user.is_authenticated() %}
<p>
{{ "Logged-in as: %s"
| tr
| format("<b>%s</b>" | format(request.user.Username))
| safe
}}
<a href="/logout?next={{ next }}">[{% trans %}Logout{% endtrans %}]</a>
</p>
{% else %}
<form method="post" action="/login?next={{ next }}">
<fieldset>
<legend>{% trans %}Enter login credentials{% endtrans %}</legend>
{% if errors %}
<ul class="errorlist">
{% for error in errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
<p>
<label for="id_username">
{% trans %}User name or primary email address{% endtrans %}:
</label>
<input id="id_username" type="text" name="user" size="30"
maxlength="254" autofocus="autofocus"
required="required" value="{{ user or '' }}">
</p>
<p>
<label for="id_password">
{% trans %}Password{% endtrans %}:
</label>
<input id="id_password" type="password" name="passwd"
size="30" required="required">
</p>
<p>
<input id="id_remember_me" type="checkbox" name="remember_me"
{% if remember_me %}
checked="checked"
{% endif %}
>
<label for="id_remember_me">
{% trans %}Remember me{% endtrans %}
</label>
</p>
<p>
<input class="button" type="submit"
value="{% trans %}Login{% endtrans %}">
<a href="/passreset">
[{% trans %}Forgot Password{% endtrans %}]
</a>
<input id="id_referer" type="hidden" name="referer"
value="{{ url_base }}">
<input type="hidden" name="next" value="{{ next }}">
</p>
</fieldset>
{% if request.user.is_authenticated() %}
<form action="/logout" method="post" class="link">
<p>
{{
"Logged-in as: %s" | tr
| format("<strong>%s</strong>" | format(request.user.Username))
| safe
}}
<input type="hidden" name="next" value="{{ next }}" />
<button type="submit">[{{ "Logout" | tr }}]</button>
</p>
</form>
{% else %}
{% if request.url.scheme == "http" and config.getboolean("options", "disable_http_login") %}
{% set https_login = url_base.replace("http://", "https://") + "/login" %}
<p>
{{ "HTTP login is disabled. Please %sswitch to HTTPs%s if you want to login."
| tr
| format(
'<a href="%s">' | format(https_login),
"</a>")
| safe
}}
</p>
{% elif request.user.is_authenticated() %}
<p>
{{ "Logged-in as: %s"
| tr
| format("<b>%s</b>" | format(request.user.Username))
| safe
}}
<a href="/logout?next={{ next }}">[{% trans %}Logout{% endtrans %}]</a>
</p>
{% else %}
<form method="post" action="/login?next={{ next }}">
<fieldset>
<legend>{% trans %}Enter login credentials{% endtrans %}</legend>
{% if errors %}
<ul class="errorlist">
{% for error in errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
<p>
<label for="id_username">
{% trans %}User name or primary email address{% endtrans %}:
</label>
<input id="id_username" type="text" name="user" size="30"
maxlength="254" autofocus="autofocus"
required="required" value="{{ user or '' }}">
</p>
<p>
<label for="id_password">
{% trans %}Password{% endtrans %}:
</label>
<input id="id_password" type="password" name="passwd"
size="30" required="required">
</p>
<p>
<input id="id_remember_me" type="checkbox" name="remember_me"
{% if remember_me %}
checked="checked"
{% endif %}
>
<label for="id_remember_me">
{% trans %}Remember me{% endtrans %}
</label>
</p>
<p>
<input class="button" type="submit"
value="{% trans %}Login{% endtrans %}">
<a href="/passreset">
[{% trans %}Forgot Password{% endtrans %}]
</a>
<input id="id_referer" type="hidden" name="referer"
value="{{ url_base }}">
<input type="hidden" name="next" value="{{ next }}">
</p>
</fieldset>
</form>
{% endif %}
{% endif %}
</div>

View file

@ -131,7 +131,7 @@ def test_secure_login(mock):
assert user.session == record
def test_authenticated_login_forbidden():
def test_authenticated_login():
post_data = {
"user": "test",
"passwd": "testPassword",
@ -139,15 +139,19 @@ def test_authenticated_login_forbidden():
}
with client as request:
# Login.
# Try to login.
response = request.post("/login", data=post_data,
allow_redirects=False)
assert response.status_code == int(HTTPStatus.SEE_OTHER)
assert response.headers.get("location") == "/"
# Now, let's verify that we get the logged in rendering
# when requesting GET /login as an authenticated user.
# Now, let's verify that we receive 403 Forbidden when we
# try to get /login as an authenticated user.
response = request.get("/login", allow_redirects=False)
assert response.status_code == int(HTTPStatus.SEE_OTHER)
assert response.status_code == int(HTTPStatus.OK)
assert "Logged-in as: <strong>test</strong>" in response.text
def test_unauthenticated_logout_unauthorized():

View file

@ -232,7 +232,7 @@ input#search-action-submit {
/* Styling used to clone <a> styles for a form.link button. */
form.link, form.link button {
display: inline-block;
display: inline;
font-family: sans-serif;
}
form.link button {
@ -247,3 +247,11 @@ form.link button:hover {
cursor: pointer;
text-decoration: underline;
}
/* Customize form.link when used inside of a page. */
div.box form.link p {
margin: .33em 0 1em;
}
div.box form.link button {
padding: 0;
}