Projet

Général

Profil

0001-WIP-support-avatar-picture-in-user-profile-26022.patch

Paul Marillonnet, 04 septembre 2018 20:34

Télécharger (7,01 ko)

Voir les différences:

Subject: [PATCH] WIP support avatar picture in user profile (#26022)

 src/authentic2/attribute_kinds.py             | 10 +++-
 src/authentic2/custom_user/apps.py            | 20 +++++--
 .../templates/authentic2/accounts_edit.html   |  7 ++-
 src/authentic2/utils.py                       | 58 ++++++++++++++++++-
 4 files changed, 86 insertions(+), 9 deletions(-)
src/authentic2/attribute_kinds.py
17 17
from .plugins import collect_from_plugins
18 18
from . import app_settings
19 19
from .forms import widgets
20
from .utils import store_image
20 21

  
21 22
capfirst = allow_lazy(capfirst, unicode)
22 23

  
......
151 152
        'field_class': PhoneNumberField,
152 153
        'rest_framework_field_class': PhoneNumberDRFField,
153 154
    },
155
    {
156
        'label': _('image'),
157
        'name': 'image',
158
        'field_class': forms.ImageField,
159
        'serialize': store_image,
160
        'deserialize': lambda x: x,
161
        'rest_framework_field_class': serializers.ImageField,
162
    },
154 163
]
155 164

  
156

  
157 165
def get_attribute_kinds():
158 166
    attribute_kinds = {}
159 167
    for attribute_kind in chain(DEFAULT_ATTRIBUTE_KINDS, app_settings.A2_ATTRIBUTE_KINDS):
src/authentic2/custom_user/apps.py
10 10
        from django.db.models.signals import post_migrate
11 11

  
12 12
        post_migrate.connect(
13
            self.create_first_name_last_name_attributes,
13
            self.create_custom_attributes,
14 14
            sender=self)
15 15

  
16
    def create_first_name_last_name_attributes(self, app_config, verbosity=2, interactive=True,
16
    def create_custom_attributes(self, app_config, verbosity=2, interactive=True,
17 17
                                               using=DEFAULT_DB_ALIAS, **kwargs):
18 18
        from django.utils import translation
19 19
        from django.utils.translation import ugettext_lazy as _
......
50 50
                      'asked_on_registration': True,
51 51
                      'user_editable': True,
52 52
                      'user_visible': True})
53
        attrs['avatar_picture'], created = Attribute.objects.get_or_create(
54
            name='avatar_picture',
55
            defaults={'kind': 'image',
56
                      'label': _('Avatar picture'),
57
                      'required': False,
58
                      'asked_on_registration': False,
59
                      'user_editable': True,
60
                      'user_visible': True})
53 61

  
54
        serialize = get_kind('string').get('serialize')
55 62
        for user in User.objects.all():
56
            for attr_name in attrs:
63
            for at in attrs:
64
                serialize = get_kind(at.kind).get('serialize')
57 65
                av, created = AttributeValue.objects.get_or_create(
58 66
                    content_type=content_type,
59 67
                    object_id=user.id,
60
                    attribute=attrs[attr_name],
68
                    attribute=attrs[at],
61 69
                    defaults={
62 70
                        'multiple': False,
63 71
                        'verified': False,
64
                        'content': serialize(getattr(user, attr_name, None))
72
                        'content': serialize(getattr(user, at, None))
65 73
                    })
src/authentic2/templates/authentic2/accounts_edit.html
12 12
{% endblock %}
13 13

  
14 14
{% block content %}
15
  <form method="post">
15
    {% if form.is_multipart %}
16
      <form enctype="multipart/form-data" method="post">
17
    {% else %}
18
      <form method="post">
19
    {% endif %}
20

  
16 21
    {% csrf_token %}
17 22
    {{ form.as_p }}
18 23
    {% if form.instance and form.instance.id %}
src/authentic2/utils.py
8 8
import uuid
9 9
import datetime
10 10
import copy
11
import fcntl
12
import os
11 13

  
12 14
from functools import wraps
13 15
from itertools import islice, chain, count
14

  
16
from PIL import Image
15 17
from importlib import import_module
18
from hashlib import md5
19
from base64 import b32encode
16 20

  
17 21
from django.conf import settings
18 22
from django.http import HttpResponseRedirect, HttpResponse
......
30 34
from django.template.loader import render_to_string, TemplateDoesNotExist
31 35
from django.core.mail import send_mail
32 36
from django.core import signing
37
from django.core.files.storage import default_storage
33 38
from django.core.urlresolvers import reverse, NoReverseMatch
34 39
from django.utils.formats import localize
35 40
from django.contrib import messages
......
1073 1078
        if ou_value is not None:
1074 1079
            return ou_value
1075 1080
    return default
1081

  
1082

  
1083
def store_image(image, owner_uuid, *args, **kwargs):
1084
    logger = logging.getLogger(__name__)
1085

  
1086
    digest = md5(value.read())
1087
    image_uuid = b32encode(digest)[0:63]
1088
    image_format = image.image.format
1089

  
1090
    filefolder = default_storage.path('{root}/avatars/{oid}'.format(
1091
        root=app_settings.MEDIA_ROOT,
1092
        oid=owner_uuid))
1093

  
1094
    filepath = os.path.join(
1095
            filefolder,
1096
            "{uuid}.{ext}".format(uuid=image_uuid, ext=image_format))
1097

  
1098
    try:
1099
        if not os.path.exists(local_folder):
1100
            os.makesdir(local_folder)
1101

  
1102
        with open(filepath, 'wb') as f:
1103
            try:
1104
                fcntl.lockf(f, fcntl.LOCK_EX | fcntl.LOCK_NB)
1105
                with tempfile.NamedTemporaryFile(mode='w', dir=folder, delete=False) as temp:
1106
                    try:
1107
                        image.seek(0)
1108
                        temp.write(image.read())
1109
                        temp.flush()
1110
                        os.rename(temp.name, filepath)
1111
                        pass
1112
                    except:
1113
                        logger.error("Could'nt store fingerprint for entity ID", entity_id)
1114
                        os.unlink(temp.name)
1115
                    finally:
1116
                        fcntl.lockf(f, fcntl.LOCK_UN)
1117
            except:
1118
                logger.error("Couldn't hold exclusive lock for file {}".format(filepath))
1119
            finally:
1120
                fctnl.lockf(f, fcntl.LOCK_UN)
1121
    except IOError:
1122
        return
1123

  
1124
    return filepath
1125

  
1126

  
1127
def retrieve_image_url(image_filename):
1128
    media_url = app_settings.MEDIA_URL
1129
    # xxx retrieve everything after MEDIA_ROOT, concatenate craft the
1130
    # appropriate media url
1131
    pass
1076
-