Пример #1
0
def update_component(request, project, component):
    obj = get_component(request, project, component)

    if not request.user.has_perm('vcs.update', obj):
        raise PermissionDenied()

    return perform_update(request, obj)
Пример #2
0
def push_component(request, project, component):
    obj = get_component(request, project, component)

    if not request.user.has_perm('vcs.push', obj):
        raise PermissionDenied()

    return perform_push(request, obj)
Пример #3
0
def move_component(request, project, component):
    obj = get_component(request, project, component)
    return perform_rename(
        ComponentMoveForm, request, obj, 'project.edit',
        component=obj, target=obj.project.slug,
        action=Change.ACTION_MOVE_COMPONENT
    )
Пример #4
0
def component_progress_terminate(request, project, component):
    obj = get_component(request, project, component)

    if obj.in_progress and request.user.has_perm('component.edit', obj):
        obj.background_task.revoke(terminate=True)

    return redirect(obj)
Пример #5
0
def agreement_confirm(request, project, component):
    component = get_component(request, project, component)

    has_agreed = ContributorAgreement.objects.has_agreed(
        request.user, component
    )

    if request.method == 'POST':
        form = ContributorAgreementForm(request.POST)
        if form.is_valid() and not has_agreed:
            ContributorAgreement.objects.create(
                user=request.user,
                component=component
            )
            return redirect_next(
                request.GET.get('next'),
                component.get_absolute_url(),
            )
    else:
        form = ContributorAgreementForm(
            initial={
                'next': request.GET.get('next'),
                'confirm': has_agreed,
            }
        )

    return render(
        request,
        'contributor-agreement.html',
        {
            'form': form,
            'object': component,
            'has_agreed': has_agreed,
        }
    )
Пример #6
0
def change_component(request, project, component):
    obj = get_component(request, project, component)

    if not request.user.has_perm('component.edit', obj):
        raise Http404()

    if request.method == 'POST':
        form = ComponentSettingsForm(request, request.POST, instance=obj)
        if form.is_valid():
            form.save()
            messages.success(request, _('Settings saved'))
            return redirect(
                'settings', project=obj.project.slug, component=obj.slug
            )
        else:
            messages.error(
                request,
                _('Invalid settings, please check the form for errors!')
            )
    else:
        form = ComponentSettingsForm(request, instance=obj)

    return render(
        request,
        'component-settings.html',
        {
            'project': obj.project,
            'object': obj,
            'form': form,
        }
    )
Пример #7
0
def cleanup_component(request, project, component):
    obj = get_component(request, project, component)

    if not request.user.has_perm('vcs.reset', obj):
        raise PermissionDenied()

    return perform_cleanup(request, obj)
Пример #8
0
def matrix(request, project, component):
    """Matrix view of all strings"""
    obj = get_component(request, project, component)

    show = False
    languages = None
    language_codes = None

    if 'lang' in request.GET:
        form = MatrixLanguageForm(obj, request.GET)
        show = form.is_valid()
    else:
        form = MatrixLanguageForm(obj)

    if show:
        languages = Language.objects.filter(
            code__in=form.cleaned_data['lang']
        )
        language_codes = ','.join(languages.values_list('code', flat=True))

    return render(
        request,
        'matrix.html',
        {
            'object': obj,
            'project': obj.project,
            'languages': languages,
            'language_codes': language_codes,
            'languages_form': form,
        }
    )
Пример #9
0
def mute_component(request, project, component):
    obj = get_component(request, project, component)
    mute_real(request.user, scope=SCOPE_COMPONENT, component=obj, project=None)
    return redirect(
        '{}?notify_component={}#notifications'.format(
            reverse('profile'), obj.pk
        )
    )
Пример #10
0
def component_progress_js(request, project, component):
    obj = get_component(request, project, component)
    progress, log = obj.get_progress()
    return JsonResponse({
        'in_progress': obj.in_progress(),
        'progress': progress,
        'log': '\n'.join(log)
    })
Пример #11
0
def get_source(request, project, component):
    """
    Returns first translation in component
    (this assumes all have same source strings).
    """
    obj = get_component(request, project, component)
    try:
        return obj, obj.translation_set.all()[0]
    except (Translation.DoesNotExist, IndexError):
        raise Http404('No translation exists in this component.')
Пример #12
0
def new_language(request, project, component):
    obj = get_component(request, project, component)

    form_class = get_new_language_form(request, obj)
    can_add = obj.can_add_new_language(request)

    if request.method == 'POST':
        form = form_class(obj, request.POST)

        if form.is_valid():
            langs = form.cleaned_data['lang']
            kwargs = {
                'user': request.user,
                'author': request.user,
                'component': obj,
                'details': {},
            }
            for language in Language.objects.filter(code__in=langs):
                kwargs['details']['language'] = language.code
                if can_add:
                    obj.add_new_language(language, request)
                    Change.objects.create(
                        action=Change.ACTION_ADDED_LANGUAGE,
                        **kwargs
                    )
                elif obj.new_lang == 'contact':
                    Change.objects.create(
                        action=Change.ACTION_REQUESTED_LANGUAGE,
                        **kwargs
                    )
                    messages.success(
                        request,
                        _(
                            "A request for a new translation has been "
                            "sent to the project's maintainers."
                        )
                    )
            return redirect(obj)
        messages.error(
            request,
            _('Please fix errors in the form.')
        )
    else:
        form = form_class(obj)

    return render(
        request,
        'new-language.html',
        {
            'object': obj,
            'project': obj.project,
            'form': form,
            'can_add': can_add,
        }
    )
Пример #13
0
def unlock_component(request, project, component):
    obj = get_component(request, project, component)

    if not request.user.has_perm('component.lock', obj):
        raise PermissionDenied()

    obj.do_lock(request.user, False)

    messages.success(
        request,
        _('Component is now open for translation updates.')
    )

    return redirect_param(obj, '#repository')
