Пример #1
0
def deny_demo(request):
    """Deny editing of demo account on demo server."""
    messages.warning(
        request,
        _('You cannot change demo account on the demo server.')
    )
    return redirect_profile(request.POST.get('activetab'))
Пример #2
0
def adjust_primary_mail(strategy, entries, user, *args, **kwargs):
    """Fix primary mail on disconnect."""
    # Remove pending verification codes
    mails = VerifiedEmail.objects.filter(
        social__user=user,
        social__in=entries
    ).values_list('email', flat=True)
    Code.objects.filter(email__in=mails).delete()

    # Check remaining verified mails
    verified = VerifiedEmail.objects.filter(
        social__user=user,
    ).exclude(
        social__in=entries
    )
    if verified.filter(email=user.email).exists():
        return

    user.email = verified[0].email
    user.save()
    messages.warning(
        strategy.request,
        _(
            'Your email no longer belongs to verified account, '
            'it has been changed to {0}.'
        ).format(
            user.email
        )
    )
Пример #3
0
 def pre_install(cls, component, request):
     if cls.trigger_update:
         perform_update.delay('Component', component.pk, auto=True)
         if component.repo_needs_merge():
             messages.warning(
                 request,
                 _('The repository is outdated, you might not get '
                   'expected results until you update it.'),
             )
Пример #4
0
def search(translation, request, form_class=SearchForm):
    """Perform search or returns cached search results."""
    # Possible new search
    form = form_class(request.user, request.GET, show_builder=False)

    # Process form
    form_valid = form.is_valid()
    if not form_valid:
        show_form_errors(request, form)

    search_result = {
        "form": form,
        "offset": form.cleaned_data.get("offset", 1),
        "checksum": form.cleaned_data.get("checksum"),
    }
    search_url = form.urlencode()
    session_key = "search_{0}_{1}".format(translation.pk, search_url)

    if (
        session_key in request.session
        and "offset" in request.GET
        and "items" in request.session[session_key]
    ):
        search_result.update(request.session[session_key])
        return search_result

    allunits = translation.unit_set.search(form.cleaned_data.get("q", "")).distinct()

    search_query = form.get_search_query() if form_valid else ""
    name = form.get_name()

    # Grab unit IDs
    unit_ids = list(
        allunits.order_by_request(form.cleaned_data).values_list("id", flat=True)
    )

    # Check empty search results
    if not unit_ids:
        messages.warning(request, _("No string matched your search!"))
        return redirect(translation)

    # Remove old search results
    cleanup_session(request.session)

    store_result = {
        "query": search_query,
        "url": search_url,
        "items": form.items(),
        "key": session_key,
        "name": force_str(name),
        "ids": unit_ids,
        "ttl": int(time.time()) + 86400,
    }
    request.session[session_key] = store_result

    search_result.update(store_result)
    return search_result
Пример #5
0
def deny_demo(request):
    """
    Denies editing of demo account on demo server.
    """
    messages.warning(
        request,
        _('You cannot change demo account on the demo server.')
    )
    return redirect_profile(request.POST.get('activetab'))
Пример #6
0
def add_host_key(request, host, port=""):
    """Add host key for a host."""
    if not host:
        messages.error(request, _("Invalid host name given!"))
    else:
        cmdline = ["ssh-keyscan"]
        if port:
            cmdline.extend(["-p", str(port)])
        cmdline.append(host)
        try:
            result = subprocess.run(
                cmdline,
                env=get_clean_env(),
                check=True,
                text=True,
                capture_output=True,
            )
            keys = set()
            for key in result.stdout.splitlines():
                key = key.strip()
                if not is_key_line(key):
                    continue
                keys.add(key)
                host, keytype, fingerprint = parse_hosts_line(key)
                messages.warning(
                    request,
                    _("Added host key for %(host)s with fingerprint "
                      "%(fingerprint)s (%(keytype)s), "
                      "please verify that it is correct.") % {
                          "host": host,
                          "fingerprint": fingerprint,
                          "keytype": keytype
                      },
                )
            if keys:
                known_hosts_file = ssh_file(KNOWN_HOSTS)
                # Remove existing key entries
                if os.path.exists(known_hosts_file):
                    with open(known_hosts_file) as handle:
                        for line in handle:
                            keys.discard(line.strip())
                # Write any new keys
                if keys:
                    with open(known_hosts_file, "a") as handle:
                        for key in keys:
                            handle.write(key)
                            handle.write("\n")
            else:
                messages.error(request,
                               _("Failed to fetch public key for a host!"))
        except subprocess.CalledProcessError as exc:
            messages.error(
                request,
                _("Failed to get host key: %s") % exc.stderr or exc.stdout)
        except OSError as exc:
            messages.error(request, _("Failed to get host key: %s") % str(exc))
Пример #7
0
def search(translation, request):
    """Perform search or returns cached search results."""
    # Possible new search
    form = SearchForm(request.GET)

    # Process form
    form_valid = form.is_valid()
    if not form_valid:
        show_form_errors(request, form)

    search_result = {
        'form': form,
        'offset': form.cleaned_data.get('offset', 1),
        'checksum': form.cleaned_data.get('checksum'),
    }
    search_url = form.urlencode()
    session_key = 'search_{0}_{1}'.format(translation.pk, search_url)

    if (session_key in request.session
            and 'offset' in request.GET
            and 'items' in request.session[session_key]):
        search_result.update(request.session[session_key])
        return search_result

    allunits = translation.unit_set.search(
        form.cleaned_data,
        translation=translation,
    )

    search_query = form.get_search_query() if form_valid else ''
    name = form.get_name() if form_valid else ''

    # Grab unit IDs
    unit_ids = list(allunits.order().values_list('id', flat=True))

    # Check empty search results
    if not unit_ids:
        messages.warning(request, _('No string matched your search!'))
        return redirect(translation)

    # Remove old search results
    cleanup_session(request.session)

    store_result = {
        'query': search_query,
        'url': search_url,
        'items': form.items(),
        'key': session_key,
        'name': force_text(name),
        'ids': unit_ids,
        'ttl': int(time.time()) + 86400,
    }
    request.session[session_key] = store_result

    search_result.update(store_result)
    return search_result
Пример #8
0
def search(translation, request):
    """Perform search or returns cached search results."""
    # Possible new search
    form = SearchForm(request.GET)

    # Process form
    form_valid = form.is_valid()
    if not form_valid:
        show_form_errors(request, form)

    search_result = {
        'form': form,
        'offset': form.cleaned_data.get('offset', 1),
        'checksum': form.cleaned_data.get('checksum'),
    }
    search_url = form.urlencode()
    session_key = 'search_{0}_{1}'.format(translation.pk, search_url)

    if (session_key in request.session and
            'offset' in request.GET and
            'items' in request.session[session_key]):
        search_result.update(request.session[session_key])
        return search_result

    allunits = translation.unit_set.search(
        form.cleaned_data,
        translation=translation,
    )

    search_query = form.get_search_query() if form_valid else ''
    name = form.get_name() if form_valid else ''

    # Grab unit IDs
    unit_ids = list(allunits.values_list('id', flat=True))

    # Check empty search results
    if not unit_ids:
        messages.warning(request, _('No string matched your search!'))
        return redirect(translation)

    # Remove old search results
    cleanup_session(request.session)

    store_result = {
        'query': search_query,
        'url': search_url,
        'items': form.items(),
        'key': session_key,
        'name': force_text(name),
        'ids': unit_ids,
        'ttl': int(time.time()) + 86400,
    }
    request.session[session_key] = store_result

    search_result.update(store_result)
    return search_result
Пример #9
0
 def warn_outdated(self, form):
     linked = form.instance.linked_component
     if linked:
         perform_update.delay("Component", linked.pk, auto=True)
         if linked.repo_needs_merge():
             messages.warning(
                 self.request,
                 _("The repository is outdated, you might not get "
                   "expected results until you update it."),
             )
Пример #10
0
def add_host_key(request):
    """Add host key for a host."""
    host = request.POST.get('host', '')
    port = request.POST.get('port', '')
    if len(host) == 0:
        messages.error(request, _('Invalid host name given!'))
    else:
        cmdline = ['ssh-keyscan']
        if port:
            cmdline.extend(['-p', port])
        cmdline.append(host)
        try:
            output = subprocess.check_output(
                cmdline,
                stderr=subprocess.STDOUT,
                env=get_clean_env(),
            )
            keys = []
            for key in output.decode('utf-8').splitlines():
                key = key.strip()
                if not is_key_line(key):
                    continue
                keys.append(key)
                host, keytype, fingerprint = parse_hosts_line(key)
                messages.warning(
                    request,
                    _(
                        'Added host key for %(host)s with fingerprint '
                        '%(fingerprint)s (%(keytype)s), '
                        'please verify that it is correct.'
                    ) % {
                        'host': host,
                        'fingerprint': fingerprint,
                        'keytype': keytype,
                    }
                )
            if len(keys) == 0:
                messages.error(
                    request,
                    _('Failed to fetch public key for a host!')
                )
            with open(ssh_file(KNOWN_HOSTS), 'a') as handle:
                for key in keys:
                    handle.write('{0}\n'.format(key))
        except subprocess.CalledProcessError as exc:
            messages.error(
                request,
                _('Failed to get host key: %s') % exc.output
            )
        except OSError as exc:
            messages.error(
                request,
                _('Failed to get host key: %s') % str(exc)
            )
