feat: notice_config access messenger (#190)

This commit is contained in:
simontigers 2023-10-09 17:32:20 +08:00 committed by GitHub
parent ccce5c830a
commit 297270063c
8 changed files with 220 additions and 42 deletions

View File

@ -177,7 +177,7 @@ class InitDepartment(object):
else: else:
resource_type = results[0] resource_type = results[0]
for name in ['公司信息']: for name in ['公司信息', '通知设置']:
payload = dict( payload = dict(
type_id=resource_type['id'], type_id=resource_type['id'],
app_id=acl.app_name, app_id=acl.app_name,

View File

@ -1,5 +1,5 @@
# -*- coding:utf-8 -*- # -*- coding:utf-8 -*-
from api.extensions import cache
from api.models.common_setting import CompanyInfo from api.models.common_setting import CompanyInfo
@ -11,14 +11,34 @@ class CompanyInfoCRUD(object):
@staticmethod @staticmethod
def create(**kwargs): def create(**kwargs):
return CompanyInfo.create(**kwargs) res = CompanyInfo.create(**kwargs)
CompanyInfoCache.refresh(res.info)
return res
@staticmethod @staticmethod
def update(_id, **kwargs): def update(_id, **kwargs):
kwargs.pop('id', None) kwargs.pop('id', None)
existed = CompanyInfo.get_by_id(_id) existed = CompanyInfo.get_by_id(_id)
if not existed: if not existed:
return CompanyInfoCRUD.create(**kwargs) existed = CompanyInfoCRUD.create(**kwargs)
else: else:
existed = existed.update(**kwargs) existed = existed.update(**kwargs)
return existed CompanyInfoCache.refresh(existed.info)
return existed
class CompanyInfoCache(object):
key = 'CompanyInfoCache::'
@classmethod
def get(cls):
info = cache.get(cls.key)
if not info:
res = CompanyInfo.get_by(first=True) or {}
info = res.get('info', {})
cache.set(cls.key, info)
return info
@classmethod
def refresh(cls, info):
cache.set(cls.key, info)

View File

@ -12,3 +12,10 @@ class OperatorType(BaseEnum):
LESS_THAN = 6 LESS_THAN = 6
IS_EMPTY = 7 IS_EMPTY = 7
IS_NOT_EMPTY = 8 IS_NOT_EMPTY = 8
BotNameMap = {
'wechatApp': 'wechatBot',
'feishuApp': 'feishuBot',
'dingdingApp': 'dingdingBot',
}

View File

@ -1,8 +1,9 @@
# -*- coding:utf-8 -*- # -*- coding:utf-8 -*-
import copy
import traceback import traceback
from datetime import datetime from datetime import datetime
import requests
from flask import abort from flask import abort
from flask_login import current_user from flask_login import current_user
from sqlalchemy import or_, literal_column, func, not_, and_ from sqlalchemy import or_, literal_column, func, not_, and_
@ -474,6 +475,58 @@ class EmployeeCRUD(object):
return [r.to_dict() for r in results] return [r.to_dict() for r in results]
@staticmethod
def remove_bind_notice_by_uid(_platform, _uid):
existed = EmployeeCRUD.get_employee_by_uid(_uid)
employee_data = existed.to_dict()
notice_info = copy.deepcopy(employee_data.get('notice_info', {}))
notice_info[_platform] = ''
existed.update(
notice_info=notice_info
)
return ErrFormat.notice_remove_bind_success
@staticmethod
def bind_notice_by_uid(_platform, _uid):
existed = EmployeeCRUD.get_employee_by_uid(_uid)
mobile = existed.mobile
if not mobile or len(mobile) == 0:
abort(400, ErrFormat.notice_bind_err_with_empty_mobile)
from api.lib.common_setting.notice_config import NoticeConfigCRUD
messenger = NoticeConfigCRUD.get_messenger_url()
if not messenger or len(messenger) == 0:
abort(400, ErrFormat.notice_please_config_messenger_first)
url = f"{messenger}/v1/uid/getbyphone"
try:
payload = dict(
phone=mobile,
sender=_platform
)
res = requests.post(url, json=payload)
result = res.json()
if res.status_code != 200:
raise Exception(result.get('msg', ''))
target_id = result.get('uid', '')
employee_data = existed.to_dict()
notice_info = copy.deepcopy(employee_data.get('notice_info', {}))
notice_info[_platform] = '' if not target_id else target_id
existed.update(
notice_info=notice_info
)
return ErrFormat.notice_bind_success
except Exception as e:
return abort(400, ErrFormat.notice_bind_failed.format(str(e)))
@staticmethod @staticmethod
def get_employee_notice_by_ids(employee_ids): def get_employee_notice_by_ids(employee_ids):
criterion = [ criterion = [

View File

@ -1,41 +1,104 @@
from api.models.common_setting import NoticeConfig import requests
from api.lib.common_setting.const import BotNameMap
from api.lib.common_setting.resp_format import ErrFormat
from api.models.common_setting import CompanyInfo, NoticeConfig
from wtforms import Form from wtforms import Form
from wtforms import StringField from wtforms import StringField
from wtforms import validators from wtforms import validators
from flask import abort from flask import abort, current_app
import smtplib
from email.mime.text import MIMEText
from email.utils import formataddr
class NoticeConfigCRUD(object): class NoticeConfigCRUD(object):
@staticmethod @staticmethod
def add_notice_config(**kwargs): def add_notice_config(**kwargs):
NoticeConfigCRUD.check_platform(kwargs.get('platform')) platform = kwargs.get('platform')
NoticeConfigCRUD.check_platform(platform)
info = kwargs.get('info', {})
if 'name' not in info:
info['name'] = platform
kwargs['info'] = info
try: try:
return NoticeConfig.create( NoticeConfigCRUD.update_messenger_config(**info)
res = NoticeConfig.create(
**kwargs **kwargs
) )
return res
except Exception as e: except Exception as e:
return abort(400, str(e)) return abort(400, str(e))
@staticmethod @staticmethod
def check_platform(platform): def check_platform(platform):
NoticeConfig.get_by(first=True, to_dict=False, platform=platform) and abort(400, f"{platform} 已存在!") NoticeConfig.get_by(first=True, to_dict=False, platform=platform) and \
abort(400, ErrFormat.notice_platform_existed.format(platform))
@staticmethod @staticmethod
def edit_notice_config(_id, **kwargs): def edit_notice_config(_id, **kwargs):
existed = NoticeConfigCRUD.get_notice_config_by_id(_id) existed = NoticeConfigCRUD.get_notice_config_by_id(_id)
try: try:
return existed.update(**kwargs) info = kwargs.get('info', {})
if 'name' not in info:
info['name'] = existed.platform
kwargs['info'] = info
NoticeConfigCRUD.update_messenger_config(**info)
res = existed.update(**kwargs)
return res
except Exception as e:
return abort(400, str(e))
@staticmethod
def get_messenger_url():
from api.lib.common_setting.company_info import CompanyInfoCache
com_info = CompanyInfoCache.get()
if not com_info:
return
messenger = com_info.get('messenger', '')
if len(messenger) == 0:
return
if messenger[-1] == '/':
messenger = messenger[:-1]
return messenger
@staticmethod
def update_messenger_config(**kwargs):
try:
messenger = NoticeConfigCRUD.get_messenger_url()
if not messenger or len(messenger) == 0:
raise Exception(ErrFormat.notice_please_config_messenger_first)
url = f"{messenger}/v1/senders"
name = kwargs.get('name')
bot_list = kwargs.pop('bot', None)
for k, v in kwargs.items():
if isinstance(v, bool):
kwargs[k] = 'true' if v else 'false'
else:
kwargs[k] = str(v)
payload = {name: [kwargs]}
current_app.logger.info(f"update_messenger_config: {url}, {payload}")
res = requests.put(url, json=payload, timeout=2)
current_app.logger.info(f"update_messenger_config: {res.status_code}, {res.text}")
if not bot_list or len(bot_list) == 0:
return
bot_name = BotNameMap.get(name)
payload = {bot_name: bot_list}
current_app.logger.info(f"update_messenger_config: {url}, {payload}")
bot_res = requests.put(url, json=payload, timeout=2)
current_app.logger.info(f"update_messenger_config: {bot_res.status_code}, {bot_res.text}")
except Exception as e: except Exception as e:
return abort(400, str(e)) return abort(400, str(e))
@staticmethod @staticmethod
def get_notice_config_by_id(_id): def get_notice_config_by_id(_id):
return NoticeConfig.get_by(first=True, to_dict=False, id=_id) or abort(400, f"{_id} 配置项不存在!") return NoticeConfig.get_by(first=True, to_dict=False, id=_id) or \
abort(400,
ErrFormat.notice_not_existed.format(_id))
@staticmethod @staticmethod
def get_all(): def get_all():
@ -43,38 +106,46 @@ class NoticeConfigCRUD(object):
@staticmethod @staticmethod
def test_send_email(receive_address, **kwargs): def test_send_email(receive_address, **kwargs):
# 设置发送方和接收方的电子邮件地址 messenger = NoticeConfigCRUD.get_messenger_url()
sender_email = 'test@test.com' if not messenger or len(messenger) == 0:
sender_name = 'Test Sender' abort(400, ErrFormat.notice_please_config_messenger_first)
url = f"{messenger}/v1/message"
recipient_email = receive_address recipient_email = receive_address
recipient_name = receive_address
subject = 'Test Email' subject = 'Test Email'
body = 'This is a test email' body = 'This is a test email'
payload = {
message = MIMEText(body, 'plain', 'utf-8') "sender": 'email',
message['From'] = formataddr((sender_name, sender_email)) "msgtype": "text/plain",
message['To'] = formataddr((recipient_name, recipient_email)) "title": subject,
message['Subject'] = subject "content": body,
"tos": [recipient_email],
smtp_server = kwargs.get('server') }
smtp_port = kwargs.get('port') current_app.logger.info(f"test_send_email: {url}, {payload}")
smtp_username = kwargs.get('username') response = requests.post(url, json=payload)
smtp_password = kwargs.get('password') if response.status_code != 200:
abort(400, response.text)
if kwargs.get('mail_type') == 'SMTP':
smtp_connection = smtplib.SMTP(smtp_server, smtp_port)
else:
smtp_connection = smtplib.SMTP_SSL(smtp_server, smtp_port)
if kwargs.get('is_login'):
smtp_connection.login(smtp_username, smtp_password)
smtp_connection.sendmail(sender_email, recipient_email, message.as_string())
smtp_connection.quit()
return 1 return 1
@staticmethod
def get_app_bot():
result = []
for notice_app in NoticeConfig.get_by(to_dict=False):
if notice_app.platform in ['email']:
continue
info = notice_app.info
name = info.get('name', '')
if name not in BotNameMap:
continue
result.append(dict(
name=info.get('name', ''),
label=info.get('label', ''),
bot=info.get('bot', []),
))
return result
class NoticeConfigForm(Form): class NoticeConfigForm(Form):
platform = StringField(validators=[ platform = StringField(validators=[
@ -91,4 +162,4 @@ class NoticeConfigUpdateForm(Form):
info = StringField(validators=[ info = StringField(validators=[
validators.DataRequired(message="信息 不能为空"), validators.DataRequired(message="信息 不能为空"),
validators.Length(max=255), validators.Length(max=255),
]) ])

View File

@ -56,3 +56,10 @@ class ErrFormat(CommonErrFormat):
email_send_timeout = "邮件发送超时" email_send_timeout = "邮件发送超时"
common_data_not_found = "ID {} 找不到记录" common_data_not_found = "ID {} 找不到记录"
notice_platform_existed = "{} 已存在"
notice_not_existed = "{} 配置项不存在"
notice_please_config_messenger_first = "请先配置 messenger"
notice_bind_err_with_empty_mobile = "绑定失败,手机号为空"
notice_bind_failed = "绑定失败: {}"
notice_bind_success = "绑定成功"
notice_remove_bind_success = "解绑成功"

View File

@ -156,3 +156,15 @@ class GetEmployeeNoticeByIds(APIView):
else: else:
result = EmployeeCRUD.get_employee_notice_by_ids(employee_ids) result = EmployeeCRUD.get_employee_notice_by_ids(employee_ids)
return self.jsonify(result) return self.jsonify(result)
class EmployeeBindNoticeWithACLID(APIView):
url_prefix = (f'{prefix}/by_uid/bind_notice/<string:platform>/<int:_uid>',)
def put(self, platform, _uid):
data = EmployeeCRUD.bind_notice_by_uid(platform, _uid)
return self.jsonify(info=data)
def delete(self, platform, _uid):
data = EmployeeCRUD.remove_bind_notice_by_uid(platform, _uid)
return self.jsonify(info=data)

View File

@ -69,3 +69,11 @@ class NoticeConfigGetView(APIView):
def get(self): def get(self):
res = NoticeConfigCRUD.get_all() res = NoticeConfigCRUD.get_all()
return self.jsonify(res) return self.jsonify(res)
class NoticeAppBotView(APIView):
url_prefix = (f'{prefix}/app_bot',)
def get(self):
res = NoticeConfigCRUD.get_app_bot()
return self.jsonify(res)