Пример #14
0
def new_language(request, project, component):
    obj = get_component(request, project, component)

    form_class = get_new_language_form(request, obj)
    can_add = obj.can_add_new_language(request)

    if request.method == 'POST':
        form = form_class(obj, request.POST)

        if form.is_valid():
            langs = form.cleaned_data['lang']
            kwargs = {
                'user': request.user,
                'author': request.user,
                'component': obj,
                'details': {},
            }
            for language in Language.objects.filter(code__in=langs):
                kwargs['details']['language'] = language.code
                if can_add:
                    translation = obj.add_new_language(language, request)
                    if translation:
                        kwargs['translation'] = translation
                        if len(langs) == 1:
                            obj = translation
                        Change.objects.create(
                            action=Change.ACTION_ADDED_LANGUAGE, **kwargs
                        )
                elif obj.new_lang == 'contact':
                    Change.objects.create(
                        action=Change.ACTION_REQUESTED_LANGUAGE, **kwargs
                    )
                    messages.success(
                        request,
                        _(
                            "A request for a new translation has been "
                            "sent to the project's maintainers."
                        ),
                    )
            return redirect(obj)
        messages.error(request, _('Please fix errors in the form.'))
    else:
        form = form_class(obj)

    return render(
        request,
        'new-language.html',
        {'object': obj, 'project': obj.project, 'form': form, 'can_add': can_add},
    )
Пример #15
0
def render_widget(request, project, widget='287x66', color=None, lang=None,
                  component=None, extension='png'):
    # We intentionally skip ACL here to allow widget sharing
    if component is None:
        obj = get_project(request, project, skip_acl=True)
    else:
        obj = get_component(request, project, component, skip_acl=True)

    # Handle language parameter
    if lang is not None:
        if 'native' not in request.GET:
            try_set_language(lang)
        lang = Language.objects.try_get(code=lang)
    else:
        try_set_language('en')

    # Get widget class
    try:
        widget_class = WIDGETS[widget]
    except KeyError:
        raise Http404()

    # Construct object
    widget_obj = widget_class(obj, color, lang)

    # Redirect widget
    if hasattr(widget_obj, 'redirect'):
        return redirect(widget_obj.redirect(), permanent=True)

    # Invalid extension
    if extension != widget_obj.extension or color != widget_obj.color:
        kwargs = {
            'project': project,
            'widget': widget,
            'color': widget_obj.color,
            'extension': widget_obj.extension,
        }
        if lang:
            kwargs['lang'] = lang.code
            return redirect('widget-image', permanent=True, **kwargs)
        return redirect('widget-image', permanent=True, **kwargs)

    # Render widget
    widget_obj.render()

    return HttpResponse(
        content_type=widget_obj.content_type,
        content=widget_obj.get_content()
    )
Пример #16
0
def new_language(request, project, component):
    obj = get_component(request, project, component)

    form_class = get_new_language_form(request, obj)
    can_add = obj.can_add_new_language(request.user)

    if request.method == "POST":
        form = form_class(obj, request.POST)

        if form.is_valid():
            langs = form.cleaned_data["lang"]
            kwargs = {
                "user": request.user,
                "author": request.user,
                "component": obj,
                "details": {},
            }
            for language in Language.objects.filter(code__in=langs):
                kwargs["details"]["language"] = language.code
                if can_add:
                    translation = obj.add_new_language(language, request)
                    if translation:
                        kwargs["translation"] = translation
                        if len(langs) == 1:
                            obj = translation
                        Change.objects.create(
                            action=Change.ACTION_ADDED_LANGUAGE, **kwargs
                        )
                elif obj.new_lang == "contact":
                    Change.objects.create(
                        action=Change.ACTION_REQUESTED_LANGUAGE, **kwargs
                    )
                    messages.success(
                        request,
                        _(
                            "A request for a new translation has been "
                            "sent to the project's maintainers."
                        ),
                    )
            return redirect(obj)
        messages.error(request, _("Please fix errors in the form."))
    else:
        form = form_class(obj)

    return render(
        request,
        "new-language.html",
        {"object": obj, "project": obj.project, "form": form, "can_add": can_add},
    )
Пример #17
0
def dismiss_alert(request, project, component):
    obj = get_component(request, project, component)

    if not request.user.has_perm("component.edit", obj):
        raise Http404()

    try:
        alert = obj.alert_set.get(name=request.POST["dismiss"])
        if alert.obj.dismissable:
            alert.dismissed = True
            alert.save(update_fields=["dismissed"])
    except ObjectDoesNotExist:
        pass

    return redirect_param(obj, "#alerts")
Пример #18
0
def component_progress(request, project, component):
    obj = get_component(request, project, component)
    return_url = 'component' if 'info' in request.get else 'guide'
    if not obj.in_progress():
        return redirect(return_url, **obj.get_reverse_url_kwargs())

    progress, log = obj.get_progress()

    return render(
        request, 'component-progress.html', {
            'object': obj,
            'progress': progress,
            'log': '\n'.join(log),
            'return_url': return_url,
        })
Пример #19
0
def remove_component(request, project, component):
    obj = get_component(request, project, component)

    if not request.user.has_perm("component.edit", obj):
        raise PermissionDenied()

    form = ComponentDeleteForm(obj, request.POST)
    if not form.is_valid():
        show_form_errors(request, form)
        return redirect_param(obj, "#delete")

    component_removal.delay(obj.pk, request.user.pk)
    messages.success(request, _("Translation component was scheduled for removal."))

    return redirect(obj.project)
Пример #20
0
def render_widget(request, project, widget='287x66', color=None, lang=None,
                  component=None, extension='png'):
    # We intentionally skip ACL here to allow widget sharing
    if component is None:
        obj = get_project(request, project, skip_acl=True)
    else:
        obj = get_component(request, project, component, skip_acl=True)

    # Handle language parameter
    if lang is not None:
        lang = Language.objects.fuzzy_get(code=lang, strict=True)
        if lang is None:
            raise Http404()
        if 'native' not in request.GET:
            try_set_language(lang.code)
    else:
        try_set_language('en')

    # Get widget class
    try:
        widget_class = WIDGETS[widget]
    except KeyError:
        raise Http404()

    # Construct object
    widget_obj = widget_class(obj, color, lang)

    # Redirect widget
    if hasattr(widget_obj, 'redirect'):
        return redirect(widget_obj.redirect(), permanent=True)

    # Invalid extension
    if extension != widget_obj.extension or color != widget_obj.color:
        kwargs = {
            'project': project,
            'widget': widget,
            'color': widget_obj.color,
            'extension': widget_obj.extension,
        }
        if lang:
            kwargs['lang'] = lang.code
            return redirect('widget-image', permanent=True, **kwargs)
        return redirect('widget-image', permanent=True, **kwargs)

    # Render widget
    response = HttpResponse(content_type=widget_obj.content_type)
    widget_obj.render(response)
    return response
