wip: refactor login flow

Instead of dealing with in JavaScript, let's do a more classic
HTTP flow.

The main flows work, but there is still at least one to deal with:
when editing a map without being logged in, the server may ask for
login, and in this case we should login THEN reissue the request,
so we need to interrupt the first request in some way,
otherwise the server will still answer with a 403, which is what
happens after this commit.
This commit is contained in:
Yohan Boniface 2024-01-24 11:54:51 +01:00
parent 084bc3d518
commit 49f600adfa
8 changed files with 81 additions and 79 deletions

View file

@ -60,17 +60,3 @@ def can_view_map(view_func):
return view_func(request, *args, **kwargs)
return wrapper
def jsonize_view(view_func):
@wraps(view_func)
def wrapper(request, *args, **kwargs):
response = view_func(request, *args, **kwargs)
response_kwargs = {}
if hasattr(response, "rendered_content"):
response_kwargs["html"] = response.rendered_content
if response.has_header("location"):
response_kwargs["redirect"] = response["location"]
return simple_json_response(**response_kwargs)
return wrapper

View file

@ -37,6 +37,21 @@ input:-moz-placeholder, :-moz-placeholder {
/* **************** */
/* Login icons */
/* **************** */
body.login {
width: 320px;
margin: auto;
text-align: center;
}
body.login header {
display: flex;
justify-content: center;
}
.login-grid {
display: grid;
justify-content: space-between;
grid-gap: 5px;
grid-template-columns: repeat(auto-fill,92px);
}
.login-grid li,
.login-grid a {
display: inline-block;

View file

@ -73,12 +73,12 @@ export const ServerRequest = Request.extend({
headers['X-CSRFToken'] = token
}
const response = await Request.prototype.post.call(this, uri, headers, data)
return this._handle_json_response(response)
return await this._handle_json_response(response)
},
get: async function (uri, headers) {
const response = await Request.prototype.get.call(this, uri, headers)
return this._handle_json_response(response)
return await this._handle_json_response(response)
},
_handle_json_response: async function (response) {
@ -105,10 +105,15 @@ export const ServerRequest = Request.extend({
this.ui.closePanel()
} else if (data.error) {
this.ui.alert({ content: data.error, level: 'error' })
} else if (data.html) {
const ui_options = { data }
let listen_options
this.ui.openPanel(ui_options)
} else if (data.login_required) {
// TODO: stop flow and run request again when user
// is logged in
const win = window.open(data.login_required)
window.umap_proceed = () => {
console.log('logged in')
this.fire('login')
win.close()
}
}
},

View file

@ -1,37 +1,51 @@
{% load i18n %}
{% if ENABLE_ACCOUNT_LOGIN %}
<h5>{% trans "Please log in with your account" %}</h5>
<div>
{% if form.non_field_errors %}
<ul class="form-errors">
{% for error in form.non_field_errors %}<li>{{ error }}</li>{% endfor %}
{% extends "base.html" %}
{% load umap_tags i18n %}
{% block extra_head %}
{% umap_css %}
{% endblock extra_head %}
{% block body_class %}
login
{% endblock body_class %}
{% block content %}
<section>
<header class="umap-nav">
{% include "umap/branding.html" %}
</header>
{% if ENABLE_ACCOUNT_LOGIN %}
<h2>{% trans "Please log in with your account" %}</h2>
<div>
{% if form.non_field_errors %}
<ul class="form-errors">
{% for error in form.non_field_errors %}<li>{{ error }}</li>{% endfor %}
</ul>
{% endif %}
<form id="login_form" action="{% url "login" %}" method="post">
{% csrf_token %}
{{ form.username.errors }}
<input type="text"
name="username"
placeholder="{% trans "Username" %}"
autofocus />
{{ form.password.errors }}
<input type="password" name="password" placeholder="{% trans "Password" %}" />
<input type="submit" value="{% trans "Login" %}" />
</form>
</div>
{% endif %}
{% if backends.backends|length %}
<h2>{% trans "Please choose a provider" %}</h2>
<div>
<ul class="login-grid block-grid">
{% for name in backends.backends %}
<li>
<a rel="nofollow"
href="{% url "social:begin" name %}"
class="umap-login-popup login-{{ name }}"
title="{{ name|title }}"></a>
</li>
{% endfor %}
</ul>
{% endif %}
<form id="login_form" action="{% url "login" %}" method="post">
{% csrf_token %}
{{ form.username.errors }}
<input type="text"
name="username"
placeholder="{% trans "Username" %}"
autofocus />
{{ form.password.errors }}
<input type="password" name="password" placeholder="{% trans "Password" %}" />
<input type="submit" value="{% trans "Login" %}" />
</form>
</div>
{% endif %}
{% if backends.backends|length %}
<h5>{% trans "Please choose a provider" %}</h5>
<div>
<ul class="login-grid block-grid">
{% for name in backends.backends %}
<li>
<a rel="nofollow"
href="{% url "social:begin" name %}"
class="umap-login-popup login-{{ name }}"
title="{{ name|title }}"></a>
</li>
{% endfor %}
</ul>
</div>
{% endif %}
</div>
{% endif %}
</section>
{% endblock content %}

View file

@ -0,0 +1,3 @@
<h1>
<a href="{% url "home" %}">{{ SITE_NAME }}</a>
</h1>

View file

@ -40,24 +40,6 @@
!(function () {
const ui = new L.U.UI(document.querySelector('header'))
const xhr = new L.U.Xhr(ui)
const login = document.querySelector('a.login')
if (login) {
L.DomEvent.on(login, 'click', function (e) {
L.DomEvent.stop(e)
xhr.login({
login_required: this.getAttribute('href'),
redirect: '/',
})
})
}
const logout = document.querySelector('a.logout')
if (logout) {
L.DomEvent.on(logout, 'click', function (e) {
L.DomEvent.stop(e)
xhr.logout(this.getAttribute('href'))
})
}
const getMore = function (e) {
L.DomEvent.stop(e)
xhr._ajax({

View file

@ -1,9 +1,7 @@
{% load i18n %}
<nav class="umap-nav">
<section>
<h1>
<a href="{% url "home" %}">{{ title }}</a>
</h1>
{% include "umap/branding.html" %}
</section>
<section>
<ul>

View file

@ -15,7 +15,6 @@ from . import views
from .decorators import (
can_edit_map,
can_view_map,
jsonize_view,
login_required_if_not_anonymous_allowed,
)
from .utils import decorated_patterns
@ -50,7 +49,7 @@ urlpatterns = [
]
i18n_urls = [
re_path(r"^login/$", jsonize_view(auth_views.LoginView.as_view()), name="login"),
re_path(r"^login/$", auth_views.LoginView.as_view(), name="login"),
re_path(
r"^login/popup/end/$", views.LoginPopupEnd.as_view(), name="login_popup_end"
),