Skip to content

Commit

Permalink
Merge branch 'async' into SDESK-7325
Browse files Browse the repository at this point in the history
  • Loading branch information
MarkLark86 committed Jul 30, 2024
2 parents d192bdd + bd55b40 commit 93647cd
Show file tree
Hide file tree
Showing 22 changed files with 588 additions and 84 deletions.
10 changes: 9 additions & 1 deletion apps/archive/archive.py
Original file line number Diff line number Diff line change
Expand Up @@ -1217,6 +1217,7 @@ def handle_mark_user_notifications(self, updates, original, add_activity=True):
:param original: original item version before update
:param add_activity: flag to decide whether to add notification as activity or not
"""

marked_user = marked_for_user = None
orig_marked_user = original.get("marked_for_user", None)
new_marked_user = updates.get("marked_for_user", None)
Expand Down Expand Up @@ -1291,7 +1292,14 @@ def _send_mark_user_notifications(

if add_activity:
notify_and_add_activity(
activity_name, msg, resource=resource, item=item, user_list=user_list, link=link, **data
activity_name,
msg,
resource=resource,
item=item,
user_list=user_list,
link=link,
preference_notification_name="mark_for_user",
**data,
)
# send separate notification for markForUser extension
push_notification(activity_name, item_id=item.get(ID_FIELD), user_list=user_list, extension="markForUser")
Expand Down
26 changes: 26 additions & 0 deletions apps/preferences.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,17 @@ class PreferencesResource(Resource):
category=lazy_gettext("contacts"),
)

superdesk.register_default_user_preference(
"email:notification:mark_for_user",
{
"type": "bool",
"enabled": True,
"default": True,
},
label=lazy_gettext("Send Mark for User notifications via email"),
category=lazy_gettext("notifications"),
)

superdesk.register_default_user_preference("destination:active", {})

superdesk.register_default_user_preference("extensions", {})
Expand Down Expand Up @@ -338,6 +349,8 @@ def get_user_preference(self, user_id):
This function returns preferences for the user.
"""
doc = get_resource_service("users").find_one(req=None, _id=user_id)
if doc is None:
return {}
prefs = doc.get(_user_preferences_key, {})
return prefs

Expand Down Expand Up @@ -398,3 +411,16 @@ def has_missing_privileges(prefs):
return [priv for pref in prefs for priv in pref.get("privileges", []) if not privileges.get(priv)]

doc[_user_preferences_key] = {k: v for k, v in preferences.items() if not has_missing_privileges(v)}

def check_preference_email_notification_is_enabled(self, preference_name, user_id=None, preferences=None):
"""
This function checks if email notification is enabled or not based on the preference.
"""
send_email = {}
if user_id:
preferences = self.get_user_preference(user_id)
if preference_name:
send_email = (
preferences.get(f"email:notification:{preference_name}", {}) if isinstance(preferences, dict) else {}
)
return send_email and send_email.get("enabled", False)
6 changes: 2 additions & 4 deletions apps/publish/content/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -581,17 +581,15 @@ def test_queue_transmission_wrong_article_type_fails(self):
service = get_enqueue_service(doc[ITEM_OPERATION])

subscribers, subscriber_codes, associations = service.get_subscribers(doc, SUBSCRIBER_TYPES.DIGITAL)
no_formatters, queued = get_enqueue_service("publish").queue_transmission(doc, subscribers, subscriber_codes)
queued = get_enqueue_service("publish").queue_transmission(doc, subscribers, subscriber_codes)
queue_items = self.app.data.find(PUBLISH_QUEUE, None, None)[0]
self.assertEqual(1, queue_items.count())
self.assertEqual(0, len(no_formatters))
self.assertTrue(queued)

subscribers, subscriber_codes, associations = service.get_subscribers(doc, SUBSCRIBER_TYPES.WIRE)
no_formatters, queued = get_enqueue_service("publish").queue_transmission(doc, subscribers)
queued = get_enqueue_service("publish").queue_transmission(doc, subscribers)
queue_items = self.app.data.find(PUBLISH_QUEUE, None, None)[0]
self.assertEqual(2, queue_items.count())
self.assertEqual(0, len(no_formatters))
self.assertTrue(queued)

def test_delete_from_queue_by_article_id(self):
Expand Down
16 changes: 10 additions & 6 deletions apps/publish/enqueue/enqueue_corrected.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,18 @@
# AUTHORS and LICENSE files distributed with this source code, or
# at https://www.sourcefabric.org/superdesk/license

import logging

from superdesk.resource_fields import ID_FIELD
from apps.publish.content.utils import filter_non_digital
from superdesk import get_resource_service
from superdesk.metadata.item import CONTENT_STATE
from apps.publish.enqueue.enqueue_service import EnqueueService


logger = logging.getLogger(__name__)


class EnqueueCorrectedService(EnqueueService):
publish_type = "correct"
published_state = "corrected"
Expand All @@ -38,18 +43,15 @@ def get_subscribers(self, doc, target_media_type):

