def can_unpublish(user, video): """Return True if the user can unpublish subtitles for this video. Safe to use with anonymous users as well as non-team videos. Usage: {% if request.user|can_unpublish:video %} ... {% endif %} """ team_video = video.get_team_video() if not team_video: return False workflow = Workflow.get_for_team_video(team_video) if not workflow: return False if workflow.approve_enabled: return _can_approve(team_video, user) return False
def can_delete_task(task, user): """Return whether the given user can delete the given task.""" team, project, lang = task.team, task.team_video.project, task.language can_delete = can_delete_tasks(team, user, project, lang) # Allow stray review tasks to be deleted. if task.type == Task.TYPE_IDS['Review']: workflow = Workflow.get_for_team_video(task.team_video) if not workflow.review_allowed: return can_delete # Allow stray approve tasks to be deleted. if task.type == Task.TYPE_IDS['Approve']: workflow = Workflow.get_for_team_video(task.team_video) if not workflow.approve_allowed: return can_delete return can_delete and can_perform_task(user, task)
def can_approve(team_video, user, lang=None): workflow = Workflow.get_for_team_video(team_video) role = get_role_for_target(user, team_video.team, team_video.project, lang) if not workflow.approve_allowed: return False role_req = { 10: ROLE_MANAGER, 20: ROLE_ADMIN, }[workflow.approve_allowed] return role in _perms_equal_or_greater(role_req)
def _moderate_session(self, session, user): """Return the right moderation_status for a version based on the given session. Also may possibly return a Task object that needs to be saved once the subtitle_version is ready. Also perform any ancillary tasks that are appropriate, assuming the version actually gets created later. Also :( """ sl = session.language team_video = sl.video.get_team_video() if not team_video: return UNMODERATED, False workflow = Workflow.get_for_team_video(team_video) if not workflow.approve_enabled and not workflow.review_enabled: return UNMODERATED, False # If there are any open team tasks for this video/language, it needs to # be kept under moderation. tasks = team_video.task_set.incomplete().filter( Q(language=sl.language) | Q(type=Task.TYPE_IDS['Subtitle'])) if tasks: for task in tasks: if task.type == Task.TYPE_IDS['Subtitle']: if not task.language: task.language = sl.language task.save() return WAITING_MODERATION, False if sl.has_version: # If there are already active subtitles for this language, we're # dealing with an edit. if can_publish_edits_immediately(team_video, user, sl.language): # The user may have the rights to immediately publish edits to # subtitles. If that's the case we mark them as approved and # don't need a task. return APPROVED, False else: # Otherwise it's an edit that needs to be reviewed/approved. return WAITING_MODERATION, True else: # Otherwise we're dealing with a new set of subtitles for this # language. return WAITING_MODERATION, True
def can_unpublish_subs(team_video, user, lang): """Return whether the user has permission to unpublish subtitles. lang should be a language code string. """ workflow = Workflow.get_for_team_video(team_video) if workflow.approve_allowed: return can_approve(team_video, user, lang) if workflow.review_allowed: return can_review(team_video, user, lang, allow_own=True) return False
def can_post_edit_subtitles(team_video, user, lang=None): """ Returns wheter the user has permission to post edit an original language """ if user.is_staff: return True team = team_video.team if team.workflow_enabled: workflow = Workflow.get_for_team_video(team_video) if workflow.approve_allowed: return can_approve(team_video, user, lang=lang) elif workflow.review_allowed: return can_review(team_video, user, lang=lang) else: return team_video.team.is_member(user) else: return can_create_and_edit_subtitles(user, team_video, lang=lang)
def can_publish_edits_immediately(team_video, user, lang): """Return whether the user has permission to publish subtitle edits immediately. This may be the case when review/approval is not required, or when it is but the user is someone who can do it themselves. lang should be a language code string. """ workflow = Workflow.get_for_team_video(team_video) if workflow.approve_allowed: return can_approve(team_video, user, lang) if workflow.review_allowed: return can_review(team_video, user, lang) return True
def _create_review_or_approve_task(self, subtitle_version): team_video = subtitle_version.video.get_team_video() lang = subtitle_version.subtitle_language.language_code workflow = Workflow.get_for_team_video(team_video) if workflow.review_allowed: type = Task.TYPE_IDS['Review'] can_do = partial(can_review, allow_own=True) elif workflow.approve_allowed: type = Task.TYPE_IDS['Approve'] can_do = can_approve else: return None # TODO: Dedupe this and Task._find_previous_assignee # Find the assignee. # # For now, we'll assign the review/approval task to whomever did # it last time (if it was indeed done), but only if they're # still eligible to perform it now. last_task = team_video.task_set.complete().filter( language=lang, type=type).order_by('-completed')[:1] assignee = None if last_task: candidate = last_task[0].assignee if candidate and can_do(team_video, candidate, lang): assignee = candidate task = Task(team=team_video.team, team_video=team_video, assignee=assignee, language=lang, type=type) task.set_expiration() task.new_subtitle_version = subtitle_version if task.get_type_display() in ['Review', 'Approve']: task.new_review_base_version = subtitle_version task.save()
def can_review(team_video, user, lang=None, allow_own=False): workflow = Workflow.get_for_team_video(team_video) role = get_role_for_target(user, team_video.team, team_video.project, lang) if not workflow.review_allowed: return False role_req = { 10: ROLE_CONTRIBUTOR, 20: ROLE_MANAGER, 30: ROLE_ADMIN, }[workflow.review_allowed] # Check that the user has the correct role. if role not in _perms_equal_or_greater(role_req): return False # Users cannot review their own subtitles, unless we're specifically # overriding that restriction in the arguments. if allow_own: return True # Users usually cannot review their own subtitles. if not hasattr(team_video, '_cached_version_for_review'): team_video._cached_version_for_review = team_video.video.latest_version( language_code=lang, public_only=False) subtitle_version = team_video._cached_version_for_review if lang and subtitle_version and subtitle_version.author_id == user.id: if can_review_own_subtitles(role, team_video): return True else: return False return True
def test_can_approve(self): user, outsider = self.user, self.outsider self.team.workflow_enabled = True self.team.save() workflow = Workflow.get_for_team_video(self.nonproject_video) # TODO: Test with Project/video-specific workflows. # Approval disabled. workflow.approve_allowed = Workflow.APPROVE_IDS[ "Don't require approval"] workflow.save() self.clear_cached_workflows() for r in [ROLE_CONTRIBUTOR, ROLE_MANAGER, ROLE_ADMIN, ROLE_OWNER]: with self.role(r): self.assertFalse(can_approve(self.nonproject_video, user)) self.assertFalse(can_approve(self.nonproject_video, outsider)) # Manager approval. workflow.approve_allowed = Workflow.APPROVE_IDS["Manager must approve"] workflow.save() self.clear_cached_workflows() for r in [ROLE_MANAGER, ROLE_ADMIN, ROLE_OWNER]: with self.role(r): self.assertTrue(can_approve(self.nonproject_video, user)) for r in [ROLE_CONTRIBUTOR]: with self.role(r): self.assertFalse(can_approve(self.nonproject_video, user)) for r in [ROLE_MANAGER, ROLE_ADMIN]: with self.role(r, self.test_project): self.assertFalse(can_approve(self.nonproject_video, user)) self.assertTrue(can_approve(self.project_video, user)) self.assertFalse(can_approve(self.nonproject_video, outsider)) # Admin approval. workflow.approve_allowed = Workflow.APPROVE_IDS["Admin must approve"] workflow.save() self.clear_cached_workflows() for r in [ROLE_ADMIN, ROLE_OWNER]: with self.role(r): self.assertTrue(can_approve(self.nonproject_video, user)) for r in [ROLE_MANAGER, ROLE_CONTRIBUTOR]: with self.role(r): self.assertFalse(can_approve(self.nonproject_video, user)) for r in [ROLE_ADMIN]: with self.role(r, self.test_project): self.assertFalse(can_approve(self.nonproject_video, user)) self.assertTrue(can_approve(self.project_video, user)) self.assertFalse(can_approve(self.nonproject_video, outsider)) # Workflows disabled entirely. self.team.workflow_enabled = False self.team.save() self.clear_cached_workflows() for r in [ROLE_CONTRIBUTOR, ROLE_MANAGER, ROLE_ADMIN, ROLE_OWNER]: with self.role(r): self.assertFalse(can_approve(self.nonproject_video, user)) self.assertFalse(can_approve(self.nonproject_video, outsider))
def test_can_review(self): user, outsider = self.user, self.outsider workflow = Workflow.get_for_team_video(self.nonproject_video) self.team.workflow_enabled = True self.team.save() # TODO: Test with Project/video-specific workflows. # Review disabled. workflow.review_allowed = Workflow.REVIEW_IDS["Don't require review"] workflow.save() self.clear_cached_workflows() for r in [ROLE_CONTRIBUTOR, ROLE_MANAGER, ROLE_ADMIN, ROLE_OWNER]: with self.role(r): self.assertFalse(can_review(self.nonproject_video, user)) self.assertFalse(can_review(self.nonproject_video, outsider)) # Peer reviewing. workflow.review_allowed = Workflow.REVIEW_IDS["Peer must review"] workflow.save() self.clear_cached_workflows() for r in [ROLE_CONTRIBUTOR, ROLE_MANAGER, ROLE_ADMIN, ROLE_OWNER]: with self.role(r): self.assertTrue(can_review(self.nonproject_video, user)) self.assertFalse(can_review(self.nonproject_video, outsider)) # Manager review. workflow.review_allowed = Workflow.REVIEW_IDS["Manager must review"] workflow.save() self.clear_cached_workflows() for r in [ROLE_MANAGER, ROLE_ADMIN, ROLE_OWNER]: with self.role(r): self.assertTrue(can_review(self.nonproject_video, user)) for r in [ROLE_CONTRIBUTOR]: with self.role(r): self.assertFalse(can_review(self.nonproject_video, user)) for r in [ROLE_MANAGER, ROLE_ADMIN]: with self.role(r, self.test_project): self.assertFalse(can_review(self.nonproject_video, user)) self.assertTrue(can_review(self.project_video, user)) self.assertFalse(can_review(self.nonproject_video, outsider)) # Admin review. workflow.review_allowed = Workflow.REVIEW_IDS["Admin must review"] workflow.save() self.clear_cached_workflows() for r in [ROLE_ADMIN, ROLE_OWNER]: with self.role(r): self.assertTrue(can_review(self.nonproject_video, user)) for r in [ROLE_MANAGER, ROLE_CONTRIBUTOR]: with self.role(r): self.assertFalse(can_review(self.nonproject_video, user)) for r in [ROLE_ADMIN]: with self.role(r, self.test_project): self.assertFalse(can_review(self.nonproject_video, user)) self.assertTrue(can_review(self.project_video, user)) self.assertFalse(can_review(self.nonproject_video, outsider)) # Workflows disabled entirely. self.team.workflow_enabled = False self.team.save() self.clear_cached_workflows() for r in [ROLE_CONTRIBUTOR, ROLE_MANAGER, ROLE_ADMIN, ROLE_OWNER]: with self.role(r): self.assertFalse(can_review(self.nonproject_video, user)) self.assertFalse(can_review(self.nonproject_video, outsider))