@@ -125,6 +126,7 @@ class Wikis extends Component {
+ }
diff --git a/seahub/api2/endpoints/admin/organizations.py b/seahub/api2/endpoints/admin/organizations.py
index b5560493aa..41b4159d9e 100644
--- a/seahub/api2/endpoints/admin/organizations.py
+++ b/seahub/api2/endpoints/admin/organizations.py
@@ -106,7 +106,7 @@ def gen_org_url_prefix(max_trial=None, length=20):
Url prefix if succed, otherwise, ``None``.
"""
def _gen_prefix():
- url_prefix = 'org_' + get_random_string(
+ url_prefix = 'org-' + get_random_string(
length, allowed_chars='abcdefghijklmnopqrstuvwxyz0123456789')
if ccnet_api.get_org_by_url_prefix(url_prefix) is not None:
logger.error("org url prefix, %s is duplicated" % url_prefix)
diff --git a/seahub/api2/endpoints/file.py b/seahub/api2/endpoints/file.py
index 0671db97d7..cf34d7c626 100644
--- a/seahub/api2/endpoints/file.py
+++ b/seahub/api2/endpoints/file.py
@@ -207,10 +207,15 @@ class FileView(APIView):
try:
seafile_api.post_empty_file(repo_id, parent_dir, new_file_name, username)
- except SearpcError as e:
- logger.error(e)
- error_msg = 'Internal Server Error'
- return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
+ except Exception as e:
+ if str(e) == 'Too many files in library.':
+ error_msg = _("The number of files in library exceeds the limit")
+ from seahub.api2.views import HTTP_442_TOO_MANY_FILES_IN_LIBRARY
+ return api_error(HTTP_442_TOO_MANY_FILES_IN_LIBRARY, error_msg)
+ else:
+ logger.error(e)
+ error_msg = 'Internal Server Error'
+ return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
if is_draft.lower() == 'true':
Draft.objects.add(username, repo, path, file_exist=False)
diff --git a/seahub/api2/endpoints/share_link_zip_task.py b/seahub/api2/endpoints/share_link_zip_task.py
index ed3e71bb3a..7c167b7ee5 100644
--- a/seahub/api2/endpoints/share_link_zip_task.py
+++ b/seahub/api2/endpoints/share_link_zip_task.py
@@ -1,6 +1,5 @@
# Copyright (c) 2012-2016 Seafile Ltd.
import logging
-import stat
import os
import json
import posixpath
@@ -10,7 +9,6 @@ from rest_framework.views import APIView
from rest_framework import status
from django.conf import settings
-from django.utils.translation import gettext as _
from seahub.api2.throttling import UserRateThrottle
from seahub.api2.utils import api_error
@@ -22,11 +20,11 @@ from seahub.utils import is_windows_operating_system, is_pro_version, \
from seahub.utils.repo import parse_repo_perm
from seahub.settings import ENABLE_SHARE_LINK_AUDIT, SHARE_LINK_LOGIN_REQUIRED
-import seaserv
from seaserv import seafile_api
logger = logging.getLogger(__name__)
+
class ShareLinkZipTaskView(APIView):
throttle_classes = (UserRateThrottle,)
@@ -66,6 +64,12 @@ class ShareLinkZipTaskView(APIView):
error_msg = 'share_link_token %s not found.' % share_link_token
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
+ # check share link password
+ if fileshare.is_encrypted() and not check_share_link_access(request,
+ share_link_token):
+ error_msg = 'Permission denied.'
+ return api_error(status.HTTP_403_FORBIDDEN, error_msg)
+
if req_path[-1] != '/':
req_path += '/'
@@ -94,8 +98,7 @@ class ShareLinkZipTaskView(APIView):
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
# get file server access token
- dir_name = repo.name if real_path == '/' else \
- os.path.basename(real_path.rstrip('/'))
+ dir_name = repo.name if real_path == '/' else os.path.basename(real_path.rstrip('/'))
is_windows = 0
if is_windows_operating_system(request):
@@ -155,7 +158,7 @@ class ShareLinkZipTaskView(APIView):
# resource check
try:
- share_link= FileShare.objects.get(token=share_link_token)
+ share_link = FileShare.objects.get(token=share_link_token)
except FileShare.DoesNotExist:
error_msg = 'Share link %s not found.' % share_link_token
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
@@ -171,7 +174,7 @@ class ShareLinkZipTaskView(APIView):
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
full_parent_dir = posixpath.join(normalize_dir_path(share_link.path),
- parent_dir.strip('/'))
+ parent_dir.strip('/'))
full_parent_dir = normalize_dir_path(full_parent_dir)
dir_id = seafile_api.get_dir_id_by_path(repo_id, full_parent_dir)
if not dir_id:
@@ -194,7 +197,7 @@ class ShareLinkZipTaskView(APIView):
# check share link password
if share_link.is_encrypted() and not check_share_link_access(request,
- share_link_token):
+ share_link_token):
error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
diff --git a/seahub/api2/endpoints/share_links.py b/seahub/api2/endpoints/share_links.py
index 92aaeea9c4..9c3c3f1d43 100644
--- a/seahub/api2/endpoints/share_links.py
+++ b/seahub/api2/endpoints/share_links.py
@@ -459,6 +459,71 @@ class ShareLinks(APIView):
link_info = get_share_link_info(fs)
return Response(link_info)
+ def delete(self, request):
+ """ Delete share links.
+
+ Permission checking:
+ 1. default(NOT guest) user;
+ 2. link owner;
+ """
+
+ token_list = request.data.get('tokens')
+ if not token_list:
+ error_msg = 'token invalid.'
+ return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
+
+ result = {}
+ result['failed'] = []
+ result['success'] = []
+
+ username = request.user.username
+ for token in token_list:
+
+ try:
+ fs = FileShare.objects.get(token=token)
+ except FileShare.DoesNotExist:
+ result['success'].append({
+ 'token': token,
+ })
+ continue
+
+ has_published_library = False
+ if fs.path == '/':
+ try:
+ Wiki.objects.get(repo_id=fs.repo_id)
+ has_published_library = True
+ except Wiki.DoesNotExist:
+ pass
+
+ if not fs.is_owner(username):
+ result['failed'].append({
+ 'token': token,
+ 'error_msg': 'Permission denied.'
+ })
+ continue
+
+ if has_published_library:
+ result['failed'].append({
+ 'token': token,
+ 'error_msg': _('There is an associated published library.')
+ })
+ continue
+
+ try:
+ fs.delete()
+ result['success'].append({
+ 'token': token,
+ })
+ except Exception as e:
+ logger.error(e)
+ result['failed'].append({
+ 'token': token,
+ 'error_msg': 'Internal Server Error'
+ })
+ continue
+
+ return Response(result)
+
class ShareLink(APIView):
diff --git a/seahub/api2/endpoints/upload_links.py b/seahub/api2/endpoints/upload_links.py
index be8f0bb3d9..585efa8a43 100644
--- a/seahub/api2/endpoints/upload_links.py
+++ b/seahub/api2/endpoints/upload_links.py
@@ -461,19 +461,29 @@ class UploadLinkUpload(APIView):
if is_pro_version() and ENABLE_UPLOAD_LINK_VIRUS_CHECK:
check_virus = True
- if check_virus:
- token = seafile_api.get_fileserver_access_token(repo_id,
- obj_id,
- 'upload-link',
- uls.username,
- use_onetime=False,
- check_virus=check_virus)
- else:
- token = seafile_api.get_fileserver_access_token(repo_id,
- obj_id,
- 'upload-link',
- uls.username,
- use_onetime=False)
+ try:
+ if check_virus:
+ token = seafile_api.get_fileserver_access_token(repo_id,
+ obj_id,
+ 'upload-link',
+ uls.username,
+ use_onetime=False,
+ check_virus=check_virus)
+ else:
+ token = seafile_api.get_fileserver_access_token(repo_id,
+ obj_id,
+ 'upload-link',
+ uls.username,
+ use_onetime=False)
+ except Exception as e:
+ if str(e) == 'Too many files in library.':
+ error_msg = _("The number of files in library exceeds the limit")
+ from seahub.api2.views import HTTP_442_TOO_MANY_FILES_IN_LIBRARY
+ return api_error(HTTP_442_TOO_MANY_FILES_IN_LIBRARY, error_msg)
+ else:
+ logger.error(e)
+ error_msg = 'Internal Server Error'
+ return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
if not token:
error_msg = 'Internal Server Error'
diff --git a/seahub/api2/endpoints/wikis.py b/seahub/api2/endpoints/wikis.py
index 7b39cc45ce..ce174e55b0 100644
--- a/seahub/api2/endpoints/wikis.py
+++ b/seahub/api2/endpoints/wikis.py
@@ -127,10 +127,15 @@ class WikisView(APIView):
if not seafile_api.get_file_id_by_path(repo_id, "/" + page_name):
try:
seafile_api.post_empty_file(repo_id, '/', page_name, username)
- except SearpcError as e:
- logger.error(e)
- msg = 'Internal Server Error'
- return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, msg)
+ except Exception as e:
+ if str(e) == 'Too many files in library.':
+ error_msg = _("The number of files in library exceeds the limit")
+ from seahub.api2.views import HTTP_442_TOO_MANY_FILES_IN_LIBRARY
+ return api_error(HTTP_442_TOO_MANY_FILES_IN_LIBRARY, error_msg)
+ else:
+ logger.error(e)
+ error_msg = 'Internal Server Error'
+ return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
fs = FileShare.objects.get_dir_link_by_path(username, repo_id, '/')
if not fs:
diff --git a/seahub/api2/views.py b/seahub/api2/views.py
index bade85992f..4215417b0f 100644
--- a/seahub/api2/views.py
+++ b/seahub/api2/views.py
@@ -147,6 +147,7 @@ json_content_type = 'application/json; charset=utf-8'
# Define custom HTTP status code. 4xx starts from 440, 5xx starts from 520.
HTTP_440_REPO_PASSWD_REQUIRED = 440
HTTP_441_REPO_PASSWD_MAGIC_REQUIRED = 441
+HTTP_442_TOO_MANY_FILES_IN_LIBRARY = 442
HTTP_443_ABOVE_QUOTA = 443
HTTP_520_OPERATION_FAILED = 520
@@ -1853,12 +1854,22 @@ class UploadLinkView(APIView):
return api_error(HTTP_443_ABOVE_QUOTA, _("Out of quota."))
obj_id = json.dumps({'parent_dir': parent_dir})
- token = seafile_api.get_fileserver_access_token(repo_id,
- obj_id, 'upload', request.user.username, use_onetime=False)
+ try:
+ token = seafile_api.get_fileserver_access_token(repo_id,
+ obj_id, 'upload', request.user.username, use_onetime=False)
+ except Exception as e:
+ if str(e) == 'Too many files in library.':
+ error_msg = _("The number of files in library exceeds the limit")
+ return api_error(HTTP_442_TOO_MANY_FILES_IN_LIBRARY, error_msg)
+ else:
+ logger.error(e)
+ error_msg = 'Internal Server Error'
+ return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
if not token:
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
+
req_from = request.GET.get('from', 'api')
if req_from == 'api':
try:
diff --git a/seahub/auth/__init__.py b/seahub/auth/__init__.py
index a1ea5ca7f0..1e5e4a918e 100644
--- a/seahub/auth/__init__.py
+++ b/seahub/auth/__init__.py
@@ -73,6 +73,15 @@ def login(request, user):
# TODO: It would be nice to support different login methods, like signed cookies.
user.last_login = datetime.datetime.now()
+ # After each ADFS/SAML single sign-on is completed, `_saml2_subject_id` will be recorded in the session,
+ # so that to distinguish ADFS/SAML users and local users when logging out.
+ # Therefore, every time login, try to delete `_saml2_subject_id` from the session
+ # to ensure that `_saml2_subject_id` is brand new and will not interfere with other users' logout.
+ try:
+ del request.saml_session['_saml2_subject_id']
+ except:
+ pass
+
if SESSION_KEY in request.session:
if request.session[SESSION_KEY] != user.username:
# To avoid reusing another user's session, create a new, empty
diff --git a/seahub/auth/views.py b/seahub/auth/views.py
index db2d753b36..cc3d19504b 100644
--- a/seahub/auth/views.py
+++ b/seahub/auth/views.py
@@ -476,14 +476,21 @@ def multi_adfs_sso(request):
try:
org_saml_config = OrgSAMLConfig.objects.get_config_by_domain(domain)
+ if not org_saml_config:
+ render_data['error_msg'] = "Cannot find a SAML/ADFS config for the organization related to domain %s." % domain
+ return render(request, template_name, render_data)
org_id = org_saml_config.org_id
org = ccnet_api.get_org_by_id(org_id)
+ if not org:
+ render_data['error_msg'] = 'Cannot find an organization related to domain %s.' % domain
+ return render(request, template_name, render_data)
+ url_prefix = org.url_prefix
except Exception as e:
logger.error(e)
render_data['error_msg'] = 'Error, please contact administrator.'
return render(request, template_name, render_data)
- return HttpResponseRedirect('/org/custom/%s/saml2/login/' % org.url_prefix)
+ return HttpResponseRedirect('/org/custom/%s/saml2/login/' % url_prefix)
if request.method == "GET":
return render(request, template_name, render_data)
diff --git a/seahub/notifications/management/commands/send_notices.py b/seahub/notifications/management/commands/send_notices.py
index 41db1ca1b7..7573a573bc 100644
--- a/seahub/notifications/management/commands/send_notices.py
+++ b/seahub/notifications/management/commands/send_notices.py
@@ -217,6 +217,43 @@ class Command(BaseCommand):
notice.avatar_src = self.get_avatar_src(notice.to_user)
return notice
+ def format_repo_monitor_msg(self, notice):
+
+ d = json.loads(notice.detail)
+
+ op_user_email = d['op_user']
+ notice.user_url = reverse('user_profile', args=[op_user_email])
+ notice.user_name = email2nickname(op_user_email)
+ notice.avatar_src = self.get_avatar_src(op_user_email)
+
+ notice.op_type = d['op_type']
+
+ repo_id = d['repo_id']
+ repo_name = d['repo_name']
+ notice.repo_url = reverse('lib_view', args=[repo_id, repo_name, ''])
+ notice.repo_name = d['repo_name']
+
+ obj_type = d['obj_type']
+ obj_path_list = d['obj_path_list']
+ notice.obj_type = obj_type
+ notice.obj_path_count = len(obj_path_list)
+ notice.obj_path_count_minus_one = len(obj_path_list) - 1
+ notice.obj_name = os.path.basename(d['obj_path_list'][0])
+
+ old_obj_path_list = d.get('old_obj_path_list', [])
+ if old_obj_path_list:
+ notice.old_obj_name = os.path.basename(d['old_obj_path_list'][0])
+ else:
+ notice.old_obj_name = ''
+
+ if obj_type == 'file':
+ notice.obj_url = reverse('view_lib_file', args=[repo_id, obj_path_list[0]])
+ else:
+ notice.obj_url = reverse('lib_view',
+ args=[repo_id, repo_name, obj_path_list[0].strip('/')])
+
+ return notice
+
def get_user_language(self, username):
return Profile.objects.get_user_language(username)
@@ -347,6 +384,9 @@ class Command(BaseCommand):
elif notice.is_deleted_files_msg():
notice = self.format_deleted_files_msg(notice)
+ elif notice.is_repo_monitor_msg():
+ notice = self.format_repo_monitor_msg(notice)
+
if notice is None:
continue
@@ -354,6 +394,7 @@ class Command(BaseCommand):
if not notices:
continue
+
user_name = email2nickname(to_user)
contact_email = Profile.objects.get_contact_email_by_user(to_user)
c = {
@@ -368,8 +409,7 @@ class Command(BaseCommand):
'notifications/notice_email.html', c,
None, [contact_email])
# set new last_emailed_time
- UserOptions.objects.set_collaborate_last_emailed_time(
- to_user, now)
+ UserOptions.objects.set_collaborate_last_emailed_time(to_user, now)
logger.info('Successfully sent email to %s' % contact_email)
self.stdout.write('[%s] Successfully sent email to %s' % (str(datetime.datetime.now()), contact_email))
except Exception as e:
diff --git a/seahub/notifications/templates/notifications/notice_email.html b/seahub/notifications/templates/notifications/notice_email.html
index 10b970ddca..8dd41cc100 100644
--- a/seahub/notifications/templates/notifications/notice_email.html
+++ b/seahub/notifications/templates/notifications/notice_email.html
@@ -65,6 +65,69 @@ You've got {{num}} new notices on {{ site_name }}:
{% elif notice.is_deleted_files_msg %}
{% blocktrans with repo_url=notice.repo_url repo_name=notice.repo_name %}Your library {{ repo_name }} has recently deleted a large number of files.{% endblocktrans %}
+ {% elif notice.is_repo_monitor_msg %}
+
+ {% if notice.obj_type == 'file' %}
+ {% if notice.op_type == 'create' %}
+ {% if notice.obj_path_count == 1 %}
+ {% blocktrans with user_url=notice.user_url user_name=notice.user_name obj_url=notice.obj_url obj_name=notice.obj_name repo_url=notice.repo_url repo_name=notice.repo_name %} User {{user_name}} created file {{obj_name}} in library {{repo_name}}.{% endblocktrans %}
+ {% else %}
+ {% blocktrans with user_url=notice.user_url user_name=notice.user_name obj_url=notice.obj_url obj_name=notice.obj_name repo_url=notice.repo_url repo_name=notice.repo_name obj_path_count_minus_one=notice.obj_path_count_minus_one %} User {{user_name}} created file {{obj_name}} and {{ obj_path_count_minus_one }} other file(s) in library {{repo_name}}.{% endblocktrans %}
+ {% endif %}
+ {% endif %}
+ {% if notice.op_type == 'delete' %}
+ {% if notice.obj_path_count == 1 %}
+ {% blocktrans with user_url=notice.user_url user_name=notice.user_name obj_url=notice.obj_url obj_name=notice.obj_name repo_url=notice.repo_url repo_name=notice.repo_name %} User {{user_name}} deleted file {{obj_name}} in library {{repo_name}}.{% endblocktrans %}
+ {% else %}
+ {% blocktrans with user_url=notice.user_url user_name=notice.user_name obj_url=notice.obj_url obj_name=notice.obj_name repo_url=notice.repo_url repo_name=notice.repo_name obj_path_count_minus_one=notice.obj_path_count_minus_one %} User {{user_name}} deleted file {{obj_name}} and {{ obj_path_count_minus_one }} other file(s) in library {{repo_name}}.{% endblocktrans %}
+ {% endif %}
+ {% endif %}
+ {% if notice.op_type == 'recover' %}
+ {% blocktrans with user_url=notice.user_url user_name=notice.user_name obj_url=notice.obj_url obj_name=notice.obj_name repo_url=notice.repo_url repo_name=notice.repo_name %} User {{user_name}} restored file {{obj_name}} in library {{repo_name}}.{% endblocktrans %}
+ {% endif %}
+ {% if notice.op_type == 'rename' %}
+ {% blocktrans with user_url=notice.user_url user_name=notice.user_name obj_url=notice.obj_url obj_name=notice.obj_name repo_url=notice.repo_url repo_name=notice.repo_name old_obj_name=notice.old_obj_name %} User {{user_name}} renamed file {{old_obj_name}} to {{obj_name}} in library {{repo_name}}.{% endblocktrans %}
+ {% endif %}
+ {% if notice.op_type == 'move' %}
+ {% if notice.obj_path_count == 1 %}
+ {% blocktrans with user_url=notice.user_url user_name=notice.user_name obj_url=notice.obj_url obj_name=notice.obj_name repo_url=notice.repo_url repo_name=notice.repo_name %} User {{user_name}} moved file {{obj_name}} in library {{repo_name}}.{% endblocktrans %}
+ {% else %}
+ {% blocktrans with user_url=notice.user_url user_name=notice.user_name obj_url=notice.obj_url obj_name=notice.obj_name repo_url=notice.repo_url repo_name=notice.repo_name obj_path_count_minus_one=notice.obj_path_count_minus_one %} User {{user_name}} moved file {{obj_name}} and {{ obj_path_count_minus_one }} other file(s) in library {{repo_name}}.{% endblocktrans %}
+ {% endif %}
+ {% endif %}
+ {% if notice.op_type == 'edit' %}
+ {% blocktrans with user_url=notice.user_url user_name=notice.user_name obj_url=notice.obj_url obj_name=notice.obj_name repo_url=notice.repo_url repo_name=notice.repo_name %} User {{user_name}} updated file {{obj_name}} in library {{repo_name}}.{% endblocktrans %}
+ {% endif %}
+ {% else %}
+ {% if notice.op_type == 'create' %}
+ {% if notice.obj_path_count == 1 %}
+ {% blocktrans with user_url=notice.user_url user_name=notice.user_name obj_url=notice.obj_url obj_name=notice.obj_name repo_url=notice.repo_url repo_name=notice.repo_name %} User {{user_name}} created folder {{obj_name}} in library {{repo_name}}.{% endblocktrans %}
+ {% else %}
+ {% blocktrans with user_url=notice.user_url user_name=notice.user_name obj_url=notice.obj_url obj_name=notice.obj_name repo_url=notice.repo_url repo_name=notice.repo_name obj_path_count_minus_one=notice.obj_path_count_minus_one %} User {{user_name}} created folder {{obj_name}} and {{ obj_path_count_minus_one }} other folder(s) in library {{repo_name}}.{% endblocktrans %}
+ {% endif %}
+ {% endif %}
+ {% if notice.op_type == 'delete' %}
+ {% if notice.obj_path_count == 1 %}
+ {% blocktrans with user_url=notice.user_url user_name=notice.user_name obj_url=notice.obj_url obj_name=notice.obj_name repo_url=notice.repo_url repo_name=notice.repo_name %} User {{user_name}} deleted folder {{obj_name}} in library {{repo_name}}.{% endblocktrans %}
+ {% else %}
+ {% blocktrans with user_url=notice.user_url user_name=notice.user_name obj_url=notice.obj_url obj_name=notice.obj_name repo_url=notice.repo_url repo_name=notice.repo_name obj_path_count_minus_one=notice.obj_path_count_minus_one %} User {{user_name}} deleted folder {{obj_name}} and {{ obj_path_count_minus_one }} other folder(s) in library {{repo_name}}.{% endblocktrans %}
+ {% endif %}
+ {% endif %}
+ {% if notice.op_type == 'recover' %}
+ {% blocktrans with user_url=notice.user_url user_name=notice.user_name obj_url=notice.obj_url obj_name=notice.obj_name repo_url=notice.repo_url repo_name=notice.repo_name %} User {{user_name}} restored folder {{obj_name}} in library {{repo_name}}.{% endblocktrans %}
+ {% endif %}
+ {% if notice.op_type == 'rename' %}
+ {% blocktrans with user_url=notice.user_url user_name=notice.user_name obj_url=notice.obj_url obj_name=notice.obj_name repo_url=notice.repo_url repo_name=notice.repo_name old_obj_name=notice.old_obj_name %} User {{user_name}} renamed folder {{old_obj_name}} to {{obj_name}} in library {{repo_name}}.{% endblocktrans %}
+ {% endif %}
+ {% if notice.op_type == 'move' %}
+ {% if notice.obj_path_count == 1 %}
+ {% blocktrans with user_url=notice.user_url user_name=notice.user_name obj_url=notice.obj_url obj_name=notice.obj_name repo_url=notice.repo_url repo_name=notice.repo_name %} User {{user_name}} moved folder {{obj_name}} in library {{repo_name}}.{% endblocktrans %}
+ {% else %}
+ {% blocktrans with user_url=notice.user_url user_name=notice.user_name obj_url=notice.obj_url obj_name=notice.obj_name repo_url=notice.repo_url repo_name=notice.repo_name obj_path_count_minus_one=notice.obj_path_count_minus_one %} User {{user_name}} moved folder {{obj_name}} and {{ obj_path_count_minus_one }} other folder(s) in library {{repo_name}}.{% endblocktrans %}
+ {% endif %}
+ {% endif %}
+ {% endif %}
+
{% endif %}
{{ notice.timestamp|date:"Y-m-d G:i:s"}}
diff --git a/seahub/organizations/views.py b/seahub/organizations/views.py
index 3b3d93daa1..b7fbd8943d 100644
--- a/seahub/organizations/views.py
+++ b/seahub/organizations/views.py
@@ -154,7 +154,7 @@ def gen_org_url_prefix(max_trial=None):
Url prefix if succed, otherwise, ``None``.
"""
def _gen_prefix():
- url_prefix = 'org_' + get_random_string(
+ url_prefix = 'org-' + get_random_string(
6, allowed_chars='abcdefghijklmnopqrstuvwxyz0123456789')
if get_org_by_url_prefix(url_prefix) is not None:
logger.info("org url prefix, %s is duplicated" % url_prefix)