Пример #11
0
def add_host_key(request):
    """Add host key for a host."""
    host = request.POST.get('host', '')
    port = request.POST.get('port', '')
    if len(host) == 0:
        messages.error(request, _('Invalid host name given!'))
    else:
        cmdline = ['ssh-keyscan']
        if port:
            cmdline.extend(['-p', port])
        cmdline.append(host)
        try:
            output = subprocess.check_output(
                cmdline,
                stderr=subprocess.STDOUT,
                env=get_clean_env(),
            )
            keys = []
            for key in output.decode('utf-8').splitlines():
                key = key.strip()
                if not is_key_line(key):
                    continue
                keys.append(key)
                host, keytype, fingerprint = parse_hosts_line(key)
                messages.warning(
                    request,
                    _(
                        'Added host key for %(host)s with fingerprint '
                        '%(fingerprint)s (%(keytype)s), '
                        'please verify that it is correct.'
                    ) % {
                        'host': host,
                        'fingerprint': fingerprint,
                        'keytype': keytype,
                    }
                )
            if len(keys) == 0:
                messages.error(
                    request,
                    _('Failed to fetch public key for a host!')
                )
            with open(ssh_file(KNOWN_HOSTS), 'a') as handle:
                for key in keys:
                    handle.write('{0}\n'.format(key))
        except subprocess.CalledProcessError as exc:
            messages.error(
                request,
                _('Failed to get host key: %s') % exc.output
            )
        except OSError as exc:
            messages.error(
                request,
                _('Failed to get host key: %s') % str(exc)
            )
Пример #12
0
def ensure_valid(strategy, backend, user, registering_user, weblate_action,
                 weblate_expires, new_association, details, **kwargs):
    """Ensure the activation link is still."""

    # Didn't the link expire?
    if weblate_expires < time.time():
        raise AuthMissingParameter(backend, 'expires')

    # We allow password reset for unauthenticated users
    if weblate_action == 'reset':
        if strategy.request.user.is_authenticated:
            messages.warning(
                strategy.request,
                _('You can not complete password reset while logged in!'),
            )
            messages.warning(strategy.request,
                             _('The registration link has been invalidated.'))
            raise AuthMissingParameter(backend, 'user')
        return

    # Add e-mail/register should stay on same user
    if user and user.is_authenticated:
        current_user = user.pk
    else:
        current_user = None

    if current_user != registering_user:
        if registering_user is None:
            messages.warning(
                strategy.request,
                _('You can not complete registration while logged in!'),
            )
        else:
            messages.warning(
                strategy.request,
                _('You can confirm your registration only while logged in!'),
            )
        messages.warning(strategy.request,
                         _('The registration link has been invalidated.'))

        raise AuthMissingParameter(backend, 'user')

    # Verify if this mail is not used on other accounts
    if new_association:
        same = VerifiedEmail.objects.filter(email=details['email'])
        if user:
            same = same.exclude(social__user=user)

        if same.exists():
            AuditLog.objects.create(same[0].social.user, strategy.request,
                                    'connect')
            raise AuthAlreadyAssociated(backend, 'E-mail exists')
Пример #13
0
def adjust_primary_mail(strategy, entries, user, *args, **kwargs):
    """Fix primary mail on disconnect."""
    verified = VerifiedEmail.objects.filter(
        social__user=user, ).exclude(social__in=entries)
    if verified.filter(email=user.email).exists():
        return

    user.email = verified[0].email
    user.save()
    messages.warning(
        strategy.request,
        _('Your email no longer belongs to verified account, '
          'it has been changed to {0}.').format(user.email))
Пример #14
0
def add_host_key(request, host, port=""):
    """Add host key for a host."""
    if not host:
        messages.error(request, _("Invalid host name given!"))
    else:
        cmdline = ["ssh-keyscan"]
        if port:
            cmdline.extend(["-p", str(port)])
        cmdline.append(host)
        try:
            result = subprocess.run(
                cmdline,
                env=get_clean_env(),
                check=True,
                universal_newlines=True,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
            )
            keys = []
            for key in result.stdout.splitlines():
                key = key.strip()
                if not is_key_line(key):
                    continue
                keys.append(key)
                host, keytype, fingerprint = parse_hosts_line(key)
                messages.warning(
                    request,
                    _("Added host key for %(host)s with fingerprint "
                      "%(fingerprint)s (%(keytype)s), "
                      "please verify that it is correct.") % {
                          "host": host,
                          "fingerprint": fingerprint,
                          "keytype": keytype
                      },
                )
            if not keys:
                messages.error(request,
                               _("Failed to fetch public key for a host!"))
            with open(ssh_file(KNOWN_HOSTS), "a") as handle:
                for key in keys:
                    handle.write("{0}\n".format(key))
        except subprocess.CalledProcessError as exc:
            messages.error(
                request,
                _("Failed to get host key: %s") % exc.stderr or exc.stdout)
        except OSError as exc:
            messages.error(request, _("Failed to get host key: %s") % str(exc))
Пример #15
0
def adjust_primary_mail(strategy, entries, user, *args, **kwargs):
    """Fix primary mail on disconnect."""
    # Remove pending verification codes
    invalidate_reset_codes(user=user, entries=entries)

    # Check remaining verified mails
    verified = VerifiedEmail.objects.filter(social__user=user).exclude(
        social__in=entries)
    if verified.filter(email=user.email).exists():
        return

    user.email = verified[0].email
    user.save()
    messages.warning(
        strategy.request,
        _('Your e-mail no longer belongs to verified account, '
          'it has been changed to {0}.').format(user.email),
    )
Пример #16
0
def adjust_primary_mail(strategy, entries, user, *args, **kwargs):
    """Fix primary mail on disconnect."""
    # Remove pending verification codes
    mails = VerifiedEmail.objects.filter(
        social__user=user, social__in=entries).values_list('email', flat=True)
    Code.objects.filter(email__in=mails).delete()

    # Check remaining verified mails
    verified = VerifiedEmail.objects.filter(
        social__user=user, ).exclude(social__in=entries)
    if verified.filter(email=user.email).exists():
        return

    user.email = verified[0].email
    user.save()
    messages.warning(
        strategy.request,
        _('Your email no longer belongs to verified account, '
          'it has been changed to {0}.').format(user.email))
Пример #17
0
def adjust_primary_mail(strategy, entries, user, *args, **kwargs):
    """Fix primary mail on disconnect."""
    verified = VerifiedEmail.objects.filter(
        social__user=user,
    ).exclude(
        social__in=entries
    )
    if verified.filter(email=user.email).exists():
        return

    user.email = verified[0].email
    user.save()
    messages.warning(
        strategy.request,
        _(
            'Your email no longer belongs to verified account, '
            'it has been changed to {0}.'
        ).format(
            user.email
        )
    )
Пример #18
0
def home(request):
    """Home page handler serving different views based on user."""

    # This is used on Hosted Weblate to handle removed translation projects.
    # The redirect itself is done in the http server.
    if 'removed' in request.GET:
        messages.warning(
            request,
            _('The project you were looking for has been removed, '
              'however you are welcome to contribute to other ones.'))

    if not request.user.is_authenticated:
        return dashboard_anonymous(request)

    if 'show_set_password' in request.session:
        messages.warning(
            request,
            _('You have activated your account, now you should set '
              'the password to be able to login next time.'))
        return redirect('password')

    # Warn about not filled in username (usually caused by migration of
    # users from older system
    if not request.user.full_name or not request.user.email:
        messages.warning(
            request,
            mark_safe('<a href="{0}">{1}</a>'.format(
                reverse('profile') + '#account',
                escape(
                    _('Please set your full name and email in your profile.')))
                      ))

    return dashboard_user(request)
Пример #19
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
        },
    )
Пример #20
0
def ensure_valid(strategy, backend, user, registering_user, weblate_action,
                 weblate_expires, **kwargs):
    """Ensure the activation link is still."""
    # Didn't the link expire?
    if weblate_expires < time.time():
        raise AuthMissingParameter(backend, 'expires')

    # We allow password reset for unauthenticated users
    if weblate_action == 'reset':
        if strategy.request.user.is_authenticated:
            messages.warning(
                strategy.request,
                _('You can not complete password reset while logged in!'))
            messages.warning(strategy.request,
                             _('The registration link has been invalidated.'))
            raise AuthMissingParameter(backend, 'user')
        return

    # Add email/register should stay on same user
    if user and user.is_authenticated:
        current_user = user.pk
    else:
        current_user = None

    if current_user != registering_user:
        if registering_user is None:
            messages.warning(
                strategy.request,
                _('You can not complete registration while logged in!'))
        else:
            messages.warning(
                strategy.request,
                _('You can confirm your registration only while logged in!'))
        messages.warning(strategy.request,
                         _('The registration link has been invalidated.'))

        raise AuthMissingParameter(backend, 'user')
Пример #21
0
def hosting(request):
    """Form for hosting request."""
    if not settings.OFFER_HOSTING or request.user.is_demo:
        if request.user.is_demo:
            message = _(
                'Please log in using your personal account to request hosting.'
            )
            messages.warning(request, message)
        return redirect('home')

    if request.method == 'POST':
        form = HostingForm(request.POST)
        if form.is_valid():
            context = form.cleaned_data
            context['username'] = request.user.username
            mail_admins_contact(
                request,
                'Hosting request for %(project)s',
                HOSTING_TEMPLATE,
                context,
                form.cleaned_data['email'],
                settings.ADMINS_HOSTING,
            )
            return redirect('home')
    else:
        initial = get_initial_contact(request)
        form = HostingForm(initial=initial)

    return render(
        request,
        'accounts/hosting.html',
        {
            'form': form,
            'title': _('Hosting'),
        }
    )
Пример #22
0
def hosting(request):
    """Form for hosting request."""
    if not settings.OFFER_HOSTING or request.user.is_demo:
        if request.user.is_demo:
            message = _(
                'Please log in using your personal account to request hosting.'
            )
            messages.warning(request, message)
        return redirect('home')

    if request.method == 'POST':
        form = HostingForm(request.POST)
        if form.is_valid():
            context = form.cleaned_data
            context['username'] = request.user.username
            mail_admins_contact(
                request,
                'Hosting request for %(project)s',
                HOSTING_TEMPLATE,
                context,
                form.cleaned_data['email'],
                settings.ADMINS_HOSTING,
            )
            return redirect('home')
    else:
        initial = get_initial_contact(request)
        form = HostingForm(initial=initial)

    return render(
        request,
        'accounts/hosting.html',
        {
            'form': form,
            'title': _('Hosting'),
        }
    )
Пример #23
0
def home(request):
    """Home page handler serving different views based on user."""
    user = request.user

    # This is used on Hosted Weblate to handle removed translation projects.
    # The redirect itself is done in the http server.
    if "removed" in request.GET:
        messages.warning(
            request,
            _(
                "The project you were looking for has been removed, "
                "however you are welcome to contribute to other ones."
            ),
        )

    if "show_set_password" in request.session:
        messages.warning(
            request,
            _(
                "You have activated your account, now you should set "
                "the password to be able to sign in next time."
            ),
        )
        return redirect("password")

    # Warn about not filled in username (usually caused by migration of
    # users from older system
    if user.is_authenticated and (not user.full_name or not user.email):
        messages.warning(
            request,
            mark_safe(
                '<a href="{0}">{1}</a>'.format(
                    reverse("profile") + "#account",
                    escape(_("Please set your full name and e-mail in your profile.")),
                )
            ),
        )

    # Redirect to single project or component
    if isinstance(settings.SINGLE_PROJECT, str):
        return redirect(Project.objects.get(slug=settings.SINGLE_PROJECT))
    if settings.SINGLE_PROJECT:
        if Component.objects.count() == 1:
            return redirect(Component.objects.first())

        if Project.objects.count() == 1:
            return redirect(Project.objects.first())

    if not user.is_authenticated:
        return dashboard_anonymous(request)

    return dashboard_user(request)
Пример #24
0
def home(request):
    """Home page handler serving different views based on user."""

    # This is used on Hosted Weblate to handle removed translation projects.
    # The redirect itself is done in the http server.
    if 'removed' in request.GET:
        messages.warning(
            request,
            _(
                'The project you were looking for has been removed, '
                'however you are welcome to contribute to other ones.'
            )
        )

    if not request.user.is_authenticated:
        return dashboard_anonymous(request)

    if 'show_set_password' in request.session:
        messages.warning(
            request,
            _(
                'You have activated your account, now you should set '
                'the password to be able to login next time.'
            )
        )
        return redirect('password')

    # Warn about not filled in username (usually caused by migration of
    # users from older system
    if not request.user.full_name or not request.user.email:
        messages.warning(
            request,
            mark_safe('<a href="{0}">{1}</a>'.format(
                reverse('profile') + '#account',
                escape(
                    _('Please set your full name and email in your profile.')
                )
            ))
        )

    return dashboard_user(request)
Пример #25
0
def user_profile(request):

    profile = request.user.profile

    if not request.user.is_demo and not profile.language:
        profile.language = get_language()
        profile.save(update_fields=['language'])

    form_classes = [
        ProfileForm,
        SubscriptionForm,
        SubscriptionSettingsForm,
        UserSettingsForm,
        DashboardSettingsForm,
    ]
    all_backends = set(load_backends(social_django.utils.BACKENDS).keys())

    if request.method == 'POST':
        # Parse POST params
        forms = [form(request.POST, instance=profile) for form in form_classes]
        forms.append(UserForm(request.POST, instance=request.user))

        if request.user.is_demo:
            return deny_demo(request)

        if all(form.is_valid() for form in forms):
            # Save changes
            for form in forms:
                form.save()

            # Change language
            set_lang(request, request.user.profile)

            # Redirect after saving (and possibly changing language)
            response = redirect_profile(request.POST.get('activetab'))

            # Set language cookie and activate new language (for message below)
            lang_code = profile.language
            response.set_cookie(settings.LANGUAGE_COOKIE_NAME, lang_code)
            translation.activate(lang_code)

            messages.success(request, _('Your profile has been updated.'))

            return response
    else:
        forms = [form(instance=profile) for form in form_classes]
        forms.append(UserForm(instance=request.user))

        if not request.user.has_usable_password() and 'email' in all_backends:
            messages.warning(
                request,
                render_to_string('accounts/password-warning.html')
            )

    social = request.user.social_auth.all()
    social_names = [assoc.provider for assoc in social]
    new_backends = [
        x for x in all_backends
        if x == 'email' or x not in social_names
    ]
    license_projects = Component.objects.filter(
        project__in=request.user.allowed_projects
    ).exclude(
        license=''
    )

    result = render(
        request,
        'accounts/profile.html',
        {
            'languagesform': forms[0],
            'subscriptionform': forms[1],
            'subscriptionsettingsform': forms[2],
            'usersettingsform': forms[3],
            'dashboardsettingsform': forms[4],
            'userform': forms[5],
            'profile': profile,
            'title': _('User profile'),
            'licenses': license_projects,
            'associated': social,
            'new_backends': new_backends,
            'managed_projects': request.user.owned_projects,
            'auditlog': request.user.auditlog_set.all()[:20],
        }
    )
    result.set_cookie(
        settings.LANGUAGE_COOKIE_NAME,
        profile.language
    )
    return result
Пример #26
0
def search(translation, request):
    """Perform search or returns cached search results."""
    # Possible new search
    search_form = SearchForm(request.GET)
    review_form = ReviewForm(request.GET)

    # Process form
    if 'date' in request.GET:
        if review_form.is_valid():
            form = review_form
        else:
            show_form_errors(request, review_form)
            # Use blank form
            form = SearchForm([])
            form.is_valid()
    elif search_form.is_valid():
        form = search_form
    else:
        show_form_errors(request, search_form)
        # Use blank form
        form = SearchForm([])
        form.is_valid()

    search_result = {
        'form': form,
        'offset': form.cleaned_data['offset'],
        'checksum': form.cleaned_data['checksum'],
    }
    search_url = form.urlencode()
    session_key = 'search_{0}_{1}'.format(translation.pk, search_url)

    if session_key in request.session:
        search_result.update(request.session[session_key])
        return search_result

    if form.cleaned_data['type'] == 'review':
        allunits = translation.unit_set.review(
            form.cleaned_data['date'],
            request.user
        )
    else:
        allunits = translation.unit_set.search(
            translation,
            form.cleaned_data,
        )
        if form.cleaned_data['type'] == 'random':
            allunits = allunits[:25]

    search_query = form.get_search_query()
    name = form.get_name()

    # Grab unit IDs
    unit_ids = list(allunits.values_list('id', flat=True))

    # Check empty search results
    if len(unit_ids) == 0:
        messages.warning(request, _('No string matched your search!'))
        return redirect(translation)

    # Remove old search results
    cleanup_session(request.session)

    store_result = {
        'query': search_query,
        'url': search_url,
        'key': session_key,
        'name': force_text(name),
        'ids': unit_ids,
        'ttl': int(time.time()) + 86400,
    }
    request.session[session_key] = store_result

    search_result.update(store_result)
    return search_result
Пример #27
0
def upload_translation(request, project, subproject, lang):
    '''
    Handling of translation uploads.
    '''
    obj = get_translation(request, project, subproject, lang)

    if not can_upload_translation(request.user, obj):
        raise PermissionDenied()

    # Check method and lock
    if obj.is_locked(request.user):
        messages.error(request, _('Access denied.'))
        return redirect(obj)

    # Get correct form handler based on permissions
    form = get_upload_form(
        request.user, obj,
        request.POST, request.FILES
    )

    # Check form validity
    if not form.is_valid():
        messages.error(request, _('Please fix errors in the form.'))
        show_form_errors(request, form)
        return redirect(obj)

    # Create author name
    author = None
    if (can_author_translation(request.user, obj.subproject.project) and
            form.cleaned_data['author_name'] != '' and
            form.cleaned_data['author_email'] != ''):
        author = '%s <%s>' % (
            form.cleaned_data['author_name'],
            form.cleaned_data['author_email']
        )

    # Check for overwriting
    overwrite = False
    if can_overwrite_translation(request.user, obj.subproject.project):
        overwrite = form.cleaned_data['overwrite']

    # Do actual import
    try:
        ret, count = obj.merge_upload(
            request,
            request.FILES['file'],
            overwrite,
            author,
            merge_header=form.cleaned_data['merge_header'],
            merge_comments=form.cleaned_data['merge_comments'],
            method=form.cleaned_data['method'],
            fuzzy=form.cleaned_data['fuzzy'],
        )
        import_message(
            request, count,
            _('No strings were imported from the uploaded file.'),
            ungettext(
                'Processed %d string from the uploaded files.',
                'Processed %d strings from the uploaded files.',
                count
            )
        )
        if not ret:
            messages.warning(
                request,
                _('There were no new strings in uploaded file!')
            )
    except Exception as error:
        messages.error(
            request, _('File content merge failed: %s') % force_text(error)
        )
        report_error(error, sys.exc_info(), request)

    return redirect(obj)
Пример #28
0
def ensure_valid(strategy, backend, user, registering_user, weblate_action,
                 weblate_expires, new_association, details, **kwargs):
    """Ensure the activation link is still."""

    # Didn't the link expire?
    if weblate_expires < time.time():
        raise AuthMissingParameter(backend, 'expires')

    # We allow password reset for unauthenticated users
    if weblate_action == 'reset':
        if strategy.request.user.is_authenticated:
            messages.warning(
                strategy.request,
                _('You can not complete password reset while logged in!')
            )
            messages.warning(
                strategy.request,
                _('The registration link has been invalidated.')
            )
            raise AuthMissingParameter(backend, 'user')
        return

    # Add email/register should stay on same user
    if user and user.is_authenticated:
        current_user = user.pk
    else:
        current_user = None

    if current_user != registering_user:
        if registering_user is None:
            messages.warning(
                strategy.request,
                _('You can not complete registration while logged in!')
            )
        else:
            messages.warning(
                strategy.request,
                _('You can confirm your registration only while logged in!')
            )
        messages.warning(
            strategy.request,
            _('The registration link has been invalidated.')
        )

        raise AuthMissingParameter(backend, 'user')

    # Verify if this mail is not used on other accounts
    if new_association:
        same = VerifiedEmail.objects.filter(
            email=details['email']
        )
        if user:
            same = same.exclude(social__user=user)

        if same.exists():
            notify_account_activity(
                same[0].social.user,
                strategy.request,
                'connect'
            )
            raise AuthAlreadyAssociated(backend, 'Email exists')
Пример #29
0
def translate(request, project, component, lang):
    """Generic entry point for translating, suggesting and searching."""
    obj, project, unit_set = parse_params(request, project, component, lang)

    # Search results
    search_result = search(obj, unit_set, request)

    # Handle redirects
    if isinstance(search_result, HttpResponse):
        return search_result

    # Get numer of results
    num_results = len(search_result["ids"])

    # Search offset
    offset = search_result["offset"]

    # Checksum unit access
    checksum_form = ChecksumForm(unit_set, request.GET or request.POST)
    if checksum_form.is_valid():
        unit = checksum_form.cleaned_data["unit"]
        try:
            offset = search_result["ids"].index(unit.id) + 1
        except ValueError:
            messages.warning(request, _("No string matched your search!"))
            return redirect(obj)
    else:
        # Check boundaries
        if not 0 < offset <= num_results:
            messages.info(request, _("The translation has come to an end."))
            # Delete search
            del request.session[search_result["key"]]
            return redirect(obj)

        # Grab actual unit
        try:
            unit = unit_set.get(pk=search_result["ids"][offset - 1])
        except Unit.DoesNotExist:
            # Can happen when using SID for other translation
            messages.error(request, _("Invalid search string!"))
            return redirect(obj)

    # Check locks
    locked = unit.translation.component.locked

    # Some URLs we will most likely use
    base_unit_url = "{}?{}&offset=".format(obj.get_translate_url(),
                                           search_result["url"])
    this_unit_url = base_unit_url + str(offset)
    next_unit_url = base_unit_url + str(offset + 1)

    response = None

    # Any form submitted?
    if "skip" in request.POST:
        return redirect(next_unit_url)
    if request.method == "POST" and "merge" not in request.POST:
        if (not locked and "accept" not in request.POST
                and "accept_edit" not in request.POST
                and "delete" not in request.POST and "spam" not in request.POST
                and "upvote" not in request.POST
                and "downvote" not in request.POST):
            # Handle translation
            response = handle_translate(request, unit, this_unit_url,
                                        next_unit_url)
        elif not locked or "delete" in request.POST or "spam" in request.POST:
            # Handle accepting/deleting suggestions
            response = handle_suggestions(request, unit, this_unit_url,
                                          next_unit_url)

    # Handle translation merging
    elif "merge" in request.POST and not locked:
        response = handle_merge(unit, request, next_unit_url)

    # Handle reverting
    elif "revert" in request.GET and not locked:
        response = handle_revert(unit, request, this_unit_url)

    # Pass possible redirect further
    if response is not None:
        return response

    # Show secondary languages for signed in users
    if request.user.is_authenticated:
        secondary = unit.get_secondary_units(request.user)
    else:
        secondary = None

    # Spam protection
    antispam = AntispamForm()

    # Prepare form
    form = TranslationForm(request.user, unit)
    sort = get_sort_name(request)

    return render(
        request,
        "translate.html",
        {
            "this_unit_url":
            this_unit_url,
            "first_unit_url":
            base_unit_url + "1",
            "last_unit_url":
            base_unit_url + str(num_results),
            "next_unit_url":
            next_unit_url,
            "prev_unit_url":
            base_unit_url + str(offset - 1),
            "object":
            obj,
            "project":
            project,
            "unit":
            unit,
            "nearby":
            unit.nearby(request.user.profile.nearby_strings),
            "nearby_keys":
            unit.nearby_keys(request.user.profile.nearby_strings),
            "others":
            get_other_units(unit),
            "search_url":
            search_result["url"],
            "search_items":
            search_result["items"],
            "search_query":
            search_result["query"],
            "offset":
            offset,
            "sort_name":
            sort["name"],
            "sort_query":
            sort["query"],
            "filter_name":
            search_result["name"],
            "filter_count":
            num_results,
            "filter_pos":
            offset,
            "form":
            form,
            "antispam":
            antispam,
            "comment_form":
            CommentForm(
                project,
                initial={
                    "scope": "global" if unit.is_source else "translation"
                },
            ),
            "context_form":
            ContextForm(instance=unit.source_unit, user=request.user),
            "search_form":
            search_result["form"].reset_offset(),
            "secondary":
            secondary,
            "locked":
            locked,
            "glossary":
            Term.objects.get_terms(unit),
            "addterm_form":
            TermForm(project),
            "last_changes":
            unit.change_set.prefetch().order()[:10],
            "screenshots": (unit.source_unit.screenshots.all()
                            | unit.screenshots.all()).order,
            "last_changes_url":
            urlencode(unit.translation.get_reverse_url_kwargs()),
            "display_checks":
            list(get_display_checks(unit)),
            "machinery_services":
            json.dumps(list(MACHINE_TRANSLATION_SERVICES.keys())),
        },
    )
