Skip to content

Commit

Permalink
mail notification: improve with signal
Browse files Browse the repository at this point in the history
- mail are sent on signal and moved to tind-mail
- see https://tindtechnologies.atlassian.net/browse/IN3-227
  • Loading branch information
remileduc committed Sep 22, 2016
1 parent 265ec41 commit 02ce83b
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 163 deletions.
4 changes: 1 addition & 3 deletions invenio_communities/ext.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,7 @@
manage_permission_factory,
curate_permission_factory)
from .receivers import create_oaipmh_set, destroy_oaipmh_set, \
inject_provisional_community, new_request
from .signals import inclusion_request_created
inject_provisional_community


class InvenioCommunities(object):
Expand All @@ -65,7 +64,6 @@ def register_signals(self, app):
if app.config['COMMUNITIES_OAI_ENABLED']:
listen(Community, 'after_insert', create_oaipmh_set)
listen(Community, 'after_delete', destroy_oaipmh_set)
inclusion_request_created.connect(new_request)

def init_config(self, app):
"""Initialize configuration."""
Expand Down
7 changes: 0 additions & 7 deletions invenio_communities/receivers.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,6 @@
from invenio_db import db

from .models import InclusionRequest
from .utils import send_community_request_email


def new_request(sender, request=None, notify=True, **kwargs):
"""New request for inclusion."""
if current_app.config['COMMUNITIES_MAIL_ENABLED'] and notify:
send_community_request_email(request)


def inject_provisional_community(sender, json=None, record=None, index=None,
Expand Down
114 changes: 38 additions & 76 deletions invenio_communities/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,13 @@
from math import ceil
from uuid import UUID

from flask import current_app, url_for
from flask import current_app

from invenio_db import db
from invenio_files_rest.errors import FilesException
from invenio_files_rest.models import Bucket, Location, ObjectVersion
from invenio_records.api import Record

from invenio_communities.proxies import current_permission_factory, needs


class Pagination(object):
Expand Down Expand Up @@ -140,84 +142,44 @@ def initialize_communities_bucket():
db.session.commit()


def format_request_email_templ(increq, template, **ctx):
"""Format the email message element for inclusion request notification.
Formats the message according to the provided template file, using
some default fields from 'increq' object as default context.
Arbitrary context can be provided as keywords ('ctx'), and those will
not be overwritten by the fields from 'increq' object.
:param increq: Inclusion request object for which the request is made.
:type increq: `invenio_communities.models.InclusionRequest`
:param template: relative path to jinja template.
:type template: str
:param ctx: Optional extra context parameters passed to formatter.
:type ctx: dict.
:returns: Formatted message.
:rtype: str
def _get_permission(action, community=""):
"""
# Add minimal information to the contex (without overwriting).
curate_link = url_for('invenio_communities.curate',
community_id=increq.community.id)

min_ctx = dict(
record=Record.get_record(increq.record.id),
requester=increq.user,
community=increq.community,
curate_link=curate_link,
)
for k, v in min_ctx.items():
if k not in ctx:
ctx[k] = v

msg_element = render_template_to_string(template, **ctx)
return msg_element


def format_request_email_title(increq, **ctx):
"""Format the email message title for inclusion request notification.
:param increq: Inclusion request object for which the request is made.
:type increq: `invenio_communities.models.InclusionRequest`
:param ctx: Optional extra context parameters passed to formatter.
:type ctx: dict.
:returns: Email message title.
:rtype: str
:param action: the action to execute (i.e. "communities-read")
:type action: str
:param community: the community
:type community: str
:returns: permission the permission associated to this action with
this community as a parameter
"""
template = current_app.config["COMMUNITIES_REQUEST_EMAIL_TITLE_TEMPLATE"],
return format_request_email_templ(increq, template, **ctx)

if community:
return current_permission_factory[action](community)
return current_permission_factory[action]()

def format_request_email_body(increq, **ctx):
"""Format the email message body for inclusion request notification.

:param increq: Inclusion request object for which the request is made.
:type increq: `invenio_communities.models.InclusionRequest`
:param ctx: Optional extra context parameters passed to formatter.
:type ctx: dict.
:returns: Email message body.
:rtype: str
def _get_permissions(remove_forbidden=True, sorted=True):
"""
template = current_app.config["COMMUNITIES_REQUEST_EMAIL_BODY_TEMPLATE"],
return format_request_email_templ(increq, template, **ctx)


def send_community_request_email(increq):
"""Signal for sending emails after community inclusion request."""
from flask_mail import Message
from invenio_mail.tasks import send_email

msg_body = format_request_email_body(increq)
msg_title = format_request_email_title(increq)

sender = current_app.config['COMMUNITIES_REQUEST_EMAIL_SENDER']
returns the list of all the permissions associated with the communities
:param remove_forbidden: tells if we should remove special actions
that should be accessible by the administrators only, like create and
delete communities.
:param sorted: tells if the list should be alphabetically sorted
"""
actions = list(current_permission_factory)
if remove_forbidden:
actions.remove("communities-admin")
if sorted:
actions.sort()
return actions

msg = Message(
msg_title,
sender=sender,
recipients=[increq.community.owner.email, ],
body=msg_body
)

send_email.delay(msg.__dict__)
def _get_needs(action, community=""):
"""
:param action: the action to execute (i.e. "communities-read")
:type action: str
:param community: the community
:type community: str
:returns: the need associated with the action
"""
if community:
return needs[action](community)
return needs[action]()
83 changes: 6 additions & 77 deletions invenio_communities/views/ui.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
render_template, request, url_for)
from flask_babelex import gettext as _
from flask_login import current_user, login_required
from flask_principal import ActionNeed, UserNeed
from flask_principal import ActionNeed
from invenio_db import db
from invenio_indexer.api import RecordIndexer
from invenio_pidstore.resolver import Resolver
Expand All @@ -42,7 +42,6 @@
from invenio_access import DynamicPermission
from invenio_access.models import ActionUsers
from invenio_accounts.models import User
from invenio_mail.api import TemplatedMessage

from invenio_communities.errors import (InclusionRequestExistsError,
InclusionRequestObsoleteError)
Expand All @@ -53,8 +52,11 @@
from invenio_communities.models import (Community,
FeaturedCommunity,
InclusionRequest)
from invenio_communities.proxies import current_permission_factory, needs
from invenio_communities.utils import Pagination, render_template_to_string
from invenio_communities.utils import (_get_permission,
_get_permissions,
_get_needs,
Pagination,
render_template_to_string)

from .api import CommunitiesFacets

Expand All @@ -67,49 +69,6 @@
)


def _get_needs(action, community=""):
"""
:param action: the action to execute (i.e. "communities-read")
:type action: str
:param community: the community
:type community: str
:returns: the need associated with the action
"""
if community:
return needs[action](community)
return needs[action]()


def _get_permission(action, community=""):
"""
:param action: the action to execute (i.e. "communities-read")
:type action: str
:param community: the community
:type community: str
:returns: permission the permission associated to this action with
this community as a parameter
"""
if community:
return current_permission_factory[action](community)
return current_permission_factory[action]()


def _get_permissions(remove_forbidden=True, sorted=True):
"""
returns the list of all the permissions associated with the communities
:param remove_forbidden: tells if we should remove special actions
that should be accessible by the administrators only, like create and
delete communities.
:param sorted: tells if the list should be alphabetically sorted
"""
actions = list(current_permission_factory)
if remove_forbidden:
actions.remove("communities-admin")
if sorted:
actions.sort()
return actions


def pass_community(f):
"""Decorator to pass community."""
@wraps(f)
Expand Down Expand Up @@ -551,41 +510,11 @@ def suggest():
u"to the {} {}.".format(
current_app.config["COMMUNITIES_NAME"],
community.title))
send_email_suggest(record, community)
db.session.commit()
RecordIndexer().index_by_id(record.id)
return redirect(url)


def send_email_suggest(record, community):
"""
Send email to curators.
TODO: must be done through signal later
"""
class FakeIdentity(object):
"""Fake class to test DynamicPermission."""
def __init__(self, *provides):
self.provides = set(provides)

permission = _get_permission("communities-curate", community)
users = User.query.filter_by(active=True).all()
recipients = [u for u in users \
if permission.allows(FakeIdentity(UserNeed(u.id)))]
msg = TemplatedMessage(template_body="tind_mail/communities_submition.txt",
template_html="tind_mail/communities_submition.html",
subject="New submition to your community",
recipients=recipients,
ctx={
"logo": current_app.config["THEME_LOGO"],
"user": "Curators",
"sender": "SysAdmin",
"record": record,
"community": community,
"submitter": current_user.email
})
current_app.extensions["mail"].send(msg)


@blueprint.route('/<string:community_id>/team/')
@login_required
@pass_community
Expand Down

0 comments on commit 02ce83b

Please sign in to comment.