From 2efb1b88f9a80d58c6ac853239e1405310149bc4 Mon Sep 17 00:00:00 2001 From: vapao Date: Mon, 13 Nov 2023 16:59:02 +0800 Subject: [PATCH] =?UTF-8?q?#=20=E4=BC=98=E5=8C=96=E6=8E=A8=E9=80=81?= =?UTF-8?q?=E9=9B=86=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- spug_api/apps/account/views.py | 9 ++- spug_api/apps/setting/views.py | 21 ++---- spug_api/libs/push.py | 19 ++++++ spug_api/libs/spug.py | 68 +++---------------- spug_web/src/pages/system/account/Form.js | 30 +++++--- .../pages/system/setting/SecuritySetting.js | 32 ++++----- 6 files changed, 75 insertions(+), 104 deletions(-) diff --git a/spug_api/apps/account/views.py b/spug_api/apps/account/views.py index 182b9bd5..0a07e18d 100644 --- a/spug_api/apps/account/views.py +++ b/spug_api/apps/account/views.py @@ -6,7 +6,7 @@ from libs.mixins import AdminView, View from libs import JsonParser, Argument, human_datetime, json_response from libs.utils import get_request_real_ip, generate_random_str -from libs.spug import send_login_wx_code +from libs.push import send_login_code from apps.account.models import User, Role, History from apps.setting.utils import AppSetting from apps.account.utils import verify_password @@ -255,9 +255,12 @@ def handle_user_info(handle_response, request, user, captcha): mfa = AppSetting.get_default('MFA', {'enable': False}) if mfa['enable']: if not user.wx_token: - return handle_response(error='已启用登录双重认证,但您的账户未配置微信Token,请联系管理员') + return handle_response(error='已启用登录双重认证,但您的账户未配置推送标识,请联系管理员') + spug_push_key = AppSetting.get_default('spug_push_key') + if not spug_push_key: + return handle_response(error='已启用登录双重认证,但系统未配置推送服务,请联系管理员') code = generate_random_str(6) - send_login_wx_code(user.wx_token, code) + send_login_code(spug_push_key, user.wx_token, code) cache.set(key, code, 300) return json_response({'required_mfa': True}) diff --git a/spug_api/apps/setting/views.py b/spug_api/apps/setting/views.py index 92979064..67bfebcb 100644 --- a/spug_api/apps/setting/views.py +++ b/spug_api/apps/setting/views.py @@ -7,8 +7,7 @@ from libs import JsonParser, Argument, json_response, auth from libs.utils import generate_random_str from libs.mail import Mail -from libs.spug import send_login_wx_code -from libs.push import get_balance +from libs.push import get_balance, send_login_code from libs.mixins import AdminView from apps.setting.utils import AppSetting from apps.setting.models import Setting, KEYS_DEFAULT @@ -41,9 +40,12 @@ class MFAView(AdminView): def get(self, request): if not request.user.wx_token: return json_response( - error='检测到当前账户未配置微信Token,请配置后再尝试启用MFA认证,否则可能造成系统无法正常登录。') + error='检测到当前账户未配置推送标识(账户管理/编辑),请配置后再尝试启用MFA认证,否则可能造成系统无法正常登录。') + spug_push_key = AppSetting.get_default('spug_push_key') + if not spug_push_key: + return json_response(error='检测到当前账户未绑定推送服务,请在系统设置/推送服务设置中绑定推送助手账户。') code = generate_random_str(6) - send_login_wx_code(request.user.wx_token, code) + send_login_code(spug_push_key, request.user.wx_token, code) cache.set(f'{request.user.username}:code', code, 300) return json_response() @@ -107,17 +109,6 @@ def email_test(request): return json_response(error=error) -@auth('admin') -def mfa_test(request): - if not request.user.wx_token: - return json_response( - error='检测到当前账户未配置微信Token,请配置后再尝试启用MFA认证,否则可能造成系统无法正常登录。') - code = generate_random_str(6) - send_login_wx_code(request.user.wx_token, code) - cache.set(f'{request.user.username}:code', code, 300) - return json_response() - - @auth('admin') def get_about(request): return json_response({ diff --git a/spug_api/libs/push.py b/spug_api/libs/push.py index 6c0d5189..5ff8561c 100644 --- a/spug_api/libs/push.py +++ b/spug_api/libs/push.py @@ -1,6 +1,7 @@ # Copyright: (c) OpenSpug Organization. https://github.com/openspug/spug # Copyright: (c) # Released under the AGPL-3.0 License. +from apps.setting.utils import AppSetting import requests push_server = 'https://push.spug.cc' @@ -24,3 +25,21 @@ def get_contacts(token): return res['data'] except Exception: return [] + + +def send_login_code(token, user, code): + url = f'{push_server}/spug/message/' + data = { + 'token': token, + 'targets': [user], + 'source': 'mfa', + 'dataset': { + 'code': code + } + } + res = requests.post(url, json=data, timeout=15) + if res.status_code != 200: + raise Exception(f'status code: {res.status_code}') + res = res.json() + if res.get('error'): + raise Exception(res['error']) diff --git a/spug_api/libs/spug.py b/spug_api/libs/spug.py index 6f76182f..e0ab6588 100644 --- a/spug_api/libs/spug.py +++ b/spug_api/libs/spug.py @@ -7,34 +7,9 @@ from libs.mail import Mail from libs.utils import human_datetime from libs.push import push_server -from functools import partial import requests import json -spug_server = 'https://api.spug.cc' -notify_source = 'monitor' -make_no_spug_key_notify = partial( - Notify.make_monitor_notify, - '发送报警信息失败', - '未配置报警服务调用凭据,请在系统管理/系统设置/基本设置/调用凭据中配置。' -) -make_no_push_key_notify = partial( - Notify.make_monitor_notify, - '发送报警信息失败', - '未绑定推送服务,请在系统管理/系统设置/推送服务设置中绑定推送助手账户。' -) - - -def send_login_wx_code(wx_token, code): - url = f'{spug_server}/apis/login/wx/' - spug_key = AppSetting.get_default('spug_key') - res = requests.post(url, json={'token': spug_key, 'user': wx_token, 'code': code}, timeout=30) - if res.status_code != 200: - raise Exception(f'status code: {res.status_code}') - res = res.json() - if res.get('error'): - raise Exception(res['error']) - class Notification: def __init__(self, grp, event, target, title, message, duration): @@ -44,7 +19,6 @@ def __init__(self, grp, event, target, title, message, duration): self.target = target self.message = message self.duration = duration - self.spug_key = AppSetting.get_default('spug_key') self.spug_push_key = AppSetting.get_default('spug_push_key') @staticmethod @@ -72,20 +46,6 @@ def handle_request(url, data, mode=None): raise NotImplementedError Notify.make_system_notify('通知发送失败', f'返回数据:{res}') - def monitor_by_wx(self, users): - if not self.spug_key: - make_no_spug_key_notify() - return - data = { - 'token': self.spug_key, - 'event': self.event, - 'subject': f'{self.title} >> {self.target}', - 'desc': self.message, - 'remark': f'故障持续{self.duration}' if self.event == '2' else None, - 'users': list(users) - } - self.handle_request(f'{spug_server}/apis/notify/wx/', data, 'spug') - def monitor_by_email(self, users): mail_service = AppSetting.get_default('mail_service', {}) body = [ @@ -101,17 +61,11 @@ def monitor_by_email(self, users): subject = f'{event_map[self.event]}-{self.title}' mail = Mail(**mail_service) mail.send_text_mail(users, subject, '\r\n'.join(body) + '\r\n\r\n自动发送,请勿回复。') - elif self.spug_key: - data = { - 'token': self.spug_key, - 'event': self.event, - 'subject': self.title, - 'body': '\r\n'.join(body), - 'users': list(users) - } - self.handle_request(f'{spug_server}/apis/notify/mail/', data, 'spug') else: - make_no_spug_key_notify() + Notify.make_monitor_notify( + '发送报警信息失败', + '未配置报警服务,请在系统管理/系统设置/报警服务设置中配置邮件服务。' + ) def monitor_by_dd(self, users): texts = [ @@ -158,7 +112,10 @@ def monitor_by_qy_wx(self, users): def monitor_by_spug_push(self, targets): if not self.spug_push_key: - make_no_push_key_notify() + Notify.make_monitor_notify( + '发送报警信息失败', + '未绑定推送服务,请在系统管理/系统设置/推送服务设置中绑定推送助手账户。' + ) return data = { 'source': 'monitor', @@ -188,15 +145,6 @@ def dispatch_monitor(self, modes): if mode == '1': wx_mp_ids = set(x for x in push_ids if x.startswith('wx_mp_')) targets.update(wx_mp_ids) - users = set(x.wx_token for x in Contact.objects.filter(id__in=u_ids, wx_token__isnull=False)) - if not users: - if not wx_mp_ids: - Notify.make_monitor_notify( - '发送报警信息失败', - '未找到可用的通知对象,请确保设置了相关报警联系人的微信Token。' - ) - continue - self.monitor_by_wx(users) elif mode == '2': sms_ids = set(x for x in push_ids if x.startswith('sms_')) targets.update(sms_ids) diff --git a/spug_web/src/pages/system/account/Form.js b/spug_web/src/pages/system/account/Form.js index 09e09d87..214ad1c2 100644 --- a/spug_web/src/pages/system/account/Form.js +++ b/spug_web/src/pages/system/account/Form.js @@ -3,11 +3,11 @@ * Copyright (c) * Released under the AGPL-3.0 License. */ -import React, { useState } from 'react'; -import { Link } from 'react-router-dom'; -import { observer } from 'mobx-react'; -import { Modal, Form, Select, Input, message } from 'antd'; -import http from 'libs/http'; +import React, {useState, useEffect} from 'react'; +import {Link} from 'react-router-dom'; +import {observer} from 'mobx-react'; +import {Modal, Form, Select, Input, message} from 'antd'; +import {http, includes} from 'libs'; import store from './store'; import rStore from '../role/store'; @@ -15,6 +15,12 @@ import rStore from '../role/store'; export default observer(function () { const [form] = Form.useForm(); const [loading, setLoading] = useState(false); + const [contacts, setContacts] = useState([]) + + useEffect(() => { + http.get('/api/alarm/contact/?only_push=1') + .then(res => setContacts(res)) + }, []); function handleSubmit() { setLoading(true); @@ -44,11 +50,13 @@ export default observer(function () { -