Пример #30
0
def translate(request, project, component, lang):
    """Generic entry point for translating, suggesting and searching."""
    translation = get_translation(request, project, component, lang)

    # Check locks
    locked = translation.component.locked

    # Search results
    search_result = search(translation, request)

    # Handle redirects
    if isinstance(search_result, HttpResponse):
        return search_result

    # Get numer of results
    num_results = len(search_result['ids'])

    # Search offset
    offset = search_result['offset']

    # Checksum unit access
    if search_result['checksum']:
        try:
            unit = translation.unit_set.get(id_hash=search_result['checksum'])
            offset = search_result['ids'].index(unit.id) + 1
        except (Unit.DoesNotExist, ValueError):
            messages.warning(request, _('No string matched your search!'))
            return redirect(translation)

    # Check boundaries
    if not 0 < offset <= num_results:
        messages.info(request, _('The translation has come to an end.'))
        # Delete search
        del request.session[search_result['key']]
        # Redirect to translation
        return redirect(translation)

    # Some URLs we will most likely use
    base_unit_url = '{0}?{1}&offset='.format(
        translation.get_translate_url(),
        search_result['url']
    )
    this_unit_url = base_unit_url + str(offset)
    next_unit_url = base_unit_url + str(offset + 1)

    response = None

    # Any form submitted?
    if 'skip' in request.POST:
        return redirect(next_unit_url)
    if request.method == 'POST':
        if (not locked
                and 'accept' not in request.POST
                and 'accept_edit' not in request.POST
                and 'delete' not in request.POST
                and 'spam' not in request.POST
                and 'upvote' not in request.POST
                and 'downvote' not in request.POST):
            # Handle translation
            response = handle_translate(
                request, translation, this_unit_url, next_unit_url
            )
        elif not locked or 'delete' in request.POST or 'spam' in request.POST:
            # Handle accepting/deleting suggestions
            response = handle_suggestions(
                translation, request, this_unit_url, next_unit_url,
            )

    # Handle translation merging
    elif 'merge' in request.GET and not locked:
        response = handle_merge(
            translation, request, next_unit_url
        )

    # Handle reverting
    elif 'revert' in request.GET and not locked:
        response = handle_revert(
            translation, request, this_unit_url
        )

    # Pass possible redirect further
    if response is not None:
        return response

    # Grab actual unit
    try:
        unit = translation.unit_set.get(pk=search_result['ids'][offset - 1])
    except Unit.DoesNotExist:
        # Can happen when using SID for other translation
        messages.error(request, _('Invalid search string!'))
        return redirect(translation)

    # Show secondary languages for logged in users
    if request.user.is_authenticated:
        secondary = unit.get_secondary_units(request.user)
    else:
        secondary = None

    # Spam protection
    antispam = AntispamForm()

    # Prepare form
    form = TranslationForm(request.user, translation, unit)

    return render(
        request,
        'translate.html',
        {
            'this_unit_url': this_unit_url,
            'first_unit_url': base_unit_url + '1',
            'last_unit_url': base_unit_url + str(num_results),
            'next_unit_url': next_unit_url,
            'prev_unit_url': base_unit_url + str(offset - 1),
            'object': translation,
            'project': translation.component.project,
            'unit': unit,
            'others': get_other_units(unit),
            'total': translation.unit_set.all().count(),
            'search_url': search_result['url'],
            'search_items': search_result['items'],
            'search_query': search_result['query'],
            'offset': offset,
            'filter_name': search_result['name'],
            'filter_count': num_results,
            'filter_pos': offset,
            'form': form,
            'antispam': antispam,
            'comment_form': CommentForm(),
            'search_form': search_result['form'].reset_offset(),
            'secondary': secondary,
            'locked': locked,
            'glossary': Dictionary.objects.get_words(unit),
            'addword_form': InlineWordForm(),
        }
    )
Пример #31
0
def import_message(request, count, message_none, message_ok):
    if count == 0:
        messages.warning(request, message_none)
    else:
        messages.success(request, message_ok % count)
Пример #32
0
def user_profile(request):
    profile = request.user.profile

    if not profile.language:
        profile.language = get_language()
        profile.save(update_fields=["language"])

    form_classes = [
        ProfileForm,
        SubscriptionForm,
        UserSettingsForm,
        DashboardSettingsForm,
        UserForm,
    ]
    forms = [form.from_request(request) for form in form_classes]
    forms.extend(get_notification_forms(request))
    all_backends = get_auth_keys()

    if request.method == "POST":
        if all(form.is_valid() for form in forms):
            # Save changes
            for form in forms:
                if hasattr(form, "audit"):
                    form.audit(request)
                form.save()

            messages.success(request, _("Your profile has been updated."))

            # Redirect after saving (and possibly changing language)
            return redirect_profile(request.POST.get("activetab"))
    else:
        if not request.user.has_usable_password() and "email" in all_backends:
            messages.warning(
                request, render_to_string("accounts/password-warning.html"))

    social = request.user.social_auth.all()
    social_names = [assoc.provider for assoc in social]
    new_backends = [
        x for x in sorted(all_backends)
        if x == "email" or x not in social_names
    ]
    license_projects = (Component.objects.filter_access(
        request.user).exclude(license="").prefetch().order_by("license"))

    result = render(
        request,
        "accounts/profile.html",
        {
            "languagesform": forms[0],
            "subscriptionform": forms[1],
            "usersettingsform": forms[2],
            "dashboardsettingsform": forms[3],
            "userform": forms[4],
            "notification_forms": forms[5:],
            "all_forms": forms,
            "profile": profile,
            "title": _("User profile"),
            "licenses": license_projects,
            "associated": social,
            "new_backends": new_backends,
            "has_email_auth": "email" in all_backends,
            "auditlog": request.user.auditlog_set.order()[:20],
        },
    )
    return result
Пример #33
0
def user_profile(request):

    profile = request.user.profile

    if not request.user.is_demo and not profile.language:
        profile.language = get_language()
        profile.save(update_fields=['language'])

    form_classes = [
        ProfileForm,
        SubscriptionForm,
        SubscriptionSettingsForm,
        UserSettingsForm,
        DashboardSettingsForm,
    ]
    all_backends = set(load_backends(social_django.utils.BACKENDS).keys())

    if request.method == 'POST':
        # Parse POST params
        forms = [form(request.POST, instance=profile) for form in form_classes]
        forms.append(UserForm(request.POST, instance=request.user))

        if request.user.is_demo:
            return deny_demo(request)

        if all(form.is_valid() for form in forms):
            # Save changes
            for form in forms:
                form.save()

            # Change language
            set_lang(request, request.user.profile)

            # Redirect after saving (and possibly changing language)
            response = redirect_profile(request.POST.get('activetab'))

            # Set language cookie and activate new language (for message below)
            lang_code = profile.language
            response.set_cookie(settings.LANGUAGE_COOKIE_NAME, lang_code)
            translation.activate(lang_code)

            messages.success(request, _('Your profile has been updated.'))

            return response
    else:
        forms = [form(instance=profile) for form in form_classes]
        forms.append(UserForm(instance=request.user))

        if not request.user.has_usable_password() and 'email' in all_backends:
            messages.warning(
                request, render_to_string('accounts/password-warning.html'))

    social = request.user.social_auth.all()
    social_names = [assoc.provider for assoc in social]
    new_backends = [
        x for x in all_backends if x == 'email' or x not in social_names
    ]
    license_projects = Component.objects.filter(
        project__in=request.user.allowed_projects).exclude(license='')

    billings = None
    if 'weblate.billing' in settings.INSTALLED_APPS:
        # pylint: disable=wrong-import-position
        from weblate.billing.models import Billing
        billings = Billing.objects.filter(
            projects__in=request.user.projects_with_perm(
                'billing.view')).distinct()

    result = render(
        request, 'accounts/profile.html', {
            'form': forms[0],
            'subscriptionform': forms[1],
            'subscriptionsettingsform': forms[2],
            'usersettingsform': forms[3],
            'dashboardsettingsform': forms[4],
            'userform': forms[5],
            'profile': profile,
            'title': _('User profile'),
            'licenses': license_projects,
            'associated': social,
            'new_backends': new_backends,
            'managed_projects': request.user.owned_projects,
            'auditlog': request.user.auditlog_set.all()[:20],
            'billings': billings,
        })
    result.set_cookie(settings.LANGUAGE_COOKIE_NAME, profile.language)
    return result
