Switch to unified view

a/Allura/allura/controllers/discuss.py b/Allura/allura/controllers/discuss.py
...
...
36
from allura.lib.security import require, has_access, require_access
36
from allura.lib.security import require, has_access, require_access
37
from allura.lib.helpers import DateTimeConverter
37
from allura.lib.helpers import DateTimeConverter
38
38
39
from allura.lib.widgets import discuss as DW
39
from allura.lib.widgets import discuss as DW
40
from .attachments import AttachmentsController, AttachmentController
40
from .attachments import AttachmentsController, AttachmentController
41
from .feed import Feed, FeedController
41
42
42
log = logging.getLogger(__name__)
43
log = logging.getLogger(__name__)
43
44
44
class pass_validator(object):
45
class pass_validator(object):
45
    def validate(self, v, s):
46
    def validate(self, v, s):
...
...
66
    thread = DW.Thread()
67
    thread = DW.Thread()
67
    post = DW.Post()
68
    post = DW.Post()
68
    thread_header = DW.ThreadHeader()
69
    thread_header = DW.ThreadHeader()
69
70
70
# Controllers
71
# Controllers
71
class DiscussionController(BaseController):
72
class DiscussionController(BaseController, FeedController):
72
    M=ModelConfig
73
    M=ModelConfig
73
    W=WidgetConfig
74
    W=WidgetConfig
74
75
75
    def __init__(self):
76
    def __init__(self):
76
        setattr(self, 'feed.rss', self.feed)
77
        setattr(self, 'feed.atom', self.feed)
78
        if not hasattr(self, 'ThreadController'):
77
        if not hasattr(self, 'ThreadController'):
79
            self.ThreadController = ThreadController
78
            self.ThreadController = ThreadController
80
        if not hasattr(self, 'PostController'):
79
        if not hasattr(self, 'PostController'):
81
            self.PostController = PostController
80
            self.PostController = PostController
82
        if not hasattr(self, 'AttachmentController'):
81
        if not hasattr(self, 'AttachmentController'):
...
...
104
            else:
103
            else:
105
                thread['subscription'] = False
104
                thread['subscription'] = False
106
            M.session.artifact_orm_session._get().skip_mod_date = True
105
            M.session.artifact_orm_session._get().skip_mod_date = True
107
        redirect(request.referer)
106
        redirect(request.referer)
108
107
109
    @without_trailing_slash
108
    def get_feed(self, project, app, user):
110
    @expose()
109
        """Return a :class:`allura.controllers.feed.Feed` object describing
111
    @validate(dict(
110
        the xml feed for this controller.
112
            since=DateTimeConverter(if_empty=None),
111
113
            until=DateTimeConverter(if_empty=None),
112
        Overrides :meth:`allura.controllers.feed.FeedController.get_feed`.
114
            page=validators.Int(if_empty=None),
113
115
            limit=validators.Int(if_empty=None)))
114
        """
116
    def feed(self, since=None, until=None, page=None, limit=None, **kw):
115
        return Feed(
117
        if request.environ['PATH_INFO'].endswith('.atom'):
118
            feed_type = 'atom'
119
        else:
120
            feed_type = 'rss'
121
        title = 'Recent posts to %s' % self.discussion.name
122
        feed = M.Feed.feed(
123
            dict(ref_id={'$in': [t.index_id() for t in self.discussion.threads]}),
116
            dict(ref_id={'$in': [t.index_id() for t in self.discussion.threads]}),
124
            feed_type,
117
            'Recent posts to %s' % self.discussion.name,
125
            title,
126
            self.discussion.url(),
118
            self.discussion.url())
127
            title,
119
128
            since, until, page, limit)
129
        response.headers['Content-Type'] = ''
130
        response.content_type = 'application/xml'
131
        return feed.writeString('utf-8')
132
120
133
class AppDiscussionController(DiscussionController):
121
class AppDiscussionController(DiscussionController):
134
122
135
    @LazyProperty
123
    @LazyProperty
136
    def discussion(self):
124
    def discussion(self):
...
...
154
            id=unquote(id)
142
            id=unquote(id)
155
            return self.ThreadController(self._discussion_controller, id), remainder
143
            return self.ThreadController(self._discussion_controller, id), remainder
156
        else:
144
        else:
157
            raise exc.HTTPNotFound()
145
            raise exc.HTTPNotFound()
158
146
159
class ThreadController(BaseController):
147
class ThreadController(BaseController, FeedController):
160
    __metaclass__=h.ProxiedAttrMeta
148
    __metaclass__=h.ProxiedAttrMeta
161
    M=h.attrproxy('_discussion_controller', 'M')
149
    M=h.attrproxy('_discussion_controller', 'M')
162
    W=h.attrproxy('_discussion_controller', 'W')
150
    W=h.attrproxy('_discussion_controller', 'W')
163
    ThreadController=h.attrproxy('_discussion_controller', 'ThreadController')
151
    ThreadController=h.attrproxy('_discussion_controller', 'ThreadController')
164
    PostController=h.attrproxy('_discussion_controller', 'PostController')
152
    PostController=h.attrproxy('_discussion_controller', 'PostController')
...
...
168
        require_access(self.thread, 'read')
156
        require_access(self.thread, 'read')
169
        if self.thread.ref:
157
        if self.thread.ref:
170
            require_access(self.thread.ref.artifact, 'read')
158
            require_access(self.thread.ref.artifact, 'read')
171
159
172
    def __init__(self, discussion_controller, thread_id):
160
    def __init__(self, discussion_controller, thread_id):
173
        setattr(self, 'feed.rss', self.feed)
174
        setattr(self, 'feed.atom', self.feed)
175
        self._discussion_controller = discussion_controller
161
        self._discussion_controller = discussion_controller
176
        self.discussion = discussion_controller.discussion
162
        self.discussion = discussion_controller.discussion
177
        self.thread = self.M.Thread.query.get(_id=thread_id)
163
        self.thread = self.M.Thread.query.get(_id=thread_id)
178
        if not self.thread:
164
        if not self.thread:
179
            raise exc.HTTPNotFound
165
            raise exc.HTTPNotFound
...
...
235
        require_access(self.thread, 'moderate')
221
        require_access(self.thread, 'moderate')
236
        self.thread.spam()
222
        self.thread.spam()
237
        flash('Thread flagged as spam.')
223
        flash('Thread flagged as spam.')
238
        redirect(self.discussion.url())
224
        redirect(self.discussion.url())
239
225
240
    @without_trailing_slash
226
    def get_feed(self, project, app, user):
241
    @expose()
227
        """Return a :class:`allura.controllers.feed.Feed` object describing
242
    @validate(dict(
228
        the xml feed for this controller.
243
            since=DateTimeConverter(if_empty=None),
229
244
            until=DateTimeConverter(if_empty=None),
230
        Overrides :meth:`allura.controllers.feed.FeedController.get_feed`.
245
            page=validators.Int(if_empty=None),
231
246
            limit=validators.Int(if_empty=None)))
232
        """
247
    def feed(self, since=None, until=None, page=None, limit=None, **kw):
233
        return Feed(
248
        if request.environ['PATH_INFO'].endswith('.atom'):
249
            feed_type = 'atom'
250
        else:
251
            feed_type = 'rss'
252
        title = 'Recent posts to %s' % (self.thread.subject or '(no subject)')
253
        feed = M.Feed.feed(
254
            dict(ref_id=self.thread.index_id()),
234
            dict(ref_id=self.thread.index_id()),
255
            feed_type,
235
            'Recent posts to %s' % (self.thread.subject or '(no subject)'),
256
            title,
257
            self.thread.url(),
236
            self.thread.url())
258
            title,
237
259
            since, until, page, limit)
260
        response.headers['Content-Type'] = ''
261
        response.content_type = 'application/xml'
262
        return feed.writeString('utf-8')
263
238
264
class PostController(BaseController):
239
class PostController(BaseController):
265
    __metaclass__=h.ProxiedAttrMeta
240
    __metaclass__=h.ProxiedAttrMeta
266
    M=h.attrproxy('_discussion_controller', 'M')
241
    M=h.attrproxy('_discussion_controller', 'M')
267
    W=h.attrproxy('_discussion_controller', 'W')
242
    W=h.attrproxy('_discussion_controller', 'W')