def test_update_annotations(self): self.modifications = [{ "time": "0", "drawing": { "objects": [{ "id": "obj1", "type": "path", "path": ["Q", 2, 14] }] } }] preview_file = self.generate_fixture_preview_file().serialize() preview_files_service.update_preview_file_annotations( self.user_id, self.project_id, preview_file["id"], additions=self.annotations_1 + self.annotations_2) persisted_preview_file = \ files_service.get_preview_file(preview_file["id"]) preview_files_service.update_preview_file_annotations( self.user_id, self.project_id, preview_file["id"], updates=self.modifications) persisted_preview_file = \ files_service.get_preview_file(preview_file["id"]) self.assertEqual( self.modifications + self.annotations_2, persisted_preview_file["annotations"], )
def test_add_annotations_different_objects(self): expected_result = [{ "time": "0", "drawing": { "objects": [ self.annotations_1[0]["drawing"]["objects"][0], self.annotations_3[0]["drawing"]["objects"][0] ] } }] preview_file = self.generate_fixture_preview_file().serialize() preview_files_service.update_preview_file_annotations( self.user_id, self.project_id, preview_file["id"], additions=self.annotations_1, ) preview_files_service.update_preview_file_annotations( self.user_id, self.project_id, preview_file["id"], additions=self.annotations_3, ) annotations = \ files_service.get_preview_file(preview_file["id"])["annotations"] self.assertEqual(expected_result, annotations) preview_files_service.update_preview_file_annotations( self.user_id, self.project_id, preview_file["id"], additions=self.annotations_3, ) annotations = \ files_service.get_preview_file(preview_file["id"])["annotations"] self.assertEqual(expected_result, annotations)
def test_delete_annotations(self): preview_file = self.generate_fixture_preview_file().serialize() preview_files_service.update_preview_file_annotations( self.user_id, self.project_id, preview_file["id"], additions=self.annotations_1, ) preview_files_service.update_preview_file_annotations( self.user_id, self.project_id, preview_file["id"], additions=[], deletions=[{ "time": "2", "objects": ["obj1"] }], ) persisted_preview_file = files_service.get_preview_file( preview_file["id"]) self.assertEqual( self.annotations_1, persisted_preview_file["annotations"], ) preview_files_service.update_preview_file_annotations( self.user_id, self.project_id, preview_file["id"], additions=[], deletions=[{ "time": "0", "objects": ["obj4"] }], ) persisted_preview_file = files_service.get_preview_file( preview_file["id"]) self.assertEqual( self.annotations_1, persisted_preview_file["annotations"], ) preview_files_service.update_preview_file_annotations( self.user_id, self.project_id, preview_file["id"], additions=[], deletions=[{ "time": "0", "objects": ["obj1"] }], ) persisted_preview_file = files_service.get_preview_file( preview_file["id"]) self.assertEqual( [], persisted_preview_file["annotations"], )
def retrieve_playlist_tmp_files(playlist): """ Retrieve all files for a given playlist into the temporary folder. """ preview_file_ids = [] for shot in playlist["shots"]: if ("preview_file_id" in shot and shot["preview_file_id"] is not None and len(shot["preview_file_id"]) > 0): preview_file = files_service.get_preview_file( shot["preview_file_id"]) if preview_file is not None and preview_file["extension"] == "mp4": preview_file_ids.append(preview_file["id"]) file_paths = [] for preview_file_id in preview_file_ids: if config.FS_BACKEND == "local": file_path = file_store.get_local_movie_path( "previews", preview_file_id) else: file_path = os.path.join( config.TMP_DIR, "cache-previews-%s.%s" % (preview_file_id, "mp4"), ) if not os.path.exists(file_path) or os.path.getsize( file_path) == 0: with open(file_path, "wb") as tmp_file: for chunk in file_store.open_movie("previews", preview_file_id): tmp_file.write(chunk) file_name = names_service.get_preview_file_name(preview_file_id) tmp_file_path = os.path.join(config.TMP_DIR, file_name) copyfile(file_path, tmp_file_path) file_paths.append((tmp_file_path, file_name)) return file_paths
def put(self, preview_file_id): preview_file = files_service.get_preview_file(preview_file_id) task = tasks_service.get_task(preview_file["task_id"]) user_service.check_project_access(task["project_id"]) is_manager = permissions.has_manager_permissions() is_client = permissions.has_client_permissions() is_supervisor_allowed = False if permissions.has_supervisor_permissions(): user_departments = persons_service.get_current_user( relations=True)["departments"] if (user_departments == [] or tasks_service.get_task_type( task["task_type_id"])["department_id"] in user_departments): is_supervisor_allowed = True if not (is_manager or is_client or is_supervisor_allowed): raise permissions.PermissionDenied additions = request.json.get("additions", []) updates = request.json.get("updates", []) deletions = request.json.get("deletions", []) user = persons_service.get_current_user() return preview_files_service.update_preview_file_annotations( user["id"], task["project_id"], preview_file_id, additions=additions, updates=updates, deletions=deletions, )
def get(self, instance_id): if not self.is_allowed(instance_id): abort(403) preview_file = files_service.get_preview_file(instance_id) extension = preview_file["extension"] try: if extension == "png": return send_picture_file("original", instance_id, as_attachment=True) elif extension == "pdf": mimetype = "application/pdf" return send_standard_file(instance_id, extension, mimetype, as_attachment=True) else: return send_standard_file(instance_id, extension, as_attachment=True) except FileNotFound: current_app.logger.error("File was not found for: %s" % instance_id) abort(404)
def emit_app_preview_event(self, preview_file_id): """ Emit an event, each time a preview is added. """ preview_file = files_service.get_preview_file(preview_file_id) comment = tasks_service.get_comment_by_preview_file_id(preview_file_id) task = tasks_service.get_task(preview_file["task_id"]) comment_id = None if comment is not None: comment_id = comment["id"] events.emit( "comment:update", {"comment_id": comment_id}, project_id=task["project_id"], ) events.emit( "preview-file:add-file", { "comment_id": comment_id, "task_id": preview_file["task_id"], "preview_file_id": preview_file["id"], "revision": preview_file["revision"], "extension": preview_file["extension"], "status": preview_file["status"], }, project_id=task["project_id"], )
def put(self, entity_id, preview_file_id): preview_file = files_service.get_preview_file(preview_file_id) task = tasks_service.get_task(preview_file["task_id"]) user_service.check_project_access(task["project_id"]) return entities_service.update_entity_preview( entity_id, preview_file_id )
def get_preview_file_name(preview_file_id): """ Build unique and human readable file name for preview downloads. The convention followed is: [project_name]_[entity_name]_[task_type_name]_v[revivision].[extension]. """ organisation = Organisation.query.first() preview_file = files_service.get_preview_file(preview_file_id) task = tasks_service.get_task(preview_file["task_id"]) task_type = tasks_service.get_task_type(task["task_type_id"]) project = projects_service.get_project(task["project_id"]) (entity_name, _) = get_full_entity_name(task["entity_id"]) if (organisation.use_original_file_name and preview_file.get("original_name", None) is not None): name = preview_file["original_name"] else: name = "%s_%s_%s_v%s" % ( project["name"], entity_name, task_type["name"], preview_file["revision"], ) name = slugify.slugify(name, separator="_") return "%s.%s" % (name, preview_file["extension"])
def update_preview_file_annotations(person_id, project_id, preview_file_id, additions=[], updates=[], deletions=[]): """ Update annotations for given preview file. """ preview_file = files_service.get_preview_file_raw(preview_file_id) previous_annotations = preview_file.annotations or [] annotations = _apply_annotation_additions(previous_annotations, additions) annotations = _apply_annotation_updates(annotations, updates) annotations = _apply_annotation_deletions(annotations, deletions) preview_file.update({"annotations": []}) preview_file.update({"annotations": annotations}) files_service.clear_preview_file_cache(preview_file_id) preview_file = files_service.get_preview_file(preview_file_id) events.emit( "preview-file:annotation-update", { "preview_file_id": preview_file_id, "person_id": person_id, "updated_at": preview_file["updated_at"], }, project_id=project_id, ) return preview_file
def is_allowed(self, preview_file_id): preview_file = files_service.get_preview_file(preview_file_id) task = tasks_service.get_task(preview_file["task_id"]) try: user_service.check_project_access(task["project_id"]) return True except permissions.PermissionDenied: return False
def put(self, preview_file_id): annotations = request.json["annotations"] preview_file = files_service.get_preview_file(preview_file_id) task = tasks_service.get_task(preview_file["task_id"]) user_service.check_manager_project_access(task["project_id"]) user_service.check_entity_access(task["entity_id"]) return preview_files_service.update_preview_file_annotations( task["project_id"], preview_file_id, annotations )
def is_allowed(self, preview_file_id): """ Return true if user is allowed to add a preview. """ if permissions.has_manager_permissions(): return True else: preview_file = files_service.get_preview_file(preview_file_id) return user_service.check_assigned(preview_file["task_id"])
def put(self, preview_file_id): parser = reqparse.RequestParser() parser.add_argument("position", default=0, type=int) args = parser.parse_args() preview_file = files_service.get_preview_file(preview_file_id) task = tasks_service.get_task(preview_file["task_id"]) user_service.check_manager_project_access(task["project_id"]) return tasks_service.update_preview_file_position( preview_file_id, args["position"])
def put(self, preview_file_id): preview_file = files_service.get_preview_file(preview_file_id) task = tasks_service.get_task(preview_file["task_id"]) user_service.check_project_access(task["project_id"]) user_service.check_entity_access(task["entity_id"]) asset = entities_service.update_entity_preview(task["entity_id"], preview_file_id) assets_service.clear_asset_cache(asset["id"]) shots_service.clear_shot_cache(asset["id"]) return asset
def is_allowed(self, preview_file_id): if permissions.has_manager_permissions(): return True else: preview_file = files_service.get_preview_file(preview_file_id) task = tasks_service.get_task(preview_file["task_id"]) try: user_service.check_has_task_related(task["project_id"]) return True except permissions.PermissionDenied: return False
def is_allowed(self, preview_file_id): """ Return true if user is allowed to add a preview. """ preview_file = files_service.get_preview_file(preview_file_id) task = tasks_service.get_task(preview_file["task_id"]) try: user_service.check_project_access(task["project_id"]) user_service.check_entity_access(task["entity_id"]) return True except permissions.PermissionDenied: return False
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 test_add_annotations(self): preview_file = self.generate_fixture_preview_file().serialize() preview_files_service.update_preview_file_annotations( self.user_id, self.project_id, preview_file["id"], additions=self.annotations_1) persisted_preview_file = \ files_service.get_preview_file(preview_file["id"]) self.assertEqual( self.annotations_1, persisted_preview_file["annotations"], )
def emit_app_preview_event(self, preview_file_id): preview_file = files_service.get_preview_file(preview_file_id) comment = tasks_service.get_comment_by_preview_file_id( preview_file_id ) comment_id = None if comment is not None: comment_id = comment["id"] events.emit("preview:add", { "comment_id": comment_id, "task_id": preview_file["task_id"], "preview": preview_file })
def retrieve_playlist_tmp_files(playlist, only_movies=False): """ Retrieve all files for a given playlist into the temporary folder. """ preview_files = [] for entity in playlist["shots"]: if ("preview_file_id" in entity and entity["preview_file_id"] is not None and len(entity["preview_file_id"]) > 0): preview_file = files_service.get_preview_file( entity["preview_file_id"]) if preview_file is not None and ( (only_movies and preview_file["extension"] == "mp4") or not only_movies): preview_files.append(preview_file) file_paths = [] for preview_file in preview_files: prefix = "original" if preview_file["extension"] == "mp4": get_path_func = file_store.get_local_movie_path open_func = file_store.open_movie prefix = "previews" elif preview_file["extension"] == "png": get_path_func = file_store.get_local_picture_path open_func = file_store.open_picture else: get_path_func = file_store.get_local_file_path open_func = file_store.open_file if config.FS_BACKEND == "local": file_path = get_path_func(prefix, preview_file["id"]) else: file_path = os.path.join( config.TMP_DIR, "cache-previews-%s.%s" % (preview_file["id"], preview_file["extension"]), ) if not os.path.exists(file_path) or os.path.getsize( file_path) == 0: with open(file_path, "wb") as tmp_file: for chunk in open_func(prefix, preview_file["id"]): tmp_file.write(chunk) file_name = names_service.get_preview_file_name(preview_file["id"]) tmp_file_path = os.path.join(config.TMP_DIR, file_name) copyfile(file_path, tmp_file_path) file_paths.append((tmp_file_path, file_name)) return file_paths
def get_preview_file_name(preview_file_id): """ Build unique and human readable file name for preview downloads. The convention followed is: [project_name]_[entity_name]_[task_type_name]_v[revivision].[extension]. """ preview_file = files_service.get_preview_file(preview_file_id) task = tasks_service.get_task(preview_file["task_id"]) task_type = tasks_service.get_task_type(task["task_type_id"]) project = projects_service.get_project(task["project_id"]) (entity_name, _) = get_full_entity_name(task["entity_id"]) name = "%s_%s_%s_v%s" % (project["name"], entity_name, task_type["name"], preview_file["revision"]) return "%s.%s" % (slugify.slugify( name, separator="_"), preview_file["extension"])
def build_row(self, shot): name, _ = names_service.get_full_entity_name(shot["entity_id"]) preview_file = files_service.get_preview_file(shot["preview_file_id"]) task = tasks_service.get_task(shot["preview_file_task_id"]) task_type = self.task_type_map[task["task_type_id"]] task_status = self.task_status_map[task["task_status_id"]] comment = self.task_comment_map.get(task["id"], {}) author = self.get_author(comment) date = self.get_date(comment) return [ name, task_type["name"], preview_file["revision"], task_status["name"], author, date, comment.get("text",""), ]
def emit_app_preview_event(self, preview_file_id): """ Emit an event, each time a preview is added. """ preview_file = files_service.get_preview_file(preview_file_id) comment = tasks_service.get_comment_by_preview_file_id(preview_file_id) comment_id = None if comment is not None: comment_id = comment["id"] events.emit( "preview:add", { "comment_id": comment_id, "task_id": preview_file["task_id"], "preview_file_id": preview_file["id"], "is_movie": preview_file["is_movie"], "revision": preview_file["revision"], "extension": preview_file["extension"] })
def retrieve_playlist_tmp_files(preview_files, full=False): """ Retrieve all files for a given playlist into the temporary folder. """ file_paths = [] for preview_file in preview_files: if full: preview_file = files_service.get_preview_file(preview_file["id"]) sub_preview_files = ( preview_files_service.get_preview_files_for_revision( preview_file["task_id"], preview_file["revision"])) for preview_file in sub_preview_files: tmp_file_path, file_name = retrieve_playlist_tmp_file( preview_file) file_paths.append((tmp_file_path, file_name)) else: tmp_file_path, file_name = retrieve_playlist_tmp_file(preview_file) file_paths.append((tmp_file_path, file_name)) return file_paths
def put(self, preview_file_id): preview_file = files_service.get_preview_file(preview_file_id) task = tasks_service.get_task(preview_file["task_id"]) user_service.check_project_access(task["project_id"]) is_manager = permissions.has_manager_permissions() is_client = permissions.has_client_permissions() if not (is_manager or is_client): raise permissions.PermissionDenied additions = request.json.get("additions", []) updates = request.json.get("updates", []) deletions = request.json.get("deletions", []) user = persons_service.get_current_user() return preview_files_service.update_preview_file_annotations( user["id"], task["project_id"], preview_file_id, additions=additions, updates=updates, deletions=deletions)
def playlist_previews(shots, only_movies=False): """ Retrieve all preview id and extension for the given shots. """ preview_files = [] for entity in shots: if ("preview_file_id" in entity and entity["preview_file_id"] is not None and len(entity["preview_file_id"]) > 0): preview_file = files_service.get_preview_file( entity["preview_file_id"]) if preview_file is not None and ( (only_movies and preview_file["extension"] == "mp4") or not only_movies): preview_files.append(preview_file) return [{ "id": x["id"], "extension": x["extension"] } for x in preview_files]
def post(self, task_id, comment_id, preview_file_id): """ Add a preview to given comment. --- tags: - Tasks parameters: - in: path name: task_id required: True schema: type: UUID example: a24a6ea4-ce75-4665-a070-57453082c25 - in: path name: comment_id required: True schema: type: UUID example: a24a6ea4-ce75-4665-a070-57453082c25 - in: path name: preview_file_id required: True schema: type: UUID example: a24a6ea4-ce75-4665-a070-57453082c25 responses: 201: description: Preview added to given comment """ task = tasks_service.get_task(task_id) user_service.check_project_access(task["project_id"]) user_service.check_entity_access(task["entity_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_comments(task_id, is_client=False, is_manager=False): """ Return all comments related to given task. """ comments = [] query = ( Comment.query.order_by(Comment.created_at.desc()) .filter_by(object_id=task_id) .join(Person, TaskStatus) .add_columns( TaskStatus.name, TaskStatus.short_name, TaskStatus.color, Person.first_name, Person.last_name, Person.has_avatar, ) ) if is_client: query = query.filter(Person.role == "client") if not is_client and not is_manager: query = query.filter(Person.role != "client") for result in query.all(): ( comment, task_status_name, task_status_short_name, task_status_color, person_first_name, person_last_name, person_has_avatar, ) = result comment_dict = comment.serialize() comment_dict["person"] = { "first_name": person_first_name, "last_name": person_last_name, "has_avatar": person_has_avatar, "id": str(comment.person_id), } comment_dict["task_status"] = { "name": task_status_name, "short_name": task_status_short_name, "color": task_status_color, "id": str(comment.task_status_id), } if comment.preview_file_id is not None: # Legacy stuff, should not be used anymore. preview = files_service.get_preview_file(comment.preview_file_id) comment_dict["previews"] = [ { "id": str(preview.id), "revision": preview["revision"], "extension": preview["extension"], "annotations": preview["annotations"], } ] else: comment_dict["previews"] = [] previews = sorted(comment.previews, key=lambda x: x.created_at) for preview in previews: comment_dict["previews"].append( { "id": str(preview.id), "revision": preview.revision, "extension": preview.extension, "annotations": preview.annotations, } ) comments.append(comment_dict) return comments
def is_exist(self, preview_file_id): return files_service.get_preview_file(preview_file_id) is not None