Пример #34
0
def search(translation, request):
    """Perform search or returns cached search results."""

    # Already performed search
    if 'sid' in request.GET:
        # Grab from session storage
        search_id = 'search_{0}'.format(request.GET['sid'])

        # Check if we know the search
        if search_id not in request.session:
            messages.error(request, _('Invalid search string!'))
            return redirect(translation)

        search_result = copy.copy(request.session[search_id])
        if 'params' in search_result:
            search_result['form'] = SearchForm(search_result['params'])
        else:
            search_result['form'] = SearchForm()

        return search_result

    # Possible new search
    search_form = SearchForm(request.GET)
    review_form = ReviewForm(request.GET)

    search_query = None
    if 'date' in request.GET:
        if review_form.is_valid():
            # Review
            allunits = translation.unit_set.review(
                review_form.cleaned_data['date'], request.user)

            formatted_date = formats.date_format(
                review_form.cleaned_data['date'], 'SHORT_DATE_FORMAT')
            name = _('Review of translations since %s') % formatted_date
        else:
            show_form_errors(request, review_form)

            # Filtering by type
            allunits = translation.unit_set.all()
            name = _('All strings')
    elif search_form.is_valid():
        # Apply search conditions
        allunits = translation.unit_set.search(
            translation,
            search_form.cleaned_data,
        )

        search_query = search_form.cleaned_data['q']
        name = search_form.get_name()
    else:
        # Error reporting
        show_form_errors(request, search_form)

        # Filtering by type
        allunits = translation.unit_set.all()
        name = _('All strings')

    # Grab unit IDs
    unit_ids = list(allunits.values_list('id', flat=True))

    # Check empty search results
    if len(unit_ids) == 0:
        messages.warning(request, _('No string matched your search!'))
        return redirect(translation)

    # Checksum unit access
    offset = 0
    if 'checksum' in request.GET:
        try:
            unit = allunits.filter(
                id_hash=checksum_to_hash(request.GET['checksum']))[0]
            offset = unit_ids.index(unit.id)
        except (Unit.DoesNotExist, IndexError, ValueError):
            messages.warning(request, _('No string matched your search!'))
            return redirect(translation)

    # Remove old search results
    cleanup_session(request.session)

    # Store in cache and return
    search_id = str(uuid.uuid1())
    search_result = {
        'params': request.GET,
        'query': search_query,
        'name': force_text(name),
        'ids': unit_ids,
        'search_id': search_id,
        'ttl': int(time.time()) + 86400,
        'offset': offset,
    }

    request.session['search_{0}'.format(search_id)] = search_result

    search_result = copy.copy(search_result)
    search_result['form'] = search_form
    return search_result
Пример #35
0
def upload_translation(request, project, component, lang):
    """Handling of translation uploads."""
    obj = get_translation(request, project, component, lang)

    if not request.user.has_perm('upload.perform', obj):
        raise PermissionDenied()

    # Check method and lock
    if obj.component.locked:
        messages.error(request, _('Access denied.'))
        return redirect(obj)

    # Get correct form handler based on permissions
    form = get_upload_form(request.user, obj, request.POST, request.FILES)

    # Check form validity
    if not form.is_valid():
        messages.error(request, _('Please fix errors in the form.'))
        show_form_errors(request, form)
        return redirect(obj)

    # Create author name
    author_name = None
    author_email = None
    if request.user.has_perm('upload.authorship', obj):
        author_name = form.cleaned_data['author_name']
        author_email = form.cleaned_data['author_email']

    # Check for overwriting
    overwrite = False
    if request.user.has_perm('upload.overwrite', obj):
        overwrite = form.cleaned_data['upload_overwrite']

    # Do actual import
    try:
        not_found, skipped, accepted, total = obj.merge_upload(
            request,
            request.FILES['file'],
            overwrite,
            author_name,
            author_email,
            method=form.cleaned_data['method'],
            fuzzy=form.cleaned_data['fuzzy'],
        )
        if total == 0:
            message = _('No strings were imported from the uploaded file.')
        else:
            message = ungettext(
                'Processed {0} string from the uploaded files '
                '(skipped: {1}, not found: {2}, updated: {3}).',
                'Processed {0} strings from the uploaded files '
                '(skipped: {1}, not found: {2}, updated: {3}).',
                total).format(total, skipped, not_found, accepted)
        if accepted == 0:
            messages.warning(request, message)
        else:
            messages.success(request, message)
    except Exception as error:
        messages.error(request,
                       _('File content merge failed: %s') % force_text(error))
        report_error(error, request, prefix='Failed to merge content')

    return redirect(obj)
Пример #36
0
def translate(request, project, component, lang):
    """Generic entry point for translating, suggesting and searching."""
    translation = get_translation(request, project, component, lang)

    # Check locks
    locked = translation.component.locked

    # Search results
    search_result = search(translation, request)

    # Handle redirects
    if isinstance(search_result, HttpResponse):
        return search_result

    # Get numer of results
    num_results = len(search_result['ids'])

    # Search offset
    offset = search_result['offset']

    # Checksum unit access
    if search_result['checksum']:
        try:
            unit = translation.unit_set.get(id_hash=search_result['checksum'])
            offset = search_result['ids'].index(unit.id) + 1
        except (Unit.DoesNotExist, ValueError):
            messages.warning(request, _('No string matched your search!'))
            return redirect(translation)

    # Check boundaries
    if not 0 < offset <= num_results:
        messages.info(request, _('The translation has come to an end.'))
        # Delete search
        del request.session[search_result['key']]
        # Redirect to translation
        return redirect(translation)

    # Some URLs we will most likely use
    base_unit_url = '{0}?{1}&offset='.format(
        translation.get_translate_url(),
        search_result['url']
    )
    this_unit_url = base_unit_url + str(offset)
    next_unit_url = base_unit_url + str(offset + 1)

    response = None

    # Any form submitted?
    if 'skip' in request.POST:
        return redirect(next_unit_url)
    if request.method == 'POST':
        if (not locked and
                'accept' not in request.POST and
                'accept_edit' not in request.POST and
                'delete' not in request.POST and
                'spam' not in request.POST and
                'upvote' not in request.POST and
                'downvote' not in request.POST):
            # Handle translation
            response = handle_translate(
                request, translation, this_unit_url, next_unit_url
            )
        elif not locked or 'delete' in request.POST or 'spam' in request.POST:
            # Handle accepting/deleting suggestions
            response = handle_suggestions(
                translation, request, this_unit_url, next_unit_url,
            )

    # Handle translation merging
    elif 'merge' in request.GET and not locked:
        response = handle_merge(
            translation, request, next_unit_url
        )

    # Handle reverting
    elif 'revert' in request.GET and not locked:
        response = handle_revert(
            translation, request, this_unit_url
        )

    # Pass possible redirect further
    if response is not None:
        return response

    # Grab actual unit
    try:
        unit = translation.unit_set.get(pk=search_result['ids'][offset - 1])
    except Unit.DoesNotExist:
        # Can happen when using SID for other translation
        messages.error(request, _('Invalid search string!'))
        return redirect(translation)

    # Show secondary languages for logged in users
    if request.user.is_authenticated:
        secondary = unit.get_secondary_units(request.user)
    else:
        secondary = None

    # Spam protection
    antispam = AntispamForm()

    # Prepare form
    form = TranslationForm(request.user, translation, unit)

    return render(
        request,
        'translate.html',
        {
            'this_unit_url': this_unit_url,
            'first_unit_url': base_unit_url + '1',
            'last_unit_url': base_unit_url + str(num_results),
            'next_unit_url': next_unit_url,
            'prev_unit_url': base_unit_url + str(offset - 1),
            'object': translation,
            'project': translation.component.project,
            'unit': unit,
            'others': get_other_units(unit),
            'total': translation.unit_set.all().count(),
            'search_url': search_result['url'],
            'search_items': search_result['items'],
            'search_query': search_result['query'],
            'offset': offset,
            'filter_name': search_result['name'],
            'filter_count': num_results,
            'filter_pos': offset,
            'form': form,
            'antispam': antispam,
            'comment_form': CommentForm(),
            'search_form': search_result['form'].reset_offset(),
            'secondary': secondary,
            'locked': locked,
            'glossary': Dictionary.objects.get_words(unit),
            'addword_form': InlineWordForm(),
        }
    )
