def _user_can_bypass_moderation(team_video, version, committer): """Determine whether the given committer can bypass moderation for this video. A user can bypass moderation iff: 1) They are a moderator. 2) This version is a post-publish edit. 3) The subtitles are complete. If no committer is specified, treat the current user as a super user. Note that version.subtitle_language.subtitles_complete must be correctly set *before* this for this to work properly. TODO: Can we eliminate that property? Are moderators going to be submitting incomplete subtitles as post-publish edits? Why would that happen? """ if not committer: return True from teams.permissions import can_publish_edits_immediately subtitle_language = version.subtitle_language is_post_publish_edit = (version.sibling_set.public() .exclude(id=version.id) .exists()) user_can_bypass = can_publish_edits_immediately(team_video, committer, subtitle_language.language_code) return is_post_publish_edit and user_can_bypass
def _moderate_language(self, language, user): """Return the right visibility 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 :( """ team_video = language.video.get_team_video() if not team_video: return 'public', False team = team_video.team workflow = team.get_workflow() # 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=language.language_code) | 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 = language.language_code task.save() return ('public', False) if not team.workflow_enabled else ('private', False) if not workflow.requires_tasks: return 'public', False elif language.old_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, language.language_code): # 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 'public', False else: # Otherwise it's an edit that needs to be reviewed/approved. return 'private', True else: # Otherwise we're dealing with a new set of subtitles for this # language. return 'private', True
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 _get_user_message_for_save(self, user, language, is_complete): """Return the message that should be sent to the user regarding this save. This may be a message saying that the save was successful, or an error message. The message displayed to the user has a complex requirement / outcomes 1) Subs will go live in a moment. Works for unmoderated subs and for D and H D. Transcript, post-publish edit by moderator with the power to approve. Will go live immediately. H. Translation, post-publish edit by moderator with the power to approve. Will go live immediately. 2) Subs must be completed before being submitted to moderators. Works for A and E A. Transcript, incomplete (checkbox not ticked). Must be completed before being submitted to moderators. E. Translation, incomplete (some lines missing). Must be completed before being submitted to moderators. 3) Subs will be submitted for review/approval. Works for B, C, F, and G B. Transcript, complete (checkbox ticked). Will be submitted to moderators promptly for approval or rejection. C. Transcript, post-publish edit by contributor. Will be submitted to moderators promptly for approval or rejection. F. Translation, complete (all the lines filled). Will be submitted to moderators promptly for approval or rejection. G. Translation, post-publish edit by contributor. Will be submitted to moderators promptly for approval or rejection. TODO: Localize this? """ message_will_be_live_soon = "Your changes have been saved. It may take a moment for your subtitles to appear." message_will_be_submited = ("This video is moderated by %s." "Your changes will be reviewed by the " "team's moderators.") message_incomplete = ("These subtitles are incomplete. " "They will not be submitted for publishing " "until they've been completed.") under_moderation = language.video.is_moderated _user_can_publish = True team_video = language.video.get_team_video() if under_moderation and team_video: # videos are only supposed to have one team video _user_can_publish = can_publish_edits_immediately( team_video, user, language.language_code) # this is case 1 if under_moderation and not _user_can_publish: if is_complete: # case 3 return message_will_be_submited % team_video.team.name else: # case 2 return message_incomplete else: return message_will_be_live_soon
def save_subtitles(self, parser, video=None, language=None, update_video=True, is_complete=True): video = video or self.cleaned_data['video'] if not video.has_original_language(): self._save_original_language(video, self.cleaned_data['video_language']) if language: self._sl_created = False language = language else: language, self._sl_created = self._find_appropriate_language( video, self.cleaned_data['language']) language = save_subtitle(video, language, parser, self.user, update_video) # If there are any outstanding tasks for this language, associate the # new version with them. team_video = video.get_team_video() if team_video: new_version = language.latest_version(public_only=False) # TODO: Refactor all of this out into some kind of generic "add subtitles" pipeline. # Determine if we need to moderate these subtitles and create a # review/approve task for them. workflow = team_video.get_workflow() # user can bypass moderation if: # 1) he is a moderator and # 2) it's a post-publish edit # 3) subtitle is complete can_bypass_moderation = (is_complete and not self._sl_created and can_publish_edits_immediately( team_video, self.user, language.language)) if can_bypass_moderation: new_version.moderate = APPROVED elif workflow.review_allowed or workflow.approve_allowed: new_version.moderation_status = WAITING_MODERATION else: new_version.moderation_status = UNMODERATED new_version.save() outstanding_tasks = team_video.task_set.incomplete().filter( language__in=[language.language, '']) if outstanding_tasks.exists(): if new_version.moderation_status != WAITING_MODERATION: outstanding_tasks.update(subtitle_version=new_version, language=language.language) elif not can_bypass_moderation: # we just need to create review/approve/subtitle if the language # is a new one or, if it's a post-publish edit, if the user can't # approve subtitles by himself. task_type = None if new_version.is_synced() and is_complete: if workflow.review_allowed: task_type = Task.TYPE_IDS['Review'] elif workflow.approve_allowed: task_type = Task.TYPE_IDS['Approve'] else: task_type = Task.TYPE_IDS['Subtitle'] if task_type: task = Task(team=team_video.team, team_video=team_video, language=language.language, type=task_type, subtitle_version=new_version) if not self._sl_created: task.assignee = task._find_previous_assignee( Task.TYPE_NAMES[task_type]) else: if task_type == Task.TYPE_IDS['Subtitle']: task.assignee = self.user task.save() return language