##// END OF EJS Templates
fix missing c.user reference
marcink -
r2959:db40558e beta
parent child Browse files
Show More
@@ -1,300 +1,298 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.controllers.journal
3 rhodecode.controllers.journal
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5
5
6 Journal controller for pylons
6 Journal controller for pylons
7
7
8 :created_on: Nov 21, 2010
8 :created_on: Nov 21, 2010
9 :author: marcink
9 :author: marcink
10 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
10 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
11 :license: GPLv3, see COPYING for more details.
11 :license: GPLv3, see COPYING for more details.
12 """
12 """
13 # This program is free software: you can redistribute it and/or modify
13 # This program is free software: you can redistribute it and/or modify
14 # it under the terms of the GNU General Public License as published by
14 # it under the terms of the GNU General Public License as published by
15 # the Free Software Foundation, either version 3 of the License, or
15 # the Free Software Foundation, either version 3 of the License, or
16 # (at your option) any later version.
16 # (at your option) any later version.
17 #
17 #
18 # This program is distributed in the hope that it will be useful,
18 # This program is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # GNU General Public License for more details.
21 # GNU General Public License for more details.
22 #
22 #
23 # You should have received a copy of the GNU General Public License
23 # You should have received a copy of the GNU General Public License
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25 import logging
25 import logging
26 from itertools import groupby
26 from itertools import groupby
27
27
28 from sqlalchemy import or_
28 from sqlalchemy import or_
29 from sqlalchemy.orm import joinedload
29 from sqlalchemy.orm import joinedload
30 from webhelpers.paginate import Page
30 from webhelpers.paginate import Page
31 from webhelpers.feedgenerator import Atom1Feed, Rss201rev2Feed
31 from webhelpers.feedgenerator import Atom1Feed, Rss201rev2Feed
32
32
33 from webob.exc import HTTPBadRequest
33 from webob.exc import HTTPBadRequest
34 from pylons import request, tmpl_context as c, response, url
34 from pylons import request, tmpl_context as c, response, url
35 from pylons.i18n.translation import _
35 from pylons.i18n.translation import _
36
36
37 import rhodecode.lib.helpers as h
37 import rhodecode.lib.helpers as h
38 from rhodecode.lib.auth import LoginRequired, NotAnonymous
38 from rhodecode.lib.auth import LoginRequired, NotAnonymous
39 from rhodecode.lib.base import BaseController, render
39 from rhodecode.lib.base import BaseController, render
40 from rhodecode.model.db import UserLog, UserFollowing, Repository, User
40 from rhodecode.model.db import UserLog, UserFollowing, Repository, User
41 from rhodecode.model.meta import Session
41 from rhodecode.model.meta import Session
42 from sqlalchemy.sql.expression import func
42 from sqlalchemy.sql.expression import func
43 from rhodecode.model.scm import ScmModel
43 from rhodecode.model.scm import ScmModel
44 from rhodecode.lib.utils2 import safe_int
44 from rhodecode.lib.utils2 import safe_int
45
45
46 log = logging.getLogger(__name__)
46 log = logging.getLogger(__name__)
47
47
48
48
49 class JournalController(BaseController):
49 class JournalController(BaseController):
50
50
51 def __before__(self):
51 def __before__(self):
52 super(JournalController, self).__before__()
52 super(JournalController, self).__before__()
53 self.language = 'en-us'
53 self.language = 'en-us'
54 self.ttl = "5"
54 self.ttl = "5"
55 self.feed_nr = 20
55 self.feed_nr = 20
56
56
57 @LoginRequired()
57 @LoginRequired()
58 @NotAnonymous()
58 @NotAnonymous()
59 def index(self):
59 def index(self):
60 # Return a rendered template
60 # Return a rendered template
61 p = safe_int(request.params.get('page', 1), 1)
61 p = safe_int(request.params.get('page', 1), 1)
62
63 c.user = User.get(self.rhodecode_user.user_id)
62 c.user = User.get(self.rhodecode_user.user_id)
64
65 c.following = self.sa.query(UserFollowing)\
63 c.following = self.sa.query(UserFollowing)\
66 .filter(UserFollowing.user_id == self.rhodecode_user.user_id)\
64 .filter(UserFollowing.user_id == self.rhodecode_user.user_id)\
67 .options(joinedload(UserFollowing.follows_repository))\
65 .options(joinedload(UserFollowing.follows_repository))\
68 .all()
66 .all()
69
67
70 journal = self._get_journal_data(c.following)
68 journal = self._get_journal_data(c.following)
71
69
72 c.journal_pager = Page(journal, page=p, items_per_page=20)
70 c.journal_pager = Page(journal, page=p, items_per_page=20)
73
74 c.journal_day_aggreagate = self._get_daily_aggregate(c.journal_pager)
71 c.journal_day_aggreagate = self._get_daily_aggregate(c.journal_pager)
75
72
76 c.journal_data = render('journal/journal_data.html')
73 c.journal_data = render('journal/journal_data.html')
77 if request.environ.get('HTTP_X_PARTIAL_XHR'):
74 if request.environ.get('HTTP_X_PARTIAL_XHR'):
78 return c.journal_data
75 return c.journal_data
79 return render('journal/journal.html')
76 return render('journal/journal.html')
80
77
81 @LoginRequired()
78 @LoginRequired()
82 @NotAnonymous()
79 @NotAnonymous()
83 def index_my_repos(self):
80 def index_my_repos(self):
81 c.user = User.get(self.rhodecode_user.user_id)
84 if request.environ.get('HTTP_X_PARTIAL_XHR'):
82 if request.environ.get('HTTP_X_PARTIAL_XHR'):
85 all_repos = self.sa.query(Repository)\
83 all_repos = self.sa.query(Repository)\
86 .filter(Repository.user_id == c.user.user_id)\
84 .filter(Repository.user_id == c.user.user_id)\
87 .order_by(func.lower(Repository.repo_name)).all()
85 .order_by(func.lower(Repository.repo_name)).all()
88 c.user_repos = ScmModel().get_repos(all_repos)
86 c.user_repos = ScmModel().get_repos(all_repos)
89 return render('journal/journal_page_repos.html')
87 return render('journal/journal_page_repos.html')
90
88
91 @LoginRequired(api_access=True)
89 @LoginRequired(api_access=True)
92 @NotAnonymous()
90 @NotAnonymous()
93 def journal_atom(self):
91 def journal_atom(self):
94 """
92 """
95 Produce an atom-1.0 feed via feedgenerator module
93 Produce an atom-1.0 feed via feedgenerator module
96 """
94 """
97 following = self.sa.query(UserFollowing)\
95 following = self.sa.query(UserFollowing)\
98 .filter(UserFollowing.user_id == self.rhodecode_user.user_id)\
96 .filter(UserFollowing.user_id == self.rhodecode_user.user_id)\
99 .options(joinedload(UserFollowing.follows_repository))\
97 .options(joinedload(UserFollowing.follows_repository))\
100 .all()
98 .all()
101 return self._atom_feed(following, public=False)
99 return self._atom_feed(following, public=False)
102
100
103 @LoginRequired(api_access=True)
101 @LoginRequired(api_access=True)
104 @NotAnonymous()
102 @NotAnonymous()
105 def journal_rss(self):
103 def journal_rss(self):
106 """
104 """
107 Produce an rss feed via feedgenerator module
105 Produce an rss feed via feedgenerator module
108 """
106 """
109 following = self.sa.query(UserFollowing)\
107 following = self.sa.query(UserFollowing)\
110 .filter(UserFollowing.user_id == self.rhodecode_user.user_id)\
108 .filter(UserFollowing.user_id == self.rhodecode_user.user_id)\
111 .options(joinedload(UserFollowing.follows_repository))\
109 .options(joinedload(UserFollowing.follows_repository))\
112 .all()
110 .all()
113 return self._rss_feed(following, public=False)
111 return self._rss_feed(following, public=False)
114
112
115 def _get_daily_aggregate(self, journal):
113 def _get_daily_aggregate(self, journal):
116 groups = []
114 groups = []
117 for k, g in groupby(journal, lambda x: x.action_as_day):
115 for k, g in groupby(journal, lambda x: x.action_as_day):
118 user_group = []
116 user_group = []
119 for k2, g2 in groupby(list(g), lambda x: x.user.email):
117 for k2, g2 in groupby(list(g), lambda x: x.user.email):
120 l = list(g2)
118 l = list(g2)
121 user_group.append((l[0].user, l))
119 user_group.append((l[0].user, l))
122
120
123 groups.append((k, user_group,))
121 groups.append((k, user_group,))
124
122
125 return groups
123 return groups
126
124
127 def _get_journal_data(self, following_repos):
125 def _get_journal_data(self, following_repos):
128 repo_ids = [x.follows_repository.repo_id for x in following_repos
126 repo_ids = [x.follows_repository.repo_id for x in following_repos
129 if x.follows_repository is not None]
127 if x.follows_repository is not None]
130 user_ids = [x.follows_user.user_id for x in following_repos
128 user_ids = [x.follows_user.user_id for x in following_repos
131 if x.follows_user is not None]
129 if x.follows_user is not None]
132
130
133 filtering_criterion = None
131 filtering_criterion = None
134
132
135 if repo_ids and user_ids:
133 if repo_ids and user_ids:
136 filtering_criterion = or_(UserLog.repository_id.in_(repo_ids),
134 filtering_criterion = or_(UserLog.repository_id.in_(repo_ids),
137 UserLog.user_id.in_(user_ids))
135 UserLog.user_id.in_(user_ids))
138 if repo_ids and not user_ids:
136 if repo_ids and not user_ids:
139 filtering_criterion = UserLog.repository_id.in_(repo_ids)
137 filtering_criterion = UserLog.repository_id.in_(repo_ids)
140 if not repo_ids and user_ids:
138 if not repo_ids and user_ids:
141 filtering_criterion = UserLog.user_id.in_(user_ids)
139 filtering_criterion = UserLog.user_id.in_(user_ids)
142 if filtering_criterion is not None:
140 if filtering_criterion is not None:
143 journal = self.sa.query(UserLog)\
141 journal = self.sa.query(UserLog)\
144 .options(joinedload(UserLog.user))\
142 .options(joinedload(UserLog.user))\
145 .options(joinedload(UserLog.repository))\
143 .options(joinedload(UserLog.repository))\
146 .filter(filtering_criterion)\
144 .filter(filtering_criterion)\
147 .order_by(UserLog.action_date.desc())
145 .order_by(UserLog.action_date.desc())
148 else:
146 else:
149 journal = []
147 journal = []
150
148
151 return journal
149 return journal
152
150
153 @LoginRequired()
151 @LoginRequired()
154 @NotAnonymous()
152 @NotAnonymous()
155 def toggle_following(self):
153 def toggle_following(self):
156 cur_token = request.POST.get('auth_token')
154 cur_token = request.POST.get('auth_token')
157 token = h.get_token()
155 token = h.get_token()
158 if cur_token == token:
156 if cur_token == token:
159
157
160 user_id = request.POST.get('follows_user_id')
158 user_id = request.POST.get('follows_user_id')
161 if user_id:
159 if user_id:
162 try:
160 try:
163 self.scm_model.toggle_following_user(user_id,
161 self.scm_model.toggle_following_user(user_id,
164 self.rhodecode_user.user_id)
162 self.rhodecode_user.user_id)
165 Session.commit()
163 Session.commit()
166 return 'ok'
164 return 'ok'
167 except:
165 except:
168 raise HTTPBadRequest()
166 raise HTTPBadRequest()
169
167
170 repo_id = request.POST.get('follows_repo_id')
168 repo_id = request.POST.get('follows_repo_id')
171 if repo_id:
169 if repo_id:
172 try:
170 try:
173 self.scm_model.toggle_following_repo(repo_id,
171 self.scm_model.toggle_following_repo(repo_id,
174 self.rhodecode_user.user_id)
172 self.rhodecode_user.user_id)
175 Session.commit()
173 Session.commit()
176 return 'ok'
174 return 'ok'
177 except:
175 except:
178 raise HTTPBadRequest()
176 raise HTTPBadRequest()
179
177
180 log.debug('token mismatch %s vs %s' % (cur_token, token))
178 log.debug('token mismatch %s vs %s' % (cur_token, token))
181 raise HTTPBadRequest()
179 raise HTTPBadRequest()
182
180
183 @LoginRequired()
181 @LoginRequired()
184 def public_journal(self):
182 def public_journal(self):
185 # Return a rendered template
183 # Return a rendered template
186 p = safe_int(request.params.get('page', 1), 1)
184 p = safe_int(request.params.get('page', 1), 1)
187
185
188 c.following = self.sa.query(UserFollowing)\
186 c.following = self.sa.query(UserFollowing)\
189 .filter(UserFollowing.user_id == self.rhodecode_user.user_id)\
187 .filter(UserFollowing.user_id == self.rhodecode_user.user_id)\
190 .options(joinedload(UserFollowing.follows_repository))\
188 .options(joinedload(UserFollowing.follows_repository))\
191 .all()
189 .all()
192
190
193 journal = self._get_journal_data(c.following)
191 journal = self._get_journal_data(c.following)
194
192
195 c.journal_pager = Page(journal, page=p, items_per_page=20)
193 c.journal_pager = Page(journal, page=p, items_per_page=20)
196
194
197 c.journal_day_aggreagate = self._get_daily_aggregate(c.journal_pager)
195 c.journal_day_aggreagate = self._get_daily_aggregate(c.journal_pager)
198
196
199 c.journal_data = render('journal/journal_data.html')
197 c.journal_data = render('journal/journal_data.html')
200 if request.environ.get('HTTP_X_PARTIAL_XHR'):
198 if request.environ.get('HTTP_X_PARTIAL_XHR'):
201 return c.journal_data
199 return c.journal_data
202 return render('journal/public_journal.html')
200 return render('journal/public_journal.html')
203
201
204 def _atom_feed(self, repos, public=True):
202 def _atom_feed(self, repos, public=True):
205 journal = self._get_journal_data(repos)
203 journal = self._get_journal_data(repos)
206 if public:
204 if public:
207 _link = url('public_journal_atom', qualified=True)
205 _link = url('public_journal_atom', qualified=True)
208 _desc = '%s %s %s' % (c.rhodecode_name, _('public journal'),
206 _desc = '%s %s %s' % (c.rhodecode_name, _('public journal'),
209 'atom feed')
207 'atom feed')
210 else:
208 else:
211 _link = url('journal_atom', qualified=True)
209 _link = url('journal_atom', qualified=True)
212 _desc = '%s %s %s' % (c.rhodecode_name, _('journal'), 'atom feed')
210 _desc = '%s %s %s' % (c.rhodecode_name, _('journal'), 'atom feed')
213
211
214 feed = Atom1Feed(title=_desc,
212 feed = Atom1Feed(title=_desc,
215 link=_link,
213 link=_link,
216 description=_desc,
214 description=_desc,
217 language=self.language,
215 language=self.language,
218 ttl=self.ttl)
216 ttl=self.ttl)
219
217
220 for entry in journal[:self.feed_nr]:
218 for entry in journal[:self.feed_nr]:
221 action, action_extra, ico = h.action_parser(entry, feed=True)
219 action, action_extra, ico = h.action_parser(entry, feed=True)
222 title = "%s - %s %s" % (entry.user.short_contact, action(),
220 title = "%s - %s %s" % (entry.user.short_contact, action(),
223 entry.repository.repo_name)
221 entry.repository.repo_name)
224 desc = action_extra()
222 desc = action_extra()
225 _url = None
223 _url = None
226 if entry.repository is not None:
224 if entry.repository is not None:
227 _url = url('changelog_home',
225 _url = url('changelog_home',
228 repo_name=entry.repository.repo_name,
226 repo_name=entry.repository.repo_name,
229 qualified=True)
227 qualified=True)
230
228
231 feed.add_item(title=title,
229 feed.add_item(title=title,
232 pubdate=entry.action_date,
230 pubdate=entry.action_date,
233 link=_url or url('', qualified=True),
231 link=_url or url('', qualified=True),
234 author_email=entry.user.email,
232 author_email=entry.user.email,
235 author_name=entry.user.full_contact,
233 author_name=entry.user.full_contact,
236 description=desc)
234 description=desc)
237
235
238 response.content_type = feed.mime_type
236 response.content_type = feed.mime_type
239 return feed.writeString('utf-8')
237 return feed.writeString('utf-8')
240
238
241 def _rss_feed(self, repos, public=True):
239 def _rss_feed(self, repos, public=True):
242 journal = self._get_journal_data(repos)
240 journal = self._get_journal_data(repos)
243 if public:
241 if public:
244 _link = url('public_journal_atom', qualified=True)
242 _link = url('public_journal_atom', qualified=True)
245 _desc = '%s %s %s' % (c.rhodecode_name, _('public journal'),
243 _desc = '%s %s %s' % (c.rhodecode_name, _('public journal'),
246 'rss feed')
244 'rss feed')
247 else:
245 else:
248 _link = url('journal_atom', qualified=True)
246 _link = url('journal_atom', qualified=True)
249 _desc = '%s %s %s' % (c.rhodecode_name, _('journal'), 'rss feed')
247 _desc = '%s %s %s' % (c.rhodecode_name, _('journal'), 'rss feed')
250
248
251 feed = Rss201rev2Feed(title=_desc,
249 feed = Rss201rev2Feed(title=_desc,
252 link=_link,
250 link=_link,
253 description=_desc,
251 description=_desc,
254 language=self.language,
252 language=self.language,
255 ttl=self.ttl)
253 ttl=self.ttl)
256
254
257 for entry in journal[:self.feed_nr]:
255 for entry in journal[:self.feed_nr]:
258 action, action_extra, ico = h.action_parser(entry, feed=True)
256 action, action_extra, ico = h.action_parser(entry, feed=True)
259 title = "%s - %s %s" % (entry.user.short_contact, action(),
257 title = "%s - %s %s" % (entry.user.short_contact, action(),
260 entry.repository.repo_name)
258 entry.repository.repo_name)
261 desc = action_extra()
259 desc = action_extra()
262 _url = None
260 _url = None
263 if entry.repository is not None:
261 if entry.repository is not None:
264 _url = url('changelog_home',
262 _url = url('changelog_home',
265 repo_name=entry.repository.repo_name,
263 repo_name=entry.repository.repo_name,
266 qualified=True)
264 qualified=True)
267
265
268 feed.add_item(title=title,
266 feed.add_item(title=title,
269 pubdate=entry.action_date,
267 pubdate=entry.action_date,
270 link=_url or url('', qualified=True),
268 link=_url or url('', qualified=True),
271 author_email=entry.user.email,
269 author_email=entry.user.email,
272 author_name=entry.user.full_contact,
270 author_name=entry.user.full_contact,
273 description=desc)
271 description=desc)
274
272
275 response.content_type = feed.mime_type
273 response.content_type = feed.mime_type
276 return feed.writeString('utf-8')
274 return feed.writeString('utf-8')
277
275
278 @LoginRequired(api_access=True)
276 @LoginRequired(api_access=True)
279 def public_journal_atom(self):
277 def public_journal_atom(self):
280 """
278 """
281 Produce an atom-1.0 feed via feedgenerator module
279 Produce an atom-1.0 feed via feedgenerator module
282 """
280 """
283 c.following = self.sa.query(UserFollowing)\
281 c.following = self.sa.query(UserFollowing)\
284 .filter(UserFollowing.user_id == self.rhodecode_user.user_id)\
282 .filter(UserFollowing.user_id == self.rhodecode_user.user_id)\
285 .options(joinedload(UserFollowing.follows_repository))\
283 .options(joinedload(UserFollowing.follows_repository))\
286 .all()
284 .all()
287
285
288 return self._atom_feed(c.following)
286 return self._atom_feed(c.following)
289
287
290 @LoginRequired(api_access=True)
288 @LoginRequired(api_access=True)
291 def public_journal_rss(self):
289 def public_journal_rss(self):
292 """
290 """
293 Produce an rss2 feed via feedgenerator module
291 Produce an rss2 feed via feedgenerator module
294 """
292 """
295 c.following = self.sa.query(UserFollowing)\
293 c.following = self.sa.query(UserFollowing)\
296 .filter(UserFollowing.user_id == self.rhodecode_user.user_id)\
294 .filter(UserFollowing.user_id == self.rhodecode_user.user_id)\
297 .options(joinedload(UserFollowing.follows_repository))\
295 .options(joinedload(UserFollowing.follows_repository))\
298 .all()
296 .all()
299
297
300 return self._rss_feed(c.following)
298 return self._rss_feed(c.following)
General Comments 0
You need to be logged in to leave comments. Login now