diff --git a/src/sentry/web/urls.py b/src/sentry/web/urls.py index 9963a8c0f93706..978267b14b76b7 100644 --- a/src/sentry/web/urls.py +++ b/src/sentry/web/urls.py @@ -143,15 +143,16 @@ def init_all_applications(): ), # Javascript SDK Loader - url( r'^js-sdk-loader/(?P[^/\.]+)(?:(?P\.min))?\.js$', JavaScriptSdkLoader.as_view(), name='sentry-js-sdk-loader' ), - # API + # Versioned API url(r'^api/0/', include('sentry.api.urls')), + + # Legacy unversioned endpoints url( r'^api/hooks/mailgun/inbound/', MailgunInboundWebhookView.as_view(), @@ -166,145 +167,162 @@ def init_all_applications(): name='sentry-error-page-embed'), # OAuth - url(r'^oauth/authorize/$', OAuthAuthorizeView.as_view()), - url(r'^oauth/token/$', OAuthTokenView.as_view()), + url(r'^oauth/', include([ + url(r'^authorize/$', OAuthAuthorizeView.as_view()), + url(r'^token/$', OAuthTokenView.as_view()), + ])), # SAML - url(r'^saml/acs/(?P[^/]+)/$', SAML2AcceptACSView.as_view(), - name='sentry-auth-organization-saml-acs'), - url(r'^saml/sls/(?P[^/]+)/$', SAML2SLSView.as_view(), - name='sentry-auth-organization-saml-sls'), - url(r'^saml/metadata/(?P[^/]+)/$', SAML2MetadataView.as_view(), - name='sentry-auth-organization-saml-metadata'), + url(r'^saml/', include([ + url(r'^acs/(?P[^/]+)/$', SAML2AcceptACSView.as_view(), + name='sentry-auth-organization-saml-acs'), + url(r'^sls/(?P[^/]+)/$', SAML2SLSView.as_view(), + name='sentry-auth-organization-saml-sls'), + url(r'^metadata/(?P[^/]+)/$', SAML2MetadataView.as_view(), + name='sentry-auth-organization-saml-metadata'), + ])), # Auth - url( - r'^auth/link/(?P[^/]+)/$', - AuthOrganizationLoginView.as_view(), - name='sentry-auth-link-identity' - ), - url(r'^auth/login/$', AuthLoginView.as_view(), name='sentry-login'), - url( - r'^auth/login/(?P[^/]+)/$', - AuthOrganizationLoginView.as_view(), - name='sentry-auth-organization' - ), - url(r'^auth/2fa/$', TwoFactorAuthView.as_view(), name='sentry-2fa-dialog'), - url(r'^auth/2fa/u2fappid\.json$', u2f_appid, name='sentry-u2f-app-id'), - url(r'^auth/sso/$', AuthProviderLoginView.as_view(), name='sentry-auth-sso'), - url(r'^auth/logout/$', AuthLogoutView.as_view(), name='sentry-logout'), - url(r'^auth/reactivate/$', ReactivateAccountView.as_view(), - name='sentry-reactivate-account'), - url(r'^auth/register/$', AuthLoginView.as_view(), name='sentry-register'), - url(r'^auth/close/$', AuthCloseView.as_view(), name='sentry-auth-close'), + url(r'^auth/', include([ + url(r'^login/$', AuthLoginView.as_view(), name='sentry-login'), + url( + r'^login/(?P[^/]+)/$', + AuthOrganizationLoginView.as_view(), + name='sentry-auth-organization' + ), + url( + r'^link/(?P[^/]+)/$', + AuthOrganizationLoginView.as_view(), + name='sentry-auth-link-identity' + ), + url(r'^2fa/$', TwoFactorAuthView.as_view(), name='sentry-2fa-dialog'), + url(r'^2fa/u2fappid\.json$', u2f_appid, name='sentry-u2f-app-id'), + url(r'^sso/$', AuthProviderLoginView.as_view(), name='sentry-auth-sso'), + url(r'^logout/$', AuthLogoutView.as_view(), name='sentry-logout'), + url(r'^reactivate/$', ReactivateAccountView.as_view(), + name='sentry-reactivate-account'), + url(r'^register/$', AuthLoginView.as_view(), name='sentry-register'), + url(r'^close/$', AuthCloseView.as_view(), name='sentry-auth-close'), + ])), - # Account url(r'^login-redirect/$', accounts.login_redirect, name='sentry-login-redirect'), - url(r'^account/sudo/$', SudoView.as_view(), name='sentry-sudo'), - url( - r'^account/confirm-email/$', - accounts.start_confirm_email, - name='sentry-account-confirm-email-send' - ), - url(r'^account/authorizations/$', - RedirectView.as_view( - pattern_name="sentry-account-settings-authorizations", - permanent=False), + + # Account + url(r'^account/', include([ + url(r'^sudo/$', SudoView.as_view(), name='sentry-sudo'), + url( + r'^confirm-email/$', + accounts.start_confirm_email, + name='sentry-account-confirm-email-send' ), - url( - r'^account/confirm-email/(?P[\d]+)/(?P[0-9a-zA-Z]+)/$', - accounts.confirm_email, - name='sentry-account-confirm-email' - ), - url(r'^account/recover/$', accounts.recover, name='sentry-account-recover'), - url( - r'^account/recover/confirm/(?P[\d]+)/(?P[0-9a-zA-Z]+)/$', - accounts.recover_confirm, - name='sentry-account-recover-confirm' - ), - url( - r'^account/password/confirm/(?P[\d]+)/(?P[0-9a-zA-Z]+)/$', - accounts.set_password_confirm, - name='sentry-account-set-password-confirm' - ), - url(r'^account/settings/$', - RedirectView.as_view(pattern_name="sentry-account-settings", permanent=False), + url(r'^authorizations/$', + RedirectView.as_view( + pattern_name="sentry-account-settings-authorizations", + permanent=False), + ), + url( + r'^confirm-email/(?P[\d]+)/(?P[0-9a-zA-Z]+)/$', + accounts.confirm_email, + name='sentry-account-confirm-email' ), - url( - r'^account/settings/2fa/', - RedirectView.as_view(pattern_name="sentry-account-settings-security", permanent=False), - ), - url( - r'^account/settings/avatar/$', - RedirectView.as_view(pattern_name="sentry-account-settings-avatar", permanent=False), - ), - url( - r'^account/settings/appearance/$', - RedirectView.as_view(pattern_name="sentry-account-settings-appearance", permanent=False), - ), - url( - r'^account/settings/identities/$', - RedirectView.as_view(pattern_name="sentry-account-settings-identities", permanent=False), - ), - url( - r'^account/settings/subscriptions/$', - RedirectView.as_view(pattern_name="sentry-account-settings-subscriptions", permanent=False), - ), - url( - r'^account/settings/identities/(?P[^\/]+)/disconnect/$', - accounts.disconnect_identity, - name='sentry-account-disconnect-identity' - ), - url( - r'^account/settings/identities/associate/(?P[^\/]+)/(?P[^\/]+)/(?P[^\/]+)/$', - AccountIdentityAssociateView.as_view(), - name='sentry-account-associate-identity' - ), - url( - r'^account/settings/security/', - RedirectView.as_view(pattern_name="sentry-account-settings-security", permanent=False), - ), - url(r'^account/settings/emails/$', - RedirectView.as_view(pattern_name="sentry-account-settings-emails", permanent=False), + url(r'^recover/$', accounts.recover, name='sentry-account-recover'), + url( + r'^recover/confirm/(?P[\d]+)/(?P[0-9a-zA-Z]+)/$', + accounts.recover_confirm, + name='sentry-account-recover-confirm' ), - - # Project Wizard - url( - r'^account/settings/wizard/(?P[^\/]+)/$', - SetupWizardView.as_view(), - name='sentry-project-wizard-fetch' - ), - - # compatibility - url( - r'^account/settings/notifications/unsubscribe/(?P\d+)/$', - accounts.email_unsubscribe_project - ), - url( - r'^account/settings/notifications/', - RedirectView.as_view(pattern_name="sentry-account-settings-notifications", permanent=False), - ), - url( - r'^account/notifications/unsubscribe/(?P\d+)/$', - accounts.email_unsubscribe_project, - name='sentry-account-email-unsubscribe-project' - ), - url( - r'^account/notifications/unsubscribe/issue/(?P\d+)/$', - UnsubscribeIssueNotificationsView.as_view(), - name='sentry-account-email-unsubscribe-issue' - ), - url( - r'^account/notifications/unsubscribe/incident/(?P\d+)/$', - UnsubscribeIncidentNotificationsView.as_view(), - name='sentry-account-email-unsubscribe-incident' - ), - url(r'^account/remove/$', - RedirectView.as_view(pattern_name="sentry-remove-account", permanent=False), + url( + r'^password/confirm/(?P[\d]+)/(?P[0-9a-zA-Z]+)/$', + accounts.set_password_confirm, + name='sentry-account-set-password-confirm' + ), + url(r'^settings/$', + RedirectView.as_view(pattern_name="sentry-account-settings", permanent=False), + ), + url( + r'^settings/2fa/', + RedirectView.as_view(pattern_name="sentry-account-settings-security", permanent=False), + ), + url( + r'^settings/avatar/$', + RedirectView.as_view(pattern_name="sentry-account-settings-avatar", permanent=False), + ), + url( + r'^settings/appearance/$', + RedirectView.as_view( + pattern_name="sentry-account-settings-appearance", + permanent=False), + ), + url( + r'^settings/identities/$', + RedirectView.as_view( + pattern_name="sentry-account-settings-identities", + permanent=False), + ), + url( + r'^settings/subscriptions/$', + RedirectView.as_view( + pattern_name="sentry-account-settings-subscriptions", + permanent=False), + ), + url( + r'^settings/identities/(?P[^\/]+)/disconnect/$', + accounts.disconnect_identity, + name='sentry-account-disconnect-identity' ), - url(r'^account/settings/social/', include('social_auth.urls')), - url(r'^account/', generic_react_page_view), + url( + r'^settings/identities/associate/(?P[^\/]+)/(?P[^\/]+)/(?P[^\/]+)/$', + AccountIdentityAssociateView.as_view(), + name='sentry-account-associate-identity' + ), + url( + r'^settings/security/', + RedirectView.as_view(pattern_name="sentry-account-settings-security", permanent=False), + ), + url(r'^settings/emails/$', + RedirectView.as_view(pattern_name="sentry-account-settings-emails", permanent=False), + ), + # Project Wizard + url( + r'^settings/wizard/(?P[^\/]+)/$', + SetupWizardView.as_view(), + name='sentry-project-wizard-fetch' + ), + # compatibility + url( + r'^settings/notifications/unsubscribe/(?P\d+)/$', + accounts.email_unsubscribe_project + ), + url( + r'^settings/notifications/', + RedirectView.as_view( + pattern_name="sentry-account-settings-notifications", + permanent=False), + ), + url( + r'^notifications/unsubscribe/(?P\d+)/$', + accounts.email_unsubscribe_project, + name='sentry-account-email-unsubscribe-project' + ), + url( + r'^notifications/unsubscribe/issue/(?P\d+)/$', + UnsubscribeIssueNotificationsView.as_view(), + name='sentry-account-email-unsubscribe-issue' + ), + url( + r'^notifications/unsubscribe/incident/(?P\d+)/$', + UnsubscribeIncidentNotificationsView.as_view(), + name='sentry-account-email-unsubscribe-incident' + ), + url(r'^remove/$', + RedirectView.as_view(pattern_name="sentry-remove-account", permanent=False), + ), + url(r'^settings/social/', include('social_auth.urls')), + url(r'^', generic_react_page_view), + ])), + + # Onboarding url(r'^onboarding/', generic_react_page_view), # Admin @@ -336,149 +354,155 @@ def init_all_applications(): url(r'^out/$', OutView.as_view()), url(r'^accept-transfer/$', react_page_view, name='sentry-accept-project-transfer'), - # User settings use generic_react_page_view, while any view - # acting on behalf of an organization should use react_page_view - url(r'^settings/account/$', generic_react_page_view, name="sentry-account-settings"), - url(r'^settings/account/$', generic_react_page_view, name="sentry-account-settings-appearance"), - url(r'^settings/account/authorizations/$', generic_react_page_view, - name="sentry-account-settings-authorizations"), - url(r'^settings/account/security/', generic_react_page_view, - name='sentry-account-settings-security'), - url(r'^settings/account/avatar/$', generic_react_page_view, name='sentry-account-settings-avatar'), - url(r'^settings/account/identities/$', generic_react_page_view, - name='sentry-account-settings-identities'), - url(r'^settings/account/subscriptions/$', generic_react_page_view, - name='sentry-account-settings-subscriptions'), - url(r'^settings/account/notifications/', generic_react_page_view, - name='sentry-account-settings-notifications'), - url(r'^settings/account/emails/$', generic_react_page_view, name='sentry-account-settings-emails'), - url(r'^settings/account/api/applications/$', - generic_react_page_view, name='sentry-api-applications'), - url(r'^settings/account/api/auth-tokens/new-token/$', - generic_react_page_view, name='sentry-api-new-auth-token'), - url(r'^settings/account/api/', generic_react_page_view, name='sentry-api'), - url(r'^settings/account/close-account/$', generic_react_page_view, name='sentry-remove-account'), - url(r'^settings/account/', generic_react_page_view), - - url(r'^settings/', react_page_view), - url( - r'^settings/(?P[\w_-]+)/members/$', - react_page_view, - name='sentry-organization-members' - ), - url( - r'^settings/(?P[\w_-]+)/members/new/$', - react_page_view, - name='sentry-create-organization-member' - ), - url( - r'^settings/(?P[\w_-]+)/members/(?P\d+)/$', - react_page_view, - name='sentry-organization-member-settings' - ), + + # User settings use generic_react_page_view, while any view acting on + # behalf of an organization should use react_page_view + url(r'^settings/', include([ + url(r'^account/$', generic_react_page_view, name="sentry-account-settings"), + url(r'^account/$', generic_react_page_view, name="sentry-account-settings-appearance"), + url(r'^account/authorizations/$', generic_react_page_view, + name="sentry-account-settings-authorizations"), + url(r'^account/security/', generic_react_page_view, + name='sentry-account-settings-security'), + url(r'^account/avatar/$', generic_react_page_view, name='sentry-account-settings-avatar'), + url(r'^account/identities/$', generic_react_page_view, + name='sentry-account-settings-identities'), + url(r'^account/subscriptions/$', generic_react_page_view, + name='sentry-account-settings-subscriptions'), + url(r'^account/notifications/', generic_react_page_view, + name='sentry-account-settings-notifications'), + url(r'^account/emails/$', generic_react_page_view, name='sentry-account-settings-emails'), + url(r'^account/api/applications/$', + generic_react_page_view, name='sentry-api-applications'), + url(r'^account/api/auth-tokens/new-token/$', + generic_react_page_view, name='sentry-api-new-auth-token'), + url(r'^account/api/', generic_react_page_view, name='sentry-api'), + url(r'^account/close-account/$', generic_react_page_view, name='sentry-remove-account'), + url(r'^account/', generic_react_page_view), + url( + r'^(?P[\w_-]+)/members/$', + react_page_view, + name='sentry-organization-members' + ), + url( + r'^(?P[\w_-]+)/members/new/$', + react_page_view, + name='sentry-create-organization-member' + ), + url( + r'^(?P[\w_-]+)/members/(?P\d+)/$', + react_page_view, + name='sentry-organization-member-settings' + ), + url(r'^', react_page_view), + ])), + url(r'^extensions/external-install/(?P\w+)/(?P\w+)/$', react_page_view, name='integration-installation'), # Organizations url(r'^(?P[\w_-]+)/$', react_page_view, name='sentry-organization-home'), - url(r'^organizations/new/$', generic_react_page_view), - url( - r'^organizations/(?P[\w_-]+)/$', - react_page_view, - name='sentry-organization-index' - ), - url( - r'^organizations/(?P[\w_-]+)/issues/$', - react_page_view, - name='sentry-organization-issue-list' - ), - url( - r'^organizations/(?P[\w_-]+)/issues/(?P\d+)/$', - react_page_view, - name='sentry-organization-issue' - ), - url( - r'^organizations/(?P[\w_-]+)/issues/(?P\d+)/$', - react_page_view, - name='sentry-organization-issue-detail' - ), - url( - r'^organizations/(?P[\w_-]+)/issues/(?P\d+)/events/(?P[\w-]+)/$', - react_page_view, - name='sentry-organization-event-detail' - ), - url( - r'^organizations/(?P[\w_-]+)/issues/(?P\d+)/events/(?P[\w-]+)/json/$', - GroupEventJsonView.as_view(), - name='sentry-group-event-json' - ), - url( - r'^organizations/(?P[\w_-]+)/projects/(?P[\w_-]+)/events/(?P[\w_-]+)/$', - ProjectEventRedirect.as_view(), - name='sentry-project-event-redirect' - ), - url( - r'^organizations/(?P[\w_-]+)/api-keys/$', - react_page_view, - name='sentry-organization-api-keys' - ), - url( - r'^organizations/(?P[\w_-]+)/api-keys/(?P[\w_-]+)/$', - react_page_view, - name='sentry-organization-api-key-settings' - ), - url( - r'^organizations/(?P[\w_-]+)/auth/$', - react_page_view, - name='sentry-organization-auth-settings' - ), - url( - r'^organizations/(?P[\w_-]+)/auth/configure/$', - OrganizationAuthSettingsView.as_view(), - name='sentry-organization-auth-provider-settings' - ), - url( - r'^organizations/(?P[\w_-]+)/integrations/(?P[\w_-]+)/setup/$', - OrganizationIntegrationSetupView.as_view(), - name='sentry-organization-integrations-setup' - ), - url( - r'^organizations/(?P[\w_-]+)/members/$', - RedirectView.as_view(pattern_name="sentry-organization-members", permanent=False), - name='sentry-organization-members-old' - ), - url( - r'^organizations/(?P[\w_-]+)/members/new/$', - RedirectView.as_view(pattern_name="sentry-create-organization-member", permanent=False), - name='sentry-create-organization-member-old' - ), - url( - r'^organizations/(?P[\w_-]+)/members/(?P\d+)/$', - RedirectView.as_view(pattern_name="sentry-organization-member-settings", permanent=False), - name='sentry-organization-member-settings-old' - ), - url( - r'^organizations/(?P[\w_-]+)/stats/$', - react_page_view, - name='sentry-organization-stats' - ), - url( - r'^organizations/(?P[\w_-]+)/restore/$', - RestoreOrganizationView.as_view(), - name='sentry-restore-organization' - ), + url(r'^organizations/', include([ + url(r'^new/$', generic_react_page_view), + url( + r'^(?P[\w_-]+)/$', + react_page_view, + name='sentry-organization-index' + ), + url( + r'^(?P[\w_-]+)/issues/$', + react_page_view, + name='sentry-organization-issue-list' + ), + url( + r'^(?P[\w_-]+)/issues/(?P\d+)/$', + react_page_view, + name='sentry-organization-issue' + ), + url( + r'^(?P[\w_-]+)/issues/(?P\d+)/$', + react_page_view, + name='sentry-organization-issue-detail' + ), + url( + r'^(?P[\w_-]+)/issues/(?P\d+)/events/(?P[\w-]+)/$', + react_page_view, + name='sentry-organization-event-detail' + ), + url( + r'^(?P[\w_-]+)/issues/(?P\d+)/events/(?P[\w-]+)/json/$', + GroupEventJsonView.as_view(), + name='sentry-group-event-json' + ), + url( + r'^(?P[\w_-]+)/projects/(?P[\w_-]+)/events/(?P[\w_-]+)/$', + ProjectEventRedirect.as_view(), + name='sentry-project-event-redirect' + ), + url( + r'^(?P[\w_-]+)/api-keys/$', + react_page_view, + name='sentry-organization-api-keys' + ), + url( + r'^(?P[\w_-]+)/api-keys/(?P[\w_-]+)/$', + react_page_view, + name='sentry-organization-api-key-settings' + ), + url( + r'^(?P[\w_-]+)/auth/$', + react_page_view, + name='sentry-organization-auth-settings' + ), + url( + r'^(?P[\w_-]+)/auth/configure/$', + OrganizationAuthSettingsView.as_view(), + name='sentry-organization-auth-provider-settings' + ), + url( + r'^(?P[\w_-]+)/integrations/(?P[\w_-]+)/setup/$', + OrganizationIntegrationSetupView.as_view(), + name='sentry-organization-integrations-setup' + ), + url( + r'^(?P[\w_-]+)/members/$', + RedirectView.as_view(pattern_name="sentry-organization-members", permanent=False), + name='sentry-organization-members-old' + ), + url( + r'^(?P[\w_-]+)/members/new/$', + RedirectView.as_view(pattern_name="sentry-create-organization-member", permanent=False), + name='sentry-create-organization-member-old' + ), + url( + r'^(?P[\w_-]+)/members/(?P\d+)/$', + RedirectView.as_view( + pattern_name="sentry-organization-member-settings", + permanent=False), + name='sentry-organization-member-settings-old' + ), + url( + r'^(?P[\w_-]+)/stats/$', + react_page_view, + name='sentry-organization-stats' + ), + url( + r'^(?P[\w_-]+)/restore/$', + RestoreOrganizationView.as_view(), + name='sentry-restore-organization' + ), + # need to catch settings and force it to react + url(r'^(?P[\w_-]+)/settings/', react_page_view), + ])), + url( r'^accept/(?P\d+)/(?P\w+)/$', AcceptOrganizationInviteView.as_view(), name='sentry-accept-invite' ), - # need to catch settings and force it to react - url( - r'^organizations/(?P[\w_-]+)/settings/', react_page_view), - # Settings - Projects url( r'^(?P[\w_-]+)/(?P[\w_-]+)/settings/$', @@ -521,8 +545,6 @@ def init_all_applications(): url(r'^$', HomeView.as_view(), name='sentry'), url(r'^robots\.txt$', api.robots_txt, name='sentry-api-robots-txt'), - - # Force a 404 of favicon.ico. # This url is commonly requested by browsers, and without # blocking this, it was treated as a 200 OK for a react page view. @@ -538,20 +560,22 @@ def init_all_applications(): # XXX(dcramer): preferably we'd be able to use 'integrations' as the URL # prefix here, but unfortunately sentry.io has that mapped to marketing # assets for the time being - url( - r'^extensions/(?P[\w_-]+)/setup/$', - PipelineAdvancerView.as_view(), - name='sentry-extension-setup' - ), - url(r'^extensions/cloudflare/', include('sentry.integrations.cloudflare.urls')), - url(r'^extensions/jira/', include('sentry.integrations.jira.urls')), - url(r'^extensions/jira-server/', include('sentry.integrations.jira_server.urls')), - url(r'^extensions/slack/', include('sentry.integrations.slack.urls')), - url(r'^extensions/github/', include('sentry.integrations.github.urls')), - url(r'^extensions/github-enterprise/', include('sentry.integrations.github_enterprise.urls')), - url(r'^extensions/gitlab/', include('sentry.integrations.gitlab.urls')), - url(r'^extensions/vsts/', include('sentry.integrations.vsts.urls')), - url(r'^extensions/bitbucket/', include('sentry.integrations.bitbucket.urls')), + url(r'^extensions/', include([ + url( + r'^(?P[\w_-]+)/setup/$', + PipelineAdvancerView.as_view(), + name='sentry-extension-setup' + ), + url(r'^cloudflare/', include('sentry.integrations.cloudflare.urls')), + url(r'^jira/', include('sentry.integrations.jira.urls')), + url(r'^jira-server/', include('sentry.integrations.jira_server.urls')), + url(r'^slack/', include('sentry.integrations.slack.urls')), + url(r'^github/', include('sentry.integrations.github.urls')), + url(r'^github-enterprise/', include('sentry.integrations.github_enterprise.urls')), + url(r'^gitlab/', include('sentry.integrations.gitlab.urls')), + url(r'^vsts/', include('sentry.integrations.vsts.urls')), + url(r'^bitbucket/', include('sentry.integrations.bitbucket.urls')), + ])), url(r'^plugins/', include('sentry.plugins.base.urls')),