Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into REKDAT-176_disable_mo…
Browse files Browse the repository at this point in the history
…difying_organization_name
  • Loading branch information
Zharktas committed Oct 9, 2024
2 parents a76990d + 5d8edcf commit 6425f0d
Show file tree
Hide file tree
Showing 7 changed files with 61 additions and 83 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,6 @@
from ckan.logic import NotFound
from flask import has_request_context
from logging import getLogger
from datetime import datetime, timedelta
import iso8601
import requests
from html import escape as html_escape
from urllib.parse import quote

Expand Down Expand Up @@ -83,64 +80,6 @@ def call_toolkit_function(fn, args, kwargs):
return getattr(toolkit, fn)(*args, **kwargs)


NEWS_CACHE = None


def get_homepage_news(count=4, cache_duration=timedelta(days=1), language=None):
global NEWS_CACHE
log.debug('Fetching homepage news')
if NEWS_CACHE is None or datetime.now() - NEWS_CACHE[0] > cache_duration:
log.debug('Updating news cache')
news_endpoint_url = toolkit.config.get('ckanext.restricteddata.news.endpoint_url')
news_ssl_verify = toolkit.asbool(toolkit.config.get('ckanext.restricteddata.news.ssl_verify', True))
news_tags = toolkit.config.get('ckanext.restricteddata.news.tags')
news_url_template = toolkit.config.get('ckanext.restricteddata.news.url_template')

if not news_endpoint_url:
log.warning('ckanext.restricteddata.news.endpoint_url not set')
news = []
else:
log.debug('Fetching from %s', news_endpoint_url)
try:
news_items = requests.get(news_endpoint_url, verify=news_ssl_verify).json()
log.debug('Received %i news items', len(news_items))

tags = set(t.strip() for t in news_tags.split(',')) if news_tags else None
if tags:
log.debug('Filtering with tags: %s', repr(tags))
news_items = [n for n in news_items if any(t.get('slug') in tags for t in n.get('tags', []))]

news = [{'title': {tl: t for tl, t in list(item.get('title', {}).items()) if t != 'undefined'},
'content': {tl: t for tl, t in list(item.get('content', {}).items()) if t != 'undefined'},
'published': iso8601.parse_date(item.get('publishedAt')),
'brief': item.get('brief', {}),
'image': '',
'image_alt': '',
'tags': [tag for tag in item.get('tags', []) if tag.get('slug') in news_tags],
'url': {lang: news_url_template.format(**{'id': item.get('id'), 'language': lang})
for lang in list(item.get('title').keys())}}
for item in news_items]
news.sort(key=lambda x: x['published'], reverse=True)

log.debug('Updating news cache with %i news', len(news))
news_cache_timestamp = datetime.now()
NEWS_CACHE = (news_cache_timestamp, news)

except Exception as e:
# Fetch failed for some reason, keep old value until cache invalidates
log.error(e)
news = [] if NEWS_CACHE is None else NEWS_CACHE[1]

else:
log.debug('Returning cached news')
news_cache_timestamp, news = NEWS_CACHE

if language:
news = [n for n in news if language in n.get('title', {}) and language in n.get('content', {})]

return news[:count]


