mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-23 12:27:48 +00:00
Org reactivate (#7925)
* org reactivate * update * update * update * remove print
This commit is contained in:
@@ -186,6 +186,9 @@ class Item extends Component {
|
|||||||
case 'default':
|
case 'default':
|
||||||
translateResult = gettext('Default');
|
translateResult = gettext('Default');
|
||||||
break;
|
break;
|
||||||
|
case 'org':
|
||||||
|
translateResult = gettext('Organization');
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return translateResult;
|
return translateResult;
|
||||||
};
|
};
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
# Copyright (c) 2012-2016 Seafile Ltd.
|
# Copyright (c) 2012-2016 Seafile Ltd.
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
from django.utils.translation import gettext as _
|
||||||
from django.utils.crypto import get_random_string
|
from django.utils.crypto import get_random_string
|
||||||
|
|
||||||
from rest_framework.authentication import SessionAuthentication
|
from rest_framework.authentication import SessionAuthentication
|
||||||
@@ -12,8 +13,10 @@ from rest_framework import status
|
|||||||
from seaserv import ccnet_api, seafile_api
|
from seaserv import ccnet_api, seafile_api
|
||||||
|
|
||||||
from seahub.auth.utils import get_virtual_id_by_email
|
from seahub.auth.utils import get_virtual_id_by_email
|
||||||
from seahub.organizations.settings import ORG_MEMBER_QUOTA_DEFAULT
|
from seahub.organizations.settings import ORG_MEMBER_QUOTA_DEFAULT, \
|
||||||
from seahub.utils import is_valid_email
|
ORG_ENABLE_REACTIVATE
|
||||||
|
from seahub.organizations.utils import generate_org_reactivate_link
|
||||||
|
from seahub.utils import is_valid_email, IS_EMAIL_CONFIGURED, send_html_email
|
||||||
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, datetime_to_isoformat_timestr
|
from seahub.utils.timeutils import timestamp_to_isoformat_timestr, datetime_to_isoformat_timestr
|
||||||
from seahub.base.templatetags.seahub_tags import email2nickname, \
|
from seahub.base.templatetags.seahub_tags import email2nickname, \
|
||||||
@@ -182,7 +185,7 @@ class AdminOrganizations(APIView):
|
|||||||
result = []
|
result = []
|
||||||
org_ids = [org.org_id for org in orgs]
|
org_ids = [org.org_id for org in orgs]
|
||||||
orgs_last_activity = OrgLastActivityTime.objects.filter(org_id__in=org_ids)
|
orgs_last_activity = OrgLastActivityTime.objects.filter(org_id__in=org_ids)
|
||||||
orgs_last_activity_dict = {org.org_id:org.timestamp for org in orgs_last_activity}
|
orgs_last_activity_dict = {org.org_id: org.timestamp for org in orgs_last_activity}
|
||||||
for org in orgs:
|
for org in orgs:
|
||||||
org_info = get_org_info(org)
|
org_info = get_org_info(org)
|
||||||
org_id = org_info['org_id']
|
org_id = org_info['org_id']
|
||||||
@@ -408,6 +411,23 @@ class AdminOrganization(APIView):
|
|||||||
|
|
||||||
OrgSettings.objects.add_or_update(org, is_active=is_active == 'true')
|
OrgSettings.objects.add_or_update(org, is_active=is_active == 'true')
|
||||||
|
|
||||||
|
if is_active == 'false' and IS_EMAIL_CONFIGURED and ORG_ENABLE_REACTIVATE:
|
||||||
|
|
||||||
|
subject = _(f'Your team {org.org_name} has been deactivated')
|
||||||
|
email_template = 'organizations/org_deactivate_email.html'
|
||||||
|
from_email = None
|
||||||
|
|
||||||
|
org_users = ccnet_api.get_org_emailusers(org.url_prefix, -1, -1)
|
||||||
|
org_admin_users = [org_user.email for org_user in org_users
|
||||||
|
if ccnet_api.is_org_staff(org_id, org_user.email)]
|
||||||
|
for email in org_admin_users:
|
||||||
|
con_context = {
|
||||||
|
'org_name': org.org_name,
|
||||||
|
'reactivate_link': generate_org_reactivate_link(org_id)
|
||||||
|
}
|
||||||
|
send_html_email(subject, email_template, con_context,
|
||||||
|
from_email, [email2contact_email(email)])
|
||||||
|
|
||||||
org = ccnet_api.get_org_by_id(org_id)
|
org = ccnet_api.get_org_by_id(org_id)
|
||||||
org_info = get_org_info(org)
|
org_info = get_org_info(org)
|
||||||
return Response(org_info)
|
return Response(org_info)
|
||||||
@@ -517,7 +537,7 @@ class AdminOrganizationsBaseInfo(APIView):
|
|||||||
error_msg = 'Feature is not enabled.'
|
error_msg = 'Feature is not enabled.'
|
||||||
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
|
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
|
||||||
|
|
||||||
org_ids = request.GET.getlist('org_ids',[])
|
org_ids = request.GET.getlist('org_ids', [])
|
||||||
include_org_staffs = to_python_boolean(request.GET.get('include_org_staffs', 'false'))
|
include_org_staffs = to_python_boolean(request.GET.get('include_org_staffs', 'false'))
|
||||||
orgs = []
|
orgs = []
|
||||||
for org_id in org_ids:
|
for org_id in org_ids:
|
||||||
|
@@ -13,11 +13,13 @@ from seaserv import ccnet_api
|
|||||||
from seahub.auth import logout
|
from seahub.auth import logout
|
||||||
from seahub.utils import render_error
|
from seahub.utils import render_error
|
||||||
from seahub.organizations.models import OrgSettings
|
from seahub.organizations.models import OrgSettings
|
||||||
|
from seahub.organizations.utils import generate_org_reactivate_link
|
||||||
from seahub.notifications.models import Notification
|
from seahub.notifications.models import Notification
|
||||||
from seahub.notifications.utils import refresh_cache
|
from seahub.notifications.utils import refresh_cache
|
||||||
from seahub.api2.utils import api_error
|
from seahub.api2.utils import api_error
|
||||||
|
|
||||||
from seahub.settings import SITE_ROOT, SUPPORT_EMAIL
|
from seahub.settings import SITE_ROOT, SUPPORT_EMAIL
|
||||||
|
from seahub.organizations.settings import ORG_ENABLE_REACTIVATE
|
||||||
try:
|
try:
|
||||||
from seahub.settings import CLOUD_MODE
|
from seahub.settings import CLOUD_MODE
|
||||||
except ImportError:
|
except ImportError:
|
||||||
@@ -34,30 +36,47 @@ class BaseMiddleware(MiddlewareMixin):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def process_request(self, request):
|
def process_request(self, request):
|
||||||
|
|
||||||
username = request.user.username
|
username = request.user.username
|
||||||
request.user.org = None
|
request.user.org = None
|
||||||
|
|
||||||
if CLOUD_MODE:
|
# not enable multi-tenancy
|
||||||
request.cloud_mode = True
|
request.cloud_mode = CLOUD_MODE
|
||||||
|
if not CLOUD_MODE or not MULTI_TENANCY:
|
||||||
|
return None
|
||||||
|
|
||||||
if MULTI_TENANCY:
|
# not org user
|
||||||
orgs = ccnet_api.get_orgs_by_user(username)
|
orgs = ccnet_api.get_orgs_by_user(username)
|
||||||
if orgs:
|
if not orgs:
|
||||||
request.user.org = orgs[0]
|
return None
|
||||||
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:
|
# org is active
|
||||||
request.cloud_mode = False
|
request.user.org = orgs[0]
|
||||||
|
if OrgSettings.objects.get_is_active_by_org(request.user.org):
|
||||||
|
return None
|
||||||
|
|
||||||
return None
|
# handle inactive org
|
||||||
|
org_id = request.user.org.org_id
|
||||||
|
org_name = request.user.org.org_name
|
||||||
|
is_org_staff = request.user.org.is_staff
|
||||||
|
logout(request)
|
||||||
|
|
||||||
|
error_msg = _(f"Team {org_name} is inactive.")
|
||||||
|
if "api2/" in request.path or "api/v2.1/" in request.path:
|
||||||
|
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
|
||||||
|
|
||||||
|
extra_ctx = {"organization_inactive": True}
|
||||||
|
|
||||||
|
if ORG_ENABLE_REACTIVATE and is_org_staff:
|
||||||
|
reactivate_link = generate_org_reactivate_link(org_id)
|
||||||
|
extra_ctx["reactivate_link"] = reactivate_link
|
||||||
|
return render_error(request, error_msg, extra_ctx)
|
||||||
|
|
||||||
|
if SUPPORT_EMAIL:
|
||||||
|
contact_msg = _(f"Please contact {SUPPORT_EMAIL} if you want to activate the team.")
|
||||||
|
error_msg = f"{error_msg} {contact_msg}"
|
||||||
|
|
||||||
|
return render_error(request, error_msg, extra_ctx)
|
||||||
|
|
||||||
def process_response(self, request, response):
|
def process_response(self, request, response):
|
||||||
return response
|
return response
|
||||||
|
@@ -41,6 +41,7 @@ class Invitation(models.Model):
|
|||||||
INVITE_TYPE_CHOICES = (
|
INVITE_TYPE_CHOICES = (
|
||||||
(GUEST_USER, 'guest'),
|
(GUEST_USER, 'guest'),
|
||||||
(DEFAULT_USER, 'default'),
|
(DEFAULT_USER, 'default'),
|
||||||
|
('Organization', 'org'),
|
||||||
)
|
)
|
||||||
|
|
||||||
token = models.CharField(max_length=40, db_index=True)
|
token = models.CharField(max_length=40, db_index=True)
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import logging
|
import logging
|
||||||
from seahub.organizations.signals import org_created
|
from seahub.organizations.signals import org_created, org_reactivated
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -12,5 +12,11 @@ try:
|
|||||||
org_created.connect(org_created_callback)
|
org_created.connect(org_created_callback)
|
||||||
except ImportError as e:
|
except ImportError as e:
|
||||||
logger.debug(e)
|
logger.debug(e)
|
||||||
|
|
||||||
|
try:
|
||||||
|
from seahub_custom_functions import org_reactivated_callback
|
||||||
|
org_reactivated.connect(org_reactivated_callback)
|
||||||
|
except ImportError as e:
|
||||||
|
logger.debug(e)
|
||||||
except KeyError as e:
|
except KeyError as e:
|
||||||
logger.debug(e)
|
logger.debug(e)
|
||||||
|
@@ -17,6 +17,8 @@ ORG_ENABLE_ADMIN_INVITE_USER_VIA_WEIXIN = getattr(settings,
|
|||||||
'ORG_ENABLE_ADMIN_INVITE_USER_VIA_WEIXIN',
|
'ORG_ENABLE_ADMIN_INVITE_USER_VIA_WEIXIN',
|
||||||
False)
|
False)
|
||||||
|
|
||||||
|
ORG_ENABLE_REACTIVATE = getattr(settings, 'ORG_ENABLE_REACTIVATE', False)
|
||||||
|
|
||||||
ORG_ENABLE_ADMIN_INVITE_USER = getattr(settings, 'ORG_ENABLE_ADMIN_INVITE_USER', True)
|
ORG_ENABLE_ADMIN_INVITE_USER = getattr(settings, 'ORG_ENABLE_ADMIN_INVITE_USER', True)
|
||||||
ORG_ENABLE_ADMIN_CUSTOM_NAME = getattr(settings, 'ORG_ENABLE_ADMIN_CUSTOM_NAME', True)
|
ORG_ENABLE_ADMIN_CUSTOM_NAME = getattr(settings, 'ORG_ENABLE_ADMIN_CUSTOM_NAME', True)
|
||||||
ORG_ENABLE_ADMIN_CUSTOM_LOGO = getattr(settings, 'ORG_ENABLE_ADMIN_CUSTOM_LOGO', True)
|
ORG_ENABLE_ADMIN_CUSTOM_LOGO = getattr(settings, 'ORG_ENABLE_ADMIN_CUSTOM_LOGO', True)
|
||||||
|
@@ -3,4 +3,5 @@ from django.dispatch import Signal
|
|||||||
|
|
||||||
# A new org is created
|
# A new org is created
|
||||||
org_created = Signal()
|
org_created = Signal()
|
||||||
|
org_reactivated = Signal()
|
||||||
org_last_activity = Signal()
|
org_last_activity = Signal()
|
||||||
|
@@ -0,0 +1,23 @@
|
|||||||
|
{% extends 'email_base.html' %}
|
||||||
|
|
||||||
|
{% load i18n seahub_tags %}
|
||||||
|
|
||||||
|
{% block email_con %}
|
||||||
|
|
||||||
|
{% autoescape off %}
|
||||||
|
|
||||||
|
<p style="color:#121214;font-size:14px;">{% trans "Hi," %}</p>
|
||||||
|
|
||||||
|
<p style="font-size:14px;color:#434144;">
|
||||||
|
{% blocktrans with org_name=org_name %}You are receiving this email because your team {{org_name}} has been deactivated.{% endblocktrans %}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p style="font-size:14px;color:#434144;">
|
||||||
|
{% blocktrans with link=reactivate_link %}
|
||||||
|
If you like to continue using our site, click <a href="{{ link }}">here</a>. Otherwise your account will be deleted in 60 days.
|
||||||
|
{% endblocktrans %}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
{% endautoescape %}
|
||||||
|
|
||||||
|
{% endblock %}
|
@@ -6,6 +6,7 @@ from .views import *
|
|||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('add/', org_add, name='org_add'),
|
path('add/', org_add, name='org_add'),
|
||||||
path('register/', org_register, name='org_register'),
|
path('register/', org_register, name='org_register'),
|
||||||
|
re_path('reactivate/(?P<token>[a-f0-9]{32})/', org_reactivate, name='org_reactivate'),
|
||||||
|
|
||||||
path('statistics-admin/file/', react_fake_view, name='org_statistics_admin_file'),
|
path('statistics-admin/file/', react_fake_view, name='org_statistics_admin_file'),
|
||||||
path('statistics-admin/total-storage/', react_fake_view, name='org_statistics_admin_total_storage'),
|
path('statistics-admin/total-storage/', react_fake_view, name='org_statistics_admin_total_storage'),
|
||||||
|
@@ -2,6 +2,7 @@
|
|||||||
from django.core.cache import cache
|
from django.core.cache import cache
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
|
||||||
|
from seahub.invitations.models import Invitation
|
||||||
from seahub.utils import gen_token, get_service_url
|
from seahub.utils import gen_token, get_service_url
|
||||||
|
|
||||||
|
|
||||||
@@ -38,3 +39,14 @@ def get_or_create_invitation_link(org_id):
|
|||||||
link = '%s/weixin/oauth-login/?next=%s' % (
|
link = '%s/weixin/oauth-login/?next=%s' % (
|
||||||
get_service_url().rstrip('/'), reverse('org_associate', args=[token]))
|
get_service_url().rstrip('/'), reverse('org_associate', args=[token]))
|
||||||
return link
|
return link
|
||||||
|
|
||||||
|
|
||||||
|
def generate_org_reactivate_link(org_id):
|
||||||
|
i = Invitation.objects.add(inviter='Administrator',
|
||||||
|
accepter=org_id,
|
||||||
|
invite_type='org')
|
||||||
|
|
||||||
|
service_url = get_service_url().strip('/')
|
||||||
|
url = reverse('org_reactivate', args=[i.token])
|
||||||
|
url = f'{service_url}{url}'
|
||||||
|
return url
|
||||||
|
@@ -27,7 +27,8 @@ from seahub.profile.models import Profile
|
|||||||
from seahub.utils import get_service_url, render_error
|
from seahub.utils import get_service_url, render_error
|
||||||
from seahub.utils.auth import get_login_bg_image_path
|
from seahub.utils.auth import get_login_bg_image_path
|
||||||
|
|
||||||
from seahub.organizations.signals import org_created
|
from seahub.organizations.models import OrgSettings
|
||||||
|
from seahub.organizations.signals import org_created, org_reactivated
|
||||||
from seahub.organizations.decorators import org_staff_required
|
from seahub.organizations.decorators import org_staff_required
|
||||||
from seahub.organizations.forms import OrgRegistrationForm
|
from seahub.organizations.forms import OrgRegistrationForm
|
||||||
from seahub.organizations.settings import ORG_AUTO_URL_PREFIX, \
|
from seahub.organizations.settings import ORG_AUTO_URL_PREFIX, \
|
||||||
@@ -39,6 +40,8 @@ from seahub.subscription.utils import subscription_check
|
|||||||
from seahub.billing.settings import ENABLE_EXTERNAL_BILLING_SERVICE
|
from seahub.billing.settings import ENABLE_EXTERNAL_BILLING_SERVICE
|
||||||
from registration.models import RegistrationProfile
|
from registration.models import RegistrationProfile
|
||||||
|
|
||||||
|
from seahub.invitations.models import Invitation
|
||||||
|
|
||||||
# Get an instance of a logger
|
# Get an instance of a logger
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@@ -337,3 +340,24 @@ def org_associate(request, token):
|
|||||||
set_org_user(org_id, username)
|
set_org_user(org_id, username)
|
||||||
|
|
||||||
return HttpResponseRedirect(settings.LOGIN_REDIRECT_URL)
|
return HttpResponseRedirect(settings.LOGIN_REDIRECT_URL)
|
||||||
|
|
||||||
|
|
||||||
|
def org_reactivate(request, token):
|
||||||
|
|
||||||
|
invite = Invitation.objects.get_by_token(token=token)
|
||||||
|
if not invite:
|
||||||
|
return render_error(request, _('Invalid token.'))
|
||||||
|
|
||||||
|
if invite.is_expired():
|
||||||
|
return render_error(request, _('Expired token.'))
|
||||||
|
|
||||||
|
org_id = invite.accepter
|
||||||
|
org_id = int(org_id)
|
||||||
|
org = ccnet_api.get_org_by_id(org_id)
|
||||||
|
if not org:
|
||||||
|
return render_error(request, f'Organization {org_id} not found')
|
||||||
|
|
||||||
|
invite.accept()
|
||||||
|
OrgSettings.objects.add_or_update(org, is_active=True)
|
||||||
|
org_reactivated.send(sender=None, email=None, org=org)
|
||||||
|
return HttpResponseRedirect(settings.SITE_ROOT)
|
||||||
|
@@ -1,10 +1,18 @@
|
|||||||
{% extends 'base.html' %}
|
{% extends 'base.html' %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
{% block main_content %}
|
{% block main_content %}
|
||||||
<div class="w-100 h-100 d-flex flex-column align-items-center justify-content-center text-center">
|
<div class="w-100 h-100 d-flex flex-column align-items-center justify-content-center text-center">
|
||||||
{% if organization_inactive %}
|
{% if organization_inactive %}
|
||||||
<img src="{{MEDIA_URL}}img/organization-inactive.png" alt="" width="100" />
|
<img src="{{MEDIA_URL}}img/organization-inactive.png" alt="" width="100" />
|
||||||
<p>{{ error_msg }}</p>
|
<p>{{ error_msg }}</p>
|
||||||
|
{% if reactivate_link %}
|
||||||
|
<p>
|
||||||
|
{% blocktrans with link=reactivate_link %}
|
||||||
|
Click <a href="{{ link }}">here</a> to reactivate your team and relogin.
|
||||||
|
{% endblocktrans %}
|
||||||
|
</p>
|
||||||
|
{% endif %}
|
||||||
{% else %}
|
{% else %}
|
||||||
<img src="{{MEDIA_URL}}img/error-tip.png" alt="" width="100" />
|
<img src="{{MEDIA_URL}}img/error-tip.png" alt="" width="100" />
|
||||||
<p>{{ error_msg }}</p>
|
<p>{{ error_msg }}</p>
|
||||||
|
Reference in New Issue
Block a user