Mercurial > kallithea
comparison rhodecode/controllers/admin/admin.py @ 3062:a08624dd675e beta
Implemented filtering of admin journal based on Whoosh Query language
ref #210
author | Marcin Kuzminski <marcin@python-works.com> |
---|---|
date | Wed, 05 Dec 2012 21:14:31 +0100 |
parents | 6b176c679896 |
children | ca2b21819dfd |
comparison
equal
deleted
inserted
replaced
3061:7727faad5baf | 3062:a08624dd675e |
---|---|
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 | 25 |
26 import logging | 26 import logging |
27 | 27 |
28 from pylons import request, tmpl_context as c | 28 from pylons import request, tmpl_context as c, url |
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 whoosh.qparser.default import QueryParser | |
32 from whoosh import query | |
33 from sqlalchemy.sql.expression import or_ | |
31 | 34 |
32 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator | 35 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator |
33 from rhodecode.lib.base import BaseController, render | 36 from rhodecode.lib.base import BaseController, render |
34 from rhodecode.model.db import UserLog | 37 from rhodecode.model.db import UserLog, User |
35 from rhodecode.lib.utils2 import safe_int | 38 from rhodecode.lib.utils2 import safe_int, remove_prefix |
39 from rhodecode.lib.indexers import JOURNAL_SCHEMA | |
40 | |
36 | 41 |
37 log = logging.getLogger(__name__) | 42 log = logging.getLogger(__name__) |
43 | |
44 | |
45 def _filter(user_log, search_term): | |
46 """ | |
47 Filters sqlalchemy user_log based on search_term with whoosh Query language | |
48 http://packages.python.org/Whoosh/querylang.html | |
49 | |
50 :param user_log: | |
51 :param search_term: | |
52 """ | |
53 qry = None | |
54 if search_term: | |
55 qp = QueryParser('repository', schema=JOURNAL_SCHEMA) | |
56 qry = qp.parse(unicode(search_term)) | |
57 log.debug('Filtering using query %r' % qry) | |
58 | |
59 def get_filterion(field, val, term): | |
60 if field == 'repository': | |
61 field = getattr(UserLog, 'repository_name') | |
62 elif field == 'ip': | |
63 field = getattr(UserLog, 'user_ip') | |
64 elif field == 'date': | |
65 field = getattr(UserLog, 'action_date') | |
66 elif field == 'username': | |
67 ##special case for username | |
68 if isinstance(term, query.Wildcard): | |
69 #only support wildcards with * at beggining | |
70 val = remove_prefix(val, prefix='*') | |
71 return getattr(UserLog, 'user_id').in_( | |
72 [x.user_id for x in | |
73 User.query().filter(User.username.endswith(val))]) | |
74 elif isinstance(term, query.Prefix): | |
75 return getattr(UserLog, 'user_id').in_( | |
76 [x.user_id for x in | |
77 User.query().filter(User.username.startswith(val))]) | |
78 # term == exact match, case insensitive | |
79 field = getattr(UserLog, 'user') | |
80 val = User.get_by_username(val, case_insensitive=True) | |
81 | |
82 else: | |
83 field = getattr(UserLog, field) | |
84 | |
85 #sql filtering | |
86 if isinstance(term, query.Wildcard): | |
87 return field.endsswith(val) | |
88 elif isinstance(term, query.Prefix): | |
89 return field.startswith(val) | |
90 return field == val | |
91 | |
92 if isinstance(qry, (query.And, query.Term, query.Prefix, query.Wildcard)): | |
93 if not isinstance(qry, query.And): | |
94 qry = [qry] | |
95 for term in qry: | |
96 field = term.fieldname | |
97 val = term.text | |
98 user_log = user_log.filter(get_filterion(field, val, term)) | |
99 elif isinstance(qry, query.Or): | |
100 filters = [] | |
101 for term in qry: | |
102 field = term.fieldname | |
103 val = term.text | |
104 if isinstance(term, query.Term): | |
105 filters.append(get_filterion(field, val, term)) | |
106 user_log = user_log.filter(or_(*filters)) | |
107 | |
108 return user_log | |
38 | 109 |
39 | 110 |
40 class AdminController(BaseController): | 111 class AdminController(BaseController): |
41 | 112 |
42 @LoginRequired() | 113 @LoginRequired() |
43 def __before__(self): | 114 def __before__(self): |
44 super(AdminController, self).__before__() | 115 super(AdminController, self).__before__() |
45 | 116 |
46 @HasPermissionAllDecorator('hg.admin') | 117 @HasPermissionAllDecorator('hg.admin') |
47 def index(self): | 118 def index(self): |
48 | |
49 users_log = UserLog.query()\ | 119 users_log = UserLog.query()\ |
50 .options(joinedload(UserLog.user))\ | 120 .options(joinedload(UserLog.user))\ |
51 .options(joinedload(UserLog.repository))\ | 121 .options(joinedload(UserLog.repository)) |
52 .order_by(UserLog.action_date.desc()) | 122 |
123 #FILTERING | |
124 c.search_term = request.GET.get('filter') | |
125 try: | |
126 users_log = _filter(users_log, c.search_term) | |
127 except: | |
128 # we want this to crash for now | |
129 raise | |
130 | |
131 users_log = users_log.order_by(UserLog.action_date.desc()) | |
53 | 132 |
54 p = safe_int(request.params.get('page', 1), 1) | 133 p = safe_int(request.params.get('page', 1), 1) |
55 c.users_log = Page(users_log, page=p, items_per_page=10) | 134 |
135 def url_generator(**kw): | |
136 return url.current(filter=c.search_term, **kw) | |
137 | |
138 c.users_log = Page(users_log, page=p, items_per_page=10, url=url_generator) | |
56 c.log_data = render('admin/admin_log.html') | 139 c.log_data = render('admin/admin_log.html') |
57 | 140 |
58 if request.environ.get('HTTP_X_PARTIAL_XHR'): | 141 if request.environ.get('HTTP_X_PARTIAL_XHR'): |
59 return c.log_data | 142 return c.log_data |
60 return render('admin/admin.html') | 143 return render('admin/admin.html') |