1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-09-13 13:50:07 +00:00

Merge branch '6.3'

This commit is contained in:
zhengxie
2019-01-02 12:53:36 +08:00
15 changed files with 286 additions and 27 deletions

View File

@@ -34,18 +34,16 @@ logger = logging.getLogger(__name__)
def get_org_user_info(org_id, email): def get_org_user_info(org_id, email):
user_info = {} user_info = {}
user_obj = User.objects.get(email=email)
user_info['org_id'] = org_id user_info['org_id'] = org_id
user_info['active'] = user_obj.is_active
user_info['email'] = email user_info['email'] = email
user_info['name'] = email2nickname(email) user_info['name'] = email2nickname(email)
user_info['contact_email'] = email2contact_email(email) user_info['contact_email'] = email2contact_email(email)
org_user_quota = seafile_api.get_org_user_quota(org_id, email) org_user_quota = seafile_api.get_org_user_quota(org_id, email)
user_info['quota_total'] = org_user_quota / get_file_size_unit('MB') user_info['quota_total'] = org_user_quota
org_user_quota_usage = seafile_api.get_org_user_quota_usage(org_id, email) org_user_quota_usage = seafile_api.get_org_user_quota_usage(org_id, email)
user_info['quota_usage'] = org_user_quota_usage / get_file_size_unit('MB') user_info['quota_usage'] = org_user_quota_usage
return user_info return user_info
@@ -94,6 +92,32 @@ class AdminOrgUsers(APIView):
throttle_classes = (UserRateThrottle,) throttle_classes = (UserRateThrottle,)
permission_classes = (IsAdminUser, IsProVersion) permission_classes = (IsAdminUser, IsProVersion)
def get(self, request, org_id):
""" Get all users in an org.
Permission checking:
1. only admin can perform this action.
"""
# argument check
org_id = int(org_id)
if org_id == 0:
error_msg = 'org_id invalid.'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
org = ccnet_api.get_org_by_id(org_id)
if not org:
error_msg = 'Organization %d not found.' % org_id
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
result = []
org_users = ccnet_api.get_org_emailusers(org.url_prefix, -1, -1)
for org_user in org_users:
user_info = get_org_user_info(org_id, org_user.email)
user_info['active'] = org_user.is_active
result.append(user_info)
return Response({'users': result})
def post(self, request, org_id): def post(self, request, org_id):
""" Add new user to org. """ Add new user to org.
@@ -121,6 +145,14 @@ class AdminOrgUsers(APIView):
error_msg = 'password invalid.' error_msg = 'password invalid.'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg) return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
active = request.POST.get('active', 'true')
active = active.lower()
if active not in ('true', 'false'):
error_msg = 'active invalid.'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
is_active = active == 'true'
try: try:
User.objects.get(email=email) User.objects.get(email=email)
user_exists = True user_exists = True
@@ -147,7 +179,8 @@ class AdminOrgUsers(APIView):
# create user # create user
try: try:
User.objects.create_user(email, password, is_staff=False, is_active=True) User.objects.create_user(email, password, is_staff=False,
is_active=is_active)
except User.DoesNotExist as e: except User.DoesNotExist as e:
logger.error(e) logger.error(e)
error_msg = 'Fail to add user %s.' % email error_msg = 'Fail to add user %s.' % email
@@ -170,6 +203,7 @@ class AdminOrgUsers(APIView):
UserOptions.objects.set_force_passwd_change(email) UserOptions.objects.set_force_passwd_change(email)
user_info = get_org_user_info(org_id, email) user_info = get_org_user_info(org_id, email)
user_info['active'] = is_active
return Response(user_info) return Response(user_info)
@@ -188,7 +222,24 @@ class AdminOrgUser(APIView):
""" """
# argument check # argument check
org_id = int(org_id)
if org_id == 0:
error_msg = 'org_id invalid.'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
org = ccnet_api.get_org_by_id(org_id)
if not org:
error_msg = 'Organization %d not found.' % org_id
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
try:
user_obj = User.objects.get(email=email)
except User.DoesNotExist:
error_msg = 'User %s not found.' % email
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
user_info = get_org_user_info(org_id, email) user_info = get_org_user_info(org_id, email)
user_info['active'] = user_obj.is_active
return Response(user_info) return Response(user_info)
@check_org_user @check_org_user
@@ -199,6 +250,12 @@ class AdminOrgUser(APIView):
1. only admin can perform this action. 1. only admin can perform this action.
""" """
try:
user = User.objects.get(email=email)
except User.DoesNotExist:
error_msg = 'User %s not found.' % email
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
# update active # update active
active = request.data.get('active', None) active = request.data.get('active', None)
if active: if active:
@@ -207,7 +264,6 @@ class AdminOrgUser(APIView):
error_msg = "active invalid, should be 'true' or 'false'." error_msg = "active invalid, should be 'true' or 'false'."
return api_error(status.HTTP_400_BAD_REQUEST, error_msg) return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
user = User.objects.get(email=email)
if active == 'true': if active == 'true':
user.is_active = True user.is_active = True
else: else:
@@ -267,6 +323,7 @@ class AdminOrgUser(APIView):
seafile_api.set_org_user_quota(org_id, email, user_quota) seafile_api.set_org_user_quota(org_id, email, user_quota)
user_info = get_org_user_info(org_id, email) user_info = get_org_user_info(org_id, email)
user_info['active'] = user.is_active
return Response(user_info) return Response(user_info)
@check_org_user @check_org_user