# step 1
query = {
"$and": [
{"item_id": doc["item_id"]},
{"publishing_action": {"$in": [CONTENT_STATE.PUBLISHED, CONTENT_STATE.CORRECTED]}},
]
"item_id": doc["item_id"],
"publishing_action": {"$in": [CONTENT_STATE.PUBLISHED, CONTENT_STATE.CORRECTED]},
}

subscribers, subscriber_codes, previous_associations = self._get_subscribers_for_previously_sent_items(query)

if subscribers:
# Step 2
query = {"is_active": True}
active_subscribers = list(get_resource_service("subscribers").get(req=None, lookup=query))
active_subscribers = list(get_resource_service("subscribers").get_active())
subscribers_yet_to_receive = [
a for a in active_subscribers if not any(a[ID_FIELD] == s[ID_FIELD] for s in subscribers)
]
Expand All @@ -64,6 +66,8 @@ def get_subscribers(self, doc, target_media_type):
)
if codes:
subscriber_codes.update(codes)
else:
logger.info("No previous subscribers found for item %s", doc["item_id"])

subscribers = subscribers + subscribers_yet_to_receive
associations = self._filter_subscribers_for_associations(
Expand Down
14 changes: 8 additions & 6 deletions apps/publish/enqueue/enqueue_published.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,16 @@
# AUTHORS and LICENSE files distributed with this source code, or
# at https://www.sourcefabric.org/superdesk/license

import logging
import elasticapm

from superdesk.resource_fields import ID_FIELD
from superdesk import get_resource_service
from superdesk.metadata.item import ITEM_TYPE, CONTENT_TYPE, CONTENT_STATE
from apps.publish.enqueue.enqueue_service import EnqueueService

logger = logging.getLogger(__name__)


class EnqueuePublishedService(EnqueueService):
@elasticapm.capture_span()
Expand All @@ -40,13 +43,9 @@ def get_subscribers(self, doc, target_media_type):
# Step 2b
if doc.get(ITEM_TYPE) in [CONTENT_TYPE.TEXT, CONTENT_TYPE.PREFORMATTED]:
if rewrite_of:
item_ids = [rewrite_of]

query = {
"$and": [
{"item_id": {"$in": item_ids}},
{"publishing_action": {"$in": [CONTENT_STATE.PUBLISHED, CONTENT_STATE.CORRECTED]}},
]
"item_id": rewrite_of,
"publishing_action": {"$in": [CONTENT_STATE.PUBLISHED, CONTENT_STATE.CORRECTED]},
}

(
Expand All @@ -55,6 +54,9 @@ def get_subscribers(self, doc, target_media_type):
rewrite_associations,
) = self._get_subscribers_for_previously_sent_items(query)

if not rewrite_subscribers:
logger.info("No previous subscribers found for rewrite item: %s", rewrite_of)

# Step 2
subscribers, codes = self.filter_subscribers(doc, subscribers, target_media_type)

Expand Down
13 changes: 7 additions & 6 deletions apps/publish/enqueue/enqueue_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from bson import ObjectId
from copy import deepcopy
from eve.utils import ParsedRequest
from flask_babel import _

from superdesk.core import get_current_app, get_app_config
from superdesk.resource_fields import ID_FIELD, VERSION
Expand All @@ -35,7 +36,6 @@
from apps.packages.package_service import PackageService
from apps.publish.published_item import PUBLISH_STATE, QUEUE_STATE
from apps.content_types import apply_schema
from flask_babel import _

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -452,16 +452,17 @@ def queue_transmission(self, doc, subscribers, subscriber_codes=None, associatio
subscriber_codes = {}

try:
if get_app_config("PUBLISH_ASSOCIATIONS_RESEND") and not sent:
publish_associations_resend = get_app_config("PUBLISH_ASSOCIATIONS_RESEND")
if publish_associations_resend and not sent:
is_correction = doc.get("state") in ["corrected", "being_corrected"]
is_update = doc.get("rewrite_of")
is_new = not is_correction and not is_update

if get_app_config("PUBLISH_ASSOCIATIONS_RESEND") == "new" and is_new:
if publish_associations_resend == "new" and is_new:
self.resend_association_items(doc)
elif get_app_config("PUBLISH_ASSOCIATIONS_RESEND") == "corrections":
elif publish_associations_resend == "corrections":
self.resend_association_items(doc)
elif get_app_config("PUBLISH_ASSOCIATIONS_RESEND") == "updates" and not is_correction:
elif publish_associations_resend == "updates" and not is_correction:
self.resend_association_items(doc)

queued = False
Expand Down Expand Up @@ -990,4 +991,4 @@ def filter_document(doc):
for null_rendition_key in [k for k in renditions if not renditions[k]]:
del doc[ASSOCIATIONS][association_key]["renditions"][null_rendition_key]

return doc
return doc
74 changes: 43 additions & 31 deletions apps/rundowns/rundowns.py
Original file line number Diff line number Diff line change
Expand Up @@ -213,43 +213,55 @@ def sync_item_changes(self, item_id) -> None:
self.system_update(rundown["_id"], updates, rundown)

def get(self, req, lookup):
if req and req.args.get("q"):
query_string_query = {
"query_string": {
"query": req.args.get("q"),
"default_operator": "AND",
"lenient": True,
},
}
if req:
source = json.loads(req.args.get("source")) if req.args.get("source") else {}
query_string_query = None
if source.get("query"):
try:
query_string_query = source["query"]["filtered"]["query"]["query_string"]
query_string_query = {"query_string": query_string_query}
source["query"].pop("filtered")
except KeyError:
query_string_query = None

items_query = {
"nested": {
"path": "items_data",
"query": query_string_query,
"inner_hits": {"name": "rundown_items"},
},
}
if req.args.get("q"):
query_string_query = {
"query_string": {
"query": req.args.get("q"),
"default_operator": "AND",
"lenient": True,
},
}

query = {
"bool": {
"should": [
query_string_query,
items_query,
],
"minimum_should_match": 1,
if query_string_query:
items_query = {
"nested": {
"path": "items_data",
"query": query_string_query,
"inner_hits": {"name": "rundown_items"},
},
}
}

source = json.loads(req.args.get("source")) if req.args.get("source") else {}
if source.get("query"):
old_query = source["query"]
source["query"] = query
query["bool"]["must"] = old_query
else:
source["query"] = query
query = {
"bool": {
"should": [
query_string_query,
items_query,
],
"minimum_should_match": 1,
}
}

if source.get("query"):
old_query = source["query"]
source["query"] = query
query["bool"]["must"] = old_query
else:
source["query"] = query

args = req.args.to_dict()
args.pop("q")
if args.get("q"):
args.pop("q")
args["source"] = json.dumps(source)
req.args = ImmutableMultiDict(args)
cursor = super().get(req, lookup)
Expand Down
14 changes: 14 additions & 0 deletions apps/validate/test_validate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from superdesk.factory.app import SuperdeskEve
from flask_babel import Babel

from .validate import ValidateService


def test_validate_service_get_error_field_name():
settings = {"DOMAIN": {}}
app = SuperdeskEve(settings=settings)
Babel(app)
service = ValidateService()
with app.app_context():
assert service.get_error_field_name("headline") == "Headline"
assert service.get_error_field_name("foo") == "foo"
1 change: 1 addition & 0 deletions content_api/publish/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ def _assign_associations(self, item, doc):
for assoc, assoc_item in (item.get("associations") or {}).items():
if not assoc_item:
continue
doc["associations"][assoc] = assoc_item.copy()
doc["associations"][assoc]["subscribers"] = list(map(str, assoc_item.get("subscribers") or []))

def _process_associations(self, updates, original):
Expand Down
2 changes: 1 addition & 1 deletion dev-requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ pydocstyle<7.0
httmock==1.4.0
watchdog==4.0.1
wooper==0.4.4
requests-mock==1.11.0
requests-mock==1.12.1
responses
pytest
pytest-env
Expand Down
18 changes: 9 additions & 9 deletions docs/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#
# pip-compile requirements.in
#
alabaster==0.7.16
alabaster==1.0.0
# via sphinx
anyio==4.4.0
# via
Expand Down Expand Up @@ -48,28 +48,28 @@ sniffio==1.3.1
# via anyio
snowballstemmer==2.2.0
# via sphinx
sphinx==7.4.4
sphinx==8.0.1
# via
# -r requirements.in
# sphinx-autobuild
# sphinxcontrib-plantuml
sphinx-autobuild==2024.4.16
# via -r requirements.in
sphinxcontrib-applehelp==1.0.8
sphinxcontrib-applehelp==2.0.0
# via sphinx
sphinxcontrib-devhelp==1.0.6
sphinxcontrib-devhelp==2.0.0
# via sphinx
sphinxcontrib-htmlhelp==2.0.5
sphinxcontrib-htmlhelp==2.1.0
# via sphinx
sphinxcontrib-jsmath==1.0.1
# via sphinx
sphinxcontrib-plantuml==0.30
# via -r requirements.in
sphinxcontrib-qthelp==1.0.7
sphinxcontrib-qthelp==2.0.0
# via sphinx
sphinxcontrib-serializinghtml==1.1.10
sphinxcontrib-serializinghtml==2.0.0
# via sphinx
starlette==0.37.2
starlette==0.38.2
# via sphinx-autobuild
tomli==2.0.1
# via sphinx
Expand All @@ -81,7 +81,7 @@ urllib3==1.26.19
# via
# -r requirements.in
# requests
uvicorn==0.30.1
uvicorn==0.30.3
# via sphinx-autobuild
watchfiles==0.22.0
# via sphinx-autobuild
Expand Down
Loading

0 comments on commit 93647cd

Please sign in to comment.