Skip to content

Commit

Permalink
merge v1.0.2 release
Browse files Browse the repository at this point in the history
  • Loading branch information
mikkonie authored Sep 9, 2024
2 parents 42d2732 + 474c415 commit e239917
Show file tree
Hide file tree
Showing 31 changed files with 1,055 additions and 544 deletions.
49 changes: 49 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,55 @@ Changelog for the **SODAR Core** Django app package. Loosely follows the
`Keep a Changelog <http://keepachangelog.com/en/1.0.0/>`_ guidelines.


v1.0.2 (2024-09-09)
===================

Added
-----

- **General**
- ``python3.11-gdbm`` dependency (#1491)
- **Projectroles**
- ``get_user_by_uuid()`` common template tag (#1478)
- ``ProjectInvite.get_url()`` helper (#1485)
- ``ProjectInvite.refresh_date_expire()`` helper (#1486)

Changed
-------

- **General**
- Upgrade minimum Django version to v4.2.16 (#1481)
- **Projectroles**
- Truncate app setting values in ``remoteproject_sync.html`` (#1474)
- JSON app setting value rendering in ``remoteproject_sync.html`` (#1472)
- Change ``AppSettingAPI.compare_value()`` into public method (#1479)
- Refactor ``AppLinkContent`` (#1470, #1483)
- **Userprofile**
- Improve user settings list layout (#1490)

Fixed
-----

- **General**
- Celery process raising ``dbm.error`` (#1491)
- Celery process raising ``broker_connection_retry`` warning (#1493)
- **Bgjobs**
- Non-migrated changes reported by squashed migrations (#1475)
- **Projectroles**
- Incorrect app plugin link order in ``get_project_app_links()`` (#1468)
- Remote sync crash on updating user with additional email (#1476)
- User scope app setting display in ``remoteproject_sync.html`` (#1478)
- Incorrect boolean comparison in ``AppSettingAPI._compare_value()`` with string value (#1473)
- Boolean app setting update status in remote sync (#1473)

Removed
-------

- **Projectroles**
- ``build_invite_url()`` utility method (#1485)
- ``get_expiry_date()`` utility method (#1486)


v1.0.1 (2024-08-08)
===================

Expand Down
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ and breaking changes are possible.

.. code-block:: console
pip install django-sodar-core==1.0.1
pip install django-sodar-core==1.0.2
For installing a development version you can point your dependency to a specific
commit ID in GitHub. Note that these versions may not be stable.
Expand Down
2 changes: 0 additions & 2 deletions bgjobs/migrations/0001_squashed_0006_auto_20200526_1657.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,14 +81,12 @@ class Migration(migrations.Migration):
'date_created',
models.DateTimeField(
auto_now_add=True,
default=django.utils.timezone.now,
help_text='DateTime of creation',
),
),
(
'user',
models.ForeignKey(
default=1,
on_delete=django.db.models.deletion.CASCADE,
related_name='background_jobs',
to=settings.AUTH_USER_MODEL,
Expand Down
4 changes: 2 additions & 2 deletions codemeta.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,10 @@
"codeRepository": "https://github.com/bihealth/sodar-core",
"datePublished": "2023-12-06",
"dateModified": "2023-12-06",
"dateCreated": "2024-08-08",
"dateCreated": "2024-09-09",
"description": "SODAR Core: A Django-based framework for scientific data management and analysis web apps",
"keywords": "Python, Django, scientific data managmenent, software library",
"license": "MIT",
"title": "SODAR Core",
"version": "v1.0.1"
"version": "v1.0.2"
}
2 changes: 2 additions & 0 deletions config/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,8 @@
CELERYD_TASK_TIME_LIMIT = 5 * 60
# http://docs.celeryproject.org/en/latest/userguide/configuration.html#task-soft-time-limit
CELERYD_TASK_SOFT_TIME_LIMIT = 60
# https://docs.celeryq.dev/en/latest/userguide/configuration.html#broker-connection-retry-on-startup
CELERY_BROKER_CONNECTION_RETRY_ON_STARTUP = False


# Django REST framework
Expand Down
19 changes: 19 additions & 0 deletions docs/source/app_projectroles_api_rest.rst
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,25 @@ field upon a successfully processed request.
For creation views, the ``sodar_uuid`` of the created object is returned
along with other object fields.

Pagination
----------

From SODAR Core V1.0 onwards, list views support pagination unless otherwise
specified. Pagination can be enabled by providing the ``?page=x`` query string
in the API request. This will change the return data into a paginated format.
Example:

.. code-block:: python
{
'count' 170,
'next': 'api/url?page=3',
'previous': 'api/url?page=1',
'results': [
# ...
]
}
Projectroles REST API Versioning
================================
Expand Down
4 changes: 2 additions & 2 deletions docs/source/app_projectroles_integration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -81,11 +81,11 @@ chapter.

First, add the ``django-sodar-core`` dependency into your
``requirements/base.txt`` file. Make sure you are pointing to the desired
release tag or commit ID.
release tag.

.. code-block:: console
django-sodar-core==1.0.1
django-sodar-core==x.y.z
Install the requirements for development:

Expand Down
2 changes: 1 addition & 1 deletion docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
# The short X.Y version
version = '1.0'
# The full version, including alpha/beta/rc tags
release = '1.0.1'
release = '1.0.2'


# -- General configuration ---------------------------------------------------
Expand Down
7 changes: 4 additions & 3 deletions docs/source/getting_started.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,13 @@ Installation
============

The ``django-sodar-core`` package can be installed into your Django project
from PyPI as follows. It is strongly recommended to specify a version tag, as
the package is under active development and breaking changes are expected.
from PyPI as follows. It is strongly recommended to pin the import to a specific
version tag, as the package is under active development and breaking changes are
expected.

.. code-block:: console
pip install django-sodar-core==1.0.1
pip install django-sodar-core==x.y.z
Please note that the django-sodar-core package only installs
:term:`Django apps<Django App>`, which you need to include in a
Expand Down
26 changes: 26 additions & 0 deletions docs/source/major_changes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,32 @@ older SODAR Core version. For a complete list of changes in current and previous
releases, see the :ref:`full changelog<changelog>`.


v1.0.2 (2024-09-09)
*******************

Release Highlights
==================

- Update app setting rendering in remote sync UI
- Fix project sidebar and dropdown app plugin link order
- Fix remote sync crash on updating user with additional email
- Fix Celery process issues
- General bug fixes and minor updates

Breaking Changes
================

System Prerequisites
--------------------

Django Version
The minimum Django version has been bumped to v4.2.16.
Celery Support
It is recommended to install the ``python3.11-gdbm`` package (or equivalent
for the Python version in use) to ensure full compatibility of the current
Celery implementation.


v1.0.1 (2024-08-08)
*******************

Expand Down
40 changes: 21 additions & 19 deletions projectroles/app_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -302,24 +302,6 @@ def _get_json_value(cls, value):
except Exception:
raise ValueError('Value is not valid JSON: {}'.format(value))

@classmethod
def _compare_value(cls, obj, input_value):
"""
Compare input value to value in an AppSetting object. Return True if
values match, False if there is a mismatch.
:param obj: AppSetting object
:param input_value: Input value (string, int, bool or dict)
:return: Bool
"""
if obj.type == 'JSON':
return (
not obj.value_json and not input_value
) or obj.value_json == cls._get_json_value(input_value)
elif obj.type == 'BOOLEAN':
return bool(int(obj.value)) == input_value
return obj.value == str(input_value)

@classmethod
def _log_set_debug(
cls, action, plugin_name, setting_name, value, project, user
Expand Down Expand Up @@ -587,7 +569,7 @@ def set(
else:
q_kwargs['app_plugin'] = None
setting = AppSetting.objects.get(**q_kwargs)
if cls._compare_value(setting, value):
if cls.compare_value(setting, value):
return False
if validate:
cls.validate(
Expand Down Expand Up @@ -912,6 +894,26 @@ def get_global_value(cls, setting_def):
return not setting_def['local'] # Inverse value
return setting_def.get('global', APP_SETTING_GLOBAL_DEFAULT)

@classmethod
def compare_value(cls, obj, input_value):
"""
Compare input value to value in an AppSetting object. Return True if
values match, False if there is a mismatch.
:param obj: AppSetting object
:param input_value: Input value (string, int, bool or dict)
:return: Bool
"""
if obj.type == 'JSON':
return (
not obj.value_json and not input_value
) or obj.value_json == cls._get_json_value(input_value)
elif obj.type == 'BOOLEAN':
if isinstance(input_value, str):
input_value = bool(int(input_value))
return bool(int(obj.value)) == input_value
return obj.value == str(input_value)


def get_example_setting_default(project=None, user=None):
"""
Expand Down
5 changes: 2 additions & 3 deletions projectroles/email.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from projectroles.app_settings import AppSettingAPI
from projectroles.models import SODARUserAdditionalEmail
from projectroles.plugins import get_app_plugin
from projectroles.utils import build_invite_url, get_display_name
from projectroles.utils import get_display_name


app_settings = AppSettingAPI()
Expand Down Expand Up @@ -502,12 +502,11 @@ def send_invite_mail(invite, request):
:param request: HttpRequest object
:return: Amount of sent email (int)
"""
invite_url = build_invite_url(invite, request)
message = get_invite_body(
project=invite.project,
issuer=invite.issuer,
role_name=invite.role.name,
invite_url=invite_url,
invite_url=invite.get_url(request),
date_expire_str=localtime(invite.date_expire).strftime(
'%Y-%m-%d %H:%M'
),
Expand Down
3 changes: 1 addition & 2 deletions projectroles/management/commands/batchupdateroles.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
SODAR_CONSTANTS,
)
from projectroles.views import RoleAssignmentModifyMixin, ProjectInviteMixin
from projectroles.utils import get_expiry_date, build_secret
from projectroles.utils import build_secret


logger = ManagementCommandLogger(__name__)
Expand Down Expand Up @@ -116,7 +116,6 @@ def _invite_user(self, email, project, role):
project=project,
role=role,
issuer=self.issuer,
date_expire=get_expiry_date(),
secret=build_secret(),
)
self.handle_invite(invite, self.request, add_message=False)
Expand Down
38 changes: 38 additions & 0 deletions projectroles/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from django.db import models
from django.db.models import Q
from django.urls import reverse
from django.utils import timezone
from django.utils.translation import gettext_lazy as _

from djangoplugins.models import Plugin
Expand Down Expand Up @@ -1101,6 +1102,22 @@ def __repr__(self):
values = (self.project.title, self.email, self.role.name, self.active)
return 'ProjectInvite({})'.format(', '.join(repr(v) for v in values))

@classmethod
def _get_date_expire(cls):
"""
Return expiry date based on current date + INVITE_EXPIRY_DAYS
:return: DateTime object
"""
return timezone.now() + timezone.timedelta(
days=settings.PROJECTROLES_INVITE_EXPIRY_DAYS
)

def save(self, *args, **kwargs):
if not self.pk and not self.date_expire: # Set date_expire on create
self.date_expire = self._get_date_expire()
super().save(*args, **kwargs)

# Custom row-level functions

def is_ldap(self):
Expand All @@ -1126,6 +1143,27 @@ def is_ldap(self):
return True
return False

def get_url(self, request):
"""
Return invite URL for a project invitation.
:param request: HttpRequest object
:return: URL (string)
"""
return request.build_absolute_uri(
reverse(
'projectroles:invite_accept', kwargs={'secret': self.secret}
)
)

def reset_date_expire(self):
"""
Reset date_expire to current date plus defined expiry days. Saves the
object.
"""
self.date_expire = self._get_date_expire()
self.save()


# RemoteSite -------------------------------------------------------------------

Expand Down
Loading

0 comments on commit e239917

Please sign in to comment.