Skip to content

Commit

Permalink
Merge pull request #1979 from dandi/mailchimp
Browse files Browse the repository at this point in the history
Add dashboard link to view to emit user list as Mailchimp-compatible CSV
  • Loading branch information
waxlamp committed Jul 19, 2024
2 parents 460da4d + b6884ef commit bdd6dd1
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 2 deletions.
1 change: 1 addition & 0 deletions dandiapi/api/templates/dashboard/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ <h1 id="site-name"><a href="{% url 'admin:index' %}">{{ site_header|default:_('D
<a class="dandi-navbar-link" href="{% url 'dashboard-index' %}">Dashboard Home</a>
<a class="dandi-navbar-link" href="{% url "admin:auth_user_changelist" %}">Users</a>
<a class="dandi-navbar-link" href="{% url 'admin:index' %}">Admin</a>
<a class="dandi-navbar-link" href="{% url 'mailchimp-csv' %}">Mailchimp CSV</a>
{% if title %} &rsaquo; {{ title }}{% endif %}
</div>
{% endblock %}
3 changes: 2 additions & 1 deletion dandiapi/api/views/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from .asset import AssetViewSet, NestedAssetViewSet
from .auth import auth_token_view, authorize_view, user_questionnaire_form_view
from .dandiset import DandisetViewSet
from .dashboard import DashboardView, user_approval_view
from .dashboard import DashboardView, mailchimp_csv_view, user_approval_view
from .info import info_view
from .root import root_content_view
from .stats import stats_view
Expand All @@ -25,6 +25,7 @@
'authorize_view',
'auth_token_view',
'blob_read_view',
'mailchimp_csv_view',
'upload_initialize_view',
'upload_complete_view',
'upload_validate_view',
Expand Down
39 changes: 38 additions & 1 deletion dandiapi/api/views/dashboard.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
from __future__ import annotations

import csv
from typing import TYPE_CHECKING

from django.conf import settings
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from django.contrib.auth.models import User
from django.core.exceptions import PermissionDenied, ValidationError
from django.db.models import Exists, OuterRef
from django.http import HttpRequest, HttpResponseRedirect
from django.http import HttpRequest, HttpResponseRedirect, StreamingHttpResponse
from django.shortcuts import get_object_or_404, render
from django.views.decorators.http import require_http_methods
from django.views.generic.base import TemplateView
Expand All @@ -17,6 +18,8 @@
from dandiapi.api.views.users import social_account_to_dict

if TYPE_CHECKING:
from collections.abc import Iterator

from allauth.socialaccount.models import SocialAccount


Expand Down Expand Up @@ -82,6 +85,40 @@ def _users(self):
)


def mailchimp_csv_view(request: HttpRequest) -> StreamingHttpResponse:
"""Generate a Mailchimp-compatible CSV file of all active users."""
# Exclude the django-guardian anonymous user account.
users = User.objects.filter(metadata__status=UserMetadata.Status.APPROVED).exclude(
username='AnonymousUser'
)

fieldnames = ['email', 'first_name', 'last_name']
data = users.values(*fieldnames).iterator()

def streaming_output() -> Iterator[str]:
"""Stream out the header and CSV rows (for consumption by streaming response)."""

# This class implements a filelike's write() interface to provide a way
# for the CSV writer to "return" the CSV lines as strings.
class Echo:
def write(self, value):
return value

# Yield back the rows of the CSV file.
writer = csv.DictWriter(Echo(), fieldnames=fieldnames)
yield writer.writeheader()
for row in data:
yield writer.writerow(row)

return StreamingHttpResponse(
streaming_output(),
content_type='text/csv',
headers={
'Content-Disposition': 'attachment; filename="dandi_users_mailchimp.csv"',
},
)


@require_http_methods(['GET', 'POST'])
def user_approval_view(request: HttpRequest, username: str):
# Redirect user to login if they're not authenticated
Expand Down
2 changes: 2 additions & 0 deletions dandiapi/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
authorize_view,
blob_read_view,
info_view,
mailchimp_csv_view,
root_content_view,
stats_view,
upload_complete_view,
Expand Down Expand Up @@ -105,6 +106,7 @@ def to_url(self, value):
path('admin/', admin.site.urls),
path('dashboard/', DashboardView.as_view(), name='dashboard-index'),
path('dashboard/user/<str:username>/', user_approval_view, name='user-approval'),
path('dashboard/mailchimp/', mailchimp_csv_view, name='mailchimp-csv'),
# this url overrides the authorize url in oauth2_provider.urls to
# support our user signup workflow
re_path(r'^oauth/authorize/$', authorize_view, name='authorize'),
Expand Down

0 comments on commit bdd6dd1

Please sign in to comment.