This commit is contained in:
王思川 2022-04-26 17:04:09 +08:00
parent 39820c5341
commit 0ee3b3f579
18 changed files with 594 additions and 13 deletions

View File

@ -9,10 +9,9 @@ from werkzeug.security import check_password_hash
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
from DBHelper.MongoHelper import MongoHelper
from Utils.ErrorUtil import ReturnConditionCheckFailed, LogConditionCheckFailed
from Utils.ErrorUtil import ReturnConditionCheckFailed
from CompanyUser.CompanyUserObj import CompanyUser, VerifyInfo, EmailVerifyCodeRecord, VerifyMaterial, \
CompanyVerifyThreeFactors
from Utils.ValidateUtil import ValidateAttr
class CompanyUserImpl(CompanyUser):

View File

@ -1,7 +1,7 @@
from flask import Blueprint, request, Response
from common.rsa import decrypt_data
from CompanyUser.CompanyUserAuth import check_block, verify_token
from Utils.AuthUtil import check_block, verify_token
from Utils.ErrorUtil import ReturnConditionCheckFailed
from CompanyUser.CompanyUserImpl import CompanyUserImpl, EmailVerifyCodeRecordImpl, VerifyMaterialImpl, \
CompanyVerifyThreeFactorsImpl

View File

@ -0,0 +1,21 @@
from Utils.ObjUtil import SpecObject
from Utils.ValidateUtil import ValidateAttr, Validate
class EmailNotice(SpecObject):
"""用户邮件通知"""
email = ValidateAttr(field='email', func=Validate.email, error_info='邮箱格式异常', error_code=200)
v_period = ValidateAttr(field='v_period', type=float, error_info='验证有效期格式异常', error_code=200)
v_code = ValidateAttr(field='v_code', type=str, length=6, error_info='验证码格式异常', error_code=200)
v_type = ValidateAttr(field="v_type", type=str, in_list=["register", "resetemail", "resetpwd"], error_info="邮件验证类型错误", error_code=200)
fields_map = {
"email": "邮箱",
"v_period": "验证有效期",
"v_code": "验证码",
"v_type": "验证类型"
}
def send_email(self):
"""发送邮件"""

View File

