コード例 #1
0
ファイル: docs.py プロジェクト: Crowdbooster/sentry
def client_guide(request, project, platform):
    if platform not in PLATFORM_LIST:
        return HttpResponseRedirect(reverse('sentry'))

    key = ProjectKey.objects.get(user=request.user, project=project)
    dsn = key.get_dsn()
    dsn_public = key.get_dsn(public=True)

    template = 'sentry/partial/client_config/%s.html' % (platform,)

    context = {
        'platform': platform,
        'platform_title': platform.title(),
        'project': project,
        'dsn': dsn,
        'dsn_public': dsn_public,
        'page': 'client_help'
    }

    if request.is_ajax():
        return render_to_response(template, context, request)

    context['template'] = render_to_string(template, context, request)

    return render_to_response('sentry/projects/docs/client_config.html', context, request)
コード例 #2
0
ファイル: generic.py プロジェクト: Aaron1011/sentry
def dashboard(request, template='dashboard.html'):
    team_list = Team.objects.get_for_user(request.user)
    if not team_list:
        if can_create_teams(request.user):
            return HttpResponseRedirect(reverse('sentry-new-team'))

        return render_to_response('sentry/generic_error.html', {
            'title': _('No Membership'),
            'message': _('You are not a member of any teams in Sentry and you do not have access to create a new team.'),
        }, request)

    # This cookie gets automatically set by render_to_response
    if len(team_list) == 1:
        team = team_list.values()[0]
        return HttpResponseRedirect(reverse('sentry', args=[team.slug]))

    # these kinds of queries make people sad :(
    results = []
    for team in sorted(team_list.itervalues(), key=lambda x: x.name):
        project_list = list(team.project_set.filter(
            status=STATUS_VISIBLE,
        ).order_by('name')[:20])
        results.append((team, project_list))

    return render_to_response('sentry/select_team.html', {
        'team_list': results,
    }, request)
コード例 #3
0
ファイル: projects.py プロジェクト: cheekybastard/sentry
def new_project(request):
    from django.contrib.auth.models import User

    if not can_create_projects(request.user):
        return HttpResponseRedirect(reverse('sentry'))

    allow_create_teams = can_create_teams(request.user)
    team_list = Team.objects.get_for_user(request.user)

    if request.user.has_perm('sentry.can_add_project') and User.objects.all()[0:2] == 2:
        project_form_cls = NewProjectAdminForm
        project_initial = {
            'owner': request.user.username,
        }
    else:
        project_form_cls = NewProjectForm
        project_initial = {}

    if len(team_list) > 0:
        select_team_form = SelectTeamForm(team_list, request.POST or None, prefix='st')
    elif not allow_create_teams:
        return render_to_response('sentry/projects/cannot_create_teams.html', {}, request)
    else:
        select_team_form = None

    if allow_create_teams:
        new_team_form = NewTeamForm(request.POST or None, prefix='nt')
    else:
        new_team_form = None

    project_form = project_form_cls(request.POST or None, initial=project_initial, prefix='prj')

    is_new_team = new_team_form and new_team_form.is_valid()
    if is_new_team or not select_team_form:
        team_form = new_team_form
    else:
        team_form = select_team_form

    if project_form.is_valid() and team_form.is_valid():
        project = project_form.save(commit=False)
        if not project.owner:
            project.owner = request.user

        if is_new_team:
            team = new_team_form.save(commit=False)
            team.owner = project.owner
            team.save()
        else:
            team = select_team_form.cleaned_data['team']

        project.team = team
        project.save()

        return HttpResponseRedirect(reverse('sentry-get-started', args=[project.slug]))

    return render_to_response('sentry/projects/new.html', {
        'project_form': project_form,
        'select_team_form': select_team_form,
        'new_team_form': new_team_form,
    }, request)
コード例 #4
0
ファイル: accounts.py プロジェクト: Aaron1011/sentry
def recover(request):
    form = RecoverPasswordForm(request.POST or None)
    if form.is_valid():
        password_hash, created = LostPasswordHash.objects.get_or_create(
            user=form.cleaned_data['user']
        )
        if not password_hash.is_valid():
            created = True
            password_hash.date_added = timezone.now()
            password_hash.set_hash()

        if not created:
            form.errors['__all__'] = ['A password reset was already attempted for this account within the last 24 hours.']

    if form.is_valid():
        password_hash.send_recover_mail()

        return render_to_response('sentry/account/recover/sent.html', {
            'email': password_hash.user.email,
        }, request)

    context = {
        'form': form,
    }
    return render_to_response('sentry/account/recover/index.html', context, request)
コード例 #5
0
ファイル: accounts.py プロジェクト: DNIWE-Systems/sentry
def recover(request):
    form = RecoverPasswordForm(request.POST or None,
                               captcha=bool(request.session.get('needs_captcha')))
    if form.is_valid():
        password_hash, created = LostPasswordHash.objects.get_or_create(
            user=form.cleaned_data['user']
        )
        if not password_hash.is_valid():
            password_hash.date_added = timezone.now()
            password_hash.set_hash()

    if form.is_valid():
        password_hash.send_recover_mail()

        request.session.pop('needs_captcha', None)

        return render_to_response('sentry/account/recover/sent.html', {
            'email': password_hash.user.email,
        }, request)

    elif request.POST and not request.session.get('needs_captcha'):
        request.session['needs_captcha'] = 1
        form = RecoverPasswordForm(request.POST or None, captcha=True)
        form.errors.pop('captcha', None)

    context = {
        'form': form,
    }
    return render_to_response('sentry/account/recover/index.html', context, request)
コード例 #6
0
ファイル: accounts.py プロジェクト: sashahilton00/sentry
def recover(request):
    from sentry.app import ratelimiter

    if request.method == 'POST' and ratelimiter.is_limited(
        'accounts:recover:{}'.format(request.META['REMOTE_ADDR']),
        limit=5, window=60,  # 5 per minute should be enough for anyone
    ):
        return HttpResponse(
            'You have made too many password recovery attempts. Please try again later.',
            content_type='text/plain',
            status=429,
        )

    form = RecoverPasswordForm(request.POST or None)
    if form.is_valid():
        password_hash = send_password_recovery_mail(request, form.cleaned_data['user'])

        return render_to_response('sentry/account/recover/sent.html', {
            'email': password_hash.user.email,
        }, request)

    context = {
        'form': form,
    }
    return render_to_response('sentry/account/recover/index.html', context, request)
コード例 #7
0
ファイル: groups.py プロジェクト: adamsc64/sentry
def search(request, project):
    query = request.GET.get('q')

    if not query:
        return HttpResponseRedirect(reverse('sentry', args=[project.slug]))

    sort = request.GET.get('sort')
    if sort not in SEARCH_SORT_OPTIONS:
        sort = settings.SEARCH_DEFAULT_SORT_OPTION
    sort_label = SEARCH_SORT_OPTIONS[sort]

    result = event_re.match(query)
    if result:
        # Forward to message if it exists
        # event_id = result.group(1)
        checksum = result.group(2)
        event_list = Group.objects.filter(checksum=checksum)
        top_matches = event_list[:2]
        if len(top_matches) == 0:
            return render_to_response('sentry/invalid_message_id.html', {
                'project': project,
            }, request)
        elif len(top_matches) == 1:
            return HttpResponseRedirect(top_matches[0].get_absolute_url())
    elif uuid_re.match(query):
        # Forward to message if it exists
        try:
            message = Event.objects.get(project=project, event_id=query)
        except Event.DoesNotExist:
            return render_to_response('sentry/invalid_message_id.html', {
                'project': project,
            }, request)
        else:
            return HttpResponseRedirect(message.get_absolute_url())
    elif not settings.USE_SEARCH:
        event_list = Group.objects.none()
        # return render_to_response('sentry/invalid_message_id.html', {
        #         'project': project,
        #     }, request)
    else:
        documents = list(SearchDocument.objects.search(project, query, sort_by=sort))
        groups = Group.objects.in_bulk([d.group_id for d in documents])

        event_list = []
        for doc in documents:
            try:
                event_list.append(groups[doc.group_id])
            except KeyError:
                continue

    return render_to_response('sentry/search.html', {
        'project': project,
        'event_list': event_list,
        'query': query,
        'sort': sort,
        'sort_label': sort_label,
    }, request)
