diff --git a/ietf/idtracker/models.py b/ietf/idtracker/models.py index aaa1db268..528f552f5 100644 --- a/ietf/idtracker/models.py +++ b/ietf/idtracker/models.py @@ -1042,6 +1042,8 @@ class IRTF(models.Model): meeting_scheduled = models.BooleanField(blank=True) def __str__(self): return self.acronym + def chairs(self): # return a set of IRTFChair objects for this work group + return IRTFChair.objects.filter(irtf=self) class Meta: db_table = 'irtf' verbose_name="IRTF Research Group" diff --git a/ietf/ietfworkflows/accounts.py b/ietf/ietfworkflows/accounts.py new file mode 100644 index 000000000..ea4f89cf1 --- /dev/null +++ b/ietf/ietfworkflows/accounts.py @@ -0,0 +1,45 @@ +from ietf.idrfc.idrfc_wrapper import IdRfcWrapper, IdWrapper +from ietf.ietfworkflows.streams import get_streamed_draft, get_chair_model + + +def get_person_for_user(user): + try: + return user.get_profile().person() + except: + return None + + +def is_secretariat(user): + if not user or not user.is_authenticated(): + return False + return bool(user.groups.filter(name='Secretariat')) + + +def is_chair(user, draft): + person = get_person_for_user(user) + if not person: + return False + streamed = get_streamed_draft(draft) + if not streamed or not streamed.stream: + return False + group = streamed.group + if not group or not hasattr(group, 'chairs'): + return False + return bool(group.chairs().filter(person=person).count()) + + +def can_edit_state(user, draft): + streamed = get_streamed_draft(draft) + if not streamed or not streamed.stream: + return False + return (is_secretariat(user) or + is_chair(user, draft) + ) + + +def can_edit_tags(user, draft): + return can_edit_state(user, draft) + + +def can_edit_stream(user, draft): + return is_secretariat(user) diff --git a/ietf/ietfworkflows/streams.py b/ietf/ietfworkflows/streams.py index 503eba4f5..7eebddffa 100644 --- a/ietf/ietfworkflows/streams.py +++ b/ietf/ietfworkflows/streams.py @@ -29,6 +29,20 @@ def get_stream_from_id(stream_id): return None +def get_chair_model(stream): + model_str = stream.group_chair_model + if not model_str: + return None + try: + app, model = model_str.split('.', 1) + except ValueError: + return None + chair_model = models.get_model(app, model) + if not chair_model: + return + return chair_model + + def _get_group_from_acronym(group_model_str, acronym): try: app, model = group_model_str.split('.', 1) diff --git a/ietf/ietfworkflows/templatetags/ietf_streams.py b/ietf/ietfworkflows/templatetags/ietf_streams.py index b26963b9f..98b32b76b 100644 --- a/ietf/ietfworkflows/templatetags/ietf_streams.py +++ b/ietf/ietfworkflows/templatetags/ietf_streams.py @@ -4,6 +4,8 @@ from ietf.idrfc.idrfc_wrapper import IdRfcWrapper, IdWrapper from ietf.ietfworkflows.utils import (get_workflow_for_draft, get_state_for_draft) from ietf.ietfworkflows.streams import get_stream_from_wrapper +from ietf.ietfworkflows.accounts import (can_edit_state, can_edit_tags, + can_edit_stream) register = template.Library() @@ -45,3 +47,25 @@ def workflow_history_entry(context, entry): real_entry = entry.get_real_instance() return {'entry': real_entry, 'entry_class': real_entry.__class__.__name__.lower()} + + +@register.inclusion_tag('ietfworkflows/edit_actions.html', takes_context=True) +def edit_actions(context, wrapper): + request = context.get('request', None) + user = request and request.user + if not user: + return {} + idwrapper = None + if isinstance(wrapper, IdRfcWrapper): + idwrapper = wrapper.id + elif isinstance(wrapper, IdWrapper): + idwrapper = wrapper + if not idwrapper: + return None + draft = idwrapper._draft + return { + 'can_edit_state': can_edit_state(user, draft), + 'can_edit_tags': can_edit_tags(user, draft), + 'can_edit_stream': can_edit_stream(user, draft), + 'doc': wrapper, + } diff --git a/ietf/templates/idrfc/doc_main_id.html b/ietf/templates/idrfc/doc_main_id.html index 8f9893b32..3c4a08f09 100644 --- a/ietf/templates/idrfc/doc_main_id.html +++ b/ietf/templates/idrfc/doc_main_id.html @@ -32,7 +32,7 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. {% endcomment %} -{% load ietf_filters %} +{% load ietf_filters ietf_streams %} {% block title %}{{ doc.draft_name_and_revision }}{% endblock %} {% block doc_meta_description %}{{ doc.title }} ({{info.type}}; {{doc.publication_date|date:"Y"}}){% endblock %} @@ -81,6 +81,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. {% endblock doc_metatable %} {% block doc_metalinks %} +{% edit_actions doc %}
Email Authors | IPR Disclosures diff --git a/ietf/templates/ietfworkflows/edit_actions.html b/ietf/templates/ietfworkflows/edit_actions.html new file mode 100644 index 000000000..05634197e --- /dev/null +++ b/ietf/templates/ietfworkflows/edit_actions.html @@ -0,0 +1,6 @@ +
+{% if can_edit_state %} Change state {% endif %} +{% if can_edit_tags %}{% if can_edit_state %} | {% endif %} Change annotation tags {% endif %} +{% if can_edit_stream %}{% if can_edit_state or can_edit_tags %} | {% endif %} Change draft stream{% endif %} +
+