Passed
Push — main ( d49116...8987e2 )
by Jochen
04:25
created

byceps.blueprints.site.user.avatar.views._update()   A

Complexity

Conditions 5

Size

Total Lines 12
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 22.5589

Importance

Changes 0
Metric Value
cc 5
eloc 10
nop 2
dl 0
loc 12
ccs 1
cts 9
cp 0.1111
crap 22.5589
rs 9.3333
c 0
b 0
f 0
1
"""
2
byceps.blueprints.site.user.avatar.views
3
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4
5
:Copyright: 2006-2021 Jochen Kupperschmidt
6
:License: Revised BSD (see `LICENSE` file for details)
7
"""
8
9 1
from flask import abort, g, request
10 1
from flask_babel import gettext
11
12 1
from .....services.image import service as image_service
13 1
from .....services.user_avatar import service as avatar_service
14 1
from .....signals import user_avatar as user_avatar_signals
15 1
from .....util.framework.blueprint import create_blueprint
16 1
from .....util.framework.flash import flash_notice, flash_success
17 1
from .....util.image.models import ImageType
18 1
from .....util.framework.templating import templated
19 1
from .....util.views import redirect_to, respond_no_content
20
21 1
from .forms import UpdateForm
22
23
24 1
blueprint = create_blueprint('user_avatar', __name__)
25
26
27 1
ALLOWED_IMAGE_TYPES = frozenset(
28
    [
29
        ImageType.jpeg,
30
        ImageType.png,
31
    ]
32
)
33
34
35 1
@blueprint.get('/me/avatar/update')
36 1
@templated
37 1
def update_form(erroneous_form=None):
38
    """Show a form to update the current user's avatar image."""
39
    _get_current_user_or_404()
40
41
    form = erroneous_form if erroneous_form else UpdateForm()
42
43
    image_type_names = image_service.get_image_type_names(ALLOWED_IMAGE_TYPES)
44
45
    return {
46
        'form': form,
47
        'allowed_types': image_type_names,
48
        'maximum_dimensions': avatar_service.MAXIMUM_DIMENSIONS,
49
    }
50
51
52 1
@blueprint.post('/me/avatar')
53
def update():
54
    """Update the current user's avatar image."""
55
    user = _get_current_user_or_404()
56
57
    # Make `InputRequired` work on `FileField`.
58
    form_fields = request.form.copy()
59
    if request.files:
60
        form_fields.update(request.files)
61
62
    form = UpdateForm(form_fields)
63
64
    if not form.validate():
65
        return update_form(form)
66
67
    image = request.files.get('image')
68
69
    _update(user.id, image)
70
71
    flash_success(gettext('Avatar image has been updated.'), icon='upload')
72
    user_avatar_signals.avatar_updated.send(None, user_id=user.id)
73
74
    return redirect_to('user_settings.view')
75
76
77 1
def _update(user_id, image):
78
    if not image or not image.filename:
79
        abort(400, 'No file to upload has been specified.')
80
81
    try:
82
        avatar_service.update_avatar_image(
83
            user_id, image.stream, ALLOWED_IMAGE_TYPES
84
        )
85
    except avatar_service.ImageTypeProhibited as e:
86
        abort(400, str(e))
87
    except FileExistsError:
88
        abort(409, 'File already exists, not overwriting.')
89
90
91 1
@blueprint.delete('/me/avatar')
92 1
@respond_no_content
93
def delete():
94
    """Remove the current user's avatar image."""
95
    user = _get_current_user_or_404()
96
97
    try:
98
        avatar_service.remove_avatar_image(user.id)
99
    except ValueError:
100
        # No avatar selected.
101
        # But that's ok, deletions should be idempotent.
102
        flash_notice(gettext('No avatar image is set that could be removed.'))
103
    else:
104
        flash_success(gettext('Avatar image has been removed.'))
105
106
107 1
def _get_current_user_or_404():
108
    user = g.user
109
110
    if not user.authenticated:
111
        abort(404)
112
113
    return user
114