##// END OF EJS Templates
audit-logs: fixed search cases with special chars such as `-`....
dan -
r4135:9b536d10 default
parent child Browse files
Show More
@@ -1,126 +1,127 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2010-2019 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 whoosh.qparser.default import QueryParser, query
24 24 from whoosh.qparser.dateparse import DateParserPlugin
25 from whoosh.fields import (TEXT, Schema, DATETIME)
25 from whoosh.fields import (TEXT, Schema, DATETIME, KEYWORD)
26 26 from sqlalchemy.sql.expression import or_, and_, not_, func
27 27
28 28 from rhodecode.model.db import UserLog
29 29 from rhodecode.lib.utils2 import remove_prefix, remove_suffix, safe_unicode
30 30
31 31 # JOURNAL SCHEMA used only to generate queries in journal. We use whoosh
32 32 # querylang to build sql queries and filter journals
33 JOURNAL_SCHEMA = Schema(
34 username=TEXT(),
33 AUDIT_LOG_SCHEMA = Schema(
34 username=KEYWORD(),
35 repository=KEYWORD(),
36
35 37 date=DATETIME(),
36 38 action=TEXT(),
37 repository=TEXT(),
38 39 ip=TEXT(),
39 40 )
40 41
41 42 log = logging.getLogger(__name__)
42 43
43 44
44 45 def user_log_filter(user_log, search_term):
45 46 """
46 47 Filters sqlalchemy user_log based on search_term with whoosh Query language
47 48 http://packages.python.org/Whoosh/querylang.html
48 49
49 50 :param user_log:
50 51 :param search_term:
51 52 """
52 53 log.debug('Initial search term: %r', search_term)
53 54 qry = None
54 55 if search_term:
55 qp = QueryParser('repository', schema=JOURNAL_SCHEMA)
56 qp = QueryParser('repository', schema=AUDIT_LOG_SCHEMA)
56 57 qp.add_plugin(DateParserPlugin())
57 58 qry = qp.parse(safe_unicode(search_term))
58 59 log.debug('Filtering using parsed query %r', qry)
59 60
60 61 def wildcard_handler(col, wc_term):
61 62 if wc_term.startswith('*') and not wc_term.endswith('*'):
62 63 # postfix == endswith
63 64 wc_term = remove_prefix(wc_term, prefix='*')
64 65 return func.lower(col).endswith(wc_term)
65 66 elif wc_term.startswith('*') and wc_term.endswith('*'):
66 67 # wildcard == ilike
67 68 wc_term = remove_prefix(wc_term, prefix='*')
68 69 wc_term = remove_suffix(wc_term, suffix='*')
69 70 return func.lower(col).contains(wc_term)
70 71
71 72 def get_filterion(field, val, term):
72 73
73 74 if field == 'repository':
74 75 field = getattr(UserLog, 'repository_name')
75 76 elif field == 'ip':
76 77 field = getattr(UserLog, 'user_ip')
77 78 elif field == 'date':
78 79 field = getattr(UserLog, 'action_date')
79 80 elif field == 'username':
80 81 field = getattr(UserLog, 'username')
81 82 else:
82 83 field = getattr(UserLog, field)
83 84 log.debug('filter field: %s val=>%s', field, val)
84 85
85 86 # sql filtering
86 87 if isinstance(term, query.Wildcard):
87 88 return wildcard_handler(field, val)
88 89 elif isinstance(term, query.Prefix):
89 90 return func.lower(field).startswith(func.lower(val))
90 91 elif isinstance(term, query.DateRange):
91 92 return and_(field >= val[0], field <= val[1])
92 93 elif isinstance(term, query.Not):
93 94 return not_(field == val)
94 95 return func.lower(field) == func.lower(val)
95 96
96 97 if isinstance(qry, (query.And, query.Not, query.Term, query.Prefix,
97 98 query.Wildcard, query.DateRange)):
98 99 if not isinstance(qry, query.And):
99 100 qry = [qry]
100 101
101 102 for term in qry:
102 103 if isinstance(term, query.Not):
103 104 not_term = [z for z in term.leaves()][0]
104 105 field = not_term.fieldname
105 106 val = not_term.text
106 107 elif isinstance(term, query.DateRange):
107 108 field = term.fieldname
108 109 val = [term.startdate, term.enddate]
109 110 elif isinstance(term, query.NullQuery.__class__):
110 111 field = ''
111 112 val = ''
112 113 else:
113 114 field = term.fieldname
114 115 val = term.text
115 116 if field:
116 117 user_log = user_log.filter(get_filterion(field, val, term))
117 118 elif isinstance(qry, query.Or):
118 119 filters = []
119 120 for term in qry:
120 121 field = term.fieldname
121 122 val = (term.text if not isinstance(term, query.DateRange)
122 123 else [term.startdate, term.enddate])
123 124 filters.append(get_filterion(field, val, term))
124 125 user_log = user_log.filter(or_(*filters))
125 126
126 127 return user_log
General Comments 0
You need to be logged in to leave comments. Login now