优化代码,修复定时任务检测证书获取异常并清理问题

重要: 开发者账号有时候会获取到非本人开发证书问题,估计是苹果问题,【该问题导致三个开发者证书被系统自动清理】
pull/37/head
nineven 3 years ago
parent fc1963c8a9
commit 4e7927a332
  1. 6
      fir_client/src/components/user/FirSuperSignBase.vue
  2. 2
      fir_client/src/restful/download.js
  3. 2
      fir_client/src/utils/index.js
  4. 3
      fir_ser/common/base/magic.py
  5. 2
      fir_ser/config.py
  6. 33
      fir_ser/xsign/utils/ctasks.py
  7. 2
      fir_ser/xsign/utils/iossignapi.py
  8. 28
      fir_ser/xsign/utils/supersignutils.py
  9. 6
      fir_ser/xsign/views/supersign.py

@ -1774,7 +1774,7 @@ export default {
}, },
canceledit() { canceledit() {
this.dialogaddDeveloperVisible = false; this.dialogaddDeveloperVisible = false;
this.editdeveloperinfo = {auth_type: 0, usable_number: 100, app_limit_number: 100}; this.editdeveloperinfo = {auth_type: 0, usable_number: 100, app_limit_number: 100, p8key: ''};
this.isedit = false; this.isedit = false;
this.placeholder = "" this.placeholder = ""
}, },
@ -1944,12 +1944,12 @@ export default {
this.canceledit(); this.canceledit();
this.$message.success("操作成功"); this.$message.success("操作成功");
this.activeName = "iosdeveloper"; this.activeName = "iosdeveloper";
this.editdeveloperinfo = {auth_type: 0, usable_number: 100, app_limit_number: 100}; this.editdeveloperinfo = {auth_type: 0, usable_number: 100, app_limit_number: 100, p8key: ''}
} }
if (params.methods === 'POST') { if (params.methods === 'POST') {
this.$message.success("添加成功"); this.$message.success("添加成功");
this.activeName = "iosdeveloper"; this.activeName = "iosdeveloper";
this.editdeveloperinfo = {auth_type: 0, usable_number: 100, app_limit_number: 100}; this.editdeveloperinfo = {auth_type: 0, usable_number: 100, app_limit_number: 100, p8key: ''}
} }
} else if (data.code === 1008) { } else if (data.code === 1008) {
this.$message.error(data.msg); this.$message.error(data.msg);

@ -153,7 +153,7 @@ export function getAuthTokenFun(callBack, params) {
export function geetest(self, uid, params, callback) { export function geetest(self, uid, params, callback) {
return geetestbase(self, loginFun, uid, params, callback, res => { return geetestbase(loginFun, self, uid, params, callback, res => {
alert(res.msg); alert(res.msg);
}) })
} }

@ -351,7 +351,7 @@ export function geetest(self, uid, params, callback) {
text: 'Loading', text: 'Loading',
spinner: 'el-icon-loading', spinner: 'el-icon-loading',
}); });
return geetestbase(self, loginFun, uid, params, callback, res => { return geetestbase(loginFun, self, uid, params, callback, res => {
self.$message({ self.$message({
message: res.msg, message: res.msg,
type: 'error' type: 'error'

@ -56,7 +56,8 @@ def call_function_try_attempts(try_attempts=3, sleep_time=2, failed_callback=Non
if not res[0]: if not res[0]:
logger.error(f'exec {func} failed after the maximum number of attempts. Failed:{res[1]}') logger.error(f'exec {func} failed after the maximum number of attempts. Failed:{res[1]}')
if failed_callback: if failed_callback:
failed_callback() logger.error(f'exec {func} failed and exec failed callback {failed_callback.__name__}')
failed_callback(*args, **kwargs)
logger.info(f"exec {func} finished. time:{time.time() - start_time}") logger.info(f"exec {func} finished. time:{time.time() - start_time}")
return res return res

@ -357,7 +357,7 @@ class APPLEDEVELOPERCONF(object):
# (-1, '疑似被封'), (0, '未激活'), (1, '已激活'), (2, '协议待同意'), (3, '维护中'), (4, '证书过期'), (5, '状态异常') # (-1, '疑似被封'), (0, '未激活'), (1, '已激活'), (2, '协议待同意'), (3, '维护中'), (4, '证书过期'), (5, '状态异常')
DEVELOPER_SIGN_STATUS = [1] # 开发者可用于签名的查询 DEVELOPER_SIGN_STATUS = [1] # 开发者可用于签名的查询
DEVELOPER_USE_STATUS = [1, 2, 3, 4, 5] # 开发者可用状态,详情查看 model.AppIOSDeveloperInfo DEVELOPER_USE_STATUS = [1, 2, 3, 4, 5] # 开发者可用状态,详情查看 model.AppIOSDeveloperInfo
DEVELOPER_AUTO_CHECK_STATUS = [1, 2, 5] # 定时认证自动检测 DEVELOPER_AUTO_CHECK_STATUS = [1, 2, 4, 5] # 定时认证自动检测
DEVELOPER_WRITE_STATUS = [1, 3, 4] # 开发者api写操作查询 DEVELOPER_WRITE_STATUS = [1, 3, 4] # 开发者api写操作查询
DEVELOPER_DISABLED_STATUS = [2, 4, 5] # 开发者不可 修改为状态,用户前端控制 DEVELOPER_DISABLED_STATUS = [2, 4, 5] # 开发者不可 修改为状态,用户前端控制
DEVELOPER_UID_KEY = "T:" # 开发者共享给其他第三方用户, 中间必须包含 : 前端需要根据 : 进行分割 DEVELOPER_UID_KEY = "T:" # 开发者共享给其他第三方用户, 中间必须包含 : 前端需要根据 : 进行分割

@ -6,7 +6,9 @@
import logging import logging
import os import os
import random
import time import time
from concurrent.futures import ThreadPoolExecutor
from django.template import loader from django.template import loader
@ -34,24 +36,33 @@ def auto_delete_ios_mobile_tmp_file():
def auto_check_ios_developer_active(): def auto_check_ios_developer_active():
all_ios_developer = AppIOSDeveloperInfo.objects.filter(status__in=Config.DEVELOPER_AUTO_CHECK_STATUS,
auto_check=True)
error_issuer_id = {} error_issuer_id = {}
for ios_developer in all_ios_developer:
userinfo = ios_developer.user_id def check_active_task(developer_obj):
err_issuer_id = error_issuer_id.get(userinfo.uid, []) time.sleep(random.randint(1, 5))
if userinfo.supersign_active: user_obj = developer_obj.user_id
status, result = IosUtils.active_developer(ios_developer) err_issuer_id = error_issuer_id.get(user_obj.uid, [])
msg = f"auto_check_ios_developer_active user:{userinfo} ios.developer:{ios_developer} status:{status} result:{result}" if user_obj.supersign_active:
err_issuer_id.append(ios_developer) status, result = IosUtils.active_developer(developer_obj, False)
error_issuer_id[userinfo.uid] = list(set(err_issuer_id)) msg = f"auto_check_ios_developer_active user:{user_obj} ios.developer:{developer_obj} status:{status} result:{result}"
err_issuer_id.append(developer_obj)
error_issuer_id[user_obj.uid] = list(set(err_issuer_id))
if status: if status:
IosUtils.get_device_from_developer(ios_developer) IosUtils.get_device_from_developer(developer_obj)
logger.info(msg) logger.info(msg)
else: else:
logger.error(msg) logger.error(msg)
ios_developer_queryset = AppIOSDeveloperInfo.objects.filter(status__in=Config.DEVELOPER_AUTO_CHECK_STATUS,
auto_check=True, user_id__is_active=True,
user_id__supersign_active=True)
pools = ThreadPoolExecutor(10)
for ios_developer_obj in ios_developer_queryset:
pools.submit(check_active_task, ios_developer_obj)
pools.shutdown()
for uid, developer_obj_list in error_issuer_id.items(): for uid, developer_obj_list in error_issuer_id.items():
userinfo = UserInfo.objects.filter(uid=uid).first() userinfo = UserInfo.objects.filter(uid=uid).first()
content = loader.render_to_string('check_developer.html', content = loader.render_to_string('check_developer.html',

@ -56,7 +56,7 @@ def exec_shell(cmd, timeout=None):
result = shell_command(cmd, timeout) result = shell_command(cmd, timeout)
logger.info(f"exec_shell cmd:{cmd} result:{result}") logger.info(f"exec_shell cmd:{cmd} result:{result}")
if result.get("exit_code") != 0: if result.get("exit_code") != 0:
err_info = result.get("err_info", None) err_info = result.get("err_info", result.get("return_info", None))
if err_info: if err_info:
logger.error(f"exec_shell cmd:{cmd} failed: {err_info}") logger.error(f"exec_shell cmd:{cmd} failed: {err_info}")
result["err_info"] = "Unknown Error" result["err_info"] = "Unknown Error"

@ -406,6 +406,18 @@ def check_sign_is_exists(user_obj, app_obj, udid, developer_obj, sign=True):
logger.warning(f"udid {udid} not exist app_id {app_obj} . start find developer and sign") logger.warning(f"udid {udid} not exist app_id {app_obj} . start find developer and sign")
def active_failed_callback(*args, **kwargs):
developer_obj, auto_clean = args
if auto_clean:
logger.warning(f"clean developer {developer_obj}")
IosUtils.clean_developer(developer_obj, developer_obj.user_id)
developer_obj.certid = None
developer_obj.cert_expire_time = None
else:
developer_obj.status = 4
developer_obj.save(update_fields=['certid', 'cert_expire_time', 'status'])
class IosUtils(object): class IosUtils(object):
def __init__(self, udid_info, user_obj, app_obj=None): def __init__(self, udid_info, user_obj, app_obj=None):
self.developer_obj = None self.developer_obj = None
@ -699,7 +711,7 @@ class IosUtils(object):
'err_match_msg': ["There is no App ID with ID"] 'err_match_msg': ["There is no App ID with ID"]
}, },
{ {
'func_list': [err_callback(IosUtils.active_developer, developer_obj)], 'func_list': [err_callback(IosUtils.active_developer, developer_obj, True)],
'err_match_msg': ["There are no current certificates on this team matching the provided certificate"] 'err_match_msg': ["There are no current certificates on this team matching the provided certificate"]
} }
]) ])
@ -882,6 +894,10 @@ class IosUtils(object):
d_result['msg'] = '数据更新失败,请稍后重试' d_result['msg'] = '数据更新失败,请稍后重试'
return status, d_result return status, d_result
else: else:
# 导致签名问题:
# 1.描述文件下载失败,也就是描述文件不存在
# 2.IPA 包打包编码有误,非utf-8编码打包
# 3.签名证书有误或者不存在
d_result['code'] = 1004 d_result['code'] = 1004
d_result['msg'] = '签名失败,请检查包是否正常' d_result['msg'] = '签名失败,请检查包是否正常'
return status, d_result return status, d_result
@ -1017,6 +1033,7 @@ class IosUtils(object):
return False, {'err_info': str(e)} return False, {'err_info': str(e)}
@staticmethod @staticmethod
@call_function_try_attempts(failed_callback=active_failed_callback)
def active_developer(developer_obj, auto_clean=True): def active_developer(developer_obj, auto_clean=True):
""" """
激活开发者账户 激活开发者账户
@ -1033,14 +1050,13 @@ class IosUtils(object):
developer_obj.cert_expire_time = format_apple_date(cert_obj.expirationDate) developer_obj.cert_expire_time = format_apple_date(cert_obj.expirationDate)
cert_is_exists = False cert_is_exists = False
break break
developer_obj.status = 1
if developer_obj.certid and len(developer_obj.certid) > 3 and cert_is_exists and len(result) > 0: if developer_obj.certid and len(developer_obj.certid) > 3 and cert_is_exists and len(result) > 0:
# 数据库证书id和苹果开发id不一致,可认为被用户删掉,需要执行清理开发者操作 # 数据库证书id和苹果开发id不一致,可认为被用户删掉,需要执行清理开发者操作
if auto_clean: if auto_clean:
logger.warning(f"clean developer {developer_obj}") # 捕获失败结果,三次重试之后,执行callback 方法,避免一次执行失败直接清理数据
IosUtils.clean_developer(developer_obj, developer_obj.user_id) return False, {'return_info': '证书检测有误'}
developer_obj.certid = None developer_obj.status = 4
developer_obj.cert_expire_time = None
developer_obj.status = 1
developer_obj.save(update_fields=['certid', 'cert_expire_time', 'status']) developer_obj.save(update_fields=['certid', 'cert_expire_time', 'status'])
return status, result return status, result

@ -108,7 +108,7 @@ class DeveloperView(APIView):
if issuer_ids: if issuer_ids:
for developer_s_obj in AppIOSDeveloperInfo.objects.filter(user_id=request.user, for developer_s_obj in AppIOSDeveloperInfo.objects.filter(user_id=request.user,
issuer_id__in=issuer_ids).all(): issuer_id__in=issuer_ids).all():
status, result = IosUtils.active_developer(developer_s_obj) status, result = IosUtils.active_developer(developer_s_obj, False)
if status: if status:
IosUtils.get_device_from_developer(developer_s_obj) IosUtils.get_device_from_developer(developer_s_obj)
elif act == "setstatus": elif act == "setstatus":
@ -127,7 +127,7 @@ class DeveloperView(APIView):
if act: if act:
logger.info(f"user {request.user} ios developer {developer_obj} act {act}") logger.info(f"user {request.user} ios developer {developer_obj} act {act}")
if act == "checkauth": if act == "checkauth":
status, result = IosUtils.active_developer(developer_obj) status, result = IosUtils.active_developer(developer_obj, False)
if status: if status:
IosUtils.get_device_from_developer(developer_obj) IosUtils.get_device_from_developer(developer_obj)
return Response(res.dict) return Response(res.dict)
@ -258,7 +258,7 @@ class DeveloperView(APIView):
logger.error(f"user {request.user} add new developer {data.get('issuer_id', '')} data {data_info}") logger.error(f"user {request.user} add new developer {data.get('issuer_id', '')} data {data_info}")
developer_obj = AppIOSDeveloperInfo.objects.create(user_id=request.user, **data_info) developer_obj = AppIOSDeveloperInfo.objects.create(user_id=request.user, **data_info)
IosUtils.create_developer_space(developer_obj, request.user) IosUtils.create_developer_space(developer_obj, request.user)
status, result = IosUtils.active_developer(developer_obj) status, result = IosUtils.active_developer(developer_obj, False)
if not status: if not status:
res.code = 1008 res.code = 1008
res.msg = result.get("return_info", "未知错误") res.msg = result.get("return_info", "未知错误")

Loading…
Cancel
Save