Skip to content

Commit

Permalink
update search user web api
Browse files Browse the repository at this point in the history
only return active users
  • Loading branch information
imwhatiam committed Oct 22, 2024
1 parent a5953c5 commit f1dccc5
Show file tree
Hide file tree
Showing 6 changed files with 114 additions and 136 deletions.
101 changes: 43 additions & 58 deletions seahub/api2/endpoints/search_user.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# Copyright (c) 2012-2016 Seafile Ltd.
import os
import sys
import json
import logging

from django.db.models import Q
Expand All @@ -18,12 +17,13 @@
from seahub.api2.authentication import TokenAuthentication
from seahub.api2.throttling import UserRateThrottle
from seahub.api2.utils import api_error

from seahub.utils import is_valid_email, is_org_context
from seahub.utils.ccnet_db import CcnetDB
from seahub.base.accounts import User
from seahub.base.templatetags.seahub_tags import email2nickname, \
email2contact_email
from seahub.profile.models import Profile
from seahub.contacts.models import Contact
from seahub.avatar.templatetags.avatar_tags import api_avatar_url

from seahub.settings import ENABLE_GLOBAL_ADDRESSBOOK, \
Expand All @@ -38,12 +38,11 @@

try:
current_path = os.path.dirname(os.path.abspath(__file__))
seafile_conf_dir = os.path.join(current_path, \
'../../../../../conf')
seafile_conf_dir = os.path.join(current_path, '../../../../../conf')
sys.path.append(seafile_conf_dir)
from seahub_custom_functions import custom_search_user
CUSTOM_SEARCH_USER = True
except ImportError as e:
except ImportError:
CUSTOM_SEARCH_USER = False


Expand Down Expand Up @@ -84,6 +83,10 @@ def get(self, request, format=None):

limited_emails = []
for org_user in all_org_users:

if not org_user.is_active:
continue

# prepare limited emails for search from profile
limited_emails.append(org_user.email)

Expand Down Expand Up @@ -121,18 +124,7 @@ def get(self, request, format=None):

# remove duplicate emails
# get_emailusers_in_list can only accept 20 users at most
email_list = list({}.fromkeys(email_list).keys())[:20]

email_result = []

# remove nonexistent or inactive user
email_list_json = json.dumps(email_list)
user_obj_list = ccnet_api.get_emailusers_in_list('DB', email_list_json) + \
ccnet_api.get_emailusers_in_list('LDAP', email_list_json)

for user_obj in user_obj_list:
if user_obj.is_active:
email_result.append(user_obj.email)
email_result = list({}.fromkeys(email_list).keys())[:20]

# specific search `q`
user_q_obj = ccnet_api.get_emailuser(q)
Expand Down Expand Up @@ -177,7 +169,7 @@ def format_searched_user_result(request, users, size):
results = []
if ENABLE_SHOW_LOGIN_ID_WHEN_SEARCH_USER:
profile_queryset = Profile.objects.filter(user__in=users)
profile_dict = { p.user: p.login_id for p in profile_queryset if p.login_id }
profile_dict = {p.user: p.login_id for p in profile_queryset if p.login_id}

for email in users:
url, is_default, date_uploaded = api_avatar_url(email, size)
Expand All @@ -194,21 +186,16 @@ def format_searched_user_result(request, users, size):
return results


def search_user_from_ccnet(q):
def search_user_from_ccnet(q, offset=0, limit=10):
""" Return 10 items at most.
"""

users = []

db_users = ccnet_api.search_emailusers('DB', q, 0, 10)
users.extend(db_users)

count = len(users)
if count < 10:
ldap_imported_users = ccnet_api.search_emailusers('LDAP', q, 0, 10 - count)
users.extend(ldap_imported_users)
ccnet_db = CcnetDB()
users, count = ccnet_db.list_eligible_users(offset, limit,
is_active=True, q=q)

count = len(users)
if count < 10 and ENABLE_SEARCH_FROM_LDAP_DIRECTLY:
all_ldap_users = ccnet_api.search_ldapusers(q, 0, 10 - count)
users.extend(all_ldap_users)
Expand All @@ -221,29 +208,44 @@ def search_user_from_ccnet(q):
return email_list


def search_user_from_profile(q):
""" Return 10 items at most.
"""
# 'nickname__icontains' for search by nickname
# 'contact_email__icontains' for search by contact email
users = Profile.objects.filter(Q(nickname__icontains=q) | \
Q(contact_email__icontains=q) | \
Q(login_id__icontains=q)).values('user')[:10]
def search_user_from_profile(q, offset=0, limit=10, max_attempts=10):
"""Return a list of email addresses, with a length of at least 10.
If not enough results are found, continue searching up to max_attempts times.
"""
email_list = []
for user in users:
email_list.append(user['user'])
attempts = 0

return email_list
ccnet_db = CcnetDB()

