Skip to content

Commit 3ee252b

Browse files
authored
Merge pull request #75 from salsburj/add_github_actions_to_5
add github actions to 5
2 parents a83e23b + a049d29 commit 3ee252b

25 files changed

Lines changed: 349 additions & 99 deletions

‎.github/workflows/ci.yml‎

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
permissions:
2+
contents: read
3+
pull-requests: read
4+
5+
name: CI
6+
7+
on: [push, pull_request]
8+
9+
jobs:
10+
checks:
11+
runs-on: ubuntu-latest
12+
steps:
13+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
14+
with:
15+
persist-credentials: false
16+
17+
- name: Set up Python
18+
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
19+
with:
20+
python-version: 3.11
21+
22+
- name: Install Checkers
23+
run: pip install ruff djlint
24+
25+
- name: ruff
26+
run: ruff check .
27+
continue-on-error: true
28+
29+
- name: djlint-formatting
30+
run: djlint --check .
31+
continue-on-error: true
32+
33+
- name: djlint-linting
34+
run: djlint --lint .
35+
continue-on-error: true
36+
test:
37+
runs-on: ubuntu-latest
38+
services:
39+
postgres:
40+
image: postgres:16-alpine
41+
env:
42+
POSTGRES_DB: django-dynamic-attachments
43+
POSTGRES_PASSWORD: django-dynamic-attachments-secret
44+
options: >-
45+
--health-cmd pg_isready
46+
--health-interval 10s
47+
--health-timeout 5s
48+
--health-retries 5
49+
ports:
50+
- 5432:5432
51+
steps:
52+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
53+
with:
54+
persist-credentials: false
55+
56+
- name: Set up Python 3.11
57+
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
58+
with:
59+
python-version: 3.11
60+
61+
- name: Install requirements
62+
run: pip install "django>=5.2.14,<6" "coverage==7.14.0" "ims-bootstrap>=5.3.2,<6"
63+
"python-magic>=0.4.27"
64+
65+
- name: Run Tests (PostgreSQL)
66+
run: python manage.py test
67+
continue-on-error: true
68+
69+
- name: Run Tests (SQLite)
70+
run: TEST_ENGINE=sqlite python manage.py test
71+
continue-on-error: true

‎.github/workflows/zizmor.yml‎

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
name: GitHub Actions Security Analysis with zizmor 🌈
2+
3+
on:
4+
push:
5+
branches: ["**"]
6+
pull_request:
7+
branches: ["**"]
8+
9+
permissions: {}
10+
11+
jobs:
12+
zizmor:
13+
name: Run zizmor 🌈
14+
runs-on: ubuntu-latest
15+
permissions:
16+
security-events: write # Required for upload-sarif (used by zizmor-action) to upload SARIF files.
17+
contents: read # Only needed for private repos. Needed to clone the repo.
18+
actions: read # Only needed for private repos. Needed for upload-sarif to read workflow run info.
19+
steps:
20+
- name: Checkout repository
21+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
22+
with:
23+
persist-credentials: false
24+
25+
- name: Run zizmor 🌈
26+
uses: zizmorcore/zizmor-action@5f14fd08f7cf1cb1609c1e344975f152c7ee938d # v0.5.6

‎Dockerfile‎

Lines changed: 0 additions & 13 deletions
This file was deleted.

‎attachments/__init__.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@
33

44
def session(*args, **kwargs):
55
# Expose utils.session without importing utils from __init__ at module level.
6-
from .utils import session as attachment_session
6+
from attachments.utils import session as attachment_session
77
return attachment_session(*args, **kwargs)

‎attachments/admin.py‎

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
from django import forms
22
from django.contrib import admin
33

4-
from .models import Attachment, Property, Session, Upload
5-
from .utils import import_class
4+
from attachments.models import Attachment, Property, Session, Upload
5+
from attachments.utils import import_class
66

77

88
@admin.register(Attachment)
@@ -40,5 +40,3 @@ class UploadInline (admin.TabularInline):
4040
class SessionAdmin (admin.ModelAdmin):
4141
list_display = ('uuid', 'user', 'template', 'context', 'date_created')
4242
inlines = (UploadInline,)
43-
44-

‎attachments/apps.py‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ def user_has_access(self, request, attachment):
1111
# otherwise fall back to checking request.user.is_authenticated by
1212
# default.
1313
obj = attachment.content_object
14-
14+
1515
if hasattr(obj, 'can_download'):
1616
return obj.can_download(request, attachment)
1717

@@ -20,4 +20,4 @@ def user_has_access(self, request, attachment):
2020
def get_attach_view(self):
2121
from attachments.views import AttachView
2222

23-
return AttachView
23+
return AttachView

‎attachments/exceptions.py‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
class InvalidExtensionException(Exception):
32
"""Exception raised for an attachment with an invalid extension"""
43
pass

