diff --git a/fir_client/src/components/user/FirSuperSignBase.vue b/fir_client/src/components/user/FirSuperSignBase.vue
index dc542d2..7b86689 100644
--- a/fir_client/src/components/user/FirSuperSignBase.vue
+++ b/fir_client/src/components/user/FirSuperSignBase.vue
@@ -65,26 +65,26 @@
- 导出证书
- 导入p12证书
- 清理签名数据
- 同步设备信息
+ 同步设备信息
- 手动创建发布证书
- 删除发布证书
diff --git a/fir_client/src/components/user/FirUserProfileInfo.vue b/fir_client/src/components/user/FirUserProfileInfo.vue
index 53dd77f..0963686 100644
--- a/fir_client/src/components/user/FirUserProfileInfo.vue
+++ b/fir_client/src/components/user/FirUserProfileInfo.vue
@@ -307,17 +307,19 @@ export default {
}
}, methods: {
delete_wx_u(wx_user_info) {
- this.$confirm(`此操作将导致微信用户 “${wx_user_info.nickname}” 无法通过扫码登录, 是否继续删除?`, '提示', {
+ this.$prompt(`此操作将导致微信用户 “${wx_user_info.nickname}” 无法通过扫码登录, 是否继续删除?`, '警告', {
confirmButtonText: '确定',
cancelButtonText: '取消',
- type: 'warning'
- }).then(() => {
+ inputPlaceholder: '该用户的登录密码',
+ inputValidator: this.validFun
+ }).then(({value}) => {
this.wxUtilsFun({
- methods: 'DELETE',
+ methods: 'POST',
data: {
"size": this.pagination.pagesize,
"page": this.pagination.currentPage,
"openid": wx_user_info.openid,
+ "confirm_pwd": value
}
})
}).catch(() => {
@@ -332,6 +334,8 @@ export default {
if (data.code === 1000) {
this.wx_user_list = data.data;
this.show_wx_visible = true
+ } else if (data.code === 1001) {
+ this.$message.error(data.msg)
} else {
this.$message.error("获取授权列表失败")
}
diff --git a/fir_client/src/components/user/FirUserStorage.vue b/fir_client/src/components/user/FirUserStorage.vue
index 9c99bfd..de41aeb 100644
--- a/fir_client/src/components/user/FirUserStorage.vue
+++ b/fir_client/src/components/user/FirUserStorage.vue
@@ -407,10 +407,7 @@ export default {
},
validFun(val) {
- if (val && val.length > 6) {
- return true
- }
- return false
+ return val && val.length > 6;
},
clean_storage_data(act) {
diff --git a/fir_ser/api/utils/app/iossignapi.py b/fir_ser/api/utils/app/iossignapi.py
index 218cb51..a9aec2b 100644
--- a/fir_ser/api/utils/app/iossignapi.py
+++ b/fir_ser/api/utils/app/iossignapi.py
@@ -196,9 +196,17 @@ def make_pem(cer_content, pem_path):
def check_error_call_back(error):
- logger.error(error)
+ msg = ''
if 'Cannot connect to proxy' in error or 'Read timed out' in error or 'Max retries exceeded with' in error:
logger.error('access apple api failed . change proxy ip again')
+ msg = "代理网络错误,请稍后重试或联系管理员处理"
+ if 'it may be encrypted with an unsupported algorithm' in error:
+ msg = "数据校验失败,请检查p8key内容是否正常"
+ if 'Authentication credentials are missing or invalid' in error:
+ msg = '认证失败,请检查开发者信息填写是否正确'
+
+ logger.error(f"{msg} {error}")
+ return msg if msg else error
class AppDeveloperApiV2(object):
@@ -221,8 +229,7 @@ class AppDeveloperApiV2(object):
return True, result
except Exception as e:
logger.error(f"ios developer active Failed Exception:{e}")
- check_error_call_back(str(e))
- result['return_info'] = "%s" % e
+ result['return_info'] = check_error_call_back(str(e))
return False, result
def file_format_path_name(self, user_obj):
@@ -250,8 +257,7 @@ class AppDeveloperApiV2(object):
return True, certificates
except Exception as e:
logger.error(f"ios developer create cert Failed Exception:{e}")
- check_error_call_back(str(e))
- result['return_info'] = "%s" % e
+ result['return_info'] = check_error_call_back(str(e))
return False, result
def get_cert_obj_by_cid(self):
@@ -266,8 +272,7 @@ class AppDeveloperApiV2(object):
return False, result
except Exception as e:
logger.error(f"ios developer get cert {self.cert_id} Failed Exception:{e}")
- check_error_call_back(str(e))
- result['return_info'] = "%s" % e
+ result['return_info'] = check_error_call_back(str(e))
return False, result
def revoke_cert(self):
@@ -286,8 +291,7 @@ class AppDeveloperApiV2(object):
return True, result
except Exception as e:
logger.error(f"ios developer cert {self.cert_id} revoke Failed Exception:{e}")
- check_error_call_back(str(e))
- result['return_info'] = "%s" % e
+ result['return_info'] = check_error_call_back(str(e))
return False, result
def auto_set_certid_by_p12(self, app_dev_pem):
@@ -307,8 +311,7 @@ class AppDeveloperApiV2(object):
return False, result
except Exception as e:
logger.error(f"ios developer cert {app_dev_pem} auto get Failed Exception:{e}")
- check_error_call_back(str(e))
- result['return_info'] = "%s" % e
+ result['return_info'] = check_error_call_back(str(e))
return False, result
def del_profile(self, profile_id, profile_name):
@@ -319,8 +322,7 @@ class AppDeveloperApiV2(object):
return True
except Exception as e:
logger.error(f"ios developer delete profile Failed Exception:{e}")
- check_error_call_back(str(e))
- result['return_info'] = "%s" % e
+ result['return_info'] = check_error_call_back(str(e))
return False, result
def set_device_status(self, status, device_id, device_name, device_udid, failed_call_prefix,
@@ -337,8 +339,7 @@ class AppDeveloperApiV2(object):
return True, result
except Exception as e:
logger.error("ios developer set devices status Failed Exception:%s" % e)
- check_error_call_back(str(e))
- result['return_info'] = "%s" % e
+ result['return_info'] = check_error_call_back(str(e))
if device_err_callback and ("There are no current ios devices" in str(e) or "Device obj is None" in str(e)):
with CleanErrorBundleIdSignDataState(failed_call_prefix) as state:
if state:
@@ -358,8 +359,7 @@ class AppDeveloperApiV2(object):
return True, devices_obj_list
except Exception as e:
logger.error("ios developer get device Failed Exception:%s" % e)
- check_error_call_back(str(e))
- result['return_info'] = "%s" % e
+ result['return_info'] = check_error_call_back(str(e))
return False, result
def del_app(self, identifier_id, bundle_id, app_id):
@@ -371,8 +371,7 @@ class AppDeveloperApiV2(object):
except Exception as e:
logger.error("ios developer delete app Failed Exception:%s" % e)
- check_error_call_back(str(e))
- result['return_info'] = "%s" % e
+ result['return_info'] = check_error_call_back(str(e))
return False, result
def create_app(self, bundle_id, app_id, s_type, app_id_err_callback=None):
@@ -393,8 +392,7 @@ class AppDeveloperApiV2(object):
except Exception as e:
logger.error("ios developer create app Failed Exception:%s" % e)
- check_error_call_back(str(e))
- result['return_info'] = "%s" % e
+ result['return_info'] = check_error_call_back(str(e))
if app_id_err_callback and "There is no App ID with ID" in str(e):
for call_fun in app_id_err_callback:
call_fun()
@@ -407,8 +405,7 @@ class AppDeveloperApiV2(object):
return True, apple_obj.register_device(device_name, device_udid)
except Exception as e:
logger.error("ios developer register device Failed Exception:%s" % e)
- check_error_call_back(str(e))
- result['return_info'] = "%s" % e
+ result['return_info'] = check_error_call_back(str(e))
if device_err_callback and "There are no current ios devices" in str(e):
with CleanErrorBundleIdSignDataState(failed_call_prefix) as state:
@@ -439,8 +436,7 @@ class AppDeveloperApiV2(object):
return True, result
except Exception as e:
logger.error(f"app_id {app_obj.app_id} ios developer make profile Failed Exception:{e}")
- check_error_call_back(str(e))
- result['return_info'] = "%s" % e
+ result['return_info'] = check_error_call_back(str(e))
if app_id_err_callback and "There is no App ID with ID" in str(e):
with CleanErrorBundleIdSignDataState(failed_call_prefix) as state:
if state:
@@ -474,6 +470,5 @@ class AppDeveloperApiV2(object):
return True, result
except Exception as e:
logger.error("ios developer modify_capability Failed Exception:%s" % e)
- check_error_call_back(str(e))
- result['return_info'] = "%s" % e
+ result['return_info'] = check_error_call_back(str(e))
return False, result
diff --git a/fir_ser/api/utils/app/supersignutils.py b/fir_ser/api/utils/app/supersignutils.py
index 8a16c9d..43328db 100644
--- a/fir_ser/api/utils/app/supersignutils.py
+++ b/fir_ser/api/utils/app/supersignutils.py
@@ -21,7 +21,7 @@ from api.utils.app.iossignapi import ResignApp, AppDeveloperApiV2
from api.utils.baseutils import file_format_path, delete_app_profile_file, get_profile_full_path, format_apple_date, \
get_format_time, make_app_uuid, make_from_user_uuid
from api.utils.modelutils import get_ios_developer_public_num, check_ipa_is_latest_sign, \
- get_developer_can_used_from_public_sign
+ get_developer_can_used_from_public_sign, update_or_create_developer_udid_info
from api.utils.response import BaseResponse
from api.utils.serializer import BillAppInfoSerializer, BillDeveloperInfoSerializer
from api.utils.storage.caches import del_cache_response_by_short, send_msg_over_limit, check_app_permission, \
@@ -278,7 +278,7 @@ def get_new_developer_by_app_obj(user_objs, app_obj, apple_to_app=False):
developer_obj_lists = obj_base_filter.filter(appledevelopertoappuse__app_id=app_obj)
else:
developer_obj_lists = obj_base_filter.exclude(appledevelopertoappuse__developerid__isnull=False)
- developer_obj_lists = developer_obj_lists.distinct().order_by("created_time")
+ developer_obj_lists = developer_obj_lists.all().distinct().order_by("created_time")
for developer_obj in developer_obj_lists:
# 通过开发者数限制进行过滤
used_number = get_developer_udided(developer_obj)[2] + get_developer_can_used_from_public_sign(
@@ -288,60 +288,97 @@ def get_new_developer_by_app_obj(user_objs, app_obj, apple_to_app=False):
apple_to_app_obj = AppleDeveloperToAppUse.objects.filter(app_id=app_obj,
developerid=developer_obj).first()
if apple_to_app_obj:
- if used_number < apple_to_app_obj.usable_number:
+ # 通过配置的专属分配数量进行过滤
+ app_used_number = DeveloperDevicesID.objects.filter(developerid=developer_obj,
+ app_id=app_obj).distinct().count()
+ if app_used_number < apple_to_app_obj.usable_number:
can_used_developer_pk_list.append(developer_obj.pk)
else:
can_used_developer_pk_list.append(developer_obj.pk)
return can_used_developer_pk_list
-def get_developer_user_by_app_udid(user_objs, udid, app_obj):
- developer_udid_obj_list = UDIDsyncDeveloper.objects.filter(developerid__user_id__in=user_objs,
+def get_developer_by_pk_list(developer_pk_list, f_key):
+ developer_obj_dict = AppIOSDeveloperInfo.objects.filter(pk__in=developer_pk_list,
+ is_actived=True,
+ certid__isnull=False).values(
+ f_key, 'pk').annotate(
+ count=Count('pk')).order_by('created_time').order_by('count').first()
+ if developer_obj_dict:
+ developer_obj = AppIOSDeveloperInfo.objects.filter(pk=developer_obj_dict.get('pk')).first()
+ logger.info(f'get {f_key} suitable developer {developer_obj} and return')
+ return developer_obj
+
+
+def get_developer_user_by_app_udid(user_objs, udid, app_obj, private_first=True):
+ """
+ :param user_objs: [user_obj]
+ :param udid: udid
+ :param app_obj: app_obj
+ :param private_first: 专属应用优先使用专属开发者,而不是公共开发者
+ :return: (developer_obj, is_exist_devices)
+ """
+ developer_udid_queryset = UDIDsyncDeveloper.objects.filter(developerid__user_id__in=user_objs,
developerid__is_actived=True,
developerid__certid__isnull=False).values(
- 'developerid').distinct()
+ 'developerid').all().distinct()
# 根据udid和应用查找该用户开发者账户【主要可能是开发者未激活】
- developer_obj = AppIOSDeveloperInfo.objects.filter(
- pk__in=developer_udid_obj_list.filter(udid=udid, developerid__apptodeveloper__app_id=app_obj)).last()
- if developer_obj:
- logger.info(f'udid:{udid} app_obj:{app_obj} return')
- return developer_obj, True
-
- # 根据udid查找开发者账户
- developer_obj = AppIOSDeveloperInfo.objects.filter(pk__in=developer_udid_obj_list.filter(udid=udid)).last()
- if developer_obj:
- logger.info(f'udid:{udid} only and return')
- return developer_obj, True
+ developer_pk_list = developer_udid_queryset.filter(udid=udid, developerid__apptodeveloper__app_id=app_obj)
+ app_search_flag = True
+
+ # 联合udid和应用查询不到数据,那么,仅根据udid查找开发者账户
+ if not developer_pk_list:
+ app_search_flag = False
+ developer_pk_list = developer_udid_queryset.filter(udid=udid)
+
+ if developer_pk_list:
+ developer_obj = get_developer_by_pk_list(developer_pk_list, 'developerappid')
+ if developer_obj:
+ if app_search_flag:
+ logger.info(f'udid:{udid} and app_obj:{app_obj} exist and return. developer_obj: {developer_obj}')
+ else:
+ logger.info(f'udid:{udid} exist and return. app_obj:{app_obj} developer_obj: {developer_obj}')
+ return developer_obj, True
+ else:
+ logger.info(f"udid:{udid} is a new device. app_obj:{app_obj} will find a suitable developer and register it")
# 新设备查找策略
# 根据app查找开发者账户
exist_app_developer_pk_list = []
- for developer_obj in AppIOSDeveloperInfo.objects.filter(
- pk__in=developer_udid_obj_list.filter(developerid__apptodeveloper__app_id=app_obj)):
- if get_developer_udided(developer_obj)[2] + get_developer_can_used_from_public_sign(
- developer_obj.user_id) < developer_obj.usable_number:
- logger.info(f'app_obj:{app_obj} only and return')
- exist_app_developer_pk_list.append(developer_obj.pk)
- # return developer_obj, False
-
+ developer_pk_list = developer_udid_queryset.filter(developerid__apptodeveloper__app_id=app_obj)
+ if developer_pk_list:
+ for developer_obj in AppIOSDeveloperInfo.objects.filter(pk__in=developer_pk_list):
+ if get_developer_udided(developer_obj)[2] + get_developer_can_used_from_public_sign(
+ developer_obj.user_id) < developer_obj.usable_number:
+ exist_app_developer_pk_list.append(developer_obj.pk)
+
+ # 查询状态正常的专属开发者信息,判断是否为专属应用
apple_to_app = AppleDeveloperToAppUse.objects.filter(app_id=app_obj, developerid__is_actived=True,
developerid__certid__isnull=False).first()
+
+ # 存在专属开发者账户,但是也同时存在已经安装的设备,优先选择已经安装设备的开发者账户?是or否
+ # 是:使应用趋向于一个开发者,为后期更新提供方便
+ # 否:优先使用专属开发者进行签名
+ if not private_first and apple_to_app and exist_app_developer_pk_list:
+ return AppIOSDeveloperInfo.objects.filter(pk=exist_app_developer_pk_list[0]).first(), False
+
can_used_developer_pk_list = get_new_developer_by_app_obj(user_objs, app_obj, apple_to_app)
+
+ # 存在指定开发者账户,但是获取可用的开发者账户为空,那么开始匹配全部开发者
if not can_used_developer_pk_list and apple_to_app:
+ logger.info(f"udid:{udid} app_obj:{app_obj} private developer is null. start find all developer")
can_used_developer_pk_list = get_new_developer_by_app_obj(user_objs, app_obj)
if can_used_developer_pk_list and exist_app_developer_pk_list:
can_used_developer_pk_list = list(set(can_used_developer_pk_list) & set(exist_app_developer_pk_list))
+ logger.info(f"udid:{udid} app_obj:{app_obj} find private and can use developer {can_used_developer_pk_list}")
# 查询开发者策略 按照最小注册设备数进行查找,这样可以分散,进而使应用趋向于一个开发者,为后期更新提供方便
if can_used_developer_pk_list:
- developer_obj_dict = AppIOSDeveloperInfo.objects.filter(pk__in=can_used_developer_pk_list).values(
- 'udidsyncdeveloper', 'pk').annotate(
- count=Count('pk')).order_by('created_time').order_by('count').first()
- if developer_obj_dict:
- developer_obj = AppIOSDeveloperInfo.objects.filter(pk=developer_obj_dict.get('pk')).first()
- logger.info(f'get suitable developer {developer_obj} and return')
+ developer_obj = get_developer_by_pk_list(can_used_developer_pk_list, 'udidsyncdeveloper')
+ if developer_obj:
+ logger.info(f"udid:{udid} is a new device. app_obj:{app_obj} find {developer_obj} and return")
return developer_obj, False
return None, None
@@ -517,12 +554,7 @@ class IosUtils(object):
if app_udid_obj and app_udid_obj.is_download:
sign_flag = False
if app_udid_obj.is_signed:
- # release_obj = AppReleaseInfo.objects.filter(app_id=self.app_obj, is_master=True).first()
-
if check_ipa_is_latest_sign(self.app_obj, self.developer_obj):
- #
- # for apptodev_obj in APPToDeveloper.objects.filter(app_id=self.app_obj).all():
- # if release_obj.release_id == apptodev_obj.release_file:
msg = "udid %s exists app_id %s" % (self.udid, self.app_obj)
d_result['msg'] = msg
logger.info(d_result)
@@ -581,15 +613,7 @@ class IosUtils(object):
if not status:
return status, device_obj
- device = {
- "serial": device_obj.id,
- "product": device_obj.name,
- "udid": device_obj.udid,
- "version": device_obj.model,
- "status": True if device_obj.status == 'ENABLED' else False
- }
- sync_device_obj, _ = UDIDsyncDeveloper.objects.update_or_create(developerid=developer_obj,
- udid=device_obj.udid, defaults=device)
+ sync_device_obj, _ = update_or_create_developer_udid_info(device_obj, developer_obj)
# 更新设备状态
# 1. UDIDsyncDeveloper 库,通过udid 更新或创建设备信息
@@ -1040,15 +1064,7 @@ class IosUtils(object):
will_del_disabled_udid_list = list(set(udid_developer_list) - set(udid_enabled_result_list))
for device_obj in result:
- device = {
- "serial": device_obj.id,
- "product": device_obj.name,
- "udid": device_obj.udid,
- "version": device_obj.model,
- "status": True if device_obj.status == 'ENABLED' else False
- }
- obj, create = UDIDsyncDeveloper.objects.update_or_create(developerid=developer_obj,
- udid=device_obj.udid, defaults=device)
+ obj, create = update_or_create_developer_udid_info(device_obj, developer_obj)
if not create:
DeveloperDevicesID.objects.filter(udid=obj, developerid=developer_obj).update(
**{'did': device_obj.id})
diff --git a/fir_ser/api/utils/apple/appleapiv3.py b/fir_ser/api/utils/apple/appleapiv3.py
index 2cf9fef..0fa59f0 100644
--- a/fir_ser/api/utils/apple/appleapiv3.py
+++ b/fir_ser/api/utils/apple/appleapiv3.py
@@ -705,7 +705,7 @@ def call_function_try_attempts(try_attempts=5, sleep_time=3):
f'again...{i}')
res = str(e)
if 'Authentication credentials are missing or invalid' in str(e):
- res = '认证失败,请检查开发者信息填写是否正确'
+ raise Exception(res)
time.sleep(sleep_time)
logger.info(f"exec {func} finished. time:{time.time() - start_time}")
if not flag:
diff --git a/fir_ser/api/utils/modelutils.py b/fir_ser/api/utils/modelutils.py
index 400e3f5..24dfc3f 100644
--- a/fir_ser/api/utils/modelutils.py
+++ b/fir_ser/api/utils/modelutils.py
@@ -12,7 +12,7 @@ from urllib.parse import urljoin
from django.db.models import Count, Sum, Q
from api.models import AppReleaseInfo, UserDomainInfo, DomainCnameInfo, UserAdDisplayInfo, RemoteClientInfo, \
- AppIOSDeveloperInfo, IosDeveloperPublicPoolBill, APPToDeveloper, UserInfo
+ AppIOSDeveloperInfo, IosDeveloperPublicPoolBill, APPToDeveloper, UserInfo, UDIDsyncDeveloper
from api.utils.baseutils import get_server_domain_from_request, get_user_default_domain_name, get_real_ip_address, \
get_origin_domain_name, is_valid_phone
@@ -203,3 +203,14 @@ def get_user_obj_from_epu(user_id):
else:
user_obj = UserInfo.objects.filter(Q(email=user_id) | Q(uid=user_id)).first()
return user_obj
+
+
+def update_or_create_developer_udid_info(device_obj, developer_obj):
+ device = {
+ "serial": device_obj.id,
+ "product": device_obj.name,
+ "udid": device_obj.udid,
+ "version": device_obj.model,
+ "status": True if device_obj.status == 'ENABLED' else False
+ }
+ return UDIDsyncDeveloper.objects.update_or_create(developerid=developer_obj, udid=device_obj.udid, defaults=device)
diff --git a/fir_ser/api/views/supersign.py b/fir_ser/api/views/supersign.py
index 43e366e..c203c24 100644
--- a/fir_ser/api/views/supersign.py
+++ b/fir_ser/api/views/supersign.py
@@ -110,7 +110,7 @@ class DeveloperView(APIView):
IosUtils.get_device_from_developer(developer_obj)
else:
res.code = 1008
- res.msg = result.get("err_info")
+ res.msg = result.get("return_info")
return Response(res.dict)
elif act == "renewcert":
if developer_obj.certid:
diff --git a/fir_ser/api/views/thirdlogin.py b/fir_ser/api/views/thirdlogin.py
index b51fbfd..c2af94c 100644
--- a/fir_ser/api/views/thirdlogin.py
+++ b/fir_ser/api/views/thirdlogin.py
@@ -183,7 +183,6 @@ class ValidWxChatToken(APIView):
WxTemplateMsg().query_bind_info_failed_msg(to_user, wx_user_info.get('nickname'),
"查询登录绑定", content)
-
elif rec_msg.Eventkey == 'unbind':
if wx_user_obj:
content = f'解绑用户 {wx_user_obj.user_id.first_name} 成功'
@@ -234,12 +233,8 @@ class ThirdWxAccount(APIView):
def get(self, request):
res = BaseResponse()
-
if get_login_type().get('third', '').get('wxp'):
- # wx_open_id = request.query_params.get("openid", None)
wx_obj_lists = ThirdWeChatUserInfo.objects.filter(user_id=request.user)
- # if wx_open_id:
- # wx_obj_lists = wx_obj_lists.filter(openid=wx_open_id)
page_obj = PageNumber()
info_serializer = page_obj.paginate_queryset(queryset=wx_obj_lists.order_by("-subscribe_time"),
request=request,
@@ -247,11 +242,17 @@ class ThirdWxAccount(APIView):
wx_user_info = ThirdWxSerializer(info_serializer, many=True, )
res.data = wx_user_info.data
res.count = wx_obj_lists.count()
-
return Response(res.dict)
- def delete(self, request):
- openid = request.query_params.get("openid")
+ def post(self, request):
+ data = request.data
+ openid = data.get("openid")
if get_login_type().get('third', '').get('wxp') and openid:
- ThirdWeChatUserInfo.objects.filter(user_id=request.user, openid=openid).delete()
+ if request.user.check_password(data.get('confirm_pwd', '')):
+ ThirdWeChatUserInfo.objects.filter(user_id=request.user, openid=openid).delete()
+ else:
+ res = BaseResponse()
+ res.code = 1001
+ res.msg = "密码有误,请检查"
+ return Response(res.dict)
return self.get(request)