while len(email_list) < 10 and attempts < max_attempts:

# Search by nickname, contact email, or login ID
users = Profile.objects.filter(
Q(nickname__icontains=q) |
Q(contact_email__icontains=q) |
Q(login_id__icontains=q)
).values('user')[offset:offset + limit]

new_emails = ccnet_db.get_active_users_by_user_list([user['user'] for user in users])
email_list.extend([email for email in new_emails if email not in email_list])
offset += limit
attempts += 1

return email_list[:10]


def search_user_from_profile_with_limits(q, limited_emails):
""" Return 10 items at most.
"""
# search within limited_emails
users = Profile.objects.filter(Q(user__in=limited_emails) & (Q(nickname__icontains=q) | \
Q(contact_email__icontains=q) | \
Q(login_id__icontains=q))).values('user')[:10]
users = Profile.objects.filter(
Q(user__in=limited_emails) & (
Q(nickname__icontains=q) |
Q(contact_email__icontains=q) |
Q(login_id__icontains=q)
)
).values('user')[:10]

email_list = []
for user in users:
Expand All @@ -259,23 +261,6 @@ def search_user_when_global_address_book_disabled(request, q):

email_list = []
username = request.user.username

# search from contact
# get user's contact list
contacts = Contact.objects.get_contacts_by_user(username)
for contact in contacts:

# search user from contact list
if q in contact.contact_email:
email_list.append(contact.contact_email)

# search from profile, limit search range in user's contacts
limited_emails = []
for contact in contacts:
limited_emails.append(contact.contact_email)

email_list += search_user_from_profile_with_limits(q, limited_emails)

current_user = User.objects.get(email=username)
if current_user.role.lower() != 'guest':

Expand Down
12 changes: 6 additions & 6 deletions seahub/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,12 @@

DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'.
'NAME': '%s/seahub/seahub.db' % PROJECT_ROOT, # Or path to database file if using sqlite3.
'USER': '', # Not used with sqlite3.
'PASSWORD': '', # Not used with sqlite3.
'HOST': '', # Set to empty string for localhost. Not used with sqlite3.
'PORT': '', # Set to empty string for default. Not used with sqlite3.
'ENGINE': 'django.db.backends.mysql',
'NAME': 'seahub',
'USER': 'root',
'PASSWORD': 'root',
'HOST': '127.0.0.1',
'PORT': '3306',
}
}

Expand Down
38 changes: 20 additions & 18 deletions seahub/utils/ccnet_db.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
import os
import configparser
from django.db import connection


def get_ccnet_db_name():
Expand All @@ -24,11 +25,6 @@ def get_ccnet_db_name():
return db_name, None


import os
import configparser
from django.db import connection


class CcnetGroup(object):

def __init__(self, **kwargs):
Expand Down Expand Up @@ -89,23 +85,29 @@ def list_org_departments(self, org_id):
groups.append(group_obj)
return groups

def list_eligible_users(self, start, limit, is_active=None, role=None):
def list_eligible_users(self, start, limit,
is_active=None, role=None, q=None):

def status(is_active):
return 'AND t1.is_active=%s ' % is_active
return f'AND t1.is_active={is_active} '

def is_role(role):
if role == 'default':
return 'AND (t2.role is null or t2.role = "default")'
return 'AND (t2.role is null or t2.role = "default") '
else:
return 'AND t2.role = "%s"' % role

return f'AND t2.role = "{role}" '

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 q:
search_clause += search(q)

count_sql = f"""
SELECT count(1)
FROM
Expand All @@ -130,16 +132,15 @@ def is_role(role):
WHERE
t1.email NOT LIKE '%%@seafile_group' %s
ORDER BY t1.id
LIMIT {limit} OFFSET {start}
LIMIT {limit} OFFSET {start};
""" % search_clause

users = []
total = 0
with connection.cursor() as cursor:
cursor.execute(count_sql)
cursor.execute(count_sql)
total_count = int(cursor.fetchone()[0])

cursor.execute(sql)
for item in cursor.fetchall():
user_id = item[0]
Expand Down Expand Up @@ -168,9 +169,9 @@ def get_group_ids_admins_map(self, group_ids):
group_ids_str = ','.join(str(id) for id in group_ids)
sql = f"""
SELECT user_name, group_id
FROM
FROM
`{self.db_name}`.`GroupUser`
WHERE
WHERE
group_id IN ({group_ids_str}) AND is_staff = 1
"""
with connection.cursor() as cursor:
Expand Down Expand Up @@ -210,10 +211,11 @@ def get_active_users_by_user_list(self, user_list):
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 ({user_list_str}) AND is_active = 1 AND email NOT LIKE '%%@seafile_group'
"""
with connection.cursor() as cursor:
cursor.execute(sql)
for user in cursor.fetchall():
active_users.append(user[0])

return active_users
Loading

0 comments on commit f1dccc5

Please sign in to comment.