def _verify_team_policies(self, team_video, language_code, from_language_code): # if this is being saved as part of a task, than permissions mean # something else. For example a team might require admins to transcribe # but if it allows managers to review, then saves done as part of a review # task can be done by a manager (nice huh?) possible_task_languages = [language_code, ''] try: # If a task exist, we should let permissions be checked by _verify_no_blocking_review... # so don't bother with assignment team_video.task_set.incomplete_review_or_approve().filter(language__in=possible_task_languages).exists() return except Task.DoesNotExist: pass is_transcription = (not from_language_code) if is_transcription: allowed = can_create_and_edit_subtitles(self.user, team_video, language_code) if not allowed: raise forms.ValidationError(_( u"Sorry, we can't upload your subtitles because this " u"language is moderated and you don't have permission to " u"transcribe subtitles.")) else: allowed = can_create_and_edit_translations(self.user, team_video, language_code) if not allowed: raise forms.ValidationError(_( u"Sorry, we can't upload your subtitles because this " u"language is moderated and you don't have permission to " u"translate subtitles."))
def test_save_role(self): owner = self.owner member_account = UserFactory(username='******', password='******') member = TeamMemberFactory(team=self.team, user=member_account, role=TeamMember.ROLE_CONTRIBUTOR) tv = self.project_video video_url = reverse("videos:video", args=(tv.video.video_id, )) owner.user.set_password("hey") owner.user.save() self.team.is_visible = False self.team.save() resp = self.client.get(video_url, follow=True) self.assertNotEqual(resp.status_code, 200) self.team.video_policy = Team.VP_MEMBER self.task_assign_policy = 10 self.team.save() self.assertTrue(can_add_video(self.team, member.user)) self.assertTrue(can_add_video_somewhere(self.team, member.user)) self.assertTrue(can_view_tasks_tab(self.team, member.user)) self.assertTrue(can_create_and_edit_subtitles(member.user, tv)) self.assertTrue(can_create_and_edit_translations(member.user, tv)) self.assertFalse(can_view_settings_tab(self.team, member.user)) self.save_role(member, owner, ROLE_ADMIN) self.assertTrue(can_add_video_somewhere(self.team, member.user)) self.assertTrue(can_view_tasks_tab(self.team, member.user)) self.assertTrue(can_create_and_edit_subtitles(member.user, tv)) self.assertTrue(can_create_and_edit_translations(member.user, tv)) self.assertTrue(can_view_settings_tab(self.team, member.user)) self.save_role(member, owner, ROLE_CONTRIBUTOR) self.assertFalse(can_view_settings_tab(self.team, member.user)) self.assertTrue(can_add_video_somewhere(self.team, member.user)) self.assertTrue(can_view_tasks_tab(self.team, member.user)) self.assertTrue(can_create_and_edit_subtitles(member.user, tv)) self.assertTrue(can_create_and_edit_translations(member.user, tv)) self.client.login(username=member.user.username, password="******") resp = self.client.get(video_url, follow=True) self.assertEqual(resp.status_code, 200)
def clean(self): cleaned_data = super(CreateSubtitlesFormBase, self).clean() team_video = self.get_video().get_team_video() language_code = cleaned_data.get('subtitle_language_code') if (team_video is not None and not can_create_and_edit_subtitles( self.user, team_video, language_code)): raise forms.ValidationError("You don't have permissions to " "edit that video") return cleaned_data
def _check_team_video_locking(self, user, video_id, language_code, is_translation, mode, is_edit): """Check whether the a team prevents the user from editing the subs. Returns a dict appropriate for sending back if the user should be prevented from editing them, or None if the user can safely edit. """ video = models.Video.objects.get(video_id=video_id) team_video = video.get_team_video() if not team_video: # If there's no team video to worry about, just bail early. return None if team_video.team.is_visible: message = _( u"These subtitles are moderated. See the %s team page for information on how to contribute." % str(team_video.team)) else: message = _(u"Sorry, these subtitles are privately moderated.") # Check that there are no open tasks for this action. tasks = team_video.task_set.incomplete().filter( language__in=[language_code, '']) if tasks: task = tasks[0] # can_assign verify if the user has permission to either # 1. assign the task to himself # 2. do the task himself (the task is assigned to him) if not user.is_authenticated() or ( task.assignee and task.assignee != user) or ( not task.assignee and not can_assign_task(task, user)): return { "can_edit": False, "locked_by": str(task.assignee or task.team), "message": message } # Check that the team's policies don't prevent the action. if mode not in ['review', 'approve']: if is_translation: can_edit = can_create_and_edit_translations( user, team_video, language_code) else: can_edit = can_create_and_edit_subtitles( user, team_video, language_code) if not can_edit: return { "can_edit": False, "locked_by": str(team_video.team), "message": message }
def get_timing_mode(self, language, user): """ Decides if allows forking. Criteria: - hard coded ted teams can't fork, ever - Non team videos, can fork, always - For team videos, the user must have permission to subtitle (not only translate) """ team_video = language.video.get_team_video() _TED_TEAMS = ['ted', 'ted-transcribe'] if team_video and team_video.team.slug.lower() in _TED_TEAMS: return 'off' elif team_video and not can_create_and_edit_subtitles(user, team_video, language): return 'off' else: return 'on'
def can_create_subtitles_for(user, video): """Return True if the user can create original subtitles for this video. Safe to use with anonymous users as well as non-team videos. Usage: {% if request.user|can_create_subtitles_for:video %} ... {% endif %} """ team_video = video.get_team_video() if not team_video: return True else: return can_create_and_edit_subtitles(user, team_video)
def can_user_edit_video(self, request, video_id): """Return a dictionary of information about what the user can do with this video. The response will contain can_subtitle and can_translate attributes. """ video = models.Video.objects.get(video_id=video_id) team_video = video.get_team_video() if not team_video: can_subtitle = True can_translate = True else: can_subtitle = can_create_and_edit_subtitles(request.user, team_video) can_translate = can_create_and_edit_translations(request.user, team_video) return { 'response': 'ok', 'can_subtitle': can_subtitle, 'can_translate': can_translate, }
def test_can_create_and_edit_subtitles(self): team, user, outsider = self.team, self.user, self.outsider # Anyone team.subtitle_policy = Team.SUBTITLE_IDS['Anyone'] team.save() for r in [ROLE_CONTRIBUTOR, ROLE_MANAGER, ROLE_ADMIN, ROLE_OWNER]: with self.role(r): self.assertTrue( can_create_and_edit_subtitles(user, self.nonproject_video)) self.assertTrue( can_create_and_edit_subtitles(outsider, self.nonproject_video)) # Contributors only. team.subtitle_policy = Team.SUBTITLE_IDS['Any team member'] team.save() for r in [ROLE_CONTRIBUTOR, ROLE_MANAGER, ROLE_ADMIN, ROLE_OWNER]: with self.role(r): self.assertTrue( can_create_and_edit_subtitles(user, self.nonproject_video)) self.assertFalse( can_create_and_edit_subtitles(outsider, self.nonproject_video)) # Managers only. team.subtitle_policy = Team.SUBTITLE_IDS['Only managers and admins'] team.save() for r in [ROLE_MANAGER, ROLE_ADMIN, ROLE_OWNER]: with self.role(r): self.assertTrue( can_create_and_edit_subtitles(user, self.nonproject_video)) for r in [ROLE_MANAGER, ROLE_ADMIN]: with self.role(r, self.test_project): self.assertFalse( can_create_and_edit_subtitles(user, self.nonproject_video)) self.assertTrue( can_create_and_edit_subtitles(user, self.project_video)) for r in [ROLE_CONTRIBUTOR]: with self.role(r): self.assertFalse( can_create_and_edit_subtitles(user, self.nonproject_video)) self.assertFalse( can_create_and_edit_subtitles(outsider, self.nonproject_video)) # Admins only. team.subtitle_policy = Team.SUBTITLE_IDS['Only admins'] team.save() for r in [ROLE_ADMIN, ROLE_OWNER]: with self.role(r): self.assertTrue( can_create_and_edit_subtitles(user, self.nonproject_video)) for r in [ROLE_ADMIN]: with self.role(r, self.test_project): self.assertFalse( can_create_and_edit_subtitles(user, self.nonproject_video)) self.assertTrue( can_create_and_edit_subtitles(user, self.project_video)) for r in [ROLE_CONTRIBUTOR, ROLE_MANAGER]: with self.role(r): self.assertFalse( can_create_and_edit_subtitles(user, self.nonproject_video)) self.assertFalse( can_create_and_edit_subtitles(outsider, self.nonproject_video))
def clean(self): video = self.cleaned_data['video'] language = self.cleaned_data['language'] video_language = self.cleaned_data['video_language'] subtitle_language = video.subtitle_language(language) # first verify if this language for this video already exists. # if exists, verify if it's not writelocked if subtitle_language: if subtitle_language.is_writelocked and subtitle_language.writelock_owner != self.user: raise forms.ValidationError( _(u"Sorry, we can't upload your subtitles because work on this language is already in progress." )) # we can't let the user upload a subtitle to a language that already # have dependents. that will fork the dependents and make everything break. # see sifter #1075 if video.subtitlelanguage_set.filter( standard_language=subtitle_language).exists(): for language in video.subtitlelanguage_set.filter( standard_language=subtitle_language): # if it exists, let's verify if the version is not empty if language.latest_subtitles(public_only=False): raise forms.ValidationError( _(u"Sorry, we cannot upload subtitles for this language because this would ruin translations made from it" )) team_video = video.get_team_video() if team_video: blocking_tasks = team_video.task_set.incomplete_subtitle_or_translate( ).filter(language__in=[language, '']) if blocking_tasks.exists(): task = blocking_tasks.get() # only block if the user can't assign the task # aka he can't do himself or he can't actually # assign it to himself. # also block if the task is assigned to another user if (task.assignee and task.assignee != self.user) or ( not task.assignee and not can_assign_task(task, self.user)): raise forms.ValidationError( _(u"Sorry, we can't upload your subtitles because work on this language is already in progress." )) # Now we know that there are no transcribe/translate tasks that # should block this upload. # # However, if there are any review/approve tasks open they should # block it, even if the user is the assignee. # # TODO: Remove this restriction? blocking_tasks = team_video.task_set.incomplete_review_or_approve( ).filter(language=language) if blocking_tasks.exists(): raise forms.ValidationError( _(u"Sorry, we can't upload your subtitles because a draft for this language is already in moderation." )) # There are no tasks for this video that should block the upload. # The last thing to check is that the team's transcription policy doesn't block this. if video_language and (not subtitle_language or subtitle_language.is_original): if not can_create_and_edit_subtitles(self.user, team_video, language): raise forms.ValidationError( _(u"Sorry, we can't upload your subtitles because this language is moderated and you don't have sufficient permission." )) else: if not can_create_and_edit_translations( self.user, team_video, language): raise forms.ValidationError( _(u"Sorry, we can't upload your subtitles because this language is moderated and you don't have sufficient permission." )) return self.cleaned_data