コード例 #8
0
ファイル: projects.py プロジェクト: nkabir/sentry
def new_project(request):
    from django.contrib.auth.models import User

    if not can_create_projects(request.user):
        return HttpResponseRedirect(reverse("sentry"))

    allow_create_teams = can_create_teams(request.user)
    team_list = Team.objects.get_for_user(request.user)

    if request.user.has_perm("sentry.can_add_project") and User.objects.all()[0:2] == 2:
        project_form_cls = NewProjectAdminForm
        project_initial = {"owner": request.user.username}
    else:
        project_form_cls = NewProjectForm
        project_initial = {}

    if len(team_list) > 0:
        select_team_form = SelectTeamForm(team_list, request.POST or None, prefix="st")
    elif not allow_create_teams:
        return render_to_response("sentry/projects/cannot_create_teams.html", {}, request)
    else:
        select_team_form = None

    if allow_create_teams:
        new_team_form = NewTeamForm(request.POST or None, prefix="nt")
    else:
        new_team_form = None

    project_form = project_form_cls(request.POST or None, initial=project_initial, prefix="prj")

    is_new_team = new_team_form and new_team_form.is_valid()
    if is_new_team or not select_team_form:
        team_form = new_team_form
    else:
        team_form = select_team_form

    if project_form.is_valid() and team_form.is_valid():
        project = project_form.save(commit=False)
        if not project.owner:
            project.owner = request.user
        if is_new_team:
            team = new_team_form.save(commit=False)
            team.owner = project.owner
            team.save()
        else:
            team = select_team_form.cleaned_data["team"]
        project.team = team
        project.save()
        return HttpResponseRedirect(reverse("sentry-project-client-help", args=[project.slug]))

    return render_to_response(
        "sentry/projects/new.html",
        {"project_form": project_form, "select_team_form": select_team_form, "new_team_form": new_team_form},
        request,
    )
コード例 #9
0
ファイル: teams.py プロジェクト: SmashingDevelopment/sentry
def accept_invite(request, member_id, token):
    try:
        pending_member = PendingTeamMember.objects.get(pk=member_id)
    except PendingTeamMember.DoesNotExist:
        return HttpResponseRedirect(reverse('sentry'))

    if pending_member.token != token:
        return HttpResponseRedirect(reverse('sentry'))

    team = pending_member.team

    project_list = list(team.project_set.filter(status=0))
    for project in project_list:
        project.team = team

    context = {
        'team': team,
        'team_owner': team.get_owner_name(),
        'project_list': project_list,
    }

    if not request.user.is_authenticated():
        # Show login or register form
        request.session['_next'] = request.get_full_path()
        request.session['can_register'] = True

        return render_to_response('sentry/teams/members/accept_invite_unauthenticated.html', context, request)

    if request.method == 'POST':
        form = AcceptInviteForm(request.POST)
    else:
        form = AcceptInviteForm()

    if form.is_valid():
        team.member_set.get_or_create(
            user=request.user,
            defaults={
                'type': pending_member.type,
            }
        )

        request.session.pop('can_register', None)

        pending_member.delete()

        messages.add_message(request, messages.SUCCESS,
            _('You have been added to the %r team.') % (team.name.encode('utf-8'),))

        return HttpResponseRedirect(reverse('sentry', args=[team.slug]))

    context['form'] = form

    return render_to_response('sentry/teams/members/accept_invite.html', context, request)
コード例 #10
0
ファイル: accounts.py プロジェクト: ollie314/sentry
def recover(request):
    form = RecoverPasswordForm(request.POST or None)
    if form.is_valid():
        password_hash = send_password_recovery_mail(form.cleaned_data['user'])

        return render_to_response('sentry/account/recover/sent.html', {
            'email': password_hash.user.email,
        }, request)

    context = {
        'form': form,
    }
    return render_to_response('sentry/account/recover/index.html', context, request)
コード例 #11
0
ファイル: generic.py プロジェクト: 755/sentry
def dashboard(request, template='dashboard.html'):
    team_list = Team.objects.get_for_user(request.user, with_projects=True)
    if not team_list:
        if can_create_teams(request.user):
            return HttpResponseRedirect(reverse('sentry-new-team'))

        return render_to_response('sentry/generic_error.html', {
            'title': _('No Membership'),
            'message': _('You are not a member of any teams in Sentry and you do not have access to create a new team.'),
        }, request)

    return render_to_response('sentry/select_team.html', {
        'team_list': team_list.values(),
    }, request)
コード例 #12
0
ファイル: accounts.py プロジェクト: hosmelq/sentry
def recover_confirm(request, user_id, hash, mode='recover'):
    try:
        password_hash = LostPasswordHash.objects.get(user=user_id, hash=hash)
        if not password_hash.is_valid():
            password_hash.delete()
            raise LostPasswordHash.DoesNotExist
        user = password_hash.user

    except LostPasswordHash.DoesNotExist:
        tpl = get_template('failure', mode)
        return render_to_response(tpl, {}, request)

    if request.method == 'POST':
        form = ChangePasswordRecoverForm(request.POST)
        if form.is_valid():
            with transaction.atomic():
                user.set_password(form.cleaned_data['password'])
                user.refresh_session_nonce(request)
                user.save()

                # Ugly way of doing this, but Django requires the backend be set
                user = authenticate(
                    username=user.username,
                    password=form.cleaned_data['password'],
                )

                # Only log the user in if there is no two-factor on the
                # account.
                if not Authenticator.objects.user_has_2fa(user):
                    login_user(request, user)

                password_hash.delete()

                capture_security_activity(
                    account=user,
                    type='password-changed',
                    actor=request.user,
                    ip_address=request.META['REMOTE_ADDR'],
                    send_email=True,
                )

            return login_redirect(request)
    else:
        form = ChangePasswordRecoverForm()

    tpl = get_template('confirm', mode)
    context = {'form': form}

    return render_to_response(tpl, context, request)
コード例 #13
0
ファイル: accounts.py プロジェクト: Kayle009/sentry
def recover(request):
    from sentry.app import ratelimiter

    extra = {
        'ip_address': request.META['REMOTE_ADDR'],
        'user_agent': request.META.get('HTTP_USER_AGENT'),
    }

    if request.method == 'POST' and ratelimiter.is_limited(
        u'accounts:recover:{}'.format(extra['ip_address']),
        limit=5,
        window=60,  # 5 per minute should be enough for anyone
    ):
        logger.warning('recover.rate-limited', extra=extra)

        return HttpResponse(
            'You have made too many password recovery attempts. Please try again later.',
            content_type='text/plain',
            status=429,
        )

    prefill = {'user': request.GET.get('email')}

    form = RecoverPasswordForm(request.POST or None, initial=prefill)
    extra['user_recovered'] = form.data.get('user')

    if form.is_valid():
        email = form.cleaned_data['user']
        if email:
            password_hash = LostPasswordHash.for_user(email)
            password_hash.send_email(request)

            extra['passwordhash_id'] = password_hash.id
            extra['user_id'] = password_hash.user_id

            logger.info('recover.sent', extra=extra)

        tpl = 'sentry/account/recover/sent.html'
        context = {'email': email}

        return render_to_response(tpl, context, request)

    if form._errors:
        logger.warning('recover.error', extra=extra)

    tpl = 'sentry/account/recover/index.html'
    context = {'form': form}

    return render_to_response(tpl, context, request)
コード例 #14
0
ファイル: accounts.py プロジェクト: rnoldo/sentry
def recover(request):
    form = RecoverPasswordForm(request.POST or None)
    if form.is_valid():
        password_hash, created = LostPasswordHash.objects.get_or_create(user=form.cleaned_data["user"])
        if not password_hash.is_valid():
            password_hash.date_added = timezone.now()
            password_hash.set_hash()

    if form.is_valid():
        password_hash.send_recover_mail()

        return render_to_response("sentry/account/recover/sent.html", {"email": password_hash.user.email}, request)

    context = {"form": form}
    return render_to_response("sentry/account/recover/index.html", context, request)
コード例 #15
0
ファイル: groups.py プロジェクト: Kronuz/django-sentry
def search(request, project):
    query = request.GET.get('q')

    if query:
        result = event_re.match(query)
        if result:
            # Forward to message if it exists
            # event_id = result.group(1)
            checksum = result.group(2)
            event_list = Group.objects.filter(checksum=checksum)
            top_matches = event_list[:2]
            if len(top_matches) == 0:
                return render_to_response('sentry/invalid_message_id.html', {
                    'project': project,
                }, request)
            elif len(top_matches) == 1:
                return HttpResponseRedirect(top_matches[0].get_absolute_url())
        elif uuid_re.match(query):
            # Forward to message if it exists
            try:
                message = Event.objects.get(event_id=query)
            except Event.DoesNotExist:
                return render_to_response('sentry/invalid_message_id.html', {
                    'project': project,
                }, request)
            else:
                return HttpResponseRedirect(message.get_absolute_url())
        else:
            return render_to_response('sentry/invalid_message_id.html', {
                    'project': project,
                }, request)
    else:
        event_list = Group.objects.none()

    sort = request.GET.get('sort')
    if sort == 'date':
        event_list = event_list.order_by('-last_seen')
    elif sort == 'new':
        event_list = event_list.order_by('-first_seen')
    else:
        sort = 'relevance'

    return render_to_response('sentry/search.html', {
        'project': project,
        'event_list': event_list,
        'query': query,
        'sort': sort,
    }, request)
コード例 #16
0
ファイル: teams.py プロジェクト: SmashingDevelopment/sentry
def create_new_team(request):
    if not can_create_teams(request.user):
        return missing_perm(request, Permissions.ADD_TEAM)

    if request.user.has_perm('sentry.can_add_team'):
        form_cls = NewTeamAdminForm
        initial = {
            'owner': request.user.username,
        }
    else:
        form_cls = NewTeamForm
        initial = {}

    form = form_cls(request.POST or None, initial=initial)
    if form.is_valid():
        team = form.save(commit=False)
        if not team.owner_id:
            team.owner = request.user
        team.save()
        return HttpResponseRedirect(reverse('sentry-new-project', args=[team.slug]))

    context = csrf(request)
    context.update({
        'form': form,
    })

    return render_to_response('sentry/teams/new.html', context, request)
コード例 #17
0
ファイル: teams.py プロジェクト: tsesci/sentry
def edit_team_member(request, team, member_id):
    try:
        member = team.member_set.get(pk=member_id)
    except TeamMember.DoesNotExist:
        return HttpResponseRedirect(reverse('sentry-manage-team', args=[team.slug]))

    if not can_edit_team_member(request.user, member):
        return HttpResponseRedirect(reverse('sentry'))

    form = EditTeamMemberForm(team, request.POST or None, instance=member)
    if form.is_valid():
        member = form.save(commit=True)

        messages.add_message(request, messages.SUCCESS,
            _('Changes to your team member were saved.'))

        return HttpResponseRedirect(request.path)

    context = csrf(request)
    context.update({
        'page': 'members',
        'member': member,
        'team': team,
        'form': form,
        'SECTION': 'team',
        'SUBSECTION': 'members',
    })

    return render_to_response('sentry/teams/members/edit.html', context, request)
コード例 #18
0
ファイル: projects.py プロジェクト: Fashiolista/sentry
def remove_project(request, project):
    if not can_remove_project(request.user, project):
        return HttpResponseRedirect(reverse('sentry'))

    project_list = filter(lambda x: x != project, get_project_list(request.user).itervalues())

    form = RemoveProjectForm(request.user, project_list, request.POST or None)

    if form.is_valid():
        removal_type = form.cleaned_data['removal_type']
        if removal_type == '1':
            project.delete()
        elif removal_type == '2':
            new_project = form.cleaned_data['project']
            project.merge_to(new_project)
        elif removal_type == '3':
            project.update(status=1)
        else:
            raise ValueError(removal_type)

        return HttpResponseRedirect(reverse('sentry-project-list'))

    context = csrf(request)
    context.update({
        'form': form,
        'project': project,
    })

    return render_to_response('sentry/projects/remove.html', context, request)
コード例 #19
0
ファイル: teams.py プロジェクト: tsesci/sentry
def remove_team_member(request, team, member_id):
    try:
        member = team.member_set.get(pk=member_id)
    except TeamMember.DoesNotExist:
        return HttpResponseRedirect(reverse('sentry-manage-team', args=[team.slug]))

    if member.user == team.owner:
        return HttpResponseRedirect(reverse('sentry-manage-team', args=[team.slug]))

    if not can_remove_team_member(request.user, member):
        return HttpResponseRedirect(reverse('sentry'))

    if request.POST:
        member.delete()

        return HttpResponseRedirect(reverse('sentry-manage-team', args=[team.slug]))

    context = csrf(request)
    context.update({
        'page': 'members',
        'member': member,
        'team': team,
        'SECTION': 'team',
        'SUBSECTION': 'members',
    })

    return render_to_response('sentry/teams/members/remove.html', context, request)
コード例 #20
0
ファイル: decorators.py プロジェクト: TracyWebTech/sentry
 def _wrapped(request, *args, **kwargs):
     if not request.user.is_authenticated():
         request.session['_next'] = request.get_full_path()
         return HttpResponseRedirect(get_login_url())
     if not request.user.has_perm(perm):
         return render_to_response('sentry/missing_permissions.html', status=400)
     return func(request, *args, **kwargs)
コード例 #21
0
ファイル: generic.py プロジェクト: WhoTrades/sentry
 def render_to_response(self, context, **response_kwargs):
     return render_to_response(
         request=self.request,
         template=self.get_template_names(),
         context=context,
         **response_kwargs
     )
コード例 #22
0
ファイル: projects.py プロジェクト: Caramel/sentry
def manage_project(request, team, project):
    result = plugins.first('has_perm', request.user, 'edit_project', project)
    if result is False and not request.user.has_perm('sentry.can_change_project'):
        return HttpResponseRedirect(reverse('sentry'))

    team_list = Team.objects.get_for_user(project.owner or request.user, MEMBER_OWNER)

    form = EditProjectForm(request, team_list, request.POST or None, instance=project, initial={
        'origins': '\n'.join(project.get_option('sentry:origins', None) or []),
        'owner': project.owner,
        'resolve_age': int(project.get_option('sentry:resolve_age', 0)),
    })

    if form.is_valid():
        project = form.save()
        project.update_option('sentry:origins', form.cleaned_data.get('origins') or [])
        project.update_option('sentry:resolve_age', form.cleaned_data.get('resolve_age'))
        messages.add_message(
            request, messages.SUCCESS,
            _('Changes to your project were saved.'))

        return HttpResponseRedirect(reverse('sentry-manage-project', args=[team.slug, project.slug]))

    context = csrf(request)
    context.update({
        'team': team,
        'can_remove_project': can_remove_project(request.user, project),
        'page': 'details',
        'form': form,
        'project': project,
        'SECTION': 'team',
        'SUBSECTION': 'projects'
    })

    return render_to_response('sentry/projects/manage.html', context, request)
コード例 #23
0
ファイル: accounts.py プロジェクト: dz0ny/sentry
def notification_settings(request):
    forms = []
    for plugin in plugins.all():
        for form in safe_execute(plugin.get_notification_forms) or ():
            form = safe_execute(form, plugin, request.user, request.POST or None)
            if not form:
                continue
            helper = FormHelper()
            helper.form_tag = False
            forms.append((form, helper))

    # Ensure our form comes first
    helper = FormHelper()
    helper.form_tag = False
    forms = [
        (NotificationSettingsForm(request.user, request.POST or None), helper),
    ] + forms

    if request.POST:
        if all(f.is_valid() for f, h in forms):
            for form, helper in forms:
                form.save()
            response = HttpResponseRedirect(reverse('sentry-account-settings-notifications') + '?success=1')
            return response

    context = csrf(request)
    context.update({
        'forms': forms,
        'page': 'notifications',
    })
    return render_to_response('sentry/account/notifications.html', context, request)
コード例 #24
0
ファイル: projects.py プロジェクト: Caramel/sentry
def get_started(request, team, project):
    return render_to_response('sentry/get_started.html', {
        'project': project,
        'team': project.team,
        'SECTION': 'team',
        'SUBSECTION': 'projects'
    }, request)
コード例 #25
0
ファイル: projects.py プロジェクト: Caramel/sentry
def remove_project(request, team, project):
    if not can_remove_project(request.user, project):
        return HttpResponseRedirect(reverse('sentry'))

    project_list = filter(lambda x: x != project, Project.objects.get_for_user(request.user))

    form = RemoveProjectForm(request.user, project_list, request.POST or None)

    if form.is_valid():
        removal_type = form.cleaned_data['removal_type']
        if removal_type == '1':
            project.delete()
        elif removal_type == '2':
            new_project = form.cleaned_data['project']
            project.merge_to(new_project)
        elif removal_type == '3':
            project.update(status=1)
        else:
            raise ValueError(removal_type)

        return HttpResponseRedirect(reverse('sentry-manage-team-projects', args=[project.team.slug]))

    context = csrf(request)
    context.update({
        'team': team,
        'form': form,
        'project': project,
        'SECTION': 'team',
        'SUBSECTION': 'projects'
    })

    return render_to_response('sentry/projects/remove.html', context, request)
