def post(self, task_id, comment_id): task = tasks_service.get_task(task_id) user_service.check_project_access(task["project_id"]) user_service.check_entity_access(task["entity_id"]) comment = tasks_service.get_comment(comment_id) tasks_service.get_task_status(comment["task_status_id"]) person = persons_service.get_current_user() preview_file = tasks_service.add_preview_file_to_comment( comment_id, person["id"], task_id ) return preview_file, 201
def post(self, person_id): arguments = self.get_arguments() current_user = persons_service.get_current_user() if current_user["id"] != person_id and \ not permissions.has_admin_permissions(): raise permissions.PermissionDenied desktop_login_log = persons_service.create_desktop_login_logs( person_id, arguments["date"]) return desktop_login_log, 201
def get(self, sequence_id): """ Retrieve all shot entries for a given sequence. Filters can be specified in the query string. """ sequence = shots_service.get_sequence(sequence_id) user_service.check_project_access(sequence["project_id"]) criterions = query.get_query_criterions_from_request(request) criterions["parent_id"] = sequence_id if permissions.has_vendor_permissions(): criterions["assigned_to"] = persons_service.get_current_user()["id"] return shots_service.get_shots(criterions)
def remove_filter(search_filter_id): """ Remove given filter from database. """ current_user = persons_service.get_current_user() search_filter = SearchFilter.get_by(id=search_filter_id, person_id=current_user["id"]) if search_filter is None: raise SearchFilterNotFoundException search_filter.delete() clear_filter_cache(current_user["id"]) return search_filter.serialize()
def get(self, project_id, asset_type_id): """ Retrieve all assets for given project and entity type. """ user_service.check_project_access(project_id) criterions = query.get_query_criterions_from_request(request) criterions["project_id"] = project_id criterions["entity_type_id"] = asset_type_id if permissions.has_vendor_permissions(): criterions["assigned_to"] = persons_service.get_current_user( )["id"] return assets_service.get_assets(criterions)
def post(self, task_id, comment_id, preview_file_id): task = tasks_service.get_task(task_id) user_service.check_project_access(task["project_id"]) tasks_service.get_comment(comment_id) person = persons_service.get_current_user() related_preview_file = files_service.get_preview_file(preview_file_id) preview_file = tasks_service.add_preview_file_to_comment( comment_id, person["id"], task_id, related_preview_file["revision"] ) return preview_file, 201
def get(self): """ Retrieve desktop login logs. --- tags: - User responses: 200: description: Desktop login logs """ current_user = persons_service.get_current_user() return persons_service.get_desktop_login_logs(current_user["id"])
def post(self, task_id): (task_status_id, comment, person_id) = self.get_arguments() task = tasks_service.get_task(task_id) user_service.check_project_access(task["project_id"]) task_status = tasks_service.get_task_status(task_status_id) if person_id: person = persons_service.get_person(person_id) else: person = persons_service.get_current_user() comment = tasks_service.create_comment(object_id=task_id, object_type="Task", task_status_id=task_status_id, person_id=person["id"], text=comment) status_changed = task_status_id != task["task_status_id"] new_data = { "task_status_id": task_status_id, "last_comment_date": comment["created_at"] } if status_changed: if task_status["is_retake"]: retake_count = task["retake_count"] if retake_count is None or retake_count == 'NoneType': retake_count = 0 new_data["retake_count"] = retake_count + 1 if task_status["is_done"]: new_data["end_date"] = datetime.datetime.now() else: new_data["end_date"] = None if task_status["short_name"] == "wip" \ and task["real_start_date"] is None: new_data["real_start_date"] = datetime.datetime.now() tasks_service.update_task(task_id, new_data) notifications_service.create_notifications_for_task_and_comment( task, comment, change=status_changed) news_service.create_news_for_task_and_comment(task, comment, change=status_changed) comment["task_status"] = task_status comment["person"] = person return comment, 201
def get(self, playlist_id): playlist = playlists_service.get_playlist(playlist_id) user_service.check_manager_project_access(playlist["project_id"]) if config.ENABLE_JOB_QUEUE: current_user = persons_service.get_current_user() queue_store.job_queue.enqueue( playlists_service.build_playlist_job, args=(playlist, current_user["email"]), job_timeout=3600, ) return {"job": "running"} else: playlists_service.build_playlist_movie_file(playlist) return {"job": "succeeded"}
def check_belong_to_project(project_id): """ Return true if current user is assigned to a task of the given project or if current_user is part of the project team. """ if project_id is None: return False project = projects_service.get_project_with_relations(str(project_id)) current_user = persons_service.get_current_user() if current_user["id"] in project["team"]: return True else: return False
def get(self): """ Retrieve all entities that are not shot or sequence. Adds project name and asset type name and all related tasks. If episode_id is given as parameter, it returns assets not linked to an episode and assets linked to given episode. """ criterions = query.get_query_criterions_from_request(request) page = query.get_page_from_request(request) check_criterion_access(criterions) if permissions.has_vendor_permissions(): criterions["assigned_to"] = persons_service.get_current_user( )["id"] return assets_service.get_assets_and_tasks(criterions, page)
def mark_notifications_as_read(): """ Mark all recent notifications for current_user as read. It is useful to mark a list of notifications as read after an user retrieved them. """ current_user = persons_service.get_current_user() notifications = (Notification.query.filter_by( person_id=current_user["id"], read=False).order_by(Notification.created_at).limit(100).all()) for notification in notifications: notification.update({"read": True}) return fields.serialize_list(notifications)
def get(self): """ Retrieve all shot entries. Filters can be specified in the query string. """ criterions = query.get_query_criterions_from_request(request) if "sequence_id" in criterions: sequence = shots_service.get_sequence(criterions["sequence_id"]) criterions["project_id"] = sequence["project_id"] criterions["parent_id"] = sequence["id"] del criterions["sequence_id"] if permissions.has_vendor_permissions(): criterions["assigned_to"] = persons_service.get_current_user()["id"] user_service.check_project_access(criterions.get("project_id", None)) return shots_service.get_shots(criterions)
def create_task(task_type, entity, name="main"): """ Create a new task for given task type and entity. """ task_status = get_todo_status() try: try: current_user_id = persons_service.get_current_user()["id"] except RuntimeError: current_user_id = None task = Task.create( name=name, duration=0, estimation=0, completion_rate=0, start_date=None, end_date=None, due_date=None, real_start_date=None, project_id=entity["project_id"], task_type_id=task_type["id"], task_status_id=task_status["id"], entity_id=entity["id"], assigner_id=current_user_id, assignees=[], ) task_dict = task.serialize(relations=True) task_dict.update( { "task_status_id": task_status["id"], "task_status_name": task_status["name"], "task_status_short_name": task_status["short_name"], "task_status_color": task_status["color"], "task_type_id": task_type["id"], "task_type_name": task_type["name"], "task_type_color": task_type["color"], "task_type_priority": task_type["priority"], } ) events.emit( "task:new", {"task_id": task.id}, project_id=entity["project_id"] ) return task_dict except IntegrityError: pass # Tasks already exists, no need to create it.
def create_filter(list_type, name, query, project_id=None, entity_type=None): """ Add a new search filter to the database. """ current_user = persons_service.get_current_user() search_filter = SearchFilter.create( list_type=list_type, name=name, search_query=query, project_id=project_id, person_id=current_user["id"], entity_type=entity_type, ) search_filter.serialize() clear_filter_cache(current_user["id"]) return search_filter.serialize()
def get(self): """ Return a table giving time spent by user and by month for given year. --- tags: - Persons responses: 200: description: Table giving time spent by user and by month for given year """ project_id = self.get_project_id() person_id = None if not permissions.has_admin_permissions(): person_id = persons_service.get_current_user()["id"] return time_spents_service.get_year_table( person_id=person_id, project_id=project_id )
def get(self): """ Retrieve all entities that are not shot or sequence. Adds project name and asset type name. --- tags: - Assets responses: 200: description: All assets """ criterions = query.get_query_criterions_from_request(request) check_criterion_access(criterions) if permissions.has_vendor_permissions(): criterions["assigned_to"] = persons_service.get_current_user( )["id"] return assets_service.get_assets(criterions)
def check_project_departement_access(task_id, person_id): """ Return true if current user is admin or is manager and is in team or is artist in the task department. """ user = persons_service.get_current_user(relations=True) task = tasks_service.get_task(task_id) task_type = tasks_service.get_task_type(task["task_type_id"]) is_allowed = (permissions.has_admin_permissions() or (permissions.has_manager_permissions() and check_belong_to_project(task["project_id"])) or (check_belong_to_project(task["project_id"]) and task_type["department_id"] in user["departments"] and person_id == user["id"])) if not is_allowed: raise permissions.PermissionDenied return is_allowed
def post(self, file_id): ( task_status_id, # NOT USED CURRENTLY comment, person_id, created_at, checklist) = self.get_arguments() output_file = files_service.get_output_file(file_id) # TODO: test and maybe check_asset_access if output_file.get("entity_id"): instance = entities_service.get_entity(output_file["entity_id"]) elif output_file.get("asset_instance_id"): instance = assets_service.get_asset_instance( output_file["asset_instance_id"]) user_service.check_project_access(instance["project_id"]) # TODO: improve this task_status = TaskStatus.get_by(short_name="wip") if not task_status: print("no task status") return None, 404 task_status_id = task_status.id if not permissions.has_manager_permissions(): person_id = None created_at = None if person_id: person = persons_service.get_person(person_id) else: person = persons_service.get_current_user() comment = tasks_service.create_comment(object_id=file_id, object_type="OutputFile", files=request.files, person_id=person["id"], task_status_id=task_status_id, text=comment, checklist=checklist, created_at=created_at) comment["task_status"] = task_status.serialize() comment["person"] = person return comment, 201
def post(self, project_id): comments = request.json person_id = persons_service.get_current_user()["id"] try: user_service.check_manager_project_access(project_id) except permissions.PermissionDenied: comments = self.get_allowed_comments_only(comments, person_id) result = [] for comment in comments: try: comment = comments_service.create_comment( person_id, comment["object_id"], comment["task_status_id"], comment["comment"], [], {}, None) result.append(comment) except KeyError: pass return result, 201
def reply_comment(comment_id, text): person = persons_service.get_current_user() comment = tasks_service.get_comment_raw(comment_id) if comment.replies is None: comment.replies = [] reply = { "id": str(fields.gen_uuid()), "date": date_helpers.get_now(), "person_id": person["id"], "text": text } replies = comment.replies replies.append(reply) comment.replies = [] comment.save() comment.update({"replies": replies}) return reply
def post(self, project_id): comments = request.json user_service.check_manager_project_access(project_id) person_id = persons_service.get_current_user()["id"] result = [] for comment in comments: comment = comments_service.create_comment( person_id, comment["object_id"], comment["task_status_id"], comment["comment"], [], {}, None ) result.append(comment) return result, 201
def create_tasks(task_type, entities): """ Create a new task for given task type and for each entity. """ task_status = get_todo_status() current_user_id = None try: current_user_id = persons_service.get_current_user()["id"] except RuntimeError: pass tasks = [] for entity in entities: existing_task = Task.query \ .filter_by( entity_id=entity["id"], task_type_id=task_type["id"] ) \ .scalar() if existing_task is None: task = Task.create_no_commit( name="main", duration=0, estimation=0, completion_rate=0, start_date=None, end_date=None, due_date=None, real_start_date=None, project_id=entity["project_id"], task_type_id=task_type["id"], task_status_id=task_status["id"], entity_id=entity["id"], assigner_id=current_user_id, assignees=[], ) tasks.append(task) Task.commit() task_dicts = [] for task in tasks: task_dict = _finalize_task_creation(task_type, task_status, task) task_dicts.append(task_dict) return task_dicts
def get(self, playlist_id): playlist = playlists_service.get_playlist(playlist_id) user_service.check_project_access(playlist["project_id"]) if config.ENABLE_JOB_QUEUE: current_user = persons_service.get_current_user() queue_store.job_queue.enqueue(playlists_service.build_playlist_job, playlist, current_user["email"]) return {"job": "running"} else: movie_file_path = playlists_service.build_playlist_movie_file( playlist) attachment_filename = movie_file_path.split(os.sep)[-1] return flask_send_file(movie_file_path, conditional=True, mimetype="video/mp4", as_attachment=True, attachment_filename=attachment_filename)
def check_has_task_related(project_id): """ Return true if current user is assigned to a task of the given project or if current_user is part of the project team. """ project = projects_service.get_project(project_id) current_user = persons_service.get_current_user() if current_user["id"] in project["team"]: return True query = Project.query \ .join(Task) \ .filter(build_assignee_filter()) \ if query.first() is None: raise permissions.PermissionDenied return True
def check_task_departement_access(task_id, person_id): """ Return true if current user is an admin or is a manager and is in team or is a supervisor in the department of the task or is an artist assigning himself in the department of the task. """ user = persons_service.get_current_user(relations=True) task = tasks_service.get_task(task_id) task_type = tasks_service.get_task_type(task["task_type_id"]) is_allowed = ( permissions.has_admin_permissions() or ( permissions.has_manager_permissions() and check_belong_to_project(task["project_id"]) ) or ( permissions.has_supervisor_permissions() and check_belong_to_project(task["project_id"]) and ( user["departments"] == [] or ( task_type["department_id"] in user["departments"] and len( set( persons_service.get_person(person_id)[ "departments" ] ) & set(user["departments"]) ) > 0 ) ) ) or ( check_belong_to_project(task["project_id"]) and task_type["department_id"] in user["departments"] and person_id == user["id"] ) ) if not is_allowed: raise permissions.PermissionDenied return is_allowed
def post(self, person_id): """ Create desktop login logs. --- tags: - Persons description: Set "default" as password. User role can be set but only admins can create admin users. parameters: - in: path name: person_id required: True schema: type: UUID example: a24a6ea4-ce75-4665-a070-57453082c25 - in: body name: Date schema: type: object required: - date properties: date: type: timestamp example: 2022-07-12 responses: 201: description: Desktop login logs created """ arguments = self.get_arguments() current_user = persons_service.get_current_user() if ( current_user["id"] != person_id and not permissions.has_admin_permissions() ): raise permissions.PermissionDenied desktop_login_log = persons_service.create_desktop_login_logs( person_id, arguments["date"] ) return desktop_login_log, 201
def get_arguments(self): person = persons_service.get_current_user() maxsoft = files_service.get_or_create_software("3ds Max", "max", ".max") parser = reqparse.RequestParser() parser.add_argument("name", help="The asset name is required.", required=True) parser.add_argument("description", default="") parser.add_argument("comment", default="") parser.add_argument("person_id", default=person["id"]) parser.add_argument("software_id", default=maxsoft["id"]) parser.add_argument("revision", default=0, type=int) parser.add_argument("sep", default="/") args = parser.parse_args() return (args["name"], args["description"], args["comment"], args["person_id"], args["software_id"], args["revision"], args["sep"])
def prepare_import(self, project_id): self.episodes = {} self.sequences = {} self.descriptor_fields = self.get_descriptor_field_map( project_id, "Shot" ) project = projects_service.get_project(project_id) self.is_tv_show = projects_service.is_tv_show(project) self.created_shots = [] self.task_types_in_project_for_shots = ( TaskType.query.join(ProjectTaskTypeLink) .filter(ProjectTaskTypeLink.project_id == project_id) .filter(TaskType.for_entity == "Shot") ) self.task_statuses = { status["id"]: [status[n] for n in ("name", "short_name")] for status in get_task_statuses() } self.current_user_id = get_current_user()["id"]
def post(self, task_id): ( name, description, comment, person_id, software_id, revision, sep ) = self.get_arguments() try: task = tasks_service.get_task(task_id) if not permissions.has_manager_permissions(): user_service.check_has_task_related(task["project_id"]) software = files_service.get_software(software_id) tasks_service.assign_task( task_id, persons_service.get_current_user()["id"] ) if revision == 0: revision = files_service.get_next_working_revision( task_id, name ) path = self.build_path(task, name, revision, software, sep) working_file = files_service.create_new_working_revision( task_id, person_id, software_id, name=name, path=path, comment=comment, revision=revision ) except EntryAlreadyExistsException: return {"error": "The given working file already exists."}, 400 return working_file, 201