##// END OF EJS Templates
audit-logs: don't use old style parser for new audit logs.
marcink -
r1834:b6177862 default
parent child Browse files
Show More
@@ -1,316 +1,349 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
17 17 # This program is dual-licensed. If you wish to learn more about the
18 18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20
21 21 import logging
22 22
23 23 from pylons import url
24 24 from pylons.i18n.translation import _
25 25 from webhelpers.html.builder import literal
26 26 from webhelpers.html.tags import link_to
27 27
28 28 from rhodecode.lib.utils2 import AttributeDict
29 29 from rhodecode.lib.vcs.backends.base import BaseCommit
30 30 from rhodecode.lib.vcs.exceptions import CommitDoesNotExistError
31 31
32 32
33 33 log = logging.getLogger(__name__)
34 34
35 35
36 36 def action_parser(user_log, feed=False, parse_cs=False):
37 37 """
38 38 This helper will action_map the specified string action into translated
39 39 fancy names with icons and links
40 40
41 41 :param user_log: user log instance
42 42 :param feed: use output for feeds (no html and fancy icons)
43 43 :param parse_cs: parse Changesets into VCS instances
44 44 """
45 if user_log.version == 'v2':
46 ap = AuditLogParser(user_log)
47 return ap.callbacks()
48 else:
49 # old style
45 50 ap = ActionParser(user_log, feed=False, parse_commits=False)
46 51 return ap.callbacks()
47 52
48 53
49 54 class ActionParser(object):
50 55
51 56 commits_limit = 3 # display this amount always
52 57 commits_top_limit = 50 # show up to this amount of commits hidden
53 58
54 59 def __init__(self, user_log, feed=False, parse_commits=False):
55 60 self.user_log = user_log
56 61 self.feed = feed
57 62 self.parse_commits = parse_commits
58 63
59 64 self.action = user_log.action
60 65 self.action_params = ' '
61 66 x = self.action.split(':', 1)
62 67 if len(x) > 1:
63 68 self.action, self.action_params = x
64 69
65 70 def callbacks(self):
66 71 action_str = self.action_map.get(self.action, self.action)
67 72 if self.feed:
68 73 action = action_str[0].replace('[', '').replace(']', '')
69 74 else:
70 75 action = action_str[0]\
71 76 .replace('[', '<span class="journal_highlight">')\
72 77 .replace(']', '</span>')
73 78
74 79 action_params_func = _no_params_func
75 80 if callable(action_str[1]):
76 81 action_params_func = action_str[1]
77 82
78 83 # returned callbacks we need to call to get
79 84 return [
80 85 lambda: literal(action), action_params_func,
81 86 self.action_parser_icon]
82 87
83 88 @property
84 89 def action_map(self):
85 90
86 91 # action : translated str, callback(extractor), icon
87 92 action_map = {
88 93 'user_deleted_repo': (
89 94 _('[deleted] repository'),
90 95 None, 'icon-trash'),
91 96 'user_created_repo': (
92 97 _('[created] repository'),
93 98 None, 'icon-plus icon-plus-colored'),
94 99 'user_created_fork': (
95 100 _('[created] repository as fork'),
96 101 None, 'icon-code-fork'),
97 102 'user_forked_repo': (
98 103 _('[forked] repository'),
99 104 self.get_fork_name, 'icon-code-fork'),
100 105 'user_updated_repo': (
101 106 _('[updated] repository'),
102 107 None, 'icon-pencil icon-pencil-colored'),
103 108 'user_downloaded_archive': (
104 109 _('[downloaded] archive from repository'),
105 110 self.get_archive_name, 'icon-download-alt'),
106 111 'admin_deleted_repo': (
107 112 _('[delete] repository'),
108 113 None, 'icon-trash'),
109 114 'admin_created_repo': (
110 115 _('[created] repository'),
111 116 None, 'icon-plus icon-plus-colored'),
112 117 'admin_forked_repo': (
113 118 _('[forked] repository'),
114 119 None, 'icon-code-fork icon-fork-colored'),
115 120 'admin_updated_repo': (
116 121 _('[updated] repository'),
117 122 None, 'icon-pencil icon-pencil-colored'),
118 123 'admin_created_user': (
119 124 _('[created] user'),
120 125 self.get_user_name, 'icon-user icon-user-colored'),
121 126 'admin_updated_user': (
122 127 _('[updated] user'),
123 128 self.get_user_name, 'icon-user icon-user-colored'),
124 129 'admin_created_users_group': (
125 130 _('[created] user group'),
126 131 self.get_users_group, 'icon-pencil icon-pencil-colored'),
127 132 'admin_updated_users_group': (
128 133 _('[updated] user group'),
129 134 self.get_users_group, 'icon-pencil icon-pencil-colored'),
130 135 'user_commented_revision': (
131 136 _('[commented] on commit in repository'),
132 137 self.get_cs_links, 'icon-comment icon-comment-colored'),
133 138 'user_commented_pull_request': (
134 139 _('[commented] on pull request for'),
135 140 self.get_pull_request, 'icon-comment icon-comment-colored'),
136 141 'user_closed_pull_request': (
137 142 _('[closed] pull request for'),
138 143 self.get_pull_request, 'icon-check'),
139 144 'user_merged_pull_request': (
140 145 _('[merged] pull request for'),
141 146 self.get_pull_request, 'icon-check'),
142 147 'push': (
143 148 _('[pushed] into'),
144 149 self.get_cs_links, 'icon-arrow-up'),
145 150 'push_local': (
146 151 _('[committed via RhodeCode] into repository'),
147 152 self.get_cs_links, 'icon-pencil icon-pencil-colored'),
148 153 'push_remote': (
149 154 _('[pulled from remote] into repository'),
150 155 self.get_cs_links, 'icon-arrow-up'),
151 156 'pull': (
152 157 _('[pulled] from'),
153 158 None, 'icon-arrow-down'),
154 159 'started_following_repo': (
155 160 _('[started following] repository'),
156 161 None, 'icon-heart icon-heart-colored'),
157 162 'stopped_following_repo': (
158 163 _('[stopped following] repository'),
159 164 None, 'icon-heart-empty icon-heart-colored'),
160 165 }
161 166 return action_map
162 167
163 168 def get_fork_name(self):
164 169 from rhodecode.lib import helpers as h
165 170 repo_name = self.action_params
166 171 _url = h.route_path('repo_summary', repo_name=repo_name)
167 172 return _('fork name %s') % link_to(self.action_params, _url)
168 173
169 174 def get_user_name(self):
170 175 user_name = self.action_params
171 176 return user_name
172 177
173 178 def get_users_group(self):
174 179 group_name = self.action_params
175 180 return group_name
176 181
177 182 def get_pull_request(self):
178 183 from rhodecode.lib import helpers as h
179 184 pull_request_id = self.action_params
180 185 if self.is_deleted():
181 186 repo_name = self.user_log.repository_name
182 187 else:
183 188 repo_name = self.user_log.repository.repo_name
184 189 return link_to(
185 190 _('Pull request #%s') % pull_request_id,
186 191 h.route_path('pullrequest_show', repo_name=repo_name,
187 192 pull_request_id=pull_request_id))
188 193
189 194 def get_archive_name(self):
190 195 archive_name = self.action_params
191 196 return archive_name
192 197
193 198 def action_parser_icon(self):
194 199 tmpl = """<i class="%s" alt="%s"></i>"""
195 200 ico = self.action_map.get(self.action, ['', '', ''])[2]
196 201 return literal(tmpl % (ico, self.action))
197 202
198 203 def get_cs_links(self):
199 204 if self.is_deleted():
200 205 return self.action_params
201 206
202 207 repo_name = self.user_log.repository.repo_name
203 208 commit_ids = self.action_params.split(',')
204 209 commits = self.get_commits(commit_ids)
205 210
206 211 link_generator = (
207 212 self.lnk(commit, repo_name)
208 213 for commit in commits[:self.commits_limit])
209 214 commit_links = [" " + ', '.join(link_generator)]
210 215 _op1, _name1 = _get_op(commit_ids[0])
211 216 _op2, _name2 = _get_op(commit_ids[-1])
212 217
213 218 commit_id_range = '%s...%s' % (_name1, _name2)
214 219
215 220 compare_view = (
216 221 ' <div class="compare_view tooltip" title="%s">'
217 222 '<a href="%s">%s</a> </div>' % (
218 223 _('Show all combined commits %s->%s') % (
219 224 commit_ids[0][:12], commit_ids[-1][:12]
220 225 ),
221 226 url('changeset_home', repo_name=repo_name,
222 227 revision=commit_id_range), _('compare view')
223 228 )
224 229 )
225 230
226 231 if len(commit_ids) > self.commits_limit:
227 232 more_count = len(commit_ids) - self.commits_limit
228 233 commit_links.append(
229 234 _(' and %(num)s more commits') % {'num': more_count}
230 235 )
231 236
232 237 if len(commits) > 1:
233 238 commit_links.append(compare_view)
234 239 return ''.join(commit_links)
235 240
236 241 def get_commits(self, commit_ids):
237 242 commits = []
238 243 if not filter(lambda v: v != '', commit_ids):
239 244 return commits
240 245
241 246 repo = None
242 247 if self.parse_commits:
243 248 repo = self.user_log.repository.scm_instance()
244 249
245 250 for commit_id in commit_ids[:self.commits_top_limit]:
246 251 _op, _name = _get_op(commit_id)
247 252
248 253 # we want parsed commits, or new log store format is bad
249 254 if self.parse_commits:
250 255 try:
251 256 commit = repo.get_commit(commit_id=commit_id)
252 257 commits.append(commit)
253 258 except CommitDoesNotExistError:
254 259 log.error(
255 260 'cannot find commit id %s in this repository',
256 261 commit_id)
257 262 commits.append(commit_id)
258 263 continue
259 264 else:
260 265 fake_commit = AttributeDict({
261 266 'short_id': commit_id[:12],
262 267 'raw_id': commit_id,
263 268 'message': '',
264 269 'op': _op,
265 270 'ref_name': _name
266 271 })
267 272 commits.append(fake_commit)
268 273
269 274 return commits
270 275
271 276 def lnk(self, commit_or_id, repo_name):
272 277 from rhodecode.lib.helpers import tooltip
273 278
274 279 if isinstance(commit_or_id, (BaseCommit, AttributeDict)):
275 280 lazy_cs = True
276 281 if (getattr(commit_or_id, 'op', None) and
277 282 getattr(commit_or_id, 'ref_name', None)):
278 283 lazy_cs = False
279 284 lbl = '?'
280 285 if commit_or_id.op == 'delete_branch':
281 286 lbl = '%s' % _('Deleted branch: %s') % commit_or_id.ref_name
282 287 title = ''
283 288 elif commit_or_id.op == 'tag':
284 289 lbl = '%s' % _('Created tag: %s') % commit_or_id.ref_name
285 290 title = ''
286 291 _url = '#'
287 292
288 293 else:
289 294 lbl = '%s' % (commit_or_id.short_id[:8])
290 295 _url = url('changeset_home', repo_name=repo_name,
291 296 revision=commit_or_id.raw_id)
292 297 title = tooltip(commit_or_id.message)
293 298 else:
294 299 # commit cannot be found/striped/removed etc.
295 300 lbl = ('%s' % commit_or_id)[:12]
296 301 _url = '#'
297 302 title = _('Commit not found')
298 303 if self.parse_commits:
299 304 return link_to(lbl, _url, title=title, class_='tooltip')
300 305 return link_to(lbl, _url, raw_id=commit_or_id.raw_id, repo_name=repo_name,
301 306 class_='lazy-cs' if lazy_cs else '')
302 307
303 308 def is_deleted(self):
304 309 return self.user_log.repository is None
305 310
306 311
312 class AuditLogParser(object):
313 def __init__(self, audit_log_entry):
314 self.audit_log_entry = audit_log_entry
315
316 def get_icon(self, action):
317 return 'icon-rhodecode'
318
319 def callbacks(self):
320 action_str = self.audit_log_entry.action
321
322 def callback():
323 # returned callbacks we need to call to get
324 action = action_str \
325 .replace('[', '<span class="journal_highlight">')\
326 .replace(']', '</span>')
327 return literal(action)
328
329 def icon():
330 tmpl = """<i class="%s" alt="%s"></i>"""
331 ico = self.get_icon(action_str)
332 return literal(tmpl % (ico, action_str))
333
334 action_params_func = _no_params_func
335
336 return [
337 callback, action_params_func, icon]
338
339
307 340 def _no_params_func():
308 341 return ""
309 342
310 343
311 344 def _get_op(commit_id):
312 345 _op = None
313 346 _name = commit_id
314 347 if len(commit_id.split('=>')) == 2:
315 348 _op, _name = commit_id.split('=>')
316 349 return _op, _name
General Comments 0
You need to be logged in to leave comments. Login now