View File

@@ -9,8 +9,6 @@ from rest_framework import status
from seaserv import ccnet_api, seafile_api from seaserv import ccnet_api, seafile_api
from seaserv import seafserv_threaded_rpc
from seahub.utils.file_size import get_file_size_unit from seahub.utils.file_size import get_file_size_unit
from seahub.utils.timeutils import timestamp_to_isoformat_timestr from seahub.utils.timeutils import timestamp_to_isoformat_timestr
from seahub.base.templatetags.seahub_tags import email2nickname, \ from seahub.base.templatetags.seahub_tags import email2nickname, \
@@ -40,12 +38,11 @@ except ImportError:
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
def get_org_info(org_id): def get_org_info(org):
org_id = org.org_id
org_info = {} org_info = {}
org = ccnet_api.get_org_by_id(org_id)
org_info['org_id'] = org_id org_info['org_id'] = org_id
org_info['org_name'] = org.org_name org_info['org_name'] = org.org_name
org_info['ctime'] = timestamp_to_isoformat_timestr(org.ctime) org_info['ctime'] = timestamp_to_isoformat_timestr(org.ctime)
@@ -57,12 +54,44 @@ def get_org_info(org_id):
org_info['creator_contact_email'] = email2contact_email(creator) org_info['creator_contact_email'] = email2contact_email(creator)
org_info['quota'] = seafile_api.get_org_quota(org_id) org_info['quota'] = seafile_api.get_org_quota(org_id)
org_info['quota_usage'] = seafile_api.get_org_quota_usage(org_id)
if ORG_MEMBER_QUOTA_ENABLED: if ORG_MEMBER_QUOTA_ENABLED:
org_info['max_user_number'] = OrgMemberQuota.objects.get_quota(org_id) org_info['max_user_number'] = OrgMemberQuota.objects.get_quota(org_id)
return org_info return org_info
class AdminOrganizations(APIView):
authentication_classes = (TokenAuthentication, SessionAuthentication)
permission_classes = (IsAdminUser, IsProVersion)
throttle_classes = (UserRateThrottle,)
def get(self, request):
""" Get all organizations
Permission checking:
1. only admin can perform this action.
"""
if not (CLOUD_MODE and MULTI_TENANCY):
error_msg = 'Feature is not enabled.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
try:
orgs = ccnet_api.get_all_orgs(-1, -1)
except Exception as e:
logger.error(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
result = []
for org in orgs:
org_info = get_org_info(org)
result.append(org_info)
return Response({'organizations': result})
class AdminOrganization(APIView): class AdminOrganization(APIView):
@@ -92,7 +121,7 @@ class AdminOrganization(APIView):
return api_error(status.HTTP_404_NOT_FOUND, error_msg) return api_error(status.HTTP_404_NOT_FOUND, error_msg)
try: try:
org_info = get_org_info(org_id) org_info = get_org_info(org)
except Exception as e: except Exception as e:
logger.error(e) logger.error(e)
error_msg = 'Internal Server Error' error_msg = 'Internal Server Error'
@@ -174,7 +203,7 @@ class AdminOrganization(APIView):
error_msg = 'Internal Server Error' error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
org_info = get_org_info(org_id) org_info = get_org_info(org)
return Response(org_info) return Response(org_info)
def delete(self, request, org_id): def delete(self, request, org_id):

View File

@@ -8,6 +8,7 @@ from seahub.auth import authenticate
from seahub.api2.models import DESKTOP_PLATFORMS from seahub.api2.models import DESKTOP_PLATFORMS
from seahub.api2.utils import get_token_v1, get_token_v2 from seahub.api2.utils import get_token_v1, get_token_v2
from seahub.profile.models import Profile from seahub.profile.models import Profile
from seahub.two_factor.models import default_device
from seahub.two_factor.views.login import is_device_remembered from seahub.two_factor.views.login import is_device_remembered
from seahub.utils.two_factor_auth import has_two_factor_auth, \ from seahub.utils.two_factor_auth import has_two_factor_auth, \
two_factor_auth_enabled, verify_two_factor_token two_factor_auth_enabled, verify_two_factor_token
@@ -118,10 +119,13 @@ class AuthTokenSerializer(serializers.Serializer):
token = request.META.get('HTTP_X_SEAFILE_OTP', '') token = request.META.get('HTTP_X_SEAFILE_OTP', '')
if not token: if not token:
# Generate challenge(send sms/call/...) if token is not provided.
default_device(user).generate_challenge()
self.two_factor_auth_failed = True self.two_factor_auth_failed = True
msg = 'Two factor auth token is missing.' msg = 'Two factor auth token is missing.'
raise serializers.ValidationError(msg) raise serializers.ValidationError(msg)
if not verify_two_factor_token(user.username, token): if not verify_two_factor_token(user, token):
self.two_factor_auth_failed = True self.two_factor_auth_failed = True
msg = 'Two factor auth token is invalid.' msg = 'Two factor auth token is invalid.'
raise serializers.ValidationError(msg) raise serializers.ValidationError(msg)

View File

@@ -8,5 +8,9 @@ class CheckPasswordHash(object):
"""Logout user if value of hash key in session is not equal to current password hash""" """Logout user if value of hash key in session is not equal to current password hash"""
def process_view(self, request, *args, **kwargs): def process_view(self, request, *args, **kwargs):
if getattr(request.user, 'is_authenticated') and request.user.is_authenticated(): if getattr(request.user, 'is_authenticated') and request.user.is_authenticated():
if request.user.enc_password == '!':
# Disable for LDAP/Shibboleth/SAML/... users.
return None
if request.session.get(PASSWORD_HASH_KEY) != get_password_hash(request.user): if request.session.get(PASSWORD_HASH_KEY) != get_password_hash(request.user):
logout(request) logout(request)

View File

@@ -5,6 +5,8 @@ from django.utils.translation import ugettext_lazy as _
from seahub.profile.models import Profile, DetailedProfile from seahub.profile.models import Profile, DetailedProfile
from seahub.settings import ENABLE_UPDATE_USER_INFO
class ProfileForm(forms.Form): class ProfileForm(forms.Form):
nickname = forms.CharField(max_length=64, required=False) nickname = forms.CharField(max_length=64, required=False)
intro = forms.CharField(max_length=256, required=False) intro = forms.CharField(max_length=256, required=False)
@@ -13,6 +15,9 @@ class ProfileForm(forms.Form):
""" """
Validates that nickname should not include '/' Validates that nickname should not include '/'
""" """
if not ENABLE_UPDATE_USER_INFO:
raise forms.ValidationError(_(u"Permission denied."))
if "/" in self.cleaned_data["nickname"]: if "/" in self.cleaned_data["nickname"]:
raise forms.ValidationError(_(u"Name should not include '/'.")) raise forms.ValidationError(_(u"Name should not include '/'."))

View File

@@ -29,7 +29,9 @@
<li class="tab"><a href="#two-factor-auth">{% trans "Two-Factor Authentication" %}</a></li> <li class="tab"><a href="#two-factor-auth">{% trans "Two-Factor Authentication" %}</a></li>
{% endif %} {% endif %}
{% if ENABLE_DELETE_ACCOUNT %}
<li class="tab" id="del-account-nav"><a href="#del-account">{% trans "Delete Account" %}</a></li> <li class="tab" id="del-account-nav"><a href="#del-account">{% trans "Delete Account" %}</a></li>
{% endif %}
</ul> </ul>
</div> </div>
@@ -48,10 +50,13 @@
</div> </div>
<form action="" method="post">{% csrf_token %} <form action="" method="post">{% csrf_token %}
<label>{% trans "Name:" context "true name" %}</label><input type="text" name="nickname" value="{{ form.data.nickname }}" class="input" /> <label>{% trans "Name:" context "true name" %}</label><input type="text" name="nickname" value="{{ form.data.nickname }}" class="input" {% if not ENABLE_UPDATE_USER_INFO %} disabled {% endif %}/>
{% if ENABLE_UPDATE_USER_INFO %}
{% for error in form.nickname.errors %} {% for error in form.nickname.errors %}
<span class="error">{{ error|escape }}</span> <span class="error">{{ error|escape }}</span>
{% endfor %} {% endfor %}
{% endif %}
<br/> <br/>
{% if form.data.login_id %} {% if form.data.login_id %}
@@ -67,14 +72,15 @@
{% endif %} {% endif %}
{% if form.telephone %} {% if form.telephone %}
<label>{% trans "Telephone:" %}</label><input type="text" name="telephone" value="{{ form.data.telephone }}" class="input" /> <label>{% trans "Telephone:" %}</label><input type="text" name="telephone" value="{{ form.data.telephone }}" class="input" {% if not ENABLE_UPDATE_USER_INFO %} disabled {% endif %} />
{% for error in form.telephone.errors %} {% for error in form.telephone.errors %}
<span class="error">{{ error|escape }}</span> <span class="error">{{ error|escape }}</span>
{% endfor %} {% endfor %}
<br/> <br/>
{% endif %} {% endif %}
{% if ENABLE_UPDATE_USER_INFO %}
<input type="submit" value="{% trans "Submit" %}" class="submit vh" /> <input type="submit" value="{% trans "Submit" %}" class="submit vh" />
{% endif %}
</form> </form>
</div> </div>
@@ -165,6 +171,7 @@
</div> </div>
{% endif %} {% endif %}
{% if ENABLE_DELETE_ACCOUNT %}
<div class="setting-item" id="del-account"> <div class="setting-item" id="del-account">
<h3>{% trans "Delete Account" %}</h3> <h3>{% trans "Delete Account" %}</h3>
<p class="txt-before-btn">{% trans "This operation will not be reverted. Please think twice!" %}</p> <p class="txt-before-btn">{% trans "This operation will not be reverted. Please think twice!" %}</p>
@@ -173,6 +180,7 @@
<input type="submit" value="{% trans "Delete" %}" class="submit" /> <input type="submit" value="{% trans "Delete" %}" class="submit" />
</form> </form>
</div> </div>
{% endif %}
</div> <!-- right-panel --> </div> <!-- right-panel -->
</div> <!-- row --> </div> <!-- row -->
@@ -228,6 +236,7 @@ $('#user-avatar-input').on('change', function() {
$('#user-basic-info .submit').css({'margin-left': $('#user-basic-info label').outerWidth(true)}).removeClass('vh'); $('#user-basic-info .submit').css({'margin-left': $('#user-basic-info label').outerWidth(true)}).removeClass('vh');
{% if ENABLE_DELETE_ACCOUNT %}
$('#account-delete-btn').on('click', function () { $('#account-delete-btn').on('click', function () {
var title = "{% trans "Delete Account" %}", var title = "{% trans "Delete Account" %}",
con = "{% trans "Really want to delete your account?" %}"; con = "{% trans "Really want to delete your account?" %}";
@@ -240,6 +249,7 @@ $('#account-delete-btn').on('click', function () {
$('#account-delete-form').trigger('submit'); $('#account-delete-form').trigger('submit');
}); });
}); });
{% endif %}
{% if ENABLE_ADDRESSBOOK_OPT_IN %} {% if ENABLE_ADDRESSBOOK_OPT_IN %}
$("#list-in-address-book input[type='checkbox']").on('change', function() { $("#list-in-address-book input[type='checkbox']").on('change', function() {

View File

@@ -23,6 +23,8 @@ from seahub.utils import is_ldap_user
from seahub.utils.two_factor_auth import has_two_factor_auth from seahub.utils.two_factor_auth import has_two_factor_auth
from seahub.views import get_owned_repo_list from seahub.views import get_owned_repo_list
from seahub.settings import ENABLE_DELETE_ACCOUNT, ENABLE_UPDATE_USER_INFO
@login_required @login_required
def edit_profile(request): def edit_profile(request):
""" """
@@ -96,6 +98,8 @@ def edit_profile(request):
'two_factor_auth_enabled': has_two_factor_auth(), 'two_factor_auth_enabled': has_two_factor_auth(),
'ENABLE_CHANGE_PASSWORD': settings.ENABLE_CHANGE_PASSWORD, 'ENABLE_CHANGE_PASSWORD': settings.ENABLE_CHANGE_PASSWORD,
'ENABLE_WEBDAV_SECRET': settings.ENABLE_WEBDAV_SECRET, 'ENABLE_WEBDAV_SECRET': settings.ENABLE_WEBDAV_SECRET,
'ENABLE_DELETE_ACCOUNT': ENABLE_DELETE_ACCOUNT,
'ENABLE_UPDATE_USER_INFO': ENABLE_UPDATE_USER_INFO,
'webdav_passwd': webdav_passwd, 'webdav_passwd': webdav_passwd,
'email_notification_interval': email_inverval, 'email_notification_interval': email_inverval,
} }
@@ -177,6 +181,11 @@ def get_user_profile(request, user):
@login_required @login_required
def delete_user_account(request): def delete_user_account(request):
if not ENABLE_DELETE_ACCOUNT:
messages.error(request, _(u'Permission denied.'))
next = request.META.get('HTTP_REFERER', settings.SITE_ROOT)
return HttpResponseRedirect(next)
if request.method != 'POST': if request.method != 'POST':
raise Http404 raise Http404

View File

@@ -365,6 +365,9 @@ FORCE_PASSWORD_CHANGE = True
# Enable a user to change password in 'settings' page. # Enable a user to change password in 'settings' page.
ENABLE_CHANGE_PASSWORD = True ENABLE_CHANGE_PASSWORD = True
ENABLE_DELETE_ACCOUNT = True
ENABLE_UPDATE_USER_INFO = True
# Enable or disable repo history setting # Enable or disable repo history setting
ENABLE_REPO_HISTORY_SETTING = True ENABLE_REPO_HISTORY_SETTING = True

View File

@@ -3,6 +3,9 @@
watermark.load({ watermark.load({
{% if request.user.username %} {% if request.user.username %}
watermark_txt: "{{site_name}} {{request.user.username|email2nickname|escapejs}}", watermark_txt: "{{site_name}} {{request.user.username|email2nickname|escapejs}}",
{# used when view shared file #}
{% elif shared_by %}
watermark_txt: "{{site_name}} {{shared_by|email2nickname|escapejs}}",
{% else %} {% else %}
watermark_txt: "{% trans "Anonymous User" %}", watermark_txt: "{% trans "Anonymous User" %}",
{% endif %} {% endif %}

View File

@@ -0,0 +1,26 @@
# Copyright (c) 2012-2016 Seafile Ltd.
import logging
from django.conf import settings
import requests
logger = logging.getLogger(__name__)
class SeafMessenger(object):
@staticmethod
def make_call(device, token):
logger.info('Fake call to %s: "Your token is: %s"', device.number, token)
@staticmethod
def send_sms(device, token):
api_token = settings.SEAF_MESSAGER_API_TOKEN
url = settings.SEAF_MESSAGER_SMS_API
values = {
'phone_num': device.number,
'code': token,
}
requests.post(url, data=values,
headers={'Authorization': 'Token %s' % api_token})

View File

@@ -215,14 +215,13 @@ def handle_two_factor_auth(request, user, redirect_to):
request.session[SESSION_KEY_TWO_FACTOR_FAILED_ATTEMPT] = 0 request.session[SESSION_KEY_TWO_FACTOR_FAILED_ATTEMPT] = 0
return redirect(reverse('two_factor_auth')) return redirect(reverse('two_factor_auth'))
def verify_two_factor_token(username, token): def verify_two_factor_token(user, token):
""" """
This function is called when doing the api authentication. We only support This function is called when doing the api authentication.
totp here to simply the case. Backup token is not supported, because if the Backup token is not supported, because if the user has the backup token,
user has the backup token, he can always login the website and re-setup the he can always login the website and re-setup the totp.
totp.
""" """
device = TOTPDevice.objects.device_for_user(username) device = default_device(user)
if device: if device:
return device.verify_token(token) return device.verify_token(token)

View File

@@ -113,7 +113,7 @@ from seahub.api2.endpoints.admin.upload_links import AdminUploadLink, \
AdminUploadLinkUpload, AdminUploadLinkCheckPassword AdminUploadLinkUpload, AdminUploadLinkCheckPassword
from seahub.api2.endpoints.admin.users_batch import AdminUsersBatch from seahub.api2.endpoints.admin.users_batch import AdminUsersBatch
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 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
from seahub.api2.endpoints.admin.org_stats import AdminOrgStatsTraffic from seahub.api2.endpoints.admin.org_stats import AdminOrgStatsTraffic
from seahub.api2.endpoints.admin.logo import AdminLogo from seahub.api2.endpoints.admin.logo import AdminLogo
@@ -457,6 +457,7 @@ urlpatterns = [
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'),
## admin::organizations ## admin::organizations
url(r'^api/v2.1/admin/organizations/$', AdminOrganizations.as_view(), name='api-v2.1-admin-organizations'),
url(r'^api/v2.1/admin/organizations/(?P<org_id>\d+)/$', AdminOrganization.as_view(), name='api-v2.1-admin-organization'), url(r'^api/v2.1/admin/organizations/(?P<org_id>\d+)/$', AdminOrganization.as_view(), name='api-v2.1-admin-organization'),
url(r'^api/v2.1/admin/organizations/(?P<org_id>\d+)/users/$', AdminOrgUsers.as_view(), name='api-v2.1-admin-org-users'), url(r'^api/v2.1/admin/organizations/(?P<org_id>\d+)/users/$', AdminOrgUsers.as_view(), name='api-v2.1-admin-org-users'),
url(r'^api/v2.1/admin/organizations/(?P<org_id>\d+)/users/(?P<email>[^/]+)/$', AdminOrgUser.as_view(), name='api-v2.1-admin-org-user'), url(r'^api/v2.1/admin/organizations/(?P<org_id>\d+)/users/(?P<email>[^/]+)/$', AdminOrgUser.as_view(), name='api-v2.1-admin-org-user'),

View File

@@ -133,7 +133,7 @@ define([
if (this.currentView == this.dirView) { if (this.currentView == this.dirView) {
if ($('#upload-file-dialog').is(':visible') && if ($('#upload-file-dialog').is(':visible') &&
$('#upload-file-dialog .status').text() == window.fileuploading) { $('#upload-file-dialog .status').text() == window.fileuploading) {
if (!window.confirm('A file is being uploaded. Are you sure you want to leave this page?')) { if (!window.confirm(gettext('A file is being uploaded. Are you sure you want to leave this page?'))) {
return false; return false;
} }
} }

View File

@@ -57,6 +57,30 @@ class OrgUsersTest(BaseTestCase):
remove_org(self.org_id) remove_org(self.org_id)
self.remove_user(self.org_creator) self.remove_user(self.org_creator)
def test_can_get_users(self):
if not LOCAL_PRO_DEV_ENV:
return
self.login_as(self.admin)
resp = self.client.get(self.org_users_url)
json_resp = json.loads(resp.content)
self.assertEqual(200, resp.status_code)
users = json_resp['organizaton_members']
assert len(users) > 0
assert users[0]['org_id'] == self.org_id
assert users[0]['email'] == self.org_creator
def test_can_not_get_users_if_not_admin(self):
if not LOCAL_PRO_DEV_ENV:
return
self.login_as(self.user)
resp = self.client.get(self.org_users_url)
self.assertEqual(403, resp.status_code)
def test_can_create(self): def test_can_create(self):
if not LOCAL_PRO_DEV_ENV: if not LOCAL_PRO_DEV_ENV:

View File

@@ -0,0 +1,85 @@
import json
from seaserv import ccnet_api
from django.core.urlresolvers import reverse
from seahub.test_utils import BaseTestCase
from tests.common.utils import randstring
from seaserv import seafserv_threaded_rpc
try:
from seahub.settings import LOCAL_PRO_DEV_ENV
except ImportError:
LOCAL_PRO_DEV_ENV = False
def remove_org(org_id):
org_id = int(org_id)
org = ccnet_api.get_org_by_id(org_id)
if org:
users =ccnet_api.get_org_emailusers(org.url_prefix, -1, -1)
for u in users:
ccnet_api.remove_org_user(org_id, u.email)
groups = ccnet_api.get_org_groups(org.org_id, -1, -1)
for g in groups:
ccnet_api.remove_org_group(org_id, g.gid)
# remove org repos
seafserv_threaded_rpc.remove_org_repo_by_org_id(org_id)
# remove org
ccnet_api.remove_org(org_id)
class OrgsTest(BaseTestCase):
def setUp(self):
self.user_name = self.user.username
self.admin_name = self.admin.username
if LOCAL_PRO_DEV_ENV:
self.org_name = randstring(6)
self.org_url_prefix = randstring(6)
tmp_user = self.create_user(email='%s@%s.com' % (randstring(6), randstring(6)))
self.org_creator = tmp_user.username
self.org_id = ccnet_api.create_org(self.org_name,
self.org_url_prefix, self.org_creator)
self.orgs_url = reverse('api-v2.1-admin-organizations')
def tearDown(self):
self.remove_group()
self.remove_repo()
if LOCAL_PRO_DEV_ENV:
remove_org(self.org_id)
self.remove_user(self.org_creator)
def test_can_get_orgs(self):
if not LOCAL_PRO_DEV_ENV:
return
self.login_as(self.admin)
resp = self.client.get(self.orgs_url)
json_resp = json.loads(resp.content)
self.assertEqual(200, resp.status_code)
users = json_resp['organizations']
assert len(users) > 0
assert users[0].has_key('org_id')
assert users[0].has_key('org_name')
assert users[0].has_key('ctime')
assert users[0].has_key('org_url_prefix')
assert users[0].has_key('creator_email')
assert users[0].has_key('creator_name')
assert users[0].has_key('creator_contact_email')
assert users[0].has_key('quota')
def test_can_not_get_orgs_if_not_admin(self):
if not LOCAL_PRO_DEV_ENV:
return
self.login_as(self.user)
resp = self.client.get(self.orgs_url)
self.assertEqual(403, resp.status_code)