1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-09-17 15:53:28 +00:00

Improve adfs error msg (#5898)

* improve error msg

* send error msg to sys/org admin

* fix code
This commit is contained in:
WJH
2024-01-17 14:49:23 +08:00
committed by GitHub
parent c9ca6efb89
commit 73afa03d63
11 changed files with 251 additions and 55 deletions

View File

@@ -19,6 +19,7 @@ const MSG_TYPE_DRAFT_REVIEWER = 'draft_reviewer';
// const MSG_TYPE_GUEST_INVITATION_ACCEPTED = 'guest_invitation_accepted';
const MSG_TYPE_REPO_MONITOR = 'repo_monitor';
const MSG_TYPE_DELETED_FILES = 'deleted_files';
const MSG_TYPE_SAML_SSO_FAILED = 'saml_sso_failed';
class NoticeItem extends React.Component {
@@ -282,6 +283,13 @@ class NoticeItem extends React.Component {
return { avatar_url : null, notice };
}
if (noticeType === MSG_TYPE_SAML_SSO_FAILED) {
const { error_msg } = detail;
let notice = gettext(error_msg);
return { avatar_url : null, notice };
}
// if (noticeType === MSG_TYPE_GUEST_INVITATION_ACCEPTED) {
// }

View File

@@ -49,14 +49,6 @@ class Saml2Backend(ModelBackend):
logger.error('Session info or attribute mapping are None')
return None
if 'ava' not in session_info:
logger.error('"ava" key not found in session_info')
return None
attributes = session_info['ava']
if not attributes:
logger.warning('The attributes dictionary is empty')
name_id = session_info.get('name_id', '')
if not name_id:
logger.error('The name_id is not available. Could not determine user identifier.')
@@ -97,6 +89,15 @@ class Saml2Backend(ModelBackend):
notify_admins_on_register_complete(user.username)
if user:
if 'ava' not in session_info:
logger.warning('"ava" key not found in session_info')
return user
attributes = session_info['ava']
if not attributes:
logger.warning('The attributes dictionary is empty')
return user
self.make_profile(user, attributes, attribute_mapping)
self.sync_saml_groups(user, attributes)

View File

@@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-
from django.dispatch import Signal
saml_sso_failed = Signal()

View File

@@ -35,18 +35,18 @@ def settings_check(func):
error = True
else:
if not XMLSEC_BINARY_PATH or not CERTS_DIR or not SAML_ATTRIBUTE_MAPPING or not SAML_PROVIDER_IDENTIFIER:
logger.error('ADFS login relevant settings invalid.')
logger.error('ADFS/SAML login relevant settings invalid.')
logger.error('SAML_XMLSEC_BINARY_PATH: %s' % XMLSEC_BINARY_PATH)
logger.error('SAML_CERTS_DIR: %s' % CERTS_DIR)
logger.error('SAML_ATTRIBUTE_MAPPING: %s' % SAML_ATTRIBUTE_MAPPING)
logger.error('SAML_PROVIDER_IDENTIFIER: %s' % SAML_PROVIDER_IDENTIFIER)
error = True
if ENABLE_ADFS_LOGIN and not REMOTE_METADATA_URL:
logger.error('SAML relevant settings invalid.')
logger.error('ADFS/SAML login relevant settings invalid.')
logger.error('SAML_REMOTE_METADATA_URL: %s' % REMOTE_METADATA_URL)
error = True
if error:
raise Exception(_('Error, please contact administrator.'))
raise Exception(_('ADFS/SAML login relevant settings invalid.'))
return func(request)
return _decorated
@@ -66,7 +66,7 @@ def config_settings_loader(request):
org_saml_config = OrgSAMLConfig.objects.get_config_by_org_id(org_id)
if not org_saml_config:
raise Exception('Failed to get org %s saml_config' % org_id)
raise Exception('Cannot find an ADFS/SAML config for the organization related to org_id %s.' % org_id)
# get org remote_metadata_url
remote_metadata_url = org_saml_config.metadata_url
@@ -131,6 +131,6 @@ def config_settings_loader(request):
conf = SPConfig()
conf.load(copy.deepcopy(saml_config))
except Exception as e:
logger.exception('Failed to load saml config, error: %s' % e)
raise Exception('Failed to load saml config, error: %s' % e)
logger.exception('Failed to load adfs/saml config, error: %s' % e)
raise RuntimeError('Failed to load adfs/saml config, error: %s' % e)
return conf

View File

@@ -20,6 +20,7 @@ from django.urls import reverse
from django.http import HttpResponseRedirect, HttpResponse, HttpResponseBadRequest, HttpResponseForbidden, \
HttpResponsePermanentRedirect
from django.utils.http import url_has_allowed_host_and_scheme
from django.utils.translation import gettext as _
from django.views.decorators.http import require_POST
from django.views.decorators.csrf import csrf_exempt
from saml2 import BINDING_HTTP_POST
@@ -28,7 +29,6 @@ from saml2.client import Saml2Client
from saml2.metadata import entity_descriptor
from djangosaml2.cache import IdentityCache, OutstandingQueriesCache
from djangosaml2.conf import get_config
from djangosaml2.signals import post_authenticated
from seaserv import ccnet_api, seafile_api
@@ -42,6 +42,7 @@ from seahub.profile.models import Profile, DetailedProfile
from seahub.utils.licenseparse import user_number_over_limit
from seahub.utils.file_size import get_quota_from_string
from seahub.role_permissions.utils import get_enabled_role_permissions_by_role
from seahub.adfs_auth.signals import saml_sso_failed
# Added by khorkin
from seahub.base.sudo_mode import update_sudo_mode_ts
try:
@@ -60,6 +61,15 @@ def _set_subject_id(session, subject_id):
session['_saml2_subject_id'] = code(subject_id)
def get_org_admins(org):
org_admins = list()
org_users = ccnet_api.get_org_emailusers(org.url_prefix, -1, -1)
for user in org_users:
if ccnet_api.is_org_staff(org.org_id, user.email):
org_admins.append(user)
return org_admins
def update_user_profile(user, attribute_mapping, attributes):
parse_result = {}
for saml_attr, django_attrs in list(attribute_mapping.items()):
@@ -111,12 +121,13 @@ def update_user_profile(user, attribute_mapping, attributes):
def login(request, org_id=None):
org = None
if org_id and int(org_id) > 0:
org_id = int(org_id)
org = ccnet_api.get_org_by_id(org_id)
if not org:
logger.error('Cannot find an organization related to org_id %s.' % org_id)
return HttpResponseBadRequest('Cannot find an organization related to org_id %s.' % org_id)
return HttpResponseBadRequest(_('Internal server error. Please contact system administrator.'))
next_url = settings.LOGIN_REDIRECT_URL
if 'next' in request.GET:
@@ -129,9 +140,23 @@ def login(request, org_id=None):
try:
sp_config = get_config(None, request)
except RuntimeError as e:
logger.error(e)
# send error msg to admin
error_msg = 'ADFS/SAML service error. Please check and fix the ADFS/SAML service.'
if org:
org_admins = get_org_admins(org)
for org_admin in org_admins:
saml_sso_failed.send(sender=None, to_user=org_admin.email, error_msg=error_msg)
else:
admins = User.objects.get_superusers()
for admin in admins:
saml_sso_failed.send(sender=None, to_user=admin.email, error_msg=error_msg)
return HttpResponseBadRequest(_('Login failed: ADFS/SAML service error. '
'Please report to your organization (company) administrator.'))
except Exception as e:
logger.error(e)
return HttpResponseBadRequest('Failed to get saml config, please check your ADFS/SAML service.')
return HttpResponseBadRequest(_('Internal server error. Please contact system administrator.'))
saml_client = Saml2Client(sp_config)
session_id, info = saml_client.prepare_for_authenticate(relay_state=next_url)
@@ -158,24 +183,50 @@ def assertion_consumer_service(request, org_id=None, attribute_mapping=None, cre
settings.py. The `djangosaml2.backends.Saml2Backend` can be used for this purpose,
though some implementations may instead register their own subclasses of Saml2Backend.
"""
if 'SAMLResponse' not in request.POST:
return HttpResponseBadRequest('Missing "SAMLResponse" parameter in POST data.')
org = None
if org_id and int(org_id) > 0:
org_id = int(org_id)
org = ccnet_api.get_org_by_id(org_id)
if not org:
logger.error('Cannot find an organization related to org_id %s.' % org_id)
return HttpResponseBadRequest('Cannot find an organization related to org_id %s.' % org_id)
return HttpResponseBadRequest(_('Internal server error. Please contact system administrator.'))
else:
org_id = -1
if 'SAMLResponse' not in request.POST:
logger.error('Missing "SAMLResponse" parameter in POST data.')
# send error msg to admin
error_msg = 'ADFS/SAML service error. Please check and fix the ADFS/SAML service.'
if org:
org_admins = get_org_admins(org)
for org_admin in org_admins:
saml_sso_failed.send(sender=None, to_user=org_admin.email, error_msg=error_msg)
else:
admins = User.objects.get_superusers()
for admin in admins:
saml_sso_failed.send(sender=None, to_user=admin.email, error_msg=error_msg)
return HttpResponseBadRequest(_('Login failed: Bad response from ADFS/SAML service. '
'Please report to your organization (company) administrator.'))
try:
conf = get_config(None, request)
except RuntimeError as e:
logger.error(e)
# send error msg to admin
error_msg = 'ADFS/SAML service error. Please check and fix the ADFS/SAML service.'
if org:
org_admins = get_org_admins(org)
for org_admin in org_admins:
saml_sso_failed.send(sender=None, to_user=org_admin.email, error_msg=error_msg)
else:
admins = User.objects.get_superusers()
for admin in admins:
saml_sso_failed.send(sender=None, to_user=admin.email, error_msg=error_msg)
return HttpResponseBadRequest(_('Login failed: ADFS/SAML service error. '
'Please report to your organization (company) administrator.'))
except Exception as e:
logger.error(e)
return HttpResponseBadRequest('Failed to get saml config, please check your ADFS/SAML service.')
return HttpResponseBadRequest(_('Internal server error. Please contact system administrator.'))
identity_cache = IdentityCache(request.saml_session)
client = Saml2Client(conf, identity_cache=identity_cache)
@@ -187,12 +238,33 @@ def assertion_consumer_service(request, org_id=None, attribute_mapping=None, cre
try:
response = client.parse_authn_request_response(xmlstr, BINDING_HTTP_POST, outstanding_queries)
except Exception as e:
logger.error(e)
return HttpResponseBadRequest('SAMLResponse Error')
logger.error('SAMLResponse Error: %s' % e)
# send error msg to admin
error_msg = 'ADFS/SAML service error. Please check and fix the ADFS/SAML service.'
if org:
org_admins = get_org_admins(org)
for org_admin in org_admins:
saml_sso_failed.send(sender=None, to_user=org_admin.email, error_msg=error_msg)
else:
admins = User.objects.get_superusers()
for admin in admins:
saml_sso_failed.send(sender=None, to_user=admin.email, error_msg=error_msg)
return HttpResponseBadRequest(_('Login failed: Bad response from ADFS/SAML service. '
'Please report to your organization (company) administrator.'))
if response is None:
logger.error('SAML response is None')
return HttpResponseBadRequest('SAML response has errors. Please check the logs')
logger.error('Invalid SAML Assertion received.')
# send error msg to admin
error_msg = 'ADFS/SAML service error. Please check and fix the ADFS/SAML service.'
if org:
org_admins = get_org_admins(org)
for org_admin in org_admins:
saml_sso_failed.send(sender=None, to_user=org_admin.email, error_msg=error_msg)
else:
admins = User.objects.get_superusers()
for admin in admins:
saml_sso_failed.send(sender=None, to_user=admin.email, error_msg=error_msg)
return HttpResponseBadRequest(_('Login failed: Bad response from ADFS/SAML service. '
'Please report to your organization (company) administrator.'))
session_id = response.session_id()
oq_cache.delete(session_id)
@@ -204,18 +276,19 @@ def assertion_consumer_service(request, org_id=None, attribute_mapping=None, cre
is_saml2_connect = parse_qs(urlparse(unquote(relay_state)).query).get('is_saml2_connect', [''])[0]
if is_saml2_connect == 'true':
if not request.user.is_authenticated:
return HttpResponseBadRequest('Failed to bind SAML, please login first.')
return HttpResponseBadRequest(_('Failed to bind SAML, please login first.'))
# get uid and other attrs from session_info
name_id = session_info.get('name_id', '')
if not name_id:
logger.error('The name_id is not available. Could not determine user identifier.')
return HttpResponseBadRequest('Failed to bind SAML, please contact admin.')
return HttpResponseBadRequest(_('Internal server error. Please contact system administrator.'))
name_id = name_id.text
saml_user = SocialAuthUser.objects.get_by_provider_and_uid(SAML_PROVIDER_IDENTIFIER, name_id)
if saml_user:
return HttpResponseBadRequest('The SAML user has already been bound to another account.')
logger.error('The SAML user has already been bound to another account.')
return HttpResponseBadRequest(_('Internal server error. Please contact system administrator.'))
# bind saml user
username = request.user.username
@@ -236,7 +309,13 @@ def assertion_consumer_service(request, org_id=None, attribute_mapping=None, cre
# check user number limit by license
if user_number_over_limit():
return HttpResponseForbidden('The number of users exceeds the license limit.')
logger.error('The number of users exceeds the license limit.')
# send error msg to admin
error_msg = 'The number of users exceeds the license limit.'
admins = User.objects.get_superusers()
for admin in admins:
saml_sso_failed.send(sender=None, to_user=admin.email, error_msg=error_msg)
return HttpResponseForbidden(_('Internal server error. Please contact system administrator.'))
# check user number limit by org member quota
if org:
@@ -245,7 +324,15 @@ def assertion_consumer_service(request, org_id=None, attribute_mapping=None, cre
from seahub.organizations.models import OrgMemberQuota
org_members_quota = OrgMemberQuota.objects.get_quota(org_id)
if org_members_quota is not None and org_members >= org_members_quota:
return HttpResponseForbidden('The number of users exceeds the organization quota.')
logger.error('The number of users exceeds the organization quota.')
# send error msg to admin
error_msg = 'Failed to create new user: the number of users exceeds the organization quota.'
org_admins = get_org_admins(org)
for org_admin in org_admins:
saml_sso_failed.send(sender=None, to_user=org_admin.email, error_msg=error_msg)
return HttpResponseForbidden(_('Failed to create new user: '
'the number of users exceeds the organization quota. '
'Please report to your organization (company) administrator.'))
# authenticate the remote user
logger.debug('Trying to authenticate the user')
@@ -254,17 +341,37 @@ def assertion_consumer_service(request, org_id=None, attribute_mapping=None, cre
create_unknown_user=create_unknown_user,
org_id=org_id)
if user is None:
logger.error('The user is None')
return HttpResponseForbidden("Permission denied")
logger.error('ADFS/SAML single sign-on failed: failed to create user.')
# send error msg to admin
error_msg = 'ADFS/SAML single sign-on failed: failed to create user.'
if org:
org_admins = get_org_admins(org)
for org_admin in org_admins:
saml_sso_failed.send(sender=None, to_user=org_admin.email, error_msg=error_msg)
else:
admins = User.objects.get_superusers()
for admin in admins:
saml_sso_failed.send(sender=None, to_user=admin.email, error_msg=error_msg)
return HttpResponseForbidden(_('Login failed: failed to create user. '
'Please report to your organization (company) administrator.'))
if not user.is_active:
logger.error('The user is inactive')
return HttpResponseForbidden("Permission denied")
logger.error('ADFS/SAML single sign-on failed: user %s is deactivated.' % user.username)
# send error msg to admin
error_msg = 'ADFS/SAML single sign-on failed: user % is deactivated.' % user.username
if org:
org_admins = get_org_admins(org)
for org_admin in org_admins:
saml_sso_failed.send(sender=None, to_user=org_admin.email, error_msg=error_msg)
else:
admins = User.objects.get_superusers()
for admin in admins:
saml_sso_failed.send(sender=None, to_user=admin.email, error_msg=error_msg)
return HttpResponseForbidden(_('Login failed: user is deactivated. '
'Please report to your organization (company) administrator.'))
auth_login(request, user)
_set_subject_id(request.saml_session, session_info['name_id'])
logger.debug('Sending the post_authenticated signal')
post_authenticated.send_robust(sender=user, session_info=session_info)
# redirect the user to the view where he came from
default_relay_state = settings.LOGIN_REDIRECT_URL
@@ -277,18 +384,34 @@ def assertion_consumer_service(request, org_id=None, attribute_mapping=None, cre
def metadata(request, org_id=None):
org = None
if org_id and int(org_id) > 0:
org_id = int(org_id)
org = ccnet_api.get_org_by_id(org_id)
if not org:
logger.error('Cannot find an organization related to org_id %s.' % org_id)
return HttpResponseBadRequest('Cannot find an organization related to org_id %s.' % org_id)
return HttpResponseBadRequest(_('Internal server error. Please contact system administrator.'))
try:
sp_config = get_config(None, request)
except RuntimeError as e:
logger.error(e)
# send error msg to admin
error_msg = 'ADFS/SAML service error. Please check and fix the ADFS/SAML service.'
if org:
org_admins = get_org_admins(org)
for org_admin in org_admins:
saml_sso_failed.send(sender=None, to_user=org_admin.email, error_msg=error_msg)
else:
admins = User.objects.get_superusers()
for admin in admins:
saml_sso_failed.send(sender=None, to_user=admin.email, error_msg=error_msg)
return HttpResponseBadRequest(_('Login failed: ADFS/SAML service error. '
'Please report to your organization (company) administrator.'))
except Exception as e:
logger.error(e)
return HttpResponseBadRequest('Failed to get saml config, please check your ADFS/SAML service.')
return HttpResponseBadRequest(_('Internal server error. Please contact system administrator.'))
sp_metadata = entity_descriptor(sp_config)
return HttpResponse(
content=str(sp_metadata).encode("utf-8"),
@@ -298,16 +421,17 @@ def metadata(request, org_id=None):
@login_required
def saml2_connect(request, org_id=None):
org = None
if org_id and int(org_id) > 0:
org_id = int(org_id)
org = ccnet_api.get_org_by_id(org_id)
if not org:
logger.error('Cannot find an organization related to org_id %s.' % org_id)
return HttpResponseBadRequest('Cannot find an organization related to org_id %s.' % org_id)
return HttpResponseBadRequest(_('Internal server error. Please contact system administrator.'))
if request.user.org.org_id != org_id:
logger.error('User %s does not belong to this organization: %s.' % (request.user.username, org.org_id))
return HttpResponseBadRequest('Failed to bind SAML, please contact admin.')
logger.error('User %s does not belong to this organization: %s.' % (request.user.username, org.org_name))
return HttpResponseBadRequest(_('Internal server error. Please contact system administrator.'))
next_url = settings.LOGIN_REDIRECT_URL
if 'next' in request.GET:
@@ -321,9 +445,23 @@ def saml2_connect(request, org_id=None):
try:
sp_config = get_config(None, request)
except RuntimeError as e:
logger.error(e)
# send error msg to admin
error_msg = 'ADFS/SAML service error. Please check and fix the ADFS/SAML service.'
if org:
org_admins = get_org_admins(org)
for org_admin in org_admins:
saml_sso_failed.send(sender=None, to_user=org_admin.email, error_msg=error_msg)
else:
admins = User.objects.get_superusers()
for admin in admins:
saml_sso_failed.send(sender=None, to_user=admin.email, error_msg=error_msg)
return HttpResponseBadRequest(_('Login failed: ADFS/SAML service error. '
'Please report to your organization (company) administrator.'))
except Exception as e:
logger.error(e)
return HttpResponseBadRequest('Failed to get ADFS/SAML config, please check your ADFS/SAML service.')
return HttpResponseBadRequest(_('Internal server error. Please contact system administrator.'))
saml_client = Saml2Client(sp_config)
session_id, info = saml_client.prepare_for_authenticate(relay_state=next_url)
@@ -347,18 +485,20 @@ def saml2_disconnect(request, org_id=None):
org_id = int(org_id)
org = ccnet_api.get_org_by_id(org_id)
if not org:
return HttpResponseBadRequest('Cannot find an organization related to org_id %s.' % org_id)
logger.error('Cannot find an organization related to org_id %s.' % org_id)
return HttpResponseBadRequest(_('Internal server error. Please contact system administrator.'))
if request.user.org.org_id != org_id:
logger.error('User %s does not belong to this organization: %s.' % (request.user.username, org.org_id))
return HttpResponseBadRequest('Failed to disbind SAML, please contact admin.')
logger.error('User %s does not belong to this organization: %s.' % (request.user.username, org.org_name))
return HttpResponseBadRequest(_('Internal server error. Please contact system administrator.'))
username = request.user.username
if request.user.enc_password == '!':
return HttpResponseBadRequest('Failed to disbind SAML, please set a password first.')
return HttpResponseBadRequest(_('Failed to unbind SAML, please set a password first.'))
profile = Profile.objects.get_profile_by_user(username)
if not profile or not profile.contact_email:
return HttpResponseBadRequest('Failed to disbind SAML, please set a contact email first.')
return HttpResponseBadRequest(_('Failed to unbind SAML, please set a contact email first.'))
SocialAuthUser.objects.delete_by_username_and_provider(username, SAML_PROVIDER_IDENTIFIER)
next_url = request.GET.get(auth.REDIRECT_FIELD_NAME, settings.LOGIN_REDIRECT_URL)
@@ -414,11 +554,11 @@ def adfs_compatible_view(request, url_prefix):
org = ccnet_api.get_org_by_url_prefix(url_prefix)
except Exception as e:
logger.error(e)
return HttpResponseBadRequest('login failed, please contact admin')
return HttpResponseBadRequest(_('Internal server error. Please contact system administrator.'))
if not org:
logger.error('Cannot find an organization related to url_prefix %s.' % url_prefix)
return HttpResponseBadRequest('Cannot find an organization related to url_prefix %s.' % url_prefix)
return HttpResponseBadRequest(_('Internal server error. Please contact system administrator.'))
org_id = str(org.org_id)
return HttpResponsePermanentRedirect(request.path.replace(url_prefix, org_id))

View File

@@ -501,7 +501,7 @@ 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 config for the team related to domain %s." % domain
render_data['error_msg'] = "Cannot find an ADFS/SAML config for the team related to domain %s." % domain
return render(request, template_name, render_data)
if not org_saml_config.domain_verified:
render_data['error_msg'] = \
@@ -510,7 +510,7 @@ def multi_adfs_sso(request):
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 a SAML config for the team related to domain %s." % domain
render_data['error_msg'] = "Cannot find an ADFS/SAML config for the team related to domain %s." % domain
return render(request, template_name, render_data)
except Exception as e:
logger.error(e)

View File

@@ -258,6 +258,11 @@ class Command(BaseCommand):
return notice
def format_saml_sso_error_msg(self, notice):
d = json.loads(notice.detail)
notice.error_msg = d['error_msg']
return notice
def format_sdoc_msg(self, sdoc_queryset, sdoc_notice):
sdoc_obj = sdoc_queryset.filter(uuid=sdoc_notice.doc_uuid).first()
if not sdoc_obj:
@@ -421,6 +426,9 @@ class Command(BaseCommand):
elif notice.is_repo_monitor_msg():
notice = self.format_repo_monitor_msg(notice)
elif notice.is_saml_sso_error_msg():
notice = self.format_saml_sso_error_msg(notice)
if notice is None:
continue

View File

@@ -76,6 +76,7 @@ MSG_TYPE_GUEST_INVITATION_ACCEPTED = 'guest_invitation_accepted'
MSG_TYPE_REPO_TRANSFER = 'repo_transfer'
MSG_TYPE_REPO_MINOTOR = 'repo_monitor'
MSG_TYPE_DELETED_FILES = 'deleted_files'
MSG_TYPE_SAML_SSO_FAILED = 'saml_sso_failed'
USER_NOTIFICATION_COUNT_CACHE_PREFIX = 'USER_NOTIFICATION_COUNT_'
@@ -133,6 +134,11 @@ def repo_transfer_msg_to_json(org_id, repo_owner, repo_id, repo_name):
return json.dumps({'org_id': org_id, 'repo_owner': repo_owner,
'repo_id': repo_id, 'repo_name': repo_name})
def saml_sso_error_msg_to_json(error_msg):
return json.dumps({'error_msg': error_msg})
def get_cache_key_of_unseen_notifications(username):
return normalize_cache_key(username,
USER_NOTIFICATION_COUNT_CACHE_PREFIX)
@@ -309,6 +315,11 @@ class UserNotificationManager(models.Manager):
return self._add_user_notification(
to_user, MSG_TYPE_REPO_TRANSFER, detail)
def add_saml_sso_error_msg(self, to_user, detail):
"""Notify ``to_user`` that saml sso occurred an error
"""
return self._add_user_notification(to_user, MSG_TYPE_SAML_SSO_FAILED, detail)
class UserNotification(models.Model):
to_user = LowerCaseCharField(db_index=True, max_length=255)
@@ -411,6 +422,9 @@ class UserNotification(models.Model):
def is_deleted_files_msg(self):
return self.msg_type == MSG_TYPE_DELETED_FILES
def is_saml_sso_error_msg(self):
return self.msg_type == MSG_TYPE_SAML_SSO_FAILED
def user_message_detail_to_dict(self):
"""Parse user message detail, returns dict contains ``message`` and
``msg_from``.
@@ -780,6 +794,8 @@ from seahub.share.signals import share_repo_to_user_successful, \
from seahub.invitations.signals import accept_guest_invitation_successful
from seahub.drafts.signals import comment_draft_successful, \
request_reviewer_successful
from seahub.adfs_auth.signals import saml_sso_failed
@receiver(upload_file_successful)
def add_upload_file_msg_cb(sender, **kwargs):
@@ -918,3 +934,12 @@ def repo_transfer_cb(sender, **kwargs):
detail = repo_transfer_msg_to_json(org_id, repo_owner, repo_id, repo_name)
UserNotification.objects.add_repo_transfer_msg(to_user, detail)
@receiver(saml_sso_failed)
def saml_sso_failed_cb(sender, **kwargs):
to_user = kwargs['to_user']
error_msg = kwargs['error_msg']
detail = saml_sso_error_msg_to_json(error_msg)
UserNotification.objects.add_saml_sso_error_msg(to_user, detail)

View File

@@ -65,6 +65,9 @@ You've got {{num}} new notices on {{ site_name }}:
{% elif notice.is_deleted_files_msg %}
<p style="line-height:1.5; margin:.2em 10px .2em 0;">{% blocktrans with repo_url=notice.repo_url repo_name=notice.repo_name %}A large number of files in your library <a href="{{url_base}}{{ repo_url }}">{{ repo_name }}</a> has been deleted recently.{% endblocktrans %}</p>
{% elif notice.is_saml_sso_error_msg %}
<p style="line-height:1.5; margin:.2em 10px .2em 0;">{% blocktrans %}{{notice.error_msg}}{% endblocktrans %}</p>
{% elif notice.is_repo_monitor_msg %}
<p style="line-height:1.5; margin:.2em 10px .2em 0;">
{% if notice.obj_type == 'file' %}

View File

@@ -268,6 +268,13 @@ def update_notice_detail(request, notices):
except Exception as e:
logger.error(e)
elif notice.is_saml_sso_error_msg():
try:
d = json.loads(notice.detail)
notice.detail = d
except Exception as e:
logger.error(e)
return notices

View File

@@ -109,7 +109,7 @@ class OrgVerifyDomain(APIView):
saml_config = OrgSAMLConfig.objects.get_config_by_org_id(org_id)
if not saml_config:
error_msg = 'Cannot find a SAML/ADFS config for the organization %s.' % org.org_name
error_msg = 'Cannot find an ADFS/SAML config for the team %s.' % org.org_name
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
if saml_config.domain != domain: