From 5c129b2cf630567d241e28237645a463d5aa4c5b Mon Sep 17 00:00:00 2001 From: Valentin Deniaud Date: Tue, 9 Mar 2021 17:23:41 +0100 Subject: [PATCH 2/3] manager: move user export code (#43153) --- src/authentic2/manager/user_export.py | 80 +++++++++++++++++++++++++++ src/authentic2/manager/user_views.py | 51 +---------------- 2 files changed, 83 insertions(+), 48 deletions(-) create mode 100644 src/authentic2/manager/user_export.py diff --git a/src/authentic2/manager/user_export.py b/src/authentic2/manager/user_export.py new file mode 100644 index 00000000..c364f212 --- /dev/null +++ b/src/authentic2/manager/user_export.py @@ -0,0 +1,80 @@ +# authentic2 - versatile identity manager +# Copyright (C) 2010-2021 Entr'ouvert +# +# This program is free software: you can redistribute it and/or modify it +# under the terms of the GNU Affero General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +import collections +import datetime + +import tablib + +from django.contrib.auth import get_user_model +from django.contrib.contenttypes.models import ContentType + +from authentic2.manager.resources import UserResource +from authentic2.models import Attribute, AttributeValue + + +def iso(rec): + if rec is None or rec == {}: + return '' + if hasattr(rec, 'strftime'): + if isinstance(rec, datetime.datetime): + _format = "%Y-%m-%d %H:%M:%S" + else: + _format = "%Y-%m-%d" + return rec.strftime(_format) + return rec + + +def get_user_attrs(): + at_mapping = {a.id: a for a in Attribute.objects.all()} + avs = AttributeValue.objects.filter( + content_type=ContentType.objects.get_for_model(get_user_model()))\ + .filter(attribute__disabled=False).values() + + user_attrs = collections.defaultdict(dict) + for av in avs: + user_attrs[av['object_id']][at_mapping[av['attribute_id']].name] = av['content'] + + return user_attrs + + +def get_user_dataset(qs): + user_resource = UserResource() + fields = user_resource._meta.export_order + ('email_verified', 'is_active', 'modified') + attributes = [attr.name for attr in Attribute.objects.all()] + headers = fields + tuple(['attribute_%s' % attr for attr in attributes]) + user_attrs = get_user_attrs() + + def create_record(user): + record = [] + for field in fields: + if field == 'roles': + value = user_resource.dehydrate_roles(user) + else: + value = getattr(user, field) + record.append(value) + + attr_d = user_attrs[user.pk] + for attr in attributes: + record.append(attr_d.get(attr)) + + return [iso(x) for x in record] + + dataset = tablib.Dataset(headers=headers) + for user in qs: + dataset.append(create_record(user)) + + return dataset diff --git a/src/authentic2/manager/user_views.py b/src/authentic2/manager/user_views.py index 7dc9b6c9..24fd6684 100644 --- a/src/authentic2/manager/user_views.py +++ b/src/authentic2/manager/user_views.py @@ -15,7 +15,6 @@ # along with this program. If not, see . import base64 -import datetime import collections import operator @@ -28,7 +27,6 @@ from django.core.exceptions import PermissionDenied from django.core.mail import EmailMultiAlternatives from django.template import loader from django.contrib.auth import get_user_model, REDIRECT_FIELD_NAME -from django.contrib.contenttypes.models import ContentType from django.contrib import messages from django.views.generic import FormView, TemplateView, DetailView from django.views.generic.edit import BaseFormView @@ -36,9 +34,7 @@ from django.views.generic.detail import SingleObjectMixin from django.http import Http404, FileResponse, HttpResponseRedirect from django.shortcuts import get_object_or_404 -import tablib - -from authentic2.models import Attribute, AttributeValue, PasswordReset +from authentic2.models import Attribute, PasswordReset from authentic2.utils import send_password_reset_mail, redirect, select_next_url, make_url, switch_user from authentic2.a2_rbac.utils import get_default_ou from authentic2 import hooks @@ -59,6 +55,7 @@ from .forms import (UserSearchForm, UserAddForm, UserEditForm, from .resources import UserResource from .utils import get_ou_count, has_show_username from .journal_views import BaseJournalView +from .user_export import get_user_dataset from . import app_settings User = get_user_model() @@ -485,49 +482,7 @@ class UsersExportView(ExportMixin, UsersView): return self._dataset.export('csv') def get_dataset(self): - user_resource = UserResource() - fields = user_resource._meta.export_order + ('email_verified', 'is_active', 'modified') - attributes = [attr.name for attr in Attribute.objects.all()] - headers = fields + tuple(['attribute_%s' % attr for attr in attributes]) - - at_mapping = {a.id: a for a in Attribute.objects.all()} - avs = AttributeValue.objects.filter( - content_type=ContentType.objects.get_for_model(get_user_model()))\ - .filter(attribute__disabled=False).values() - - user_attrs = collections.defaultdict(dict) - for av in avs: - user_attrs[av['object_id']][at_mapping[av['attribute_id']].name] = av['content'] - - def iso(rec): - if rec is None or rec == {}: - return '' - if hasattr(rec, 'strftime'): - if isinstance(rec, datetime.datetime): - _format = "%Y-%m-%d %H:%M:%S" - else: - _format = "%Y-%m-%d" - return rec.strftime(_format) - return rec - - def create_record(user): - record = [] - for field in fields: - if field == 'roles': - value = user_resource.dehydrate_roles(user) - else: - value = getattr(user, field) - record.append(value) - - attr_d = user_attrs[user.pk] - for attr in attributes: - record.append(attr_d.get(attr)) - - return [iso(x) for x in record] - - self._dataset = tablib.Dataset(headers=headers) - for user in self.get_data(): - self._dataset.append(create_record(user)) + self._dataset = get_user_dataset(self.get_data()) return self -- 2.20.1