‎attachments/forms.py‎

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from django import forms
22

3-
from .models import Attachment, Property, Upload
3+
from attachments.models import Attachment, Property, Upload
44

55

66
PROPERTY_FIELD_CLASSES = {
@@ -14,7 +14,6 @@
1414
}
1515

1616

17-
1817
DEFAULT_FORM_CLASS = forms.CharField
1918

2019
try:
@@ -26,7 +25,7 @@
2625
'model': widgets.Select,
2726
'radio': widgets.RadioSelect,
2827
'boolean': widgets.CheckboxInput,
29-
}
28+
}
3029
DEFAULT_WIDGET_CLASS = widgets.TextInput
3130
except ImportError:
3231
PROPERTY_WIDGET_CLASSES = {
@@ -36,7 +35,7 @@
3635
'model': forms.Select,
3736
'radio': forms.RadioSelect,
3837
'boolean': forms.CheckboxInput,
39-
}
38+
}
4039
DEFAULT_WIDGET_CLASS = forms.TextInput
4140

4241

@@ -60,7 +59,7 @@ def __init__(self, *args, **kwargs):
6059

6160
is_upload = isinstance(instance, Upload)
6261
is_attachment = isinstance(instance, Attachment)
63-
form_data = kwargs.pop('data', self.get_form_data_from_session_data(instance.session.data) if is_upload else {})
62+
form_data = kwargs.pop('data', self.get_form_data_from_session_data(instance.session.data) if is_upload else {})
6463
for prop in qs:
6564
if is_upload:
6665
field_key = 'upload-%d-%s' % (instance.pk, prop.slug)
@@ -93,7 +92,7 @@ def formfield(self, prop, field_class=None, data=None, **kwargs):
9392
defaults.update(kwargs)
9493
field = field_class(**defaults)
9594
return field
96-
95+
9796
@staticmethod
9897
def get_form_data_from_session_data(session_data):
9998
"""
@@ -109,4 +108,4 @@ def get_form_data_from_session_data(session_data):
109108
else:
110109
form_val = val
111110
form_data[key] = form_val
112-
return form_data
111+
return form_data

‎attachments/models.py‎

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ def model_queryset(self, **kwargs):
149149
if hasattr(ModelClass, 'field_model_queryset'):
150150
try:
151151
qs = getattr(ModelClass, 'field_model_queryset')(**kwargs)
152-
except:
152+
except Exception:
153153
qs = getattr(ModelClass, 'field_model_queryset')()
154154
else:
155155
qs = ModelClass.objects.all()
@@ -234,7 +234,7 @@ def attach(self, obj, storage=None, path=None, data=None, send_signal=True):
234234
def is_valid(self):
235235
if not self.content_type:
236236
return True
237-
from .forms import PropertyForm
237+
from attachments.forms import PropertyForm
238238
valids = []
239239
for upload in self.uploads.all():
240240
property_form = PropertyForm(self._request.POST, instance=upload, editable_only=False)
@@ -247,7 +247,7 @@ def is_valid(self):
247247

248248
@property
249249
def upload_forms(self):
250-
from .forms import PropertyForm
250+
from attachments.forms import PropertyForm
251251
for upload in self.uploads.all():
252252
kwargs = {'instance': upload, 'editable_only': False, }
253253
is_bound = (self._request is not None and (self._request.method == 'POST' or self._request.GET.get('bind-form-data', False)))
@@ -294,8 +294,10 @@ def validate_upload(self, upload):
294294
if upload.file_size != 0:
295295
file_mime = magic.from_file(upload.file_path, mime=True)
296296

297-
if (set(mimetypes.guess_all_extensions(file_mime)).isdisjoint(set(allowed_exts)) and
298-
file_mime not in mime_types_overrides.get(ext, [])):
297+
if (
298+
set(mimetypes.guess_all_extensions(file_mime)).isdisjoint(set(allowed_exts))
299+
and file_mime not in mime_types_overrides.get(ext, [])
300+
):
299301
# In case our check for extensions didn't pass we check if the file type (not mimetype)
300302
# is white-listed. If so, we can allow the file to be uploaded.
301303
allowed_types = self.allowed_file_types.split('\n')
@@ -311,6 +313,7 @@ def validate_upload(self, upload):
311313
if max_file_size and upload.file_size > max_file_size:
312314
raise FileSizeException("File is too large to be uploaded, file cannot be greater than {}".format(sizeof_fmt(max_file_size)))
313315

316+
314317
class Upload (models.Model):
315318
session = models.ForeignKey(Session, related_name='uploads', on_delete=models.CASCADE)
316319
file_path = models.TextField(unique=True)
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
{% load bootstrap %}
2-
{% bootstrap_form form %}
32

3+
{% bootstrap_form form %}

0 commit comments

Comments
 (0)