Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions apps/users/tests/test_auth_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,18 @@ def test_signup_page_renders(client):
assert b"New Account" in response.content


@pytest.mark.django_db
def test_authenticated_signup_redirects_to_dashboard(client):
"""Signed-in users do not need the public signup page."""
user = CustomUserFactory(email="signed-in@example.com")
client.force_login(user)

response = client.get(reverse("users:signup"))

assert response.status_code == 302
assert response["Location"] == reverse("dashboard:index")


@pytest.mark.django_db
def test_signup_creates_user_and_redirects_to_dashboard(client):
"""A valid signup creates a user and sends them to the dashboard."""
Expand Down Expand Up @@ -149,6 +161,30 @@ def test_login_with_email_redirects_to_dashboard(client):
assert response["Location"] == reverse("dashboard:index")


@pytest.mark.django_db
def test_authenticated_login_redirects_to_dashboard(client):
"""Signed-in users are sent to the post-login product surface."""
user = CustomUserFactory(email="already@example.com")
client.force_login(user)

response = client.get(reverse("users:login"))

assert response.status_code == 302
assert response["Location"] == reverse("dashboard:index")


@pytest.mark.django_db
def test_logout_redirects_to_home(client):
"""Logout returns users to the public landing page."""
user = CustomUserFactory(email="logout@example.com")
client.force_login(user)

response = client.post(reverse("users:logout"))

assert response.status_code == 302
assert response["Location"] == reverse("home")


@pytest.mark.django_db
def test_profile_requires_login(client):
"""Anonymous users are redirected before viewing a profile."""
Expand Down
17 changes: 12 additions & 5 deletions apps/users/urls.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,24 @@
"""User account URL routes."""
"""URL routes for StudyBuddy account workflows."""

from __future__ import annotations

from django.contrib.auth import views as auth_views
from django.contrib.auth.views import LoginView, LogoutView
from django.urls import path

from apps.users import views

app_name = "users"

urlpatterns = [
path("login/", auth_views.LoginView.as_view(), name="login"),
path("logout/", auth_views.LogoutView.as_view(), name="logout"),
path("profile/", views.profile, name="profile"),
path("signup/", views.signup, name="signup"),
path(
"login/",
LoginView.as_view(
redirect_authenticated_user=True,
template_name="users/login.html",
),
name="login",
),
path("logout/", LogoutView.as_view(), name="logout"),
path("profile/", views.profile, name="profile"),
]
3 changes: 3 additions & 0 deletions apps/users/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@

def signup(request: HttpRequest) -> HttpResponse:
"""Register a new user and send them to the dashboard."""
if request.user.is_authenticated:
return redirect("dashboard:index")

if request.method == "POST":
form = UserSignUpForm(request.POST)

Expand Down
11 changes: 11 additions & 0 deletions static/css/theme.css
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,10 @@ p {
gap: var(--space-md);
}

.nav-logout-form {
margin: 0;
}

.nav-links {
flex: 1;
}
Expand Down Expand Up @@ -407,6 +411,13 @@ p {
text-align: right;
}

.profile-pill-list {
display: flex;
flex-wrap: wrap;
justify-content: flex-end;
gap: var(--space-sm);
}

.form-card {
max-width: 560px;
margin: 0 auto;
Expand Down
4 changes: 4 additions & 0 deletions templates/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@
{% if request.user.is_authenticated %}
<a class="btn-ui" href="{% url 'users:profile' %}">Profile</a>
<a class="btn-ui btn-ui-primary" href="{% url 'dashboard:index' %}">Dashboard</a>
<form class="nav-logout-form" method="post" action="{% url 'users:logout' %}">
{% csrf_token %}
<button class="btn-ui btn-ui-ghost" type="submit">Log Out</button>
</form>
{% else %}
<a class="btn-ui btn-ui-ghost" href="{% url 'users:login' %}">Log In</a>
<a class="btn-ui btn-ui-primary" href="{% url 'users:signup' %}">Create Account</a>
Expand Down
29 changes: 0 additions & 29 deletions templates/registration/login.html

This file was deleted.

29 changes: 0 additions & 29 deletions templates/registration/signup.html

This file was deleted.

54 changes: 54 additions & 0 deletions templates/users/login.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
{% extends "base.html" %}

{% block title %}Log In | StudyBuddy{% endblock %}

{% block content %}
<div class="container-ui">
<div class="page-stack">
<header class="hero-content">
<span class="eyebrow">Welcome back</span>
<h1 class="page-title">Log In</h1>
<p class="page-subtitle">Use the email address and password linked to your StudyBuddy account.</p>
</header>

<section class="section-tight">
<article class="card-ui form-card">
<h2 class="card-title-ui">Account Access</h2>

<form class="form-ui" method="post" novalidate>
{% csrf_token %}

{% if form.non_field_errors %}
<div class="form-errors">
{{ form.non_field_errors }}
</div>
{% endif %}

<p>
<label for="{{ form.username.id_for_label }}">Email address</label>
{{ form.username }}
{% if form.username.errors %}
<span class="form-errors">{{ form.username.errors }}</span>
{% endif %}
</p>

<p>
<label for="{{ form.password.id_for_label }}">Password</label>
{{ form.password }}
{% if form.password.errors %}
<span class="form-errors">{{ form.password.errors }}</span>
{% endif %}
</p>

<input type="hidden" name="next" value="{{ next }}">

<div class="card-actions">
<button class="btn-ui btn-ui-primary" type="submit">Log In</button>
<a class="btn-ui" href="{% url 'users:signup' %}">Create Account</a>
</div>
</form>
</article>
</section>
</div>
</div>
{% endblock %}
12 changes: 12 additions & 0 deletions templates/users/profile.html
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,18 @@ <h2 class="card-title-ui">Account Details</h2>
<dt>Username</dt>
<dd>{{ request.user.username }}</dd>
</div>
<div class="detail-row">
<dt>Roles</dt>
<dd>
<span class="profile-pill-list">
{% for role in request.user.studybuddy_roles.all %}
<span class="mock-pill">{{ role.display_name }}</span>
{% empty %}
<span class="text-muted-ui">No roles assigned yet.</span>
{% endfor %}
</span>
</dd>
</div>
</dl>
</article>

Expand Down
Loading