@@ -190,7 +236,17 @@ class Item extends Component {
-
+ |
+
+
}
+ {isConfirmInactiveDialogOpen &&
+
+ }
);
}
@@ -221,6 +286,7 @@ class Item extends Component {
Item.propTypes = {
item: PropTypes.object.isRequired,
updateRole: PropTypes.func.isRequired,
+ updateStatus: PropTypes.func.isRequired,
deleteOrg: PropTypes.func.isRequired,
isItemFreezed: PropTypes.bool.isRequired,
toggleItemFreezed: PropTypes.func.isRequired
diff --git a/frontend/src/pages/sys-admin/orgs/orgs.js b/frontend/src/pages/sys-admin/orgs/orgs.js
index 026bbda294..f80057dbb2 100644
--- a/frontend/src/pages/sys-admin/orgs/orgs.js
+++ b/frontend/src/pages/sys-admin/orgs/orgs.js
@@ -66,6 +66,24 @@ class Orgs extends Component {
this.setState({ isAddOrgDialogOpen: !this.state.isAddOrgDialogOpen });
};
+ updateStatus = (orgID, isActive) => {
+ let orgInfo = {};
+ orgInfo.isActive = isActive;
+ systemAdminAPI.sysAdminUpdateOrg(orgID, orgInfo).then(res => {
+ let newOrgList = this.state.orgList.map(org => {
+ if (org.org_id == orgID) {
+ org.is_active = isActive;
+ }
+ return org;
+ });
+ this.setState({ orgList: newOrgList });
+ toaster.success(gettext('Edit succeeded'));
+ }).catch((error) => {
+ let errMessage = Utils.getErrorMsg(error);
+ toaster.danger(errMessage);
+ });
+ };
+
updateRole = (orgID, role) => {
let orgInfo = {};
orgInfo.role = role;
@@ -143,6 +161,7 @@ class Orgs extends Component {
resetPerPage={this.resetPerPage}
getListByPage={this.getItemsByPage}
updateRole={this.updateRole}
+ updateStatus={this.updateStatus}
deleteOrg={this.deleteOrg}
/>
diff --git a/frontend/src/utils/system-admin-api.js b/frontend/src/utils/system-admin-api.js
index 7403955d7d..47579f8038 100644
--- a/frontend/src/utils/system-admin-api.js
+++ b/frontend/src/utils/system-admin-api.js
@@ -608,6 +608,9 @@ class SystemAdminAPI {
if (orgInfo.role) {
formData.append('role', orgInfo.role);
}
+ if (orgInfo.isActive != undefined) {
+ formData.append('is_active', orgInfo.isActive);
+ }
return this.req.put(url, formData);
}
diff --git a/media/img/organization-inactive.png b/media/img/organization-inactive.png
new file mode 100644
index 0000000000..9ab8718f01
Binary files /dev/null and b/media/img/organization-inactive.png differ
diff --git a/seahub/api2/endpoints/admin/organizations.py b/seahub/api2/endpoints/admin/organizations.py
index 173129eb9f..85b86af096 100644
--- a/seahub/api2/endpoints/admin/organizations.py
+++ b/seahub/api2/endpoints/admin/organizations.py
@@ -29,7 +29,7 @@ from seahub.organizations.models import OrgSAMLConfig
try:
from seahub.settings import ORG_MEMBER_QUOTA_ENABLED
except ImportError:
- ORG_MEMBER_QUOTA_ENABLED= False
+ ORG_MEMBER_QUOTA_ENABLED = False
if ORG_MEMBER_QUOTA_ENABLED:
from seahub.organizations.models import OrgMemberQuota
@@ -47,6 +47,7 @@ except ImportError:
logger = logging.getLogger(__name__)
+
def get_org_info(org):
org_id = org.org_id
@@ -56,6 +57,7 @@ def get_org_info(org):
org_info['ctime'] = timestamp_to_isoformat_timestr(org.ctime)
org_info['org_url_prefix'] = org.url_prefix
org_info['role'] = OrgSettings.objects.get_role_by_org(org)
+ org_info['is_active'] = OrgSettings.objects.get_is_active_by_org(org)
creator = org.creator
org_info['creator_email'] = creator
@@ -70,7 +72,9 @@ def get_org_info(org):
return org_info
+
def get_org_detailed_info(org):
+
org_id = org.org_id
org_info = get_org_info(org)
@@ -99,6 +103,7 @@ def get_org_detailed_info(org):
return org_info
+
def gen_org_url_prefix(max_trial=None, length=20):
"""Generate organization url prefix automatically.
If ``max_trial`` is large than 0, then re-try that times if failed.
@@ -234,7 +239,7 @@ class AdminOrganizations(APIView):
logger.error(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
-
+
quota = request.data.get('quota', None)
if quota:
try:
@@ -244,7 +249,7 @@ class AdminOrganizations(APIView):
except ValueError as e:
logger.error(e)
return api_error(status.HTTP_400_BAD_REQUEST, "Quota is not valid")
-
+
if ORG_MEMBER_QUOTA_ENABLED:
member_limit = request.data.get('member_limit', ORG_MEMBER_QUOTA_DEFAULT)
OrgMemberQuota.objects.set_quota(org_id, member_limit)
@@ -367,7 +372,6 @@ class AdminOrganization(APIView):
error_msg = 'quota invalid.'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
-
quota = quota_mb * get_file_size_unit('MB')
try:
seafile_api.set_org_quota(org_id, quota)
@@ -384,6 +388,15 @@ class AdminOrganization(APIView):
OrgSettings.objects.add_or_update(org, role)
+ is_active = request.data.get('is_active', None)
+ if is_active:
+ is_active = is_active.lower()
+ if is_active not in ('true', 'false'):
+ error_msg = 'is_active invalid.'
+ return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
+
+ OrgSettings.objects.add_or_update(org, is_active=is_active == 'true')
+
org = ccnet_api.get_org_by_id(org_id)
org_info = get_org_info(org)
return Response(org_info)
@@ -493,14 +506,14 @@ class AdminOrganizationsBaseInfo(APIView):
error_msg = 'Feature is not enabled.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
- org_ids = request.GET.getlist('org_ids',[])
+ org_ids = request.GET.getlist('org_ids', [])
orgs = []
for org_id in org_ids:
try:
org = ccnet_api.get_org_by_id(int(org_id))
if not org:
continue
- except:
+ except Exception:
continue
base_info = {'org_id': org.org_id, 'org_name': org.org_name}
orgs.append(base_info)
diff --git a/seahub/base/middleware.py b/seahub/base/middleware.py
index 708e7b53f7..6209760155 100644
--- a/seahub/base/middleware.py
+++ b/seahub/base/middleware.py
@@ -1,17 +1,23 @@
# Copyright (c) 2012-2016 Seafile Ltd.
import re
-from django.utils.deprecation import MiddlewareMixin
-from django.core.cache import cache
+from rest_framework import status
from django.urls import reverse
+from django.core.cache import cache
from django.http import HttpResponseRedirect
+from django.utils.translation import gettext as _
+from django.utils.deprecation import MiddlewareMixin
from seaserv import ccnet_api
+from seahub.auth import logout
+from seahub.utils import render_error
+from seahub.organizations.models import OrgSettings
from seahub.notifications.models import Notification
from seahub.notifications.utils import refresh_cache
-from seahub.constants import DEFAULT_ADMIN
+from seahub.api2.utils import api_error
+from seahub.settings import SITE_ROOT, SUPPORT_EMAIL
try:
from seahub.settings import CLOUD_MODE
except ImportError:
@@ -20,7 +26,7 @@ try:
from seahub.settings import MULTI_TENANCY
except ImportError:
MULTI_TENANCY = False
-from seahub.settings import SITE_ROOT
+
class BaseMiddleware(MiddlewareMixin):
"""
@@ -38,6 +44,16 @@ class BaseMiddleware(MiddlewareMixin):
orgs = ccnet_api.get_orgs_by_user(username)
if orgs:
request.user.org = orgs[0]
+ if not OrgSettings.objects.get_is_active_by_org(request.user.org):
+ org_name = request.user.org.org_name
+ error_msg = _(f"Team {org_name} is inactive.")
+ if SUPPORT_EMAIL:
+ error_msg += " " + _(f"Please contact {SUPPORT_EMAIL} if you want to activate the team.")
+ logout(request)
+ if "api2/" in request.path or "api/v2.1/" in request.path:
+ return api_error(status.HTTP_403_FORBIDDEN, error_msg)
+ return render_error(request, error_msg, {"organization_inactive": True})
+
else:
request.cloud_mode = False
@@ -46,6 +62,7 @@ class BaseMiddleware(MiddlewareMixin):
def process_response(self, request, response):
return response
+
class InfobarMiddleware(MiddlewareMixin):
"""Query info bar close status, and store into request."""
@@ -99,6 +116,7 @@ class ForcePasswdChangeMiddleware(MiddlewareMixin):
if self._request_in_black_list(request):
return HttpResponseRedirect(reverse('auth_password_change'))
+
class UserAgentMiddleWare(MiddlewareMixin):
user_agents_test_match = (
"w3c ", "acs-", "alav", "alca", "amoi", "audi",
@@ -151,7 +169,7 @@ class UserAgentMiddleWare(MiddlewareMixin):
# Test common mobile values.
if self.user_agents_test_search_regex.search(user_agent) and \
- not self.user_agents_exception_search_regex.search(user_agent):
+ not self.user_agents_exception_search_regex.search(user_agent):
is_mobile = True
else:
# Nokia like test for WAP browsers.
diff --git a/seahub/organizations/migrations/0002_orgsettings_is_active.py b/seahub/organizations/migrations/0002_orgsettings_is_active.py
new file mode 100644
index 0000000000..6b979f8d7c
--- /dev/null
+++ b/seahub/organizations/migrations/0002_orgsettings_is_active.py
@@ -0,0 +1,18 @@
+# Generated by Django 4.2.16 on 2025-01-16 04:07
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('organizations', '0001_initial'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='orgsettings',
+ name='is_active',
+ field=models.BooleanField(db_index=True, default=False),
+ ),
+ ]
diff --git a/seahub/organizations/models.py b/seahub/organizations/models.py
index 4d2556a506..116aa1a22f 100644
--- a/seahub/organizations/models.py
+++ b/seahub/organizations/models.py
@@ -18,7 +18,9 @@ FORCE_ADFS_LOGIN = 'force_adfs_login'
DISABLE_ORG_USER_CLEAN_TRASH = 'disable_org_user_clean_trash'
DISABLE_ORG_ENCRYPTED_LIBRARY = 'disable_org_encrypted_library'
+
class OrgMemberQuotaManager(models.Manager):
+
def get_quota(self, org_id):
try:
return self.get(org_id=org_id).quota
@@ -63,7 +65,15 @@ class OrgSettingsManager(models.Manager):
logger.warning('Role %s is not valid' % role)
return DEFAULT_ORG
- def add_or_update(self, org, role=None):
+ def get_is_active_by_org(self, org):
+ org_id = org.org_id
+ try:
+ is_active = self.get(org_id=org_id).is_active
+ return is_active
+ except OrgSettings.DoesNotExist:
+ return True
+
+ def add_or_update(self, org, role=None, is_active=None):
org_id = org.org_id
try:
settings = self.get(org_id=org_id)
@@ -76,6 +86,9 @@ class OrgSettingsManager(models.Manager):
else:
logger.warning('Role %s is not valid' % role)
+ if is_active is not None:
+ settings.is_active = is_active
+
settings.save(using=self._db)
return settings
@@ -83,6 +96,7 @@ class OrgSettingsManager(models.Manager):
class OrgSettings(models.Model):
org_id = models.IntegerField(unique=True)
role = models.CharField(max_length=100, null=True, blank=True)
+ is_active = models.BooleanField(default=False, db_index=True)
objects = OrgSettingsManager()
diff --git a/seahub/settings.py b/seahub/settings.py
index 081f3d42a0..d99bed648b 100644
--- a/seahub/settings.py
+++ b/seahub/settings.py
@@ -504,6 +504,7 @@ ENABLE_SHOW_ABOUT = True
# enable show wechat support
SHOW_WECHAT_SUPPORT_GROUP = False
+SUPPORT_EMAIL = ''
# File preview
FILE_PREVIEW_MAX_SIZE = 30 * 1024 * 1024
diff --git a/seahub/templates/error.html b/seahub/templates/error.html
index c07fcb367d..c93c2c546f 100644
--- a/seahub/templates/error.html
+++ b/seahub/templates/error.html
@@ -5,6 +5,9 @@
{% if unable_view_file %}
{{ error_msg }}
+ {% elif organization_inactive %}
+
+ {{ error_msg }}
{% else %}
{{ error_msg }}
{% endif %}
|