Пример #21
0
def git_export(request, project, component, path):
    """Git HTTP server view.

    Wrapper around git-http-backend to provide Git repositories export over HTTP.
    Performs permission checks and hands over execution to the wrapper.
    """
    # Probably browser access
    if not path:
        return redirect("component",
                        project=project,
                        component=component,
                        permanent=False)
    # Strip possible double path separators
    path = path.lstrip("/\\")

    # HTTP authentication
    auth = request.META.get("HTTP_AUTHORIZATION", b"")

    # Reject non pull access early
    if request.GET.get("service", "") not in ("", "git-upload-pack"):
        raise PermissionDenied("Only pull is supported")

    if auth and not authenticate(request, auth):
        return response_authenticate()

    # Permissions
    try:
        obj = get_component(request, project, component)
    except Http404:
        if not request.user.is_authenticated:
            return response_authenticate()
        raise
    if not request.user.has_perm("vcs.access", obj):
        if not request.user.is_authenticated:
            return response_authenticate()
        raise PermissionDenied("No VCS permissions")
    if obj.vcs not in SUPPORTED_VCS:
        raise Http404("Not a git repository")
    if obj.is_repo_link:
        kwargs = obj.linked_component.get_reverse_url_kwargs()
        kwargs["path"] = path
        return redirect(
            "{}?{}".format(reverse("git-export", kwargs=kwargs),
                           request.META["QUERY_STRING"]),
            permanent=True,
        )

    return run_git_http(request, obj, path)
Пример #22
0
def show_component(request, project, component):
    obj = get_component(request, project, component)
    user = request.user

    last_changes = Change.objects.prefetch().order().filter(component=obj)[:10]

    return render(
        request,
        'component.html',
        {
            'allow_index': True,
            'object': obj,
            'hide_alerts': True,
            'project': obj.project,
            'translations': sort_objects(
                prefetch_stats(obj.translation_set.prefetch())
            ),
            'reports_form': ReportsForm(),
            'last_changes': last_changes,
            'last_changes_url': urlencode(
                {'component': obj.slug, 'project': obj.project.slug}
            ),
            'language_count': Language.objects.filter(
                translation__component=obj
            ).distinct().count(),
            'replace_form': optional_form(ReplaceForm, user, 'unit.edit', obj),
            'bulk_state_form': optional_form(
                BulkStateForm, user, 'translation.auto', obj,
                user=user, obj=obj
            ),
            'whiteboard_form': optional_form(
                WhiteboardForm, user, 'component.edit', obj
            ),
            'delete_form': optional_form(
                DeleteForm, user, 'component.edit', obj, obj=obj
            ),
            'rename_form': optional_form(
                ComponentRenameForm, user, 'component.edit', obj,
                request=request, instance=obj
            ),
            'move_form': optional_form(
                ComponentMoveForm, user, 'component.edit', obj,
                request=request, instance=obj
            ),
            'search_form': SearchForm(request.user),
            'alerts': obj.alert_set.order_by('name'),
        }
    )
Пример #23
0
def whiteboard_component(request, project, component):
    obj = get_component(request, project, component)

    if not request.user.has_perm('component.edit', obj):
        raise PermissionDenied()

    form = WhiteboardForm(request.POST)
    if not form.is_valid():
        show_form_errors(request, form)
        return redirect_param(obj, '#whiteboard')

    WhiteboardMessage.objects.create(project=obj.project,
                                     component=obj,
                                     **form.cleaned_data)

    return redirect(obj)
Пример #24
0
def component_progress(request, project, component):
    obj = get_component(request, project, component)
    if not obj.in_progress():
        return redirect(obj)

    progress, log = obj.get_progress()

    return render(
        request,
        'component-progress.html',
        {
            'object': obj,
            'progress': progress,
            'log': '\n'.join(log),
        }
    )
Пример #25
0
def announcement_component(request, project, component):
    obj = get_component(request, project, component)

    if not request.user.has_perm("component.edit", obj):
        raise PermissionDenied()

    form = AnnouncementForm(request.POST)
    if not form.is_valid():
        show_form_errors(request, form)
        return redirect_param(obj, "#announcement")

    Announcement.objects.create(
        user=request.user, project=obj.project, component=obj, **form.cleaned_data
    )

    return redirect(obj)
Пример #26
0
def show_component(request, project, component):
    obj = get_component(request, project, component)
    user = request.user

    last_changes = Change.objects.prefetch().filter(component=obj)[:10]

    return render(
        request,
        'component.html',
        {
            'allow_index': True,
            'object': obj,
            'project': obj.project,
            'translations': sort_objects(
                prefetch_stats(obj.translation_set.all())
            ),
            'show_language': 1,
            'reports_form': ReportsForm(),
            'last_changes': last_changes,
            'last_changes_url': urlencode(
                {'component': obj.slug, 'project': obj.project.slug}
            ),
            'language_count': Language.objects.filter(
                translation__component=obj
            ).distinct().count(),
            'replace_form': optional_form(ReplaceForm, user, 'unit.edit', obj),
            'bulk_state_form': optional_form(
                BulkStateForm, user, 'translation.auto', obj,
                user=user, obj=obj
            ),
            'whiteboard_form': optional_form(
                WhiteboardForm, user, 'component.edit', obj
            ),
            'delete_form': optional_form(
                DeleteForm, user, 'component.edit', obj, obj=obj
            ),
            'rename_form': optional_form(
                ComponentRenameForm, user, 'component.edit', obj,
                request=request, instance=obj
            ),
            'move_form': optional_form(
                ComponentMoveForm, user, 'component.edit', obj,
                request=request, instance=obj
            ),
            'search_form': SearchForm(),
        }
    )