@ -0,0 +1,216 @@
import json
import time
import random
import base64
import requests
from urllib.request import Request, urlopen
from werkzeug.security import check_password_hash, generate_password_hash
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
from DBHelper.MongoHelper import MongoHelper
from ObjectsInProject.User.TFSECompanyUser import TFSECompanyUser
from Utils.ErrorUtil import ReturnConditionCheckFailed
class TFSECompanyUserImpl(TFSECompanyUser):
"""企业用户实现类"""
db = MongoHelper("tfse_v0.21")
def check_email_registered(self):
"""检查邮箱已被注册"""
email = self.db.find_single_column(
"应用端",
"企业用户",
{"邮箱": self.email},
"邮箱"
)
if email is not None:
raise ReturnConditionCheckFailed("邮箱已被注册", 200)
def check_email_not_registered(self):
"""检查邮箱未被注册"""
email = self.db.find_single_column(
"应用端",
"企业用户",
{"邮箱": self.email},
"邮箱"
)
if email is None:
raise ReturnConditionCheckFailed("邮箱未被注册", 200)
def check_vcode_correct(self, code):
"""检查邮箱验证码是否正确"""
verify_data = self.db.find_single_data(
"应用端",
"邮箱验证码记录",
{"邮箱": self.email},
["验证码", "验证有效期"]
)
if not verify_data:
raise ReturnConditionCheckFailed("验证码错误", 200)
if verify_data['验证码'] != code:
raise ReturnConditionCheckFailed("验证码错误", 200)
if time.time() - verify_data['验证有效期'] > 300:
raise ReturnConditionCheckFailed('验证码过期', 200)
def login(self):
"""登录"""
company_user = self.db.find_single_data(
"应用端",
"企业用户",
{"邮箱": self.email},
["企业ID", "企业名称", "邮箱", "密码", "已认证"]
)
def check_user_existed():
"""检查用户是否存在"""
if company_user is None:
raise ReturnConditionCheckFailed("不存在该用户", 200)
def check_password_correct():
"""检查密码是否正确"""
if not check_password_hash(company_user['密码'], self.pwd):
raise ReturnConditionCheckFailed("登录密码错误", 200)
def create_token(param):
"""
创建token
param: 传入参数用于创建token一般为 {"cid": cid}
return: 用户token
"""
secret_key = '0FTuOi^#Afx1@2@F'
token_expire = 14400
s = Serializer(secret_key, expires_in=token_expire)
token = '' + s.dumps(param).decode('ascii')
return token
check_user_existed()
check_password_correct()
self.cid = company_user['企业ID']
self.name = self.get_attr(company_user, '企业名称', default='未认证企业用户')
self.verify_status = company_user['已认证']
self.token = create_token({"cid": self.cid})
def register(self, code):
"""注册"""
def make_new_cid():
"""生成新的企业ID如果该ID存在则重新生成"""
def random_cid(num):
"""随机企业ID"""
choices = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
salt = ''
for i in range(num):
salt += random.choice(choices)
return salt
new_cid = random_cid(8)
case = self.db.find_single_column(
"应用端",
"企业用户",
{"企业ID": new_cid},
"企业ID"
) is not None
while case:
new_cid = random_cid(8)
return new_cid
self.check_email_registered()
self.check_vcode_correct(code)
self.cid = make_new_cid()
self.avatar_id = "623152edf36000004f00124e"
self.verify_status = ""
self.db.insert_single_data(
"应用端",
"企业用户",
self.dict_to_return()
)
self.db.delete_single_data(
"应用端",
"邮箱验证码记录",
{"邮箱": self.email}
)
def get_company_user_info(self):
"""获取企业用户信息"""
company_user_data = self.db.find_single_data(
"应用端",
"企业用户",
{"企业ID": self.cid},
["企业ID", "企业名称", "邮箱", "已认证"]
)
self.name = self.get_attr(company_user_data, '企业名称', default='未认证企业用户')
self.email = company_user_data['邮箱']
self.verify_status = company_user_data['已认证']
def get_avatar(self):
"""获取用户头像"""
self.avatar_id = self.db.find_single_column(
"应用端",
"企业用户",
{"企业ID": self.cid},
"头像fid"
)
avatar = self.db.find_file(
"文件",
"企业用户头像",
self.avatar_id
)
return avatar
def change_avatar(self, avatar_option):
"""修改企业用户头像"""
avatars = {
"avatar_01": "623152edf36000004f00124e",
"avatar_02": "623152edf36000004f001250",
"avatar_03": "623152edf36000004f00124f",
"avatar_04": "623152edf36000004f001251",
"avatar_05": "623152edf36000004f001252",
"avatar_06": "623152edf36000004f001253"
}
self.avatar_id = avatars[avatar_option]
self.db.update_single_data(
"应用端",
"企业用户",
{"企业ID": self.cid},
{"头像fid": self.avatar_id}
)
def change_password(self, code):
"""修改登录密码"""
self.check_email_not_registered()
self.check_vcode_correct(code)
self.db.update_single_data(
"应用端",
"企业用户",
{"邮箱": self.email},
self.dict_to_save(columns=["密码"])
)
def change_email(self, code):
"""更换邮箱"""
self.check_vcode_correct(code)
self.check_email_registered()
self.db.update_single_data(
"应用端",
"企业用户",
{"企业ID": self.cid},
self.dict_to_save(columns=["邮箱"])
)

View File

@ -0,0 +1,22 @@
from Utils.ObjUtil import SpecObject
from Utils.ValidateUtil import ValidateAttr, Validate
class TobUser(SpecObject):
"""企业用户类"""
cid = ValidateAttr(field='cid', type=str)
pwd = ValidateAttr(field='pwd', func=Validate.password, error_info='密码强度不够')
name = ValidateAttr(field='name', type=str)
email = ValidateAttr(field='email', func=Validate.email, error_info='邮箱格式错误')
telephone = ValidateAttr(field='telephone', func=Validate.telephone, error_info='手机号格式错误')
register_time = ValidateAttr(field='register_time', func=Validate.time_format)
fields_map = {
"cid": "企业ID",
"pwd": "密码",
"name": "企业名称",
"email": "邮箱",
"telephone": "手机号",
"register_time": "注册时间"
}

View File

@ -0,0 +1,20 @@
from Utils.ObjUtil import SpecObject
from Utils.ValidateUtil import ValidateAttr
class User(SpecObject):
"""普通用户"""
uid = ValidateAttr(field='uid', type=str)
name = ValidateAttr(field='name', type=str)
pwd = ValidateAttr(field='pwd', type=str)
email = ValidateAttr(field='email', type=str)
telephone = ValidateAttr(field='telephone', type=str)
fields_map = {
"uid": "用户ID",
"name": "姓名",
"pwd": "密码",
"email": "邮箱",
"telephone": "手机号"
}

