代码优化,苹果开发者账户展示优化

xsign
MMXX 3 years ago
parent e780a2597e
commit cf14dcb0a5
  1. 118
      fir_ser/common/libs/apple/appleapiv3.py
  2. 2
      fir_ser/common/libs/sendmsg/emailApi.py
  3. 177
      fir_ser/common/libs/sendmsg/templates/check_developer.html
  4. 2
      fir_ser/fir_ser/settings.py
  5. 25
      fir_ser/tests/django_test.py
  6. 15
      fir_ser/xsign/utils/ctasks.py
  7. 180
      fir_ser/xsign/utils/iossignapi.py
  8. 12
      fir_ser/xsign/utils/supersignutils.py

@ -30,11 +30,12 @@ logger = logging.getLogger(__name__)
# timeout = settings.APPLE_DEVELOPER_API_TIMEOUT if settings.APPLE_DEVELOPER_API_TIMEOUT else 120
def request_format_log(req):
def request_format_log(self, req):
try:
logger.info(f"url:{req.url} header:{req.headers} code:{req.status_code} body:{req.content}")
logger.info(
f"issuer_id:{self.issuer_id} url:{req.url} method:{req.request.method} header:{req.headers} code:{req.status_code} body:{req.content}")
except Exception as e:
logger.error(e)
logger.error(f"issuer_id:{self.issuer_id} url:{req.url} method:{req.request.method} Exception:{e}")
return req
@ -100,9 +101,10 @@ class DevicesAPI(object):
if query_parameters:
for k, v in query_parameters.items():
params[k] = v
return request_format_log(
requests.get(self.devices_url, params=params, headers=self.headers, proxies=self.proxies,
timeout=self.timeout))
return request_format_log(self,
requests.get(self.devices_url, params=params, headers=self.headers,
proxies=self.proxies,
timeout=self.timeout))
def list_enabled_devices(self):
return self.list_devices({"filter[status]": "ENABLED"})
@ -135,9 +137,9 @@ class DevicesAPI(object):
}
}
}
return request_format_log(
requests.post(self.devices_url, json=json, headers=self.headers, proxies=self.proxies,
timeout=self.timeout))
return request_format_log(self,
requests.post(self.devices_url, json=json, headers=self.headers, proxies=self.proxies,
timeout=self.timeout))
def read_device_information(self, device_id):
"""
@ -152,8 +154,9 @@ class DevicesAPI(object):
params = {
"fields[devices]": "addedDate, deviceClass, model, name, platform, status, udid",
}
return request_format_log(
requests.get(base_url, params=params, headers=self.headers, proxies=self.proxies, timeout=self.timeout))
return request_format_log(self,
requests.get(base_url, params=params, headers=self.headers, proxies=self.proxies,
timeout=self.timeout))
def enabled_device(self, device_id, device_name):
return self.modify_registered_device(device_id, device_name, 'ENABLED')
@ -184,8 +187,9 @@ class DevicesAPI(object):
}
}
}
return request_format_log(
requests.patch(base_url, json=json, headers=self.headers, proxies=self.proxies, timeout=self.timeout))
return request_format_log(self,
requests.patch(base_url, json=json, headers=self.headers, proxies=self.proxies,
timeout=self.timeout))
class BundleIDsAPI(object):
@ -217,9 +221,10 @@ class BundleIDsAPI(object):
}
}
}
return request_format_log(
requests.post(self.bundle_ids_url, json=json, headers=self.headers, proxies=self.proxies,
timeout=self.timeout))
return request_format_log(self,
requests.post(self.bundle_ids_url, json=json, headers=self.headers,
proxies=self.proxies,
timeout=self.timeout))
def delete_bundle_id_by_id(self, bundle_id):
"""
@ -233,8 +238,9 @@ class BundleIDsAPI(object):
"""
base_url = '%s/%s' % (self.bundle_ids_url, bundle_id)
json = {}
return request_format_log(
requests.delete(base_url, json=json, headers=self.headers, proxies=self.proxies, timeout=self.timeout))
return request_format_log(self,
requests.delete(base_url, json=json, headers=self.headers, proxies=self.proxies,
timeout=self.timeout))
def list_bundle_ids(self, query_parameters=None):
"""
@ -252,9 +258,10 @@ class BundleIDsAPI(object):
if query_parameters:
for k, v in query_parameters.items():
params[k] = v
return request_format_log(
requests.get(self.bundle_ids_url, params=params, headers=self.headers, proxies=self.proxies,
timeout=self.timeout))
return request_format_log(self,
requests.get(self.bundle_ids_url, params=params, headers=self.headers,
proxies=self.proxies,
timeout=self.timeout))
def list_bundle_id_by_identifier(self, identifier):
return self.list_bundle_ids({"filter[identifier]": identifier})
@ -283,8 +290,9 @@ class BundleIDsAPI(object):
}
}
}
return request_format_log(
requests.patch(base_url, json=json, headers=self.headers, proxies=self.proxies, timeout=self.timeout))
return request_format_log(self,
requests.patch(base_url, json=json, headers=self.headers, proxies=self.proxies,
timeout=self.timeout))
class BundleIDsCapabilityAPI(object):
@ -306,8 +314,9 @@ class BundleIDsCapabilityAPI(object):
"""
base_url = '%s/%s_%s' % (self.bundle_ids_capability_url, bundle_id, capability_type)
json = {}
return request_format_log(
requests.delete(base_url, json=json, headers=self.headers, proxies=self.proxies, timeout=self.timeout))
return request_format_log(self,
requests.delete(base_url, json=json, headers=self.headers, proxies=self.proxies,
timeout=self.timeout))
def enable_capability(self, bundle_id, capability_type):
"""
@ -336,9 +345,10 @@ class BundleIDsCapabilityAPI(object):
}
}
}
return request_format_log(
requests.post(self.bundle_ids_capability_url, json=json, headers=self.headers, proxies=self.proxies,
timeout=self.timeout))
return request_format_log(self,
requests.post(self.bundle_ids_capability_url, json=json, headers=self.headers,
proxies=self.proxies,
timeout=self.timeout))
class ProfilesAPI(object):
@ -390,9 +400,10 @@ class ProfilesAPI(object):
}
}
}
return request_format_log(
requests.post(self.profiles_url, json=json, headers=self.headers, proxies=self.proxies,
timeout=self.timeout))
return request_format_log(self,
requests.post(self.profiles_url, json=json, headers=self.headers,
proxies=self.proxies,
timeout=self.timeout))
def delete_profile(self, profile_id):
"""
@ -406,8 +417,9 @@ class ProfilesAPI(object):
"""
base_url = '%s/%s' % (self.profiles_url, profile_id)
json = {}
return request_format_log(
requests.delete(base_url, json=json, headers=self.headers, proxies=self.proxies, timeout=self.timeout))
return request_format_log(self,
requests.delete(base_url, json=json, headers=self.headers, proxies=self.proxies,
timeout=self.timeout))
def download_profile(self, profile_id):
# n=base64.b64decode(profileContent)
@ -432,9 +444,10 @@ class ProfilesAPI(object):
if query_parameters:
for k, v in query_parameters.items():
params[k] = v
return request_format_log(
requests.get(self.profiles_url, params=params, headers=self.headers, proxies=self.proxies,
timeout=self.timeout))
return request_format_log(self,
requests.get(self.profiles_url, params=params, headers=self.headers,
proxies=self.proxies,
timeout=self.timeout))
def list_profile_by_profile_id(self, profile_id):
return self.list_profiles({"filter[id]": profile_id, "include": ""})
@ -469,9 +482,10 @@ class CertificatesAPI(object):
}
}
}
return request_format_log(
requests.post(self.certificates_url, json=json, headers=self.headers, proxies=self.proxies,
timeout=self.timeout))
return request_format_log(self,
requests.post(self.certificates_url, json=json, headers=self.headers,
proxies=self.proxies,
timeout=self.timeout))
def download_certificate(self, certificate_id):
# req.json()['data'][0]['attributes']['certificateContent']
@ -496,9 +510,10 @@ class CertificatesAPI(object):
if query_parameters:
for k, v in query_parameters.items():
params[k] = v
return request_format_log(
requests.get(self.certificates_url, params=params, headers=self.headers, proxies=self.proxies,
timeout=self.timeout))
return request_format_log(self,
requests.get(self.certificates_url, params=params, headers=self.headers,
proxies=self.proxies,
timeout=self.timeout))
def list_certificate_by_certificate_id(self, certificate_id):
return self.list_certificate({"filter[id]": certificate_id, })
@ -515,8 +530,9 @@ class CertificatesAPI(object):
"""
base_url = '%s/%s' % (self.certificates_url, certificate_id)
json = {}
return request_format_log(
requests.delete(base_url, json=json, headers=self.headers, proxies=self.proxies, timeout=self.timeout))
return request_format_log(self,
requests.delete(base_url, json=json, headers=self.headers, proxies=self.proxies,
timeout=self.timeout))
class BaseInfoObj(object):
@ -745,6 +761,18 @@ class AppStoreConnectApi(DevicesAPI, BundleIDsAPI, BundleIDsCapabilityAPI, Profi
CertificatesAPI.__init__(self, self.BASE_URI, self.headers)
self.rate_limit_info = {}
def __getattribute__(self, name):
attr = object.__getattribute__(self, name)
if hasattr(attr, '__call__'):
def func(*args, **kwargs):
res = attr(*args, **kwargs)
logger.info(f"issuer_id:{self.issuer_id} calling {attr.__name__} result:{res}")
return res
return func
else:
return attr
def __set_rate_limit_info(self, req_headers):
for par in req_headers.get('X-Rate-Limit').split(";"):
if par:
@ -796,6 +824,8 @@ class AppStoreConnectApi(DevicesAPI, BundleIDsAPI, BundleIDsCapabilityAPI, Profi
obj = Certificates.from_json_list(data)
if len(obj) == 1:
return obj[0]
if obj is None:
raise Exception(f'None object: {req.text}')
return obj
else:
# self.__init_jwt_headers()

@ -43,7 +43,7 @@ class EmailMsgSender(object):
def send_email_msg(self, email, text):
try:
response = send_mail("重要消息通知", text, self.form, [email], )
response = send_mail("重要消息通知", text, self.form, [email], html_message=text)
except Exception as e:
return -1, e
return response, text

@ -0,0 +1,177 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>开发者状态监测报告</title>
<style>
.container-fluid {
width: 100%;
margin-right: auto;
margin-left: auto;
}
.span12 {
width: 1170px;
}
.table {
--bs-table-bg: transparent;
--bs-table-accent-bg: transparent;
--bs-table-striped-color: #212529;
--bs-table-striped-bg: rgba(0, 0, 0, 0.05);
--bs-table-active-color: #212529;
--bs-table-active-bg: rgba(0, 0, 0, 0.1);
--bs-table-hover-color: #212529;
--bs-table-hover-bg: rgba(0, 0, 0, 0.075);
--bs-table-color: #212529;
--bs-table-border-color: #dee2e6;
width: 100%;
margin-bottom: 1rem;
color: var(--bs-table-color);
vertical-align: top;
border-color: var(--bs-table-border-color);
border-collapse: collapse;
}
.table > :not(caption) > * > * {
padding: .5rem .5rem;
background-color: var(--bs-table-bg);
border-bottom-width: 1px;
box-shadow: inset 0 0 0 9999px var(--bs-table-accent-bg)
}
.table > tbody {
vertical-align: inherit
}
.table > thead {
vertical-align: bottom
}
.table > :not(:first-child) {
border-top: 2px solid currentColor
}
.table-sm > :not(caption) > * > * {
padding: .25rem .25rem
}
.table-borderless > :not(caption) > * > * {
border-bottom-width: 0
}
.table-borderless > :not(:first-child) {
border-top-width: 0
}
.table-striped > tbody > tr:nth-of-type(odd) > * {
--bs-table-accent-bg: var(--bs-table-striped-bg);
color: var(--bs-table-striped-color)
}
.table-hover > tbody > tr:hover > * {
--bs-table-accent-bg: var(--bs-table-hover-bg);
color: var(--bs-table-hover-color)
}
.table-success {
--bs-table-bg: #d1e7dd;
--bs-table-striped-bg: #c7dbd2;
--bs-table-striped-color: #000;
--bs-table-active-bg: #bcd0c7;
--bs-table-active-color: #000;
--bs-table-hover-bg: #c1d6cc;
--bs-table-hover-color: #000;
color: #000;
border-color: #bcd0c7
}
.table-warning {
--bs-table-bg: #fff3cd;
--bs-table-striped-bg: #f2e7c3;
--bs-table-striped-color: #000;
--bs-table-active-bg: #e6dbb9;
--bs-table-active-color: #000;
--bs-table-hover-bg: #ece1be;
--bs-table-hover-color: #000;
color: #000;
border-color: #e6dbb9
}
.table-danger {
--bs-table-bg: #f8d7da;
--bs-table-striped-bg: #eccccf;
--bs-table-striped-color: #000;
--bs-table-active-bg: #dfc2c4;
--bs-table-active-color: #000;
--bs-table-hover-bg: #e5c7ca;
--bs-table-hover-color: #000;
color: #000;
border-color: #dfc2c4
}
.table-bordered {
border: 1px solid var(--bs-table-border-color);
border-collapse: separate;
*border-collapse: collapsed;
border-left: 0;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
}
.table-bordered th, .table-bordered td {
border-left: 1px solid #c7ecb8;
}
</style>
</head>
<body style="text-align: center">
<div class="container-fluid">
<div class="span12">
<h3>
尊敬的用户 {{ username }} 你好,苹果开发者状态监测如下:
</h3>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>
苹果开发者ID
</th>
<th>
苹果开发者备注
</th>
<th>
苹果开发者状态
</th>
</tr>
</thead>
<tbody>
{% for developer_obj in developer_obj_list %}
<tr class="{% if developer_obj.status == 2 %}table-warning{% elif developer_obj.status == 1 %}table-success{% else %}table-danger{% endif %}">
<td>
{{ developer_obj.issuer_id }}
</td>
<td>
{{ developer_obj.description }}
</td>
<td>
{{ developer_obj.get_status_display }}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</body>
</html>

@ -65,7 +65,7 @@ ROOT_URLCONF = 'fir_ser.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')]
'DIRS': [os.path.join(BASE_DIR, 'templates'), os.path.join(BASE_DIR, 'common/libs/sendmsg/templates')]
,
'APP_DIRS': True,
'OPTIONS': {

@ -0,0 +1,25 @@
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# project: 3月
# author: NinEveN
# date: 2022/3/9
import os
import django
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'fir_ser.settings')
django.setup()
from xsign.utils.ctasks import auto_check_ios_developer_active
# userinfo = UserInfo.objects.first()
# developer_obj_list = AppIOSDeveloperInfo.objects.all()
# aa = []
# for i in range(22):
# aa.append(developer_obj_list.first())
# content = loader.render_to_string('check_developer.html',
# {'username': userinfo.first_name, 'developer_obj_list': aa})
#
# send_ios_developer_active_status(userinfo, content)
auto_check_ios_developer_active()

@ -8,6 +8,8 @@ import logging
import os
import time
from django.template import loader
from common.core.sysconfig import Config
from fir_ser.settings import SUPER_SIGN_ROOT, SYNC_CACHE_TO_DATABASE
from xsign.models import UserInfo, AppIOSDeveloperInfo
@ -41,14 +43,17 @@ def auto_check_ios_developer_active():
if userinfo.supersign_active:
status, result = IosUtils.active_developer(ios_developer)
msg = f"auto_check_ios_developer_active user:{userinfo} ios.developer:{ios_developer} status:{status} result:{result}"
err_issuer_id.append(ios_developer)
error_issuer_id[userinfo.uid] = list(set(err_issuer_id))
if status:
IosUtils.get_device_from_developer(ios_developer)
logger.info(msg)
else:
err_issuer_id.append(ios_developer.issuer_id)
logger.error(msg)
error_issuer_id[userinfo.uid] = list(set(err_issuer_id))
for uid, val in error_issuer_id.items():
for uid, developer_obj_list in error_issuer_id.items():
userinfo = UserInfo.objects.filter(uid=uid).first()
send_ios_developer_active_status(userinfo, Config.MSG_AUTO_CHECK_DEVELOPER % (
userinfo.first_name, ",".join(val)))
content = loader.render_to_string('check_developer.html',
{'username': userinfo.first_name, 'developer_obj_list': developer_obj_list})
send_ios_developer_active_status(userinfo, content)

@ -18,7 +18,7 @@ from OpenSSL.crypto import (load_pkcs12, dump_certificate_request, dump_privatek
from common.base.baseutils import get_format_time, format_apple_date, make_app_uuid
from common.cache.state import CleanErrorBundleIdSignDataState
from common.core.sysconfig import Config
from common.libs.apple.appleapiv3 import AppStoreConnectApi
from common.libs.apple.appleapiv3 import AppStoreConnectApi, Certificates, Devices, BundleIds, Profiles
from fir_ser.settings import SUPER_SIGN_ROOT
from xsign.models import AppIOSDeveloperInfo
@ -260,60 +260,78 @@ class AppDeveloperApiV2(object):
if AppIOSDeveloperInfo.objects.filter(pk=self.developer_pk,
status__in=Config.DEVELOPER_WRITE_STATUS).first():
start_time = time.time()
logger.info(f'{self.issuer_id} calling {attr.__name__} time:{start_time}')
logger.info(f'issuer_id:{self.issuer_id} calling {attr.__name__} time:{start_time}')
result = attr(*args, **kwargs)
logger.info(f'{self.issuer_id} done {attr.__name__} used time:{time.time() - start_time}')
logger.info(
f'issuer_id:{self.issuer_id} done {attr.__name__} used time:{time.time() - start_time}')
return result
else:
result = False, {'return_info': '开发者状态异常'}
logger.warning(f'{self.issuer_id} can not calling {attr.__name__} {result}')
logger.warning(f'issuer_id:{self.issuer_id} can not calling {attr.__name__} {result}')
return result
return func
else:
return attr
def __file_format_path_name(self, user_obj):
cert_dir_name = make_app_uuid(user_obj, self.issuer_id)
cert_dir_path = os.path.join(SUPER_SIGN_ROOT, cert_dir_name)
if not os.path.isdir(cert_dir_path):
os.makedirs(cert_dir_path)
return os.path.join(cert_dir_path, cert_dir_name)
def __result_format(self, result, is_instance):
return_flag = False
if isinstance(result, list):
if len(result) == 0:
return_flag = True
else:
if isinstance(result[0], is_instance):
return_flag = True
else:
if isinstance(result, is_instance):
result = [result]
return_flag = True
if return_flag:
logger.info(f"issuer_id:{self.issuer_id} {is_instance} result:{result}")
return True, result
raise Exception(f'{result} is not {is_instance}')
def active(self):
result = {'data': []}
"""
:return: 结果为空列表或者是 object 或者是 [object,object] 其他为 false
"""
result = {}
try:
apple_obj = AppStoreConnectApi(self.issuer_id, self.private_key_id, self.p8key)
certificates = apple_obj.get_all_certificates()
if not isinstance(certificates, list):
certificates = [certificates]
result['data'] = certificates
logger.info(f"ios developer active result:{certificates}")
if len(certificates) >= 0:
return True, result
return self.__result_format(certificates, Certificates)
except Exception as e:
logger.error(f"ios developer active Failed Exception:{e}")
logger.error(f"issuer_id:{self.issuer_id} ios developer active Failed Exception:{e}")
result['return_info'] = check_error_call_back(str(e), self.developer_pk)
return False, result
def file_format_path_name(self, user_obj):
cert_dir_name = make_app_uuid(user_obj, self.issuer_id)
cert_dir_path = os.path.join(SUPER_SIGN_ROOT, cert_dir_name)
if not os.path.isdir(cert_dir_path):
os.makedirs(cert_dir_path)
return os.path.join(cert_dir_path, cert_dir_name)
def create_cert(self, user_obj):
result = {}
try:
apple_obj = AppStoreConnectApi(self.issuer_id, self.private_key_id, self.p8key)
csr_path = self.file_format_path_name(user_obj)
csr_path = self.__file_format_path_name(user_obj)
if not os.path.isdir(os.path.dirname(csr_path)):
os.makedirs(os.path.dirname(csr_path))
csr_content = make_csr_content(csr_path + ".csr", csr_path + ".key")
certificates = apple_obj.create_certificate(csr_content.decode("utf-8"))
if certificates:
if certificates and isinstance(certificates, Certificates):
n = base64.b64decode(certificates.certificateContent)
with open(csr_path + ".cer", 'wb') as f:
f.write(n)
make_pem(n, csr_path + ".pem")
logger.info(f"ios developer create cert result:{certificates.certificateContent}")
logger.info(
f"issuer_id:{self.issuer_id} ios developer create cert result:{certificates.certificateContent}")
return True, certificates
raise Exception(str(certificates))
except Exception as e:
logger.error(f"ios developer create cert Failed Exception:{e}")
logger.error(f"issuer_id:{self.issuer_id} ios developer create cert Failed Exception:{e}")
result['return_info'] = check_error_call_back(str(e), self.developer_pk)
return False, result
@ -322,13 +340,13 @@ class AppDeveloperApiV2(object):
try:
apple_obj = AppStoreConnectApi(self.issuer_id, self.private_key_id, self.p8key)
cert_obj = apple_obj.get_certificate_by_cid(self.cert_id)
if cert_obj and cert_obj.id:
return True, result
if cert_obj and isinstance(cert_obj, Certificates):
return True, cert_obj
else:
logger.info(f"ios developer get cert {self.cert_id} failed")
logger.info(f"issuer_id:{self.issuer_id} ios developer get cert {self.cert_id} failed")
return False, result
except Exception as e:
logger.error(f"ios developer get cert {self.cert_id} Failed Exception:{e}")
logger.error(f"issuer_id:{self.issuer_id} ios developer get cert {self.cert_id} Failed Exception:{e}")
result['return_info'] = check_error_call_back(str(e), self.developer_pk)
return False, result
@ -337,17 +355,19 @@ class AppDeveloperApiV2(object):
try:
apple_obj = AppStoreConnectApi(self.issuer_id, self.private_key_id, self.p8key)
cert_obj = apple_obj.get_certificate_by_cid(self.cert_id)
if cert_obj:
if cert_obj and isinstance(cert_obj, Certificates):
s_date = format_apple_date(cert_obj.expirationDate)
if s_date.timestamp() - datetime.datetime.now().timestamp() < 3600 * 24 * 3:
if apple_obj.revoke_certificate(self.cert_id):
logger.info(f"ios developer cert {self.cert_id} revoke")
logger.info(f"issuer_id:{self.issuer_id} ios developer cert {self.cert_id} revoke")
return True, result
else:
logger.info(f"ios developer cert {self.cert_id} not revoke.because expire time < 3 day ")
logger.info(
f"issuer_id:{self.issuer_id} ios developer cert {self.cert_id} not revoke.because expire time < 3 day ")
return True, result
raise Exception(str(cert_obj))
except Exception as e:
logger.error(f"ios developer cert {self.cert_id} revoke Failed Exception:{e}")
logger.error(f"issuer_id:{self.issuer_id} ios developer cert {self.cert_id} revoke Failed Exception:{e}")
result['return_info'] = check_error_call_back(str(e), self.developer_pk)
return False, result
@ -358,16 +378,17 @@ class AppDeveloperApiV2(object):
not_after = datetime.datetime.strptime(cer.get_notAfter().decode('utf-8'), "%Y%m%d%H%M%SZ")
apple_obj = AppStoreConnectApi(self.issuer_id, self.private_key_id, self.p8key)
certificates = apple_obj.get_all_certificates()
if not isinstance(certificates, list):
certificates = [certificates]
for cert_obj in certificates:
f_date = format_apple_date(cert_obj.expirationDate)
logger.info(f"{cert_obj.id}-{not_after.timestamp()} - {f_date.timestamp()} ")
if not_after.timestamp() == f_date.timestamp():
return True, cert_obj
return False, result
status, result = self.__result_format(certificates, Certificates)
if status:
for cert_obj in result:
f_date = format_apple_date(cert_obj.expirationDate)
logger.info(
f"issuer_id:{self.issuer_id} {cert_obj.id}-{not_after.timestamp()} - {f_date.timestamp()} ")
if not_after.timestamp() == f_date.timestamp():
return True, cert_obj
raise Exception(str(certificates))
except Exception as e:
logger.error(f"ios developer cert {app_dev_pem} auto get Failed Exception:{e}")
logger.error(f"issuer_id:{self.issuer_id} ios developer cert {app_dev_pem} auto get Failed Exception:{e}")
result['return_info'] = check_error_call_back(str(e), self.developer_pk)
return False, result
@ -378,7 +399,7 @@ class AppDeveloperApiV2(object):
if apple_obj.delete_profile_by_id(profile_id, profile_name):
return True
except Exception as e:
logger.error(f"ios developer delete profile Failed Exception:{e}")
logger.error(f"issuer_id:{self.issuer_id} ios developer delete profile Failed Exception:{e}")
result['return_info'] = check_error_call_back(str(e), self.developer_pk)
return False, result
@ -391,18 +412,20 @@ class AppDeveloperApiV2(object):
device_obj = apple_obj.enabled_device(device_id, device_name, device_udid)
else:
device_obj = apple_obj.disabled_device(device_id, device_name, device_udid)
logger.info("device_obj %s result:%s" % (device_obj, status))
if device_obj and device_obj.id:
logger.info(f"issuer_id:{self.issuer_id} device_obj:{device_obj} result:{status}")
if device_obj and isinstance(device_obj, Devices):
return True, result
raise Exception(str(device_obj))
except Exception as e:
logger.error("ios developer set devices status Failed Exception:%s" % e)
logger.error(f"issuer_id:{self.issuer_id} ios developer set devices status Failed Exception:{e}")
result['return_info'] = check_error_call_back(str(e), self.developer_pk)
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:
device_err_callback()
else:
logger.warning(f'{device_err_callback}-{failed_call_prefix} is running')
logger.warning(
f'issuer_id:{self.issuer_id} {device_err_callback}-{failed_call_prefix} is running')
return False, result
def get_device(self):
@ -410,12 +433,9 @@ class AppDeveloperApiV2(object):
try:
apple_obj = AppStoreConnectApi(self.issuer_id, self.private_key_id, self.p8key)
devices_obj_list = apple_obj.get_all_devices()
if not isinstance(devices_obj_list, list):
devices_obj_list = [devices_obj_list]
if devices_obj_list is not None:
return True, devices_obj_list
return self.__result_format(devices_obj_list, Devices)
except Exception as e:
logger.error("ios developer get device Failed Exception:%s" % e)
logger.error(f"issuer_id:{self.issuer_id} ios developer get device Failed Exception:{e}")
result['return_info'] = check_error_call_back(str(e), self.developer_pk)
return False, result
@ -424,10 +444,10 @@ class AppDeveloperApiV2(object):
try:
apple_obj = AppStoreConnectApi(self.issuer_id, self.private_key_id, self.p8key)
if apple_obj.delete_bundle_by_identifier(identifier_id, f"{bundle_id}.{self.issuer_id}.{app_id}"):
return True, {}
return True, result
except Exception as e:
logger.error("ios developer delete app Failed Exception:%s" % e)
logger.error(f"issuer_id:{self.issuer_id} ios developer delete app Failed Exception:{e}")
result['return_info'] = check_error_call_back(str(e), self.developer_pk)
return False, result
@ -444,11 +464,12 @@ class AppDeveloperApiV2(object):
bundle_obj = apple_obj.register_bundle_id_enable_capability(app_id,
f"{bundle_id}.{self.issuer_id}.{app_id}",
s_type)
result['aid'] = bundle_obj.id
return True, result
if bundle_obj and isinstance(bundle_obj, BundleIds):
result['aid'] = bundle_obj.id
return True, result
raise Exception(str(bundle_obj))
except Exception as e:
logger.error("ios developer create app Failed Exception:%s" % e)
logger.error(f"issuer_id:{self.issuer_id} ios developer create app Failed Exception:{e}")
result['return_info'] = check_error_call_back(str(e), self.developer_pk)
if app_id_err_callback and "There is no App ID with ID" in str(e):
for call_fun in app_id_err_callback:
@ -459,18 +480,27 @@ class AppDeveloperApiV2(object):
result = {}
try:
apple_obj = AppStoreConnectApi(self.issuer_id, self.private_key_id, self.p8key)
return True, apple_obj.register_device(device_name, device_udid)
device_obj = apple_obj.register_device(device_name, device_udid)
if device_obj and isinstance(device_obj, Devices):
return True, device_obj
raise Exception(str(device_obj))
except Exception as e:
logger.error("ios developer register device Failed Exception:%s" % e)
logger.error(f"issuer_id:{self.issuer_id} ios developer register device Failed Exception:{e}")
result['return_info'] = check_error_call_back(str(e), self.developer_pk)
if device_err_callback and "There are no current ios devices" in str(e):
with CleanErrorBundleIdSignDataState(failed_call_prefix) as state:
if state:
device_err_callback()
else:
logger.warning(f'{device_err_callback}-{failed_call_prefix} is running')
err_msg_list = [
"There are no current ios devices",
"Your development team has reached the maximum number of registered iPhone devices"
]
if device_err_callback:
for err_msg in err_msg_list:
if err_msg in str(e):
with CleanErrorBundleIdSignDataState(failed_call_prefix) as state:
if state:
device_err_callback()
else:
logger.warning(
f'issuer_id:{self.issuer_id} {device_err_callback}-{failed_call_prefix} is running')
break
return False, result
def make_and_download_profile(self, app_obj, provision_name, auth, developer_app_id, device_id_list, profile_id,
@ -483,7 +513,7 @@ class AppDeveloperApiV2(object):
profile_obj = apple_obj.create_profile(profile_id, developer_app_id, auth.get('cert_id'),
provision_name.split("/")[-1],
device_id_list)
if profile_obj:
if profile_obj and isinstance(profile_obj, Profiles):
result['profile_id'] = profile_obj.id
n = base64.b64decode(profile_obj.profileContent)
if not os.path.isdir(os.path.dirname(provision_name)):
@ -491,8 +521,10 @@ class AppDeveloperApiV2(object):
with open(provision_name, 'wb') as f:
f.write(n)
return True, result
raise Exception(str(profile_obj))
except Exception as e:
logger.error(f"app_id {app_obj.app_id} ios developer make profile Failed Exception:{e}")
logger.error(f"issuer_id:{self.issuer_id} app_id {app_obj.app_id} ios developer make profile Failed "
f"Exception:{e}")
result['return_info'] = check_error_call_back(str(e), self.developer_pk)
if app_id_err_callback and "There is no App ID with ID" in str(e):
with CleanErrorBundleIdSignDataState(failed_call_prefix) as state:
@ -500,7 +532,8 @@ class AppDeveloperApiV2(object):
for call_fun in app_id_err_callback:
call_fun()
else:
logger.warning(f'{app_id_err_callback}-{failed_call_prefix} is running')
logger.warning(
f'issuer_id:{self.issuer_id} {app_id_err_callback}-{failed_call_prefix} is running')
return False, result
def modify_capability(self, app_obj, developer_app_id):
@ -522,10 +555,13 @@ class AppDeveloperApiV2(object):
bundle_obj = apple_obj.register_bundle_id_enable_capability(app_id,
f"{bundle_id}.{self.issuer_id}.{app_id}",
s_type)
developer_app_id = bundle_obj.id
result['aid'] = developer_app_id
if bundle_obj and isinstance(bundle_obj, BundleIds):
developer_app_id = bundle_obj.id
result['aid'] = developer_app_id
else:
raise Exception(str(bundle_obj))
return True, result
except Exception as e:
logger.error("ios developer modify_capability Failed Exception:%s" % e)
logger.error(f"issuer_id:{self.issuer_id} ios developer modify_capability Failed Exception:{e}")
result['return_info'] = check_error_call_back(str(e), self.developer_pk)
return False, result

@ -986,9 +986,10 @@ class IosUtils(object):
return False, {'err_info': str(e)}
@staticmethod
def active_developer(developer_obj):
def active_developer(developer_obj, auto_clean=True):
"""
激活开发者账户
:param auto_clean:
:param developer_obj:
:return:
"""
@ -996,15 +997,16 @@ class IosUtils(object):
status, result = app_api_obj.active()
if status:
cert_is_exists = True
for cert_obj in result.get('data', []):
for cert_obj in result:
if cert_obj.id == developer_obj.certid:
developer_obj.cert_expire_time = format_apple_date(cert_obj.expirationDate)
cert_is_exists = False
break
if developer_obj.certid and len(developer_obj.certid) > 3 and cert_is_exists and len(
result.get('data', [])) > 0:
if developer_obj.certid and len(developer_obj.certid) > 3 and cert_is_exists and len(result) > 0:
# 数据库证书id和苹果开发id不一致,可认为被用户删掉,需要执行清理开发者操作
IosUtils.clean_developer(developer_obj, developer_obj.user_id)
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
developer_obj.status = 1

Loading…
Cancel
Save