Пример #27
0
def show_component(request, project, component):
    obj = get_component(request, project, component)

    last_changes = Change.objects.prefetch().filter(component=obj)[:10]

    # Is user allowed to do automatic translation?
    if request.user.has_perm('translation.auto', obj):
        mass_state_form = MassStateForm(request.user, obj)
    else:
        mass_state_form = None

    if request.user.has_perm('unit.edit', obj):
        replace_form = ReplaceForm()
    else:
        replace_form = None

    return render(
        request, 'component.html', {
            'allow_index':
            True,
            'object':
            obj,
            'project':
            obj.project,
            'translations':
            sort_objects(prefetch_stats(obj.translation_set.all())),
            'show_language':
            1,
            'reports_form':
            ReportsForm(),
            'last_changes':
            last_changes,
            'last_changes_url':
            urlencode({
                'component': obj.slug,
                'project': obj.project.slug
            }),
            'language_count':
            Language.objects.filter(
                translation__component=obj).distinct().count(),
            'replace_form':
            replace_form,
            'mass_state_form':
            mass_state_form,
            'search_form':
            SearchForm(),
        })
Пример #28
0
def git_export(request, project, component, path):
    """Git HTTP server view.

    Wrapper around git-http-backend to provide Git repositories export over
    HTTP. Performs permission checks and hands over execution to the wrapper.
    """
    # Probably browser access
    if not path:
        return redirect(
            'component', project=project, component=component, permanent=False
        )
    # Strip possible double path separators
    path = path.lstrip('/\\')

    # HTTP authentication
    auth = request.META.get('HTTP_AUTHORIZATION', b'')

    # Reject non pull access early
    if request.GET.get('service', '') not in ('', 'git-upload-pack'):
        raise PermissionDenied('Only pull is supported')

    if auth and not authenticate(request, auth):
        return response_authenticate()

    # Permissions
    try:
        obj = get_component(request, project, component)
    except Http404:
        if not request.user.is_authenticated:
            return response_authenticate()
        raise
    if not request.user.has_perm('vcs.access', obj):
        raise PermissionDenied('No VCS permissions')
    if obj.vcs not in SUPPORTED_VCS:
        raise Http404('Not a git repository')
    if obj.is_repo_link:
        kwargs = obj.linked_component.get_reverse_url_kwargs()
        kwargs['path'] = path
        return redirect(
            '{}?{}'.format(
                reverse('git-export', kwargs=kwargs), request.META['QUERY_STRING']
            ),
            permanent=True,
        )

    return run_git_http(request, obj, path)
Пример #29
0
def whiteboard_component(request, project, component):
    obj = get_component(request, project, component)

    if not request.user.has_perm('component.edit', obj):
        raise PermissionDenied()

    form = WhiteboardForm(request.POST)
    if not form.is_valid():
        show_form_errors(request, form)
        return redirect_param(obj, '#whiteboard')

    WhiteboardMessage.objects.create(
        project=obj.project,
        component=obj,
        **form.cleaned_data
    )

    return redirect(obj)
Пример #30
0
def component_progress(request, project, component):
    obj = get_component(request, project, component)
    return_url = "component" if "info" in request.GET else "guide"
    if not obj.in_progress():
        return redirect(return_url, **obj.get_reverse_url_kwargs())

    progress, log = obj.get_progress()

    return render(
        request,
        "component-progress.html",
        {
            "object": obj,
            "progress": progress,
            "log": "\n".join(log),
            "return_url": return_url,
        },
    )
Пример #31
0
def get_detail(request, project, component, checksum):
    """Return source translation detail in all languages."""
    component = get_component(request, project, component)
    try:
        units = Unit.objects.filter(
            id_hash=checksum_to_hash(checksum),
            translation__component=component
        ).order_by(*Unit.ordering)
    except ValueError:
        raise Http404('Non existing unit!')
    try:
        source = units[0].source_info
    except IndexError:
        raise Http404('Non existing unit!')

    check_flags = [
        (CHECKS[x].ignore_string, CHECKS[x].name) for x in CHECKS
    ]
    extra_flags = [(x, EXTRA_FLAGS[x]) for x in EXTRA_FLAGS]

    return render(
        request,
        'js/detail.html',
        {
            'units': units,
            'source': source,
            'project': component.project,
            'next': request.GET.get('next', ''),
            'priority_form': PriorityForm(
                initial={'priority': source.priority}
            ),
            'context_form': ContextForm(
                initial={'context': source.context}
            ),

            'check_flags_form': CheckFlagsForm(
                initial={'flags': source.check_flags}
            ),
            'screenshot_form': ScreenshotForm(),
            'extra_flags': extra_flags,
            'check_flags': check_flags,
        }
    )
Пример #32
0
def get_detail(request, project, component, checksum):
    """Return source translation detail in all languages."""
    component = get_component(request, project, component)
    try:
        units = Unit.objects.filter(
            id_hash=checksum_to_hash(checksum),
            translation__component=component
        )
    except ValueError:
        raise Http404('Non existing unit!')
    try:
        source = units[0].source_info
    except IndexError:
        raise Http404('Non existing unit!')

    check_flags = [
        (CHECKS[x].ignore_string, CHECKS[x].name) for x in CHECKS
    ]
    extra_flags = [(x, EXTRA_FLAGS[x]) for x in EXTRA_FLAGS]

    return render(
        request,
        'js/detail.html',
        {
            'units': units,
            'source': source,
            'project': component.project,
            'next': request.GET.get('next', ''),
            'priority_form': PriorityForm(
                initial={'priority': source.priority}
            ),
            'context_form': ContextForm(
                initial={'context': source.context}
            ),

            'check_flags_form': CheckFlagsForm(
                initial={'flags': source.check_flags}
            ),
            'screenshot_form': ScreenshotForm(),
            'extra_flags': extra_flags,
            'check_flags': check_flags,
        }
    )
Пример #33
0
def remove_component(request, project, component):
    obj = get_component(request, project, component)

    if not request.user.has_perm('component.edit', obj):
        raise PermissionDenied()

    form = DeleteForm(obj, request.POST)
    if not form.is_valid():
        show_form_errors(request, form)
        return redirect_param(obj, '#delete')

    obj.delete()
    messages.success(request, _('Translation component has been removed.'))
    Change.objects.create(project=obj.project,
                          action=Change.ACTION_REMOVE_COMPONENT,
                          target=obj.slug,
                          user=request.user,
                          author=request.user)

    return redirect(obj.project)