コード例 #26
0
ファイル: projects.py プロジェクト: Caramel/sentry
def manage_project_tags(request, team, project):
    tag_list = filter(
        lambda x: not x.startswith('sentry:'),
        TagKey.objects.all_keys(project))

    if tag_list:
        form = ProjectTagsForm(project, tag_list, request.POST or None)
    else:
        form = None

    if form and form.is_valid():
        form.save()

        messages.add_message(
            request, messages.SUCCESS,
            _('Your settings were saved successfully.'))

        return HttpResponseRedirect(reverse('sentry-manage-project-tags', args=[project.team.slug, project.slug]))

    context = {
        'team': team,
        'tag_list': tag_list,
        'page': 'tags',
        'project': project,
        'form': form,
        'SECTION': 'team',
        'SUBSECTION': 'projects'
    }
    return render_to_response('sentry/projects/manage_tags.html', context, request)
コード例 #27
0
ファイル: projects.py プロジェクト: Caramel/sentry
def manage_plugins(request, team, project):
    result = plugins.first('has_perm', request.user, 'configure_project_plugin', project)
    if result is False and not request.user.has_perm('sentry.can_change_project'):
        return HttpResponseRedirect(reverse('sentry'))

    if request.POST:
        enabled = set(request.POST.getlist('plugin'))
        for plugin in plugins.all():
            if plugin.can_enable_for_projects():
                plugin.set_option('enabled', plugin.slug in enabled, project)

        messages.add_message(
            request, messages.SUCCESS,
            _('Your settings were saved successfully.'))

        return HttpResponseRedirect(request.path)

    context = csrf(request)
    context.update({
        'team': team,
        'page': 'plugins',
        'project': project,
        'SECTION': 'team',
        'SUBSECTION': 'projects'
    })

    return render_to_response('sentry/projects/plugins/list.html', context, request)
コード例 #28
0
ファイル: projects.py プロジェクト: Fashiolista/sentry
def configure_project_plugin(request, project, slug):
    try:
        plugin = plugins.get(slug)
    except KeyError:
        return HttpResponseRedirect(reverse('sentry-manage-project', args=[project.slug]))

    if not plugin.is_enabled(project):
        return HttpResponseRedirect(reverse('sentry-manage-project', args=[project.slug]))

    result = plugins.first('has_perm', request.user, 'configure_project_plugin', project, plugin)
    if result is False and not request.user.is_superuser:
        return HttpResponseRedirect(reverse('sentry'))

    form = plugin.project_conf_form
    if form is None:
        return HttpResponseRedirect(reverse('sentry-manage-project', args=[project.slug]))

    action, view = plugin_config(plugin, project, request)
    if action == 'redirect':
        return HttpResponseRedirect(request.path + '?success=1')

    context = csrf(request)
    context.update({
        'page': 'plugin',
        'title': plugin.get_title(),
        'view': view,
        'project': project,
        'plugin': plugin,
    })

    return render_to_response('sentry/projects/plugins/configure.html', context, request)
コード例 #29
0
ファイル: teams.py プロジェクト: SmashingDevelopment/sentry
def render_with_team_context(team, template, context, request=None):
    context.update({
        'team': team,
        'SECTION': 'team',
    })

    return render_to_response(template, context, request)
コード例 #30
0
ファイル: projects.py プロジェクト: Caramel/sentry
def manage_project_keys(request, team, project):
    result = plugins.first('has_perm', request.user, 'edit_project', project)
    if result is False and not request.user.has_perm('sentry.can_change_project'):
        return HttpResponseRedirect(reverse('sentry'))

    key_list = list(ProjectKey.objects.filter(
        project=project,
    ).select_related('user', 'user_added').order_by('-id'))

    for key in key_list:
        key.project = project
        key.can_remove = can_remove_project_key(request.user, key),

    context = csrf(request)
    context.update({
        'team': team,
        'page': 'keys',
        'project': project,
        'key_list': key_list,
        'can_add_key': can_add_project_key(request.user, project),
        'SECTION': 'team',
        'SUBSECTION': 'projects'
    })

    return render_to_response('sentry/projects/keys.html', context, request)
コード例 #31
0
    def handle(self, request: Request, signed_params: str) -> Response:
        try:
            params = unsign(signed_params)
        except (SignatureExpired, BadSignature):
            return render_to_response(
                "sentry/integrations/slack/expired-link.html",
                request=request,
            )

        organization, integration, idp = get_identity_or_404(
            ExternalProviders.SLACK,
            request.user,
            integration_id=params["integration_id"],
            organization_id=params["organization_id"],
        )
        channel_name = params["channel_name"]
        channel_id = params["channel_id"]

        external_teams = ExternalActor.objects.filter(
            organization=organization,
            integration=integration,
            provider=ExternalProviders.SLACK.value,
            external_name=channel_name,
            external_id=channel_id,
        )
        if len(external_teams) == 0:
            return render_error_page(request,
                                     body_text="HTTP 404: Team not found")

        team = external_teams[0].actor.resolve()

        if request.method != "POST":
            return render_to_response(
                "sentry/integrations/slack/unlink-team.html",
                request=request,
                context={
                    "team": team,
                    "channel_name": channel_name,
                    "provider": integration.get_provider(),
                },
            )

        if not Identity.objects.filter(
                idp=idp, external_id=params["slack_id"]).exists():
            return render_error_page(
                request, body_text="HTTP 403: User identity does not exist")

        # Someone may have accidentally added multiple teams so unlink them all.
        for external_team in external_teams:
            external_team.delete()

        return render_to_response(
            "sentry/integrations/slack/unlinked-team.html",
            request=request,
            context={
                "heading_text": SUCCESS_UNLINKED_TEAM_TITLE,
                "body_text":
                SUCCESS_UNLINKED_TEAM_MESSAGE.format(team=team.slug),
                "channel_id": channel_id,
                "team_id": integration.external_id,
            },
        )
コード例 #32
0
ファイル: views.py プロジェクト: xsbchen/sentry-plugins
 def get_response(self, template, context=None):
     context = context or self.get_context()
     res = render_to_response(template, context, self.request)
     res['X-Frame-Options'] = 'ALLOW-FROM %s' % self.request.GET['xdm_e']
     return res
コード例 #33
0
ファイル: pipeline.py プロジェクト: commonlims/commonlims
 def _dialog_response(self, data, success):
     context = {'payload': {'success': success, 'data': data}}
     return render_to_response('sentry/integrations/dialog-complete.html',
                               context, self.request)
コード例 #34
0
    def dispatch(self, request):
        try:
            event_id = request.GET["eventId"]
        except KeyError:
            return self._smart_response(
                request, {"eventId": "Missing or invalid parameter."},
                status=400)

        normalized_event_id = normalize_event_id(event_id)
        if normalized_event_id:
            event_id = normalized_event_id
        elif event_id:
            return self._smart_response(
                request, {"eventId": "Missing or invalid parameter."},
                status=400)

        key = self._get_project_key(request)
        if not key:
            return self._smart_response(
                request, {"dsn": "Missing or invalid parameter."}, status=404)

        origin = self._get_origin(request)
        if not is_valid_origin(origin, key.project):
            return self._smart_response(request, status=403)

        if request.method == "OPTIONS":
            return self._smart_response(request)

        # customization options
        options = DEFAULT_OPTIONS.copy()
        for name in options.keys():
            if name in request.GET:
                options[name] = str(request.GET[name])

        # TODO(dcramer): since we can't use a csrf cookie we should at the very
        # least sign the request / add some kind of nonce
        initial = {
            "name": request.GET.get("name"),
            "email": request.GET.get("email")
        }

        form = UserReportForm(
            request.POST if request.method == "POST" else None,
            initial=initial)
        if form.is_valid():
            # TODO(dcramer): move this to post to the internal API
            report = form.save(commit=False)
            report.project_id = key.project_id
            report.event_id = event_id

            event = eventstore.get_event_by_id(report.project_id,
                                               report.event_id)

            if event is not None:
                report.environment_id = event.get_environment().id
                report.group_id = event.group_id

            try:
                with atomic_transaction(using=router.db_for_write(UserReport)):
                    report.save()
            except IntegrityError:
                # There was a duplicate, so just overwrite the existing
                # row with the new one. The only way this ever happens is
                # if someone is messing around with the API, or doing
                # something wrong with the SDK, but this behavior is
                # more reasonable than just hard erroring and is more
                # expected.
                UserReport.objects.filter(project_id=report.project_id,
                                          event_id=report.event_id).update(
                                              name=report.name,
                                              email=report.email,
                                              comments=report.comments,
                                              date_added=timezone.now(),
                                          )

            else:
                if report.group_id:
                    report.notify()

            user_feedback_received.send(
                project=Project.objects.get(id=report.project_id),
                sender=self,
            )

            return self._smart_response(request)
        elif request.method == "POST":
            return self._smart_response(request, {"errors": dict(form.errors)},
                                        status=400)

        show_branding = (ProjectOption.objects.get_value(
            project=key.project, key="feedback:branding", default="1") == "1")

        template = render_to_string(
            "sentry/error-page-embed.html",
            context={
                "form": form,
                "show_branding": show_branding,
                "title": options["title"],
                "subtitle": options["subtitle"],
                "subtitle2": options["subtitle2"],
                "name_label": options["labelName"],
                "email_label": options["labelEmail"],
                "comments_label": options["labelComments"],
                "submit_label": options["labelSubmit"],
                "close_label": options["labelClose"],
            },
        )

        context = {
            "endpoint":
            mark_safe("*/" +
                      json.dumps(absolute_uri(request.get_full_path())) +
                      ";/*"),
            "template":
            mark_safe("*/" + json.dumps(template) + ";/*"),
            "strings":
            mark_safe("*/" + json.dumps_htmlsafe(
                {
                    "generic_error": str(options["errorGeneric"]),
                    "form_error": str(options["errorFormEntry"]),
                    "sent_message": str(options["successMessage"]),
                }) + ";/*"),
        }

        return render_to_response("sentry/error-page-embed.js",
                                  context,
                                  request,
                                  content_type="text/javascript")