Пример #37
0
def user_profile(request):

    profile = request.user.profile

    if not profile.language:
        profile.language = get_language()
        profile.save()

    form_classes = [
        ProfileForm,
        SubscriptionForm,
        SubscriptionSettingsForm,
        UserSettingsForm,
        DashboardSettingsForm,
    ]
    all_backends = set(load_backends(BACKENDS).keys())

    if request.method == 'POST':
        # Parse POST params
        forms = [form(request.POST, instance=profile) for form in form_classes]
        forms.append(UserForm(request.POST, instance=request.user))

        if settings.DEMO_SERVER and request.user.username == 'demo':
            return deny_demo(request)

        if all(form.is_valid() for form in forms):
            # Save changes
            for form in forms:
                form.save()

            # Change language
            set_lang(request, request.user.profile)

            # Redirect after saving (and possibly changing language)
            response = redirect_profile(request.POST.get('activetab'))

            # Set language cookie and activate new language (for message below)
            lang_code = profile.language
            response.set_cookie(settings.LANGUAGE_COOKIE_NAME, lang_code)
            translation.activate(lang_code)

            messages.success(request, _('Your profile has been updated.'))

            return response
    else:
        forms = [form(instance=profile) for form in form_classes]
        forms.append(UserForm(instance=request.user))

        if not request.user.has_usable_password() and 'email' in all_backends:
            messages.warning(
                request,
                render_to_string('accounts/password-warning.html')
            )

    social = request.user.social_auth.all()
    social_names = [assoc.provider for assoc in social]
    new_backends = [
        x for x in all_backends
        if x == 'email' or x not in social_names
    ]
    license_projects = SubProject.objects.filter(
        project__in=Project.objects.all_acl(request.user)
    ).exclude(
        license=''
    )

    result = render(
        request,
        'accounts/profile.html',
        {
            'form': forms[0],
            'subscriptionform': forms[1],
            'subscriptionsettingsform': forms[2],
            'usersettingsform': forms[3],
            'dashboardsettingsform': forms[4],
            'userform': forms[5],
            'profile': profile,
            'title': _('User profile'),
            'licenses': license_projects,
            'associated': social,
            'new_backends': new_backends,
            'managed_projects': Project.objects.filter(
                groupacl__groups__name__endswith='@Administration',
                groupacl__groups__user=request.user,
            ).distinct(),
            'auditlog': request.user.auditlog_set.all()[:20],
        }
    )
    result.set_cookie(
        settings.LANGUAGE_COOKIE_NAME,
        profile.language
    )
    return result
Пример #38
0
def upload_translation(request, project, component, lang):
    """Handling of translation uploads."""
    obj = get_translation(request, project, component, lang)

    if not request.user.has_perm('upload.perform', obj):
        raise PermissionDenied()

    # Check method and lock
    if obj.component.locked:
        messages.error(request, _('Access denied.'))
        return redirect(obj)

    # Get correct form handler based on permissions
    form = get_upload_form(
        request.user, obj,
        request.POST, request.FILES
    )

    # Check form validity
    if not form.is_valid():
        messages.error(request, _('Please fix errors in the form.'))
        show_form_errors(request, form)
        return redirect(obj)

    # Create author name
    author = None
    if (request.user.has_perm('upload.authorship', obj) and
            form.cleaned_data['author_name'] != '' and
            form.cleaned_data['author_email'] != ''):
        author = '{0} <{1}>'.format(
            form.cleaned_data['author_name'],
            form.cleaned_data['author_email']
        )

    # Check for overwriting
    overwrite = False
    if request.user.has_perm('upload.overwrite', obj):
        overwrite = form.cleaned_data['upload_overwrite']

    # Do actual import
    try:
        not_found, skipped, accepted, total = obj.merge_upload(
            request,
            request.FILES['file'],
            overwrite,
            author,
            merge_header=form.cleaned_data['merge_header'],
            method=form.cleaned_data['method'],
            fuzzy=form.cleaned_data['fuzzy'],
        )
        if total == 0:
            message = _('No strings were imported from the uploaded file.')
        else:
            message = ungettext(
                'Processed {0} string from the uploaded files '
                '(skipped: {1}, not found: {2}, updated: {3}).',
                'Processed {0} strings from the uploaded files '
                '(skipped: {1}, not found: {2}, updated: {3}).',
                total
            ).format(total, skipped, not_found, accepted)
        if accepted == 0:
            messages.warning(request, message)
        else:
            messages.success(request, message)
    except Exception as error:
        messages.error(
            request, _('File content merge failed: %s') % force_text(error)
        )
        report_error(error, sys.exc_info(), request)

    return redirect(obj)
Пример #39
0
def home(request):
    """Home page of Weblate showing list of projects, stats
    and user links if logged in.
    """

    if 'show_set_password' in request.session:
        messages.warning(
            request,
            _(
                'You have activated your account, now you should set '
                'the password to be able to login next time.'
            )
        )
        return redirect('password')

    # This is used on Hosted Weblate to handle removed translation projects.
    # The redirect itself is done in the http server.
    if 'removed' in request.GET:
        messages.warning(
            request,
            _(
                'The project you were looking for has been removed, '
                'however you are welcome to contribute to other ones.'
            )
        )

    user = request.user

    user_translations = get_user_translations(request, user)

    suggestions = get_suggestions(request, user, user_translations)

    # Warn about not filled in username (usually caused by migration of
    # users from older system
    if user.is_authenticated and user.full_name == '':
        messages.warning(
            request,
            mark_safe('<a href="{0}">{1}</a>'.format(
                reverse('profile') + '#account',
                escape(_('Please set your full name in your profile.'))
            ))
        )

    usersubscriptions = None

    componentlists = list(ComponentList.objects.filter(show_dashboard=True))
    for componentlist in componentlists:
        componentlist.translations = prefetch_stats(
            user_translations.filter(
                component__in=componentlist.components.all()
            )
        )
    # Filter out component lists with translations
    # This will remove the ones where user doesn't have access to anything
    componentlists = [c for c in componentlists if c.translations]

    active_tab_id = user.profile.dashboard_view
    active_tab_slug = Profile.DASHBOARD_SLUGS.get(active_tab_id)
    if active_tab_id == Profile.DASHBOARD_COMPONENT_LIST:
        active_tab_slug = user.profile.dashboard_component_list.tab_slug()

    if user.is_authenticated:
        # Ensure ACL filtering applies (user could have been removed
        # from the project meanwhile)
        subscribed_projects = user.allowed_projects.filter(
            profile=user.profile
        )

        usersubscriptions = user_translations.filter(
            component__project__in=subscribed_projects
        )

        if user.profile.hide_completed:
            usersubscriptions = get_untranslated(usersubscriptions)
            user_translations = get_untranslated(user_translations)
            for componentlist in componentlists:
                componentlist.translations = get_untranslated(
                    componentlist.translations
                )
        usersubscriptions = prefetch_stats(usersubscriptions)

    return render(
        request,
        'index.html',
        {
            'allow_index': True,
            'suggestions': suggestions,
            'search_form': SiteSearchForm(),
            'usersubscriptions': usersubscriptions,
            'userlanguages': prefetch_stats(user_translations),
            'componentlists': componentlists,
            'all_componentlists': prefetch_stats(ComponentList.objects.all()),
            'active_tab_slug': active_tab_slug,
        }
    )
Пример #40
0
def search(base, unit_set, request):
    """Perform search or returns cached search results."""
    # Possible new search
    form = PositionSearchForm(user=request.user,
                              data=request.GET,
                              show_builder=False)

    # Process form
    form_valid = form.is_valid()
    if form_valid:
        cleaned_data = form.cleaned_data
        search_url = form.urlencode()
        search_query = form.get_search_query()
        name = form.get_name()
        search_items = form.items()
    else:
        cleaned_data = {}
        show_form_errors(request, form)
        search_url = ""
        search_query = ""
        name = ""
        search_items = ()

    search_result = {
        "form": form,
        "offset": cleaned_data.get("offset", 1),
    }
    session_key = f"search_{base.cache_key}_{search_url}"

    if (session_key in request.session and "offset" in request.GET
            and "items" in request.session[session_key]):
        search_result.update(request.session[session_key])
        return search_result

    allunits = unit_set.search(cleaned_data.get("q", "")).distinct()

    # Grab unit IDs
    unit_ids = list(
        allunits.order_by_request(cleaned_data).values_list("id", flat=True))

    # Check empty search results
    if not unit_ids:
        messages.warning(request, _("No string matched your search!"))
        return redirect(base)

    # Remove old search results
    cleanup_session(request.session)

    store_result = {
        "query": search_query,
        "url": search_url,
        "items": search_items,
        "key": session_key,
        "name": str(name),
        "ids": unit_ids,
        "ttl": int(time.time()) + 86400,
    }
    request.session[session_key] = store_result

    search_result.update(store_result)
    return search_result