Пример #34
0
def change_component(request, project, component):
    obj = get_component(request, project, component)

    if not request.user.has_perm("component.edit", obj):
        raise Http404()

    if request.method == "POST":
        form = ComponentSettingsForm(request, request.POST, instance=obj)
        if form.is_valid():
            form.save()
            messages.success(request, _("Settings saved"))
            return redirect("settings",
                            project=obj.project.slug,
                            component=obj.slug)
        else:
            messages.error(
                request,
                _("Invalid settings, please check the form for errors!"))
            # Get a fresh copy of object, otherwise it will use unsaved changes
            # from the failed form
            obj = Component.objects.get(pk=obj.pk)
    else:
        form = ComponentSettingsForm(request, instance=obj)

    if obj.repo_needs_merge():
        messages.warning(
            request,
            _("The repository is outdated, you might not get "
              "expected results until you update it."),
        )

    return render(
        request,
        "component-settings.html",
        {
            "project": obj.project,
            "object": obj,
            "form": form
        },
    )
Пример #35
0
def new_language(request, project, component):
    obj = get_component(request, project, component)

    form_class = get_new_language_form(request, obj)

    if request.method == 'POST':
        form = form_class(obj, request.POST)

        if form.is_valid():
            langs = form.cleaned_data['lang']
            for language in Language.objects.filter(code__in=langs):
                if obj.new_lang == 'contact':
                    notify_new_language(obj, language, request.user)
                    messages.success(
                        request,
                        _(
                            "A request for a new translation has been "
                            "sent to the project's maintainers."
                        )
                    )
                elif obj.new_lang == 'add':
                    obj.add_new_language(language, request)
            return redirect(obj)
        else:
            messages.error(
                request,
                _('Please fix errors in the form.')
            )
    else:
        form = form_class(obj)

    return render(
        request,
        'new-language.html',
        {
            'object': obj,
            'project': obj.project,
            'form': form,
        }
    )
Пример #36
0
def git_export(request, project, component, path):
    """Git HTTP server view.

    Wrapper around git-http-backend to provide Git repositories export over
    HTTP. Performs permission checks and hands over execution to the wrapper.
    """
    # Probably browser access
    if not path:
        return redirect(
            'component',
            project=project,
            component=component,
            permanent=False
        )
    # Strip possible double path separators
    path = path.lstrip('/\\')

    # HTTP authentication
    auth = request.META.get('HTTP_AUTHORIZATION', b'')

    # Reject non pull access early
    if request.GET.get('service', '') not in ('', 'git-upload-pack'):
        raise PermissionDenied('Only pull is supported')

    if auth and not authenticate(request, auth):
        return response_authenticate()

    # Permissions
    try:
        obj = get_component(request, project, component)
    except Http404:
        if not request.user.is_authenticated:
            return response_authenticate()
        raise
    if not request.user.has_perm('vcs.access', obj):
        raise PermissionDenied('No VCS permissions')
    if obj.vcs not in SUPPORTED_VCS:
        raise Http404('Not a git repository')

    return run_git_http(request, obj, path)
Пример #37
0
def new_language(request, project, component):
    obj = get_component(request, project, component)

    form_class = get_new_language_form(request, obj)

    if request.method == 'POST':
        form = form_class(obj, request.POST)

        if form.is_valid():
            langs = form.cleaned_data['lang']
            for language in Language.objects.filter(code__in=langs):
                if obj.new_lang == 'contact':
                    notify_new_language(obj, language, request.user)
                    messages.success(
                        request,
                        _(
                            "A request for a new translation has been "
                            "sent to the project's maintainers."
                        )
                    )
                elif obj.new_lang == 'add':
                    obj.add_new_language(language, request)
            return redirect(obj)
        else:
            messages.error(
                request,
                _('Please fix errors in the form.')
            )
    else:
        form = form_class(obj)

    return render(
        request,
        'new-language.html',
        {
            'object': obj,
            'project': obj.project,
            'form': form,
        }
    )
Пример #38
0
def matrix_load(request, project, component):
    """Backend for matrix view of all strings"""
    obj = get_component(request, project, component)

    try:
        offset = int(request.GET.get('offset', ''))
    except ValueError:
        return HttpResponseServerError('Missing offset')
    language_codes = request.GET.get('lang')
    if not language_codes or offset is None:
        return HttpResponseServerError('Missing lang')

    # Can not use filter to keep ordering
    translations = [
        get_object_or_404(obj.translation_set, language__code=lang)
        for lang in language_codes.split(',')
    ]

    data = []

    for unit in translations[0].unit_set.all()[offset:offset + 20]:
        units = []
        for translation in translations:
            try:
                units.append(translation.unit_set.get(id_hash=unit.id_hash))
            except Unit.DoesNotExist:
                units.append(None)

        data.append((unit, units))

    return render(
        request,
        'matrix-table.html',
        {
            'object': obj,
            'data': data,
            'last': translations[0].unit_set.count() <= offset + 20
        }
    )
Пример #39
0
def matrix_load(request, project, component):
    """Backend for matrix view of all strings."""
    obj = get_component(request, project, component)

    try:
        offset = int(request.GET.get("offset", ""))
    except ValueError:
        return HttpResponseServerError("Missing offset")
    language_codes = request.GET.get("lang")
    if not language_codes or offset is None:
        return HttpResponseServerError("Missing lang")

    # Can not use filter to keep ordering
    translations = [
        get_object_or_404(obj.translation_set, language__code=lang)
        for lang in language_codes.split(",")
    ]

    data = []

    for unit in translations[0].unit_set.all()[offset:offset + 20]:
        units = []
        for translation in translations:
            try:
                units.append(translation.unit_set.get(id_hash=unit.id_hash))
            except Unit.DoesNotExist:
                units.append(None)

        data.append((unit, units))

    return render(
        request,
        "matrix-table.html",
        {
            "object": obj,
            "data": data,
            "last": translations[0].unit_set.count() <= offset + 20,
        },
    )
Пример #40
0
def remove_component(request, project, component):
    obj = get_component(request, project, component)

    if not request.user.has_perm('component.edit', obj):
        raise PermissionDenied()

    form = DeleteForm(obj, request.POST)
    if not form.is_valid():
        show_form_errors(request, form)
        return redirect_param(obj, '#delete')

    obj.delete()
    messages.success(request, _('Translation component has been removed.'))
    Change.objects.create(
        project=obj.project,
        action=Change.ACTION_REMOVE_COMPONENT,
        target=obj.slug,
        user=request.user,
        author=request.user
    )

    return redirect(obj.project)
