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)
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)
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)
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)
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)
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)
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)
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, )
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
def render_to_response(self, context, **response_kwargs): return render_to_response( request=self.request, template=self.get_template_names(), context=context, **response_kwargs )
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)
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)
def get_started(request, team, project): return render_to_response('sentry/get_started.html', { 'project': project, 'team': project.team, 'SECTION': 'team', 'SUBSECTION': 'projects' }, request)
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)
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)
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)
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)
def render_with_team_context(team, template, context, request=None): context.update({ 'team': team, 'SECTION': 'team', }) return render_to_response(template, context, request)
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)
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, }, )
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
def _dialog_response(self, data, success): context = {'payload': {'success': success, 'data': data}} return render_to_response('sentry/integrations/dialog-complete.html', context, self.request)
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")
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 }, )
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)
def error(self, message): context = {"error": message} return render_to_response("sentry/pipeline-error.html", context, self.request)
def render_to_response(self, context, **response_kwargs): return render_to_response(request=self.request, template=self.get_template_names(), context=context, **response_kwargs)
def get_started(request, project): return render_to_response('sentry/get_started.html', { 'project': project, }, request)
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)
(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():
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)
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)
def render(self, request): return render_to_response('sentry/debug/mail/preview.html', { 'preview': self, 'format': request.GET.get('format'), })
def _dialog_response(self, data, success): context = {"payload": {"success": success, "data": data}} return render_to_response("sentry/integrations/dialog-complete.html", context, self.request)
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)
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)
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 }, )
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, )
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
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, )
def render(self, request): return render_to_response( "sentry/debug/mail/preview.html", {"preview": self, "format": request.GET.get("format")} )
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)
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)
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')
def notification(request, project): return render_to_response('sentry/partial/_notification.html', request.GET)
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)
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, })
def crossdomain_xml_index(request): response = render_to_response('sentry/crossdomain_index.xml') response['Content-Type'] = 'application/xml' return response
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)