def get_homepage_groups():
return toolkit.get_action('group_list')({}, {
'all_fields': True,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,9 @@ def user_autocomplete(original_action, context, data_dict):
return []

return original_action(context, data_dict)


@toolkit.chained_action
def member_list(original_action, context, data_dict):
data_dict['object_type'] = data_dict.get('object_type', 'package')
return original_action(context, data_dict)
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,15 @@ def member_delete(next_auth: AuthFunction, context: Context, data_dict: DataDict

return next_auth(context, data_dict)

@toolkit.chained_auth_function
def member_list(next_auth: AuthFunction, context: Context, data_dict: DataDict) -> AuthResult:
match data_dict['object_type']:
case 'user':
return sysadmin_only(context, data_dict)

return next_auth(context, data_dict)



def sysadmin_only(contaxt, data_dict):
return {'success': False, 'message': 'Only sysadmins are allowed to call this'}
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@ def get_helpers(self):
helpers.scheming_language_text_or_empty,
'get_lang_prefix': helpers.get_lang_prefix,
'call_toolkit_function': helpers.call_toolkit_function,
'get_homepage_news': helpers.get_homepage_news,
'get_homepage_groups': helpers.get_homepage_groups,
'scheming_category_list': helpers.scheming_category_list,
'build_nav_main': helpers.build_nav_main,
Expand Down Expand Up @@ -208,7 +207,8 @@ def get_actions(self):
return {
'user_create': action.user_create,
'member_roles_list': action.member_roles_list,
'user_autocomplete': action.user_autocomplete
'user_autocomplete': action.user_autocomplete,
'member_list': action.member_list
}

# IAuthFunctions
Expand All @@ -217,6 +217,10 @@ def get_auth_functions(self):
return {
'member_create': auth.member_create,
'member_delete': auth.member_delete,
'member_list': auth.member_list,
'organization_member_create': auth.sysadmin_only,
'organization_member_delete': auth.sysadmin_only,
'organization_member_list': auth.sysadmin_only,
'api_token_create': auth.sysadmin_only,
'user_list': auth.sysadmin_only,
'user_update': auth.sysadmin_only,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,23 +85,4 @@ <h3>{{ _('Suomi.fi open data') }}</h3>
</div>
</div>
</section>

<section>
<h2>Ajankohtaista</h2>
<ul class="news-items">
{% for news in h.get_homepage_news() %}
{% set title = news.title[h.lang()] or news.title.fi %}
{% set published = news.published | datetimeformat('d.M.y') %}
{% set url = news.url[h.lang()] or news.url.fi %}
<li>
<span class="news-published">{{ _('Published') }} {{ published }}</span>
<a class="news-title" href="{{ url }}" aria-label="{{ _('open news item') }} {{ title }}"><h3>{{ title }}</h3></a>
{% for tag in news.tags %}
<span class="news-badge">{{ tag.name[h.lang()] or tag.name.fi }}</span>
{% endfor %}
</li>
{% endfor %}
</ul>
<a class="chevron-link" href="https://palveluhallinta.suomi.fi/{{ h.lang() }}/ajankohtaista/uutiset/">{{ _('Browse all news and disruption notices') }}</a>
</section>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -744,6 +744,45 @@ def test_only_sysadmin_can_manage_organization_members():
assert all(member_id != another_user["id"] for member_id, _, _ in members)


@pytest.mark.usefixtures("with_plugins", "clean_db")
def test_normal_user_has_no_access_to_organization_member_edit_pages(app):
user = User()
organization = Organization(user=user, **minimal_organization())

Check failure on line 750 in ckan/ckanext/ckanext-restricteddata/ckanext/restricteddata/tests/test_plugin.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (F821)

ckan/ckanext/ckanext-restricteddata/ckanext/restricteddata/tests/test_plugin.py:750:20: F821 Undefined name `Organization`

Check failure on line 750 in ckan/ckanext/ckanext-restricteddata/ckanext/restricteddata/tests/test_plugin.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (F821)

ckan/ckanext/ckanext-restricteddata/ckanext/restricteddata/tests/test_plugin.py:750:46: F821 Undefined name `minimal_organization`
client = app.test_client(use_cookies=True)
headers = {"Authorization": APIToken(user=user['name'])["token"]}

# Make sure the user has admin privileges to the organization
result = client.get(toolkit.url_for("organization.edit", id=organization['name']), headers=headers)
assert result.status_code == 200

# Verify the user cannot view the member edit pages
result = client.get(toolkit.url_for("organization.member_new", id=organization['name']), headers=headers)
assert result.status_code == 403

result = client.get(toolkit.url_for("organization.member_delete", id=organization['name'], user=user["id"]),
headers=headers)
assert result.status_code == 403

result = client.get(toolkit.url_for("organization.members", id=organization['name']), headers=headers)
assert result.status_code == 403


@pytest.mark.usefixtures("with_plugins", "clean_db")
def test_member_add_and_delete_for_dataset_in_group(app):
group = Group(**minimal_group())
user = User()
dataset_fields = minimal_dataset_with_one_resource_fields(user)
dataset_fields['groups'] = [{'name': group['name']}]
dataset = Dataset(**dataset_fields)
context = {"user": user["name"], "ignore_auth": False}
members = call_action('member_list', context=context, id=group["name"])
assert len(members) == 1
call_action('member_delete', context=context,
id=group["name"], object_type="package", object=dataset["name"])
members = call_action('member_list', context=context, id=group["name"])
assert len(members) == 0


@pytest.mark.usefixtures("with_plugins", "clean_db")
def test_normal_user_cannot_edit_user_profile(app):
user = User()
Expand Down
2 changes: 1 addition & 1 deletion docker/.env.template
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ REGISTRY=""
REPOSITORY=""

# opendata images
CKAN_IMAGE_TAG="c551dc2ab798d6c9548bfe0c675381e81adf747b"
CKAN_IMAGE_TAG="0077682c1e65f71f78200a2ec8ed331e7bca4b14"
SOLR_IMAGE_TAG="1b7cce3b73e5415180fe2862bfba7d27b57c5ee8"
NGINX_IMAGE_TAG="1b7cce3b73e5415180fe2862bfba7d27b57c5ee8"

Expand Down

0 comments on commit 6425f0d

Please sign in to comment.