mirror of
https://github.com/haiwen/seahub.git
synced 2025-08-27 19:20:53 +00:00
commit
9a9b6eb9e1
@ -3,6 +3,7 @@ import logging
|
|||||||
from dateutil.relativedelta import relativedelta
|
from dateutil.relativedelta import relativedelta
|
||||||
|
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
from django.utils.translation import ugettext as _
|
||||||
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,22 +12,37 @@ from rest_framework.reverse import reverse
|
|||||||
from rest_framework.views import APIView
|
from rest_framework.views import APIView
|
||||||
import seaserv
|
import seaserv
|
||||||
from seaserv import seafile_api, ccnet_threaded_rpc
|
from seaserv import seafile_api, ccnet_threaded_rpc
|
||||||
from pysearpc import SearpcError
|
|
||||||
|
|
||||||
from seahub.api2.authentication import TokenAuthentication
|
from seahub.api2.authentication import TokenAuthentication
|
||||||
from seahub.api2.serializers import AccountSerializer
|
from seahub.api2.serializers import AccountSerializer
|
||||||
from seahub.api2.throttling import UserRateThrottle
|
from seahub.api2.throttling import UserRateThrottle
|
||||||
from seahub.api2.utils import api_error, to_python_boolean
|
from seahub.api2.utils import api_error, to_python_boolean
|
||||||
from seahub.api2.status import HTTP_520_OPERATION_FAILED
|
|
||||||
from seahub.base.accounts import User
|
from seahub.base.accounts import User
|
||||||
from seahub.profile.models import Profile
|
from seahub.base.templatetags.seahub_tags import email2nickname
|
||||||
from seahub.profile.utils import refresh_cache as refresh_profile_cache
|
from seahub.profile.models import Profile, DetailedProfile
|
||||||
from seahub.utils import is_valid_username
|
from seahub.utils import is_valid_username, is_org_context
|
||||||
|
from seahub.utils.file_size import get_file_size_unit
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
json_content_type = 'application/json; charset=utf-8'
|
json_content_type = 'application/json; charset=utf-8'
|
||||||
|
|
||||||
|
def get_account_info(user):
|
||||||
|
email = user.username
|
||||||
|
d_profile = DetailedProfile.objects.get_detailed_profile_by_user(email)
|
||||||
|
|
||||||
|
info = {}
|
||||||
|
info['email'] = email
|
||||||
|
info['name'] = email2nickname(email)
|
||||||
|
info['department'] = d_profile.department if d_profile else ''
|
||||||
|
info['id'] = user.id
|
||||||
|
info['is_staff'] = user.is_staff
|
||||||
|
info['is_active'] = user.is_active
|
||||||
|
info['create_time'] = user.ctime
|
||||||
|
info['total'] = seafile_api.get_user_quota(email)
|
||||||
|
info['usage'] = seafile_api.get_user_self_usage(email)
|
||||||
|
|
||||||
|
return info
|
||||||
|
|
||||||
class Account(APIView):
|
class Account(APIView):
|
||||||
"""Query/Add/Delete a specific account.
|
"""Query/Add/Delete a specific account.
|
||||||
@ -46,136 +62,9 @@ class Account(APIView):
|
|||||||
except User.DoesNotExist:
|
except User.DoesNotExist:
|
||||||
return api_error(status.HTTP_404_NOT_FOUND, 'User %s not found.' % email)
|
return api_error(status.HTTP_404_NOT_FOUND, 'User %s not found.' % email)
|
||||||
|
|
||||||
info = {}
|
info = get_account_info(user)
|
||||||
info['email'] = user.email
|
|
||||||
info['id'] = user.id
|
|
||||||
info['is_staff'] = user.is_staff
|
|
||||||
info['is_active'] = user.is_active
|
|
||||||
info['create_time'] = user.ctime
|
|
||||||
info['total'] = seafile_api.get_user_quota(email)
|
|
||||||
info['usage'] = seafile_api.get_user_self_usage(email)
|
|
||||||
|
|
||||||
return Response(info)
|
return Response(info)
|
||||||
|
|
||||||
def _update_account_profile(self, request, email):
|
|
||||||
name = request.data.get("name", None)
|
|
||||||
note = request.data.get("note", None)
|
|
||||||
|
|
||||||
if name is None and note is None:
|
|
||||||
return
|
|
||||||
|
|
||||||
profile = Profile.objects.get_profile_by_user(email)
|
|
||||||
if profile is None:
|
|
||||||
profile = Profile(user=email)
|
|
||||||
|
|
||||||
if name is not None:
|
|
||||||
# if '/' in name:
|
|
||||||
# return api_error(status.HTTP_400_BAD_REQUEST, "Nickname should not include '/'")
|
|
||||||
profile.nickname = name
|
|
||||||
|
|
||||||
if note is not None:
|
|
||||||
profile.intro = note
|
|
||||||
|
|
||||||
profile.save()
|
|
||||||
|
|
||||||
def _update_account_quota(self, request, email):
|
|
||||||
storage = request.data.get("storage", None)
|
|
||||||
sharing = request.data.get("sharing", None)
|
|
||||||
|
|
||||||
if storage is None and sharing is None:
|
|
||||||
return
|
|
||||||
|
|
||||||
if storage is not None:
|
|
||||||
seafile_api.set_user_quota(email, int(storage))
|
|
||||||
|
|
||||||
# if sharing is not None:
|
|
||||||
# seafile_api.set_user_share_quota(email, int(sharing))
|
|
||||||
|
|
||||||
def _create_account(self, request, email):
|
|
||||||
copy = request.data.copy()
|
|
||||||
copy['email'] = email
|
|
||||||
serializer = AccountSerializer(data=copy)
|
|
||||||
if serializer.is_valid():
|
|
||||||
try:
|
|
||||||
user = User.objects.create_user(serializer.data['email'],
|
|
||||||
serializer.data['password'],
|
|
||||||
serializer.data['is_staff'],
|
|
||||||
serializer.data['is_active'])
|
|
||||||
except User.DoesNotExist as e:
|
|
||||||
logger.error(e)
|
|
||||||
return api_error(status.HTTP_520_OPERATION_FAILED,
|
|
||||||
'Failed to add user.')
|
|
||||||
|
|
||||||
self._update_account_profile(request, user.username)
|
|
||||||
|
|
||||||
resp = Response('success', status=status.HTTP_201_CREATED)
|
|
||||||
resp['Location'] = reverse('api2-account', args=[email])
|
|
||||||
return resp
|
|
||||||
else:
|
|
||||||
return api_error(status.HTTP_400_BAD_REQUEST, serializer.errors)
|
|
||||||
|
|
||||||
def _update_account(self, request, user):
|
|
||||||
password = request.data.get("password", None)
|
|
||||||
is_staff = request.data.get("is_staff", None)
|
|
||||||
if is_staff is not None:
|
|
||||||
try:
|
|
||||||
is_staff = to_python_boolean(is_staff)
|
|
||||||
except ValueError:
|
|
||||||
return api_error(status.HTTP_400_BAD_REQUEST,
|
|
||||||
'is_staff invalid.')
|
|
||||||
|
|
||||||
is_active = request.data.get("is_active", None)
|
|
||||||
if is_active is not None:
|
|
||||||
try:
|
|
||||||
is_active = to_python_boolean(is_active)
|
|
||||||
except ValueError:
|
|
||||||
return api_error(status.HTTP_400_BAD_REQUEST,
|
|
||||||
'is_active invalid.')
|
|
||||||
|
|
||||||
if password is not None:
|
|
||||||
user.set_password(password)
|
|
||||||
|
|
||||||
if is_staff is not None:
|
|
||||||
user.is_staff = is_staff
|
|
||||||
|
|
||||||
if is_active is not None:
|
|
||||||
user.is_active = is_active
|
|
||||||
|
|
||||||
result_code = user.save()
|
|
||||||
if result_code == -1:
|
|
||||||
return api_error(status.HTTP_520_OPERATION_FAILED,
|
|
||||||
'Failed to update user.')
|
|
||||||
|
|
||||||
self._update_account_profile(request, user.username)
|
|
||||||
|
|
||||||
try:
|
|
||||||
self._update_account_quota(request, user.username)
|
|
||||||
except SearpcError as e:
|
|
||||||
logger.error(e)
|
|
||||||
return api_error(HTTP_520_OPERATION_FAILED, 'Failed to set user quota.')
|
|
||||||
|
|
||||||
is_trial = request.data.get("is_trial", None)
|
|
||||||
if is_trial is not None:
|
|
||||||
try:
|
|
||||||
from seahub_extra.trialaccount.models import TrialAccount
|
|
||||||
except ImportError:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
is_trial = to_python_boolean(is_trial)
|
|
||||||
except ValueError:
|
|
||||||
return api_error(status.HTTP_400_BAD_REQUEST,
|
|
||||||
'is_trial invalid')
|
|
||||||
|
|
||||||
if is_trial is True:
|
|
||||||
expire_date = timezone.now() + relativedelta(days=7)
|
|
||||||
TrialAccount.object.create_or_update(user.username,
|
|
||||||
expire_date)
|
|
||||||
else:
|
|
||||||
TrialAccount.objects.filter(user_or_org=user.username).delete()
|
|
||||||
|
|
||||||
return Response('success')
|
|
||||||
|
|
||||||
def post(self, request, email, format=None):
|
def post(self, request, email, format=None):
|
||||||
# migrate an account's repos and groups to an exist account
|
# migrate an account's repos and groups to an exist account
|
||||||
if not is_valid_username(email):
|
if not is_valid_username(email):
|
||||||
@ -207,19 +96,208 @@ class Account(APIView):
|
|||||||
if from_user == g.creator_name:
|
if from_user == g.creator_name:
|
||||||
ccnet_threaded_rpc.set_group_creator(g.id, to_user)
|
ccnet_threaded_rpc.set_group_creator(g.id, to_user)
|
||||||
|
|
||||||
return Response("success")
|
return Response({'success': True})
|
||||||
else:
|
else:
|
||||||
return api_error(status.HTTP_400_BAD_REQUEST, 'op can only be migrate.')
|
return api_error(status.HTTP_400_BAD_REQUEST, 'op can only be migrate.')
|
||||||
|
|
||||||
|
def _update_account_additional_info(self, request, email):
|
||||||
|
|
||||||
|
# update account profile
|
||||||
|
name = request.data.get("name", None)
|
||||||
|
note = request.data.get("note", None)
|
||||||
|
if name is not None or note is not None:
|
||||||
|
profile = Profile.objects.get_profile_by_user(email)
|
||||||
|
if profile is None:
|
||||||
|
profile = Profile(user=email)
|
||||||
|
|
||||||
|
if name is not None:
|
||||||
|
profile.nickname = name
|
||||||
|
|
||||||
|
if note is not None:
|
||||||
|
profile.intro = note
|
||||||
|
|
||||||
|
profile.save()
|
||||||
|
|
||||||
|
# update account detailed profile
|
||||||
|
department = request.data.get("department", None)
|
||||||
|
if department is not None:
|
||||||
|
d_profile = DetailedProfile.objects.get_detailed_profile_by_user(email)
|
||||||
|
if d_profile is None:
|
||||||
|
d_profile = DetailedProfile(user=email)
|
||||||
|
|
||||||
|
d_profile.department = department
|
||||||
|
d_profile.save()
|
||||||
|
|
||||||
|
# update user quota
|
||||||
|
space_quota_mb = request.data.get("storage", None)
|
||||||
|
if space_quota_mb is not None:
|
||||||
|
space_quota = int(space_quota_mb) * get_file_size_unit('MB')
|
||||||
|
if is_org_context(request):
|
||||||
|
org_id = request.user.org.org_id
|
||||||
|
seaserv.seafserv_threaded_rpc.set_org_user_quota(org_id,
|
||||||
|
email, space_quota)
|
||||||
|
else:
|
||||||
|
seafile_api.set_user_quota(email, space_quota)
|
||||||
|
|
||||||
|
# update is_trial
|
||||||
|
is_trial = request.data.get("is_trial", None)
|
||||||
|
if is_trial is not None:
|
||||||
|
try:
|
||||||
|
from seahub_extra.trialaccount.models import TrialAccount
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
if is_trial is True:
|
||||||
|
expire_date = timezone.now() + relativedelta(days=7)
|
||||||
|
TrialAccount.object.create_or_update(email, expire_date)
|
||||||
|
else:
|
||||||
|
TrialAccount.objects.filter(user_or_org=email).delete()
|
||||||
|
|
||||||
def put(self, request, email, format=None):
|
def put(self, request, email, format=None):
|
||||||
|
|
||||||
|
# argument check for email
|
||||||
if not is_valid_username(email):
|
if not is_valid_username(email):
|
||||||
return api_error(status.HTTP_400_BAD_REQUEST, 'Email %s invalid.' % email)
|
return api_error(status.HTTP_400_BAD_REQUEST,
|
||||||
|
'Email %s invalid.' % email)
|
||||||
|
|
||||||
|
# argument check for name
|
||||||
|
name = request.data.get("name", None)
|
||||||
|
if name is not None:
|
||||||
|
if len(name) > 64:
|
||||||
|
return api_error(status.HTTP_400_BAD_REQUEST,
|
||||||
|
_(u'Name is too long (maximum is 64 characters)'))
|
||||||
|
|
||||||
|
if "/" in name:
|
||||||
|
return api_error(status.HTTP_400_BAD_REQUEST,
|
||||||
|
_(u"Name should not include ' / '"))
|
||||||
|
|
||||||
|
# argument check for note
|
||||||
|
note = request.data.get("note", None)
|
||||||
|
if note is not None:
|
||||||
|
if len(note) > 256:
|
||||||
|
return api_error(status.HTTP_400_BAD_REQUEST,
|
||||||
|
_(u'Note is too long (maximum is 256 characters)'))
|
||||||
|
|
||||||
|
# argument check for department
|
||||||
|
department = request.data.get("department", None)
|
||||||
|
if department is not None:
|
||||||
|
if len(department) > 512:
|
||||||
|
return api_error(status.HTTP_400_BAD_REQUEST,
|
||||||
|
_(u'Department is too long (maximum is 512 characters)'))
|
||||||
|
|
||||||
|
# argument check for storage
|
||||||
|
space_quota_mb = request.data.get("storage", None)
|
||||||
|
if space_quota_mb is not None:
|
||||||
|
if space_quota_mb == '':
|
||||||
|
return api_error(status.HTTP_400_BAD_REQUEST,
|
||||||
|
_('Space quota can\'t be empty'))
|
||||||
|
|
||||||
|
try:
|
||||||
|
space_quota_mb = int(space_quota_mb)
|
||||||
|
except ValueError:
|
||||||
|
return api_error(status.HTTP_400_BAD_REQUEST,
|
||||||
|
'storage invalid.')
|
||||||
|
|
||||||
|
if space_quota_mb < 0:
|
||||||
|
return api_error(status.HTTP_400_BAD_REQUEST,
|
||||||
|
_('Space quota is too low (minimum value is 0)'))
|
||||||
|
|
||||||
|
if is_org_context(request):
|
||||||
|
org_id = request.user.org.org_id
|
||||||
|
org_quota_mb = seaserv.seafserv_threaded_rpc.get_org_quota(org_id) / \
|
||||||
|
get_file_size_unit('MB')
|
||||||
|
if space_quota_mb > org_quota_mb:
|
||||||
|
return api_error(status.HTTP_400_BAD_REQUEST, \
|
||||||
|
_(u'Failed to set quota: maximum quota is %d MB' % org_quota_mb))
|
||||||
|
|
||||||
|
# argument check for is_trial
|
||||||
|
is_trial = request.data.get("is_trial", None)
|
||||||
|
if is_trial is not None:
|
||||||
|
try:
|
||||||
|
is_trial = to_python_boolean(is_trial)
|
||||||
|
except ValueError:
|
||||||
|
return api_error(status.HTTP_400_BAD_REQUEST,
|
||||||
|
'is_trial invalid')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
# update account basic info
|
||||||
user = User.objects.get(email=email)
|
user = User.objects.get(email=email)
|
||||||
return self._update_account(request, user)
|
# argument check for is_staff
|
||||||
|
is_staff = request.data.get("is_staff", None)
|
||||||
|
if is_staff is not None:
|
||||||
|
try:
|
||||||
|
is_staff = to_python_boolean(is_staff)
|
||||||
|
except ValueError:
|
||||||
|
return api_error(status.HTTP_400_BAD_REQUEST,
|
||||||
|
'is_staff invalid.')
|
||||||
|
|
||||||
|
user.is_staff = is_staff
|
||||||
|
|
||||||
|
# argument check for is_active
|
||||||
|
is_active = request.data.get("is_active", None)
|
||||||
|
if is_active is not None:
|
||||||
|
try:
|
||||||
|
is_active = to_python_boolean(is_active)
|
||||||
|
except ValueError:
|
||||||
|
return api_error(status.HTTP_400_BAD_REQUEST,
|
||||||
|
'is_active invalid.')
|
||||||
|
|
||||||
|
user.is_active = is_active
|
||||||
|
|
||||||
|
# update password
|
||||||
|
password = request.data.get("password", None)
|
||||||
|
if password is not None:
|
||||||
|
user.set_password(password)
|
||||||
|
|
||||||
|
# save user
|
||||||
|
result_code = user.save()
|
||||||
|
if result_code == -1:
|
||||||
|
return api_error(status.HTTP_520_OPERATION_FAILED,
|
||||||
|
'Failed to update user.')
|
||||||
|
|
||||||
|
try:
|
||||||
|
# update account additional info
|
||||||
|
self._update_account_additional_info(request, email)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(e)
|
||||||
|
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||||
|
'Internal Server Error')
|
||||||
|
|
||||||
|
# get account info and return
|
||||||
|
info = get_account_info(user)
|
||||||
|
return Response(info)
|
||||||
|
|
||||||
except User.DoesNotExist:
|
except User.DoesNotExist:
|
||||||
return self._create_account(request, email)
|
# create user account
|
||||||
|
copy = request.data.copy()
|
||||||
|
copy['email'] = email
|
||||||
|
serializer = AccountSerializer(data=copy)
|
||||||
|
if not serializer.is_valid():
|
||||||
|
return api_error(status.HTTP_400_BAD_REQUEST, serializer.errors)
|
||||||
|
|
||||||
|
try:
|
||||||
|
user = User.objects.create_user(serializer.data['email'],
|
||||||
|
serializer.data['password'],
|
||||||
|
serializer.data['is_staff'],
|
||||||
|
serializer.data['is_active'])
|
||||||
|
except User.DoesNotExist as e:
|
||||||
|
logger.error(e)
|
||||||
|
return api_error(status.HTTP_520_OPERATION_FAILED,
|
||||||
|
'Failed to add user.')
|
||||||
|
|
||||||
|
try:
|
||||||
|
# update account additional info
|
||||||
|
self._update_account_additional_info(request, email)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(e)
|
||||||
|
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||||
|
'Internal Server Error')
|
||||||
|
|
||||||
|
# get account info and return
|
||||||
|
info = get_account_info(user)
|
||||||
|
resp = Response(info, status=status.HTTP_201_CREATED)
|
||||||
|
resp['Location'] = reverse('api2-account', args=[email])
|
||||||
|
return resp
|
||||||
|
|
||||||
def delete(self, request, email, format=None):
|
def delete(self, request, email, format=None):
|
||||||
if not is_valid_username(email):
|
if not is_valid_username(email):
|
||||||
@ -229,7 +307,7 @@ class Account(APIView):
|
|||||||
try:
|
try:
|
||||||
user = User.objects.get(email=email)
|
user = User.objects.get(email=email)
|
||||||
user.delete()
|
user.delete()
|
||||||
return Response("success")
|
return Response({'success': True})
|
||||||
except User.DoesNotExist:
|
except User.DoesNotExist:
|
||||||
resp = Response("success", status=status.HTTP_202_ACCEPTED)
|
resp = Response({'success': True}, status=status.HTTP_202_ACCEPTED)
|
||||||
return resp
|
return resp
|
||||||
|
@ -16,6 +16,9 @@ class AddUserForm(forms.Form):
|
|||||||
Form for adding a user.
|
Form for adding a user.
|
||||||
"""
|
"""
|
||||||
email = forms.EmailField()
|
email = forms.EmailField()
|
||||||
|
name = forms.CharField(max_length=64, required=False)
|
||||||
|
department = forms.CharField(max_length=512, required=False)
|
||||||
|
|
||||||
role = forms.ChoiceField(choices=[(DEFAULT_USER, DEFAULT_USER),
|
role = forms.ChoiceField(choices=[(DEFAULT_USER, DEFAULT_USER),
|
||||||
(GUEST_USER, GUEST_USER)])
|
(GUEST_USER, GUEST_USER)])
|
||||||
password1 = forms.CharField(widget=forms.PasswordInput())
|
password1 = forms.CharField(widget=forms.PasswordInput())
|
||||||
@ -32,6 +35,16 @@ class AddUserForm(forms.Form):
|
|||||||
except User.DoesNotExist:
|
except User.DoesNotExist:
|
||||||
return self.cleaned_data['email']
|
return self.cleaned_data['email']
|
||||||
|
|
||||||
|
def clean_name(self):
|
||||||
|
"""
|
||||||
|
should not include '/'
|
||||||
|
"""
|
||||||
|
if "/" in self.cleaned_data["name"]:
|
||||||
|
raise forms.ValidationError(_(u"Name should not include ' / '"))
|
||||||
|
|
||||||
|
return self.cleaned_data["name"]
|
||||||
|
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
"""
|
"""
|
||||||
Verifiy that the values entered into the two password fields
|
Verifiy that the values entered into the two password fields
|
||||||
@ -137,7 +150,6 @@ class SetUserQuotaForm(forms.Form):
|
|||||||
"""
|
"""
|
||||||
Form for setting user quota.
|
Form for setting user quota.
|
||||||
"""
|
"""
|
||||||
email = forms.CharField(error_messages={'required': _('Email is required')})
|
|
||||||
space_quota = forms.IntegerField(min_value=0,
|
space_quota = forms.IntegerField(min_value=0,
|
||||||
error_messages={'required': _('Space quota can\'t be empty'),
|
error_messages={'required': _('Space quota can\'t be empty'),
|
||||||
'min_value': _('Space quota is too low (minimum value is 0)')})
|
'min_value': _('Space quota is too low (minimum value is 0)')})
|
||||||
|
@ -26,9 +26,9 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<th width="36%">{% trans "Email" %}</th>
|
<th width="36%">{% trans "Email" %}</th>
|
||||||
<th width="12%">{% trans "Status" %}</th>
|
<th width="12%">{% trans "Status" %}</th>
|
||||||
<th width="16%">{% trans "Space Used" %}</th>
|
<th width="18%">{% trans "Space Used / Quota" %}</th>
|
||||||
<th width="18%">{% trans "Last Login" %}</th>
|
<th width="18%">{% trans "Last Login" %}</th>
|
||||||
<th width="18%">{% trans "Operations" %}</th>
|
<th width="16%">{% trans "Operations" %}</th>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
{% for user in users %}
|
{% for user in users %}
|
||||||
@ -53,7 +53,15 @@
|
|||||||
</select>
|
</select>
|
||||||
</td>
|
</td>
|
||||||
<td style="font-size:11px;">
|
<td style="font-size:11px;">
|
||||||
<p> {{ user.space_usage|seahub_filesizeformat }} {% if user.space_quota > 0 %} / {{ user.space_quota|seahub_filesizeformat }} {% endif %} </p>
|
{{ user.space_usage|seahub_filesizeformat }} /
|
||||||
|
<span class="user-space-quota">
|
||||||
|
{% if user.space_quota > 0 %}
|
||||||
|
{{ user.space_quota|seahub_filesizeformat }}
|
||||||
|
{% else %}
|
||||||
|
--
|
||||||
|
{% endif %}
|
||||||
|
</span>
|
||||||
|
<span title="{% trans "Edit Quota" %}" class="quota-edit-icon sf2-icon-edit op-icon vh"></span>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{% if user.last_login %}{{user.last_login|translate_seahub_time}} {% else %} -- {% endif %}
|
{% if user.last_login %}{{user.last_login|translate_seahub_time}} {% else %} -- {% endif %}
|
||||||
@ -67,6 +75,13 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
</table>
|
</table>
|
||||||
{% include "snippets/admin_paginator.html" %}
|
{% include "snippets/admin_paginator.html" %}
|
||||||
|
<form id="set-quota-form" method="post" action="" class="hide">{% csrf_token %}
|
||||||
|
<h3>{% trans "Set user storage limit" %}</h3>
|
||||||
|
<input type="text" name="space_quota" /> MB
|
||||||
|
<p class="tip">{% trans "Tip: 0 means default limit" %}</p>
|
||||||
|
<p class="error hide"></p>
|
||||||
|
<input type="submit" value="{% trans "Submit" %}" class="submit" />
|
||||||
|
</form>
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="empty-tips">
|
<div class="empty-tips">
|
||||||
<h2 class="alc">{% trans "No LDAP users have been imported" %}</h2>
|
<h2 class="alc">{% trans "No LDAP users have been imported" %}</h2>
|
||||||
|
@ -32,6 +32,12 @@
|
|||||||
<h3>{% trans "Add user" %}</h3>
|
<h3>{% trans "Add user" %}</h3>
|
||||||
<label for="id_email">{% trans "Email" %}</label><br />
|
<label for="id_email">{% trans "Email" %}</label><br />
|
||||||
<input type="text" name="email" id="id_email" class="input" /><br />
|
<input type="text" name="email" id="id_email" class="input" /><br />
|
||||||
|
|
||||||
|
<label for="id_name">{% trans "Name(optional)" %}</label><br />
|
||||||
|
<input type="text" name="name" id="id_name" class="input" /><br />
|
||||||
|
<label for="id_dept">{% trans "Department(optional)" %}</label><br />
|
||||||
|
<input type="text" name="department" id="id_dept" class="input" /><br />
|
||||||
|
|
||||||
{% if is_pro %}
|
{% if is_pro %}
|
||||||
<label>{% trans "Role"%}</label><span class="icon-question-sign" title="{% trans "You can also add a user as a guest, who will not be allowed to create libraries and groups." %}" style="color:#666; margin-left:3px;"></span>
|
<label>{% trans "Role"%}</label><span class="icon-question-sign" title="{% trans "You can also add a user as a guest, who will not be allowed to create libraries and groups." %}" style="color:#666; margin-left:3px;"></span>
|
||||||
<select name="role" class="w100">
|
<select name="role" class="w100">
|
||||||
@ -54,7 +60,10 @@
|
|||||||
<form id="upload-csv-form" class="hide" enctype="multipart/form-data" method="post" action="{% url 'batch_add_user' %}">{% csrf_token %}
|
<form id="upload-csv-form" class="hide" enctype="multipart/form-data" method="post" action="{% url 'batch_add_user' %}">{% csrf_token %}
|
||||||
<h3>{% trans "Import users from a CSV file" %}</h3>
|
<h3>{% trans "Import users from a CSV file" %}</h3>
|
||||||
<input type="file" name="file" />
|
<input type="file" name="file" />
|
||||||
<p class="tip">{% trans "File format: user@mail.com,password"%}</p>
|
<p class="tip">
|
||||||
|
{% trans "File format: user@mail.com,password,name,department"%}<br />
|
||||||
|
{% trans "Name and department are optional." %}
|
||||||
|
</p>
|
||||||
<p class="error hide">{% trans "Please choose a CSV file" %}</p>
|
<p class="error hide">{% trans "Please choose a CSV file" %}</p>
|
||||||
<button type="submit" class="submit">{% trans "Submit" %}</button>
|
<button type="submit" class="submit">{% trans "Submit" %}</button>
|
||||||
</form>
|
</form>
|
||||||
@ -143,6 +152,8 @@ $('#add-user-form').submit(function() {
|
|||||||
var form = $(this),
|
var form = $(this),
|
||||||
form_id = $(this).attr('id'),
|
form_id = $(this).attr('id'),
|
||||||
email = $.trim(form.children('[name="email"]').val()),
|
email = $.trim(form.children('[name="email"]').val()),
|
||||||
|
name = $.trim($('[name="name"]', form).val()),
|
||||||
|
department = $.trim($('[name="department"]', form).val()),
|
||||||
{% if is_pro %}
|
{% if is_pro %}
|
||||||
role = $('select[name="role"]', form).val(),
|
role = $('select[name="role"]', form).val(),
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@ -176,6 +187,8 @@ $('#add-user-form').submit(function() {
|
|||||||
beforeSend: prepareCSRFToken,
|
beforeSend: prepareCSRFToken,
|
||||||
data: {
|
data: {
|
||||||
'email': email,
|
'email': email,
|
||||||
|
'name': name,
|
||||||
|
'department': department,
|
||||||
{% if is_pro %}
|
{% if is_pro %}
|
||||||
'role': role,
|
'role': role,
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@ -22,18 +22,22 @@
|
|||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<th width="40%">{% trans "Email" %}</th>
|
<th width="40%">{% trans "Email" %}</th>
|
||||||
|
<th width="25%">{% trans "Space Used / Quota" %}</th>
|
||||||
<th width="35%">{% trans "Create At / Last Login" %}</th>
|
<th width="35%">{% trans "Create At / Last Login" %}</th>
|
||||||
<th width="25%">{% trans "Space Used" %}</th>
|
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
{% for user in users %}
|
{% for user in users %}
|
||||||
<tr>
|
<tr>
|
||||||
<td data="{{user.id}}"><a href="{{ SITE_ROOT }}useradmin/info/{{ user.props.email }}/">{{ user.email }}</a></td>
|
<td data="{{user.id}}"><a href="{{ SITE_ROOT }}useradmin/info/{{ user.props.email }}/">{{ user.email }}</a></td>
|
||||||
<td style="font-size:11px;"> -- / {% if user.last_login %}{{user.last_login|translate_seahub_time}} {% else %} -- {% endif %}
|
|
||||||
</td>
|
|
||||||
<td style="font-size:11px;">
|
<td style="font-size:11px;">
|
||||||
<p> {{ user.space_usage|seahub_filesizeformat }} {% if user.space_quota > 0 %} / {{ user.space_quota|seahub_filesizeformat }} {% endif %} </p>
|
{{ user.space_usage|seahub_filesizeformat }} /
|
||||||
|
{% if user.space_quota > 0 %}
|
||||||
|
{{ user.space_quota|seahub_filesizeformat }}
|
||||||
|
{% else %}
|
||||||
|
--
|
||||||
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
|
<td> -- / {% if user.last_login %}{{user.last_login|translate_seahub_time}} {% else %} -- {% endif %}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</table>
|
</table>
|
||||||
|
@ -80,6 +80,60 @@ $('.user-status-select, .user-role-select').change(function() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
{% if user.source == "DB" or user.source == 'LDAPImport' %}
|
||||||
|
// edit quota
|
||||||
|
$('.quota-edit-icon').click(function() {
|
||||||
|
var email = $(this).closest('tr').attr('data-userid');
|
||||||
|
var $spaceQuota = $(this).prev('.user-space-quota');
|
||||||
|
$('#set-quota-form').data({'email': email, '$spaceQuota': $spaceQuota}).modal();
|
||||||
|
$('#simplemodal-container').css({'width':'auto', 'height':'auto'});
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#set-quota-form').submit(function() {
|
||||||
|
var space_quota = $.trim($('[name="space_quota"]', $(this)).val());
|
||||||
|
var $error = $('.error', $(this));
|
||||||
|
if (!space_quota) {
|
||||||
|
$error.html("{% trans "It is required." %}").show();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var $submitBtn = $('[type="submit"]', $(this));
|
||||||
|
disable($submitBtn);
|
||||||
|
|
||||||
|
var email = $(this).data('email');
|
||||||
|
var $spaceQuota = $(this).data('$spaceQuota');
|
||||||
|
$.ajax({
|
||||||
|
url: '{{ SITE_ROOT }}api2/accounts/' + encodeURIComponent(email) + '/',
|
||||||
|
type: 'PUT',
|
||||||
|
dataType: 'json',
|
||||||
|
cache: false,
|
||||||
|
beforeSend: prepareCSRFToken,
|
||||||
|
data: {'storage': space_quota},
|
||||||
|
success: function(data) {
|
||||||
|
if (space_quota == 0) {
|
||||||
|
$spaceQuota.html('--');
|
||||||
|
} else {
|
||||||
|
$spaceQuota.html(parseInt(data['total'])/1000000 + ' MB');
|
||||||
|
}
|
||||||
|
$.modal.close();
|
||||||
|
},
|
||||||
|
error: function(xhr, textStatus, errorThrown) {
|
||||||
|
var err_msg;
|
||||||
|
if (xhr.responseText) {
|
||||||
|
err_msg = $.parseJSON(xhr.responseText).error_msg;
|
||||||
|
} else {
|
||||||
|
err_msg = "{% trans "Failed. Please check the network." %}";
|
||||||
|
}
|
||||||
|
$error.html(err_msg).show();
|
||||||
|
enable($submitBtn);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
// select shows, but the user doesn't select a value, or doesn't change the permission, click other place to hide the select
|
// select shows, but the user doesn't select a value, or doesn't change the permission, click other place to hide the select
|
||||||
$(document).click(function(e) {
|
$(document).click(function(e) {
|
||||||
var target = e.target || event.srcElement;
|
var target = e.target || event.srcElement;
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
<th width="36%">{% trans "Email" %} / {% trans "Name" %} / {% trans "Contact Email" %}</th>
|
<th width="36%">{% trans "Email" %} / {% trans "Name" %} / {% trans "Contact Email" %}</th>
|
||||||
<th width="12%">{% trans "Status" %}</th>
|
<th width="12%">{% trans "Status" %}</th>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<th width="16%">{% trans "Space Used" %}</th>
|
<th width="16%">{% trans "Space Used / Quota" %}</th>
|
||||||
<th width="22%">{% trans "Create At / Last Login" %}</th>
|
<th width="22%">{% trans "Create At / Last Login" %}</th>
|
||||||
<th width="14%">{% trans "Operations" %}</th>
|
<th width="14%">{% trans "Operations" %}</th>
|
||||||
</tr>
|
</tr>
|
||||||
@ -70,7 +70,17 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<td style="font-size:11px;">
|
<td style="font-size:11px;">
|
||||||
<p> {{ user.space_usage|seahub_filesizeformat }} {% if user.space_quota > 0 %} / {{ user.space_quota|seahub_filesizeformat }} {% endif %} </p>
|
{{ user.space_usage|seahub_filesizeformat }} /
|
||||||
|
<span class="user-space-quota">
|
||||||
|
{% if user.space_quota > 0 %}
|
||||||
|
{{ user.space_quota|seahub_filesizeformat }}
|
||||||
|
{% else %}
|
||||||
|
--
|
||||||
|
{% endif %}
|
||||||
|
</span>
|
||||||
|
{% if user.source == "DB" or user.source == 'LDAPImport' %}
|
||||||
|
<span title="{% trans "Edit Quota" %}" class="quota-edit-icon sf2-icon-edit op-icon vh"></span>
|
||||||
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{% if user.source == "DB" %}
|
{% if user.source == "DB" %}
|
||||||
@ -94,3 +104,13 @@
|
|||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
{% if user.source == "DB" or user.source == 'LDAPImport' %}
|
||||||
|
<form id="set-quota-form" method="post" action="" class="hide">{% csrf_token %}
|
||||||
|
<h3>{% trans "Set user storage limit" %}</h3>
|
||||||
|
<input type="text" name="space_quota" /> MB
|
||||||
|
<p class="tip">{% trans "Tip: 0 means default limit" %}</p>
|
||||||
|
<p class="error hide"></p>
|
||||||
|
<input type="submit" value="{% trans "Submit" %}" class="submit" />
|
||||||
|
</form>
|
||||||
|
{% endif %}
|
||||||
|
@ -41,26 +41,65 @@
|
|||||||
<dd>{{ org_name }}</dd>
|
<dd>{{ org_name }}</dd>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if profile %}
|
|
||||||
<dt>{% trans "Name" context "true name" %}</dt>
|
<dt>{% trans "Name" context "true name" %}</dt>
|
||||||
<dd>{{ profile.nickname }}</dd>
|
<dd>
|
||||||
{% endif %}
|
<span id="nickname">
|
||||||
|
{% if profile and profile.nickname %}
|
||||||
|
{{ profile.nickname }}
|
||||||
|
{% else %}
|
||||||
|
--
|
||||||
|
{% endif %}
|
||||||
|
</span>
|
||||||
|
<span id="set-name" title="{% trans "Edit"%}" class="sf2-icon-edit op-icon"></span>
|
||||||
|
</dd>
|
||||||
|
|
||||||
{% if d_profile %}
|
|
||||||
<dt>{% trans "Department" %}</dt>
|
<dt>{% trans "Department" %}</dt>
|
||||||
<dd>{{ d_profile.department }}</dd>
|
<dd>
|
||||||
|
<span id="department">
|
||||||
|
{% if d_profile and d_profile.department %}
|
||||||
|
{{ d_profile.department }}
|
||||||
|
{% else %}
|
||||||
|
--
|
||||||
|
{% endif %}
|
||||||
|
</span>
|
||||||
|
<span id="set-dept" title="{% trans "Edit"%}" class="sf2-icon-edit op-icon"></span>
|
||||||
|
</dd>
|
||||||
|
|
||||||
|
{% if d_profile and d_profile.telephone %}
|
||||||
<dt>{% trans "Telephone" %}</dt>
|
<dt>{% trans "Telephone" %}</dt>
|
||||||
<dd>{{ d_profile.telephone }}</dd>
|
<dd>{{ d_profile.telephone }}</dd>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<dt>{% trans "Space Used" %}</dt>
|
<dt>{% trans "Space Used / Quota" %}</dt>
|
||||||
<dd>{{ space_usage|seahub_filesizeformat }} {% if space_quota > 0 %} / {{ space_quota|seahub_filesizeformat }} {% endif %} <a href="#" class="sf-btn-link" style="margin-left:20px;" id="set-quota">{% trans "Set Quota" %}</a></dd>
|
<dd>
|
||||||
|
{{ space_usage|seahub_filesizeformat }} /
|
||||||
|
<span id="quota">
|
||||||
|
{% if space_quota > 0 %}
|
||||||
|
{{ space_quota|seahub_filesizeformat }}
|
||||||
|
{% else %}
|
||||||
|
--
|
||||||
|
{% endif %}
|
||||||
|
</span>
|
||||||
|
<span id="set-quota" title="{% trans "Edit Quota" %}" class="sf2-icon-edit op-icon"></span>
|
||||||
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
|
<form id="set-name-form" method="post" action="" class="hide">{% csrf_token %}
|
||||||
|
<h3>{% trans "Set user name" %}</h3>
|
||||||
|
<input type="text" name="nickname" class="input" value="" /><br />
|
||||||
|
<p class="error hide"></p>
|
||||||
|
<input type="submit" value="{% trans "Submit" %}" class="submit" />
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<form id="set-dept-form" method="post" action="" class="hide">{% csrf_token %}
|
||||||
|
<h3>{% trans "Set user department" %}</h3>
|
||||||
|
<input type="text" name="department" class="input" value="" /><br />
|
||||||
|
<p class="error hide"></p>
|
||||||
|
<input type="submit" value="{% trans "Submit" %}" class="submit" />
|
||||||
|
</form>
|
||||||
|
|
||||||
<form id="set-quota-form" method="post" class="hide">{% csrf_token %}
|
<form id="set-quota-form" method="post" class="hide">{% csrf_token %}
|
||||||
<h3>{% trans "Set user storage limit" %}</h3>
|
<h3>{% trans "Set user storage limit" %}</h3>
|
||||||
<input type="hidden" name="email" value="{{ email }}" />
|
|
||||||
<input type="text" name="space_quota" /> MB
|
<input type="text" name="space_quota" /> MB
|
||||||
<p class="tip">{% trans "Tip: 0 means default limit" %}</p>
|
<p class="tip">{% trans "Tip: 0 means default limit" %}</p>
|
||||||
<p class="error hide"></p>
|
<p class="error hide"></p>
|
||||||
@ -254,43 +293,134 @@ $('.rm-link').click(function() {
|
|||||||
});
|
});
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
$('#set-name').click(function() {
|
||||||
|
$("#set-name-form").modal({appendTo: "#main"});
|
||||||
|
$('#simplemodal-container').css({'width':'auto', 'height':'auto'});
|
||||||
|
});
|
||||||
|
$('#set-dept').click(function() {
|
||||||
|
$("#set-dept-form").modal({appendTo: "#main"});
|
||||||
|
$('#simplemodal-container').css({'width':'auto', 'height':'auto'});
|
||||||
|
});
|
||||||
$('#set-quota').click(function() {
|
$('#set-quota').click(function() {
|
||||||
$("#set-quota-form").modal({appendTo: "#main"});
|
$("#set-quota-form").modal({appendTo: "#main"});
|
||||||
return false;
|
$('#simplemodal-container').css({'width':'auto', 'height':'auto'});
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#set-quota-form .submit').click(function() {
|
$('#set-name-form').submit(function() {
|
||||||
var form = $('#set-quota-form'),
|
var nickname = $.trim($('[name="nickname"]', $(this)).val());
|
||||||
form_id = form.attr('id'),
|
var $name = $('#nickname');
|
||||||
space_quota = $('input[name="space_quota"]', form).val();
|
var $error = $('.error', $(this));
|
||||||
|
if (nickname.indexOf('/') != -1) {
|
||||||
if (!$.trim(space_quota)) {
|
$error.html("{% trans "Name should not include '/'." %}").show();
|
||||||
apply_form_error(form_id, "{% trans "Space Quota can't be empty" %}");
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
data = { 'email': $('input[name="email"]', form).val(), 'space_quota': space_quota };
|
var $submitBtn = $('[type="submit"]', $(this));
|
||||||
|
disable($submitBtn);
|
||||||
|
|
||||||
var sb_btn = $(this);
|
|
||||||
disable(sb_btn);
|
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: '{% url 'user_set_quota' email %}',
|
url: '{% url 'api2-account' email %}',
|
||||||
type: 'POST',
|
type: 'PUT',
|
||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
cache: false,
|
cache: false,
|
||||||
beforeSend: prepareCSRFToken,
|
beforeSend: prepareCSRFToken,
|
||||||
data: data,
|
data: {'name': nickname},
|
||||||
success: function(data) {
|
success: function(data) {
|
||||||
location.reload(true);
|
if (nickname == '') {
|
||||||
|
$name.html('--');
|
||||||
|
} else {
|
||||||
|
$name.html(HTMLescape(data['name']));
|
||||||
|
}
|
||||||
|
$.modal.close();
|
||||||
|
},
|
||||||
|
error: function(xhr, textStatus, errorThrown) {
|
||||||
|
var err_msg;
|
||||||
|
if (xhr.responseText) {
|
||||||
|
err_msg = $.parseJSON(xhr.responseText).error_msg;
|
||||||
|
} else {
|
||||||
|
err_msg = "{% trans "Failed. Please check the network." %}";
|
||||||
|
}
|
||||||
|
$error.html(err_msg).show();
|
||||||
|
enable($submitBtn);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#set-dept-form').submit(function() {
|
||||||
|
var department = $.trim($('[name="department"]', $(this)).val());
|
||||||
|
var $department = $('#department');
|
||||||
|
var $error = $('.error', $(this));
|
||||||
|
var $submitBtn = $('[type="submit"]', $(this));
|
||||||
|
disable($submitBtn);
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: '{% url 'api2-account' email %}',
|
||||||
|
type: 'PUT',
|
||||||
|
dataType: 'json',
|
||||||
|
cache: false,
|
||||||
|
beforeSend: prepareCSRFToken,
|
||||||
|
data: {'department': department},
|
||||||
|
success: function(data) {
|
||||||
|
if (department == '') {
|
||||||
|
$department.html('--');
|
||||||
|
} else {
|
||||||
|
$department.html(HTMLescape(data['department']));
|
||||||
|
}
|
||||||
|
$.modal.close();
|
||||||
|
},
|
||||||
|
error: function(xhr, textStatus, errorThrown) {
|
||||||
|
var err_msg;
|
||||||
|
if (xhr.responseText) {
|
||||||
|
err_msg = $.parseJSON(xhr.responseText).error_msg;
|
||||||
|
} else {
|
||||||
|
err_msg = "{% trans "Failed. Please check the network." %}";
|
||||||
|
}
|
||||||
|
$error.html(err_msg).show();
|
||||||
|
enable($submitBtn);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#set-quota-form').submit(function() {
|
||||||
|
var form = $(this),
|
||||||
|
form_id = form.attr('id'),
|
||||||
|
space_quota = $.trim($('input[name="space_quota"]', form).val());
|
||||||
|
var $quota = $('#quota');
|
||||||
|
|
||||||
|
if (!space_quota) {
|
||||||
|
apply_form_error(form_id, "{% trans "It is required." %}");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var $submitBtn = $('[type="submit"]', $(this));
|
||||||
|
disable($submitBtn);
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: '{% url 'api2-account' email %}',
|
||||||
|
type: 'PUT',
|
||||||
|
dataType: 'json',
|
||||||
|
cache: false,
|
||||||
|
beforeSend: prepareCSRFToken,
|
||||||
|
data: {'storage': space_quota},
|
||||||
|
success: function(data) {
|
||||||
|
if (space_quota == 0) {
|
||||||
|
$quota.html('--');
|
||||||
|
} else {
|
||||||
|
$quota.html(parseInt(data['total'])/1000000 + ' MB');
|
||||||
|
}
|
||||||
|
$.modal.close();
|
||||||
},
|
},
|
||||||
error: function(xhr, textStatus, errorThrown) {
|
error: function(xhr, textStatus, errorThrown) {
|
||||||
if (xhr.responseText) {
|
if (xhr.responseText) {
|
||||||
apply_form_error(form_id, $.parseJSON(xhr.responseText).error);
|
apply_form_error(form_id, $.parseJSON(xhr.responseText).error_msg);
|
||||||
} else {
|
} else {
|
||||||
apply_form_error(form_id, "{% trans "Failed. Please check the network." %}");
|
apply_form_error(form_id, "{% trans "Failed. Please check the network." %}");
|
||||||
}
|
}
|
||||||
enable(sb_btn);
|
enable($submitBtn);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return false;
|
return false;
|
||||||
|
@ -54,6 +54,7 @@ from seahub.views.ajax import (get_related_users_by_org_repo,
|
|||||||
get_related_users_by_repo)
|
get_related_users_by_repo)
|
||||||
from seahub.forms import SetUserQuotaForm, AddUserForm, BatchAddUserForm, \
|
from seahub.forms import SetUserQuotaForm, AddUserForm, BatchAddUserForm, \
|
||||||
TermsAndConditionsForm
|
TermsAndConditionsForm
|
||||||
|
from seahub.profile.forms import ProfileForm, DetailedProfileForm
|
||||||
from seahub.options.models import UserOptions
|
from seahub.options.models import UserOptions
|
||||||
from seahub.profile.models import Profile, DetailedProfile
|
from seahub.profile.models import Profile, DetailedProfile
|
||||||
from seahub.signals import repo_deleted
|
from seahub.signals import repo_deleted
|
||||||
@ -645,7 +646,6 @@ def user_set_quota(request, email):
|
|||||||
|
|
||||||
f = SetUserQuotaForm(request.POST)
|
f = SetUserQuotaForm(request.POST)
|
||||||
if f.is_valid():
|
if f.is_valid():
|
||||||
email = f.cleaned_data['email']
|
|
||||||
space_quota_mb = f.cleaned_data['space_quota']
|
space_quota_mb = f.cleaned_data['space_quota']
|
||||||
space_quota = space_quota_mb * get_file_size_unit('MB')
|
space_quota = space_quota_mb * get_file_size_unit('MB')
|
||||||
|
|
||||||
@ -980,6 +980,8 @@ def user_add(request):
|
|||||||
form = AddUserForm(post_values)
|
form = AddUserForm(post_values)
|
||||||
if form.is_valid():
|
if form.is_valid():
|
||||||
email = form.cleaned_data['email']
|
email = form.cleaned_data['email']
|
||||||
|
name = form.cleaned_data['name']
|
||||||
|
department = form.cleaned_data['department']
|
||||||
role = form.cleaned_data['role']
|
role = form.cleaned_data['role']
|
||||||
password = form.cleaned_data['password1']
|
password = form.cleaned_data['password1']
|
||||||
|
|
||||||
@ -995,6 +997,10 @@ def user_add(request):
|
|||||||
User.objects.update_role(email, role)
|
User.objects.update_role(email, role)
|
||||||
if config.FORCE_PASSWORD_CHANGE:
|
if config.FORCE_PASSWORD_CHANGE:
|
||||||
UserOptions.objects.set_force_passwd_change(email)
|
UserOptions.objects.set_force_passwd_change(email)
|
||||||
|
if name:
|
||||||
|
Profile.objects.add_or_update(email, name, '')
|
||||||
|
if department:
|
||||||
|
DetailedProfile.objects.add_or_update(email, department, '')
|
||||||
|
|
||||||
if request.user.org:
|
if request.user.org:
|
||||||
org_id = request.user.org.org_id
|
org_id = request.user.org.org_id
|
||||||
@ -1834,12 +1840,31 @@ def batch_add_user(request):
|
|||||||
username = row[0].strip()
|
username = row[0].strip()
|
||||||
password = row[1].strip()
|
password = row[1].strip()
|
||||||
|
|
||||||
|
# nickname & department are optional
|
||||||
|
try:
|
||||||
|
nickname = row[2].strip()
|
||||||
|
except IndexError:
|
||||||
|
nickname = ''
|
||||||
|
|
||||||
|
try:
|
||||||
|
department = row[3].strip()
|
||||||
|
except IndexError:
|
||||||
|
department = ''
|
||||||
|
|
||||||
if not is_valid_username(username):
|
if not is_valid_username(username):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if password == '':
|
if password == '':
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
if nickname:
|
||||||
|
if len(nickname) > 64 or '/' in nickname:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if department:
|
||||||
|
if len(department) > 512:
|
||||||
|
continue
|
||||||
|
|
||||||
try:
|
try:
|
||||||
User.objects.get(email=username)
|
User.objects.get(email=username)
|
||||||
continue
|
continue
|
||||||
@ -1847,6 +1872,11 @@ def batch_add_user(request):
|
|||||||
User.objects.create_user(username, password, is_staff=False,
|
User.objects.create_user(username, password, is_staff=False,
|
||||||
is_active=True)
|
is_active=True)
|
||||||
|
|
||||||
|
if nickname:
|
||||||
|
Profile.objects.add_or_update(username, nickname, '')
|
||||||
|
if department:
|
||||||
|
DetailedProfile.objects.add_or_update(username, department, '')
|
||||||
|
|
||||||
send_html_email_with_dj_template(
|
send_html_email_with_dj_template(
|
||||||
username, dj_template='sysadmin/user_batch_add_email.html',
|
username, dj_template='sysadmin/user_batch_add_email.html',
|
||||||
subject=_(u'You are invited to join %s') % SITE_NAME,
|
subject=_(u'You are invited to join %s') % SITE_NAME,
|
||||||
|
@ -77,7 +77,7 @@ class AccountTest(BaseTestCase):
|
|||||||
|
|
||||||
resp = self._do_get_info()
|
resp = self._do_get_info()
|
||||||
json_resp = json.loads(resp.content)
|
json_resp = json.loads(resp.content)
|
||||||
assert len(json_resp) == 7
|
assert len(json_resp) == 9
|
||||||
assert json_resp['email'] == self.user1.username
|
assert json_resp['email'] == self.user1.username
|
||||||
assert json_resp['is_staff'] is False
|
assert json_resp['is_staff'] is False
|
||||||
assert json_resp['is_active'] is True
|
assert json_resp['is_active'] is True
|
||||||
@ -104,7 +104,7 @@ class AccountTest(BaseTestCase):
|
|||||||
self.assertEqual(Profile.objects.get_profile_by_user(
|
self.assertEqual(Profile.objects.get_profile_by_user(
|
||||||
self.user1.username).intro, 'this_is_user1')
|
self.user1.username).intro, 'this_is_user1')
|
||||||
self.assertEqual(seafile_api.get_user_quota(
|
self.assertEqual(seafile_api.get_user_quota(
|
||||||
self.user1.username), 102400)
|
self.user1.username), 102400000000)
|
||||||
|
|
||||||
def test_refresh_profile_cache_after_update(self):
|
def test_refresh_profile_cache_after_update(self):
|
||||||
self.login_as(self.admin)
|
self.login_as(self.admin)
|
||||||
|
@ -35,8 +35,7 @@ class AccountsApiTest(ApiTestBase):
|
|||||||
# non-admin user can not create new user
|
# non-admin user can not create new user
|
||||||
self.put(test_account_url, data=data, expected=403)
|
self.put(test_account_url, data=data, expected=403)
|
||||||
|
|
||||||
res = self.admin_put(test_account_url, data=data, expected=201)
|
self.admin_put(test_account_url, data=data, expected=201)
|
||||||
self.assertEqual(res.text, u'"success"')
|
|
||||||
|
|
||||||
# non-admin user can not delete a user
|
# non-admin user can not delete a user
|
||||||
self.delete(test_account_url, expected=403)
|
self.delete(test_account_url, expected=403)
|
||||||
@ -99,10 +98,10 @@ class AccountsApiTest(ApiTestBase):
|
|||||||
|
|
||||||
def test_update_account_storage_quota(self):
|
def test_update_account_storage_quota(self):
|
||||||
with self.get_tmp_user() as user:
|
with self.get_tmp_user() as user:
|
||||||
data = {'storage': 1024} # 1KB
|
data = {'storage': 1024} # 1 Mb
|
||||||
self.admin_put(user.user_url, data=data, expected=200)
|
self.admin_put(user.user_url, data=data, expected=200)
|
||||||
self.assertEqual(self.admin_get(user.user_url).json()['total'],
|
self.assertEqual(self.admin_get(user.user_url).json()['total'],
|
||||||
1024)
|
1024000000)
|
||||||
|
|
||||||
# def test_update_account_sharing_quota(self):
|
# def test_update_account_sharing_quota(self):
|
||||||
# with self.get_tmp_user() as user:
|
# with self.get_tmp_user() as user:
|
||||||
|
Loading…
Reference in New Issue
Block a user