View File

@ -0,0 +1,79 @@
from werkzeug.security import generate_password_hash
from Utils.ObjUtil import SpecObject
from Utils.ValidateUtil import ValidateAttr, Validate
class TFSECompanyUser(SpecObject):
"""天府股交项企业用户"""
class VerifyInfo(SpecObject):
"""认证信息"""
name = ValidateAttr(field='name', type=str)
code = ValidateAttr(field='code', type=str)
legal_person = ValidateAttr(field='legal_person', type=str)
legal_person_id = ValidateAttr(field='legal_person_id', type=str)
fields_map = {
"name": "企业名称",
"code": "统一社会信用代码",
"legal_person": "法人姓名",
"legal_person_id": "法人身份证号"
}
cid = ValidateAttr(field='cid', type=str)
pwd = ValidateAttr(field='pwd', func=Validate.password, error_info='密码强度不够')
name = ValidateAttr(field='name', type=str)
email = ValidateAttr(field='email', func=Validate.email, error_info='邮箱格式错误')
telephone = ValidateAttr(field='telephone', func=Validate.telephone, error_info='手机号格式错误')
register_time = ValidateAttr(field='register_time', func=Validate.time_format)
avatar_id = ValidateAttr(field='avatar_id', type=str, length=24)
verify_status = ValidateAttr(field='verify_status', in_list=["", ""])
verify_info = ValidateAttr(field='verify_info', type=VerifyInfo)
token = ValidateAttr(field='token', type=str)
fields_map = {
"cid": "企业ID",
"pwd": "密码",
"name": "企业名称",
"email": "邮箱",
"telephone": "手机号",
"register_time": "注册时间",
"avatar_id": "头像fid",
"verify_status": "已认证",
"verify_info": "认证信息",
"token": "token"
}
def dict_to_return(self, **kwargs):
_dict_ = self.dict_keys_toggle(columns=kwargs['columns']) if kwargs.__contains__('columns') else self.dict_keys_toggle()
if kwargs.__contains__('verify_status'):
if kwargs['verify_status'] is True:
_dict_['认证状态'] = '已认证' if _dict_.pop('已认证') == '' else '未认证'
if _dict_.__contains__('密码'):
_dict_['密码'] = generate_password_hash(_dict_['密码'])
return _dict_
def login(self, **kwargs):
"""登录"""
def register(self, **kwargs):
"""注册"""
def get_company_user_info(self):
"""获取企业用户信息"""
def get_avatar(self):
"""获取用户头像"""
def change_avatar(self, **kwargs):
"""修改用户头像"""
def change_password(self, **kwargs):
"""修改登录密码"""
def change_email(self, **kwargs):
"""修改登录邮箱"""

View File

View File

@ -1,5 +1,5 @@
from flask import Blueprint, request
from CompanyUser.CompanyUserAuth import verify_token, verify_real_company
from Utils.AuthUtil import verify_token, verify_real_company
from Rating.Credit.CreditImpl import CreditRating
from Utils.ErrorUtil import ReturnConditionCheckFailed

View File

@ -1,5 +1,5 @@
from flask import Blueprint, request
from CompanyUser.CompanyUserAuth import verify_token, verify_real_company
from Utils.AuthUtil import verify_token
from Rating.Esg.EsgImpl import EsgRating
from Utils.ErrorUtil import ReturnConditionCheckFailed

View File

@ -1,7 +1,7 @@
from flask import Blueprint
from CompanyUser.CompanyUserAuth import verify_token
from Utils.AuthUtil import verify_token
from Utils.ErrorUtil import ReturnConditionCheckFailed
from Implements.Company.Index import CompanyIndexImpl

View File

