2019-02-26 04:38:20 +00:00
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
#
|
|
|
|
|
2020-09-07 12:33:44 +00:00
|
|
|
import threading
|
2023-05-25 08:26:35 +00:00
|
|
|
|
|
|
|
from django.conf import settings
|
2023-07-24 03:52:25 +00:00
|
|
|
from django.utils.translation import gettext_lazy as _
|
2019-05-29 02:11:58 +00:00
|
|
|
from rest_framework import generics
|
2023-05-25 08:26:35 +00:00
|
|
|
from rest_framework.generics import CreateAPIView
|
2019-03-22 07:55:46 +00:00
|
|
|
from rest_framework.views import Response, APIView
|
2019-02-26 04:38:20 +00:00
|
|
|
|
2023-05-25 08:26:35 +00:00
|
|
|
from common.api import AsyncApiMixin
|
2023-06-22 13:36:19 +00:00
|
|
|
from common.utils import get_logger
|
2023-05-25 08:26:35 +00:00
|
|
|
from orgs.models import Organization
|
|
|
|
from orgs.utils import current_org
|
|
|
|
from users.models import User
|
|
|
|
from ..models import Setting
|
2021-01-26 09:54:12 +00:00
|
|
|
from ..serializers import (
|
2021-07-23 03:16:12 +00:00
|
|
|
LDAPTestConfigSerializer, LDAPUserSerializer,
|
|
|
|
LDAPTestLoginSerializer
|
2019-11-06 03:57:00 +00:00
|
|
|
)
|
2023-05-25 08:26:35 +00:00
|
|
|
from ..tasks import sync_ldap_user
|
|
|
|
from ..utils import (
|
|
|
|
LDAPServerUtil, LDAPCacheUtil, LDAPImportUtil, LDAPSyncUtil,
|
|
|
|
LDAP_USE_CACHE_FLAGS, LDAPTestUtil
|
|
|
|
)
|
2019-02-26 04:38:20 +00:00
|
|
|
|
2019-03-28 04:50:04 +00:00
|
|
|
logger = get_logger(__file__)
|
|
|
|
|
|
|
|
|
2023-05-25 08:26:35 +00:00
|
|
|
class LDAPTestingConfigAPI(AsyncApiMixin, CreateAPIView):
|
2020-03-12 08:24:38 +00:00
|
|
|
serializer_class = LDAPTestConfigSerializer
|
2022-03-10 09:59:05 +00:00
|
|
|
perm_model = Setting
|
2022-02-17 12:13:31 +00:00
|
|
|
rbac_perms = {
|
2023-05-25 08:26:35 +00:00
|
|
|
'POST': 'settings.change_auth',
|
|
|
|
'create': 'settings.change_auth',
|
2022-02-17 12:13:31 +00:00
|
|
|
}
|
2020-03-12 08:24:38 +00:00
|
|
|
|
2023-05-25 08:26:35 +00:00
|
|
|
def is_need_async(self):
|
|
|
|
return True
|
|
|
|
|
|
|
|
def create(self, request, *args, **kwargs):
|
2020-03-12 08:24:38 +00:00
|
|
|
serializer = self.serializer_class(data=request.data)
|
|
|
|
if not serializer.is_valid():
|
2020-05-07 08:57:57 +00:00
|
|
|
return Response({"error": str(serializer.errors)}, status=400)
|
2020-03-12 08:24:38 +00:00
|
|
|
config = self.get_ldap_config(serializer)
|
|
|
|
ok, msg = LDAPTestUtil(config).test_config()
|
2020-05-07 08:57:57 +00:00
|
|
|
status = 200 if ok else 400
|
2020-03-12 08:24:38 +00:00
|
|
|
return Response(msg, status=status)
|
2019-02-26 04:38:20 +00:00
|
|
|
|
2019-03-28 04:50:04 +00:00
|
|
|
@staticmethod
|
2019-11-11 08:41:32 +00:00
|
|
|
def get_ldap_config(serializer):
|
|
|
|
server_uri = serializer.validated_data["AUTH_LDAP_SERVER_URI"]
|
2019-03-28 04:50:04 +00:00
|
|
|
bind_dn = serializer.validated_data["AUTH_LDAP_BIND_DN"]
|
|
|
|
password = serializer.validated_data["AUTH_LDAP_BIND_PASSWORD"]
|
|
|
|
use_ssl = serializer.validated_data.get("AUTH_LDAP_START_TLS", False)
|
2020-03-12 08:24:38 +00:00
|
|
|
search_ou = serializer.validated_data["AUTH_LDAP_SEARCH_OU"]
|
2019-03-28 04:50:04 +00:00
|
|
|
search_filter = serializer.validated_data["AUTH_LDAP_SEARCH_FILTER"]
|
|
|
|
attr_map = serializer.validated_data["AUTH_LDAP_USER_ATTR_MAP"]
|
2020-03-12 08:24:38 +00:00
|
|
|
auth_ldap = serializer.validated_data.get('AUTH_LDAP', False)
|
2021-12-14 11:28:05 +00:00
|
|
|
|
|
|
|
if not password:
|
|
|
|
password = settings.AUTH_LDAP_BIND_PASSWORD
|
|
|
|
|
2019-11-11 08:41:32 +00:00
|
|
|
config = {
|
|
|
|
'server_uri': server_uri,
|
|
|
|
'bind_dn': bind_dn,
|
|
|
|
'password': password,
|
|
|
|
'use_ssl': use_ssl,
|
2020-03-12 08:24:38 +00:00
|
|
|
'search_ou': search_ou,
|
2019-11-11 08:41:32 +00:00
|
|
|
'search_filter': search_filter,
|
2020-03-12 08:24:38 +00:00
|
|
|
'attr_map': attr_map,
|
|
|
|
'auth_ldap': auth_ldap
|
2019-11-11 08:41:32 +00:00
|
|
|
}
|
|
|
|
return config
|
2019-03-28 04:50:04 +00:00
|
|
|
|
2020-03-12 08:24:38 +00:00
|
|
|
|
|
|
|
class LDAPTestingLoginAPI(APIView):
|
|
|
|
serializer_class = LDAPTestLoginSerializer
|
2022-03-10 09:59:05 +00:00
|
|
|
perm_model = Setting
|
2022-02-17 12:13:31 +00:00
|
|
|
rbac_perms = {
|
2022-03-10 09:59:05 +00:00
|
|
|
'POST': 'settings.change_auth'
|
2022-02-17 12:13:31 +00:00
|
|
|
}
|
2020-03-12 08:24:38 +00:00
|
|
|
|
2019-02-26 04:38:20 +00:00
|
|
|
def post(self, request):
|
|
|
|
serializer = self.serializer_class(data=request.data)
|
2019-03-28 04:50:04 +00:00
|
|
|
if not serializer.is_valid():
|
2020-05-07 08:57:57 +00:00
|
|
|
return Response({"error": str(serializer.errors)}, status=400)
|
2020-03-12 08:24:38 +00:00
|
|
|
username = serializer.validated_data['username']
|
|
|
|
password = serializer.validated_data['password']
|
|
|
|
ok, msg = LDAPTestUtil().test_login(username, password)
|
2020-05-07 08:57:57 +00:00
|
|
|
status = 200 if ok else 400
|
2020-03-12 08:24:38 +00:00
|
|
|
return Response(msg, status=status)
|
2019-02-26 04:38:20 +00:00
|
|
|
|
|
|
|
|
2019-05-29 02:11:58 +00:00
|
|
|
class LDAPUserListApi(generics.ListAPIView):
|
2019-08-21 12:27:21 +00:00
|
|
|
serializer_class = LDAPUserSerializer
|
2022-03-10 09:59:05 +00:00
|
|
|
perm_model = Setting
|
2022-02-17 12:13:31 +00:00
|
|
|
rbac_perms = {
|
2022-03-10 09:59:05 +00:00
|
|
|
'list': 'settings.change_auth'
|
2022-02-17 12:13:31 +00:00
|
|
|
}
|
2019-03-22 07:55:46 +00:00
|
|
|
|
2019-11-11 08:41:32 +00:00
|
|
|
def get_queryset_from_cache(self):
|
|
|
|
search_value = self.request.query_params.get('search')
|
|
|
|
users = LDAPCacheUtil().search(search_value=search_value)
|
|
|
|
return users
|
|
|
|
|
|
|
|
def get_queryset_from_server(self):
|
|
|
|
search_value = self.request.query_params.get('search')
|
|
|
|
users = LDAPServerUtil().search(search_value=search_value)
|
|
|
|
return users
|
|
|
|
|
2019-05-29 02:11:58 +00:00
|
|
|
def get_queryset(self):
|
2019-09-18 14:06:46 +00:00
|
|
|
if hasattr(self, 'swagger_fake_view'):
|
2022-02-21 10:51:11 +00:00
|
|
|
return User.objects.none()
|
2019-11-11 08:41:32 +00:00
|
|
|
cache_police = self.request.query_params.get('cache_police', True)
|
|
|
|
if cache_police in LDAP_USE_CACHE_FLAGS:
|
|
|
|
users = self.get_queryset_from_cache()
|
|
|
|
else:
|
|
|
|
users = self.get_queryset_from_server()
|
2019-05-29 02:11:58 +00:00
|
|
|
return users
|
|
|
|
|
2019-11-11 09:45:39 +00:00
|
|
|
@staticmethod
|
|
|
|
def processing_queryset(queryset):
|
|
|
|
db_username_list = User.objects.all().values_list('username', flat=True)
|
|
|
|
for q in queryset:
|
|
|
|
q['id'] = q['username']
|
|
|
|
q['existing'] = q['username'] in db_username_list
|
|
|
|
return queryset
|
|
|
|
|
|
|
|
def sort_queryset(self, queryset):
|
|
|
|
order_by = self.request.query_params.get('order')
|
|
|
|
if not order_by:
|
|
|
|
order_by = 'existing'
|
|
|
|
if order_by.startswith('-'):
|
|
|
|
order_by = order_by.lstrip('-')
|
|
|
|
reverse = True
|
|
|
|
else:
|
|
|
|
reverse = False
|
|
|
|
queryset = sorted(queryset, key=lambda x: x[order_by], reverse=reverse)
|
|
|
|
return queryset
|
|
|
|
|
|
|
|
def filter_queryset(self, queryset):
|
|
|
|
if queryset is None:
|
|
|
|
return queryset
|
|
|
|
queryset = self.processing_queryset(queryset)
|
|
|
|
queryset = self.sort_queryset(queryset)
|
|
|
|
return queryset
|
|
|
|
|
2019-11-11 08:41:32 +00:00
|
|
|
def list(self, request, *args, **kwargs):
|
|
|
|
cache_police = self.request.query_params.get('cache_police', True)
|
|
|
|
# 不是用缓存
|
|
|
|
if cache_police not in LDAP_USE_CACHE_FLAGS:
|
|
|
|
return super().list(request, *args, **kwargs)
|
|
|
|
|
2019-11-11 09:45:39 +00:00
|
|
|
try:
|
|
|
|
queryset = self.get_queryset()
|
|
|
|
except Exception as e:
|
|
|
|
data = {'error': str(e)}
|
|
|
|
return Response(data=data, status=400)
|
|
|
|
|
2019-11-11 08:41:32 +00:00
|
|
|
# 缓存有数据
|
|
|
|
if queryset is not None:
|
|
|
|
return super().list(request, *args, **kwargs)
|
|
|
|
|
|
|
|
sync_util = LDAPSyncUtil()
|
|
|
|
# 还没有同步任务
|
|
|
|
if sync_util.task_no_start:
|
2023-06-22 13:36:19 +00:00
|
|
|
ok, msg = LDAPTestUtil().test_config()
|
|
|
|
if not ok:
|
|
|
|
return Response(data={'msg': msg}, status=400)
|
2019-11-13 07:08:54 +00:00
|
|
|
# 任务外部设置 task running 状态
|
|
|
|
sync_util.set_task_status(sync_util.TASK_STATUS_IS_RUNNING)
|
2020-09-07 12:33:44 +00:00
|
|
|
t = threading.Thread(target=sync_ldap_user)
|
|
|
|
t.start()
|
2021-09-15 11:16:44 +00:00
|
|
|
data = {'msg': _('Synchronization start, please wait.')}
|
2019-11-11 08:41:32 +00:00
|
|
|
return Response(data=data, status=409)
|
|
|
|
# 同步任务正在执行
|
|
|
|
if sync_util.task_is_running:
|
2021-09-15 11:16:44 +00:00
|
|
|
data = {'msg': _('Synchronization is running, please wait.')}
|
2019-11-11 08:41:32 +00:00
|
|
|
return Response(data=data, status=409)
|
|
|
|
# 同步任务执行结束
|
|
|
|
if sync_util.task_is_over:
|
|
|
|
msg = sync_util.get_task_error_msg()
|
2021-09-15 11:16:44 +00:00
|
|
|
data = {'error': _('Synchronization error: {}'.format(msg))}
|
2019-11-11 08:41:32 +00:00
|
|
|
return Response(data=data, status=400)
|
|
|
|
|
|
|
|
return super().list(request, *args, **kwargs)
|
|
|
|
|
2019-03-22 07:55:46 +00:00
|
|
|
|
2019-11-11 08:41:32 +00:00
|
|
|
class LDAPUserImportAPI(APIView):
|
2022-03-10 09:59:05 +00:00
|
|
|
perm_model = Setting
|
|
|
|
rbac_perms = {
|
|
|
|
'POST': 'settings.change_auth'
|
|
|
|
}
|
|
|
|
|
2023-05-25 09:35:36 +00:00
|
|
|
def get_orgs(self):
|
|
|
|
org_ids = self.request.data.get('org_ids')
|
|
|
|
if org_ids:
|
|
|
|
orgs = list(Organization.objects.filter(id__in=org_ids))
|
2021-06-22 11:09:34 +00:00
|
|
|
else:
|
2023-05-25 09:35:36 +00:00
|
|
|
orgs = [current_org]
|
|
|
|
return orgs
|
2021-06-22 11:09:34 +00:00
|
|
|
|
2019-11-11 08:41:32 +00:00
|
|
|
def get_ldap_users(self):
|
|
|
|
username_list = self.request.data.get('username_list', [])
|
|
|
|
cache_police = self.request.query_params.get('cache_police', True)
|
2022-04-01 07:33:14 +00:00
|
|
|
if '*' in username_list:
|
|
|
|
users = LDAPServerUtil().search()
|
|
|
|
elif cache_police in LDAP_USE_CACHE_FLAGS:
|
2019-11-11 08:41:32 +00:00
|
|
|
users = LDAPCacheUtil().search(search_users=username_list)
|
|
|
|
else:
|
|
|
|
users = LDAPServerUtil().search(search_users=username_list)
|
|
|
|
return users
|
|
|
|
|
2019-03-22 07:55:46 +00:00
|
|
|
def post(self, request):
|
2019-11-11 09:45:39 +00:00
|
|
|
try:
|
|
|
|
users = self.get_ldap_users()
|
|
|
|
except Exception as e:
|
2020-05-07 08:57:57 +00:00
|
|
|
return Response({'error': str(e)}, status=400)
|
2019-11-11 09:45:39 +00:00
|
|
|
|
|
|
|
if users is None:
|
2020-05-07 08:57:57 +00:00
|
|
|
return Response({'msg': _('Get ldap users is None')}, status=400)
|
2019-11-11 09:45:39 +00:00
|
|
|
|
2023-05-25 09:35:36 +00:00
|
|
|
orgs = self.get_orgs()
|
|
|
|
errors = LDAPImportUtil().perform_import(users, orgs)
|
2019-11-11 08:41:32 +00:00
|
|
|
if errors:
|
2020-05-07 08:57:57 +00:00
|
|
|
return Response({'errors': errors}, status=400)
|
2019-11-11 09:45:39 +00:00
|
|
|
|
|
|
|
count = users if users is None else len(users)
|
2023-05-25 09:35:36 +00:00
|
|
|
orgs_name = ', '.join([str(org) for org in orgs])
|
2021-06-22 11:09:34 +00:00
|
|
|
return Response({
|
2023-05-25 09:35:36 +00:00
|
|
|
'msg': _('Imported {} users successfully (Organization: {})').format(count, orgs_name)
|
2021-06-22 11:09:34 +00:00
|
|
|
})
|
2019-11-11 08:41:32 +00:00
|
|
|
|
2019-03-28 04:50:04 +00:00
|
|
|
|
2019-11-11 08:41:32 +00:00
|
|
|
class LDAPCacheRefreshAPI(generics.RetrieveAPIView):
|
2022-03-10 09:59:05 +00:00
|
|
|
perm_model = Setting
|
|
|
|
rbac_perms = {
|
|
|
|
'retrieve': 'settings.change_auth'
|
|
|
|
}
|
|
|
|
|
2019-11-11 08:41:32 +00:00
|
|
|
def retrieve(self, request, *args, **kwargs):
|
2019-03-28 04:50:04 +00:00
|
|
|
try:
|
2019-11-11 08:41:32 +00:00
|
|
|
LDAPSyncUtil().clear_cache()
|
2019-03-28 04:50:04 +00:00
|
|
|
except Exception as e:
|
2019-11-11 08:41:32 +00:00
|
|
|
logger.error(str(e))
|
|
|
|
return Response(data={'msg': str(e)}, status=400)
|
|
|
|
return Response(data={'msg': 'success'})
|