コード例 #35
0
    def handle(self, request, signed_params):
        params = unsign(signed_params.encode("ascii", errors="ignore"))

        organization, integration, idp = get_identity(
            request.user, params["organization_id"], params["integration_id"])

        if request.method != "POST":
            return render_to_response(
                "sentry/auth-link-identity.html",
                request=request,
                context={
                    "organization": organization,
                    "provider": integration.get_provider()
                },
            )

        # TODO(epurkhiser): We could do some fancy slack querying here to
        # render a nice linking page with info about the user their linking.

        # Link the user with the identity. Handle the case where the user is linked to a
        # different identity or the identity is linked to a different user.
        defaults = {
            "status": IdentityStatus.VALID,
            "date_verified": timezone.now()
        }
        try:
            identity, created = Identity.objects.get_or_create(
                idp=idp,
                user=request.user,
                external_id=params["slack_id"],
                defaults=defaults)
            if not created:
                identity.update(**defaults)
        except IntegrityError:
            Identity.reattach(idp, params["slack_id"], request.user, defaults)

        payload = {
            "replace_original":
            False,
            "response_type":
            "ephemeral",
            "text":
            "Your Slack identity has been linked to your Sentry account. You're good to go!",
        }

        client = SlackClient()
        try:
            client.post(params["response_url"], data=payload, json=True)
        except ApiError as e:
            message = six.text_type(e)
            # If the user took their time to link their slack account, we may no
            # longer be able to respond, and we're not guaranteed able to post into
            # the channel. Ignore Expired url errors.
            #
            # XXX(epurkhiser): Yes the error string has a space in it.
            if message != "Expired url":
                logger.error("slack.link-notify.response-error",
                             extra={"error": message})

        return render_to_response(
            "sentry/slack-linked.html",
            request=request,
            context={
                "channel_id": params["channel_id"],
                "team_id": integration.external_id
            },
        )
コード例 #36
0
ファイル: accounts.py プロジェクト: yeliex/sentry
def expired(request, user):
    password_hash = send_password_recovery_mail(user)
    return render_to_response('sentry/account/recover/expired.html', {
        'email': password_hash.user.email,
    }, request)
コード例 #37
0
 def error(self, message):
     context = {"error": message}
     return render_to_response("sentry/pipeline-error.html", context,
                               self.request)
コード例 #38
0
 def render_to_response(self, context, **response_kwargs):
     return render_to_response(request=self.request,
                               template=self.get_template_names(),
                               context=context,
                               **response_kwargs)
コード例 #39
0
def get_started(request, project):
    return render_to_response('sentry/get_started.html', {
        'project': project,
    }, request)
コード例 #40
0
def show_emails(request):
    user = request.user
    emails = user.emails.all()
    email_form = EmailForm(user, request.POST or None)
    primary_email = UserEmail.get_primary_email(user)
    alt_emails = emails.exclude(email=primary_email.email)

    if 'remove' in request.POST:
        email = request.POST.get('email')
        del_email = UserEmail.objects.filter(user=user, email=email)
        del_email.delete()
        logger.info('user.email.remove',
                    extra={
                        'user_id': user.id,
                        'ip_address': request.META['REMOTE_ADDR'],
                        'email': email,
                    })
        user.clear_lost_passwords()
        return HttpResponseRedirect(request.path)

    if 'primary' in request.POST:
        new_primary = request.POST['new_primary_email'].lower().strip()

        if User.objects.filter(
                Q(email__iexact=new_primary)
                | Q(username__iexact=new_primary)).exclude(
                    id=user.id).exists():
            messages.add_message(
                request, messages.ERROR,
                _("That email is already in use for another user"))

        elif new_primary != user.email:

            # update notification settings for those set to primary email with new primary email
            alert_email = UserOption.objects.get_value(user=user,
                                                       key='alert_email')

            if alert_email == user.email:
                UserOption.objects.set_value(user=user,
                                             key='alert_email',
                                             value=new_primary)
            options = UserOption.objects.filter(user=user, key='mail:email')
            for option in options:
                if option.value != user.email:
                    continue
                option.value = new_primary
                option.save()

            has_new_username = user.email == user.username

            user.email = new_primary

            msg = _('Your settings were saved')
            messages.add_message(request, messages.SUCCESS, msg)

            if has_new_username and not User.objects.filter(
                    username__iexact=new_primary).exists():
                user.username = user.email
            user.save()
        user.clear_lost_passwords()
        return HttpResponseRedirect(request.path)

    if email_form.is_valid():

        alternative_email = email_form.cleaned_data['alt_email'].lower().strip(
        )

        # check if this alternative email already exists for user
        if alternative_email and not UserEmail.objects.filter(
                user=user, email__iexact=alternative_email).exists():
            # create alternative email for user
            try:
                with transaction.atomic():
                    new_email = UserEmail.objects.create(
                        user=user, email=alternative_email)
            except IntegrityError:
                pass
            else:
                new_email.set_hash()
                new_email.save()
                user.send_confirm_email_singular(new_email)
                # Update newsletter subscription and mark as unverified
                newsletter.update_subscription(
                    user=user,
                    verified=False,
                )

                logger.info('user.email.add',
                            extra={
                                'user_id': user.id,
                                'ip_address': request.META['REMOTE_ADDR'],
                                'email': new_email.email,
                            })
                msg = _('A confirmation email has been sent to %s.'
                        ) % new_email.email
                messages.add_message(request, messages.SUCCESS, msg)

        user.clear_lost_passwords()

        messages.add_message(request, messages.SUCCESS,
                             _('Your settings were saved.'))
        return HttpResponseRedirect(request.path)

    context = csrf(request)
    context.update({
        'email_form': email_form,
        'primary_email': primary_email,
        'alt_emails': alt_emails,
        'page': 'emails',
        'AUTH_PROVIDERS': auth.get_auth_providers(),
        'has_newsletters': newsletter.is_enabled,
    })
    return render_to_response('sentry/account/emails.html', context, request)
コード例 #41
0
                          (settings.EMAIL_SUBJECT_PREFIX, ),
                          body,
                          settings.SERVER_EMAIL, [user.email],
                          fail_silently=False)
            except Exception, e:
                logger = logging.getLogger('sentry.mail.errors')
                logger.exception(e)

        return HttpResponseRedirect(reverse('sentry-admin-users'))

    context = {
        'form': form,
    }
    context.update(csrf(request))

    return render_to_response('sentry/admin/users/new.html', context, request)


@requires_admin
@csrf_protect
def edit_user(request, user_id):
    if not request.user.has_perm('auth.can_change_user'):
        return HttpResponseRedirect(reverse('sentry'))

    try:
        user = User.objects.get(pk=user_id)
    except User.DoesNotExist:
        return HttpResponseRedirect(reverse('sentry-admin-users'))

    form = ChangeUserForm(request.POST or None, instance=user)
    if form.is_valid():
