Compare commits

..

1 Commits

Author SHA1 Message Date
dependabot[bot] d60b6c088f [UPDATE] Update mkdocs-material requirement
Updates the requirements on [mkdocs-material](https://github.com/squidfunk/mkdocs-material) to permit the latest version.
- [Release notes](https://github.com/squidfunk/mkdocs-material/releases)
- [Changelog](https://github.com/squidfunk/mkdocs-material/blob/master/CHANGELOG)
- [Commits](https://github.com/squidfunk/mkdocs-material/compare/9.7.5...9.7.6)

---
updated-dependencies:
- dependency-name: mkdocs-material
  dependency-version: 9.7.6
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-04-13 08:40:44 +00:00
9 changed files with 13 additions and 200 deletions
+2 -4
View File
@@ -16,7 +16,7 @@
# details. # details.
# #
# You should have received a copy of the GNU General Public License along with # You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc., 59 Temple # this program; if not, write to the Free Sofware Foundation, Inc., 59 Temple
# Place - Suite 330, Boston, MA 02111-1307, USA. # Place - Suite 330, Boston, MA 02111-1307, USA.
# #
# #
@@ -110,9 +110,7 @@ class Command(BaseCommand):
p.save(force_lock=True) p.save(force_lock=True)
club_root = SithFile.objects.create(name="clubs", owner=root) club_root = SithFile.objects.create(name="clubs", owner=root)
sas = SithFile.objects.create( sas = SithFile.objects.create(name="SAS", owner=root)
name="SAS", owner=root, id=settings.SITH_SAS_ROOT_DIR_ID
)
main_club = Club.objects.create( main_club = Club.objects.create(
id=1, name="AE", address="6 Boulevard Anatole France, 90000 Belfort" id=1, name="AE", address="6 Boulevard Anatole France, 90000 Belfort"
) )
+3 -7
View File
@@ -131,9 +131,7 @@ class UserQuerySet(models.QuerySet):
if user.has_perm("core.view_hidden_user"): if user.has_perm("core.view_hidden_user"):
return self return self
if user.has_perm("core.view_user"): if user.has_perm("core.view_user"):
return self.filter( return self.filter(Q(is_viewable=True) | Q(whitelisted_users=user))
Q(is_viewable=True) | Q(whitelisted_users=user) | Q(pk=user.pk)
)
if user.is_anonymous: if user.is_anonymous:
return self.none() return self.none()
return self.filter(id=user.id) return self.filter(id=user.id)
@@ -886,10 +884,8 @@ class SithFile(models.Model):
return self.get_parent_path() + "/" + self.name return self.get_parent_path() + "/" + self.name
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
sas_id = settings.SITH_SAS_ROOT_DIR_ID sas = SithFile.objects.filter(id=settings.SITH_SAS_ROOT_DIR_ID).first()
self.is_in_sas = self.id == sas_id or any( self.is_in_sas = sas in self.get_parent_list() or self == sas
p.id == sas_id for p in self.get_parent_list()
)
adding = self._state.adding adding = self._state.adding
super().save(*args, **kwargs) super().save(*args, **kwargs)
if adding: if adding:
-11
View File
@@ -344,14 +344,3 @@ def test_quick_upload_image(
assert ( assert (
parsed["name"] == Path(file.name).stem[: QuickUploadImage.IMAGE_NAME_SIZE - 1] parsed["name"] == Path(file.name).stem[: QuickUploadImage.IMAGE_NAME_SIZE - 1]
) )
@pytest.mark.django_db
def test_populated_sas_is_in_sas():
"""Test that, in the data generated by the populate command,
the SAS has value is_in_sas=True.
If it's not the case, it has no incidence in prod, but it's annoying
in dev and may cause misunderstandings.
"""
assert SithFile.objects.get(id=settings.SITH_SAS_ROOT_DIR_ID).is_in_sas
+4 -12
View File
@@ -410,20 +410,12 @@ class TestUserQuerySetViewableBy:
assert set(viewable) == set(users) assert set(viewable) == set(users)
@pytest.mark.parametrize( @pytest.mark.parametrize(
"user_factory", "user_factory", [old_subscriber_user.make, subscriber_user.make]
[
old_subscriber_user.make,
lambda: old_subscriber_user.make(is_viewable=False),
subscriber_user.make,
lambda: subscriber_user.make(is_viewable=False),
],
) )
def test_can_search(self, users: list[User], user_factory): def test_subscriber(self, users: list[User], user_factory):
user = user_factory() user = user_factory()
viewable = User.objects.filter( viewable = User.objects.filter(id__in=[u.id for u in users]).viewable_by(user)
id__in=[u.id for u in [*users, user]] assert set(viewable) == {users[0], users[1]}
).viewable_by(user)
assert set(viewable) == {user, users[0], users[1]}
def test_whitelist(self, users: list[User]): def test_whitelist(self, users: list[User]):
user = subscriber_user.make() user = subscriber_user.make()
+1 -1
View File
@@ -82,7 +82,7 @@ tests = [
] ]
docs = [ docs = [
"mkdocs<2.0.0,>=1.6.1", "mkdocs<2.0.0,>=1.6.1",
"mkdocs-material>=9.7.5,<10.0.0", "mkdocs-material>=9.7.6,<10.0.0",
"mkdocstrings>=1.0.3,<2.0.0", "mkdocstrings>=1.0.3,<2.0.0",
"mkdocstrings-python>=2.0.3,<3.0.0", "mkdocstrings-python>=2.0.3,<3.0.0",
"mkdocs-include-markdown-plugin>=7.2.1,<8.0.0", "mkdocs-include-markdown-plugin>=7.2.1,<8.0.0",
+1 -3
View File
@@ -50,15 +50,13 @@ class AlbumEditForm(forms.ModelForm):
model = Album model = Album
fields = ["name", "date", "file", "parent", "edit_groups"] fields = ["name", "date", "file", "parent", "edit_groups"]
widgets = { widgets = {
"parent": AutoCompleteSelectAlbum,
"edit_groups": AutoCompleteSelectMultipleGroup, "edit_groups": AutoCompleteSelectMultipleGroup,
} }
name = forms.CharField(max_length=Album.NAME_MAX_LENGTH, label=_("file name")) name = forms.CharField(max_length=Album.NAME_MAX_LENGTH, label=_("file name"))
date = forms.DateField(label=_("Date"), widget=SelectDate, required=True) date = forms.DateField(label=_("Date"), widget=SelectDate, required=True)
recursive = forms.BooleanField(label=_("Apply rights recursively"), required=False) recursive = forms.BooleanField(label=_("Apply rights recursively"), required=False)
parent = forms.ModelChoiceField(
Album.objects.all(), required=True, widget=AutoCompleteSelectAlbum
)
class PictureModerationRequestForm(forms.ModelForm): class PictureModerationRequestForm(forms.ModelForm):
+1 -1
View File
@@ -205,7 +205,7 @@ class AlbumQuerySet(models.QuerySet):
class SASAlbumManager(models.Manager): class SASAlbumManager(models.Manager):
def get_queryset(self): def get_queryset(self):
return super().get_queryset().filter(Q(is_in_sas=True, is_folder=True)) return super().get_queryset().filter(is_in_sas=True, is_folder=True)
class Album(SasFile): class Album(SasFile):
-154
View File
@@ -20,14 +20,12 @@ from django.conf import settings
from django.core.cache import cache from django.core.cache import cache
from django.test import Client, TestCase from django.test import Client, TestCase
from django.urls import reverse from django.urls import reverse
from django.utils.timezone import localdate
from model_bakery import baker from model_bakery import baker
from pytest_django.asserts import assertHTMLEqual, assertInHTML, assertRedirects from pytest_django.asserts import assertHTMLEqual, assertInHTML, assertRedirects
from core.baker_recipes import old_subscriber_user, subscriber_user from core.baker_recipes import old_subscriber_user, subscriber_user
from core.models import Group, User from core.models import Group, User
from sas.baker_recipes import picture_recipe from sas.baker_recipes import picture_recipe
from sas.forms import AlbumEditForm
from sas.models import Album, Picture from sas.models import Album, Picture
# Create your tests here. # Create your tests here.
@@ -66,24 +64,6 @@ def test_main_page_no_form_for_regular_users(client: Client):
assert len(forms) == 0 assert len(forms) == 0
@pytest.mark.django_db
def test_main_page_displayed_albums(client: Client):
"""Test that the right data is displayed on the SAS main page"""
sas = Album.objects.get(id=settings.SITH_SAS_ROOT_DIR_ID)
Album.objects.exclude(id=sas.id).delete()
album_a = baker.make(Album, parent=sas, is_moderated=True)
album_b = baker.make(Album, parent=album_a, is_moderated=True)
album_c = baker.make(Album, parent=sas, is_moderated=True)
baker.make(Album, parent=sas, is_moderated=False)
client.force_login(subscriber_user.make())
res = client.get(reverse("sas:main"))
# album_b is not a direct child of the SAS, so it shouldn't be displayed
# in the categories, but it should appear in the latest albums.
# album_d isn't moderated, so it shouldn't appear at all for a simple user.
assert res.context_data["latest"] == [album_c, album_b, album_a]
assert res.context_data["categories"] == [album_a, album_c]
@pytest.mark.django_db @pytest.mark.django_db
def test_main_page_content_anonymous(client: Client): def test_main_page_content_anonymous(client: Client):
"""Test that public users see only an incentive to login""" """Test that public users see only an incentive to login"""
@@ -153,140 +133,6 @@ class TestAlbumUpload:
assert not album.children.exists() assert not album.children.exists()
@pytest.mark.django_db
class TestAlbumEdit:
@pytest.fixture
def sas_root(self) -> Album:
return Album.objects.get(id=settings.SITH_SAS_ROOT_DIR_ID)
@pytest.fixture
def album(self) -> Album:
return baker.make(
Album, parent_id=settings.SITH_SAS_ROOT_DIR_ID, is_moderated=True
)
@pytest.mark.parametrize(
"user",
[None, lambda: baker.make(User), subscriber_user.make],
)
def test_permission_denied(
self,
client: Client,
album: Album,
user: Callable[[], User] | None,
):
if user:
client.force_login(user())
url = reverse("sas:album_edit", kwargs={"album_id": album.pk})
response = client.get(url)
assert response.status_code == 403
response = client.post(url)
assert response.status_code == 403
def test_sas_root_read_only(self, client: Client, sas_root: Album):
moderator = baker.make(
User, groups=[Group.objects.get(pk=settings.SITH_GROUP_SAS_ADMIN_ID)]
)
client.force_login(moderator)
url = reverse("sas:album_edit", kwargs={"album_id": sas_root.pk})
response = client.get(url)
assert response.status_code == 404
response = client.post(url)
assert response.status_code == 404
@pytest.mark.parametrize(
("excluded", "is_valid"),
[
("name", False),
("date", False),
("file", True),
("parent", False),
("edit_groups", True),
("recursive", True),
],
)
def test_form_required(self, album: Album, excluded: str, is_valid: bool): # noqa: FBT001
data = {
"name": album.name[: Album.NAME_MAX_LENGTH],
"parent": baker.make(Album, parent=album.parent, is_moderated=True).pk,
"date": localdate().strftime("%Y-%m-%d"),
"file": "/random/path",
"edit_groups": [settings.SITH_GROUP_SAS_ADMIN_ID],
"recursive": False,
}
del data[excluded]
assert AlbumEditForm(data=data).is_valid() == is_valid
def test_form_album_name(self, album: Album):
data = {
"name": album.name[: Album.NAME_MAX_LENGTH],
"parent": album.pk,
"date": localdate().strftime("%Y-%m-%d"),
}
assert AlbumEditForm(data=data).is_valid()
data["name"] = album.name[: Album.NAME_MAX_LENGTH + 1]
assert not AlbumEditForm(data=data).is_valid()
def test_update_recursive_parent(self, client: Client, album: Album):
client.force_login(baker.make(User, is_superuser=True))
payload = {
"name": album.name[: Album.NAME_MAX_LENGTH],
"parent": album.pk,
"date": localdate().strftime("%Y-%m-%d"),
}
response = client.post(
reverse("sas:album_edit", kwargs={"album_id": album.pk}), payload
)
assertInHTML("<li>Boucle dans l'arborescence des dossiers</li>", response.text)
assert response.status_code == 200
@pytest.mark.parametrize(
"user",
[
lambda: baker.make(User, is_superuser=True),
lambda: baker.make(
User, groups=[Group.objects.get(pk=settings.SITH_GROUP_SAS_ADMIN_ID)]
),
],
)
@pytest.mark.parametrize(
"parent",
[
lambda: baker.make(
Album, parent_id=settings.SITH_SAS_ROOT_DIR_ID, is_moderated=True
),
lambda: Album.objects.get(id=settings.SITH_SAS_ROOT_DIR_ID),
],
)
def test_update(
self,
client: Client,
album: Album,
sas_root: Album,
user: Callable[[], User],
parent: Callable[[], Album],
):
client.force_login(user())
expected_redirect = reverse("sas:album", kwargs={"album_id": album.pk})
payload = {
"name": album.name[: Album.NAME_MAX_LENGTH],
"parent": parent().id,
"date": localdate().strftime("%Y-%m-%d"),
"recursive": False,
}
response = client.post(
reverse("sas:album_edit", kwargs={"album_id": album.pk}), payload
)
assertRedirects(response, expected_redirect)
album.refresh_from_db()
assert album.name == payload["name"]
assert album.parent.id == payload["parent"]
assert localdate(album.date) == localdate()
class TestSasModeration(TestCase): class TestSasModeration(TestCase):
@classmethod @classmethod
def setUpTestData(cls): def setUpTestData(cls):
+1 -7
View File
@@ -85,9 +85,7 @@ class SASMainView(UseFragmentsMixin, TemplateView):
kwargs["categories"] = list( kwargs["categories"] = list(
albums_qs.filter(parent_id=settings.SITH_SAS_ROOT_DIR_ID).order_by("id") albums_qs.filter(parent_id=settings.SITH_SAS_ROOT_DIR_ID).order_by("id")
) )
kwargs["latest"] = list( kwargs["latest"] = list(albums_qs.order_by("-id")[:5])
albums_qs.exclude(id=settings.SITH_SAS_ROOT_DIR_ID).order_by("-id")[:5]
)
return kwargs return kwargs
@@ -128,9 +126,6 @@ def send_thumb(request, picture_id):
class AlbumView(CanViewMixin, UseFragmentsMixin, DetailView): class AlbumView(CanViewMixin, UseFragmentsMixin, DetailView):
model = Album model = Album
# exclude the SAS from the album accessible with this view
# the SAS can be viewed only with SASMainView
queryset = Album.objects.exclude(id=settings.SITH_SAS_ROOT_DIR_ID)
pk_url_kwarg = "album_id" pk_url_kwarg = "album_id"
template_name = "sas/album.jinja" template_name = "sas/album.jinja"
@@ -267,7 +262,6 @@ class PictureAskRemovalView(CanViewMixin, DetailView, FormView):
class AlbumEditView(CanEditMixin, UpdateView): class AlbumEditView(CanEditMixin, UpdateView):
model = Album model = Album
queryset = Album.objects.exclude(id=settings.SITH_SAS_ROOT_DIR_ID)
form_class = AlbumEditForm form_class = AlbumEditForm
template_name = "core/edit.jinja" template_name = "core/edit.jinja"
pk_url_kwarg = "album_id" pk_url_kwarg = "album_id"