1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-05-10 00:47:19 +00:00

fix "SQL query built from user-controlled sources"

This commit is contained in:
lian 2025-03-19 16:55:31 +08:00
parent 2152dca689
commit db0e17b645
2 changed files with 214 additions and 146 deletions

View File

@ -28,12 +28,14 @@ class CcnetUsers(object):
self.role = kwargs.get('role')
self.passwd = kwargs.get('passwd')
class CcnetUserRole(object):
def __init__(self, **kwargs):
self.role = kwargs.get('role')
self.is_manual_set = kwargs.get('is_manual_set')
class CcnetDB:
def __init__(self):
@ -50,11 +52,11 @@ class CcnetDB:
`{self.db_name}`.`Group` g
ON o.group_id=g.group_id
WHERE
org_id={org_id} AND parent_group_id<>0;
org_id=%s AND parent_group_id<>0;
"""
groups = []
with connection.cursor() as cursor:
cursor.execute(sql)
cursor.execute(sql, [org_id])
for item in cursor.fetchall():
group_id = item[0]
group_name = item[1]
@ -75,60 +77,52 @@ class CcnetDB:
def list_eligible_users(self, start, limit,
is_active=None, role=None, q=None):
def status(is_active):
return f'AND t1.is_active={is_active} '
conditions = []
params = []
def is_role(role):
if role == 'default':
return 'AND (t2.role is null or t2.role = "default") '
else:
return f'AND t2.role = "{role}" '
if is_active is not None:
conditions.append("t1.is_active = %s")
params.append(is_active)
def search(q):
return f'AND t1.email LIKE "%{q}%" '
search_clause = ''
if is_active:
search_clause += status(is_active)
if role:
search_clause += is_role(role)
if role == 'default':
conditions.append("(t2.role IS NULL OR t2.role = 'default')")
else:
conditions.append("t2.role = %s")
params.append(role)
if q:
search_clause += search(q)
conditions.append("t1.email LIKE %s")
params.append(f"%{q}%")
base_condition = "t1.email NOT LIKE '%%@seafile_group'"
where_clause = f"WHERE {base_condition}"
if conditions:
where_clause += " AND " + " AND ".join(conditions)
count_sql = f"""
SELECT count(1)
FROM
`{self.db_name}`.`EmailUser` t1
LEFT JOIN
`{self.db_name}`.`UserRole` t2
ON
t1.email = t2.email
WHERE
t1.email NOT LIKE '%%@seafile_group' %s
ORDER BY t1.id
""" % search_clause
SELECT COUNT(1)
FROM `{self.db_name}`.`EmailUser` t1
LEFT JOIN `{self.db_name}`.`UserRole` t2 ON t1.email = t2.email
{where_clause}
ORDER BY t1.id
"""
sql = f"""
SELECT t1.id, t1.email, t1.is_staff, t1.is_active, t1.ctime, t2.role, t1.passwd
FROM
`{self.db_name}`.`EmailUser` t1
LEFT JOIN
`{self.db_name}`.`UserRole` t2
ON
t1.email = t2.email
WHERE
t1.email NOT LIKE '%%@seafile_group' %s
ORDER BY t1.id
LIMIT {limit} OFFSET {start};
""" % search_clause
SELECT t1.id, t1.email, t1.is_staff, t1.is_active, t1.ctime, t2.role, t1.passwd
FROM `{self.db_name}`.`EmailUser` t1
LEFT JOIN `{self.db_name}`.`UserRole` t2 ON t1.email = t2.email
{where_clause}
ORDER BY t1.id
LIMIT %s OFFSET %s;
"""
users = []
with connection.cursor() as cursor:
cursor.execute(count_sql)
cursor.execute(count_sql)
cursor.execute(count_sql, params)
total_count = int(cursor.fetchone()[0])
cursor.execute(sql)
cursor.execute(sql, params + [limit, start])
for item in cursor.fetchall():
user_id = item[0]
email = item[1]
@ -159,10 +153,10 @@ class CcnetDB:
FROM
`{self.db_name}`.`GroupUser`
WHERE
group_id IN ({group_ids_str}) AND is_staff = 1
group_id IN (%s) AND is_staff = 1
"""
with connection.cursor() as cursor:
cursor.execute(sql)
cursor.execute(sql, [group_ids_str])
result = cursor.fetchall()
for user, group_id in result:
if group_id in group_admins:
@ -178,16 +172,16 @@ class CcnetDB:
g.creator_name = 'system admin',
g.parent_group_id = -1
WHERE
g.group_id = {group_id}
g.group_id = %s
"""
structure_sql = f"""
INSERT INTO `{self.db_name}`.`GroupStructure` (group_id, path)
VALUES ('{group_id}', '{group_id}')
VALUES (%s, %s)
"""
with connection.cursor() as cursor:
cursor.execute(sql)
cursor.execute(structure_sql)
cursor.execute(sql, [group_id])
cursor.execute(structure_sql, [group_id, group_id])
def get_active_users_by_user_list(self, user_list):
if not user_list:
@ -198,10 +192,12 @@ class CcnetDB:
SELECT `email`
FROM `{self.db_name}`.`EmailUser`
WHERE
email IN ({user_list_str}) AND is_active = 1 AND email NOT LIKE '%%@seafile_group'
email IN (%s)
AND is_active = 1
AND email NOT LIKE '%%@seafile_group'
"""
with connection.cursor() as cursor:
cursor.execute(sql)
cursor.execute(sql, [user_list_str])
for user in cursor.fetchall():
active_users.append(user[0])
@ -209,21 +205,25 @@ class CcnetDB:
def get_org_user_count(self, org_id):
sql = f"""
SELECT COUNT(1) FROM `{self.db_name}`.`OrgUser` WHERE org_id={org_id}
SELECT COUNT(1)
FROM `{self.db_name}`.`OrgUser`
WHERE org_id=%s
"""
user_count = 0
with connection.cursor() as cursor:
cursor.execute(sql)
cursor.execute(sql, [org_id])
user_count = cursor.fetchone()[0]
return user_count
def get_user_role_from_db(self, email):
sql = f"""
SELECT `role`, `is_manual_set` FROM `{self.db_name}`.`UserRole` WHERE email = '{email}';
SELECT `role`, `is_manual_set`
FROM `{self.db_name}`.`UserRole`
WHERE email = %s;
"""
with connection.cursor() as cursor:
cursor.execute(sql)
cursor.execute(sql, [email])
row = cursor.fetchone()
if not row:
role = None

View File

@ -13,7 +13,9 @@ class RepoTrash(object):
self.size = kwargs.get('size')
self.del_time = kwargs.get('del_time')
class WikiInfo(object):
def __init__(self, **kwargs):
self.repo_id = kwargs.get('repo_id')
self.wiki_name = kwargs.get('wiki_name')
@ -25,7 +27,6 @@ class WikiInfo(object):
self.last_modified = kwargs.get('last_modified')
class SeafileDB:
def __init__(self):
@ -67,7 +68,7 @@ class SeafileDB:
FROM
`{self.db_name}`.`SharedRepo` s
WHERE
repo_id = '{repo_id}';
repo_id = %s;
"""
else:
sql = f"""
@ -76,13 +77,13 @@ class SeafileDB:
FROM
`{self.db_name}`.`OrgSharedRepo` s
WHERE
repo_id = '{repo_id}';
repo_id = %s;
"""
share_info_list = []
with connection.cursor() as cursor:
cursor.execute(sql)
cursor.execute(sql, [repo_id])
for item in cursor.fetchall():
info = {}
@ -108,7 +109,7 @@ class SeafileDB:
FROM
`{self.db_name}`.`RepoGroup` s
WHERE
repo_id = '{repo_id}';
repo_id = %s;
"""
else:
sql = f"""
@ -117,13 +118,13 @@ class SeafileDB:
FROM
`{self.db_name}`.`OrgGroupRepo` s
WHERE
repo_id = '{repo_id}';
repo_id = %s;
"""
share_info_list = []
with connection.cursor() as cursor:
cursor.execute(sql)
cursor.execute(sql, [repo_id])
for item in cursor.fetchall():
info = {}
@ -150,7 +151,7 @@ class SeafileDB:
ON
s.repo_id=v.repo_id
WHERE
v.origin_repo = '{repo_id}';
v.origin_repo = %s;
"""
else:
sql = f"""
@ -161,13 +162,13 @@ class SeafileDB:
ON
s.repo_id=v.repo_id
WHERE
v.origin_repo = '{repo_id}';
v.origin_repo = %s;
"""
share_info_list = []
with connection.cursor() as cursor:
cursor.execute(sql)
cursor.execute(sql, [repo_id])
for item in cursor.fetchall():
info = {}
@ -195,7 +196,7 @@ class SeafileDB:
ON
r.repo_id=v.repo_id
WHERE
v.origin_repo = '{repo_id}';
v.origin_repo = %s;
"""
else:
sql = f"""
@ -206,13 +207,13 @@ class SeafileDB:
ON
r.repo_id=v.repo_id
WHERE
v.origin_repo = '{repo_id}';
v.origin_repo = %s;
"""
share_info_list = []
with connection.cursor() as cursor:
cursor.execute(sql)
cursor.execute(sql, [repo_id])
for item in cursor.fetchall():
info = {}
@ -260,12 +261,17 @@ class SeafileDB:
u.repo_id = o.repo_id
ORDER BY
e.error_time DESC
LIMIT {limit} OFFSET {start}
LIMIT %s OFFSET %s
"""
device_errors = []
with connection.cursor() as cursor:
cursor.execute(sql)
if start == -1 and limit == -1:
cursor.execute(sql)
else:
cursor.execute(sql, [limit, start])
for item in cursor.fetchall():
info = {}
info['repo_id'] = item[0]
@ -287,13 +293,13 @@ class SeafileDB:
sql = f"""
SELECT repo_id, repo_name, head_id, owner_id, `size`, del_time
FROM `{self.db_name}`.`RepoTrash`
WHERE org_id = {org_id}
WHERE org_id = %s
ORDER BY del_time DESC
LIMIT {limit} OFFSET {start}
LIMIT %s OFFSET %s
"""
trash_repo_list = []
with connection.cursor() as cursor:
cursor.execute(sql)
cursor.execute(sql, [org_id, limit, start])
for item in cursor.fetchall():
repo_id = item[0]
repo_name = item[1]
@ -319,29 +325,30 @@ class SeafileDB:
empty org repo trash
"""
def del_repo_trash(cursor, repo_ids):
del_file_count_sql = """
DELETE FROM
`%s`.`RepoFileCount`
WHERE
repo_id in %%s;
""" % self.db_name
cursor.execute(del_file_count_sql, (repo_ids, ))
del_repo_info_sql = """
del_file_count_sql = f"""
DELETE FROM
`%s`.`RepoInfo`
`{self.db_name}`.`RepoFileCount`
WHERE
repo_id in %%s;
""" % self.db_name
cursor.execute(del_repo_info_sql, (repo_ids, ))
repo_id in %s;
"""
cursor.execute(del_file_count_sql, [repo_ids])
del_trash_sql = """
del_repo_info_sql = f"""
DELETE FROM
`%s`.`RepoTrash`
`{self.db_name}`.`RepoInfo`
WHERE
repo_id in %%s;
""" % self.db_name
cursor.execute(del_trash_sql, (repo_ids,))
repo_id in %s;
"""
cursor.execute(del_repo_info_sql, [repo_ids])
del_trash_sql = f"""
DELETE FROM
`{self.db_name}`.`RepoTrash`
WHERE
repo_id in %s;
"""
cursor.execute(del_trash_sql, [repo_ids])
sql_list_repo_id = f"""
SELECT
@ -349,10 +356,10 @@ class SeafileDB:
FROM
`{self.db_name}`.`RepoTrash` t
WHERE
org_id={org_id};
org_id = %s;
"""
with connection.cursor() as cursor:
cursor.execute(sql_list_repo_id)
cursor.execute(sql_list_repo_id, [org_id])
repo_ids = []
for item in cursor.fetchall():
repo_id = item[0]
@ -361,81 +368,123 @@ class SeafileDB:
cursor.close()
def add_repos_to_org_user(self, org_id, username, repo_ids):
for repo_id in repo_ids:
sql = f"""
sql = f"""
INSERT INTO `{self.db_name}`.`OrgRepo` (org_id, repo_id, user)
VALUES ({org_id}, "{repo_id}", "{username}");
"""
with connection.cursor() as cursor:
cursor.execute(sql)
VALUES (%s, %s, %s);
"""
with connection.cursor() as cursor:
for repo_id in repo_ids:
cursor.execute(sql, [org_id, repo_id, username])
def set_repo_type(self, repo_id, repo_type):
sql = f"""
UPDATE `{self.db_name}`. `RepoInfo`
SET `type`= '%s'
WHERE `repo_id`='%s'
""" % (repo_type, repo_id)
sql = f"""
UPDATE `{self.db_name}`.`RepoInfo`
SET `type` = %s
WHERE `repo_id` = %s;
"""
with connection.cursor() as cursor:
cursor.execute(sql)
cursor.execute(sql, [repo_type, repo_id])
def get_repo_ids_in_repo(self, repo_id):
repo_ids_sql = f"""
SELECT repo_id from `{self.db_name}`.`VirtualRepo` where origin_repo="{repo_id}"
"""
SELECT repo_id
FROM `{self.db_name}`.`VirtualRepo`
WHERE origin_repo = %s;
"""
repo_ids = [repo_id, ]
with connection.cursor() as cursor:
try:
cursor.execute(repo_ids_sql)
cursor.execute(repo_ids_sql, [repo_id])
for item in cursor.fetchall():
repo_id = item[0]
repo_ids.append(repo_id)
except:
except Exception:
return repo_ids
return repo_ids
def set_repo_owner(self, repo_id, new_owner, org_id=None):
# transfert repo to user
repo_ids = self.get_repo_ids_in_repo(repo_id)
repo_ids_str = ','.join(["'%s'" % str(rid) for rid in repo_ids])
if org_id:
sql = f"""
UPDATE `{self.db_name}`.`OrgRepo` SET user="{new_owner}" WHERE org_id ={org_id} AND repo_id IN ({repo_ids_str})
UPDATE `{self.db_name}`.`OrgRepo`
SET user= %s
WHERE org_id =%s AND repo_id IN (%s)
"""
else:
sql = f"""
UPDATE `{self.db_name}`.`RepoOwner` SET owner_id="{new_owner}" WHERE repo_id IN ({repo_ids_str})
UPDATE `{self.db_name}`.`RepoOwner`
SET owner_id= %s
WHERE repo_id IN (%s)
"""
repo_ids = self.get_repo_ids_in_repo(repo_id)
repo_ids_str = ','.join(["'%s'" % str(rid) for rid in repo_ids])
with connection.cursor() as cursor:
cursor.execute(sql)
if org_id:
cursor.execute(sql, [new_owner, org_id, repo_ids_str])
else:
cursor.execute(sql, [new_owner, repo_ids_str])
def set_repo_group_owner(self, repo_id, group_id, current_group_id=None, org_id=None):
# transfer repo to department
group_username = "%s@seafile_group" % group_id
current_group_username = None
if current_group_id:
current_group_username = "%s@seafile_group" % current_group_id
if org_id:
sql1 = f"""
DELETE From `{self.db_name}`.`OrgGroupRepo` where owner="{current_group_username}" AND repo_id="{repo_id}" AND org_id="{org_id}" AND group_id="{current_group_id}"
delete_sql = f"""
DELETE From `{self.db_name}`.`OrgGroupRepo`
WHERE owner=%s
AND repo_id=%s
AND org_id=%s
AND group_id=%s
"""
sql = f"""
INSERT INTO `{self.db_name}`.`OrgGroupRepo` (org_id, repo_id, group_id, owner, permission) VALUES ({org_id}, "{repo_id}", {group_id}, "{group_username}", "rw")
ON DUPLICATE KEY UPDATE owner="{group_username}"
INSERT INTO `{self.db_name}`.`OrgGroupRepo` (org_id, repo_id, group_id, owner, permission)
VALUES (%s, %s, %s, %s, "rw")
ON DUPLICATE KEY UPDATE owner=%s
"""
else:
sql1 = f"""
DELETE From `{self.db_name}`.`RepoGroup` where user_name="{current_group_username}" AND repo_id="{repo_id}" AND group_id="{current_group_id}"
"""
delete_sql = f"""
DELETE FROM `{self.db_name}`.`RepoGroup`
WHERE user_name=%s
AND repo_id=%s
AND group_id=%s
"""
sql = f"""
INSERT INTO `{self.db_name}`.`RepoGroup` (repo_id, group_id, user_name, permission) VALUES ("{repo_id}", {group_id}, "{group_username}", "rw")
ON DUPLICATE KEY UPDATE user_name="{group_username}"
INSERT INTO `{self.db_name}`.`RepoGroup` (repo_id, group_id, user_name, permission)
VALUES (%s, %s, %s, "rw")
ON DUPLICATE KEY UPDATE user_name=%s
"""
with connection.cursor() as cursor:
if current_group_id:
cursor.execute(sql1)
cursor.execute(sql)
if org_id:
if current_group_id:
cursor.execute(delete_sql, [current_group_username,
repo_id, org_id, current_group_id])
cursor.execute(sql, [org_id, repo_id, group_id,
group_username, group_username])
else:
if current_group_id:
cursor.execute(delete_sql, [current_group_username,
repo_id, current_group_id])
cursor.execute(sql, [repo_id, group_id,
group_username, group_username])
self.set_repo_owner(repo_id, group_username, org_id)
def update_repo_user_shares(self, repo_id, new_owner, org_id=None):
@ -443,38 +492,54 @@ class SeafileDB:
repo_ids_str = ','.join(["'%s'" % str(rid) for rid in repo_ids])
if org_id:
sql = f"""
UPDATE `{self.db_name}`.`OrgSharedRepo` SET from_email="{new_owner}" WHERE org_id={org_id} AND repo_id IN ({repo_ids_str})
UPDATE `{self.db_name}`.`OrgSharedRepo`
SET from_email=%s
WHERE org_id=%s
AND repo_id IN (%s)
"""
else:
sql = f"""
UPDATE `{self.db_name}`.`SharedRepo` SET from_email="{new_owner}" WHERE repo_id IN ({repo_ids_str})
UPDATE `{self.db_name}`.`SharedRepo`
SET from_email=%s
WHERE repo_id IN (%s)
"""
with connection.cursor() as cursor:
cursor.execute(sql)
if org_id:
cursor.execute(sql, [new_owner, org_id, repo_ids_str])
else:
cursor.execute(sql, [new_owner, repo_ids_str])
def update_repo_group_shares(self, repo_id, new_owner, org_id=None):
repo_ids = self.get_repo_ids_in_repo(repo_id)
repo_ids_str = ','.join(["'%s'" % str(rid) for rid in repo_ids])
if org_id:
sql = f"""
UPDATE `{self.db_name}`.`OrgGroupRepo` SET owner="{new_owner}" WHERE org_id={org_id} AND repo_id IN ({repo_ids_str})
UPDATE `{self.db_name}`.`OrgGroupRepo`
SET owner=%s
WHERE org_id=%s
AND repo_id IN (%s)
"""
else:
sql = f"""
UPDATE `{self.db_name}`.`RepoGroup` SET user_name="{new_owner}" WHERE repo_id IN ({repo_ids_str})
UPDATE `{self.db_name}`.`RepoGroup`
SET user_name=%s
WHERE repo_id IN (%s)
"""
with connection.cursor() as cursor:
cursor.execute(sql)
if org_id:
cursor.execute(sql, [new_owner, org_id, repo_ids_str])
else:
cursor.execute(sql, [new_owner, repo_ids_str])
def delete_repo_user_token(self, repo_id, owner):
sql = f"""
DELETE FROM `{self.db_name}`.`RepoUserToken` where repo_id="{repo_id}" AND email="{owner}"
DELETE FROM `{self.db_name}`.`RepoUserToken`
WHERE repo_id=%s
AND email=%s
"""
with connection.cursor() as cursor:
cursor.execute(sql)
cursor.execute(sql, [repo_id, owner])
def get_all_wikis(self, start, limit, order_by):
order_by_size_sql = f"""
SELECT r.repo_id, i.name, o.owner_id, i.is_encrypted, s.size, i.status, c.file_count, i.update_time
@ -488,7 +553,7 @@ class SeafileDB:
i.type = 'wiki'
ORDER BY
s.size DESC
LIMIT {limit} OFFSET {start}
LIMIT %s OFFSET %s
"""
order_by_filecount_sql = f"""
SELECT r.repo_id, i.name, o.owner_id, i.is_encrypted, s.size, i.status, c.file_count, i.update_time
@ -502,7 +567,7 @@ class SeafileDB:
i.type = 'wiki'
ORDER BY
c.file_count DESC
LIMIT {limit} OFFSET {start}
LIMIT %s OFFSET %s
"""
sql = f"""
SELECT r.repo_id, i.name, o.owner_id, i.is_encrypted, s.size, i.status, c.file_count, i.update_time
@ -514,18 +579,21 @@ class SeafileDB:
LEFT JOIN `{self.db_name}`.`RepoFileCount` c ON r.repo_id = c.repo_id
WHERE
i.type = 'wiki'
LIMIT {limit} OFFSET {start}
LIMIT %s OFFSET %s
"""
with connection.cursor() as cursor:
wikis = []
if order_by == 'size':
cursor.execute(order_by_size_sql)
cursor.execute(order_by_size_sql, [limit, start])
elif order_by == 'file_count':
cursor.execute(order_by_filecount_sql)
cursor.execute(order_by_filecount_sql, [limit, start])
else:
cursor.execute(sql)
cursor.execute(sql, [limit, start])
for item in cursor.fetchall():
repo_id = item[0]
wiki_name = item[1]