##// END OF EJS Templates
pytype: add assertion to guide pytype through Whoosh usage...
Mads Kiilerich -
r8637:7b58d01e default
parent child Browse files
Show More
@@ -1,147 +1,148 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 # This program is free software: you can redistribute it and/or modify
2 # This program is free software: you can redistribute it and/or modify
3 # it under the terms of the GNU General Public License as published by
3 # it under the terms of the GNU General Public License as published by
4 # the Free Software Foundation, either version 3 of the License, or
4 # the Free Software Foundation, either version 3 of the License, or
5 # (at your option) any later version.
5 # (at your option) any later version.
6 #
6 #
7 # This program is distributed in the hope that it will be useful,
7 # This program is distributed in the hope that it will be useful,
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 # GNU General Public License for more details.
10 # GNU General Public License for more details.
11 #
11 #
12 # You should have received a copy of the GNU General Public License
12 # You should have received a copy of the GNU General Public License
13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 """
14 """
15 kallithea.controllers.admin.admin
15 kallithea.controllers.admin.admin
16 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
16 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
17
17
18 Controller for Admin panel of Kallithea
18 Controller for Admin panel of Kallithea
19
19
20 This file was forked by the Kallithea project in July 2014.
20 This file was forked by the Kallithea project in July 2014.
21 Original author and date, and relevant copyright and licensing information is below:
21 Original author and date, and relevant copyright and licensing information is below:
22 :created_on: Apr 7, 2010
22 :created_on: Apr 7, 2010
23 :author: marcink
23 :author: marcink
24 :copyright: (c) 2013 RhodeCode GmbH, and others.
24 :copyright: (c) 2013 RhodeCode GmbH, and others.
25 :license: GPLv3, see LICENSE.md for more details.
25 :license: GPLv3, see LICENSE.md for more details.
26 """
26 """
27
27
28
28
29 import logging
29 import logging
30
30
31 from sqlalchemy.orm import joinedload
31 from sqlalchemy.orm import joinedload
32 from sqlalchemy.sql.expression import and_, func, or_
32 from sqlalchemy.sql.expression import and_, func, or_
33 from tg import request
33 from tg import request
34 from tg import tmpl_context as c
34 from tg import tmpl_context as c
35 from whoosh import query
35 from whoosh import query
36 from whoosh.qparser.dateparse import DateParserPlugin
36 from whoosh.qparser.dateparse import DateParserPlugin
37 from whoosh.qparser.default import QueryParser
37 from whoosh.qparser.default import QueryParser
38
38
39 from kallithea.controllers import base
39 from kallithea.controllers import base
40 from kallithea.lib.auth import HasPermissionAnyDecorator, LoginRequired
40 from kallithea.lib.auth import HasPermissionAnyDecorator, LoginRequired
41 from kallithea.lib.indexers import JOURNAL_SCHEMA
41 from kallithea.lib.indexers import JOURNAL_SCHEMA
42 from kallithea.lib.page import Page
42 from kallithea.lib.page import Page
43 from kallithea.lib.utils2 import remove_prefix, remove_suffix, safe_int
43 from kallithea.lib.utils2 import remove_prefix, remove_suffix, safe_int
44 from kallithea.model import db
44 from kallithea.model import db
45
45
46
46
47 log = logging.getLogger(__name__)
47 log = logging.getLogger(__name__)
48
48
49
49
50 def _journal_filter(user_log, search_term):
50 def _journal_filter(user_log, search_term):
51 """
51 """
52 Filters sqlalchemy user_log based on search_term with whoosh Query language
52 Filters sqlalchemy user_log based on search_term with whoosh Query language
53 http://packages.python.org/Whoosh/querylang.html
53 http://packages.python.org/Whoosh/querylang.html
54
54
55 :param user_log:
55 :param user_log:
56 :param search_term:
56 :param search_term:
57 """
57 """
58 log.debug('Initial search term: %r', search_term)
58 log.debug('Initial search term: %r', search_term)
59 qry = None
59 qry = None
60 if search_term:
60 if search_term:
61 qp = QueryParser('repository', schema=JOURNAL_SCHEMA)
61 qp = QueryParser('repository', schema=JOURNAL_SCHEMA)
62 qp.add_plugin(DateParserPlugin())
62 qp.add_plugin(DateParserPlugin())
63 qry = qp.parse(search_term)
63 qry = qp.parse(search_term)
64 log.debug('Filtering using parsed query %r', qry)
64 log.debug('Filtering using parsed query %r', qry)
65
65
66 def wildcard_handler(col, wc_term):
66 def wildcard_handler(col, wc_term):
67 if wc_term.startswith('*') and not wc_term.endswith('*'):
67 if wc_term.startswith('*') and not wc_term.endswith('*'):
68 # postfix == endswith
68 # postfix == endswith
69 wc_term = remove_prefix(wc_term, prefix='*')
69 wc_term = remove_prefix(wc_term, prefix='*')
70 return func.lower(col).endswith(func.lower(wc_term))
70 return func.lower(col).endswith(func.lower(wc_term))
71 elif wc_term.startswith('*') and wc_term.endswith('*'):
71 elif wc_term.startswith('*') and wc_term.endswith('*'):
72 # wildcard == ilike
72 # wildcard == ilike
73 wc_term = remove_prefix(wc_term, prefix='*')
73 wc_term = remove_prefix(wc_term, prefix='*')
74 wc_term = remove_suffix(wc_term, suffix='*')
74 wc_term = remove_suffix(wc_term, suffix='*')
75 return func.lower(col).contains(func.lower(wc_term))
75 return func.lower(col).contains(func.lower(wc_term))
76
76
77 def get_filterion(field, val, term):
77 def get_filterion(field, val, term):
78
78
79 if field == 'repository':
79 if field == 'repository':
80 field = getattr(db.UserLog, 'repository_name')
80 field = getattr(db.UserLog, 'repository_name')
81 elif field == 'ip':
81 elif field == 'ip':
82 field = getattr(db.UserLog, 'user_ip')
82 field = getattr(db.UserLog, 'user_ip')
83 elif field == 'date':
83 elif field == 'date':
84 field = getattr(db.UserLog, 'action_date')
84 field = getattr(db.UserLog, 'action_date')
85 elif field == 'username':
85 elif field == 'username':
86 field = getattr(db.UserLog, 'username')
86 field = getattr(db.UserLog, 'username')
87 else:
87 else:
88 field = getattr(db.UserLog, field)
88 field = getattr(db.UserLog, field)
89 log.debug('filter field: %s val=>%s', field, val)
89 log.debug('filter field: %s val=>%s', field, val)
90
90
91 # sql filtering
91 # sql filtering
92 if isinstance(term, query.Wildcard):
92 if isinstance(term, query.Wildcard):
93 return wildcard_handler(field, val)
93 return wildcard_handler(field, val)
94 elif isinstance(term, query.Prefix):
94 elif isinstance(term, query.Prefix):
95 return func.lower(field).startswith(func.lower(val))
95 return func.lower(field).startswith(func.lower(val))
96 elif isinstance(term, query.DateRange):
96 elif isinstance(term, query.DateRange):
97 return and_(field >= val[0], field <= val[1])
97 return and_(field >= val[0], field <= val[1])
98 return func.lower(field) == func.lower(val)
98 return func.lower(field) == func.lower(val)
99
99
100 if isinstance(qry, (query.And, query.Term, query.Prefix, query.Wildcard,
100 if isinstance(qry, (query.And, query.Term, query.Prefix, query.Wildcard,
101 query.DateRange)):
101 query.DateRange)):
102 if not isinstance(qry, query.And):
102 if not isinstance(qry, query.And):
103 qry = [qry]
103 qry = [qry]
104 for term in qry:
104 for term in qry:
105 assert term is not None, term
105 field = term.fieldname
106 field = term.fieldname
106 val = (term.text if not isinstance(term, query.DateRange)
107 val = (term.text if not isinstance(term, query.DateRange)
107 else [term.startdate, term.enddate])
108 else [term.startdate, term.enddate])
108 user_log = user_log.filter(get_filterion(field, val, term))
109 user_log = user_log.filter(get_filterion(field, val, term))
109 elif isinstance(qry, query.Or):
110 elif isinstance(qry, query.Or):
110 filters = []
111 filters = []
111 for term in qry:
112 for term in qry:
112 field = term.fieldname
113 field = term.fieldname
113 val = (term.text if not isinstance(term, query.DateRange)
114 val = (term.text if not isinstance(term, query.DateRange)
114 else [term.startdate, term.enddate])
115 else [term.startdate, term.enddate])
115 filters.append(get_filterion(field, val, term))
116 filters.append(get_filterion(field, val, term))
116 user_log = user_log.filter(or_(*filters))
117 user_log = user_log.filter(or_(*filters))
117
118
118 return user_log
119 return user_log
119
120
120
121
121 class AdminController(base.BaseController):
122 class AdminController(base.BaseController):
122
123
123 @LoginRequired(allow_default_user=True)
124 @LoginRequired(allow_default_user=True)
124 def _before(self, *args, **kwargs):
125 def _before(self, *args, **kwargs):
125 super(AdminController, self)._before(*args, **kwargs)
126 super(AdminController, self)._before(*args, **kwargs)
126
127
127 @HasPermissionAnyDecorator('hg.admin')
128 @HasPermissionAnyDecorator('hg.admin')
128 def index(self):
129 def index(self):
129 users_log = db.UserLog.query() \
130 users_log = db.UserLog.query() \
130 .options(joinedload(db.UserLog.user)) \
131 .options(joinedload(db.UserLog.user)) \
131 .options(joinedload(db.UserLog.repository))
132 .options(joinedload(db.UserLog.repository))
132
133
133 # FILTERING
134 # FILTERING
134 c.search_term = request.GET.get('filter')
135 c.search_term = request.GET.get('filter')
135 users_log = _journal_filter(users_log, c.search_term)
136 users_log = _journal_filter(users_log, c.search_term)
136
137
137 users_log = users_log.order_by(db.UserLog.action_date.desc())
138 users_log = users_log.order_by(db.UserLog.action_date.desc())
138
139
139 p = safe_int(request.GET.get('page'), 1)
140 p = safe_int(request.GET.get('page'), 1)
140
141
141 c.users_log = Page(users_log, page=p, items_per_page=10,
142 c.users_log = Page(users_log, page=p, items_per_page=10,
142 filter=c.search_term)
143 filter=c.search_term)
143
144
144 if request.environ.get('HTTP_X_PARTIAL_XHR'):
145 if request.environ.get('HTTP_X_PARTIAL_XHR'):
145 return base.render('admin/admin_log.html')
146 return base.render('admin/admin_log.html')
146
147
147 return base.render('admin/admin.html')
148 return base.render('admin/admin.html')
General Comments 0
You need to be logged in to leave comments. Login now