コード例 #42
0
def new_project(request):
    from django.contrib.auth.models import User

    if not can_create_projects(request.user):
        return HttpResponseRedirect(reverse('sentry'))

    allow_create_teams = can_create_teams(request.user)
    team_list = Team.objects.get_for_user(request.user)

    if request.user.has_perm(
            'sentry.can_add_project') and User.objects.all()[0:2] == 2:
        project_form_cls = NewProjectAdminForm
        project_initial = {
            'owner': request.user.username,
        }
    else:
        project_form_cls = NewProjectForm
        project_initial = {}

    if len(team_list) > 0:
        select_team_form = SelectTeamForm(team_list,
                                          request.POST or None,
                                          prefix='st')
    elif not allow_create_teams:
        return render_to_response('sentry/projects/cannot_create_teams.html',
                                  {}, request)
    else:
        select_team_form = None

    if allow_create_teams:
        new_team_form = NewTeamForm(request.POST or None, prefix='nt')
    else:
        new_team_form = None

    project_form = project_form_cls(request.POST or None,
                                    initial=project_initial,
                                    prefix='prj')

    is_new_team = new_team_form and new_team_form.is_valid()
    if is_new_team or not select_team_form:
        team_form = new_team_form
    else:
        team_form = select_team_form

    if project_form.is_valid() and team_form.is_valid():
        project = project_form.save(commit=False)
        if not project.owner:
            project.owner = request.user

        if is_new_team:
            team = new_team_form.save(commit=False)
            team.owner = project.owner
            team.save()
        else:
            team = select_team_form.cleaned_data['team']

        project.team = team
        project.save()

        if project.platform not in (None, 'other'):
            return HttpResponseRedirect(
                reverse('sentry-docs-client',
                        args=[project.slug, project.platform]))
        return HttpResponseRedirect(
            reverse('sentry-get-started', args=[project.slug]))

    return render_to_response(
        'sentry/projects/new.html', {
            'project_form': project_form,
            'select_team_form': select_team_form,
            'new_team_form': new_team_form,
        }, request)
コード例 #43
0
def expired(request, user):
    password_hash = LostPasswordHash.for_user(user)
    password_hash.send_email(request)

    context = {"email": password_hash.user.email}
    return render_to_response("sentry/account/recover/expired.html", context, request)
コード例 #44
0
ファイル: mail.py プロジェクト: yuvrajm/sentry
 def render(self, request):
     return render_to_response('sentry/debug/mail/preview.html', {
         'preview': self,
         'format': request.GET.get('format'),
     })
コード例 #45
0
ファイル: pipeline.py プロジェクト: veekram/sentry
 def _dialog_response(self, data, success):
     context = {"payload": {"success": success, "data": data}}
     return render_to_response("sentry/integrations/dialog-complete.html",
                               context, self.request)
コード例 #46
0
ファイル: accounts.py プロジェクト: splaroche/sentry
def notification_settings(request):
    settings_form = NotificationSettingsForm(request.user, request.POST
                                             or None)

    # TODO(dcramer): this is an extremely bad pattern and we need a more optimal
    # solution for rendering this (that ideally plays well with the org data)
    project_list = []
    organization_list = Organization.objects.get_for_user(user=request.user, )
    for organization in organization_list:
        team_list = Team.objects.get_for_user(
            user=request.user,
            organization=organization,
        )
        for team in team_list:
            project_list.extend(
                Project.objects.get_for_user(
                    user=request.user,
                    team=team,
                ))

    project_forms = [
        (project,
         ProjectEmailOptionsForm(project,
                                 request.user,
                                 request.POST or None,
                                 prefix='project-%s' % (project.id, )))
        for project in sorted(project_list,
                              key=lambda x: (x.team.name, x.name))
    ]

    ext_forms = []
    for plugin in plugins.all():
        for form in safe_execute(plugin.get_notification_forms) or ():
            form = safe_execute(form,
                                plugin,
                                request.user,
                                request.POST or None,
                                prefix=plugin.slug)
            if not form:
                continue
            ext_forms.append(form)

    if request.POST:
        all_forms = list(
            itertools.chain([settings_form], ext_forms,
                            (f for _, f in project_forms)))
        if all(f.is_valid() for f in all_forms):
            for form in all_forms:
                form.save()
            messages.add_message(request, messages.SUCCESS,
                                 'Your settings were saved.')
            return HttpResponseRedirect(request.path)

    context = csrf(request)
    context.update({
        'settings_form': settings_form,
        'project_forms': project_forms,
        'ext_forms': ext_forms,
        'page': 'notifications',
        'AUTH_PROVIDERS': get_auth_providers(),
    })
    return render_to_response('sentry/account/notifications.html', context,
                              request)
コード例 #47
0
def respond(template, organization, request, context=None, status=200):
    default_context = {"organization": organization}
    if context:
        default_context.update(context)

    return render_to_response(template, default_context, request, status=status)
コード例 #48
0
ファイル: uihook.py プロジェクト: w7374520/sentry
    def dispatch(self, request):
        if request.method == "OPTIONS":
            return HttpResponse(status=200)
        if request.method != "POST":
            return HttpResponse(status=405)
        body_unicode = request.body.decode("utf-8")
        body = json.loads(body_unicode)
        configuration_id = body["configurationId"]
        user_id = body["user"]["id"]
        team_id = body["teamId"]
        external_id = team_id or user_id
        try:
            integration = Integration.objects.get(external_id=external_id,
                                                  provider="vercel",
                                                  status=ObjectStatus.ACTIVE)
        except Integration.DoesNotExist:
            logger.info(
                "vercel.integration.does-not-exist",
                extra={"external_id": external_id},
            )
            return HttpResponse("The requested integration does not exist.")
        try:
            organization = Organization.objects.get(
                id=integration.metadata["configurations"][configuration_id]
                ["organization_id"],
                status=OrganizationStatus.ACTIVE,
            )
        except KeyError:
            logger.info(
                "vercel.integration.key-error",
                extra={
                    "external_id": external_id,
                    "integration_id": integration.id
                },
            )
            return HttpResponse("Cannot fetch organization.")
        except Organization.DoesNotExist:
            logger.info(
                "vercel.organization.does-not-exist",
                extra={
                    "external_id": external_id,
                    "integration_id": integration.id
                },
            )
            return HttpResponse("Organization does not exist")
        try:
            OrganizationIntegration.objects.get(organization=organization.id,
                                                integration=integration.id)
        except OrganizationIntegration.DoesNotExist:
            logger.info(
                "vercel.organization-integration.does-not-exist",
                extra={
                    "organization_id": organization.id,
                    "integration_id": integration.id
                },
            )
            return HttpResponse("The requested integration does not exist.")

        link = absolute_uri("/settings/%s/integrations/vercel/%s/" %
                            (organization.slug, integration.id))
        return render_to_response(
            "sentry/vercel-ui-hook.vercel",
            request=request,
            context={
                "org": organization.slug,
                "link": link
            },
        )
コード例 #49
0
ファイル: twofactor.py プロジェクト: sugusbs/sentry
    def handle(self, request):
        user = auth.get_pending_2fa_user(request)
        if user is None:
            return HttpResponseRedirect(auth.get_login_url())

        interfaces = Authenticator.objects.all_interfaces_for_user(user)

        # If for whatever reason we ended up here but the user has no 2FA
        # enabled, we just continue successfully.
        if not interfaces:
            return self.perform_signin(request, user)

        challenge = activation = None
        interface = self.negotiate_interface(request, interfaces)

        if request.method == "POST" and ratelimiter.is_limited(
                "auth-2fa:user:{}".format(user.id), limit=5, window=60):
            # TODO: Maybe email the account owner or do something to notify someone
            # This would probably be good for them to know.
            return HttpResponse(
                "You have made too many 2FA attempts. Please try again later.",
                content_type="text/plain",
                status=429,
            )

        if request.method == "GET":
            activation = interface.activate(request)
            if activation is not None and activation.type == "challenge":
                challenge = activation.challenge
        elif "challenge" in request.POST:
            challenge = json.loads(request.POST["challenge"])

        form = TwoFactorForm()

        # If an OTP response was supplied, we try to make it pass.
        otp = request.POST.get("otp")
        if otp:
            used_interface = self.validate_otp(otp, interface, interfaces)
            if used_interface is not None:
                return self.perform_signin(request, user, used_interface)
            self.fail_signin(request, user, form)

        # If a challenge and response exists, validate
        if challenge:
            response = request.POST.get("response")
            if response:
                response = json.loads(response)
                if interface.validate_response(request, challenge, response):
                    return self.perform_signin(request, user, interface)
                self.fail_signin(request, user, form)

        return render_to_response(
            [
                "sentry/twofactor_%s.html" % interface.interface_id,
                "sentry/twofactor.html"
            ],
            {
                "form":
                form,
                "interface":
                interface,
                "other_interfaces":
                self.get_other_interfaces(interface, interfaces),
                "activation":
                activation,
            },
            request,
            status=200,
        )
