Skip to content

Commit 69782cf

Browse files
committed
feat: 로그아웃 기능 추가
1 parent e3fdd37 commit 69782cf

5 files changed

Lines changed: 69 additions & 6 deletions

File tree

app/user/account_views/account.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@
55
from allauth.account.forms import LoginForm
66
from core.const.account import MERGE_MESSAGES
77
from core.templatetags.i18n_extras import is_english
8+
from django.contrib.auth import logout
89
from django.http import HttpRequest, HttpResponse
9-
from django.shortcuts import render
10-
from django.views.decorators.http import require_GET, require_http_methods
10+
from django.shortcuts import redirect, render
11+
from django.views.decorators.http import require_GET, require_http_methods, require_POST
1112
from user.account_views.utils import (
1213
HEADLESS_PROVIDER_REDIRECT_URL,
1314
PROVIDERS,
@@ -23,6 +24,12 @@ def account_home(request: HttpRequest) -> HttpResponse:
2324
return render(request, "user/account_home.html", {"user": request.user})
2425

2526

27+
@require_POST
28+
def account_logout(request: HttpRequest) -> HttpResponse:
29+
logout(request)
30+
return redirect("account-login")
31+
32+
2633
@require_GET
2734
def account_login(request: HttpRequest) -> HttpResponse:
2835
target = login_target(request)

app/user/templates/user/account_base.html

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,18 @@
4545
.add-email { display: flex; gap: .5rem; align-items: stretch; }
4646
.add-email input { flex: 1; margin: 0; }
4747
.add-email button { margin: 0; }
48+
.home-actions { display: flex; flex-direction: column; gap: .75rem; margin-top: 1.5rem; }
49+
.home-actions form { margin: 0; }
50+
.btn-outline {
51+
display: block; width: 100%; box-sizing: border-box; margin: 0;
52+
padding: 1rem 2rem; border: 2px solid var(--color-link); border-radius: var(--border-radius);
53+
background: transparent; color: var(--color-link);
54+
font-family: inherit; font-size: medium; font-weight: bold; font-style: italic; line-height: var(--line-height);
55+
text-align: center; text-decoration: none; cursor: pointer;
56+
}
57+
.btn-outline:hover { background: var(--color-link); color: var(--color-bg); filter: none; }
58+
.btn-outline.danger { background: transparent; border-color: #b23b3b; color: #b23b3b; }
59+
.btn-outline.danger:hover { background: #b23b3b; color: var(--color-bg); }
4860
</style>
4961
</head>
5062
<body>

app/user/templates/user/account_home.html

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,13 @@
33
{% block body %}
44
<h1>{% if en %}Account{% else %}계정 관리{% endif %}</h1>
55
<p class="muted">{{ user.email }}</p>
6-
<p><a href="{% url 'account-email' %}"><b>{% if en %}Manage email addresses{% else %}이메일 관리{% endif %}</b></a></p>
7-
<p><a href="{% url 'account-merge-start' %}"><b>{% if en %}Merge another account{% else %}다른 계정 병합{% endif %}</b></a></p>
8-
<p><a href="{% url 'account-password-change' %}"><b>{% if en %}Change password{% else %}비밀번호 변경{% endif %}</b></a></p>
6+
<div class="home-actions">
7+
<a class="btn-outline" href="{% url 'account-email' %}">{% if en %}Manage email addresses{% else %}이메일 관리{% endif %}</a>
8+
<a class="btn-outline" href="{% url 'account-merge-start' %}">{% if en %}Merge another account{% else %}다른 계정 병합{% endif %}</a>
9+
<a class="btn-outline" href="{% url 'account-password-change' %}">{% if en %}Change password{% else %}비밀번호 변경{% endif %}</a>
10+
<form method="post" action="{% url 'account-logout' %}">
11+
{% csrf_token %}
12+
<button type="submit" class="btn-outline danger">{% if en %}Log out{% else %}로그아웃{% endif %}</button>
13+
</form>
14+
</div>
915
{% endblock %}

app/user/test/account_view_test.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import pytest
2+
from django.contrib.auth import SESSION_KEY
3+
from django.urls import reverse
4+
from user.models import UserExt
5+
6+
7+
@pytest.fixture
8+
def user(db) -> UserExt:
9+
return UserExt.objects.create_user(username="u", email="u@example.com")
10+
11+
12+
def test_account_home_shows_logout_button(client, user):
13+
client.force_login(user)
14+
15+
response = client.get(reverse("account-home"))
16+
17+
assert response.status_code == 200
18+
assert reverse("account-logout").encode() in response.content
19+
20+
21+
def test_logout_clears_session_and_redirects(client, user):
22+
client.force_login(user)
23+
assert SESSION_KEY in client.session
24+
25+
response = client.post(reverse("account-logout"))
26+
27+
assert response.status_code == 302
28+
assert response.url == reverse("account-login")
29+
assert SESSION_KEY not in client.session
30+
31+
32+
def test_logout_rejects_get(client, user):
33+
client.force_login(user)
34+
35+
response = client.get(reverse("account-logout"))
36+
37+
assert response.status_code == 405

app/user/urls.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from django.urls import path
2-
from user.account_views.account import account_home, account_login, password_login
2+
from user.account_views.account import account_home, account_login, account_logout, password_login
33
from user.account_views.email import (
44
add_email,
55
confirm_email,
@@ -15,6 +15,7 @@
1515
path("", account_home, name="account-home"),
1616
path("login/", account_login, name="account-login"),
1717
path("login/password/", password_login, name="account-password-login"),
18+
path("logout/", account_logout, name="account-logout"),
1819
path("password/", password_change, name="account-password-change"),
1920
path("password/reset/", password_reset, name="account-password-reset"),
2021
path("password/reset/key/<str:key>/", password_reset_from_key, name="account-password-reset-from-key"),

0 commit comments

Comments
 (0)