mirror of
https://github.com/haiwen/seahub.git
synced 2025-07-31 14:52:38 +00:00
add sysadmin import users api (#4202)
This commit is contained in:
parent
0f95a6bae3
commit
a53dd2ecb0
@ -1,6 +1,10 @@
|
|||||||
# Copyright (c) 2012-2016 Seafile Ltd.
|
# Copyright (c) 2012-2016 Seafile Ltd.
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
from io import BytesIO
|
||||||
|
from openpyxl import load_workbook
|
||||||
|
from constance import config
|
||||||
|
|
||||||
from rest_framework import status
|
from rest_framework import status
|
||||||
from rest_framework.authentication import SessionAuthentication
|
from rest_framework.authentication import SessionAuthentication
|
||||||
from rest_framework.permissions import IsAdminUser
|
from rest_framework.permissions import IsAdminUser
|
||||||
@ -11,6 +15,7 @@ from django.utils.translation import ugettext as _
|
|||||||
|
|
||||||
from seaserv import seafile_api
|
from seaserv import seafile_api
|
||||||
|
|
||||||
|
import seahub.settings as settings
|
||||||
from seahub.api2.authentication import TokenAuthentication
|
from seahub.api2.authentication import TokenAuthentication
|
||||||
from seahub.api2.throttling import UserRateThrottle
|
from seahub.api2.throttling import UserRateThrottle
|
||||||
from seahub.api2.utils import api_error
|
from seahub.api2.utils import api_error
|
||||||
@ -19,14 +24,21 @@ from seahub.base.accounts import User
|
|||||||
from seahub.profile.models import Profile
|
from seahub.profile.models import Profile
|
||||||
from seahub.institutions.models import Institution
|
from seahub.institutions.models import Institution
|
||||||
from seahub.utils.file_size import get_file_size_unit
|
from seahub.utils.file_size import get_file_size_unit
|
||||||
from seahub.utils import is_valid_username
|
from seahub.utils import is_valid_username, get_file_type_and_ext, \
|
||||||
from seahub.admin_log.models import USER_DELETE
|
is_pro_version, get_site_name
|
||||||
|
from seahub.utils.error_msg import file_type_error_msg
|
||||||
|
from seahub.utils.licenseparse import user_number_over_limit
|
||||||
|
from seahub.utils.mail import send_html_email_with_dj_template
|
||||||
|
from seahub.admin_log.models import USER_DELETE, USER_ADD
|
||||||
from seahub.admin_log.signals import admin_operation
|
from seahub.admin_log.signals import admin_operation
|
||||||
from seahub.utils.timeutils import timestamp_to_isoformat_timestr, datetime_to_isoformat_timestr
|
from seahub.utils.timeutils import timestamp_to_isoformat_timestr, datetime_to_isoformat_timestr
|
||||||
from seahub.constants import DEFAULT_ADMIN
|
from seahub.constants import DEFAULT_ADMIN
|
||||||
from seahub.role_permissions.models import AdminRole
|
from seahub.role_permissions.models import AdminRole
|
||||||
from seahub.base.templatetags.seahub_tags import email2nickname, email2contact_email
|
from seahub.base.templatetags.seahub_tags import email2nickname, email2contact_email
|
||||||
from seahub.base.models import UserLastLogin
|
from seahub.base.models import UserLastLogin
|
||||||
|
from seahub.options.models import UserOptions
|
||||||
|
from seahub.role_permissions.utils import get_available_roles
|
||||||
|
from seahub.utils.user_permissions import get_user_role
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -227,3 +239,161 @@ class AdminUsersBatch(APIView):
|
|||||||
})
|
})
|
||||||
|
|
||||||
return Response(result)
|
return Response(result)
|
||||||
|
|
||||||
|
|
||||||
|
class AdminImportUsers(APIView):
|
||||||
|
authentication_classes = (TokenAuthentication, SessionAuthentication)
|
||||||
|
throttle_classes = (UserRateThrottle,)
|
||||||
|
permission_classes = (IsAdminUser,)
|
||||||
|
|
||||||
|
def post(self, request):
|
||||||
|
""" Import users from xlsx file
|
||||||
|
|
||||||
|
Permission checking:
|
||||||
|
1. admin user.
|
||||||
|
"""
|
||||||
|
xlsx_file = request.FILES.get('file', None)
|
||||||
|
if not xlsx_file:
|
||||||
|
error_msg = 'file can not be found.'
|
||||||
|
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
|
||||||
|
|
||||||
|
file_type, ext = get_file_type_and_ext(xlsx_file.name)
|
||||||
|
if ext != 'xlsx':
|
||||||
|
error_msg = file_type_error_msg(ext, 'xlsx')
|
||||||
|
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
|
||||||
|
|
||||||
|
content = xlsx_file.read()
|
||||||
|
|
||||||
|
try:
|
||||||
|
fs = BytesIO(content)
|
||||||
|
wb = load_workbook(filename=fs, read_only=True)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(e)
|
||||||
|
|
||||||
|
# example file is like:
|
||||||
|
# Email Password Name(Optional) Role(Optional) Space Quota(MB, Optional)
|
||||||
|
# a@a.com a a default 1024
|
||||||
|
# b@b.com b b default 2048
|
||||||
|
|
||||||
|
rows = wb.worksheets[0].rows
|
||||||
|
records = []
|
||||||
|
# skip first row(head field).
|
||||||
|
next(rows)
|
||||||
|
for row in rows:
|
||||||
|
records.append([col.value for col in row])
|
||||||
|
|
||||||
|
if user_number_over_limit(new_users=len(records)):
|
||||||
|
error_msg = 'The number of users exceeds the limit.'
|
||||||
|
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
|
||||||
|
|
||||||
|
result = {}
|
||||||
|
result['failed'] = []
|
||||||
|
result['success'] = []
|
||||||
|
for record in records:
|
||||||
|
if record[0]:
|
||||||
|
email = record[0].strip()
|
||||||
|
if not is_valid_username(email):
|
||||||
|
result['failed'].append({
|
||||||
|
'email': email,
|
||||||
|
'error_msg': 'email %s invalid.' % email
|
||||||
|
})
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
result['failed'].append({
|
||||||
|
'email': '',
|
||||||
|
'error_msg': 'email invalid.'
|
||||||
|
})
|
||||||
|
continue
|
||||||
|
|
||||||
|
if record[1]:
|
||||||
|
password = record[1].strip()
|
||||||
|
if not password:
|
||||||
|
result['failed'].append({
|
||||||
|
'email': email,
|
||||||
|
'error_msg': 'password invalid.'
|
||||||
|
})
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
result['failed'].append({
|
||||||
|
'email': email,
|
||||||
|
'error_msg': 'password invalid.'
|
||||||
|
})
|
||||||
|
continue
|
||||||
|
|
||||||
|
try:
|
||||||
|
User.objects.get(email=email)
|
||||||
|
result['failed'].append({
|
||||||
|
'email': email,
|
||||||
|
'error_msg': 'user %s exists.' % email
|
||||||
|
})
|
||||||
|
continue
|
||||||
|
except User.DoesNotExist:
|
||||||
|
pass
|
||||||
|
|
||||||
|
User.objects.create_user(email, password, is_staff=False, is_active=True)
|
||||||
|
if config.FORCE_PASSWORD_CHANGE:
|
||||||
|
UserOptions.objects.set_force_passwd_change(email)
|
||||||
|
|
||||||
|
# update the user's optional info
|
||||||
|
# update nikename
|
||||||
|
if record[2]:
|
||||||
|
try:
|
||||||
|
nickname = record[2].strip()
|
||||||
|
if len(nickname) <= 64 and '/' not in nickname:
|
||||||
|
Profile.objects.add_or_update(email, nickname, '')
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(e)
|
||||||
|
# update role
|
||||||
|
if record[3]:
|
||||||
|
try:
|
||||||
|
role = record[3].strip()
|
||||||
|
if is_pro_version() and role in get_available_roles():
|
||||||
|
User.objects.update_role(email, role)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(e)
|
||||||
|
# update quota
|
||||||
|
if record[4]:
|
||||||
|
try:
|
||||||
|
space_quota_mb = int(record[4])
|
||||||
|
if space_quota_mb >= 0:
|
||||||
|
space_quota = int(space_quota_mb) * get_file_size_unit('MB')
|
||||||
|
seafile_api.set_user_quota(email, space_quota)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(e)
|
||||||
|
|
||||||
|
send_html_email_with_dj_template(
|
||||||
|
email, dj_template='sysadmin/user_batch_add_email.html',
|
||||||
|
subject=_('You are invited to join %s') % get_site_name(),
|
||||||
|
context={
|
||||||
|
'user': email2nickname(request.user.username),
|
||||||
|
'email': email,
|
||||||
|
'password': password,
|
||||||
|
})
|
||||||
|
|
||||||
|
user = User.objects.get(email=email)
|
||||||
|
|
||||||
|
info = {}
|
||||||
|
info['email'] = email
|
||||||
|
info['name'] = email2nickname(email)
|
||||||
|
info['contact_email'] = email2contact_email(email)
|
||||||
|
|
||||||
|
info['is_staff'] = user.is_staff
|
||||||
|
info['is_active'] = user.is_active
|
||||||
|
|
||||||
|
info['quota_usage'] = seafile_api.get_user_self_usage(user.email)
|
||||||
|
info['quota_total'] = seafile_api.get_user_quota(user.email)
|
||||||
|
|
||||||
|
info['create_time'] = timestamp_to_isoformat_timestr(user.ctime)
|
||||||
|
|
||||||
|
info['role'] = get_user_role(user)
|
||||||
|
result['success'].append(info)
|
||||||
|
|
||||||
|
# send admin operation log signal
|
||||||
|
admin_op_detail = {
|
||||||
|
"email": email,
|
||||||
|
}
|
||||||
|
admin_operation.send(sender=None, admin_name=request.user.username,
|
||||||
|
operation=USER_ADD, detail=admin_op_detail)
|
||||||
|
|
||||||
|
return Response(result)
|
||||||
|
|
||||||
|
@ -125,7 +125,8 @@ from seahub.api2.endpoints.admin.share_links import AdminShareLinks, AdminShareL
|
|||||||
AdminShareLinkDirents
|
AdminShareLinkDirents
|
||||||
from seahub.api2.endpoints.admin.upload_links import AdminUploadLinks, AdminUploadLink, \
|
from seahub.api2.endpoints.admin.upload_links import AdminUploadLinks, AdminUploadLink, \
|
||||||
AdminUploadLinkUpload, AdminUploadLinkCheckPassword
|
AdminUploadLinkUpload, AdminUploadLinkCheckPassword
|
||||||
from seahub.api2.endpoints.admin.users_batch import AdminUsersBatch, AdminAdminUsersBatch
|
from seahub.api2.endpoints.admin.users_batch import AdminUsersBatch, AdminAdminUsersBatch, \
|
||||||
|
AdminImportUsers
|
||||||
from seahub.api2.endpoints.admin.operation_logs import AdminOperationLogs
|
from seahub.api2.endpoints.admin.operation_logs import AdminOperationLogs
|
||||||
from seahub.api2.endpoints.admin.organizations import AdminOrganizations, AdminOrganization
|
from seahub.api2.endpoints.admin.organizations import AdminOrganizations, AdminOrganization
|
||||||
from seahub.api2.endpoints.admin.org_users import AdminOrgUsers, AdminOrgUser
|
from seahub.api2.endpoints.admin.org_users import AdminOrgUsers, AdminOrgUser
|
||||||
@ -527,9 +528,10 @@ urlpatterns = [
|
|||||||
url(r'^api/v2.1/admin/upload-links/(?P<token>[a-f0-9]+)/check-password/$',
|
url(r'^api/v2.1/admin/upload-links/(?P<token>[a-f0-9]+)/check-password/$',
|
||||||
AdminUploadLinkCheckPassword.as_view(), name='api-v2.1-admin-upload-link-check-password'),
|
AdminUploadLinkCheckPassword.as_view(), name='api-v2.1-admin-upload-link-check-password'),
|
||||||
|
|
||||||
## admin::users
|
## admin::users-batch
|
||||||
url(r'^api/v2.1/admin/admin-users/batch/$', AdminAdminUsersBatch.as_view(), name='api-v2.1-admin-users-batch'),
|
url(r'^api/v2.1/admin/admin-users/batch/$', AdminAdminUsersBatch.as_view(), name='api-v2.1-admin-users-batch'),
|
||||||
url(r'^api/v2.1/admin/users/batch/$', AdminUsersBatch.as_view(), name='api-v2.1-admin-users-batch'),
|
url(r'^api/v2.1/admin/users/batch/$', AdminUsersBatch.as_view(), name='api-v2.1-admin-users-batch'),
|
||||||
|
url(r'^api/v2.1/admin/import-users/$', AdminImportUsers.as_view(), name='api-v2.1-admin-import-users'),
|
||||||
|
|
||||||
## admin::admin-role
|
## admin::admin-role
|
||||||
url(r'^api/v2.1/admin/admin-role/$', AdminAdminRole.as_view(), name='api-v2.1-admin-admin-role'),
|
url(r'^api/v2.1/admin/admin-role/$', AdminAdminRole.as_view(), name='api-v2.1-admin-admin-role'),
|
||||||
|
Loading…
Reference in New Issue
Block a user