WIP: final bit to make sending edit link working

This commit is contained in:
Yohan Boniface 2023-05-31 17:05:57 +02:00
parent eb32dcc9b6
commit 8f52d34bb2
7 changed files with 87 additions and 28 deletions

View file

@ -114,6 +114,8 @@ INSTALLED_APPS = (
)
DEFAULT_AUTO_FIELD = 'django.db.models.AutoField'
EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend"
# =============================================================================
# Calculation of directories relative to the project module location
# =============================================================================

View file

@ -748,6 +748,10 @@ input[type=hidden].blur + .button {
.umap-alert .error .umap-action:hover {
color: #fff;
}
.umap-alert input {
padding: 5px;
border-radius: 4px;
}
/* *********** */
/* Tooltip */

View file

@ -1345,10 +1345,9 @@ L.U.Map.include({
if (data.permissions && data.permissions.anonymous_edit_url) {
alert.actions = [
{
label: L._('Send me edit link by email'),
callback: function () {
this.sendEditLink()
},
label: L._('Send me the link'),
input: L._('Email'),
callback: this.sendEditLink,
callbackContext: this,
},
]
@ -1374,8 +1373,16 @@ L.U.Map.include({
},
sendEditLink: function () {
var url = L.Util.template(this.options.urls.map_send_edit_link, {
map_id: this.options.umap_id,
const url = L.Util.template(this.options.urls.map_send_edit_link, {
map_id: this.options.umap_id,
}),
input = this.ui._alert.querySelector('input'),
email = input.value
const formData = new FormData()
formData.append('email', email)
this.post(url, {
data: formData,
})
},

View file

@ -75,7 +75,6 @@ L.U.UI = L.Evented.extend({
},
popAlert: function (e) {
const self = this
if (!e) {
if (this.ALERTS.length) e = this.ALERTS.pop()
else return
@ -108,20 +107,25 @@ L.U.UI = L.Evented.extend({
)
L.DomUtil.add('div', '', this._alert, e.content)
if (e.actions) {
let action, el
let action, el, input
for (let i = 0; i < e.actions.length; i++) {
action = e.actions[i]
if (action.input) {
input = L.DomUtil.element(
'input',
{ className: 'umap-alert-input', placeholder: action.input },
this._alert
)
}
el = L.DomUtil.element('a', { className: 'umap-action' }, this._alert)
el.href = '#'
el.textContent = action.label
L.DomEvent.on(el, 'click', L.DomEvent.stop).on(el, 'click', close, this)
if (action.callback)
L.DomEvent.on(
el,
'click',
action.callback,
action.callbackContext || this.map
)
L.DomEvent.on(el, 'click', () => {
action.callback.bind(action.callbackContext || this.map)()
close.bind(this)()
})
}
}
if (e.duration !== Infinity) {

View file

@ -4,6 +4,8 @@ from umap.settings.base import * # pylint: disable=W0614,W0401
SECRET_KEY = "justfortests"
COMPRESS_ENABLED = False
FROM_EMAIL = "test@test.org"
EMAIL_BACKEND = 'django.core.mail.backends.locmem.EmailBackend'
if "TRAVIS" in os.environ:
DATABASES = {

View file

@ -2,9 +2,10 @@ import json
import pytest
from django.contrib.auth import get_user_model
from django.core import mail
from django.urls import reverse
from django.core.signing import Signer
from umap.models import DataLayer, Map, Star
from .base import login_required
@ -568,3 +569,32 @@ def test_user_can_see_their_star(client, map, user):
response = client.get(url)
assert response.status_code == 200
assert map.name in response.content.decode()
@pytest.mark.usefixtures("allow_anonymous")
def test_cannot_send_link_on_owned_map(client, map):
assert len(mail.outbox) == 0
url = reverse("map_send_edit_link", args=(map.pk,))
resp = client.post(url, {"email": "foo@bar.org"})
assert resp.status_code == 200
assert json.loads(resp.content.decode()) == {"login_required": "/en/login/"}
assert len(mail.outbox) == 0
@pytest.mark.usefixtures("allow_anonymous")
def test_cannot_send_link_on_anonymous_map_without_cookie(client, anonymap):
assert len(mail.outbox) == 0
url = reverse("map_send_edit_link", args=(anonymap.pk,))
resp = client.post(url, {"email": "foo@bar.org"})
assert resp.status_code == 403
assert len(mail.outbox) == 0
@pytest.mark.usefixtures("allow_anonymous")
def test_can_send_link_on_anonymous_map_with_cookie(cookieclient, anonymap):
assert len(mail.outbox) == 0
url = reverse("map_send_edit_link", args=(anonymap.pk,))
resp = cookieclient.post(url, {"email": "foo@bar.org"})
assert resp.status_code == 200
assert len(mail.outbox) == 1
assert mail.outbox[0].subject == "Your secret edit link"

View file

@ -12,6 +12,7 @@ from django.contrib.auth import logout as do_logout
from django.contrib.auth import get_user_model
from django.contrib.gis.measure import D
from django.contrib.postgres.search import SearchQuery, SearchVector
from django.core.mail import send_mail
from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator
from django.core.signing import BadSignature, Signer
from django.core.validators import URLValidator, ValidationError
@ -33,7 +34,7 @@ from django.utils.translation import to_locale
from django.views.generic import DetailView, TemplateView, View
from django.views.generic.base import RedirectView
from django.views.generic.detail import BaseDetailView
from django.views.generic.edit import CreateView, DeleteView, UpdateView
from django.views.generic.edit import CreateView, DeleteView, FormView, UpdateView
from django.views.generic.list import ListView
from .forms import (
@ -44,6 +45,7 @@ from .forms import (
DataLayerForm,
FlatErrorList,
MapSettingsForm,
SendLinkForm,
UpdateMapPermissionsForm,
)
from .models import DataLayer, Licence, Map, Pictogram, Star, TileLayer
@ -618,26 +620,34 @@ class AttachAnonymousMap(View):
return simple_json_response()
class SendEditLink(FormLessEditMixin, PermissionsMixin, UpdateView):
model = Map
pk_url_kwarg = 'map_id'
class SendEditLink(FormLessEditMixin, FormView):
form_class = SendLinkForm
def form_valid(self, form):
if (self.object.owner
or not self.object.is_anonymous_owner(self.request)
or not self.object.can_edit(self.request.user, self.request)):
def post(self, form, **kwargs):
self.object = kwargs["map_inst"]
if (
self.object.owner
or not self.object.is_anonymous_owner(self.request)
or not self.object.can_edit(self.request.user, self.request)
):
return HttpResponseForbidden()
email = form.cleaned_data["email"]
from django.core.mail import send_mail
form = self.get_form()
if form.is_valid():
email = form.cleaned_data["email"]
else:
return HttpResponseBadRequest("Invalid")
link = self.object.get_anonymous_edit_url()
send_mail(
_('Your secret edit link'),
_('Here is your secret edit link: %(link)s' % {"link": link}),
_("Your secret edit link"),
_("Here is your secret edit link: %(link)s" % {"link": link}),
settings.FROM_EMAIL,
[email],
fail_silently=False,
)
return simple_json_response(info=_("Email sent to %(email)s" % {"email": email}))
return simple_json_response(
info=_("Email sent to %(email)s" % {"email": email})
)
class MapDelete(DeleteView):