perf: 三方用户登录通知 (#11846)

Co-authored-by: feng <1304903146@qq.com>
pull/11851/head
fit2bot 2023-10-16 11:28:53 +08:00 committed by GitHub
parent f55c84ce3b
commit 0a28c5650c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 28 additions and 14 deletions

View File

@ -11,7 +11,6 @@ from django.utils.functional import LazyObject
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from rest_framework.request import Request from rest_framework.request import Request
from acls.const import ActionChoices
from acls.models import LoginACL from acls.models import LoginACL
from acls.notifications import UserLoginReminderMsg from acls.notifications import UserLoginReminderMsg
from audits.models import UserLoginLog from audits.models import UserLoginLog
@ -85,6 +84,9 @@ def generate_data(username, request, login_type=None):
def create_user_session(request, user_id, instance: UserLoginLog): def create_user_session(request, user_id, instance: UserLoginLog):
# TODO 目前只记录 web 登录的 session
if instance.type != LoginTypeChoices.web:
return
session_key = request.session.session_key or '-' session_key = request.session.session_key or '-'
session_store_cls = import_module(settings.SESSION_ENGINE).SessionStore session_store_cls = import_module(settings.SESSION_ENGINE).SessionStore
session_store = session_store_cls(session_key=session_key) session_store = session_store_cls(session_key=session_key)
@ -102,10 +104,21 @@ def create_user_session(request, user_id, instance: UserLoginLog):
'date_expired': instance.datetime + timedelta(seconds=ttl), 'date_expired': instance.datetime + timedelta(seconds=ttl),
} }
user_session = UserSession.objects.create(**online_session_data) user_session = UserSession.objects.create(**online_session_data)
request.session['user_session_id'] = user_session.id request.session['user_session_id'] = str(user_session.id)
def send_login_info_to_reviewers(instance: UserLoginLog, reviewers): def send_login_info_to_reviewers(instance: UserLoginLog | str, auth_acl_id):
if isinstance(instance, str):
instance = UserLoginLog.objects.filter(id=instance).first()
if not instance:
return
acl = LoginACL.objects.filter(id=auth_acl_id).first()
if not acl or not acl.reviewers.exists():
return
reviewers = acl.reviewers.all()
for reviewer in reviewers: for reviewer in reviewers:
UserLoginReminderMsg(reviewer, instance).publish_async() UserLoginReminderMsg(reviewer, instance).publish_async()
@ -119,22 +132,15 @@ def on_user_auth_success(sender, user, request, login_type=None, **kwargs):
data.update({'mfa': int(user.mfa_enabled), 'status': True}) data.update({'mfa': int(user.mfa_enabled), 'status': True})
instance = write_login_log(**data) instance = write_login_log(**data)
# TODO 目前只记录 web 登录的 session
if instance.type != LoginTypeChoices.web:
return
create_user_session(request, user.id, instance) create_user_session(request, user.id, instance)
request.session['user_log_id'] = str(instance.id)
request.session['can_send_notifications'] = True
auth_notice_required = request.session.get('auth_notice_required') auth_notice_required = request.session.get('auth_notice_required')
if not auth_notice_required: if not auth_notice_required:
return return
auth_acl_id = request.session.get('auth_acl_id') auth_acl_id = request.session.get('auth_acl_id')
acl = LoginACL.objects.filter(id=auth_acl_id, action=ActionChoices.notice).first() send_login_info_to_reviewers(instance, auth_acl_id)
if not acl or not acl.reviewers.exists():
return
reviewers = acl.reviewers.all()
send_login_info_to_reviewers(instance, reviewers)
@receiver(post_auth_failed) @receiver(post_auth_failed)

View File

@ -8,6 +8,7 @@ from django.utils.deprecation import MiddlewareMixin
from django.utils.translation import gettext as _ from django.utils.translation import gettext as _
from apps.authentication import mixins from apps.authentication import mixins
from audits.signal_handlers import send_login_info_to_reviewers
from authentication.signals import post_auth_failed from authentication.signals import post_auth_failed
from common.utils import gen_key_pair from common.utils import gen_key_pair
from common.utils import get_request_ip from common.utils import get_request_ip
@ -105,6 +106,12 @@ class ThirdPartyLoginMiddleware(mixins.AuthMixin):
guard_url = "%s?%s" % (guard_url, args) guard_url = "%s?%s" % (guard_url, args)
response = redirect(guard_url) response = redirect(guard_url)
finally: finally:
if request.session.get('can_send_notifications') and \
self.request.session['auth_notice_required']:
request.session['can_send_notifications'] = False
user_log_id = self.request.session.get('user_log_id')
auth_acl_id = self.request.session.get('auth_acl_id')
send_login_info_to_reviewers(user_log_id, auth_acl_id)
return response return response

View File

@ -523,7 +523,8 @@ class AuthMixin(CommonMixin, AuthPreCheckMixin, AuthACLMixin, MFAMixin, AuthPost
def clear_auth_mark(self): def clear_auth_mark(self):
keys = [ keys = [
'auth_password', 'user_id', 'auth_confirm_required', 'auth_password', 'user_id', 'auth_confirm_required',
'auth_notice_required', 'auth_ticket_id', 'auth_acl_id' 'auth_notice_required', 'auth_ticket_id', 'auth_acl_id',
'user_session_id', 'user_log_id', 'can_send_notifications'
] ]
for k in keys: for k in keys:
self.request.session.pop(k, '') self.request.session.pop(k, '')