Пример #41
0
def search(translation, request):
    """Perform search or returns cached search results."""
    # Possible new search
    search_form = SearchForm(request.GET)
    review_form = ReviewForm(request.GET)

    # Process form
    if 'date' in request.GET:
        if review_form.is_valid():
            form = review_form
        else:
            show_form_errors(request, review_form)
            # Use blank form
            form = SearchForm([])
            form.is_valid()
    elif search_form.is_valid():
        form = search_form
    else:
        show_form_errors(request, search_form)
        # Use blank form
        form = SearchForm([])
        form.is_valid()

    search_result = {
        'form': form,
        'offset': form.cleaned_data['offset'],
        'checksum': form.cleaned_data['checksum'],
    }
    search_url = form.urlencode()
    session_key = 'search_{0}_{1}'.format(translation.pk, search_url)

    if session_key in request.session and 'offset' in request.GET:
        search_result.update(request.session[session_key])
        return search_result

    if form.cleaned_data['type'] == 'review':
        allunits = translation.unit_set.review(form.cleaned_data['date'],
                                               request.user)
    else:
        allunits = translation.unit_set.search(
            translation,
            form.cleaned_data,
        )
        if form.cleaned_data['type'] == 'random':
            allunits = allunits[:25]

    search_query = form.get_search_query()
    name = form.get_name()

    # Grab unit IDs
    unit_ids = list(allunits.values_list('id', flat=True))

    # Check empty search results
    if len(unit_ids) == 0:
        messages.warning(request, _('No string matched your search!'))
        return redirect(translation)

    # Remove old search results
    cleanup_session(request.session)

    store_result = {
        'query': search_query,
        'url': search_url,
        'key': session_key,
        'name': force_text(name),
        'ids': unit_ids,
        'ttl': int(time.time()) + 86400,
    }
    request.session[session_key] = store_result

    search_result.update(store_result)
    return search_result
Пример #42
0
def upload_translation(request, project, component, lang):
    """Handling of translation uploads."""
    obj = get_translation(request, project, component, lang)

    if not request.user.has_perm("upload.perform", obj):
        raise PermissionDenied()

    # Check method and lock
    if obj.component.locked:
        messages.error(request, _("Access denied."))
        return redirect(obj)

    # Get correct form handler based on permissions
    form = get_upload_form(request.user, obj, request.POST, request.FILES)

    # Check form validity
    if not form.is_valid():
        messages.error(request, _("Please fix errors in the form."))
        show_form_errors(request, form)
        return redirect(obj)

    # Create author name
    author_name = None
    author_email = None
    if request.user.has_perm("upload.authorship", obj):
        author_name = form.cleaned_data["author_name"]
        author_email = form.cleaned_data["author_email"]

    # Check for overwriting
    conflicts = ""
    if request.user.has_perm("upload.overwrite", obj):
        conflicts = form.cleaned_data["conflicts"]

    # Do actual import
    try:
        not_found, skipped, accepted, total = obj.handle_upload(
            request,
            request.FILES["file"],
            conflicts,
            author_name,
            author_email,
            method=form.cleaned_data["method"],
            fuzzy=form.cleaned_data["fuzzy"],
        )
        if total == 0:
            message = _("No strings were imported from the uploaded file.")
        else:
            message = ngettext(
                "Processed {0} string from the uploaded files "
                "(skipped: {1}, not found: {2}, updated: {3}).",
                "Processed {0} strings from the uploaded files "
                "(skipped: {1}, not found: {2}, updated: {3}).",
                total,
            ).format(total, skipped, not_found, accepted)
        if accepted == 0:
            messages.warning(request, message)
        else:
            messages.success(request, message)
    except PluralFormsMismatch:
        messages.error(
            request,
            _("Plural forms in the uploaded file do not match current translation."
              ),
        )
    except Exception as error:
        messages.error(
            request,
            _("File upload has failed: %s") %
            str(error).replace(obj.component.full_path, ""),
        )
        report_error(cause="Upload error")

    return redirect(obj)
Пример #43
0
def import_message(request, count, message_none, message_ok):
    if count == 0:
        messages.warning(request, message_none)
    else:
        messages.success(request, message_ok % count)
Пример #44
0
def user_profile(request):
    profile = request.user.profile

    if not profile.language:
        profile.language = get_language()
        profile.save(update_fields=['language'])

    form_classes = [
        ProfileForm,
        SubscriptionForm,
        UserSettingsForm,
        DashboardSettingsForm,
        UserForm,
    ]
    forms = [form.from_request(request) for form in form_classes]
    forms.extend(get_notification_forms(request))
    all_backends = set(load_backends(social_django.utils.BACKENDS).keys())

    if request.method == 'POST':
        if all(form.is_valid() for form in forms):
            # Save changes
            for form in forms:
                if hasattr(form, 'audit'):
                    form.audit(request)
                form.save()

            # Change language
            set_lang(request, request.user.profile)

            # Redirect after saving (and possibly changing language)
            response = redirect_profile(request.POST.get('activetab'))

            # Set language cookie and activate new language (for message below)
            lang_code = profile.language
            response.set_cookie(settings.LANGUAGE_COOKIE_NAME, lang_code)
            translation.activate(lang_code)

            messages.success(request, _('Your profile has been updated.'))

            return response
    else:
        if not request.user.has_usable_password() and 'email' in all_backends:
            messages.warning(
                request, render_to_string('accounts/password-warning.html'))

    social = request.user.social_auth.all()
    social_names = [assoc.provider for assoc in social]
    new_backends = [
        x for x in all_backends if x == 'email' or x not in social_names
    ]
    license_projects = (Component.objects.filter(
        project__in=request.user.allowed_projects).exclude(
            license='').prefetch().order_by('license'))

    result = render(
        request,
        'accounts/profile.html',
        {
            'languagesform': forms[0],
            'subscriptionform': forms[1],
            'usersettingsform': forms[2],
            'dashboardsettingsform': forms[3],
            'userform': forms[4],
            'notification_forms': forms[5:],
            'all_forms': forms,
            'profile': profile,
            'title': _('User profile'),
            'licenses': license_projects,
            'associated': social,
            'new_backends': new_backends,
            'auditlog': request.user.auditlog_set.order()[:20],
        },
    )
    result.set_cookie(settings.LANGUAGE_COOKIE_NAME, profile.language)
    return result
Пример #45
0
def home(request):
    """Home page of Weblate showing list of projects, stats
    and user links if logged in.
    """

    if 'show_set_password' in request.session:
        messages.warning(
            request,
            _(
                'You have activated your account, now you should set '
                'the password to be able to login next time.'
            )
        )
        return redirect('password')

    user = request.user

    project_ids = Project.objects.get_acl_ids(user)

    translations_base = get_user_translations(user, project_ids)

    suggestions = get_suggestions(request, user, translations_base)

    # Warn about not filled in username (usually caused by migration of
    # users from older system
    if not user.is_anonymous and user.first_name == '':
        messages.warning(
            request,
            _('Please set your full name in your profile.')
        )

    # Some stats
    last_changes = Change.objects.last_changes(user)

    # dashboard_choices is dict with labels of choices as a keys
    dashboard_choices = dict(Profile.DASHBOARD_CHOICES)
    usersubscriptions = None

    components_by_language = translations_base.order_by(
        'subproject__priority',
        'subproject__project__name',
        'subproject__name'
    )

    userlanguages = components_by_language.filter(
        subproject__project_id__in=project_ids
    )

    componentlists = list(ComponentList.objects.all())
    for componentlist in componentlists:
        componentlist.translations = components_by_language.filter(
            subproject__in=componentlist.components.all()
        )

    active_tab_id = user.profile.dashboard_view
    active_tab_slug = Profile.DASHBOARD_SLUGS.get(active_tab_id)
    if active_tab_id == Profile.DASHBOARD_COMPONENT_LIST:
        clist = user.profile.dashboard_component_list
        active_tab_slug = clist.tab_slug()
        dashboard_choices[active_tab_id] = clist.name

    if request.user.is_authenticated:
        # Ensure ACL filtering applies (user could have been removed
        # from the project meanwhile)
        subscribed_projects = user.profile.subscriptions.filter(
            id__in=project_ids
        )

        last_changes = last_changes.filter(
            subproject__project__in=subscribed_projects
        )
        usersubscriptions = components_by_language.filter(
            subproject__project__in=subscribed_projects
        )

    return render(
        request,
        'index.html',
        {
            'allow_index': True,
            'suggestions': suggestions,
            'last_changes': last_changes[:10],
            'last_changes_url': '',
            'search_form': SiteSearchForm(),
            'usersubscriptions': usersubscriptions,
            'userlanguages': userlanguages,
            'componentlists': componentlists,
            'active_tab_slug': active_tab_slug,
            'active_tab_label': dashboard_choices.get(active_tab_id)
        }
    )