Switch to unified view

a/Allura/allura/controllers/discuss.py b/Allura/allura/controllers/discuss.py
...
...
13
from allura import model as M
13
from allura import model as M
14
from base import BaseController
14
from base import BaseController
15
from allura.lib import utils
15
from allura.lib import utils
16
from allura.lib import helpers as h
16
from allura.lib import helpers as h
17
from allura.lib.decorators import require_post
17
from allura.lib.decorators import require_post
18
from allura.lib.security import require, has_artifact_access
18
from allura.lib.security import require, has_access, require_access
19
from allura.lib.helpers import DateTimeConverter
19
from allura.lib.helpers import DateTimeConverter
20
20
21
from allura.lib.widgets import discuss as DW
21
from allura.lib.widgets import discuss as DW
22
from .attachments import AttachmentsController, AttachmentController
22
from .attachments import AttachmentsController, AttachmentController
23
23
...
...
141
    ThreadController=h.attrproxy('_discussion_controller', 'ThreadController')
141
    ThreadController=h.attrproxy('_discussion_controller', 'ThreadController')
142
    PostController=h.attrproxy('_discussion_controller', 'PostController')
142
    PostController=h.attrproxy('_discussion_controller', 'PostController')
143
    AttachmentController=h.attrproxy('_discussion_controller', 'AttachmentController')
143
    AttachmentController=h.attrproxy('_discussion_controller', 'AttachmentController')
144
144
145
    def _check_security(self):
145
    def _check_security(self):
146
        require(has_artifact_access('read', self.thread))
146
        require_access(self.thread, 'read')
147
147
148
    def __init__(self, discussion_controller, thread_id):
148
    def __init__(self, discussion_controller, thread_id):
149
        self._discussion_controller = discussion_controller
149
        self._discussion_controller = discussion_controller
150
        self.discussion = discussion_controller.discussion
150
        self.discussion = discussion_controller.discussion
151
        self.thread = self.M.Thread.query.get(_id=thread_id)
151
        self.thread = self.M.Thread.query.get(_id=thread_id)
...
...
173
    @h.vardec
173
    @h.vardec
174
    @expose()
174
    @expose()
175
    @require_post()
175
    @require_post()
176
    @validate(pass_validator, error_handler=index)
176
    @validate(pass_validator, error_handler=index)
177
    def post(self, **kw):
177
    def post(self, **kw):
178
        require(has_artifact_access('post', self.thread))
178
        require_access(self.thread, 'post', self.thread)
179
        kw = self.W.edit_post.to_python(kw, None)
179
        kw = self.W.edit_post.to_python(kw, None)
180
        if not kw['text']:
180
        if not kw['text']:
181
            flash('Your post was not saved. You must provide content.', 'error')
181
            flash('Your post was not saved. You must provide content.', 'error')
182
            redirect(request.referer)
182
            redirect(request.referer)
183
        file_info = kw.pop('file_info', None)
183
        file_info = kw.pop('file_info', None)
...
...
194
        redirect(request.referer)
194
        redirect(request.referer)
195
195
196
    @expose()
196
    @expose()
197
    @require_post()
197
    @require_post()
198
    def tag(self, labels, **kw):
198
    def tag(self, labels, **kw):
199
        require(has_artifact_access('post', self.thread))
199
        require_access(self.thread, 'post')
200
        self.thread.labels = labels.split(',')
200
        self.thread.labels = labels.split(',')
201
        redirect(request.referer)
201
        redirect(request.referer)
202
202
203
    @expose()
203
    @expose()
204
    @require_post()
204
    @require_post()
205
    def flag_as_spam(self, **kw):
205
    def flag_as_spam(self, **kw):
206
        require(has_artifact_access('moderate', self.thread))
206
        require_access(self.thread, 'moderate')
207
        self.thread.first_post.status='spam'
207
        self.thread.first_post.status='spam'
208
        flash('Thread flagged as spam.')
208
        flash('Thread flagged as spam.')
209
        redirect(request.referer)
209
        redirect(request.referer)
210
210
211
    @without_trailing_slash
211
    @without_trailing_slash
...
...
239
    ThreadController=h.attrproxy('_discussion_controller', 'ThreadController')
239
    ThreadController=h.attrproxy('_discussion_controller', 'ThreadController')
240
    PostController=h.attrproxy('_discussion_controller', 'PostController')
240
    PostController=h.attrproxy('_discussion_controller', 'PostController')
241
    AttachmentController=h.attrproxy('_discussion_controller', 'AttachmentController')
241
    AttachmentController=h.attrproxy('_discussion_controller', 'AttachmentController')
242
242
243
    def _check_security(self):
243
    def _check_security(self):
244
        require(has_artifact_access('read', self.post))
244
        require_access(self.post, 'read')
245
245
246
    def __init__(self, discussion_controller, thread, slug):
246
    def __init__(self, discussion_controller, thread, slug):
247
        self._discussion_controller = discussion_controller
247
        self._discussion_controller = discussion_controller
248
        self.thread = thread
248
        self.thread = thread
249
        self._post_slug = slug
249
        self._post_slug = slug
...
...
263
    @expose('jinja:allura:templates/discussion/post.html')
263
    @expose('jinja:allura:templates/discussion/post.html')
264
    @validate(pass_validator)
264
    @validate(pass_validator)
265
    def index(self, version=None, **kw):
265
    def index(self, version=None, **kw):
266
        c.post = self.W.post
266
        c.post = self.W.post
267
        if request.method == 'POST':
267
        if request.method == 'POST':
268
            require(has_artifact_access('moderate', self.post))
268
            require_access(self.post, 'moderate')
