mirror of
https://github.com/ynput/ayon-core.git
synced 2025-12-24 21:04:40 +01:00
actions are discovered by settings
This commit is contained in:
parent
4ca70aa937
commit
c3c415e405
14 changed files with 190 additions and 109 deletions
|
|
@ -9,7 +9,6 @@ class CleanHierarchicalAttrsAction(BaseAction):
|
|||
label = "Pype Admin"
|
||||
variant = "- Clean hierarchical custom attributes"
|
||||
description = "Unset empty hierarchical attribute values."
|
||||
role_list = ["Pypeclub", "Administrator", "Project Manager"]
|
||||
icon = statics_icon("ftrack", "action_icons", "PypeAdmin.svg")
|
||||
|
||||
all_project_entities_query = (
|
||||
|
|
@ -20,12 +19,17 @@ class CleanHierarchicalAttrsAction(BaseAction):
|
|||
"select value, entity_id from CustomAttributeValue "
|
||||
"where entity_id in ({}) and configuration_id is \"{}\""
|
||||
)
|
||||
settings_key = "clean_hierarchical_attr"
|
||||
|
||||
def discover(self, session, entities, event):
|
||||
"""Show only on project entity."""
|
||||
if len(entities) == 1 and entities[0].entity_type.lower() == "project":
|
||||
return True
|
||||
return False
|
||||
if (
|
||||
len(entities) != 1
|
||||
or entities[0].entity_type.lower() != "project"
|
||||
):
|
||||
return False
|
||||
|
||||
return self.valid_roles(session, entities, event)
|
||||
|
||||
def launch(self, session, entities, event):
|
||||
project = entities[0]
|
||||
|
|
|
|||
|
|
@ -131,9 +131,8 @@ class CustomAttributes(BaseAction):
|
|||
variant = '- Create/Update Avalon Attributes'
|
||||
#: Action description.
|
||||
description = 'Creates Avalon/Mongo ID for double check'
|
||||
#: roles that are allowed to register this action
|
||||
role_list = ['Pypeclub', 'Administrator']
|
||||
icon = statics_icon("ftrack", "action_icons", "PypeAdmin.svg")
|
||||
settings_key = "create_update_attributes"
|
||||
|
||||
required_keys = ("key", "label", "type")
|
||||
|
||||
|
|
@ -150,7 +149,7 @@ class CustomAttributes(BaseAction):
|
|||
Validation
|
||||
- action is only for Administrators
|
||||
'''
|
||||
return True
|
||||
return self.valid_roles(session, entities, event)
|
||||
|
||||
def launch(self, session, entities, event):
|
||||
# JOB SETTINGS
|
||||
|
|
|
|||
|
|
@ -18,8 +18,8 @@ class DeleteAssetSubset(BaseAction):
|
|||
#: Action description.
|
||||
description = "Removes from Avalon with all childs and asset from Ftrack"
|
||||
icon = statics_icon("ftrack", "action_icons", "DeleteAsset.svg")
|
||||
#: roles that are allowed to register this action
|
||||
role_list = ["Pypeclub", "Administrator", "Project Manager"]
|
||||
|
||||
settings_key = "delete_asset_subset"
|
||||
#: Db connection
|
||||
dbcon = AvalonMongoDB()
|
||||
|
||||
|
|
@ -32,17 +32,21 @@ class DeleteAssetSubset(BaseAction):
|
|||
""" Validation """
|
||||
task_ids = []
|
||||
for ent_info in event["data"]["selection"]:
|
||||
entType = ent_info.get("entityType", "")
|
||||
if entType == "task":
|
||||
if ent_info.get("entityType") == "task":
|
||||
task_ids.append(ent_info["entityId"])
|
||||
|
||||
is_valid = False
|
||||
for entity in entities:
|
||||
ftrack_id = entity["id"]
|
||||
if ftrack_id not in task_ids:
|
||||
continue
|
||||
if entity.entity_type.lower() != "task":
|
||||
return True
|
||||
return False
|
||||
if (
|
||||
entity["id"] in task_ids
|
||||
and entity.entity_type.lower() != "task"
|
||||
):
|
||||
is_valid = True
|
||||
break
|
||||
|
||||
if is_valid:
|
||||
is_valid = self.valid_roles(session, entities, event)
|
||||
return is_valid
|
||||
|
||||
def _launch(self, event):
|
||||
try:
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@ class DeleteOldVersions(BaseAction):
|
|||
"Delete files from older publishes so project can be"
|
||||
" archived with only lates versions."
|
||||
)
|
||||
role_list = ["Pypeclub", "Project Manager", "Administrator"]
|
||||
icon = statics_icon("ftrack", "action_icons", "PypeAdmin.svg")
|
||||
|
||||
dbcon = AvalonMongoDB()
|
||||
|
|
@ -31,13 +30,16 @@ class DeleteOldVersions(BaseAction):
|
|||
sequence_splitter = "__sequence_splitter__"
|
||||
|
||||
def discover(self, session, entities, event):
|
||||
''' Validation '''
|
||||
selection = event["data"].get("selection") or []
|
||||
for entity in selection:
|
||||
entity_type = (entity.get("entityType") or "").lower()
|
||||
if entity_type == "assetversion":
|
||||
return True
|
||||
return False
|
||||
""" Validation. """
|
||||
is_valid = False
|
||||
for entity in entities:
|
||||
if entity.entity_type.lower() == "assetversion":
|
||||
is_valid = True
|
||||
break
|
||||
|
||||
if is_valid:
|
||||
is_valid = self.valid_roles(session, entities, event)
|
||||
return is_valid
|
||||
|
||||
def interface(self, session, entities, event):
|
||||
# TODO Add roots existence validation
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ class Delivery(BaseAction):
|
|||
description = "Deliver data to client"
|
||||
role_list = ["Pypeclub", "Administrator", "Project manager"]
|
||||
icon = statics_icon("ftrack", "action_icons", "Delivery.svg")
|
||||
settings_key = "delivery_action"
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.db_con = AvalonMongoDB()
|
||||
|
|
@ -30,11 +31,15 @@ class Delivery(BaseAction):
|
|||
super(Delivery, self).__init__(*args, **kwargs)
|
||||
|
||||
def discover(self, session, entities, event):
|
||||
is_valid = False
|
||||
for entity in entities:
|
||||
if entity.entity_type.lower() == "assetversion":
|
||||
return True
|
||||
is_valid = True
|
||||
break
|
||||
|
||||
return False
|
||||
if is_valid:
|
||||
is_valid = self.valid_roles(session, entities, event)
|
||||
return is_valid
|
||||
|
||||
def interface(self, session, entities, event):
|
||||
if event["data"].get("values", {}):
|
||||
|
|
|
|||
|
|
@ -13,13 +13,12 @@ class JobKiller(BaseAction):
|
|||
#: Action description.
|
||||
description = 'Killing selected running jobs'
|
||||
#: roles that are allowed to register this action
|
||||
role_list = ['Pypeclub', 'Administrator']
|
||||
icon = statics_icon("ftrack", "action_icons", "PypeAdmin.svg")
|
||||
settings_key = "job_killer"
|
||||
|
||||
def discover(self, session, entities, event):
|
||||
''' Validation '''
|
||||
|
||||
return True
|
||||
return self.valid_roles(session, entities, event)
|
||||
|
||||
def interface(self, session, entities, event):
|
||||
if not event['data'].get('values', {}):
|
||||
|
|
|
|||
|
|
@ -16,22 +16,23 @@ class PrepareProject(BaseAction):
|
|||
#: Action description.
|
||||
description = 'Set basic attributes on the project'
|
||||
#: roles that are allowed to register this action
|
||||
role_list = ["Pypeclub", "Administrator", "Project manager"]
|
||||
icon = statics_icon("ftrack", "action_icons", "PrepareProject.svg")
|
||||
|
||||
settings_key = "prepare_project"
|
||||
|
||||
# Key to store info about trigerring create folder structure
|
||||
create_project_structure_key = "create_folder_structure"
|
||||
item_splitter = {'type': 'label', 'value': '---'}
|
||||
|
||||
def discover(self, session, entities, event):
|
||||
''' Validation '''
|
||||
if len(entities) != 1:
|
||||
if (
|
||||
len(entities) != 1
|
||||
or entities[0].entity_type.lower() != "project"
|
||||
):
|
||||
return False
|
||||
|
||||
if entities[0].entity_type.lower() != "project":
|
||||
return False
|
||||
|
||||
return True
|
||||
return self.valid_roles(session, entities, event)
|
||||
|
||||
def interface(self, session, entities, event):
|
||||
if event['data'].get('values', {}):
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@ class SeedDebugProject(BaseAction):
|
|||
#: priority
|
||||
priority = 100
|
||||
#: roles that are allowed to register this action
|
||||
role_list = ["Pypeclub"]
|
||||
icon = statics_icon("ftrack", "action_icons", "SeedProject.svg")
|
||||
|
||||
# Asset names which will be created in `Assets` entity
|
||||
|
|
@ -58,9 +57,12 @@ class SeedDebugProject(BaseAction):
|
|||
existing_projects = None
|
||||
new_project_item = "< New Project >"
|
||||
current_project_item = "< Current Project >"
|
||||
settings_key = "seed_project"
|
||||
|
||||
def discover(self, session, entities, event):
|
||||
''' Validation '''
|
||||
if not self.valid_roles(session, entities, event):
|
||||
return False
|
||||
return True
|
||||
|
||||
def interface(self, session, entities, event):
|
||||
|
|
|
|||
|
|
@ -21,8 +21,8 @@ class StoreThumbnailsToAvalon(BaseAction):
|
|||
# Action description
|
||||
description = 'Test action'
|
||||
# roles that are allowed to register this action
|
||||
role_list = ["Pypeclub", "Administrator", "Project Manager"]
|
||||
icon = statics_icon("ftrack", "action_icons", "PypeAdmin.svg")
|
||||
settings_key = "store_thubmnail_to_avalon"
|
||||
|
||||
thumbnail_key = "AVALON_THUMBNAIL_ROOT"
|
||||
|
||||
|
|
@ -31,10 +31,15 @@ class StoreThumbnailsToAvalon(BaseAction):
|
|||
super(StoreThumbnailsToAvalon, self).__init__(*args, **kwargs)
|
||||
|
||||
def discover(self, session, entities, event):
|
||||
is_valid = False
|
||||
for entity in entities:
|
||||
if entity.entity_type.lower() == "assetversion":
|
||||
return True
|
||||
return False
|
||||
is_valid = True
|
||||
break
|
||||
|
||||
if is_valid:
|
||||
is_valid = self.valid_roles(session, entities, event)
|
||||
return is_valid
|
||||
|
||||
def launch(self, session, entities, event):
|
||||
user = session.query(
|
||||
|
|
|
|||
|
|
@ -41,20 +41,26 @@ class SyncToAvalonLocal(BaseAction):
|
|||
#: priority
|
||||
priority = 200
|
||||
#: roles that are allowed to register this action
|
||||
role_list = ["Pypeclub"]
|
||||
icon = statics_icon("ftrack", "action_icons", "PypeAdmin.svg")
|
||||
|
||||
settings_key = "sync_to_avalon_local"
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.entities_factory = SyncEntitiesFactory(self.log, self.session)
|
||||
|
||||
def discover(self, session, entities, event):
|
||||
''' Validation '''
|
||||
""" Validate selection. """
|
||||
is_valid = False
|
||||
for ent in event["data"]["selection"]:
|
||||
# Ignore entities that are not tasks or projects
|
||||
if ent["entityType"].lower() in ["show", "task"]:
|
||||
return True
|
||||
return False
|
||||
is_valid = True
|
||||
break
|
||||
|
||||
if is_valid:
|
||||
is_valid = self.valid_roles(session, entities, event)
|
||||
return is_valid
|
||||
|
||||
def launch(self, session, in_entities, event):
|
||||
time_start = time.time()
|
||||
|
|
|
|||
|
|
@ -15,11 +15,9 @@ class ThumbToChildren(BaseAction):
|
|||
icon = statics_icon("ftrack", "action_icons", "Thumbnail.svg")
|
||||
|
||||
def discover(self, session, entities, event):
|
||||
''' Validation '''
|
||||
|
||||
if (len(entities) != 1 or entities[0].entity_type in ['Project']):
|
||||
"""Show only on project."""
|
||||
if (len(entities) != 1 or entities[0].entity_type in ["Project"]):
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def launch(self, session, entities, event):
|
||||
|
|
|
|||
|
|
@ -61,8 +61,8 @@ class TaskStatusToParent(BaseEvent):
|
|||
session, event, project_id
|
||||
)
|
||||
# Load settings
|
||||
project_settings = self.get_settings_for_project(
|
||||
session, event, project_entity=project_entity
|
||||
project_settings = self.get_project_settings_from_event(
|
||||
event, project_entity
|
||||
)
|
||||
|
||||
# Prepare loaded settings and check if can be processed
|
||||
|
|
|
|||
|
|
@ -29,6 +29,8 @@ class BaseAction(BaseHandler):
|
|||
icon = None
|
||||
type = 'Action'
|
||||
|
||||
settings_frack_subkey = "user_handlers"
|
||||
|
||||
def __init__(self, session):
|
||||
'''Expects a ftrack_api.Session instance'''
|
||||
if self.label is None:
|
||||
|
|
@ -88,63 +90,6 @@ class BaseAction(BaseHandler):
|
|||
}]
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def get_user_entity_from_event(cls, session, event):
|
||||
"""Query user entity from event."""
|
||||
not_set = object()
|
||||
|
||||
# Check if user is already stored in event data
|
||||
user_entity = event["data"].get("user_entity", not_set)
|
||||
if user_entity is not_set:
|
||||
# Query user entity from event
|
||||
user_info = event.get("source", {}).get("user", {})
|
||||
user_id = user_info.get("id")
|
||||
username = user_info.get("username")
|
||||
if user_id:
|
||||
user_entity = session.query(
|
||||
"User where id is {}".format(user_id)
|
||||
).first()
|
||||
if not user_entity and username:
|
||||
user_entity = session.query(
|
||||
"User where username is {}".format(username)
|
||||
).first()
|
||||
event["data"]["user_entity"] = user_entity
|
||||
|
||||
return user_entity
|
||||
|
||||
@classmethod
|
||||
def get_user_roles_from_event(cls, session, event):
|
||||
"""Query user entity from event."""
|
||||
not_set = object()
|
||||
|
||||
user_roles = event["data"].get("user_roles", not_set)
|
||||
if user_roles is not_set:
|
||||
user_roles = []
|
||||
user_entity = cls.get_user_entity_from_event(session, event)
|
||||
for role in user_entity["user_security_roles"]:
|
||||
user_roles.append(role["security_role"]["name"].lower())
|
||||
event["data"]["user_roles"] = user_roles
|
||||
return user_roles
|
||||
|
||||
def get_project_entity_from_event(self, session, event, entities):
|
||||
"""Load or query and fill project entity from/to event data.
|
||||
|
||||
Project data are stored by ftrack id because in most cases it is
|
||||
easier to access project id than project name.
|
||||
|
||||
Args:
|
||||
session (ftrack_api.Session): Current session.
|
||||
event (ftrack_api.Event): Processed event by session.
|
||||
entities (list): Ftrack entities of selection.
|
||||
"""
|
||||
|
||||
# Try to get project entity from event
|
||||
project_entity = event["data"].get("project_entity")
|
||||
if not project_entity:
|
||||
project_entity = self.get_project_from_entity(entities[0])
|
||||
event["data"]["project_entity"] = project_entity
|
||||
return project_entity
|
||||
|
||||
def discover(self, session, entities, event):
|
||||
'''Return true if we can handle the selected entities.
|
||||
|
||||
|
|
@ -253,6 +198,112 @@ class BaseAction(BaseHandler):
|
|||
|
||||
return result
|
||||
|
||||
@staticmethod
|
||||
def roles_check(settings_roles, user_roles, default=True):
|
||||
"""Compare roles from setting and user's roles.
|
||||
|
||||
Args:
|
||||
settings_roles(list): List of role names from settings.
|
||||
user_roles(list): User's lowered role names.
|
||||
default(bool): If `settings_roles` is empty list.
|
||||
|
||||
Returns:
|
||||
bool: `True` if user has at least one role from settings or
|
||||
default if `settings_roles` is empty.
|
||||
"""
|
||||
if not settings_roles:
|
||||
return default
|
||||
|
||||
for role_name in settings_roles:
|
||||
if role_name.lower() in user_roles:
|
||||
return True
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
def get_user_entity_from_event(cls, session, event):
|
||||
"""Query user entity from event."""
|
||||
not_set = object()
|
||||
|
||||
# Check if user is already stored in event data
|
||||
user_entity = event["data"].get("user_entity", not_set)
|
||||
if user_entity is not_set:
|
||||
# Query user entity from event
|
||||
user_info = event.get("source", {}).get("user", {})
|
||||
user_id = user_info.get("id")
|
||||
username = user_info.get("username")
|
||||
if user_id:
|
||||
user_entity = session.query(
|
||||
"User where id is {}".format(user_id)
|
||||
).first()
|
||||
if not user_entity and username:
|
||||
user_entity = session.query(
|
||||
"User where username is {}".format(username)
|
||||
).first()
|
||||
event["data"]["user_entity"] = user_entity
|
||||
|
||||
return user_entity
|
||||
|
||||
@classmethod
|
||||
def get_user_roles_from_event(cls, session, event):
|
||||
"""Query user entity from event."""
|
||||
not_set = object()
|
||||
|
||||
user_roles = event["data"].get("user_roles", not_set)
|
||||
if user_roles is not_set:
|
||||
user_roles = []
|
||||
user_entity = cls.get_user_entity_from_event(session, event)
|
||||
for role in user_entity["user_security_roles"]:
|
||||
user_roles.append(role["security_role"]["name"].lower())
|
||||
event["data"]["user_roles"] = user_roles
|
||||
return user_roles
|
||||
|
||||
def get_project_entity_from_event(self, session, event, entities):
|
||||
"""Load or query and fill project entity from/to event data.
|
||||
|
||||
Project data are stored by ftrack id because in most cases it is
|
||||
easier to access project id than project name.
|
||||
|
||||
Args:
|
||||
session (ftrack_api.Session): Current session.
|
||||
event (ftrack_api.Event): Processed event by session.
|
||||
entities (list): Ftrack entities of selection.
|
||||
"""
|
||||
|
||||
# Try to get project entity from event
|
||||
project_entity = event["data"].get("project_entity")
|
||||
if not project_entity:
|
||||
project_entity = self.get_project_from_entity(
|
||||
entities[0], session
|
||||
)
|
||||
event["data"]["project_entity"] = project_entity
|
||||
return project_entity
|
||||
|
||||
def get_ftrack_settings(self, session, event, entities):
|
||||
project_entity = self.get_project_entity_from_event(
|
||||
session, event, entities
|
||||
)
|
||||
project_settings = self.get_project_settings_from_event(
|
||||
event, project_entity
|
||||
)
|
||||
return project_settings["ftrack"]
|
||||
|
||||
def valid_roles(self, session, entities, event):
|
||||
"""Validate user roles by settings.
|
||||
|
||||
Method requires to have set `settings_key` attribute.
|
||||
"""
|
||||
ftrack_settings = self.get_ftrack_settings(session, event, entities)
|
||||
settings = (
|
||||
ftrack_settings[self.settings_frack_subkey][self.settings_key]
|
||||
)
|
||||
if not settings.get("enabled", True):
|
||||
return False
|
||||
|
||||
user_role_list = self.get_user_roles_from_event(session, event)
|
||||
if not self.roles_check(settings.get("role_list"), user_role_list):
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
class ServerAction(BaseAction):
|
||||
"""Action class meant to be used on event server.
|
||||
|
|
@ -261,6 +312,8 @@ class ServerAction(BaseAction):
|
|||
For the same reason register is modified to not filter topics by username.
|
||||
"""
|
||||
|
||||
settings_frack_subkey = "events"
|
||||
|
||||
def register(self):
|
||||
"""Register subcription to Ftrack event hub."""
|
||||
self.session.event_hub.subscribe(
|
||||
|
|
|
|||
|
|
@ -528,7 +528,7 @@ class BaseHandler(object):
|
|||
"Publishing event: {}"
|
||||
).format(str(event.__dict__)))
|
||||
|
||||
def get_project_from_entity(self, entity):
|
||||
def get_project_from_entity(self, entity, session=None):
|
||||
low_entity_type = entity.entity_type.lower()
|
||||
if low_entity_type == "project":
|
||||
return entity
|
||||
|
|
@ -549,7 +549,10 @@ class BaseHandler(object):
|
|||
return parent["project"]
|
||||
|
||||
project_data = entity["link"][0]
|
||||
return self.session.query(
|
||||
|
||||
if session is None:
|
||||
session = self.session
|
||||
return session.query(
|
||||
"Project where id is {}".format(project_data["id"])
|
||||
).one()
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue