mirror of
				https://gitlab.crans.org/bde/nk20
				synced 2025-10-30 15:29:53 +01:00 
			
		
		
		
	Compare commits
	
		
			1 Commits
		
	
	
		
			app_downlo
			...
			migration-
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | bb9f58e497 | 
| @@ -7,25 +7,10 @@ stages: | ||||
| variables: | ||||
|   GIT_SUBMODULE_STRATEGY: recursive | ||||
|  | ||||
| # Debian Buster | ||||
| #  py37-django22: | ||||
| #   stage: test | ||||
| #   image: debian:buster-backports | ||||
| #   before_script: | ||||
| #     - > | ||||
| #         apt-get update && | ||||
| #         apt-get install --no-install-recommends -t buster-backports -y | ||||
| #         python3-django python3-django-crispy-forms | ||||
| #         python3-django-extensions python3-django-filters python3-django-polymorphic | ||||
| #         python3-djangorestframework python3-django-oauth-toolkit python3-psycopg2 python3-pil | ||||
| #         python3-babel python3-lockfile python3-pip python3-phonenumbers python3-memcache | ||||
| #         python3-bs4 python3-setuptools tox texlive-xetex | ||||
| #   script: tox -e py37-django22 | ||||
|  | ||||
| # Ubuntu 20.04 | ||||
| py38-django22: | ||||
| # Ubuntu 22.04 | ||||
| py310-django50: | ||||
|   stage: test | ||||
|   image: ubuntu:20.04 | ||||
|   image: ubuntu:22.04 | ||||
|   before_script: | ||||
|     # Fix tzdata prompt | ||||
|     - ln -sf /usr/share/zoneinfo/Europe/Paris /etc/localtime && echo Europe/Paris > /etc/timezone | ||||
| @@ -37,12 +22,12 @@ py38-django22: | ||||
|         python3-djangorestframework python3-django-oauth-toolkit python3-psycopg2 python3-pil | ||||
|         python3-babel python3-lockfile python3-pip python3-phonenumbers python3-memcache | ||||
|         python3-bs4 python3-setuptools tox texlive-xetex | ||||
|   script: tox -e py38-django22 | ||||
|   script: tox -e py310-django50 | ||||
|  | ||||
| # Debian Bullseye | ||||
| py39-django22: | ||||
| # Debian Bookworm | ||||
| py311-django50: | ||||
|   stage: test | ||||
|   image: debian:bullseye | ||||
|   image: debian:bookworm | ||||
|   before_script: | ||||
|     - > | ||||
|         apt-get update && | ||||
| @@ -52,7 +37,7 @@ py39-django22: | ||||
|         python3-djangorestframework python3-django-oauth-toolkit python3-psycopg2 python3-pil | ||||
|         python3-babel python3-lockfile python3-pip python3-phonenumbers python3-memcache | ||||
|         python3-bs4 python3-setuptools tox texlive-xetex | ||||
|   script: tox -e py39-django22 | ||||
|   script: tox -e py311-django50 | ||||
|  | ||||
| linters: | ||||
|   stage: quality-assurance | ||||
|   | ||||
| @@ -1,6 +1,8 @@ | ||||
| # Copyright (C) 2018-2024 by BDE ENS Paris-Saclay | ||||
| # SPDX-License-Identifier: GPL-3.0-or-later | ||||
|  | ||||
| from bootstrap_datepicker_plus.widgets import DateTimePickerInput | ||||
|  | ||||
| from datetime import timedelta | ||||
| from random import shuffle | ||||
|  | ||||
| @@ -10,7 +12,7 @@ from django.utils import timezone | ||||
| from django.utils.translation import gettext_lazy as _ | ||||
| from member.models import Club | ||||
| from note.models import Note, NoteUser | ||||
| from note_kfet.inputs import Autocomplete, DateTimePickerInput | ||||
| from note_kfet.inputs import Autocomplete | ||||
| from note_kfet.middlewares import get_current_request | ||||
| from permission.backends import PermissionBackend | ||||
|  | ||||
|   | ||||
| @@ -2,7 +2,7 @@ | ||||
| # SPDX-License-Identifier: GPL-3.0-or-later | ||||
|  | ||||
| from django.conf import settings | ||||
| from django.conf.urls import url, include | ||||
| from django.urls import include, re_path | ||||
| from rest_framework import routers | ||||
|  | ||||
| from .views import UserInformationView | ||||
| @@ -47,7 +47,7 @@ app_name = 'api' | ||||
| # Wire up our API using automatic URL routing. | ||||
| # Additionally, we include login URLs for the browsable API. | ||||
| urlpatterns = [ | ||||
|     url('^', include(router.urls)), | ||||
|     url('^me/', UserInformationView.as_view()), | ||||
|     url('^api-auth/', include('rest_framework.urls', namespace='rest_framework')), | ||||
|     re_path('^', include(router.urls)), | ||||
|     re_path('^me/', UserInformationView.as_view()), | ||||
|     re_path('^api-auth/', include('rest_framework.urls', namespace='rest_framework')), | ||||
| ] | ||||
|   | ||||
| @@ -3,6 +3,7 @@ | ||||
|  | ||||
| import io | ||||
|  | ||||
| from bootstrap_datepicker_plus.widgets import DatePickerInput | ||||
| from PIL import Image, ImageSequence | ||||
| from django import forms | ||||
| from django.conf import settings | ||||
| @@ -13,7 +14,7 @@ from django.forms import CheckboxSelectMultiple | ||||
| from django.utils import timezone | ||||
| from django.utils.translation import gettext_lazy as _ | ||||
| from note.models import NoteSpecial, Alias | ||||
| from note_kfet.inputs import Autocomplete, AmountInput, DatePickerInput | ||||
| from note_kfet.inputs import Autocomplete, AmountInput | ||||
| from permission.models import PermissionMask, Role | ||||
|  | ||||
| from .models import Profile, Club, Membership | ||||
| @@ -32,7 +33,7 @@ class UserForm(forms.ModelForm): | ||||
|         # Django usernames can only contain letters, numbers, @, ., +, - and _. | ||||
|         # We want to allow users to have uncommon and unpractical usernames: | ||||
|         # That is their problem, and we have normalized aliases for us. | ||||
|         return super()._get_validation_exclusions() + ["username"] | ||||
|         return super()._get_validation_exclusions() | {"username"} | ||||
|  | ||||
|     class Meta: | ||||
|         model = User | ||||
|   | ||||
| @@ -44,7 +44,7 @@ class TemplateLoggedInTests(TestCase): | ||||
|         self.assertRedirects(response, settings.LOGIN_REDIRECT_URL, 302, 302) | ||||
|  | ||||
|     def test_logout(self): | ||||
|         response = self.client.get(reverse("logout")) | ||||
|         response = self.client.post(reverse("logout")) | ||||
|         self.assertEqual(response.status_code, 200) | ||||
|  | ||||
|     def test_admin_index(self): | ||||
|   | ||||
| @@ -13,7 +13,7 @@ def register_note_urls(router, path): | ||||
|     router.register(path + '/note', NotePolymorphicViewSet) | ||||
|     router.register(path + '/alias', AliasViewSet) | ||||
|     router.register(path + '/trust', TrustViewSet) | ||||
|     router.register(path + '/consumer', ConsumerViewSet) | ||||
|     router.register(path + '/consumer', ConsumerViewSet, basename="consumer") | ||||
|  | ||||
|     router.register(path + '/transaction/category', TemplateCategoryViewSet) | ||||
|     router.register(path + '/transaction/transaction', TransactionViewSet) | ||||
|   | ||||
| @@ -179,19 +179,10 @@ class ConsumerViewSet(ReadOnlyProtectedModelViewSet): | ||||
|             # We match first an alias if it is matched without normalization, | ||||
|             # then if the normalized pattern matches a normalized alias. | ||||
|             queryset = queryset.filter( | ||||
|                 **{f'name{suffix}': alias_prefix + alias} | ||||
|             ).union( | ||||
|                 queryset.filter( | ||||
|                     Q(**{f'normalized_name{suffix}': alias_prefix + Alias.normalize(alias)}) | ||||
|                     & ~Q(**{f'name{suffix}': alias_prefix + alias}) | ||||
|                 ), | ||||
|                 all=True).union( | ||||
|                 queryset.filter( | ||||
|                     Q(**{f'normalized_name{suffix}': alias_prefix + alias.lower()}) | ||||
|                     & ~Q(**{f'normalized_name{suffix}': alias_prefix + Alias.normalize(alias)}) | ||||
|                     & ~Q(**{f'name{suffix}': alias_prefix + alias}) | ||||
|                 ), | ||||
|                 all=True) | ||||
|                 Q(**{f'name{suffix}': alias_prefix + alias}) | ||||
|                 | Q(**{f'normalized_name{suffix}': alias_prefix + Alias.normalize(alias)}) | ||||
|                 | Q(**{f'normalized_name{suffix}': alias_prefix + alias.lower()}) | ||||
|             ) | ||||
|  | ||||
|         queryset = queryset if settings.DATABASES[queryset.db]["ENGINE"] == 'django.db.backends.postgresql' \ | ||||
|             else queryset.order_by("name") | ||||
|   | ||||
| @@ -1,13 +1,15 @@ | ||||
| # Copyright (C) 2018-2024 by BDE ENS Paris-Saclay | ||||
| # SPDX-License-Identifier: GPL-3.0-or-later | ||||
|  | ||||
| from datetime import datetime | ||||
|  | ||||
| from bootstrap_datepicker_plus.widgets import DateTimePickerInput | ||||
| from django import forms | ||||
| from django.contrib.contenttypes.models import ContentType | ||||
| from django.forms import CheckboxSelectMultiple | ||||
| from django.utils.timezone import make_aware | ||||
| from django.utils.translation import gettext_lazy as _ | ||||
| from note_kfet.inputs import Autocomplete, AmountInput, DateTimePickerInput | ||||
| from note_kfet.inputs import Autocomplete, AmountInput | ||||
|  | ||||
| from .models import TransactionTemplate, NoteClub, Alias | ||||
|  | ||||
|   | ||||
| @@ -18,6 +18,7 @@ def create_special_notes(apps, schema_editor): | ||||
| class Migration(migrations.Migration): | ||||
|     dependencies = [ | ||||
|         ('note', '0001_initial'), | ||||
|         ('logs', '0001_initial'), | ||||
|     ] | ||||
|  | ||||
|     operations = [ | ||||
|   | ||||
| @@ -0,0 +1,25 @@ | ||||
| # Generated by Django 5.0.7 on 2024-07-11 09:24 | ||||
|  | ||||
| import django.db.models.deletion | ||||
| from django.db import migrations, models | ||||
|  | ||||
|  | ||||
| class Migration(migrations.Migration): | ||||
|  | ||||
|     dependencies = [ | ||||
|         ('contenttypes', '0002_remove_content_type_name'), | ||||
|         ('note', '0006_trust'), | ||||
|     ] | ||||
|  | ||||
|     operations = [ | ||||
|         migrations.AlterField( | ||||
|             model_name='note', | ||||
|             name='polymorphic_ctype', | ||||
|             field=models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='polymorphic_%(app_label)s.%(class)s_set+', to='contenttypes.contenttype'), | ||||
|         ), | ||||
|         migrations.AlterField( | ||||
|             model_name='transaction', | ||||
|             name='polymorphic_ctype', | ||||
|             field=models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='polymorphic_%(app_label)s.%(class)s_set+', to='contenttypes.contenttype'), | ||||
|         ), | ||||
|     ] | ||||
| @@ -9,7 +9,7 @@ SPDX-License-Identifier: GPL-3.0-or-later | ||||
|            name="{{ widget.name }}" | ||||
|            {# Other attributes are loaded  #} | ||||
|            {% for name, value in widget.attrs.items %} | ||||
|                 {% ifnotequal value False %}{{ name }}{% ifnotequal value True %}="{{ value|stringformat:'s' }}"{% endifnotequal %}{% endifnotequal %} | ||||
|                 {% if value != False %}{{ name }}{% if value != True %}="{{ value|stringformat:'s' }}"{% endif %}{% endif %} | ||||
|             {% endfor %}> | ||||
|     <div class="input-group-append"> | ||||
|         <span class="input-group-text">€</span> | ||||
|   | ||||
| @@ -0,0 +1,19 @@ | ||||
| # Generated by Django 5.0.7 on 2024-07-11 09:24 | ||||
|  | ||||
| from django.db import migrations, models | ||||
|  | ||||
|  | ||||
| class Migration(migrations.Migration): | ||||
|  | ||||
|     dependencies = [ | ||||
|         ('note', '0007_alter_note_polymorphic_ctype_and_more'), | ||||
|         ('treasury', '0008_auto_20240322_0045'), | ||||
|     ] | ||||
|  | ||||
|     operations = [ | ||||
|         migrations.AlterField( | ||||
|             model_name='sogecredit', | ||||
|             name='transactions', | ||||
|             field=models.ManyToManyField(blank=True, related_name='+', to='note.membershiptransaction', verbose_name='membership transactions'), | ||||
|         ), | ||||
|     ] | ||||
| @@ -1,13 +1,14 @@ | ||||
| # Copyright (C) 2018-2024 by BDE ENS Paris-Saclay | ||||
| # SPDX-License-Identifier: GPL-3.0-or-later | ||||
|  | ||||
| from bootstrap_datepicker_plus.widgets import DatePickerInput | ||||
| from django import forms | ||||
| from django.contrib.auth.models import User | ||||
| from django.db.models import Q | ||||
| from django.forms import CheckboxSelectMultiple | ||||
| from django.utils.translation import gettext_lazy as _ | ||||
| from note.models import NoteSpecial, NoteUser | ||||
| from note_kfet.inputs import AmountInput, DatePickerInput, Autocomplete, ColorWidget | ||||
| from note_kfet.inputs import AmountInput, Autocomplete, ColorWidget | ||||
|  | ||||
| from ..models import WEIClub, WEIRegistration, Bus, BusTeam, WEIMembership, WEIRole | ||||
|  | ||||
|   | ||||
| @@ -439,7 +439,7 @@ class TestWEIRegistration(TestCase): | ||||
|             emergency_contact_phone='+33123456789', | ||||
|         )) | ||||
|         self.assertEqual(response.status_code, 200) | ||||
|         self.assertTrue("This user can't be in her/his first year since he/she has already participated to a WEI." | ||||
|         self.assertTrue("This user can't be in her/his first year since he/she has already participated to a WEI." | ||||
|                         in str(response.context["form"].errors)) | ||||
|  | ||||
|         # Check that if the WEI is started, we can't register anyone | ||||
| @@ -635,7 +635,7 @@ class TestWEIRegistration(TestCase): | ||||
|         )) | ||||
|         self.assertEqual(response.status_code, 200) | ||||
|         self.assertFalse(response.context["form"].is_valid()) | ||||
|         self.assertTrue("This team doesn't belong to the given bus." in str(response.context["form"].errors)) | ||||
|         self.assertTrue("This team doesn't belong to the given bus." in str(response.context["form"].errors)) | ||||
|  | ||||
|         response = self.client.post(reverse("wei:validate_registration", kwargs=dict(pk=self.registration.pk)), dict( | ||||
|             roles=[WEIRole.objects.get(name="GC WEI").id], | ||||
|   | ||||
| @@ -25,19 +25,13 @@ admin_site.register(Site, SiteAdmin) | ||||
|  | ||||
| # Add external apps model | ||||
| if "oauth2_provider" in settings.INSTALLED_APPS: | ||||
|     from oauth2_provider.admin import Application, ApplicationAdmin, Grant, \ | ||||
|         GrantAdmin, AccessToken, AccessTokenAdmin, RefreshToken, RefreshTokenAdmin | ||||
|     from oauth2_provider.admin import ApplicationAdmin, GrantAdmin, AccessTokenAdmin, RefreshTokenAdmin | ||||
|     from oauth2_provider.models import Application, Grant, AccessToken, RefreshToken | ||||
|     admin_site.register(Application, ApplicationAdmin) | ||||
|     admin_site.register(Grant, GrantAdmin) | ||||
|     admin_site.register(AccessToken, AccessTokenAdmin) | ||||
|     admin_site.register(RefreshToken, RefreshTokenAdmin) | ||||
|  | ||||
| if "django_htcpcp_tea" in settings.INSTALLED_APPS: | ||||
|     from django_htcpcp_tea.admin import * | ||||
|     from django_htcpcp_tea.models import * | ||||
|     admin_site.register(Pot, PotAdmin) | ||||
|     admin_site.register(TeaType, TeaTypeAdmin) | ||||
|     admin_site.register(Addition, AdditionAdmin) | ||||
|  | ||||
| if "mailer" in settings.INSTALLED_APPS: | ||||
|     from mailer.admin import * | ||||
| @@ -50,9 +44,3 @@ if "rest_framework" in settings.INSTALLED_APPS: | ||||
|     from rest_framework.authtoken.admin import * | ||||
|     from rest_framework.authtoken.models import * | ||||
|     admin_site.register(Token, TokenAdmin) | ||||
|  | ||||
| if "cas_server" in settings.INSTALLED_APPS: | ||||
|     from cas_server.admin import * | ||||
|     from cas_server.models import * | ||||
|     admin_site.register(ServicePattern, ServicePatternAdmin) | ||||
|     admin_site.register(FederatedIendityProvider, FederatedIendityProviderAdmin) | ||||
|   | ||||
| @@ -41,7 +41,7 @@ INSTALLED_APPS = [ | ||||
|     'bootstrap_datepicker_plus', | ||||
|     'colorfield', | ||||
|     'crispy_forms', | ||||
|     'django_htcpcp_tea', | ||||
|     'crispy_bootstrap4', | ||||
|     'django_tables2', | ||||
|     'mailer', | ||||
|     'phonenumber_field', | ||||
| @@ -90,7 +90,6 @@ MIDDLEWARE = [ | ||||
|     'django.middleware.clickjacking.XFrameOptionsMiddleware', | ||||
|     'django.middleware.locale.LocaleMiddleware', | ||||
|     'django.contrib.sites.middleware.CurrentSiteMiddleware', | ||||
|     'django_htcpcp_tea.middleware.HTCPCPTeaMiddleware', | ||||
|     'note_kfet.middlewares.SessionMiddleware', | ||||
|     'note_kfet.middlewares.LoginByIPMiddleware', | ||||
|     'note_kfet.middlewares.TurbolinksMiddleware', | ||||
| @@ -295,3 +294,6 @@ PHONENUMBER_DEFAULT_REGION = 'FR' | ||||
|  | ||||
| # We add custom information to CAS, in order to give a normalized name to other services | ||||
| CAS_AUTH_CLASS = 'member.auth.CustomAuthUser' | ||||
|  | ||||
| # Default field for primary key | ||||
| DEFAULT_AUTO_FIELD = "django.db.models.AutoField" | ||||
|   | ||||
| @@ -8,7 +8,7 @@ SPDX-License-Identifier: GPL-3.0-or-later | ||||
|    {% if widget.value != None and widget.value != "" %}value="{{ widget.value }}"{% endif %} | ||||
|    name="{{ widget.name }}_name" autocomplete="off" | ||||
|     {% for name, value in widget.attrs.items %} | ||||
|         {% ifnotequal value False %}{{ name }}{% ifnotequal value True %}="{{ value|stringformat:'s' }}"{% endifnotequal %}{% endifnotequal %} | ||||
|         {% if value != False %}{{ name }}{% if value != True %}="{{ value|stringformat:'s' }}"{% endif %}{% endif %} | ||||
|     {% endfor %} | ||||
|     aria-describedby="{{widget.attrs.id}}_tooltip"> | ||||
|     {% if widget.resetable %} | ||||
|   | ||||
| @@ -126,9 +126,12 @@ SPDX-License-Identifier: GPL-3.0-or-later | ||||
|                                 <a class="dropdown-item" href="{% url 'member:user_detail' pk=request.user.pk %}"> | ||||
|                                     <i class="fa fa-user"></i> {% trans "My account" %} | ||||
|                                 </a> | ||||
|                                 <a class="dropdown-item" href="{% url 'logout' %}"> | ||||
|                                 <form method="post" action="{% url 'logout' %}"> | ||||
|                                   {% csrf_token %} | ||||
|                                   <button class="dropdown-item" type="submit"> | ||||
|                                     <i class="fa fa-sign-out"></i> {% trans "Log out" %} | ||||
|                                 </a> | ||||
|                                   </button> | ||||
|                                 </form> | ||||
|                             </div> | ||||
|                         </li> | ||||
|                     {% else %} | ||||
|   | ||||
| @@ -30,9 +30,6 @@ urlpatterns = [ | ||||
|     path('accounts/', include('django.contrib.auth.urls')), | ||||
|     path('api/', include('api.urls')), | ||||
|     path('permission/', include('permission.urls')), | ||||
|  | ||||
|     # Make coffee | ||||
|     path('coffee/', include('django_htcpcp_tea.urls')), | ||||
| ] | ||||
|  | ||||
| # During development, serve static and media files | ||||
| @@ -46,11 +43,6 @@ if "oauth2_provider" in settings.INSTALLED_APPS: | ||||
|         path('o/', include('oauth2_provider.urls', namespace='oauth2_provider')) | ||||
|     ) | ||||
|  | ||||
| if "cas_server" in settings.INSTALLED_APPS: | ||||
|     urlpatterns.append( | ||||
|         path('cas/', include('cas_server.urls', namespace='cas_server')) | ||||
|     ) | ||||
|  | ||||
| if "debug_toolbar" in settings.INSTALLED_APPS: | ||||
|     import debug_toolbar | ||||
|     urlpatterns = [ | ||||
|   | ||||
| @@ -1,19 +1,17 @@ | ||||
| beautifulsoup4~=4.7.1 | ||||
| Django~=2.2.15 | ||||
| django-bootstrap-datepicker-plus~=3.0.5 | ||||
| django-cas-server~=1.2.0 | ||||
| django-colorfield~=0.3.2 | ||||
| django-crispy-forms~=1.7.2 | ||||
| django-extensions>=2.1.4 | ||||
| django-filter~=2.1 | ||||
| django-htcpcp-tea~=0.3.1 | ||||
| django-mailer~=2.0.1 | ||||
| django-oauth-toolkit~=1.3.3 | ||||
| django-phonenumber-field~=5.0.0 | ||||
| django-polymorphic>=2.0.3,<3.0.0 | ||||
| djangorestframework>=3.9.0,<3.13.0 | ||||
| django-rest-polymorphic~=0.1.9 | ||||
| django-tables2~=2.3.1 | ||||
| python-memcached~=1.59 | ||||
| phonenumbers~=8.9.10 | ||||
| beautifulsoup4~=4.12.3 | ||||
| crispy-bootstrap4~=2024.1 | ||||
| Django~=5.0.7 | ||||
| django-bootstrap-datepicker-plus~=5.0.5 | ||||
| django-colorfield~=0.11.0 | ||||
| django-crispy-forms~=2.2 | ||||
| django-extensions~=3.2.3 | ||||
| django-filter~=24.2 | ||||
| django-mailer~=2.3.2 | ||||
| django-oauth-toolkit~=2.4.0 | ||||
| django-phonenumber-field~=8.0.0 | ||||
| django-polymorphic~=3.1.0 | ||||
| django-rest-polymorphic~=0.1.10 | ||||
| django-tables2~=2.7.0 | ||||
| djangorestframework~=3.15.2 | ||||
| phonenumbers~=8.13.40 | ||||
| Pillow>=5.4.1 | ||||
|   | ||||
		Reference in New Issue
	
	Block a user