269
            post_fields = self.W.edit_post.to_python(kw, None)
269
            post_fields = self.W.edit_post.to_python(kw, None)
270
            file_info = post_fields.pop('file_info', None)
270
            file_info = post_fields.pop('file_info', None)
271
            if hasattr(file_info, 'file'):
271
            if hasattr(file_info, 'file'):
272
                self.post.attach(
272
                self.post.attach(
273
                    file_info.filename, file_info.file, content_type=file_info.type,
273
                    file_info.filename, file_info.file, content_type=file_info.type,
...
...
307
    @expose()
307
    @expose()
308
    @require_post()
308
    @require_post()
309
    @validate(pass_validator, error_handler=index)
309
    @validate(pass_validator, error_handler=index)
310
    @require_post(redir='.')
310
    @require_post(redir='.')
311
    def reply(self, **kw):
311
    def reply(self, **kw):
312
        require(has_artifact_access('post', self.thread))
312
        require_access(self.thread, 'post')
313
        kw = self.W.edit_post.to_python(kw, None)
313
        kw = self.W.edit_post.to_python(kw, None)
314
        self.thread.post(parent_id=self.post._id, **kw)
314
        self.thread.post(parent_id=self.post._id, **kw)
315
        self.thread.num_replies += 1
315
        self.thread.num_replies += 1
316
        redirect(request.referer)
316
        redirect(request.referer)
317
317
318
    @h.vardec
318
    @h.vardec
319
    @expose()
319
    @expose()
320
    @require_post()
320
    @require_post()
321
    @validate(pass_validator, error_handler=index)
321
    @validate(pass_validator, error_handler=index)
322
    def moderate(self, **kw):
322
    def moderate(self, **kw):
323
        require(has_artifact_access('moderate', self.post.thread))
323
        require_access(self.post.thread, 'moderate')
324
        if kw.pop('delete', None):
324
        if kw.pop('delete', None):
325
            self.post.delete()
325
            self.post.delete()
326
            self.thread.update_stats()
326
            self.thread.update_stats()
327
        elif kw.pop('spam', None):
327
        elif kw.pop('spam', None):
328
            self.post.status = 'spam'
328
            self.post.status = 'spam'
...
...
342
342
343
    @h.vardec
343
    @h.vardec
344
    @expose()
344
    @expose()
345
    @require_post()
345
    @require_post()
346
    def attach(self, file_info=None):
346
    def attach(self, file_info=None):
347
        require(has_artifact_access('moderate', self.post))
347
        require_access(self.post, 'moderate')
348
        if hasattr(file_info, 'file'):
348
        if hasattr(file_info, 'file'):
349
            mime_type = file_info.type
349
            mime_type = file_info.type
350
            # If mime type was not passed or bogus, guess it
350
            # If mime type was not passed or bogus, guess it
351
            if not mime_type or '/' not in mime_type:
351
            if not mime_type or '/' not in mime_type:
352
                mime_type = utils.guess_mime_type(file_info.filename)
352
                mime_type = utils.guess_mime_type(file_info.filename)
...
...
380
    PostController=h.attrproxy('_discussion_controller', 'PostController')
380
    PostController=h.attrproxy('_discussion_controller', 'PostController')
381
    AttachmentController=h.attrproxy('_discussion_controller', 'AttachmentController')
381
    AttachmentController=h.attrproxy('_discussion_controller', 'AttachmentController')
382
382
383
383
384
    def _check_security(self):
384
    def _check_security(self):
385
        require(has_artifact_access('moderate', self.discussion))
385
        require_access(self.discussion, 'moderate')
386
386
387
    def __init__(self, discussion_controller):
387
    def __init__(self, discussion_controller):
388
        self._discussion_controller = discussion_controller
388
        self._discussion_controller = discussion_controller
389
389
390
    @LazyProperty
390
    @LazyProperty
...
...
450
    @h.vardec
450
    @h.vardec
451
    @expose()
451
    @expose()
452
    @require_post()
452
    @require_post()
453
    @validate(pass_validator, error_handler=h.json_validation_error)
453
    @validate(pass_validator, error_handler=h.json_validation_error)
454
    def reply(self, **kw):
454
    def reply(self, **kw):
455
        require(has_artifact_access('post', self.thread))
455
        require_access(self.thread, 'post')
456
        kw = self.W.edit_post.to_python(kw, None)
456
        kw = self.W.edit_post.to_python(kw, None)
457
        post = self.thread.post(parent_id=self.post._id, **kw)
457
        post = self.thread.post(parent_id=self.post._id, **kw)
458
        self.thread.num_replies += 1
458
        self.thread.num_replies += 1
459
        redirect(post.slug.split('/')[-1] + '/')
459
        redirect(post.slug.split('/')[-1] + '/')
460
460
...
...
467
    @h.vardec
467
    @h.vardec
468
    @expose()
468
    @expose()
469
    @require_post()
469
    @require_post()
470
    @validate(pass_validator, error_handler=h.json_validation_error)
470
    @validate(pass_validator, error_handler=h.json_validation_error)
471
    def new(self, **kw):
471
    def new(self, **kw):
472
        require(has_artifact_access('post', self.thread))
472
        require_access(self.thread, 'post')
473
        kw = self.W.edit_post.to_python(kw, None)
473
        kw = self.W.edit_post.to_python(kw, None)
474
        p = self.thread.add_post(**kw)
474
        p = self.thread.add_post(**kw)
475
        redirect(p.slug + '/')
475
        redirect(p.slug + '/')
476
476
477
class AppDiscussionRestController(AppDiscussionController):
477
class AppDiscussionRestController(AppDiscussionController):