##// END OF EJS Templates
watch: add permission check for repo action.
ergo -
r3681:4898a572 new-ui
parent child Browse files
Show More
@@ -1,384 +1,387 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2019 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
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/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21
21
22 import logging
22 import logging
23 import itertools
23 import itertools
24
24
25 from webhelpers.feedgenerator import Atom1Feed, Rss201rev2Feed
25 from webhelpers.feedgenerator import Atom1Feed, Rss201rev2Feed
26
26
27 from pyramid.view import view_config
27 from pyramid.view import view_config
28 from pyramid.httpexceptions import HTTPBadRequest
28 from pyramid.httpexceptions import HTTPBadRequest
29 from pyramid.response import Response
29 from pyramid.response import Response
30 from pyramid.renderers import render
30 from pyramid.renderers import render
31
31
32 from rhodecode.apps._base import BaseAppView
32 from rhodecode.apps._base import BaseAppView
33 from rhodecode.model.db import (
33 from rhodecode.model.db import (
34 or_, joinedload, UserLog, UserFollowing, User, UserApiKeys)
34 or_, joinedload, Repository, UserLog, UserFollowing, User, UserApiKeys)
35 from rhodecode.model.meta import Session
35 from rhodecode.model.meta import Session
36 import rhodecode.lib.helpers as h
36 import rhodecode.lib.helpers as h
37 from rhodecode.lib.helpers import Page
37 from rhodecode.lib.helpers import Page
38 from rhodecode.lib.user_log_filter import user_log_filter
38 from rhodecode.lib.user_log_filter import user_log_filter
39 from rhodecode.lib.auth import LoginRequired, NotAnonymous, CSRFRequired
39 from rhodecode.lib.auth import LoginRequired, NotAnonymous, CSRFRequired, HasRepoPermissionAny
40 from rhodecode.lib.utils2 import safe_int, AttributeDict, md5_safe
40 from rhodecode.lib.utils2 import safe_int, AttributeDict, md5_safe
41 from rhodecode.model.scm import ScmModel
41 from rhodecode.model.scm import ScmModel
42
42
43 log = logging.getLogger(__name__)
43 log = logging.getLogger(__name__)
44
44
45
45
46 class JournalView(BaseAppView):
46 class JournalView(BaseAppView):
47
47
48 def load_default_context(self):
48 def load_default_context(self):
49 c = self._get_local_tmpl_context(include_app_defaults=True)
49 c = self._get_local_tmpl_context(include_app_defaults=True)
50
50
51 self._load_defaults(c.rhodecode_name)
51 self._load_defaults(c.rhodecode_name)
52
52
53 # TODO(marcink): what is this, why we need a global register ?
53 # TODO(marcink): what is this, why we need a global register ?
54 c.search_term = self.request.GET.get('filter') or ''
54 c.search_term = self.request.GET.get('filter') or ''
55 return c
55 return c
56
56
57 def _get_config(self, rhodecode_name):
57 def _get_config(self, rhodecode_name):
58 import rhodecode
58 import rhodecode
59 config = rhodecode.CONFIG
59 config = rhodecode.CONFIG
60
60
61 return {
61 return {
62 'language': 'en-us',
62 'language': 'en-us',
63 'feed_ttl': '5', # TTL of feed,
63 'feed_ttl': '5', # TTL of feed,
64 'feed_items_per_page':
64 'feed_items_per_page':
65 safe_int(config.get('rss_items_per_page', 20)),
65 safe_int(config.get('rss_items_per_page', 20)),
66 'rhodecode_name': rhodecode_name
66 'rhodecode_name': rhodecode_name
67 }
67 }
68
68
69 def _load_defaults(self, rhodecode_name):
69 def _load_defaults(self, rhodecode_name):
70 config = self._get_config(rhodecode_name)
70 config = self._get_config(rhodecode_name)
71 # common values for feeds
71 # common values for feeds
72 self.language = config["language"]
72 self.language = config["language"]
73 self.ttl = config["feed_ttl"]
73 self.ttl = config["feed_ttl"]
74 self.feed_items_per_page = config['feed_items_per_page']
74 self.feed_items_per_page = config['feed_items_per_page']
75 self.rhodecode_name = config['rhodecode_name']
75 self.rhodecode_name = config['rhodecode_name']
76
76
77 def _get_daily_aggregate(self, journal):
77 def _get_daily_aggregate(self, journal):
78 groups = []
78 groups = []
79 for k, g in itertools.groupby(journal, lambda x: x.action_as_day):
79 for k, g in itertools.groupby(journal, lambda x: x.action_as_day):
80 user_group = []
80 user_group = []
81 # groupby username if it's a present value, else
81 # groupby username if it's a present value, else
82 # fallback to journal username
82 # fallback to journal username
83 for _, g2 in itertools.groupby(
83 for _, g2 in itertools.groupby(
84 list(g), lambda x: x.user.username if x.user else x.username):
84 list(g), lambda x: x.user.username if x.user else x.username):
85 l = list(g2)
85 l = list(g2)
86 user_group.append((l[0].user, l))
86 user_group.append((l[0].user, l))
87
87
88 groups.append((k, user_group,))
88 groups.append((k, user_group,))
89
89
90 return groups
90 return groups
91
91
92 def _get_journal_data(self, following_repos, search_term):
92 def _get_journal_data(self, following_repos, search_term):
93 repo_ids = [x.follows_repository.repo_id for x in following_repos
93 repo_ids = [x.follows_repository.repo_id for x in following_repos
94 if x.follows_repository is not None]
94 if x.follows_repository is not None]
95 user_ids = [x.follows_user.user_id for x in following_repos
95 user_ids = [x.follows_user.user_id for x in following_repos
96 if x.follows_user is not None]
96 if x.follows_user is not None]
97
97
98 filtering_criterion = None
98 filtering_criterion = None
99
99
100 if repo_ids and user_ids:
100 if repo_ids and user_ids:
101 filtering_criterion = or_(UserLog.repository_id.in_(repo_ids),
101 filtering_criterion = or_(UserLog.repository_id.in_(repo_ids),
102 UserLog.user_id.in_(user_ids))
102 UserLog.user_id.in_(user_ids))
103 if repo_ids and not user_ids:
103 if repo_ids and not user_ids:
104 filtering_criterion = UserLog.repository_id.in_(repo_ids)
104 filtering_criterion = UserLog.repository_id.in_(repo_ids)
105 if not repo_ids and user_ids:
105 if not repo_ids and user_ids:
106 filtering_criterion = UserLog.user_id.in_(user_ids)
106 filtering_criterion = UserLog.user_id.in_(user_ids)
107 if filtering_criterion is not None:
107 if filtering_criterion is not None:
108 journal = Session().query(UserLog)\
108 journal = Session().query(UserLog)\
109 .options(joinedload(UserLog.user))\
109 .options(joinedload(UserLog.user))\
110 .options(joinedload(UserLog.repository))
110 .options(joinedload(UserLog.repository))
111 # filter
111 # filter
112 try:
112 try:
113 journal = user_log_filter(journal, search_term)
113 journal = user_log_filter(journal, search_term)
114 except Exception:
114 except Exception:
115 # we want this to crash for now
115 # we want this to crash for now
116 raise
116 raise
117 journal = journal.filter(filtering_criterion)\
117 journal = journal.filter(filtering_criterion)\
118 .order_by(UserLog.action_date.desc())
118 .order_by(UserLog.action_date.desc())
119 else:
119 else:
120 journal = []
120 journal = []
121
121
122 return journal
122 return journal
123
123
124 def feed_uid(self, entry_id):
124 def feed_uid(self, entry_id):
125 return '{}:{}'.format('journal', md5_safe(entry_id))
125 return '{}:{}'.format('journal', md5_safe(entry_id))
126
126
127 def _atom_feed(self, repos, search_term, public=True):
127 def _atom_feed(self, repos, search_term, public=True):
128 _ = self.request.translate
128 _ = self.request.translate
129 journal = self._get_journal_data(repos, search_term)
129 journal = self._get_journal_data(repos, search_term)
130 if public:
130 if public:
131 _link = h.route_url('journal_public_atom')
131 _link = h.route_url('journal_public_atom')
132 _desc = '%s %s %s' % (self.rhodecode_name, _('public journal'),
132 _desc = '%s %s %s' % (self.rhodecode_name, _('public journal'),
133 'atom feed')
133 'atom feed')
134 else:
134 else:
135 _link = h.route_url('journal_atom')
135 _link = h.route_url('journal_atom')
136 _desc = '%s %s %s' % (self.rhodecode_name, _('journal'), 'atom feed')
136 _desc = '%s %s %s' % (self.rhodecode_name, _('journal'), 'atom feed')
137
137
138 feed = Atom1Feed(
138 feed = Atom1Feed(
139 title=_desc, link=_link, description=_desc,
139 title=_desc, link=_link, description=_desc,
140 language=self.language, ttl=self.ttl)
140 language=self.language, ttl=self.ttl)
141
141
142 for entry in journal[:self.feed_items_per_page]:
142 for entry in journal[:self.feed_items_per_page]:
143 user = entry.user
143 user = entry.user
144 if user is None:
144 if user is None:
145 # fix deleted users
145 # fix deleted users
146 user = AttributeDict({'short_contact': entry.username,
146 user = AttributeDict({'short_contact': entry.username,
147 'email': '',
147 'email': '',
148 'full_contact': ''})
148 'full_contact': ''})
149 action, action_extra, ico = h.action_parser(
149 action, action_extra, ico = h.action_parser(
150 self.request, entry, feed=True)
150 self.request, entry, feed=True)
151 title = "%s - %s %s" % (user.short_contact, action(),
151 title = "%s - %s %s" % (user.short_contact, action(),
152 entry.repository.repo_name)
152 entry.repository.repo_name)
153 desc = action_extra()
153 desc = action_extra()
154 _url = h.route_url('home')
154 _url = h.route_url('home')
155 if entry.repository is not None:
155 if entry.repository is not None:
156 _url = h.route_url('repo_changelog',
156 _url = h.route_url('repo_changelog',
157 repo_name=entry.repository.repo_name)
157 repo_name=entry.repository.repo_name)
158
158
159 feed.add_item(
159 feed.add_item(
160 unique_id=self.feed_uid(entry.user_log_id),
160 unique_id=self.feed_uid(entry.user_log_id),
161 title=title,
161 title=title,
162 pubdate=entry.action_date,
162 pubdate=entry.action_date,
163 link=_url,
163 link=_url,
164 author_email=user.email,
164 author_email=user.email,
165 author_name=user.full_contact,
165 author_name=user.full_contact,
166 description=desc)
166 description=desc)
167
167
168 response = Response(feed.writeString('utf-8'))
168 response = Response(feed.writeString('utf-8'))
169 response.content_type = feed.mime_type
169 response.content_type = feed.mime_type
170 return response
170 return response
171
171
172 def _rss_feed(self, repos, search_term, public=True):
172 def _rss_feed(self, repos, search_term, public=True):
173 _ = self.request.translate
173 _ = self.request.translate
174 journal = self._get_journal_data(repos, search_term)
174 journal = self._get_journal_data(repos, search_term)
175 if public:
175 if public:
176 _link = h.route_url('journal_public_atom')
176 _link = h.route_url('journal_public_atom')
177 _desc = '%s %s %s' % (
177 _desc = '%s %s %s' % (
178 self.rhodecode_name, _('public journal'), 'rss feed')
178 self.rhodecode_name, _('public journal'), 'rss feed')
179 else:
179 else:
180 _link = h.route_url('journal_atom')
180 _link = h.route_url('journal_atom')
181 _desc = '%s %s %s' % (
181 _desc = '%s %s %s' % (
182 self.rhodecode_name, _('journal'), 'rss feed')
182 self.rhodecode_name, _('journal'), 'rss feed')
183
183
184 feed = Rss201rev2Feed(
184 feed = Rss201rev2Feed(
185 title=_desc, link=_link, description=_desc,
185 title=_desc, link=_link, description=_desc,
186 language=self.language, ttl=self.ttl)
186 language=self.language, ttl=self.ttl)
187
187
188 for entry in journal[:self.feed_items_per_page]:
188 for entry in journal[:self.feed_items_per_page]:
189 user = entry.user
189 user = entry.user
190 if user is None:
190 if user is None:
191 # fix deleted users
191 # fix deleted users
192 user = AttributeDict({'short_contact': entry.username,
192 user = AttributeDict({'short_contact': entry.username,
193 'email': '',
193 'email': '',
194 'full_contact': ''})
194 'full_contact': ''})
195 action, action_extra, ico = h.action_parser(
195 action, action_extra, ico = h.action_parser(
196 self.request, entry, feed=True)
196 self.request, entry, feed=True)
197 title = "%s - %s %s" % (user.short_contact, action(),
197 title = "%s - %s %s" % (user.short_contact, action(),
198 entry.repository.repo_name)
198 entry.repository.repo_name)
199 desc = action_extra()
199 desc = action_extra()
200 _url = h.route_url('home')
200 _url = h.route_url('home')
201 if entry.repository is not None:
201 if entry.repository is not None:
202 _url = h.route_url('repo_changelog',
202 _url = h.route_url('repo_changelog',
203 repo_name=entry.repository.repo_name)
203 repo_name=entry.repository.repo_name)
204
204
205 feed.add_item(
205 feed.add_item(
206 unique_id=self.feed_uid(entry.user_log_id),
206 unique_id=self.feed_uid(entry.user_log_id),
207 title=title,
207 title=title,
208 pubdate=entry.action_date,
208 pubdate=entry.action_date,
209 link=_url,
209 link=_url,
210 author_email=user.email,
210 author_email=user.email,
211 author_name=user.full_contact,
211 author_name=user.full_contact,
212 description=desc)
212 description=desc)
213
213
214 response = Response(feed.writeString('utf-8'))
214 response = Response(feed.writeString('utf-8'))
215 response.content_type = feed.mime_type
215 response.content_type = feed.mime_type
216 return response
216 return response
217
217
218 @LoginRequired()
218 @LoginRequired()
219 @NotAnonymous()
219 @NotAnonymous()
220 @view_config(
220 @view_config(
221 route_name='journal', request_method='GET',
221 route_name='journal', request_method='GET',
222 renderer=None)
222 renderer=None)
223 def journal(self):
223 def journal(self):
224 c = self.load_default_context()
224 c = self.load_default_context()
225
225
226 p = safe_int(self.request.GET.get('page', 1), 1)
226 p = safe_int(self.request.GET.get('page', 1), 1)
227 c.user = User.get(self._rhodecode_user.user_id)
227 c.user = User.get(self._rhodecode_user.user_id)
228 following = Session().query(UserFollowing)\
228 following = Session().query(UserFollowing)\
229 .filter(UserFollowing.user_id == self._rhodecode_user.user_id)\
229 .filter(UserFollowing.user_id == self._rhodecode_user.user_id)\
230 .options(joinedload(UserFollowing.follows_repository))\
230 .options(joinedload(UserFollowing.follows_repository))\
231 .all()
231 .all()
232
232
233 journal = self._get_journal_data(following, c.search_term)
233 journal = self._get_journal_data(following, c.search_term)
234
234
235 def url_generator(**kw):
235 def url_generator(**kw):
236 query_params = {
236 query_params = {
237 'filter': c.search_term
237 'filter': c.search_term
238 }
238 }
239 query_params.update(kw)
239 query_params.update(kw)
240 return self.request.current_route_path(_query=query_params)
240 return self.request.current_route_path(_query=query_params)
241
241
242 c.journal_pager = Page(
242 c.journal_pager = Page(
243 journal, page=p, items_per_page=20, url=url_generator)
243 journal, page=p, items_per_page=20, url=url_generator)
244 c.journal_day_aggreagate = self._get_daily_aggregate(c.journal_pager)
244 c.journal_day_aggreagate = self._get_daily_aggregate(c.journal_pager)
245
245
246 c.journal_data = render(
246 c.journal_data = render(
247 'rhodecode:templates/journal/journal_data.mako',
247 'rhodecode:templates/journal/journal_data.mako',
248 self._get_template_context(c), self.request)
248 self._get_template_context(c), self.request)
249
249
250 if self.request.is_xhr:
250 if self.request.is_xhr:
251 return Response(c.journal_data)
251 return Response(c.journal_data)
252
252
253 html = render(
253 html = render(
254 'rhodecode:templates/journal/journal.mako',
254 'rhodecode:templates/journal/journal.mako',
255 self._get_template_context(c), self.request)
255 self._get_template_context(c), self.request)
256 return Response(html)
256 return Response(html)
257
257
258 @LoginRequired(auth_token_access=[UserApiKeys.ROLE_FEED])
258 @LoginRequired(auth_token_access=[UserApiKeys.ROLE_FEED])
259 @NotAnonymous()
259 @NotAnonymous()
260 @view_config(
260 @view_config(
261 route_name='journal_atom', request_method='GET',
261 route_name='journal_atom', request_method='GET',
262 renderer=None)
262 renderer=None)
263 def journal_atom(self):
263 def journal_atom(self):
264 """
264 """
265 Produce an atom-1.0 feed via feedgenerator module
265 Produce an atom-1.0 feed via feedgenerator module
266 """
266 """
267 c = self.load_default_context()
267 c = self.load_default_context()
268 following_repos = Session().query(UserFollowing)\
268 following_repos = Session().query(UserFollowing)\
269 .filter(UserFollowing.user_id == self._rhodecode_user.user_id)\
269 .filter(UserFollowing.user_id == self._rhodecode_user.user_id)\
270 .options(joinedload(UserFollowing.follows_repository))\
270 .options(joinedload(UserFollowing.follows_repository))\
271 .all()
271 .all()
272 return self._atom_feed(following_repos, c.search_term, public=False)
272 return self._atom_feed(following_repos, c.search_term, public=False)
273
273
274 @LoginRequired(auth_token_access=[UserApiKeys.ROLE_FEED])
274 @LoginRequired(auth_token_access=[UserApiKeys.ROLE_FEED])
275 @NotAnonymous()
275 @NotAnonymous()
276 @view_config(
276 @view_config(
277 route_name='journal_rss', request_method='GET',
277 route_name='journal_rss', request_method='GET',
278 renderer=None)
278 renderer=None)
279 def journal_rss(self):
279 def journal_rss(self):
280 """
280 """
281 Produce an rss feed via feedgenerator module
281 Produce an rss feed via feedgenerator module
282 """
282 """
283 c = self.load_default_context()
283 c = self.load_default_context()
284 following_repos = Session().query(UserFollowing)\
284 following_repos = Session().query(UserFollowing)\
285 .filter(UserFollowing.user_id == self._rhodecode_user.user_id)\
285 .filter(UserFollowing.user_id == self._rhodecode_user.user_id)\
286 .options(joinedload(UserFollowing.follows_repository))\
286 .options(joinedload(UserFollowing.follows_repository))\
287 .all()
287 .all()
288 return self._rss_feed(following_repos, c.search_term, public=False)
288 return self._rss_feed(following_repos, c.search_term, public=False)
289
289
290 @LoginRequired()
290 @LoginRequired()
291 @NotAnonymous()
291 @NotAnonymous()
292 @CSRFRequired()
292 @CSRFRequired()
293 @view_config(
293 @view_config(
294 route_name='toggle_following', request_method='POST',
294 route_name='toggle_following', request_method='POST',
295 renderer='json_ext')
295 renderer='json_ext')
296 def toggle_following(self):
296 def toggle_following(self):
297 user_id = self.request.POST.get('follows_user_id')
297 user_id = self.request.POST.get('follows_user_id')
298 if user_id:
298 if user_id:
299 try:
299 try:
300 ScmModel().toggle_following_user(user_id, self._rhodecode_user.user_id)
300 ScmModel().toggle_following_user(user_id, self._rhodecode_user.user_id)
301 Session().commit()
301 Session().commit()
302 return 'ok'
302 return 'ok'
303 except Exception:
303 except Exception:
304 raise HTTPBadRequest()
304 raise HTTPBadRequest()
305
305
306 repo_id = self.request.POST.get('follows_repo_id')
306 repo_id = self.request.POST.get('follows_repo_id')
307 if repo_id:
307 repo = Repository.get_or_404(repo_id)
308 perm_set = ['repository.read', 'repository.write', 'repository.admin']
309 has_perm = HasRepoPermissionAny(*perm_set)(repo.repo_name, 'RepoWatch check')
310 if repo and has_perm:
308 try:
311 try:
309 ScmModel().toggle_following_repo(repo_id, self._rhodecode_user.user_id)
312 ScmModel().toggle_following_repo(repo_id, self._rhodecode_user.user_id)
310 Session().commit()
313 Session().commit()
311 return 'ok'
314 return 'ok'
312 except Exception:
315 except Exception:
313 raise HTTPBadRequest()
316 raise HTTPBadRequest()
314
317
315 raise HTTPBadRequest()
318 raise HTTPBadRequest()
316
319
317 @LoginRequired()
320 @LoginRequired()
318 @view_config(
321 @view_config(
319 route_name='journal_public', request_method='GET',
322 route_name='journal_public', request_method='GET',
320 renderer=None)
323 renderer=None)
321 def journal_public(self):
324 def journal_public(self):
322 c = self.load_default_context()
325 c = self.load_default_context()
323 # Return a rendered template
326 # Return a rendered template
324 p = safe_int(self.request.GET.get('page', 1), 1)
327 p = safe_int(self.request.GET.get('page', 1), 1)
325
328
326 c.following = Session().query(UserFollowing)\
329 c.following = Session().query(UserFollowing)\
327 .filter(UserFollowing.user_id == self._rhodecode_user.user_id)\
330 .filter(UserFollowing.user_id == self._rhodecode_user.user_id)\
328 .options(joinedload(UserFollowing.follows_repository))\
331 .options(joinedload(UserFollowing.follows_repository))\
329 .all()
332 .all()
330
333
331 journal = self._get_journal_data(c.following, c.search_term)
334 journal = self._get_journal_data(c.following, c.search_term)
332
335
333 def url_generator(**kw):
336 def url_generator(**kw):
334 query_params = {}
337 query_params = {}
335 query_params.update(kw)
338 query_params.update(kw)
336 return self.request.current_route_path(_query=query_params)
339 return self.request.current_route_path(_query=query_params)
337
340
338 c.journal_pager = Page(
341 c.journal_pager = Page(
339 journal, page=p, items_per_page=20, url=url_generator)
342 journal, page=p, items_per_page=20, url=url_generator)
340 c.journal_day_aggreagate = self._get_daily_aggregate(c.journal_pager)
343 c.journal_day_aggreagate = self._get_daily_aggregate(c.journal_pager)
341
344
342 c.journal_data = render(
345 c.journal_data = render(
343 'rhodecode:templates/journal/journal_data.mako',
346 'rhodecode:templates/journal/journal_data.mako',
344 self._get_template_context(c), self.request)
347 self._get_template_context(c), self.request)
345
348
346 if self.request.is_xhr:
349 if self.request.is_xhr:
347 return Response(c.journal_data)
350 return Response(c.journal_data)
348
351
349 html = render(
352 html = render(
350 'rhodecode:templates/journal/public_journal.mako',
353 'rhodecode:templates/journal/public_journal.mako',
351 self._get_template_context(c), self.request)
354 self._get_template_context(c), self.request)
352 return Response(html)
355 return Response(html)
353
356
354 @LoginRequired(auth_token_access=[UserApiKeys.ROLE_FEED])
357 @LoginRequired(auth_token_access=[UserApiKeys.ROLE_FEED])
355 @view_config(
358 @view_config(
356 route_name='journal_public_atom', request_method='GET',
359 route_name='journal_public_atom', request_method='GET',
357 renderer=None)
360 renderer=None)
358 def journal_public_atom(self):
361 def journal_public_atom(self):
359 """
362 """
360 Produce an atom-1.0 feed via feedgenerator module
363 Produce an atom-1.0 feed via feedgenerator module
361 """
364 """
362 c = self.load_default_context()
365 c = self.load_default_context()
363 following_repos = Session().query(UserFollowing)\
366 following_repos = Session().query(UserFollowing)\
364 .filter(UserFollowing.user_id == self._rhodecode_user.user_id)\
367 .filter(UserFollowing.user_id == self._rhodecode_user.user_id)\
365 .options(joinedload(UserFollowing.follows_repository))\
368 .options(joinedload(UserFollowing.follows_repository))\
366 .all()
369 .all()
367
370
368 return self._atom_feed(following_repos, c.search_term)
371 return self._atom_feed(following_repos, c.search_term)
369
372
370 @LoginRequired(auth_token_access=[UserApiKeys.ROLE_FEED])
373 @LoginRequired(auth_token_access=[UserApiKeys.ROLE_FEED])
371 @view_config(
374 @view_config(
372 route_name='journal_public_rss', request_method='GET',
375 route_name='journal_public_rss', request_method='GET',
373 renderer=None)
376 renderer=None)
374 def journal_public_rss(self):
377 def journal_public_rss(self):
375 """
378 """
376 Produce an rss2 feed via feedgenerator module
379 Produce an rss2 feed via feedgenerator module
377 """
380 """
378 c = self.load_default_context()
381 c = self.load_default_context()
379 following_repos = Session().query(UserFollowing)\
382 following_repos = Session().query(UserFollowing)\
380 .filter(UserFollowing.user_id == self._rhodecode_user.user_id)\
383 .filter(UserFollowing.user_id == self._rhodecode_user.user_id)\
381 .options(joinedload(UserFollowing.follows_repository))\
384 .options(joinedload(UserFollowing.follows_repository))\
382 .all()
385 .all()
383
386
384 return self._rss_feed(following_repos, c.search_term)
387 return self._rss_feed(following_repos, c.search_term)
General Comments 0
You need to be logged in to leave comments. Login now