extensions-website/blender_extensions/urls.py
Oleg Komarov bd3a17a19b Notification emails (#80)
Implementation for #72 based on https://github.com/justquick/django-activity-stream/

Summary:
- create an Action object, specifying a corresponding Extension object as a `target` and other relevant objects (Rating, ApprovalActivity, AbuseReport) as `action_object` (search code for `action.send` to see where it happens)
  - there is one exception when we don't have an `action_object` - when we submit a new extension for a review, but this could be restructured as creating a first ApprovalActivity item, TODO revisit this
- use `follow` provided by actstream to specify relations between users and extensions, use different flags (author, moderator, reviewer) to explicitly manage those relations; proactively call the `follow` to make sure that users are subscribed before an Action interesting to them is created;
  - one downside here is that each moderator needs to follow each extensions individually, but this potentially allows to explicitly unsubscribe from activity on extensions that are not interesting to a given user
- introduce `VERB2FLAGS` mapping to define when a given Action needs to generate a Notification for a follower of a particular type (=flag) based on the Action's verb
- process Notification records by a new `send_notifications` management command that sends emails
- add a profile setting to disable notification emails

First iteration includes only internal (`@blender.org`) emails.

If you have a DB with some preexisting data, you need to run `./manage.py ensure_followers` command to retroactively create expected follow relations.

Next steps (out of scope for this PR):
- refine notification texts: current `Verb` usage may be not grammatical and is not covered by i18n
- UI: templates for showing notifications in user profile, marking notifications as read, unread counter in the header (there is some views code in this PR, but it it not surfaced to the users yet)
- remove the internal email check

Co-authored-by: Anna Sirota <railla@noreply.localhost>
Reviewed-on: #80
Reviewed-by: Anna Sirota <railla@noreply.localhost>
2024-04-18 16:11:18 +02:00

66 lines
2.5 KiB
Python

"""blender_extensions URL Configuration
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/4.0/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: path('', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.conf import settings
from django.contrib import admin
from django.contrib.flatpages import views as flatpages_views
from django.urls import path, include, re_path
from django.views.static import serve
from django.views.generic.base import RedirectView
from drf_spectacular.views import SpectacularAPIView, SpectacularSwaggerView
import blender_id_oauth_client.urls
import common.views.errors
admin.site.enable_nav_sidebar = False
admin.site.site_header = settings.ADMIN_SITE_HEADER
urlpatterns = [
path('oauth/', include(blender_id_oauth_client.urls)),
path('admin/', include('loginas.urls')),
path('admin/', admin.site.urls),
path('', include('ratings.urls')),
path('', include('extensions.urls')),
path('', include('abuse.urls')),
path('', include('users.urls')),
path('', include('teams.urls')),
path('', include('reviewers.urls')),
path('', include('notifications.urls')),
path('api/swagger/', RedirectView.as_view(url='/api/v1/swagger/')),
path('api/v1/', SpectacularAPIView.as_view(), name='schema_v1'),
path('api/v1/swagger/', SpectacularSwaggerView.as_view(url_name='schema_v1'), name='swagger'),
# Flatpages
path('about/', flatpages_views.flatpage, {'url': '/about/'}, name='flatpage-about'),
re_path(r'^(?P<url>.*/)$', flatpages_views.flatpage),
]
handler400 = common.views.errors.ErrorView.as_view(status=400)
handler403 = common.views.errors.ErrorView.as_view(status=403)
handler404 = common.views.errors.ErrorView.as_view(status=404)
handler500 = common.views.errors.ErrorView.as_view(status=500)
if settings.DEBUG:
urlpatterns = [
re_path(
r'^media/(?P<path>.*)$',
serve,
{
'document_root': settings.MEDIA_ROOT,
},
),
path('__debug__/', include('debug_toolbar.urls')),
] + urlpatterns