1
|
|
|
""" |
2
|
|
|
byceps.blueprints.api.tourney.avatar.views |
3
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
4
|
|
|
|
5
|
|
|
:Copyright: 2006-2019 Jochen Kupperschmidt |
6
|
|
|
:License: Modified BSD, see LICENSE for details. |
7
|
|
|
""" |
8
|
|
|
|
9
|
|
|
from flask import abort, request |
10
|
|
|
|
11
|
|
|
from .....services.party import service as party_service |
12
|
|
|
from .....services.tourney.avatar import service as avatar_service |
13
|
|
|
from .....services.user import service as user_service |
14
|
|
|
from .....util.framework.blueprint import create_blueprint |
15
|
|
|
from .....util.image.models import ImageType |
16
|
|
|
from .....util.views import respond_created, respond_no_content |
17
|
|
|
|
18
|
|
|
from ...decorators import api_token_required |
19
|
|
|
|
20
|
|
|
from .forms import CreateForm |
21
|
|
|
|
22
|
|
|
|
23
|
|
|
blueprint = create_blueprint('api_tourney_avatar', __name__) |
24
|
|
|
|
25
|
|
|
|
26
|
|
|
ALLOWED_IMAGE_TYPES = frozenset([ |
27
|
|
|
ImageType.jpeg, |
28
|
|
|
ImageType.png, |
29
|
|
|
]) |
30
|
|
|
|
31
|
|
|
|
32
|
|
|
@blueprint.route('', methods=['POST']) |
33
|
|
|
@api_token_required |
34
|
|
|
@respond_created |
35
|
|
|
def create(): |
36
|
|
|
"""Create an avatar image.""" |
37
|
|
|
# Make `InputRequired` work on `FileField`. |
38
|
|
|
form_fields = request.form.copy() |
39
|
|
|
if request.files: |
40
|
|
|
form_fields.update(request.files) |
41
|
|
|
|
42
|
|
|
form = CreateForm(form_fields) |
43
|
|
|
|
44
|
|
|
if not form.validate(): |
45
|
|
|
abort(400, 'Form validation failed.') |
46
|
|
|
|
47
|
|
|
party_id = form.party_id.data |
48
|
|
|
creator_id = form.creator_id.data |
49
|
|
|
image = request.files.get('image') |
50
|
|
|
|
51
|
|
|
party = party_service.find_party(party_id) |
52
|
|
|
if not party: |
53
|
|
|
abort(400, 'Unknown party ID') |
54
|
|
|
|
55
|
|
|
creator = user_service.find_user(creator_id) |
56
|
|
|
if not creator: |
57
|
|
|
abort(400, 'Unknown creator ID') |
58
|
|
|
|
59
|
|
|
avatar = _create(party.id, creator.id, image) |
60
|
|
|
|
61
|
|
|
return avatar.url_path |
62
|
|
|
|
63
|
|
|
|
64
|
|
|
def _create(party_id, creator_id, image): |
65
|
|
|
if not image or not image.filename: |
66
|
|
|
abort(400, 'No file to upload has been specified.') |
67
|
|
|
|
68
|
|
|
try: |
69
|
|
|
return avatar_service.create_avatar_image( |
70
|
|
|
party_id, creator_id, image.stream, ALLOWED_IMAGE_TYPES |
71
|
|
|
) |
72
|
|
|
except avatar_service.ImageTypeProhibited as e: |
73
|
|
|
abort(400, str(e)) |
74
|
|
|
except FileExistsError: |
75
|
|
|
abort(409, 'File already exists, not overwriting.') |
76
|
|
|
|
77
|
|
|
|
78
|
|
|
@blueprint.route('/<uuid:avatar_id>', methods=['DELETE']) |
79
|
|
|
@api_token_required |
80
|
|
|
@respond_no_content |
81
|
|
|
def delete(avatar_id): |
82
|
|
|
"""Delete the avatar image.""" |
83
|
|
|
try: |
84
|
|
|
avatar_service.delete_avatar_image(avatar_id) |
85
|
|
|
except ValueError: |
86
|
|
|
abort(404) |
87
|
|
|
|