mirror of
https://github.com/umap-project/umap.git
synced 2025-05-10 16:11:49 +02:00
Compare commits
4 commits
45a0ec5d42
...
09faa763f9
Author | SHA1 | Date | |
---|---|---|---|
![]() |
09faa763f9 | ||
![]() |
fe06a0ff8e | ||
![]() |
b578ceced4 | ||
![]() |
7c808393f0 |
6 changed files with 144 additions and 81 deletions
|
@ -40,24 +40,40 @@ Then, change the `STORAGES` settings with something like this:
|
||||||
```
|
```
|
||||||
STORAGES = {
|
STORAGES = {
|
||||||
"default": {
|
"default": {
|
||||||
"BACKEND": "django.core.files.storage.FileSystemStorage",
|
"BACKEND": "storages.backends.s3.S3Storage",
|
||||||
|
"OPTIONS": {
|
||||||
|
"access_key": "xxx",
|
||||||
|
"secret_key": "yyy",
|
||||||
|
"bucket_name": "umap-pictograms",
|
||||||
|
"endpoint_url": "http://127.0.0.1:9000",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
"data": {
|
"data": {
|
||||||
|
# Whatch out, this is a dedicated uMap class!
|
||||||
"BACKEND": "umap.storage.s3.S3DataStorage",
|
"BACKEND": "umap.storage.s3.S3DataStorage",
|
||||||
"OPTIONS": {
|
"OPTIONS": {
|
||||||
"access_key": "xxx",
|
"access_key": "xxx",
|
||||||
"secret_key": "yyy",
|
"secret_key": "yyy",
|
||||||
"bucket_name": "umap",
|
"bucket_name": "umap-data",
|
||||||
"region_name": "eu",
|
|
||||||
"endpoint_url": "http://127.0.0.1:9000",
|
"endpoint_url": "http://127.0.0.1:9000",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"staticfiles": {
|
"staticfiles": {
|
||||||
"BACKEND": "umap.storage.staticfiles.UmapManifestStaticFilesStorage",
|
"BACKEND": "storages.backends.s3.S3Storage",
|
||||||
|
"OPTIONS": {
|
||||||
|
"access_key": "xxx",
|
||||||
|
"secret_key": "yyy",
|
||||||
|
"bucket_name": "umapstatics",
|
||||||
|
"endpoint_url": "http://127.0.0.1:9000",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
As you can see in this example, both `staticfiles` and `default` use the storage class provided
|
||||||
|
by `django-storages` (`storages.backends.s3.S3Storage`), but the `data` one uses a specific class
|
||||||
|
(`umap.storage.s3.S3DataStorage`).
|
||||||
|
|
||||||
In order to store old versions of a layer, the versioning should be activated in the bucket.
|
In order to store old versions of a layer, the versioning should be activated in the bucket.
|
||||||
|
|
||||||
See more about the configuration on the [django-storages documentation](https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html).
|
See more about the configuration on the [django-storages documentation](https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html).
|
||||||
|
|
|
@ -64,7 +64,10 @@ export default class Importer extends Utils.WithTemplate {
|
||||||
this.TYPES = ['geojson', 'csv', 'gpx', 'kml', 'osm', 'georss', 'umap']
|
this.TYPES = ['geojson', 'csv', 'gpx', 'kml', 'osm', 'georss', 'umap']
|
||||||
this.IMPORTERS = []
|
this.IMPORTERS = []
|
||||||
this.loadImporters()
|
this.loadImporters()
|
||||||
this.dialog = new Dialog({ className: 'importers dark' })
|
this.dialog = new Dialog({
|
||||||
|
className: 'importers dark',
|
||||||
|
back: () => this.showImporters(),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
loadImporters() {
|
loadImporters() {
|
||||||
|
@ -172,7 +175,7 @@ export default class Importer extends Utils.WithTemplate {
|
||||||
button.addEventListener('click', () => plugin.open(this))
|
button.addEventListener('click', () => plugin.open(this))
|
||||||
grid.appendChild(button)
|
grid.appendChild(button)
|
||||||
}
|
}
|
||||||
this.dialog.open({ template: element, cancel: false, accept: false })
|
this.dialog.open({ template: element, cancel: false, accept: false, back: false })
|
||||||
}
|
}
|
||||||
|
|
||||||
build() {
|
build() {
|
||||||
|
|
|
@ -6,6 +6,7 @@ const TEMPLATE = `
|
||||||
<form method="dialog" data-ref="form">
|
<form method="dialog" data-ref="form">
|
||||||
<ul class="buttons">
|
<ul class="buttons">
|
||||||
<li><i class="icon icon-16 icon-close" data-close></i></li>
|
<li><i class="icon icon-16 icon-close" data-close></i></li>
|
||||||
|
<li hidden data-ref="back"><i class="icon icon-16 icon-back"></i></li>
|
||||||
</ul>
|
</ul>
|
||||||
<h3 data-ref="message" id="${Math.round(Date.now()).toString(36)}"></h3>
|
<h3 data-ref="message" id="${Math.round(Date.now()).toString(36)}"></h3>
|
||||||
<fieldset data-ref="fieldset" role="document">
|
<fieldset data-ref="fieldset" role="document">
|
||||||
|
@ -123,6 +124,10 @@ export default class Dialog extends WithTemplate {
|
||||||
} else {
|
} else {
|
||||||
this.elements.template.innerHTML = dialog.template || ''
|
this.elements.template.innerHTML = dialog.template || ''
|
||||||
}
|
}
|
||||||
|
this.elements.back.hidden = !dialog.back
|
||||||
|
if (dialog.back) {
|
||||||
|
this.elements.back.addEventListener('click', dialog.back)
|
||||||
|
}
|
||||||
|
|
||||||
this.focusable = this.getFocusable()
|
this.focusable = this.getFocusable()
|
||||||
this.hasFormData = this.elements.fieldset.elements.length > 0
|
this.hasFormData = this.elements.fieldset.elements.length > 0
|
||||||
|
|
82
umap/tests/test_dashboard.py
Normal file
82
umap/tests/test_dashboard.py
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
import pytest
|
||||||
|
from django.contrib.auth import get_user_model
|
||||||
|
from django.urls import reverse
|
||||||
|
|
||||||
|
from umap.models import Map
|
||||||
|
|
||||||
|
from .base import MapFactory, UserFactory
|
||||||
|
|
||||||
|
User = get_user_model()
|
||||||
|
|
||||||
|
pytestmark = pytest.mark.django_db
|
||||||
|
|
||||||
|
|
||||||
|
def test_user_dashboard_is_restricted_to_logged_in(client):
|
||||||
|
response = client.get(reverse("user_dashboard"))
|
||||||
|
assert response.status_code == 302
|
||||||
|
assert response["Location"] == "/en/login/?next=/en/me"
|
||||||
|
|
||||||
|
|
||||||
|
def test_user_dashboard_display_user_maps(client, map):
|
||||||
|
client.login(username=map.owner.username, password="123123")
|
||||||
|
response = client.get(reverse("user_dashboard"))
|
||||||
|
assert response.status_code == 200
|
||||||
|
body = response.content.decode()
|
||||||
|
assert map.name in body
|
||||||
|
assert f"{map.get_absolute_url()}?edit" in body
|
||||||
|
assert f"{map.get_absolute_url()}?share" in body
|
||||||
|
assert f"/map/{map.pk}/download" in body
|
||||||
|
assert "Everyone (public)" in body
|
||||||
|
assert "Owner only" in body
|
||||||
|
|
||||||
|
|
||||||
|
def test_user_dashboard_do_not_display_blocked_user_maps(client, map):
|
||||||
|
map.share_status = Map.BLOCKED
|
||||||
|
map.save()
|
||||||
|
client.login(username=map.owner.username, password="123123")
|
||||||
|
response = client.get(reverse("user_dashboard"))
|
||||||
|
assert response.status_code == 200
|
||||||
|
body = response.content.decode()
|
||||||
|
assert map.name not in body
|
||||||
|
|
||||||
|
|
||||||
|
def test_user_dashboard_do_not_display_deleted_user_maps(client, map):
|
||||||
|
map.share_status = Map.DELETED
|
||||||
|
map.save()
|
||||||
|
client.login(username=map.owner.username, password="123123")
|
||||||
|
response = client.get(reverse("user_dashboard"))
|
||||||
|
assert response.status_code == 200
|
||||||
|
body = response.content.decode()
|
||||||
|
assert map.name not in body
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("share_status", [Map.DRAFT, Map.PRIVATE, Map.PUBLIC, Map.OPEN])
|
||||||
|
def test_user_dashboard_display_user_team_maps(client, map, team, user, share_status):
|
||||||
|
user.teams.add(team)
|
||||||
|
user.save()
|
||||||
|
map.team = team
|
||||||
|
map.share_status = share_status
|
||||||
|
map.save()
|
||||||
|
assert map.owner != user
|
||||||
|
client.login(username=user.username, password="123123")
|
||||||
|
response = client.get(reverse("user_dashboard"))
|
||||||
|
assert response.status_code == 200
|
||||||
|
body = response.content.decode()
|
||||||
|
assert map.name in body
|
||||||
|
assert map.get_absolute_url() in body
|
||||||
|
|
||||||
|
|
||||||
|
def test_user_dashboard_display_user_maps_distinct(client, map):
|
||||||
|
# cf https://github.com/umap-project/umap/issues/1325
|
||||||
|
anonymap = MapFactory(name="Map witout owner should not appear")
|
||||||
|
user1 = UserFactory(username="user1")
|
||||||
|
user2 = UserFactory(username="user2")
|
||||||
|
map.editors.add(user1)
|
||||||
|
map.editors.add(user2)
|
||||||
|
map.save()
|
||||||
|
client.login(username=map.owner.username, password="123123")
|
||||||
|
response = client.get(reverse("user_dashboard"))
|
||||||
|
assert response.status_code == 200
|
||||||
|
body = response.content.decode()
|
||||||
|
assert body.count(f'<a href="/en/map/test-map_{map.pk}">test map</a>') == 1
|
||||||
|
assert body.count(anonymap.name) == 0
|
|
@ -1,7 +1,7 @@
|
||||||
import pytest
|
import pytest
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
|
||||||
from umap.models import Team
|
from umap.models import Map, Team
|
||||||
|
|
||||||
pytestmark = pytest.mark.django_db
|
pytestmark = pytest.mark.django_db
|
||||||
|
|
||||||
|
@ -15,6 +15,37 @@ def test_can_see_team_maps(client, map, team):
|
||||||
assert map.name in response.content.decode()
|
assert map.name in response.content.decode()
|
||||||
|
|
||||||
|
|
||||||
|
def test_others_cannot_see_team_private_maps_in_team_page(client, map, team, user):
|
||||||
|
map.team = team
|
||||||
|
map.share_status = Map.PRIVATE
|
||||||
|
map.save()
|
||||||
|
url = reverse("team_maps", args=(team.pk,))
|
||||||
|
response = client.get(url)
|
||||||
|
assert response.status_code == 200
|
||||||
|
assert map.name not in response.content.decode()
|
||||||
|
# User is not in team
|
||||||
|
client.login(username=user.username, password="123123")
|
||||||
|
response = client.get(url)
|
||||||
|
assert response.status_code == 200
|
||||||
|
assert map.name not in response.content.decode()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("share_status", [Map.PRIVATE, Map.DRAFT])
|
||||||
|
def test_members_can_see_private_maps_in_team_page(
|
||||||
|
client, map, team, user, share_status
|
||||||
|
):
|
||||||
|
map.team = team
|
||||||
|
map.share_status = share_status
|
||||||
|
map.save()
|
||||||
|
user.teams.add(team)
|
||||||
|
user.save()
|
||||||
|
url = reverse("team_maps", args=(team.pk,))
|
||||||
|
client.login(username=user.username, password="123123")
|
||||||
|
response = client.get(url)
|
||||||
|
assert response.status_code == 200
|
||||||
|
assert map.name not in response.content.decode()
|
||||||
|
|
||||||
|
|
||||||
def test_user_can_see_their_teams(client, team, user):
|
def test_user_can_see_their_teams(client, team, user):
|
||||||
user.teams.add(team)
|
user.teams.add(team)
|
||||||
user.save()
|
user.save()
|
||||||
|
|
|
@ -267,80 +267,6 @@ def test_change_user_slug(client, user, settings):
|
||||||
assert f"/en/user/{user.pk}/" in response.content.decode()
|
assert f"/en/user/{user.pk}/" in response.content.decode()
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
|
||||||
def test_user_dashboard_is_restricted_to_logged_in(client):
|
|
||||||
response = client.get(reverse("user_dashboard"))
|
|
||||||
assert response.status_code == 302
|
|
||||||
assert response["Location"] == "/en/login/?next=/en/me"
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
|
||||||
def test_user_dashboard_display_user_maps(client, map):
|
|
||||||
client.login(username=map.owner.username, password="123123")
|
|
||||||
response = client.get(reverse("user_dashboard"))
|
|
||||||
assert response.status_code == 200
|
|
||||||
body = response.content.decode()
|
|
||||||
assert map.name in body
|
|
||||||
assert f"{map.get_absolute_url()}?edit" in body
|
|
||||||
assert f"{map.get_absolute_url()}?share" in body
|
|
||||||
assert f"/map/{map.pk}/download" in body
|
|
||||||
assert "Everyone (public)" in body
|
|
||||||
assert "Owner only" in body
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
|
||||||
def test_user_dashboard_do_not_display_blocked_user_maps(client, map):
|
|
||||||
map.share_status = Map.BLOCKED
|
|
||||||
map.save()
|
|
||||||
client.login(username=map.owner.username, password="123123")
|
|
||||||
response = client.get(reverse("user_dashboard"))
|
|
||||||
assert response.status_code == 200
|
|
||||||
body = response.content.decode()
|
|
||||||
assert map.name not in body
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
|
||||||
def test_user_dashboard_do_not_display_deleted_user_maps(client, map):
|
|
||||||
map.share_status = Map.DELETED
|
|
||||||
map.save()
|
|
||||||
client.login(username=map.owner.username, password="123123")
|
|
||||||
response = client.get(reverse("user_dashboard"))
|
|
||||||
assert response.status_code == 200
|
|
||||||
body = response.content.decode()
|
|
||||||
assert map.name not in body
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
|
||||||
def test_user_dashboard_display_user_team_maps(client, map, team, user):
|
|
||||||
user.teams.add(team)
|
|
||||||
user.save()
|
|
||||||
map.team = team
|
|
||||||
map.save()
|
|
||||||
client.login(username=user.username, password="123123")
|
|
||||||
response = client.get(reverse("user_dashboard"))
|
|
||||||
assert response.status_code == 200
|
|
||||||
body = response.content.decode()
|
|
||||||
assert map.name in body
|
|
||||||
assert map.get_absolute_url() in body
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
|
||||||
def test_user_dashboard_display_user_maps_distinct(client, map):
|
|
||||||
# cf https://github.com/umap-project/umap/issues/1325
|
|
||||||
anonymap = MapFactory(name="Map witout owner should not appear")
|
|
||||||
user1 = UserFactory(username="user1")
|
|
||||||
user2 = UserFactory(username="user2")
|
|
||||||
map.editors.add(user1)
|
|
||||||
map.editors.add(user2)
|
|
||||||
map.save()
|
|
||||||
client.login(username=map.owner.username, password="123123")
|
|
||||||
response = client.get(reverse("user_dashboard"))
|
|
||||||
assert response.status_code == 200
|
|
||||||
body = response.content.decode()
|
|
||||||
assert body.count(f'<a href="/en/map/test-map_{map.pk}">test map</a>') == 1
|
|
||||||
assert body.count(anonymap.name) == 0
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
def test_logout_should_return_redirect(client, user, settings):
|
def test_logout_should_return_redirect(client, user, settings):
|
||||||
client.login(username=user.username, password="123123")
|
client.login(username=user.username, password="123123")
|
||||||
|
|
Loading…
Reference in a new issue