Skip to content

Commit

Permalink
Single table for file attachments (inventree#7420)
Browse files Browse the repository at this point in the history
* Add basic model for handling generic attachments

* Refactor migration

* Data migration to convert old files across

* Admin updates

* Increase comment field max_length

* Adjust field name

* Remove legacy serializer classes / endpoints

* Expose new model to API

* Admin site list filters

* Remove legacy attachment models

- Add new mixin class to designate which models can have attachments

* Update data migration

- Ensure other apps are at the correct migration state beforehand

* Add migrations to remove legacy attachment tables

* Fix for "rename_attachment" callback

* Refactor model_type field

- ContentType does not allow easy API serialization

* Set allowed options for admin

* Update model verbose names

* Fix logic for file upload

* Add choices for serializer

* Add API filtering

* Fix for API filter

* Fix for attachment tables in PUI

- Still not solved permission issues

* Bump API version

* Record user when uploading attachment via API

* Refactor <AttachmentTable /> for PUI

* Display 'file_size' in PUI attachment table

* Fix company migrations

* Include permission informtion in roles API endpoint

* Read user permissions in PUI

* Simplify permission checks for <AttachmentTable />

* Automatically clean up old content types

* Cleanup PUI

* Fix typo in data migration

* Add reverse data migration

* Update unit tests

* Use InMemoryStorage for media files in test mode

* Data migration unit test

* Fix "model_type" field

- It is a required field after all

* Add permission check for serializer

* Fix permission check for CUI

* Fix PUI import

* Test python lib against specific branch

- Will be reverted once code is merged

* Revert STORAGES setting

- Might be worth looking into again

* Fix part unit test

* Fix unit test for sales order

* Use 'get_global_setting'

* Use 'get_global_setting'

* Update setting getter

* Unit tests

* Tweaks

* Revert change to settings.py

* More updates for get_global_setting

* Relax API query count requirement

* remove illegal chars and add unit tests

* Fix unit tests

* Fix frontend unit tests

* settings management updates

* Prevent db write under more conditions

* Simplify settings code

* Pop values before creating filters

* Prevent settings write under certain conditions

* Add debug msg

* Clear db on record import

* Refactor permissions checks

- Allows extension / customization of permission checks at a later date

* Unit test updates

* Prevent delete of attachment without correct permissions

* Adjust odcker.yaml

* Cleanup data migrations

* Tweak migration tests for build app

* Update data migration

- Handle case with missing data

* Prevent debug shell in TESTING mode

* Update migration dependencies

- Ensure all apps are "up to date" before removing legacy tables

* add file size test

* Update migration tests

* Revert some settings caching changes

* Fix incorrect logic in migration

* Update unit tests

* Prevent create on CURRENCY_CODES

- Seems to play havoc with bootup sequence

* Fix unit test

* Some refactoring

- Use get_global_setting

* Fix typo

* Revert change

* Add "tags" and "metadata"

* Include "tags" field in API serializer

* add "metadata" endpoint for attachments
  • Loading branch information
SchrodingersGat authored and martonmiklos committed Jun 24, 2024
1 parent 527921b commit 4bc6de2
Show file tree
Hide file tree
Showing 111 changed files with 1,550 additions and 1,235 deletions.
4 changes: 2 additions & 2 deletions .github/actions/migration/action.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,5 @@ runs:
invoke export-records -f data.json
python3 ./src/backend/InvenTree/manage.py flush --noinput
invoke migrate
invoke import-records -f data.json
invoke import-records -f data.json
invoke import-records -c -f data.json
invoke import-records -c -f data.json
7 changes: 4 additions & 3 deletions .github/workflows/docker.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -115,9 +115,10 @@ jobs:
- name: Run Unit Tests
run: |
echo "GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }}" >> contrib/container/docker.dev.env
docker compose --project-directory . -f contrib/container/dev-docker-compose.yml run inventree-dev-server invoke test --disable-pty
docker compose --project-directory . -f contrib/container/dev-docker-compose.yml run inventree-dev-server invoke test --migrations --disable-pty
docker compose --project-directory . -f contrib/container/dev-docker-compose.yml down
docker compose --project-directory . -f contrib/container/dev-docker-compose.yml run --rm inventree-dev-server invoke test --disable-pty
- name: Run Migration Tests
run: |
docker compose --project-directory . -f contrib/container/dev-docker-compose.yml run --rm inventree-dev-server invoke test --migrations
- name: Clean up test folder
run: |
rm -rf InvenTree/_testfolder
Expand Down
16 changes: 0 additions & 16 deletions src/backend/InvenTree/InvenTree/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -419,22 +419,6 @@ def download_queryset(self, queryset, export_format):
raise NotImplementedError('download_queryset method not implemented!')


class AttachmentMixin:
"""Mixin for creating attachment objects, and ensuring the user information is saved correctly."""

permission_classes = [permissions.IsAuthenticated, RolePermission]

filter_backends = SEARCH_ORDER_FILTER

search_fields = ['attachment', 'comment', 'link']

def perform_create(self, serializer):
"""Save the user information when a file is uploaded."""
attachment = serializer.save()
attachment.user = self.request.user
attachment.save()


class APISearchViewSerializer(serializers.Serializer):
"""Serializer for the APISearchView."""

Expand Down
13 changes: 8 additions & 5 deletions src/backend/InvenTree/InvenTree/api_version.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
"""InvenTree API version information."""

# InvenTree API version
INVENTREE_API_VERSION = 206
INVENTREE_API_VERSION = 207

"""Increment this API version number whenever there is a significant change to the API that any clients need to know about."""

INVENTREE_API_TEXT = """
<<<<<<< HEAD
v206 - 2024-05-05 : https://github.com/inventree/InvenTree/pull/7164
v208 - 2024-05-05 : https://github.com/inventree/InvenTree/pull/7164
- Adds test statistics endpoint
=======
v207 - 2024-06-09 : https://github.com/inventree/InvenTree/pull/7420
- Moves all "Attachment" models into a single table
- All "Attachment" operations are now performed at /api/attachment/
- Add permissions information to /api/user/roles/ endpoint
v206 - 2024-06-08 : https://github.com/inventree/InvenTree/pull/7417
- Adds "choices" field to the PartTestTemplate model
>>>>>>> a90b05add (Test result choices (#7417))
v205 - 2024-06-03 : https://github.com/inventree/InvenTree/pull/7284
- Added model_type and model_id fields to the "NotesImage" serializer
Expand Down
4 changes: 2 additions & 2 deletions src/backend/InvenTree/InvenTree/exchange.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from djmoney.contrib.exchange.models import ExchangeBackend, Rate

from common.currency import currency_code_default, currency_codes
from common.settings import get_global_setting

logger = logging.getLogger('inventree')

Expand All @@ -22,14 +23,13 @@ class InvenTreeExchange(SimpleExchangeBackend):

def get_rates(self, **kwargs) -> dict:
"""Set the requested currency codes and get rates."""
from common.models import InvenTreeSetting
from plugin import registry

base_currency = kwargs.get('base_currency', currency_code_default())
symbols = kwargs.get('symbols', currency_codes())

# Find the selected exchange rate plugin
slug = InvenTreeSetting.get_setting('CURRENCY_UPDATE_PLUGIN', '', create=False)
slug = get_global_setting('CURRENCY_UPDATE_PLUGIN', create=False)

if slug:
plugin = registry.get_plugin(slug)
Expand Down
2 changes: 1 addition & 1 deletion src/backend/InvenTree/InvenTree/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def __init__(self, **kwargs):

def run_validation(self, data=empty):
"""Override default validation behaviour for this field type."""
strict_urls = get_global_setting('INVENTREE_STRICT_URLS', True, cache=False)
strict_urls = get_global_setting('INVENTREE_STRICT_URLS', cache=False)

if not strict_urls and data is not empty and '://' not in data:
# Validate as if there were a schema provided
Expand Down
5 changes: 2 additions & 3 deletions src/backend/InvenTree/InvenTree/middleware.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from allauth_2fa.middleware import AllauthTwoFactorMiddleware, BaseRequire2FAMiddleware
from error_report.middleware import ExceptionProcessor

from common.settings import get_global_setting
from InvenTree.urls import frontendpatterns
from users.models import ApiToken

Expand Down Expand Up @@ -153,11 +154,9 @@ class Check2FAMiddleware(BaseRequire2FAMiddleware):

def require_2fa(self, request):
"""Use setting to check if MFA should be enforced for frontend page."""
from common.models import InvenTreeSetting

try:
if url_matcher.resolve(request.path[1:]):
return InvenTreeSetting.get_setting('LOGIN_ENFORCE_MFA')
return get_global_setting('LOGIN_ENFORCE_MFA')
except Resolver404:
pass
return False
Expand Down
Loading

0 comments on commit 4bc6de2

Please sign in to comment.