Пример #41
0
def show_check_component(request, name, project, component):
    """Show checks failing in a component."""
    component = get_component(request, project, component)
    try:
        check = CHECKS[name]
    except KeyError:
        raise Http404("No check matches the given query.")

    kwargs = {}

    if request.GET.get("lang"):
        kwargs["language__code"] = request.GET["lang"]

    translations = (
        Translation.objects.filter(
            component=component, unit__check__check=name, **kwargs
        )
        .annotate(
            check_count=Count("unit__check"),
            dismissed_check_count=conditional_sum(1, unit__check__dismissed=True),
            active_check_count=conditional_sum(1, unit__check__dismissed=False),
            translated_check_count=conditional_sum(
                1, unit__check__dismissed=False, unit__state__gte=STATE_TRANSLATED
            ),
        )
        .order_by("language__code")
        .select_related("language")
    )

    return render(
        request,
        "check_component.html",
        {
            "translations": translations,
            "title": "{0}/{1}".format(force_str(component), check.name),
            "check": check,
            "component": component,
        },
    )
Пример #42
0
def parse_url(request, project, component=None, lang=None):
    context = {}
    if component is None:
        obj = get_project(request, project)
        unit_set = Unit.objects.filter(translation__component__project=obj)
        context["project"] = obj
    elif lang is None:
        obj = get_component(request, project, component)
        unit_set = Unit.objects.filter(translation__component=obj)
        context["component"] = obj
        context["project"] = obj.project
    else:
        obj = get_translation(request, project, component, lang)
        unit_set = obj.unit_set.all()
        context["translation"] = obj
        context["component"] = obj.component
        context["project"] = obj.component.project

    if not request.user.has_perm("unit.edit", obj):
        raise PermissionDenied()

    return obj, unit_set, context
Пример #43
0
def export_stats(request, project, component):
    """Export stats in JSON format."""
    subprj = get_component(request, project, component)
    translations = subprj.translation_set.order_by("language_code")

    return export_response(
        request,
        f"stats-{subprj.project.slug}-{subprj.slug}.csv",
        (
            "name",
            "code",
            "total",
            "translated",
            "translated_percent",
            "translated_words_percent",
            "total_words",
            "translated_words",
            "total_chars",
            "translated_chars",
            "translated_chars_percent",
            "failing",
            "failing_percent",
            "fuzzy",
            "fuzzy_percent",
            "url_translate",
            "url",
            "translate_url",
            "last_change",
            "last_author",
            "recent_changes",
            "readonly",
            "readonly_percent",
            "approved",
            "approved_percent",
            "suggestions",
            "comments",
        ),
        StatisticsSerializer(translations, many=True).data,
    )
Пример #44
0
def parse_url(request, project, component=None, lang=None):
    context = {}
    if component is None:
        obj = get_project(request, project)
        unit_set = Unit.objects.filter(translation__component__project=obj)
        context['project'] = obj
    elif lang is None:
        obj = get_component(request, project, component)
        unit_set = Unit.objects.filter(translation__component=obj)
        context['component'] = obj
        context['project'] = obj.project
    else:
        obj = get_translation(request, project, component, lang)
        unit_set = obj.unit_set
        context['translation'] = obj
        context['component'] = obj.component
        context['project'] = obj.component.project

    if not request.user.has_perm('unit.edit', obj):
        raise PermissionDenied()

    return obj, unit_set, context
Пример #45
0
def git_export(request, project, component, path):
    """Git HTTP server view.

    Wrapper around git-http-backend to provide Git repositories export over
    HTTP. Performs permission checks and hands over execution to the wrapper.
    """
    # Probably browser access
    if not path:
        return redirect(
            'component',
            project=project,
            component=component,
            permanent=False
        )
    # Strip possible double path separators
    path = path.lstrip('/\\')

    # HTTP authentication
    auth = request.META.get('HTTP_AUTHORIZATION', b'')

    # Reject non pull access early
    if request.GET.get('service', '') not in ('', 'git-upload-pack'):
        raise PermissionDenied('Only pull is supported')

    if auth and not authenticate(request, auth):
        return response_authenticate()

    # Permissions
    try:
        obj = get_component(request, project, component)
    except Http404:
        if not request.user.is_authenticated:
            return response_authenticate()
        raise
    if not request.user.has_perm('vcs.access', obj):
        raise PermissionDenied('No VCS permissions')

    return run_git_http(request, obj, path)
Пример #46
0
def git_status_component(request, project, component):
    obj = get_component(request, project, component)

    if not request.user.has_perm('meta:vcs.status', obj):
        raise PermissionDenied()

    target = obj
    if target.is_repo_link:
        target = target.linked_component

    return render(
        request,
        'js/git-status.html',
        {
            'object': obj,
            'project': obj.project,
            'changes': Change.objects.filter(
                action__in=Change.ACTIONS_REPOSITORY,
                component=target,
            )[:10],
            'statuses': [(None, obj.repository.status)],
        }
    )
Пример #47
0
def git_status_component(request, project, component):
    obj = get_component(request, project, component)

    if not request.user.has_perm('meta:vcs.status', obj):
        raise PermissionDenied()

    target = obj
    if target.is_repo_link:
        target = target.linked_component

    return render(
        request,
        'js/git-status.html',
        {
            'object': obj,
            'project': obj.project,
            'changes': Change.objects.filter(
                action__in=Change.ACTIONS_REPOSITORY,
                component=target,
            ).order_by(*Change.ordering)[:10],
            'statuses': [(None, obj.repository.status)],
        }
    )
Пример #48
0
def watch(request, project, component=None):
    user = request.user
    if component:
        redirect_obj = component_obj = get_component(request, project, component)
        obj = component_obj.project
        # Mute project level subscriptions
        mute_real(user, scope=SCOPE_PROJECT, component=None, project=obj)
        # Manually enable component level subscriptions
        for default_subscription in user.subscription_set.filter(scope=SCOPE_DEFAULT):
            subscription, created = user.subscription_set.get_or_create(
                notification=default_subscription.notification,
                scope=SCOPE_COMPONENT,
                component=component_obj,
                project=None,
                defaults={"frequency": default_subscription.frequency},
            )
            if not created and subscription.frequency != default_subscription.frequency:
                subscription.frequency = default_subscription.frequency
                subscription.save(update_fields=["frequency"])
    else:
        redirect_obj = obj = get_project(request, project)
    user.profile.watched.add(obj)
    return redirect(redirect_obj)
