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')