Piwigo: some sanity checks before adding to collection as per Elrond's suggestions.
[mediagoblin.git] / mediagoblin / plugins / piwigo / views.py
CommitLineData
427beb08
E
1# GNU MediaGoblin -- federated, autonomous media hosting
2# Copyright (C) 2013 MediaGoblin contributors. See AUTHORS.
3#
4# This program is free software: you can redistribute it and/or modify
5# it under the terms of the GNU Affero General Public License as published by
6# the Free Software Foundation, either version 3 of the License, or
7# (at your option) any later version.
8#
9# This program is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12# GNU Affero General Public License for more details.
13#
14# You should have received a copy of the GNU Affero General Public License
15# along with this program. If not, see <http://www.gnu.org/licenses/>.
16
17import logging
398d3841 18import re
c732f422
JW
19from os.path import splitext
20import shutil
427beb08 21
90d7de25 22from werkzeug.exceptions import MethodNotAllowed, BadRequest, NotImplemented
e4e5948c 23from werkzeug.wrappers import BaseResponse
427beb08
E
24
25from mediagoblin.meddleware.csrf import csrf_exempt
7fb419dd 26from mediagoblin.auth.lib import fake_login_attempt
c732f422
JW
27from mediagoblin.media_types import sniff_media
28from mediagoblin.submit.lib import check_file_field, prepare_queue_task, \
6c1467d5 29 run_process_media, new_upload_entry
c732f422 30
41501106
MS
31from mediagoblin.user_pages.lib import add_media_to_collection
32from mediagoblin.db.models import Collection
33
4adc3a85
E
34from .tools import CmdTable, response_xml, check_form, \
35 PWGSession, PwgNamedArray, PwgError
c1df8d19 36from .forms import AddSimpleForm, AddForm
427beb08
E
37
38
39_log = logging.getLogger(__name__)
40
41
427beb08
E
42@CmdTable("pwg.session.login", True)
43def pwg_login(request):
44 username = request.form.get("username")
45 password = request.form.get("password")
7fb419dd
E
46 user = request.db.User.query.filter_by(username=username).first()
47 if not user:
f035ec3d 48 _log.info("User %r not found", username)
7fb419dd 49 fake_login_attempt()
4adc3a85 50 return PwgError(999, 'Invalid username/password')
7fb419dd 51 if not user.check_login(password):
f035ec3d 52 _log.warn("Wrong password for %r", username)
4adc3a85 53 return PwgError(999, 'Invalid username/password')
f035ec3d 54 _log.info("Logging %r in", username)
7fb419dd
E
55 request.session["user_id"] = user.id
56 request.session.save()
e4e5948c 57 return True
bd3bc044
E
58
59
60@CmdTable("pwg.session.logout")
61def pwg_logout(request):
62 _log.info("Logout")
7fb419dd 63 request.session.delete()
e4e5948c 64 return True
bd3bc044
E
65
66
67@CmdTable("pwg.getVersion")
68def pwg_getversion(request):
9924cd0f 69 return "2.5.0 (MediaGoblin)"
cf0816c1
E
70
71
72@CmdTable("pwg.session.getStatus")
73def pwg_session_getStatus(request):
66594603
E
74 if request.user:
75 username = request.user.username
76 else:
77 username = "guest"
78 return {'username': username}
e4e5948c
E
79
80
81@CmdTable("pwg.categories.getList")
82def pwg_categories_getList(request):
41501106
MS
83 collections = Collection.query.filter_by(
84 get_creator=request.user).order_by(Collection.title)
85
86 catlist = [{'id': -29711,
cf0816c1 87 'uppercats': "-29711",
41501106
MS
88 'name': "All my images"}]
89
7da90d56
MS
90 if request.user:
91 for c in collections:
92 catlist.append({'id': c.id,
93 'uppercats': str(c.id),
94 'name': c.title,
95 'comment': c.description
96 })
41501106 97
e4e5948c
E
98 return {
99 'categories': PwgNamedArray(
100 catlist,
101 'category',
102 (
103 'id',
104 'url',
105 'nb_images',
106 'total_nb_images',
107 'nb_categories',
108 'date_last',
109 'max_date_last',
110 )
111 )
112 }
427beb08
E
113
114
398d3841
E
115@CmdTable("pwg.images.exist")
116def pwg_images_exist(request):
117 return {}
118
119
79f87b97
E
120@CmdTable("pwg.images.addSimple", True)
121def pwg_images_addSimple(request):
122 form = AddSimpleForm(request.form)
123 if not form.validate():
124 _log.error("addSimple: form failed")
125 raise BadRequest()
126 dump = []
127 for f in form:
128 dump.append("%s=%r" % (f.name, f.data))
18e64476
MS
129 _log.info("addSimple: %r %s %r", request.form, " ".join(dump),
130 request.files)
79f87b97 131
f6f55769
E
132 if not check_file_field(request, 'image'):
133 raise BadRequest()
134
c732f422
JW
135 filename = request.files['image'].filename
136
137 # Sniff the submitted media to determine which
138 # media plugin should handle processing
139 media_type, media_manager = sniff_media(
140 request.files['image'])
141
142 # create entry and save in database
6c1467d5 143 entry = new_upload_entry(request.user)
c732f422
JW
144 entry.media_type = unicode(media_type)
145 entry.title = (
146 unicode(form.name.data)
147 or unicode(splitext(filename)[0]))
148
149 entry.description = unicode(form.comment.data)
150
c732f422
JW
151 '''
152 # Process the user's folksonomy "tags"
153 entry.tags = convert_to_tag_list_of_dicts(
154 form.tags.data)
155 '''
156
157 # Generate a slug from the title
158 entry.generate_slug()
159
160 queue_file = prepare_queue_task(request.app, entry, filename)
161
162 with queue_file:
163 shutil.copyfileobj(request.files['image'].stream,
164 queue_file,
165 length=4 * 1048576)
166
167 # Save now so we have this data before kicking off processing
168 entry.save()
169
170 # Pass off to processing
171 #
172 # (... don't change entry after this point to avoid race
173 # conditions with changes to the document via processing code)
174 feed_url = request.urlgen(
175 'mediagoblin.user_pages.atom_feed',
176 qualified=True, user=request.user.username)
177 run_process_media(entry, feed_url)
178
41501106
MS
179 collection_id = form.category.data
180 if collection_id > 0:
181 collection = Collection.query.get(collection_id)
94d31920
MS
182 if collection is not None and collection.creator == request.user.id:
183 add_media_to_collection(collection, entry, "")
41501106 184
c732f422
JW
185 return {'image_id': entry.id, 'url': entry.url_for_self(request.urlgen,
186 qualified=True)}
187
79f87b97 188
398d3841
E
189md5sum_matcher = re.compile(r"^[0-9a-fA-F]{32}$")
190
c732f422 191
398d3841
E
192def fetch_md5(request, parm_name, optional_parm=False):
193 val = request.form.get(parm_name)
194 if (val is None) and (not optional_parm):
195 _log.error("Parameter %s missing", parm_name)
196 raise BadRequest("Parameter %s missing" % parm_name)
197 if not md5sum_matcher.match(val):
198 _log.error("Parameter %s=%r has no valid md5 value", parm_name, val)
199 raise BadRequest("Parameter %s is not md5" % parm_name)
200 return val
201
202
203@CmdTable("pwg.images.addChunk", True)
204def pwg_images_addChunk(request):
205 o_sum = fetch_md5(request, 'original_sum')
206 typ = request.form.get('type')
207 pos = request.form.get('position')
208 data = request.form.get('data')
209
210 # Validate params:
211 pos = int(pos)
212 if not typ in ("file", "thumb"):
213 _log.error("type %r not allowed for now", typ)
214 return False
215
216 _log.info("addChunk for %r, type %r, position %d, len: %d",
217 o_sum, typ, pos, len(data))
218 if typ == "thumb":
219 _log.info("addChunk: Ignoring thumb, because we create our own")
220 return True
221
222 return True
223
224
c1df8d19
E
225@CmdTable("pwg.images.add", True)
226def pwg_images_add(request):
227 _log.info("add: %r", request.form)
228 form = AddForm(request.form)
229 check_form(form)
230
231 return {'image_id': 123456, 'url': ''}
232
233
427beb08
E
234@csrf_exempt
235def ws_php(request):
236 if request.method not in ("GET", "POST"):
237 _log.error("Method %r not supported", request.method)
238 raise MethodNotAllowed()
239
240 func = CmdTable.find_func(request)
241 if not func:
242 _log.warn("wsphp: Unhandled %s %r %r", request.method,
243 request.args, request.form)
90d7de25 244 raise NotImplemented()
427beb08 245
7fb419dd
E
246 with PWGSession(request) as session:
247 result = func(request)
427beb08 248
7fb419dd
E
249 if isinstance(result, BaseResponse):
250 return result
e4e5948c 251
7fb419dd
E
252 response = response_xml(result)
253 session.save_to_cookie(response)
dc7c26f3 254
7fb419dd 255 return response