@ -0,0 +1,207 @@
from flask import Blueprint, request, Response
from Implements.User.TFSECompanyUserImpl import TFSECompanyUserImpl
from common.rsa import decrypt_data
from Utils.AuthUtil import check_block, verify_token
from Utils.ErrorUtil import ReturnConditionCheckFailed
from CompanyUser.CompanyUserImpl import EmailVerifyCodeRecordImpl, VerifyMaterialImpl, \
CompanyVerifyThreeFactorsImpl
company_user_route = Blueprint('user', __name__)
@company_user_route.route('/login', methods=['POST'])
@check_block
def login():
"""企业用户登录"""
try:
impl = TFSECompanyUserImpl()
impl.email = request.json['email']
try:
impl.pwd = decrypt_data(encrypt_msg=request.json['pwd'])
except Exception:
return {"info": "登录密码错误"}, 200
impl.login()
result = impl.dict_to_return(columns=["企业名称", "已认证", "token"], verify_status=True)
return {"info": "登陆成功", "result": result}, 200
except ReturnConditionCheckFailed as e:
e.log_error()
return {"info": e.failed_info}, e.status_code
except KeyError:
return {"info": "参数异常"}, 400
@company_user_route.route('/register', methods=['POST'])
@check_block
def register():
"""企业用户注册"""
try:
req = request.json
company_user = TFSECompanyUserImpl()
company_user.email = req['email']
try:
company_user.pwd = decrypt_data(encrypt_msg=req['pwd'])
except Exception:
return {"info": "密码格式错误"}, 200
company_user.register(req['code'])
response = {"info": "注册成功"}, 200
return response
except ReturnConditionCheckFailed as e:
e.log_error()
return {"info": e.failed_info}, e.status_code
except KeyError:
return {"info": "参数异常"}, 400
@company_user_route.route('/user_info', methods=['GET'])
@verify_token
def user_info(**kwargs):
"""获取企业用户信息"""
try:
impl = TFSECompanyUserImpl()
impl.cid = kwargs['cid']
impl.get_company_user_info()
result= impl.dict_to_return(columns=["企业ID", "企业名称", "邮箱", "已认证"], verify_status=True)
return {"info": "查询结果", "result": result}, 200
except ReturnConditionCheckFailed as e:
e.log_error()
return {"info": e.failed_info}, e.status_code
except KeyError:
return {"info": "参数异常"}, 400
@company_user_route.route('/get_avatar', methods=['GET'])
@verify_token
def get_avatar(**kwargs):
"""获取头像"""
try:
impl = TFSECompanyUserImpl()
impl.cid = kwargs['cid']
response = Response(impl.get_avatar(), content_type='image/jpeg')
return response
except ReturnConditionCheckFailed as e:
e.log_error()
return {"info": e.failed_info}, e.status_code
except KeyError:
return {"info": "参数异常"}, 400
@company_user_route.route('/change_avatar', methods=['POST'])
@verify_token
def change_avatar(**kwargs):
"""修改头像"""
try:
impl = TFSECompanyUserImpl()
impl.cid = kwargs['cid']
impl.change_avatar(request.json['avatar_id'])
return {"info": "修改成功"}, 200
except ReturnConditionCheckFailed as e:
e.log_error()
return {"info": e.failed_info}, e.status_code
except KeyError:
return {"info": "参数异常"}, 400
@company_user_route.route('/change_pwd', methods=['POST'])
@check_block
def change_pwd():
"""修改密码"""
try:
req = request.json
impl = TFSECompanyUserImpl()
impl.email = req['email']
impl.pwd = decrypt_data(encrypt_msg=req['pwd'])
impl.change_password(req['code'])
return {"info": "修改成功"}, 200
except ReturnConditionCheckFailed as e:
e.log_error()
return {"info": e.failed_info}, e.status_code
except KeyError:
return {"info": "参数异常"}, 400
@company_user_route.route('/change_email', methods=['POST'])
@check_block
@verify_token
def change_email(**kwargs):
"""更换账号邮箱"""
try:
req = request.json
impl = TFSECompanyUserImpl()
impl.cid = kwargs['cid']
impl.email = req['email']
impl.change_email(req['code'])
return {"info": "修改成功"}, 200
except ReturnConditionCheckFailed as e:
e.log_error()
return {"info": e.failed_info}, e.status_code
except KeyError:
return {"info": "参数异常"}, 400
@company_user_route.route('/verify_email', methods=['POST'])
@check_block
def verify_email():
"""发送邮箱验证码"""
try:
req = request.json
email_verify = EmailVerifyCodeRecordImpl()
email_verify.email = req['email']
email_verify.v_type = req['v_type']
email_verify.send_email()
return {"info": "邮件已发送"}, 200
except ReturnConditionCheckFailed as e:
e.log_error()
return {"info": e.failed_info}, e.status_code
except KeyError:
return {"info": "参数异常"}, 400
@company_user_route.route('/upload_id_card', methods=['POST'])
@verify_token
def upload_id_card(**kwargs):
"""上传身份证"""
try:
material = VerifyMaterialImpl()
material.cid = kwargs['cid']
material.image = request.files['image']
result = material.upload_id_card()
return {"info": "识别结果", "result": result}, 200
except ReturnConditionCheckFailed as e:
e.log_error()
return {"info": e.failed_info}, e.status_code
except KeyError:
return {"info": "参数异常"}, 400
@company_user_route.route('/upload_business_license', methods=['POST'])
@verify_token
def upload_business_license(**kwargs):
"""上传营业执照"""
try:
material = VerifyMaterialImpl()
material.cid = kwargs['cid']
material.image = request.files['image']
result = material.upload_business_license()
return {"info": "识别结果", "result": result}, 200
except ReturnConditionCheckFailed as e:
e.log_error()
return {"info": e.failed_info}, e.status_code
except KeyError:
return {"info": "参数异常"}, 400
@company_user_route.route('/company_verify', methods=['GET'])
@verify_token
def company_verify_route(**kwargs):
"""企业认证"""
try:
company_verify = CompanyVerifyThreeFactorsImpl()
company_verify.cid = kwargs['cid']
company_verify.company_verify()
return {"info": "认证成功"}, 200
except ReturnConditionCheckFailed as e:
e.log_error()
return {"info": e.failed_info}, e.status_code
except KeyError:
return {"info": "参数异常"}, 400

