1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-09-15 23:00:57 +00:00

[api] update search user api

This commit is contained in:
lian
2016-01-14 13:10:24 +08:00
parent 5f3c030a52
commit 0e43a099ff
7 changed files with 218 additions and 16 deletions

View File

@@ -861,7 +861,7 @@ function userInputOPtionsForSelect2(user_search_url) {
// for search. both name & email can be searched.
// use ' '(space) to separate name & email
"text": users[i].name + ' ' + users[i].email,
"avatar": users[i].avatar,
"avatar_url": users[i].avatar_url,
"name": users[i].name
});
}
@@ -873,8 +873,8 @@ function userInputOPtionsForSelect2(user_search_url) {
// format items shown in the drop-down menu
formatResult: function(item) {
if (item.avatar) {
return item.avatar + '<span class="text ellipsis">' + HTMLescape(item.name) + '<br />' + HTMLescape(item.id) + '</span>';
if (item.avatar_url) {
return '<img src="' + item.avatar_url + '" width="32" height="32" class="avatar">' + '<span class="text ellipsis">' + HTMLescape(item.name) + '<br />' + HTMLescape(item.id) + '</span>';
} else {
return; // if no match, show nothing
}

View File

@@ -0,0 +1,165 @@
import json
from django.db.models import Q
from django.http import HttpResponse
from rest_framework.authentication import SessionAuthentication
from rest_framework.permissions import IsAuthenticated
from rest_framework.views import APIView
from rest_framework import status
import seaserv
from seahub.api2.authentication import TokenAuthentication
from seahub.api2.throttling import UserRateThrottle
from seahub.api2.utils import api_error
from seahub.utils import is_org_context
from seahub.base.accounts import User
from seahub.base.templatetags.seahub_tags import email2nickname
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, ENABLE_SEARCH_FROM_LDAP_DIRECTLY
class SearchUser(APIView):
""" Search user from contacts/all users
"""
authentication_classes = (TokenAuthentication, SessionAuthentication)
permission_classes = (IsAuthenticated,)
throttle_classes = (UserRateThrottle, )
def _can_use_global_address_book(self, request):
return request.user.permissions.can_use_global_address_book()
def get(self, request, format=None):
if not self._can_use_global_address_book(request):
return api_error(status.HTTP_403_FORBIDDEN,
'Guest user can not use global address book.')
q = request.GET.get('q', None)
if not q:
return api_error(status.HTTP_400_BAD_REQUEST, 'Argument missing.')
users_from_ccnet = []
users_from_profile = []
users_result = []
username = request.user.username
if request.cloud_mode:
if is_org_context(request):
url_prefix = request.user.org.url_prefix
users = seaserv.get_org_users_by_url_prefix(url_prefix, -1, -1)
# search user from ccnet
users_from_ccnet = filter(lambda u: q in u.email, users)
# when search profile, only search users in org
# 'nickname__contains' for search by nickname
# 'contact_email__contains' for search by contact email
users_from_profile = Profile.objects.filter(Q(user__in=[u.email for u in users]) & \
(Q(nickname__contains=q)) | \
Q(contact_email__contains=q)).values('user')
elif ENABLE_GLOBAL_ADDRESSBOOK:
users_from_ccnet = search_user_from_ccnet(q)
users_from_profile = Profile.objects.filter(Q(contact_email__contains=q) | \
Q(nickname__contains=q)).values('user')
else:
# TODO delete this ?
users = []
contacts = Contact.objects.get_contacts_by_user(username)
for c in contacts:
try:
user = User.objects.get(email = c.contact_email)
c.is_active = user.is_active
except User.DoesNotExist:
continue
c.email = c.contact_email
users.append(c)
users_from_ccnet = filter(lambda u: q in u.email, users)
# 'user__in' for only get profile of contacts
# 'nickname__contains' for search by nickname
# 'contact_email__contains' for search by contact
users_from_profile = Profile.objects.filter(Q(user__in=[u.email for u in users]) & \
(Q(nickname__contains=q)) | \
Q(contact_email__contains=q)).values('user')
else:
users_from_ccnet = search_user_from_ccnet(q)
users_from_profile = Profile.objects.filter(Q(contact_email__contains=q) | \
Q(nickname__contains=q)).values('user')
# remove inactive users and add to result
for u in users_from_ccnet[:10]:
if u.is_active:
users_result.append(u.email)
for p in users_from_profile[:10]:
try:
user = User.objects.get(email = p['user'])
except User.DoesNotExist:
continue
if not user.is_active:
continue
users_result.append(p['user'])
# remove duplicate emails
users_result = {}.fromkeys(users_result).keys()
try:
include_self = int(request.GET.get('include_self', 1))
except ValueError:
include_self = 1
if include_self == 0 and username in users_result:
# reomve myself
users_result.remove(username)
try:
size = int(request.GET.get('avatar_size', 32))
except ValueError:
size = 32
formated_result = format_searched_user_result(request, users_result, size)[:10]
return HttpResponse(json.dumps({"users": formated_result}), status=200,
content_type='application/json; charset=utf-8')
def format_searched_user_result(request, users, size):
results = []
for email in users:
url, is_default, date_uploaded = api_avatar_url(email, size)
results.append({
"email": email,
"avatar_url": request.build_absolute_uri(url),
"name": email2nickname(email),
"contact_email": Profile.objects.get_contact_email_by_user(email),
})
return results
def search_user_from_ccnet(q):
users = []
db_users = seaserv.ccnet_threaded_rpc.search_emailusers('DB', q, 0, 10)
users.extend(db_users)
count = len(users)
if count < 10:
ldap_imported_users = seaserv.ccnet_threaded_rpc.search_emailusers('LDAP', q, 0, 10 - count)
users.extend(ldap_imported_users)
count = len(users)
if count < 10 and ENABLE_SEARCH_FROM_LDAP_DIRECTLY:
all_ldap_users = seaserv.ccnet_threaded_rpc.search_ldapusers(q, 0, 10 - count)
users.extend(all_ldap_users)
return users

View File

@@ -7,6 +7,7 @@ from .endpoints.dir_shared_items import DirSharedItemsEndpoint
from .endpoints.account import Account
from .endpoints.shared_upload_links import SharedUploadLinksView
from .endpoints.be_shared_repo import BeSharedReposView
from .endpoints.search_user import SearchUser
urlpatterns = patterns('',
url(r'^ping/$', Ping.as_view()),

View File

@@ -415,6 +415,7 @@ def get_searched_users(q):
return searched_users
class Search(APIView):
""" Search all the repos
"""

View File

@@ -227,6 +227,9 @@ ACCOUNT_ACTIVATION_DAYS = 7
# allow seafile amdin view user's repo
ENABLE_SYS_ADMIN_VIEW_REPO = False
#allow search from LDAP directly during auto-completion (not only search imported users)
ENABLE_SEARCH_FROM_LDAP_DIRECTLY = False
# show traffic on the UI
SHOW_TRAFFIC = True

View File

@@ -564,7 +564,7 @@ define([
// for search. both name & email can be searched.
// use ' '(space) to separate name & email
"text": users[i].name + ' ' + users[i].email,
"avatar": users[i].avatar,
"avatar_url": users[i].avatar_url,
"name": users[i].name
});
}
@@ -577,8 +577,8 @@ define([
// format items shown in the drop-down menu
formatResult: function(item) {
if (item.avatar) {
return item.avatar + '<span class="text ellipsis">' + _this.HTMLescape(item.name) + '<br />' + _this.HTMLescape(item.id) + '</span>';
if (item.avatar_url) {
return '<img src="' + item.avatar_url + '" width="32" height="32" class="avatar"><span class="text ellipsis">' + _this.HTMLescape(item.name) + '<br />' + _this.HTMLescape(item.id) + '</span>';
} else {
return; // if no match, show nothing
}

View File

@@ -12,20 +12,55 @@ class SearchUserTest(BaseTestCase):
self.endpoint = reverse('search-user')
def test_can_search(self):
p = Profile.objects.add_or_update(self.user.email, nickname="test")
p.contact_email = 'new_mail@test.com'
email = self.admin.email
nickname = 'admin_test'
contact_email= 'new_admin_test@test.com'
p = Profile.objects.add_or_update(email, nickname=nickname)
p.contact_email = contact_email
p.save()
resp = self.client.get(self.endpoint + '?q=' + self.user.email)
resp = self.client.get(self.endpoint + '?q=' + email)
json_resp = json.loads(resp.content)
self.assertEqual(200, resp.status_code)
assert json_resp['users'] is not None
assert json_resp['users'][0]['email'] == self.user.email
assert json_resp['users'][0]['avatar'] is not None
assert json_resp['users'][0]['email'] == email
assert json_resp['users'][0]['avatar_url'] is not None
assert json_resp['users'][0]['name'] == 'test'
assert json_resp['users'][0]['contact_email'] == 'new_mail@test.com'
assert json_resp['users'][0]['name'] == nickname
assert json_resp['users'][0]['contact_email'] == contact_email
def test_search_myself(self):
email = self.user.email
nickname = 'user_test'
contact_email= 'new_user_test@test.com'
p = Profile.objects.add_or_update(email, nickname=nickname)
p.contact_email = contact_email
p.save()
resp = self.client.get(self.endpoint + '?q=' + email)
json_resp = json.loads(resp.content)
self.assertEqual(200, resp.status_code)
assert json_resp['users'] is not None
assert json_resp['users'][0]['email'] == email
assert json_resp['users'][0]['avatar_url'] is not None
assert json_resp['users'][0]['name'] == nickname
assert json_resp['users'][0]['contact_email'] == contact_email
def test_search_without_myself(self):
email = self.user.email
resp = self.client.get(self.endpoint + '?include_self=0&q=' + email)
json_resp = json.loads(resp.content)
self.assertEqual(200, resp.status_code)
assert len(json_resp['users']) == 0
def test_search_unregistered_user(self):
resp = self.client.get(self.endpoint + '?q=unregistered_user@seafile.com')
json_resp = json.loads(resp.content)
self.assertEqual(200, resp.status_code)
assert len(json_resp['users']) == 0
def test_can_search_by_nickname(self):
admin_email = self.admin.email
@@ -42,7 +77,6 @@ class SearchUserTest(BaseTestCase):
self.assertEqual(200, resp.status_code)
assert json_resp['users'] is not None
assert json_resp['users'][0]['email'] == admin_email
assert json_resp['users'][0]['avatar'] is not None
assert json_resp['users'][0]['avatar_url'] is not None
assert json_resp['users'][0]['name'] == 'Carl Smith'
assert json_resp['users'][0]['contact_email'] == 'new_mail@test.com'
@@ -63,7 +97,6 @@ class SearchUserTest(BaseTestCase):
self.assertEqual(200, resp.status_code)
assert json_resp['users'] is not None
assert json_resp['users'][0]['email'] == admin_email
assert json_resp['users'][0]['avatar'] is not None
assert json_resp['users'][0]['avatar_url'] is not None
assert json_resp['users'][0]['name'] == 'Carl Smith'
assert json_resp['users'][0]['contact_email'] == 'new_mail@test.com'
@@ -75,7 +108,6 @@ class SearchUserTest(BaseTestCase):
self.assertEqual(200, resp.status_code)
assert json_resp['users'] is not None
assert json_resp['users'][0]['email'] == admin_email
assert json_resp['users'][0]['avatar'] is not None
assert json_resp['users'][0]['avatar_url'] is not None
assert json_resp['users'][0]['name'] == 'Carl Smith'
assert json_resp['users'][0]['contact_email'] == 'new_mail@test.com'