Пример #49
0
def git_status_component(request, project, component):
    obj = get_component(request, project, component)

    if not request.user.has_perm("meta:vcs.status", obj):
        raise PermissionDenied()

    target = obj
    if target.is_repo_link:
        target = target.linked_component

    return render(
        request,
        "js/git-status.html",
        {
            "object": obj,
            "project": obj.project,
            "changes": Change.objects.filter(
                action__in=Change.ACTIONS_REPOSITORY, component=target
            ).order()[:10],
            "statuses": [(None, obj.repository.status)],
            "component": obj,
        },
    )
Пример #50
0
def change_component(request, project, component):
    obj = get_component(request, project, component)

    if not request.user.has_perm("component.edit", obj):
        raise Http404()

    if request.method == "POST":
        form = ComponentSettingsForm(request, request.POST, instance=obj)
        if form.is_valid():
            form.save()
            messages.success(request, _("Settings saved"))
            return redirect("settings", project=obj.project.slug, component=obj.slug)
        else:
            messages.error(
                request, _("Invalid settings, please check the form for errors!")
            )
    else:
        form = ComponentSettingsForm(request, instance=obj)

    return render(
        request,
        "component-settings.html",
        {"project": obj.project, "object": obj, "form": form},
    )
Пример #51
0
def show_component(request, project, component):
    obj = get_component(request, project, component)
    user = request.user

    last_changes = Change.objects.prefetch().filter(component=obj)[:10]

    return render(
        request,
        'component.html',
        {
            'allow_index': True,
            'object': obj,
            'project': obj.project,
            'translations': sort_objects(
                prefetch_stats(obj.translation_set.all())
            ),
            'show_language': 1,
            'reports_form': ReportsForm(),
            'last_changes': last_changes,
            'last_changes_url': urlencode(
                {'component': obj.slug, 'project': obj.project.slug}
            ),
            'language_count': Language.objects.filter(
                translation__component=obj
            ).distinct().count(),
            'replace_form': optional_form(ReplaceForm, user, 'unit.edit', obj),
            'mass_state_form': optional_form(
                MassStateForm, user, 'translation.auto', obj,
                user=user, obj=obj
            ),
            'delete_form': optional_form(
                DeleteForm, user, 'component.edit', obj, obj=obj
            ),
            'search_form': SearchForm(),
        }
    )
Пример #52
0
def export_stats(request, project, component):
    """Export stats in JSON format."""
    subprj = get_component(request, project, component)

    data = [trans.get_stats() for trans in subprj.translation_set.all()]
    return export_response(
        request, 'stats-{0}-{1}.csv'.format(subprj.project.slug, subprj.slug),
        (
            'name',
            'code',
            'total',
            'translated',
            'translated_percent',
            'total_words',
            'translated_words',
            'failing',
            'failing_percent',
            'fuzzy',
            'fuzzy_percent',
            'url_translate',
            'url',
            'last_change',
            'last_author',
        ), data)
Пример #53
0
def rename_component(request, project, component):
    obj = get_component(request, project, component)
    return perform_rename(
        ComponentRenameForm, request, obj, 'component.edit',
        component=obj, target=obj.slug, action=Change.ACTION_RENAME_COMPONENT
    )
Пример #54
0
def show_check_component(request, name, project, component):
    """Show checks failing in a component."""
    subprj = get_component(request, project, component)
    try:
        check = CHECKS[name]
    except KeyError:
        raise Http404('No check matches the given query.')

    ignore = ('ignored' in request.GET)
    url_params = {}

    allchecks = acl_checks(request.user).filter(
        check=name,
        project=subprj.project,
        ignore=ignore,
    )

    if ignore:
        url_params['ignored'] = 'true'

    if check.source:
        url_params['type'] = check.url_id
        return redirect_param(
            'review_source',
            encode_optional(url_params),
            project=subprj.project.slug,
            component=subprj.slug,
        )

    if request.GET.get('language') and '/' not in request.GET['language']:
        url_params['type'] = check.url_id
        return redirect_param(
            'translate',
            encode_optional(url_params),
            project=subprj.project.slug,
            component=subprj.slug,
            lang=request.GET['language'],
        )

    units = Unit.objects.none()

    if check.target:
        langs = allchecks.values_list(
            'language', flat=True
        ).distinct()
        for lang in langs:
            checks = allchecks.filter(
                language=lang,
            ).values_list('content_hash', flat=True)
            res = Unit.objects.filter(
                translation__component=subprj,
                content_hash__in=checks,
                translation__language=lang,
            ).values(
                'translation__language__code'
            ).annotate(count=Count('id'))
            units |= res

    counts = {}
    for unit in units:
        key = unit['translation__language__code']
        if key in counts:
            counts[key] += unit['count']
        else:
            counts[key] = unit['count']

    units = [
        {
            'translation__language__code': item,
            'count': counts[item]
        } for item in counts
    ]

    return render(
        request,
        'check_component.html',
        {
            'checks': units,
            'title': '{0}/{1}'.format(force_text(subprj), check.name),
            'check': check,
            'component': subprj,
            'url_params': encode_optional(url_params),
        }
    )
Пример #55
0
 def get_object(self, request, project, component):
     return get_component(request, project, component)
Пример #56
0
 def get_object(self, request, project, component):
     return get_component(request, project, component)
Пример #57
0
def get_credits(request, project, component):
    """View for credits"""
    obj = get_component(request, project, component)

    if not request.user.has_perm('reports.view', obj):
        raise PermissionDenied()

    form = ReportsForm(request.POST)

    if not form.is_valid():
        show_form_errors(request, form)
        return redirect_param(obj, '#reports')

    data = generate_credits(
        obj,
        form.cleaned_data['start_date'],
        form.cleaned_data['end_date'],
    )

    if form.cleaned_data['style'] == 'json':
        return JsonResponse(data=data, safe=False)

    if form.cleaned_data['style'] == 'html':
        start = '<table>'
        row_start = '<tr>'
        language_format = '<th>{0}</th>'
        translator_start = '<td><ul>'
        translator_format = '<li><a href="mailto:{0}">{1}</a></li>'
        translator_end = '</ul></td>'
        row_end = '</tr>'
        mime = 'text/html'
        end = '</table>'
    else:
        start = ''
        row_start = ''
        language_format = '* {0}\n'
        translator_start = ''
        translator_format = '    * {1} <{0}>'
        translator_end = ''
        row_end = ''
        mime = 'text/plain'
        end = ''

    result = []

    result.append(start)

    for language in data:
        name, translators = language.popitem()
        result.append(row_start)
        result.append(language_format.format(name))
        result.append(
            ''.join((
                translator_start,
                '\n'.join(
                    [translator_format.format(*t) for t in translators]
                ),
                translator_end,
            ))
        )
        result.append(row_end)

    result.append(end)

    return HttpResponse(
        '\n'.join(result),
        content_type='{0}; charset=utf-8'.format(mime),
    )