コード例 #50
0
ファイル: views.py プロジェクト: joan2015/sentry
 def get_response(self, template, context=None):
     context = context or self.get_context()
     res = render_to_response(template, context, self.request)
     res["X-Frame-Options"] = "ALLOW-FROM %s" % self.request.GET["xdm_e"]
     return res
コード例 #51
0
    def handle(self, request: Request, signed_params: str) -> HttpResponse:
        if request.method not in ALLOWED_METHODS:
            return render_error_page(request,
                                     body_text="HTTP 405: Method not allowed")

        try:
            params = unsign(signed_params)
        except (SignatureExpired, BadSignature):
            return render_to_response(
                "sentry/integrations/slack/expired-link.html",
                request=request,
            )

        integration = Integration.objects.get(id=params["integration_id"])
        organization = integration.organizations.all()[0]
        teams = Team.objects.get_for_user(organization, request.user)
        channel_name = params["channel_name"]
        channel_id = params["channel_id"]
        form = SelectTeamForm(teams, request.POST or None)

        if request.method == "GET":
            return self.respond(
                "sentry/integrations/slack/link-team.html",
                {
                    "form": form,
                    "teams": teams,
                    "channel_name": channel_name,
                    "provider": integration.get_provider(),
                },
            )

        if not form.is_valid():
            return render_error_page(request,
                                     body_text="HTTP 400: Bad request")

        team_id = form.cleaned_data["team"]
        try:
            team = Team.objects.get(id=team_id, organization=organization)
        except Team.DoesNotExist:
            return render_error_page(request,
                                     body_text="HTTP 404: Team does not exist")

        try:
            idp = IdentityProvider.objects.get(
                type="slack", external_id=integration.external_id)
        except IdentityProvider.DoesNotExist:
            logger.error("slack.action.invalid-team-id",
                         extra={"slack_id": integration.external_id})
            return render_error_page(request,
                                     body_text="HTTP 403: Invalid team ID")

        if not Identity.objects.filter(
                idp=idp, external_id=params["slack_id"]).exists():
            return render_error_page(
                request, body_text="HTTP 403: User identity does not exist")

        external_team, created = ExternalActor.objects.get_or_create(
            actor_id=team.actor_id,
            organization=organization,
            integration=integration,
            provider=ExternalProviders.SLACK.value,
            defaults=dict(
                external_name=channel_name,
                external_id=channel_id,
            ),
        )

        if not created:
            return send_confirmation(
                integration,
                channel_id,
                ALREADY_LINKED_TITLE,
                ALREADY_LINKED_MESSAGE.format(slug=team.slug),
                "sentry/integrations/slack/post-linked-team.html",
                request,
            )

        # Turn on notifications for all of a team's projects.
        NotificationSetting.objects.update_settings(
            ExternalProviders.SLACK,
            NotificationSettingTypes.ISSUE_ALERTS,
            NotificationSettingOptionValues.ALWAYS,
            team=team,
        )
        return send_confirmation(
            integration,
            channel_id,
            SUCCESS_LINKED_TITLE,
            SUCCESS_LINKED_MESSAGE.format(slug=team.slug,
                                          channel_name=channel_name),
            "sentry/integrations/slack/post-linked-team.html",
            request,
        )
コード例 #52
0
ファイル: mail.py プロジェクト: zeuskingzb/sentry
 def render(self, request):
     return render_to_response(
         "sentry/debug/mail/preview.html", {"preview": self, "format": request.GET.get("format")}
     )
コード例 #53
0
def account_settings(request):
    user = request.user

    form = AccountSettingsForm(
        user,
        request,
        request.POST or None,
        initial={
            'email': UserEmail.get_primary_email(user).email,
            'username': user.username,
            'name': user.name,
        },
    )

    if form.is_valid():
        old_email = user.email

        form.save()

        # update notification settings for those set to primary email with new primary email
        alert_email = UserOption.objects.get_value(user=user, key='alert_email')

        if alert_email == old_email:
            UserOption.objects.set_value(user=user, key='alert_email', value=user.email)
        options = UserOption.objects.filter(user=user, key='mail:email')
        for option in options:
            if option.value != old_email:
                continue
            option.value = user.email
            option.save()

        # TODO(dcramer): we should maintain validation here when we support
        # multiple email addresses
        if request.user.email != old_email:
            try:
                with transaction.atomic():
                    user_email = UserEmail.objects.create(
                        user=user,
                        email=user.email,
                    )
            except IntegrityError:
                pass
            else:
                user_email.set_hash()
                user_email.save()
                user.send_confirm_email_singular(user_email)
                msg = _('A confirmation email has been sent to %s.') % user_email.email
                messages.add_message(request, messages.SUCCESS, msg)

        user.clear_lost_passwords()

        messages.add_message(request, messages.SUCCESS, _('Your settings were saved.'))
        return HttpResponseRedirect(request.path)

    context = csrf(request)
    context.update(
        {
            'form': form,
            'page': 'settings',
            'has_2fa': Authenticator.objects.user_has_2fa(request.user),
            'AUTH_PROVIDERS': auth.get_auth_providers(),
            'email': UserEmail.get_primary_email(user),
            'has_newsletters': newsletter.is_enabled,
        }
    )
    return render_to_response('sentry/account/settings.html', context, request)
コード例 #54
0
def search(request, team, project):
    query = request.GET.get('q')

    if not query:
        return HttpResponseRedirect(reverse('sentry-stream', args=[team.slug, project.slug]))

    sort = request.GET.get('sort')
    if sort not in SEARCH_SORT_OPTIONS:
        sort = SEARCH_DEFAULT_SORT_OPTION
    sort_label = SEARCH_SORT_OPTIONS[sort]

    result = event_re.match(query)
    if result:
        # Forward to aggregate if it exists
        # event_id = result.group(1)
        checksum = result.group(2)
        try:
            group = Group.objects.filter(project=project, checksum=checksum)[0]
        except IndexError:
            return render_to_response('sentry/invalid_message_id.html', {
                'team': team,
                'project': project,
            }, request)
        else:
            return HttpResponseRedirect(reverse('sentry-group', kwargs={
                'project_id': group.project.slug,
                'team_slug': group.team.slug,
                'group_id': group.id,
            }))
    elif uuid_re.match(query):
        # Forward to event if it exists
        try:
            group_id = EventMapping.objects.get(
                project=project, event_id=query
            ).group_id
        except EventMapping.DoesNotExist:
            try:
                event = Event.objects.get(project=project, event_id=query)
            except Event.DoesNotExist:
                return render_to_response('sentry/invalid_message_id.html', {
                    'team': team,
                    'project': project,
                }, request)
            else:
                return HttpResponseRedirect(reverse('sentry-group-event', kwargs={
                    'project_id': project.slug,
                    'team_slug': team.slug,
                    'group_id': event.group.id,
                    'event_id': event.id,
                }))
        else:
            return HttpResponseRedirect(reverse('sentry-group', kwargs={
                'project_id': project.slug,
                'team_slug': team.slug,
                'group_id': group_id,
            }))
    elif not settings.SENTRY_USE_SEARCH:
        event_list = Group.objects.none()
        # return render_to_response('sentry/invalid_message_id.html', {
        #         'project': project,
        #     }, request)
    else:
        documents = list(SearchDocument.objects.search(project, query, sort_by=sort))
        groups = Group.objects.in_bulk([d.group_id for d in documents])

        event_list = []
        for doc in documents:
            try:
                event_list.append(groups[doc.group_id])
            except KeyError:
                continue

    return render_to_response('sentry/search.html', {
        'team': project.team,
        'project': project,
        'event_list': event_list,
        'query': query,
        'sort': sort,
        'sort_label': sort_label,
    }, request)
