1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-07-30 22:34:53 +00:00

add sysadmin import users api (#4202)

This commit is contained in:
Leo 2019-10-28 17:49:24 +08:00 committed by Daniel Pan
parent 0f95a6bae3
commit a53dd2ecb0
2 changed files with 176 additions and 4 deletions

View File

@ -1,6 +1,10 @@
# Copyright (c) 2012-2016 Seafile Ltd.
import logging
from io import BytesIO
from openpyxl import load_workbook
from constance import config
from rest_framework import status
from rest_framework.authentication import SessionAuthentication
from rest_framework.permissions import IsAdminUser
@ -11,6 +15,7 @@ from django.utils.translation import ugettext as _
from seaserv import seafile_api
import seahub.settings as settings
from seahub.api2.authentication import TokenAuthentication
from seahub.api2.throttling import UserRateThrottle
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.institutions.models import Institution
from seahub.utils.file_size import get_file_size_unit
from seahub.utils import is_valid_username
from seahub.admin_log.models import USER_DELETE
from seahub.utils import is_valid_username, get_file_type_and_ext, \
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.utils.timeutils import timestamp_to_isoformat_timestr, datetime_to_isoformat_timestr
from seahub.constants import DEFAULT_ADMIN
from seahub.role_permissions.models import AdminRole
from seahub.base.templatetags.seahub_tags import email2nickname, email2contact_email
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__)
@ -227,3 +239,161 @@ class AdminUsersBatch(APIView):
})
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)

View File

@ -125,7 +125,8 @@ from seahub.api2.endpoints.admin.share_links import AdminShareLinks, AdminShareL
AdminShareLinkDirents
from seahub.api2.endpoints.admin.upload_links import AdminUploadLinks, AdminUploadLink, \
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.organizations import AdminOrganizations, AdminOrganization
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/$',
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/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
url(r'^api/v2.1/admin/admin-role/$', AdminAdminRole.as_view(), name='api-v2.1-admin-admin-role'),