diff --git a/backend/cal/forms.py b/backend/cal/forms.py deleted file mode 100644 index a0333fe71..000000000 --- a/backend/cal/forms.py +++ /dev/null @@ -1,23 +0,0 @@ -from django.forms import ModelForm, DateInput -from cal.models import Event - - -class EventForm(ModelForm): - class Meta: - model = Event - # datetime-local is a HTML5 input type, format to make date time show on fields - widgets = { - "start_time": DateInput( - attrs={"type": "datetime-local"}, format="%Y-%m-%dT%H:%M" - ), - "end_time": DateInput( - attrs={"type": "datetime-local"}, format="%Y-%m-%dT%H:%M" - ), - } - fields = "__all__" - - def __init__(self, *args, **kwargs): - super(EventForm, self).__init__(*args, **kwargs) - # input_formats parses HTML5 datetime-local input to datetime field - self.fields["start_time"].input_formats = ("%Y-%m-%dT%H:%M",) - self.fields["end_time"].input_formats = ("%Y-%m-%dT%H:%M",) diff --git a/backend/core/forms.py b/backend/core/forms.py deleted file mode 100644 index 3c9ba9736..000000000 --- a/backend/core/forms.py +++ /dev/null @@ -1,189 +0,0 @@ -from django.forms import ( - CheckboxInput, - DateInput, - DateTimeInput, - EmailInput, - HiddenInput, - ModelForm, - NullBooleanSelect, - NumberInput, - PasswordInput, - Select, - SelectMultiple, - TextInput, - Textarea, - TimeInput, - URLInput, - CheckboxSelectMultiple, - ValidationError, -) -from django.contrib.auth.forms import SetPasswordForm -from django import forms -from .models import * -from django.utils.translation import gettext_lazy as _ -from django.utils.html import escape -from django.contrib.auth import get_user_model - -User = get_user_model() - - -class LinkCleanMixin: - """ - Prevent code injection in link field - """ - - def clean_link(self): - """ - Method to check if a link is valid - """ - link = self.cleaned_data.get("link") - if link: - link = escape(link) - if not link.startswith(("https://", "ftps://")): - raise ValidationError(_("Invalid link")) - return link - - -class SearchableCheckboxSelectMultiple(CheckboxSelectMultiple): - """ - A searchable checkbox select multiple widget. - - Widget attributes (in addition to the standard ones): - - wrapper_class: class for the wrapper div - - searchbar_class: class for the searchbar - """ - - template_name = "forms/widgets/select_multiple.html" - recommended_applied_controls = None - - def __init__(self, recommended_applied_controls=None, *args, **kwargs) -> None: - super().__init__(*args, **kwargs) - self.recommended_applied_controls = recommended_applied_controls - - def get_context(self, name, value, attrs): - context = super().get_context(name, value, attrs) - if self.recommended_applied_controls: - context["recommended_applied_controls"] = self.recommended_applied_controls - return context - - -class SearchableSelect(Select): - template_name = "forms/widgets/searchable_select.html" - option_template_name = "forms/widgets/select_option.html" - recommended_reference_controls = None - - def __init__(self, recommended_reference_controls=None, *args, **kwargs) -> None: - super().__init__(*args, **kwargs) - self.recommended_reference_controls = recommended_reference_controls - self.id = f"searchable-select-{id(self)}" - - def get_context(self, name, value, attrs): - context = super().get_context(name, value, attrs) - if self.recommended_reference_controls: - context["recommended_reference_controls"] = ( - self.recommended_reference_controls - ) - return context - - -class DefaultDateInput(DateInput): - input_type = "date" - - -class StyledModelForm(ModelForm): - def default_if_one(self, field_name): - field = self.fields[field_name] - if not hasattr(field, "_queryset"): - return - if field._queryset and len(field._queryset) == 1: - field.widget.attrs["disabled"] = True - field.widget.attrs["class"] += " disabled:opacity-50" - field.initial = field.queryset[0] - - def default_if_one_all(self): - for fname, f in self.fields.items(): - self.default_if_one(fname) - - def __init__(self, *args, **kwargs): - super(__class__, self).__init__(*args, **kwargs) - text_inputs = ( - TextInput, - NumberInput, - EmailInput, - URLInput, - PasswordInput, - HiddenInput, - DefaultDateInput, - DateInput, - DateTimeInput, - TimeInput, - ) - select_inputs = (Select, SelectMultiple, NullBooleanSelect) - for fname, f in self.fields.items(): - input_type = f.widget.__class__ - if self.Meta.model: - model_name = str(self.Meta.model).split(".")[-1].strip("'>").lower() - if input_type in text_inputs: - f.widget.attrs["id"] = ( - f"id_{model_name}_{fname}" if model_name else f"id_{fname}" - ) - f.widget.attrs["class"] = ( - "bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5" - ) - if input_type in select_inputs: - f.widget.attrs["id"] = f"id_{model_name}_{fname}" - f.widget.attrs["autocomplete"] = ( - "off" # workaround for Firefox behavior: https://stackoverflow.com/questions/4831848/firefox-ignores-option-selected-selected - ) - f.widget.attrs["class"] = ( - "bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 disabled:opacity-50" - ) - if input_type == Textarea: - f.widget.attrs["class"] = ( - "block p-2.5 w-full text-sm text-gray-900 bg-gray-50 rounded-lg border border-gray-300 focus:ring-blue-500 focus:border-blue-500" - ) - if input_type == CheckboxInput: - f.widget.attrs["id"] = f"id_{model_name}_{fname}" - f.widget.attrs["class"] = ( - "w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500" - ) - if input_type == DefaultDateInput: - f.widget.attrs["id"] = f"id_{model_name}_{fname}" - f.widget.attrs["class"] = ( - "bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5" - ) - if input_type == Select: - self.default_if_one(fname) - - -class ResetForm(forms.Form): - email = forms.EmailField( - label=_("Email"), - widget=forms.TextInput( - attrs={ - "class": "my-2 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50" - } - ), - ) - - -class ResetConfirmForm(SetPasswordForm): - def __init__(self, *args, **kwargs): - style = "my-2 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50" - super(__class__, self).__init__(*args, **kwargs) - for password in self.fields.items(): - password[1].widget.attrs["class"] = style - - -class FirstConnexionConfirmForm(SetPasswordForm): - def __init__(self, *args, **kwargs): - style = "my-2 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50" - super(__class__, self).__init__(*args, **kwargs) - for password in self.fields.items(): - password[1].widget.attrs["class"] = style - self.fields["terms_service"].widget.attrs["class"] = ( - "ml-2 rounded border-gray-300 shadow-sm focus:border-indigo-600 focus:ring focus:ring-indigo-500 focus:ring-opacity-50 text-indigo-500" - ) - self.fields["terms_service"].widget.attrs["id"] = "terms_service" - - terms_service = forms.BooleanField(label=_("terms and conditions of use")) diff --git a/backend/iam/forms.py b/backend/iam/forms.py deleted file mode 100644 index 59b1b171a..000000000 --- a/backend/iam/forms.py +++ /dev/null @@ -1,289 +0,0 @@ -"""this module contains forms related to iam app""" - -from django.forms import ( - CheckboxInput, - DateInput, - DateTimeInput, - EmailInput, - HiddenInput, - ModelForm, - NullBooleanSelect, - NumberInput, - PasswordInput, - Select, - SelectMultiple, - TextInput, - Textarea, - TimeInput, - URLInput, - ValidationError, -) -from django.contrib.auth.forms import UserChangeForm, AdminPasswordChangeForm -from django.urls import reverse -from django.utils.translation import gettext_lazy as _ -from django.contrib.auth import password_validation -from django import forms -from .models import Folder, User, UserGroup, RoleAssignment, Role - -from core.forms import SearchableCheckboxSelectMultiple - - -class DefaultDateInput(DateInput): - """default date for input""" - - input_type = "date" - - -class StyledModelForm(ModelForm): - """a nice ModelForm""" - - def __init__(self, *args, **kwargs): - # pragma pylint: disable=no-member - super(__class__, self).__init__(*args, **kwargs) - text_inputs = ( - TextInput, - NumberInput, - EmailInput, - URLInput, - PasswordInput, - HiddenInput, - DefaultDateInput, - DateInput, - DateTimeInput, - TimeInput, - ) - select_inputs = (Select, SelectMultiple, NullBooleanSelect) - for fname, f in self.fields.items(): - input_type = f.widget.__class__ - if self.Meta.model: - model_name = str(self.Meta.model).split(".")[-1].strip("'>").lower() - if input_type in text_inputs: - f.widget.attrs["id"] = ( - f"id_{model_name}_{fname}" if model_name else f"id_{fname}" - ) - f.widget.attrs[ - "class" - ] = "bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5" - if input_type in select_inputs: - f.widget.attrs["id"] = f"id_{model_name}_{fname}" - f.widget.attrs[ - "class" - ] = "bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5" - if input_type == Textarea: - f.widget.attrs[ - "class" - ] = "block p-2.5 w-full text-sm text-gray-900 bg-gray-50 rounded-lg border border-gray-300 focus:ring-blue-500 focus:border-blue-500" - if input_type == CheckboxInput: - f.widget.attrs["id"] = f"id_{model_name}_{fname}" - f.widget.attrs[ - "class" - ] = "w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500" - if input_type == DefaultDateInput: - f.widget.attrs["id"] = f"id_{model_name}_{fname}" - f.widget.attrs[ - "class" - ] = "bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5" - - -class FolderUpdateForm(StyledModelForm): - """form to update a folder""" - - # pragma pylint: disable=no-member - - class Meta: - """for Model""" - - model = Folder - exclude = ["content_type", "builtin", "parent_folder"] - - -class UserCreationForm(forms.ModelForm): - """A form for creating new users""" - - email = forms.EmailField(max_length=100) - - class Meta: - model = User - fields = ("email",) - - def clean_email(self): - email = self.cleaned_data.get("email") - return email.lower() - - def clean_password2(self): - password1 = self.cleaned_data.get("password1") - password2 = self.cleaned_data.get("password2") - if password1 and password2 and password1 != password2: - raise ValidationError( - self.error_messages["password_mismatch"], - code="password_mismatch", - ) - return password2 - - def _post_clean(self): - super()._post_clean() - # Validate the password after self.instance is updated with form data - # by super(). - password = self.cleaned_data.get("password2") - if password: - try: - password_validation.validate_password(password, self.instance) - except ValidationError as error: - self.add_error("password2", error) - - def save(self, commit=True): - # Save the provided password in hashed format - user = super().save(commit=False) - user.set_password(self.cleaned_data["password1"]) - if commit: - user.save() - return user - - -class UserCreateForm(UserCreationForm, StyledModelForm): - """form to create user""" - - pass - - -class UserUpdateForm(UserChangeForm, StyledModelForm): - """form to update user""" - - def __init__(self, *args, user, **kwargs): - self.user = user - super().__init__(*args, **kwargs) - password = self.fields.get("password") - self.fields["password"].help_text = _( - "Raw passwords are not stored, so there is no way to see this " - "user’s password, but you can change the password using " - 'this form.' - ) - self.fields["password"].widget.attrs["class"] = "text-sm -mb-1 password_update" - self.fields["is_active"].widget.attrs["class"] += " -mt-1" - self.fields["user_groups"].widget = SearchableCheckboxSelectMultiple( - choices=self.fields["user_groups"].choices, - attrs={ - "class": "text-sm rounded", - "searchbar_class": "[&_.search-icon]:text-gray-500 text-sm border border-gray-300 rounded-t-lg px-3", - "wrapper_class": "border border-gray-300 bg-gray-50 text-gray-900 text-sm rounded-b-lg focus:ring-blue-500 focus:border-blue-500 py-2 px-4 max-h-56 overflow-y-scroll", - }, - ) - if password: - password.help_text = password.help_text.format( - reverse("password-change", kwargs={"pk": user.pk}) - ) - - field_order = ["email", "password", "first_name", "last_name", "is_active"] - - def clean_email(self): - email = self.cleaned_data.get("email") - return email.lower() - - class Meta: - """for Model""" - - model = User - fields = [ - "email", - "password", - "first_name", - "last_name", - "is_active", - "user_groups", - ] - - -class MyProfileUpdateForm(UserChangeForm, StyledModelForm): - """form for logged user""" - - # TODO: not sure this section is useful, self user could be in user list with a mention "me" - - def __init__(self, *args, user, **kwargs): - self.user = user - super().__init__(*args, **kwargs) - self.fields["email"].widget.attrs["readonly"] = True - self.fields["email"].help_text = _( - "To change your email address, please contact your administrator." - ) - self.fields["password"].widget.attrs["class"] = "text-sm -mb-1 password_update" - password = self.fields.get("password") - self.fields["password"].help_text = _( - "Raw passwords are not stored, so there is no way to see this " - "user’s password, but you can change the password using " - 'this form.' - ) - if password: - password.help_text = password.help_text.format( - reverse("password-change", kwargs={"pk": user.pk}) - ) - - field_order = ["last_name", "first_name", "password", "email"] - - class Meta: - model = User - exclude = [ - "last_login", - "is_superuser", - "date_joined", - "user_permissions", - "user_groups", - "is_active", - "first_login", - ] - - -class UserPasswordChangeForm(AdminPasswordChangeForm): - """change user password form""" - - def __init__(self, user, *args, **kwargs): - super().__init__(user, *args, **kwargs) - for fname, f in self.fields.items(): - f.widget.attrs[ - "class" - ] = "bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5" - self.fields.get("password1").widget.attrs["id"] = "password1" - self.fields.get("password2").widget.attrs["id"] = "password2" - - -class UserGroupCreateForm(StyledModelForm): - """form to create a user group""" - - class Meta: - """for Model""" - - model = UserGroup - exclude = ["permissions", "builtin"] - - -class UserGroupUpdateForm(StyledModelForm): - """form to update a user group""" - - class Meta: - """for Model""" - - model = UserGroup - exclude = ["permissions", "builtin"] - - -class RoleAssignmentCreateForm(StyledModelForm): - """form to create a RoleAssigment""" - - class Meta: - """for Model""" - - model = RoleAssignment - exclude = ["builtin"] - - -class RoleAssignmentUpdateForm(StyledModelForm): - """form to update a RoleAssigment""" - - class Meta: - """for Model""" - - model = Role - fields = ["permissions"] - - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - self.fields["permissions"].widget.attrs["class"] += " h-96" diff --git a/backend/library/forms.py b/backend/library/forms.py deleted file mode 100644 index 7d6b945bb..000000000 --- a/backend/library/forms.py +++ /dev/null @@ -1,9 +0,0 @@ -from django import forms -from django.utils.translation import gettext_lazy as _ -from library.validators import validate_file_extension - - -class UploadFileForm(forms.Form): - file = forms.FileField( - required=True, label=_("Select a file"), validators=[validate_file_extension] - ) diff --git a/backend/serdes/forms.py b/backend/serdes/forms.py deleted file mode 100644 index 37adbc94a..000000000 --- a/backend/serdes/forms.py +++ /dev/null @@ -1,17 +0,0 @@ -from typing import Any, Dict -from django import forms -from django.utils.translation import gettext_lazy as _ - - -class UploadFileForm(forms.Form): - file = forms.FileField(required=True, label=_("Select a file")) - - def clean(self) -> Dict[str, Any]: - cleaned_data = super().clean() - file = cleaned_data.get("file") - - if file: - if not file.name.endswith(".json"): - self.add_error("file", _("File must be a JSON file.")) - - return file