Skip to content

Commit 9213075

Browse files
committed
INTEGRITY: Add comprehensive search criterias in log with OR, AND conditions.
1 parent 9b62c15 commit 9213075

File tree

4 files changed

+83
-82
lines changed

4 files changed

+83
-82
lines changed

fileset.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737

3838
@app.route("/")
3939
def index():
40-
return redirect(url_for("logs"))
40+
return redirect(url_for("logs", sort="id-desc"))
4141

4242

4343
@app.route("/home")
@@ -141,7 +141,7 @@ def fileset():
141141
<a href="{{{{ url_for('user_games_list') }}}}">User Games List</a>
142142
<a href="{{{{ url_for('ready_for_review') }}}}">Ready for review</a>
143143
<a href="{{{{ url_for('fileset_search') }}}}">Fileset Search</a>
144-
<a href="{{{{ url_for('logs') }}}}">Logs</a>
144+
<a href="{{{{ url_for('logs', sort='id-desc') }}}}">Logs</a>
145145
<a href="{{{{ url_for('config') }}}}">Config</a>
146146
</div>
147147
</nav>
@@ -505,7 +505,7 @@ def merge_fileset(id):
505505
<a href="{{{{ url_for('user_games_list') }}}}">User Games List</a>
506506
<a href="{{{{ url_for('ready_for_review') }}}}">Ready for review</a>
507507
<a href="{{{{ url_for('fileset_search') }}}}">Fileset Search</a>
508-
<a href="{{{{ url_for('logs') }}}}">Logs</a>
508+
<a href="{{{{ url_for('logs', sort='id-desc') }}}}">Logs</a>
509509
<a href="{{{{ url_for('config') }}}}">Config</a>
510510
</div>
511511
</nav>
@@ -553,7 +553,7 @@ def merge_fileset(id):
553553
<a href="{{ url_for('user_games_list') }}">User Games List</a>
554554
<a href="{{ url_for('ready_for_review') }}">Ready for review</a>
555555
<a href="{{ url_for('fileset_search') }}">Fileset Search</a>
556-
<a href="{{ url_for('logs') }}">Logs</a>
556+
<a href="{{ url_for('logs', sort='id-desc') }}">Logs</a>
557557
<a href="{{ url_for('config') }}">Config</a>
558558
</div>
559559
</nav>
@@ -621,7 +621,7 @@ def possible_merge_filesets(id):
621621
<a href="{{{{ url_for('user_games_list') }}}}">User Games List</a>
622622
<a href="{{{{ url_for('ready_for_review') }}}}">Ready for review</a>
623623
<a href="{{{{ url_for('fileset_search') }}}}">Fileset Search</a>
624-
<a href="{{{{ url_for('logs') }}}}">Logs</a>
624+
<a href="{{{{ url_for('logs', sort='id-desc') }}}}">Logs</a>
625625
<a href="{{{{ url_for('config') }}}}">Config</a>
626626
</div>
627627
</nav>
@@ -824,7 +824,7 @@ def highlight_differences(source, target):
824824
<a href="{{ url_for('user_games_list') }}">User Games List</a>
825825
<a href="{{ url_for('ready_for_review') }}">Ready for review</a>
826826
<a href="{{ url_for('fileset_search') }}">Fileset Search</a>
827-
<a href="{{ url_for('logs') }}">Logs</a>
827+
<a href="{{ url_for('logs', sort='id-desc') }}">Logs</a>
828828
<a href="{{ url_for('config') }}">Config</a>
829829
</div>
830830
</nav>

pagination.py

Lines changed: 75 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,30 @@ def get_join_columns(table1, table2, mapping):
2222
return "No primary-foreign key mapping provided. Filter is invalid"
2323

2424

