Fix INF-378 inventory subscription filter not take effect as expected
[pti/o2.git] / o2common / views / view.py
1 # Copyright (C) 2021-2022 Wind River Systems, Inc.
2 #
3 #  Licensed under the Apache License, Version 2.0 (the "License");
4 #  you may not use this file except in compliance with the License.
5 #  You may obtain a copy of the License at
6 #
7 #      http://www.apache.org/licenses/LICENSE-2.0
8 #
9 #  Unless required by applicable law or agreed to in writing, software
10 #  distributed under the License is distributed on an "AS IS" BASIS,
11 #  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 #  See the License for the specific language governing permissions and
13 #  limitations under the License.
14
15 # import re
16 from sqlalchemy.sql.elements import ColumnElement
17
18 from o2common.views.route_exception import BadRequestException
19 from o2common.domain.filter import gen_orm_filter, \
20     transfer_filter_attr_name_in_special
21
22 from o2common.helper import o2logging
23 logger = o2logging.get_logger(__name__)
24
25
26 def gen_filter(obj: ColumnElement, filter_str: str):
27     check_filter(obj, filter_str)
28     try:
29         filter_list = gen_orm_filter(obj, filter_str)
30     except KeyError as e:
31         raise BadRequestException(e.args[0])
32     return filter_list
33
34
35 # The regular expressions testing example put on here
36 # (neq,testkey,value-1)
37 # (neq,testkey,value-1,value-2)
38 # (gt,hello,1)
39 # (gte,world,2)
40 # (lt,testlt,notint)
41 # (ncont,key1,v1,v_2)
42 # (gt,hello,1);(ncont,world,val1,val-2)
43 # (eq,wrong,60cba7be-e2cd-3b8c-a7ff-16e0f10573f9)
44 # (eq,description,value key)
45 def check_filter(obj: ColumnElement, filter_str: str):
46     if not filter_str:
47         return
48     # pattern = r'^(\((eq|neq|gt|lt|gte|lte){1},\w+,[\w -\.]+\)\;?|' +\
49     #     r'\((in|nin|cont|ncont){1},\w*(,[\w -\.]*)*\)\;?)+'
50     # result = re.match(pattern, filter_str)
51     # logger.debug('filter: {} match result is {}'.format(filter_str, result))
52     # if not result:
53     #     raise BadRequestException(
54     #         'filter value format is invalid')
55     check_filter_attribute(obj, filter_str)
56
57
58 def check_filter_attribute(obj: ColumnElement, filter_str: str):
59     # filter_without_space = filter_str.replace(" ", "")
60     filter_without_space = filter_str.strip(' ()')
61     logger.debug(
62         f"filter_str: {filter_str}, stripped: {filter_without_space}")
63     items = filter_without_space.split(';')
64
65     for i in items:
66         # if '(' in i:
67         #     i = i.replace("(", "")
68         # if ')' in i:
69         #     i = i.replace(")", "")
70         filter_expr = i.split(',')
71         if len(filter_expr) < 3:
72             raise BadRequestException(
73                 'ignore invalid filter {}'.format(i))
74             continue
75         filter_op = filter_expr[0].strip()
76         filter_key = filter_expr[1].strip()
77         filter_vals = filter_expr[2:]
78         if filter_op in ["eq", "neq", "gt", "lt", "gte", "lte"]:
79             if len(filter_vals) != 1:
80                 raise BadRequestException(
81                     "Found {} values: {} while only single value"
82                     " is allowed for operation {}".format(
83                         len(filter_vals), filter_vals, filter_op)
84                 )
85         elif filter_op not in ["in", "nin", "cont", "ncont"]:
86             raise BadRequestException(
87                 'Filter operation {} is invalid'.format(filter_op)
88             )
89         else:
90             pass
91         filter_key = transfer_filter_attr_name_in_special(obj, filter_key)
92         if not hasattr(obj, filter_key) or \
93                 filter_key in ['hash', 'updatetime', 'createtime', 'events']:
94             raise BadRequestException(
95                 'Filter attrName {} is invalid'.format(filter_key))