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:
parent
084bc3d518
commit
49f600adfa
8 changed files with 81 additions and 79 deletions
|
@ -60,17 +60,3 @@ def can_view_map(view_func):
|
||||||
return view_func(request, *args, **kwargs)
|
return view_func(request, *args, **kwargs)
|
||||||
|
|
||||||
return wrapper
|
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
|
|
||||||
|
|
|
@ -37,6 +37,21 @@ input:-moz-placeholder, :-moz-placeholder {
|
||||||
/* **************** */
|
/* **************** */
|
||||||
/* Login icons */
|
/* 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 li,
|
||||||
.login-grid a {
|
.login-grid a {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
|
|
@ -73,12 +73,12 @@ export const ServerRequest = Request.extend({
|
||||||
headers['X-CSRFToken'] = token
|
headers['X-CSRFToken'] = token
|
||||||
}
|
}
|
||||||
const response = await Request.prototype.post.call(this, uri, headers, data)
|
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) {
|
get: async function (uri, headers) {
|
||||||
const response = await Request.prototype.get.call(this, 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) {
|
_handle_json_response: async function (response) {
|
||||||
|
@ -105,10 +105,15 @@ export const ServerRequest = Request.extend({
|
||||||
this.ui.closePanel()
|
this.ui.closePanel()
|
||||||
} else if (data.error) {
|
} else if (data.error) {
|
||||||
this.ui.alert({ content: data.error, level: 'error' })
|
this.ui.alert({ content: data.error, level: 'error' })
|
||||||
} else if (data.html) {
|
} else if (data.login_required) {
|
||||||
const ui_options = { data }
|
// TODO: stop flow and run request again when user
|
||||||
let listen_options
|
// is logged in
|
||||||
this.ui.openPanel(ui_options)
|
const win = window.open(data.login_required)
|
||||||
|
window.umap_proceed = () => {
|
||||||
|
console.log('logged in')
|
||||||
|
this.fire('login')
|
||||||
|
win.close()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -1,37 +1,51 @@
|
||||||
{% load i18n %}
|
{% extends "base.html" %}
|
||||||
{% if ENABLE_ACCOUNT_LOGIN %}
|
{% load umap_tags i18n %}
|
||||||
<h5>{% trans "Please log in with your account" %}</h5>
|
{% block extra_head %}
|
||||||
<div>
|
{% umap_css %}
|
||||||
{% if form.non_field_errors %}
|
{% endblock extra_head %}
|
||||||
<ul class="form-errors">
|
{% block body_class %}
|
||||||
{% for error in form.non_field_errors %}<li>{{ error }}</li>{% endfor %}
|
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>
|
</ul>
|
||||||
{% endif %}
|
</div>
|
||||||
<form id="login_form" action="{% url "login" %}" method="post">
|
{% endif %}
|
||||||
{% csrf_token %}
|
</section>
|
||||||
{{ form.username.errors }}
|
{% endblock content %}
|
||||||
<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 %}
|
|
||||||
|
|
3
umap/templates/umap/branding.html
Normal file
3
umap/templates/umap/branding.html
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
<h1>
|
||||||
|
<a href="{% url "home" %}">{{ SITE_NAME }}</a>
|
||||||
|
</h1>
|
|
@ -40,24 +40,6 @@
|
||||||
|
|
||||||
!(function () {
|
!(function () {
|
||||||
const ui = new L.U.UI(document.querySelector('header'))
|
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) {
|
const getMore = function (e) {
|
||||||
L.DomEvent.stop(e)
|
L.DomEvent.stop(e)
|
||||||
xhr._ajax({
|
xhr._ajax({
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
<nav class="umap-nav">
|
<nav class="umap-nav">
|
||||||
<section>
|
<section>
|
||||||
<h1>
|
{% include "umap/branding.html" %}
|
||||||
<a href="{% url "home" %}">{{ title }}</a>
|
|
||||||
</h1>
|
|
||||||
</section>
|
</section>
|
||||||
<section>
|
<section>
|
||||||
<ul>
|
<ul>
|
||||||
|
|
|
@ -15,7 +15,6 @@ from . import views
|
||||||
from .decorators import (
|
from .decorators import (
|
||||||
can_edit_map,
|
can_edit_map,
|
||||||
can_view_map,
|
can_view_map,
|
||||||
jsonize_view,
|
|
||||||
login_required_if_not_anonymous_allowed,
|
login_required_if_not_anonymous_allowed,
|
||||||
)
|
)
|
||||||
from .utils import decorated_patterns
|
from .utils import decorated_patterns
|
||||||
|
@ -50,7 +49,7 @@ urlpatterns = [
|
||||||
]
|
]
|
||||||
|
|
||||||
i18n_urls = [
|
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(
|
re_path(
|
||||||
r"^login/popup/end/$", views.LoginPopupEnd.as_view(), name="login_popup_end"
|
r"^login/popup/end/$", views.LoginPopupEnd.as_view(), name="login_popup_end"
|
||||||
),
|
),
|
||||||
|
|
Loading…
Reference in a new issue