25+
def build_search_condition(value, column):
26+
phrases = re.findall(r'"([^"]+)"', value)
27+
if phrases:
28+
conditions = [f"{column} REGEXP '{re.escape(p)}'" for p in phrases]
29+
return " AND ".join(conditions)
30+
31+
if "+" in value:
32+
and_terms = value.split("+")
33+
and_conditions = []
34+
for term in and_terms:
35+
or_terms = term.strip().split()
36+
if len(or_terms) > 1:
37+
or_cond = " OR ".join(
38+
[f"{column} REGEXP '{re.escape(t)}'" for t in or_terms if t]
39+
)
40+
and_conditions.append(f"({or_cond})")
41+
else:
42+
and_conditions.append(f"{column} REGEXP '{re.escape(term.strip())}'")
43+
return " AND ".join(and_conditions)
44+
else:
45+
or_terms = value.split()
46+
return " OR ".join([f"{column} REGEXP '{re.escape(t)}'" for t in or_terms if t])
47+
48+
2549
def create_page(
2650
filename,
2751
results_per_page,
@@ -46,62 +70,47 @@ def create_page(
4670
)
4771

4872
with conn.cursor() as cursor:
49-
# Handle sorting
50-
sort = request.args.get("sort")
51-
if sort:
52-
column = sort.split("-")
53-
order = f"ORDER BY {column[0]}"
54-
if "desc" in sort:
55-
order += " DESC"
73+
tables = set()
74+
where_clauses = []
5675

57-
if set(request.args.keys()).difference({"page", "sort"}):
58-
condition = "WHERE "
59-
tables = set()
60-
for key, value in request.args.items():
61-
if key in ["page", "sort"] or value == "":
62-
continue
63-
tables.add(filters[key])
64-
if value == "":
65-
value = ".*"
66-
condition += (
67-
f" AND {filters[key]}.{'id' if key == 'fileset' else key} REGEXP '{value}'"
68-
if condition != "WHERE "
69-
else f"{filters[key]}.{'id' if key == 'fileset' else key} REGEXP '{value}'"
70-
)
76+
for key, value in request.args.items():
77+
if key in ("page", "sort") or value == "":
78+
continue
79+
tables.add(filters[key])
80+
col = f"{filters[key]}.{'id' if key == 'fileset' else key}"
81+
parsed = build_search_condition(value, col)
82+
if parsed:
83+
where_clauses.append(parsed)
7184

72-
if condition == "WHERE ":
73-
condition = ""
85+
condition = ""
86+
if where_clauses:
87+
condition = "WHERE " + " AND ".join(where_clauses)
7488

75-
# Handle multiple tables
76-
from_query = records_table
77-
join_order = ["game", "engine"]
78-
tables_list = sorted(
79-
list(tables),
80-
key=lambda t: join_order.index(t) if t in join_order else 99,
81-
)
82-
if records_table not in tables_list or len(tables_list) > 1:
83-
for table in tables_list:
84-
if table == records_table:
85-
continue
86-
if table == "engine":
87-
if "game" in tables:
88-
from_query += " JOIN engine ON engine.id = game.engine"
89-
else:
90-
from_query += " JOIN game ON game.id = fileset.game JOIN engine ON engine.id = game.engine"
89+
from_query = records_table
90+
join_order = ["game", "engine"]
91+
tables_list = sorted(
92+
list(tables), key=lambda t: join_order.index(t) if t in join_order else 99
93+
)
94+
95+
if records_table not in tables_list or len(tables_list) > 1:
96+
for t in tables_list:
97+
if t == records_table:
98+
continue
99+
if t == "engine":
100+
if "game" in tables:
101+
from_query += " JOIN engine ON engine.id = game.engine"
91102
else:
92-
from_query += f" JOIN {table} ON {get_join_columns(records_table, table, mapping)}"
93-
cursor.execute(
94-
f"SELECT COUNT({records_table}.id) AS count FROM {from_query} {condition}"
95-
)
96-
num_of_results = cursor.fetchone()["count"]
103+
from_query += " JOIN game ON game.id = fileset.game JOIN engine ON engine.id = game.engine"
104+
else:
105+
from_query += (
106+
f" JOIN {t} ON {get_join_columns(records_table, t, mapping)}"
107+
)
97108

98-
elif "JOIN" in records_table:
99-
first_table = records_table.split(" ")[0]
100-
cursor.execute(f"SELECT COUNT({first_table}.id) FROM {records_table}")
101-
num_of_results = cursor.fetchone()[f"COUNT({first_table}.id)"]
102-
else:
103-
cursor.execute(f"SELECT COUNT(id) FROM {records_table}")
104-
num_of_results = cursor.fetchone()["COUNT(id)"]
109+
base_table = records_table.split(" ")[0]
110+
cursor.execute(
111+
f"SELECT COUNT({base_table}.id) AS count FROM {from_query} {condition}"
112+
)
113+
num_of_results = cursor.fetchone()["count"]
105114

106115
num_of_pages = (num_of_results + results_per_page - 1) // results_per_page
107116
print(f"Num of results: {num_of_results}, Num of pages: {num_of_pages}")
@@ -110,29 +119,21 @@ def create_page(
110119
page = max(1, min(page, num_of_pages))
111120
offset = (page - 1) * results_per_page
112121

113-
# Fetch results
114-
if set(request.args.keys()).difference({"page"}):
115-
condition = "WHERE "
116-
for key, value in request.args.items():
117-
if key not in filters:
118-
continue
119-
120-
value = pymysql.converters.escape_string(value)
121-
if value == "":
122-
value = ".*"
123-
field = f"{filters[key]}.{'id' if key == 'fileset' else key}"
124-
if value == ".*":
125-
clause = f"({field} IS NULL OR {field} REGEXP '{value}')"
126-
else:
127-
clause = f"{field} REGEXP '{value}'"
128-
condition += f" AND {clause}" if condition != "WHERE " else clause
129-
130-
if condition == "WHERE ":
131-
condition = ""
132-
133-
query = f"{select_query} {condition} {order} LIMIT {results_per_page} OFFSET {offset}"
122+
# Sort
123+
order = ""
124+
sort_param = request.args.get("sort")
125+
if sort_param:
126+
sort_parts = sort_param.split("-")
127+
sort_col = sort_parts[0]
128+
order = f"ORDER BY {sort_col}"
129+
if "desc" in sort_param:
130+
order += " DESC"
134131
else:
135-
query = f"{select_query} {order} LIMIT {results_per_page} OFFSET {offset}"
132+
if records_table == "log":
133+
order = "ORDER BY `id` DESC"
134+
135+
# Fetch results
136+
query = f"{select_query} {condition} {order} LIMIT {results_per_page} OFFSET {offset}"
136137
cursor.execute(query)
137138
results = cursor.fetchall()
138139

@@ -154,7 +155,7 @@ def create_page(
154155
<a href="{{ url_for('user_games_list') }}">User Games List</a>
155156
<a href="{{ url_for('ready_for_review') }}">Ready for review</a>
156157
<a href="{{ url_for('fileset_search') }}">Fileset Search</a>
157-
<a href="{{ url_for('logs') }}">Logs</a>
158+
<a href="{{ url_for('logs', sort='id-desc') }}">Logs</a>
158159
<a href="{{ url_for('config') }}">Config</a>
159160
</div>
160161
</nav>

templates/config.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@
117117
<a href="{{ url_for('user_games_list') }}">User Games List</a>
118118
<a href="{{ url_for('ready_for_review') }}">Ready for review</a>
119119
<a href="{{ url_for('fileset_search') }}">Fileset Search</a>
120-
<a href="{{ url_for('logs') }}">Logs</a>
120+
<a href="{{ url_for('logs', sort='id-desc')}}">Logs</a>
121121
<a href="{{ url_for('config') }}">Config</a>
122122
</div>
123123
</nav>

templates/home.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@
8989
<a href="{{ url_for('user_games_list') }}">User Games List</a>
9090
<a href="{{ url_for('ready_for_review') }}">Ready for review</a>
9191
<a href="{{ url_for('fileset_search') }}">Fileset Search</a>
92-
<a href="{{ url_for('logs') }}">Logs</a>
92+
<a href="{{ url_for('logs', sort='id-desc')}}">Logs</a>
9393
<a href="{{ url_for('config') }}">Config</a>
9494
</div>
9595
<div class="dev">

0 commit comments

Comments
 (0)