コード例 #55
0
    def dispatch(self, request):
        try:
            event_id = request.GET['eventId']
        except KeyError:
            return self._json_response(
                request, {'eventId': 'Missing or invalid parameter.'},
                status=400)

        if event_id and not is_event_id(event_id):
            return self._json_response(
                request, {'eventId': 'Missing or invalid parameter.'},
                status=400)

        key = self._get_project_key(request)
        if not key:
            return self._json_response(
                request, {'dsn': 'Missing or invalid parameter.'}, status=404)

        origin = self._get_origin(request)
        if not origin:
            return self._json_response(request, status=403)

        if not is_valid_origin(origin, key.project):
            return HttpResponse(status=403)

        if request.method == 'OPTIONS':
            return self._json_response(request)

        # customization options
        options = DEFAULT_OPTIONS.copy()
        for name in six.iterkeys(options):
            if name in request.GET:
                options[name] = six.text_type(request.GET[name])

        # TODO(dcramer): since we cant use a csrf cookie we should at the very
        # least sign the request / add some kind of nonce
        initial = {
            'name': request.GET.get('name'),
            'email': request.GET.get('email'),
        }

        form = UserReportForm(
            request.POST if request.method == 'POST' else None,
            initial=initial)
        if form.is_valid():
            # TODO(dcramer): move this to post to the internal API
            report = form.save(commit=False)
            report.project = key.project
            report.event_id = event_id

            try:
                event = Event.objects.filter(
                    project_id=report.project.id,
                    event_id=report.event_id).select_related('group')[0]
            except IndexError:
                try:
                    report.group = Group.objects.from_event_id(
                        report.project, report.event_id)
                except Group.DoesNotExist:
                    pass
            else:
                report.environment = event.get_environment()
                report.group = event.group

            try:
                with transaction.atomic():
                    report.save()
            except IntegrityError:
                # There was a duplicate, so just overwrite the existing
                # row with the new one. The only way this ever happens is
                # if someone is messing around with the API, or doing
                # something wrong with the SDK, but this behavior is
                # more reasonable than just hard erroring and is more
                # expected.
                UserReport.objects.filter(
                    project=report.project,
                    event_id=report.event_id,
                ).update(
                    name=report.name,
                    email=report.email,
                    comments=report.comments,
                    date_added=timezone.now(),
                )

            else:
                if report.group:
                    report.notify()

            user_feedback_received.send(project=report.project,
                                        group=report.group,
                                        sender=self)

            return self._json_response(request)
        elif request.method == 'POST':
            return self._json_response(request, {
                "errors": dict(form.errors),
            },
                                       status=400)

        show_branding = ProjectOption.objects.get_value(
            project=key.project, key='feedback:branding', default='1') == '1'

        template = render_to_string(
            'sentry/error-page-embed.html', {
                'form': form,
                'show_branding': show_branding,
                'title': options['title'],
                'subtitle': options['subtitle'],
                'subtitle2': options['subtitle2'],
                'name_label': options['labelName'],
                'email_label': options['labelEmail'],
                'comments_label': options['labelComments'],
                'submit_label': options['labelSubmit'],
                'close_label': options['labelClose'],
            })

        context = {
            'endpoint':
            mark_safe('*/' + json.dumps(request.build_absolute_uri()) + ';/*'),
            'template':
            mark_safe('*/' + json.dumps(template) + ';/*'),
            'strings':
            json.dumps_htmlsafe({
                'generic_error':
                six.text_type(options['errorGeneric']),
                'form_error':
                six.text_type(options['errorFormEntry']),
                'sent_message':
                six.text_type(options['successMessage']),
            }),
        }

        return render_to_response('sentry/error-page-embed.js',
                                  context,
                                  request,
                                  content_type='text/javascript')
コード例 #56
0
def notification(request, project):
    return render_to_response('sentry/partial/_notification.html', request.GET)
コード例 #57
0
    def respond(self, template, context=None, status=200):
        default_context = self.default_context
        if context:
            default_context.update(context)

        return render_to_response(template, default_context, self.request, status=status)
コード例 #58
0
    def handle(self, request, signed_params):
        params = unsign(signed_params.encode('ascii', errors='ignore'))

        try:
            organization = Organization.objects.get(
                id__in=request.user.get_orgs(),
                id=params['organization_id'],
            )
        except Organization.DoesNotExist:
            raise Http404

        try:
            integration = Integration.objects.get(
                id=params['integration_id'],
                organizations=organization,
            )
        except Integration.DoesNotExist:
            raise Http404

        try:
            idp = IdentityProvider.objects.get(
                type='slack',
                organization=organization,
            )
        except Integration.DoesNotExist:
            raise Http404

        if request.method != 'POST':
            return render_to_response('sentry/auth-link-identity.html',
                                      request=request,
                                      context={
                                          'organization': organization,
                                          'provider':
                                          integration.get_provider(),
                                      })

        # TODO(epurkhiser): We could do some fancy slack querying here to
        # render a nice linking page with info about the user their linking.

        Identity.objects.get_or_create(
            external_id=params['slack_id'],
            user=request.user,
            idp=idp,
            status=IdentityStatus.VALID,
        )

        payload = {
            'token':
            integration.metadata['access_token'],
            'token':
            integration.metadata['access_token'],
            'channel':
            params['notify_channel_id'],
            'user':
            params['slack_id'],
            'text':
            "Your Slack identity has been linked to your Sentry account. You're good to go!"
        }

        session = http.build_session()
        req = session.post('https://slack.com/api/chat.postEphemeral',
                           data=payload)
        resp = req.json()
        if not resp.get('ok'):
            logger.error('slack.link-notify.response-error',
                         extra={
                             'error': resp.get('error'),
                         })

        return render_to_response('sentry/slack-linked.html',
                                  request=request,
                                  context={
                                      'channel_id':
                                      params['notify_channel_id'],
                                      'team_id': integration.external_id,
                                  })
コード例 #59
0
ファイル: api.py プロジェクト: yudina-m/sentry
def crossdomain_xml_index(request):
    response = render_to_response('sentry/crossdomain_index.xml')
    response['Content-Type'] = 'application/xml'
    return response
コード例 #60
0
ファイル: accounts.py プロジェクト: yeliex/sentry
def show_emails(request):
    user = request.user
    primary_email = UserEmail.get_primary_email(user)
    alt_emails = user.emails.all().exclude(email=primary_email.email)

    email_form = EmailForm(
        user,
        request.POST or None,
        initial={
            'primary_email': primary_email.email,
        },
    )

    if 'remove' in request.POST:
        email = request.POST.get('email')
        del_email = UserEmail.objects.filter(user=user, email=email)
        del_email.delete()
        logger.info('user.email.remove',
                    extra={
                        'user_id': user.id,
                        'ip_address': request.META['REMOTE_ADDR'],
                        'email': email,
                    })

        return HttpResponseRedirect(request.path)

    if email_form.is_valid():
        old_email = user.email

        email_form.save()

        if user.email != old_email:
            useroptions = UserOption.objects.filter(user=user, value=old_email)
            for option in useroptions:
                option.value = user.email
                option.save()
            UserEmail.objects.filter(user=user, email=old_email).delete()
            try:
                with transaction.atomic():
                    user_email = UserEmail.objects.create(
                        user=user,
                        email=user.email,
                    )
            except IntegrityError:
                pass
            else:
                user_email.set_hash()
                user_email.save()
                user.send_confirm_email_singular(user_email)
                logger.info('user.email.add',
                            extra={
                                'user_id': user.id,
                                'ip_address': request.META['REMOTE_ADDR'],
                                'email': user_email.email,
                            })
                msg = _('A confirmation email has been sent to %s.'
                        ) % user_email.email
                messages.add_message(request, messages.SUCCESS, msg)
        alternative_email = email_form.cleaned_data['alt_email']
        # check if this alternative email already exists for user
        if alternative_email and not UserEmail.objects.filter(
                user=user, email=alternative_email):
            # create alternative email for user
            try:
                with transaction.atomic():
                    new_email = UserEmail.objects.create(
                        user=user, email=alternative_email)
            except IntegrityError:
                pass
            else:
                new_email.set_hash()
                new_email.save()
            # send confirmation emails to any non verified emails
            user.send_confirm_email_singular(new_email)
            logger.info('user.email.add',
                        extra={
                            'user_id': user.id,
                            'ip_address': request.META['REMOTE_ADDR'],
                            'email': new_email.email,
                        })
            msg = _(
                'A confirmation email has been sent to %s.') % new_email.email
            messages.add_message(request, messages.SUCCESS, msg)

        messages.add_message(request, messages.SUCCESS,
                             _('Your settings were saved.'))
        return HttpResponseRedirect(request.path)

    context = csrf(request)
    context.update({
        'email_form': email_form,
        'primary_email': primary_email,
        'alt_emails': alt_emails,
        'page': 'emails',
        'AUTH_PROVIDERS': auth.get_auth_providers(),
    })
    return render_to_response('sentry/account/emails.html', context, request)