Пример #58
0
def get_counts(request, project, component):
    """View for work counts"""
    obj = get_component(request, project, component)

    if not request.user.has_perm('reports.view', obj):
        raise PermissionDenied()

    form = ReportsForm(request.POST)

    if not form.is_valid():
        show_form_errors(request, form)
        return redirect_param(obj, '#reports')

    data = generate_counts(
        obj,
        form.cleaned_data['start_date'],
        form.cleaned_data['end_date'],
    )

    if form.cleaned_data['style'] == 'json':
        return JsonResponse(data=data, safe=False)

    headers = (
        'Name',
        'Email',
        'Count total',
        'Source words total',
        'Source chars total',
        'Target words total',
        'Target chars total',

        'Count new',
        'Source words new',
        'Source chars new',
        'Target words new',
        'Target chars new',

        'Count approved',
        'Source words approved',
        'Source chars approved',
        'Target words approved',
        'Target chars approved',

        'Count edited',
        'Source words edited',
        'Source chars edited',
        'Target words edited',
        'Target chars edited',
    )

    if form.cleaned_data['style'] == 'html':
        start = HTML_HEADING.format(
            ''.join(['<th>{0}</th>'.format(h) for h in headers])
        )
        row_start = '<tr>'
        cell_name = cell_count = '<td>{0}</td>\n'
        row_end = '</tr>'
        mime = 'text/html'
        end = '</table>'
    else:
        start = '{0}\n{1} {2}\n{0}'.format(
            RST_HEADING,
            ' '.join(['{0:40}'.format(h) for h in headers[:2]]),
            ' '.join(['{0:24}'.format(h) for h in headers[2:]]),
        )
        row_start = ''
        cell_name = '{0:40} '
        cell_count = '{0:24} '
        row_end = ''
        mime = 'text/plain'
        end = RST_HEADING

    result = []

    result.append(start)

    for item in data:
        if row_start:
            result.append(row_start)
        result.append(
            ''.join((
                cell_name.format(item['name']),
                cell_name.format(item['email']),

                cell_count.format(item['count']),
                cell_count.format(item['words']),
                cell_count.format(item['chars']),
                cell_count.format(item['t_words']),
                cell_count.format(item['t_chars']),

                cell_count.format(item['count_new']),
                cell_count.format(item['words_new']),
                cell_count.format(item['chars_new']),
                cell_count.format(item['t_words_new']),
                cell_count.format(item['t_chars_new']),

                cell_count.format(item['count_approve']),
                cell_count.format(item['words_approve']),
                cell_count.format(item['chars_approve']),
                cell_count.format(item['t_words_approve']),
                cell_count.format(item['t_chars_approve']),

                cell_count.format(item['count_edit']),
                cell_count.format(item['words_edit']),
                cell_count.format(item['chars_edit']),
                cell_count.format(item['t_words_edit']),
                cell_count.format(item['t_chars_edit']),
            ))
        )
        if row_end:
            result.append(row_end)

    result.append(end)

    return HttpResponse(
        '\n'.join(result),
        content_type='{0}; charset=utf-8'.format(mime),
    )
Пример #59
0
def mute_component(request, project, component):
    obj = get_component(request, project, component)
    mute_real(request.user, scope=SCOPE_COMPONENT, component=obj, project=None)
    return redirect('{}?notify_component={}#notifications'.format(
        reverse('profile'), obj.pk))
Пример #60
0
def search(request, project=None, component=None, lang=None):
    """Perform site-wide search on units."""
    is_ratelimited = not check_rate_limit('search', request)
    search_form = SiteSearchForm(request.GET)
    context = {
        'search_form': search_form,
    }
    search_kwargs = {}
    if component:
        obj = get_component(request, project, component)
        context['component'] = obj
        context['project'] = obj.project
        context['back_url'] = obj.get_absolute_url()
        search_kwargs = {'component': obj}
    elif project:
        obj = get_project(request, project)
        context['project'] = obj
        context['back_url'] = obj.get_absolute_url()
        search_kwargs = {'project': obj}
    else:
        obj = None
        context['back_url'] = None
    if lang:
        s_language = get_object_or_404(Language, code=lang)
        context['language'] = s_language
        search_kwargs = {'language': s_language}
        if obj:
            if component:
                context['back_url'] = obj.translation_set.get(
                    language=s_language
                ).get_absolute_url()
            else:
                context['back_url'] = reverse(
                    'project-language',
                    kwargs={
                        'project': project,
                        'lang': lang,
                    }
                )
        else:
            context['back_url'] = s_language.get_absolute_url()

    if not is_ratelimited and request.GET and search_form.is_valid():
        # Filter results by ACL
        if component:
            units = Unit.objects.filter(translation__component=obj)
        elif project:
            units = Unit.objects.filter(translation__component__project=obj)
        else:
            allowed_projects = request.user.allowed_projects
            units = Unit.objects.filter(
                translation__component__project__in=allowed_projects
            )
        units = units.search(
            search_form.cleaned_data,
            **search_kwargs
        )
        if lang:
            units = units.filter(
                translation__language=context['language']
            )

        units = get_paginator(request, units)

        context['show_results'] = True
        context['page_obj'] = units
        context['title'] = _('Search for %s') % (
            search_form.cleaned_data['q']
        )
        context['query_string'] = search_form.urlencode()
        context['search_query'] = search_form.cleaned_data['q']
    elif is_ratelimited:
        messages.error(
            request, _('Too many search queries, please try again later.')
        )
    elif request.GET:
        messages.error(request, _('Invalid search query!'))
        show_form_errors(request, search_form)

    return render(
        request,
        'search.html',
        context
    )