+# :copyright: Copyright (c) 2016 ftrack
+# This snippet was last tested with ftrack 3.3.31 and Python API 0.15.5.
+logger = logging.getLogger('restrict_task_status_listener')
+ALLOWED_GROUP_NAME = 'Producers'
+def restrict_status_updates(session, group_id, restricted_status_ids, event):
+ status_reverted = False
+ for entity in event['data'].get('entities', []):
+ entity.get('entityType') == 'task' and
+ entity.get('action') in ('update',) and
+ 'statusid' in entity.get('keys', [])
+ entity_id = entity['entityId']
+ user_id = event['source'].get('user', {}).get('id', None)
+ logger.warning('No source user, allowing update...')
+ old_status_id = entity['changes']['statusid']['old']
+ new_status_id = entity['changes']['statusid']['new']
+ if not new_status_id in restricted_status_ids:
+ logger.info('Status is not restricted, allowing update...')
+ # Make sure user is a member in the allowed group.
+ membership = session.query(
+ 'Membership where user_id is "{}" and group_id is "{}"'.format(
+ logger.info('Status change is _not_ allowed, reverting')
+ task = session.get('Task', entity_id)
+ task['status_id'] = old_status_id
+ logger.info('Status change is allowed')
+ # Trigger a message to the user (new in ftrack 3.3.31)
+ session.event_hub.publish(
+ ftrack_api.event.base.Event(
+ topic='ftrack.action.trigger-user-interface',
+ message='You are not allowed to set this status'
+ target='applicationId=ftrack.client.web and user.id="{0}"'.format(user_id)
+def register(session, **kw):
+ '''Register event listener.'''
+ # Validate that session is an instance of ftrack_api.Session. If not,
+ # assume that register is being called from an incompatible API
+ # and return without doing anything.
+ if not isinstance(session, ftrack_api.Session):
+ # Exit to avoid registering this plugin again.
+ # Get the ID of the allowed group
+ allowed_group = session.query(
+ 'Group where name is {0}'.format(ALLOWED_GROUP_NAME)
+ allowed_group_id = allowed_group['id']
+ # Get the ids of the restricted statuses.
+ restricted_statuses = session.query(
+ 'Status where name in ("{0}")'.format(
+ '", "'.join(RESTRICTED_STATUSES)
+ restricted_status_ids = [status['id'] for status in restricted_statuses]
+ # Register the event handler
+ handle_event = functools.partial(
+ restrict_status_updates, session, allowed_group_id,
+ session.event_hub.subscribe('topic=ftrack.update', handle_event)
+if __name__ == '__main__':
+ logging.basicConfig(level=logging.INFO)
+ session = ftrack_api.Session()
+ session.event_hub.wait()