Bug 1470621: actionPerm is the cb_name, not name; r?tomprince draft
authorDustin J. Mitchell <dustin@mozilla.com>
Thu, 28 Jun 2018 17:34:50 +0000
changeset 814632 32946dea16558e97261abefc65ca34b03db26dc9
parent 814631 ad38db81d950bedb44520afda367c104acc50db8
push id115287
push userdmitchell@mozilla.com
push dateThu, 05 Jul 2018 20:14:40 +0000
reviewerstomprince
bugs1470621
milestone63.0a1
Bug 1470621: actionPerm is the cb_name, not name; r?tomprince The actionPerm is for access control, so it must limit access to a specific callback function, not a name (which can apply to mulitple functions). To make things nicer, we allow functions to specify their cb_name and default it to the action name. The decorated function names are not used. MozReview-Commit-ID: 2oiuXrrw7DE
taskcluster/taskgraph/actions/registry.py
--- a/taskcluster/taskgraph/actions/registry.py
+++ b/taskcluster/taskgraph/actions/registry.py
@@ -47,17 +47,17 @@ def hash_taskcluster_yml(filename):
     of the sha256 of the file's content, and is used by administrative scripts
     to create a hook based on this content.
     '''
     return hash.hash_path(filename)[:10]
 
 
 def register_callback_action(name, title, symbol, description, order=10000,
                              context=[], available=lambda parameters: True,
-                             schema=None, kind='task', generic=True):
+                             schema=None, kind='task', generic=True, cb_name=None):
     """
     Register an action callback that can be triggered from supporting
     user interfaces, such as Treeherder.
 
     This function is to be used as a decorator for a callback that takes
     parameters as follows:
 
     ``parameters``:
@@ -105,48 +105,56 @@ def register_callback_action(name, title
     schema : dict
         JSON schema specifying input accepted by the action.
         This is optional and can be left ``null`` if no input is taken.
     kind : string
         The action kind to define - must be one of `task` or `hook`.  Only for
         transitional purposes.
     generic : boolean
         For kind=hook, whether this is a generic action or has its own permissions.
+    cb_name : string
+        The name under which this function should be registered, defaulting to
+        `name`.  This is used to generation actionPerm for non-generic hook
+        actions, and thus appears in ci-configuration and various role and hook
+        names.  Unlike `name`, which can appear multiple times, cb_name must be
+        unique among all registered callbacks.
 
     Returns
     -------
     function
         To be used as decorator for the callback function.
     """
     mem = {"registered": False}  # workaround nonlocal missing in 2.x
 
     assert isinstance(title, basestring), 'title must be a string'
     assert isinstance(description, basestring), 'description must be a string'
     title = title.strip()
     description = description.strip()
 
-    def register_callback(cb):
+    def register_callback(cb, cb_name=cb_name):
         assert isinstance(name, basestring), 'name must be a string'
         assert isinstance(order, int), 'order must be an integer'
         assert kind in ('task', 'hook'), 'kind must be task or hook'
         assert callable(schema) or is_json(schema), 'schema must be a JSON compatible object'
         assert isinstance(cb, FunctionType), 'callback must be a function'
         # Allow for json-e > 25 chars in the symbol.
         if '$' not in symbol:
             assert 1 <= len(symbol) <= 25, 'symbol must be between 1 and 25 characters'
         assert isinstance(symbol, basestring), 'symbol must be a string'
 
         assert not mem['registered'], 'register_callback_action must be used as decorator'
-        assert cb.__name__ not in callbacks, 'callback name {} is not unique'.format(cb.__name__)
+        if not cb_name:
+            cb_name = name
+        assert cb_name not in callbacks, 'callback name {} is not unique'.format(cb_name)
 
         def action_builder(parameters, graph_config):
             if not available(parameters):
                 return None
 
-            actionPerm = 'generic' if generic else name
+            actionPerm = 'generic' if generic else cb_name
 
             # gather up the common decision-task-supplied data for this action
             repo_param = '{}head_repository'.format(graph_config['project-repo-param-prefix'])
             repository = {
                 'url': parameters[repo_param],
                 'project': parameters['project'],
                 'level': parameters['level'],
             }
@@ -162,17 +170,17 @@ def register_callback_action(name, title
             match = re.match(r'https://(hg.mozilla.org)/(.*?)/?$', parameters[repo_param])
             if not match:
                 raise Exception('Unrecognized {}'.format(repo_param))
             action = {
                 'name': name,
                 'title': title,
                 'description': description,
                 'taskGroupId': task_group_id,
-                'cb_name': cb.__name__,
+                'cb_name': cb_name,
                 'symbol': symbol,
             }
 
             rv = {
                 'name': name,
                 'title': title,
                 'description': description,
                 'context': context,
@@ -247,17 +255,17 @@ def register_callback_action(name, title
                     },
                 })
 
             return rv
 
         actions.append(Action(order, action_builder))
 
         mem['registered'] = True
-        callbacks[cb.__name__] = cb
+        callbacks[cb_name] = cb
     return register_callback
 
 
 def render_actions_json(parameters, graph_config):
     """
     Render JSON object for the ``public/actions.json`` artifact.
 
     Parameters