0
Routes/User/__init__.py Normal file
View File

View File

@ -8,21 +8,21 @@ class SpecObject(object):
def dict_keys_toggle(self, **kwargs):
"""字典键值切换"""
_dict_ = dict()
default_types = ['str', 'int', 'float', 'dict', 'bool', 'tuple']
for key in self.__dict__.keys():
if type(self.__dict__[key]).__name__ in ['str', 'int', 'float', 'dict', 'bool', 'tuple']:
if type(self.__dict__[key]).__name__ in default_types:
_dict_[self.fields_map[key]] = self.__dict__[key]
elif type(self.__dict__[key]).__name__ == 'list':
if len(self.__dict__[key]) == 0:
_dict_[self.fields_map[key]] = self.__dict__[key]
elif type(self.__dict__[key][0]).__name__ in ['str', 'int', 'float', 'dict', 'bool', 'tuple']:
elif type(self.__dict__[key][0]).__name__ in default_types:
_dict_[self.fields_map[key]] = self.__dict__[key]
else:
_dict_[self.fields_map[key]] = [item.dict_to_save() for item in self.__dict__[key]]
_dict_[self.fields_map[key]] = [item.dict_keys_toggle() for item in self.__dict__[key]]
elif self.__dict__[key] is None:
_dict_[self.fields_map[key]] = self.__dict__[key]
else:
_dict_[self.fields_map[key]] = self.__dict__[key].dict_to_show()
_dict_[self.fields_map[key]] = self.__dict__[key].dict_keys_toggle()
if 'columns' in kwargs:
_dict_ = {key: _dict_[key] for key in kwargs['columns']}
@ -61,3 +61,13 @@ class SpecObject(object):
list_.append(instance)
return list_
@staticmethod
def get_attr(_dict_, _key_, **kwargs):
"""获取字典属性值"""
value = kwargs['default'] if kwargs.__contains__('default') else None
try:
value = _dict_[_key_]
except KeyError:
pass
return value

View File

@ -21,6 +21,13 @@ class Validate(object):
case = (len(param) >= 8) and (re.match(regex, param) is not None)
return True if case else False
@staticmethod
def telephone(param):
"""手机号格式"""
regex = "(^(13[0-9]|14[01456879]|15[0-3,5-9]|16[2567]|17[0-8]|18[0-9]|19[0-3,5-9])d{8}$)"
case = re.match(regex, param) is not None
return True if case else False
@staticmethod
def date_format(param):
"""yyyy-mm-dd"""

2
app.py
View File

@ -3,8 +3,8 @@ from flask_cors import *
from Routes.Company.Index import company_route
from Routes.User.TFSECompanyUserRoute import company_user_route
from CompanyUser.CompanyUserRoute import company_user_route
from file.file_routes import file_route
from Rating.Credit.CreditRoutes import credit_route
from Rating.Esg.EsgRoutes import esg_route

View File

@ -1,6 +1,6 @@
from flask import Blueprint, request, Response
from CompanyUser.CompanyUserAuth import verify_token, verify_report_view_auth
from Utils.AuthUtil import verify_token, verify_report_view_auth
from file.file_obj import TfseFile
file_route = Blueprint('file', __name__)