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

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 # 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: 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: 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 return req
@ -100,9 +101,10 @@ class DevicesAPI(object):
if query_parameters: if query_parameters:
for k, v in query_parameters.items(): for k, v in query_parameters.items():
params[k] = v params[k] = v
return request_format_log( return request_format_log(self,
requests.get(self.devices_url, params=params, headers=self.headers, proxies=self.proxies, requests.get(self.devices_url, params=params, headers=self.headers,
timeout=self.timeout)) proxies=self.proxies,
timeout=self.timeout))
def list_enabled_devices(self): def list_enabled_devices(self):
return self.list_devices({"filter[status]": "ENABLED"}) return self.list_devices({"filter[status]": "ENABLED"})
@ -135,9 +137,9 @@ class DevicesAPI(object):
} }
} }
} }
return request_format_log( return request_format_log(self,
requests.post(self.devices_url, json=json, headers=self.headers, proxies=self.proxies, requests.post(self.devices_url, json=json, headers=self.headers, proxies=self.proxies,
timeout=self.timeout)) timeout=self.timeout))
def read_device_information(self, device_id): def read_device_information(self, device_id):
""" """
@ -152,8 +154,9 @@ class DevicesAPI(object):
params = { params = {
"fields[devices]": "addedDate, deviceClass, model, name, platform, status, udid", "fields[devices]": "addedDate, deviceClass, model, name, platform, status, udid",
} }
return request_format_log( return request_format_log(self,
requests.get(base_url, params=params, headers=self.headers, proxies=self.proxies, timeout=self.timeout)) requests.get(base_url, params=params, headers=self.headers, proxies=self.proxies,
timeout=self.timeout))
def enabled_device(self, device_id, device_name): def enabled_device(self, device_id, device_name):
return self.modify_registered_device(device_id, device_name, 'ENABLED') return self.modify_registered_device(device_id, device_name, 'ENABLED')
@ -184,8 +187,9 @@ class DevicesAPI(object):
} }
} }
} }
return request_format_log( return request_format_log(self,
requests.patch(base_url, json=json, headers=self.headers, proxies=self.proxies, timeout=self.timeout)) requests.patch(base_url, json=json, headers=self.headers, proxies=self.proxies,
timeout=self.timeout))
class BundleIDsAPI(object): class BundleIDsAPI(object):
@ -217,9 +221,10 @@ class BundleIDsAPI(object):
} }
} }
} }
return request_format_log( return request_format_log(self,
requests.post(self.bundle_ids_url, json=json, headers=self.headers, proxies=self.proxies, requests.post(self.bundle_ids_url, json=json, headers=self.headers,
timeout=self.timeout)) proxies=self.proxies,
timeout=self.timeout))
def delete_bundle_id_by_id(self, bundle_id): 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) base_url = '%s/%s' % (self.bundle_ids_url, bundle_id)
json = {} json = {}
return request_format_log( return request_format_log(self,
requests.delete(base_url, json=json, headers=self.headers, proxies=self.proxies, timeout=self.timeout)) requests.delete(base_url, json=json, headers=self.headers, proxies=self.proxies,
timeout=self.timeout))
def list_bundle_ids(self, query_parameters=None): def list_bundle_ids(self, query_parameters=None):
""" """
@ -252,9 +258,10 @@ class BundleIDsAPI(object):
if query_parameters: if query_parameters:
for k, v in query_parameters.items(): for k, v in query_parameters.items():
params[k] = v params[k] = v
return request_format_log( return request_format_log(self,
requests.get(self.bundle_ids_url, params=params, headers=self.headers, proxies=self.proxies, requests.get(self.bundle_ids_url, params=params, headers=self.headers,
timeout=self.timeout)) proxies=self.proxies,
timeout=self.timeout))
def list_bundle_id_by_identifier(self, identifier): def list_bundle_id_by_identifier(self, identifier):
return self.list_bundle_ids({"filter[identifier]": identifier}) return self.list_bundle_ids({"filter[identifier]": identifier})
@ -283,8 +290,9 @@ class BundleIDsAPI(object):
} }
} }
} }
return request_format_log( return request_format_log(self,
requests.patch(base_url, json=json, headers=self.headers, proxies=self.proxies, timeout=self.timeout)) requests.patch(base_url, json=json, headers=self.headers, proxies=self.proxies,
timeout=self.timeout))
class BundleIDsCapabilityAPI(object): class BundleIDsCapabilityAPI(object):
@ -306,8 +314,9 @@ class BundleIDsCapabilityAPI(object):
""" """
base_url = '%s/%s_%s' % (self.bundle_ids_capability_url, bundle_id, capability_type) base_url = '%s/%s_%s' % (self.bundle_ids_capability_url, bundle_id, capability_type)
json = {} json = {}
return request_format_log( return request_format_log(self,
requests.delete(base_url, json=json, headers=self.headers, proxies=self.proxies, timeout=self.timeout)) requests.delete(base_url, json=json, headers=self.headers, proxies=self.proxies,
timeout=self.timeout))
def enable_capability(self, bundle_id, capability_type): def enable_capability(self, bundle_id, capability_type):
""" """
@ -336,9 +345,10 @@ class BundleIDsCapabilityAPI(object):
} }
} }
} }
return request_format_log( return request_format_log(self,
requests.post(self.bundle_ids_capability_url, json=json, headers=self.headers, proxies=self.proxies, requests.post(self.bundle_ids_capability_url, json=json, headers=self.headers,
timeout=self.timeout)) proxies=self.proxies,
timeout=self.timeout))
class ProfilesAPI(object): class ProfilesAPI(object):
@ -390,9 +400,10 @@ class ProfilesAPI(object):
} }
} }
} }
return request_format_log( return request_format_log(self,
requests.post(self.profiles_url, json=json, headers=self.headers, proxies=self.proxies, requests.post(self.profiles_url, json=json, headers=self.headers,
timeout=self.timeout)) proxies=self.proxies,
timeout=self.timeout))
def delete_profile(self, profile_id): def delete_profile(self, profile_id):
""" """
@ -406,8 +417,9 @@ class ProfilesAPI(object):
""" """
base_url = '%s/%s' % (self.profiles_url, profile_id) base_url = '%s/%s' % (self.profiles_url, profile_id)
json = {} json = {}
return request_format_log( return request_format_log(self,
requests.delete(base_url, json=json, headers=self.headers, proxies=self.proxies, timeout=self.timeout)) requests.delete(base_url, json=json, headers=self.headers, proxies=self.proxies,
timeout=self.timeout))
def download_profile(self, profile_id): def download_profile(self, profile_id):
# n=base64.b64decode(profileContent) # n=base64.b64decode(profileContent)
@ -432,9 +444,10 @@ class ProfilesAPI(object):
if query_parameters: if query_parameters:
for k, v in query_parameters.items(): for k, v in query_parameters.items():
params[k] = v params[k] = v
return request_format_log( return request_format_log(self,
requests.get(self.profiles_url, params=params, headers=self.headers, proxies=self.proxies, requests.get(self.profiles_url, params=params, headers=self.headers,
timeout=self.timeout)) proxies=self.proxies,
timeout=self.timeout))
def list_profile_by_profile_id(self, profile_id): def list_profile_by_profile_id(self, profile_id):
return self.list_profiles({"filter[id]": profile_id, "include": ""}) return self.list_profiles({"filter[id]": profile_id, "include": ""})
@ -469,9 +482,10 @@ class CertificatesAPI(object):
} }
} }
} }
return request_format_log( return request_format_log(self,
requests.post(self.certificates_url, json=json, headers=self.headers, proxies=self.proxies, requests.post(self.certificates_url, json=json, headers=self.headers,
timeout=self.timeout)) proxies=self.proxies,
timeout=self.timeout))
def download_certificate(self, certificate_id): def download_certificate(self, certificate_id):
# req.json()['data'][0]['attributes']['certificateContent'] # req.json()['data'][0]['attributes']['certificateContent']
@ -496,9 +510,10 @@ class CertificatesAPI(object):
if query_parameters: if query_parameters:
for k, v in query_parameters.items(): for k, v in query_parameters.items():
params[k] = v params[k] = v
return request_format_log( return request_format_log(self,
requests.get(self.certificates_url, params=params, headers=self.headers, proxies=self.proxies, requests.get(self.certificates_url, params=params, headers=self.headers,
timeout=self.timeout)) proxies=self.proxies,
timeout=self.timeout))
def list_certificate_by_certificate_id(self, certificate_id): def list_certificate_by_certificate_id(self, certificate_id):
return self.list_certificate({"filter[id]": 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) base_url = '%s/%s' % (self.certificates_url, certificate_id)
json = {} json = {}
return request_format_log( return request_format_log(self,
requests.delete(base_url, json=json, headers=self.headers, proxies=self.proxies, timeout=self.timeout)) requests.delete(base_url, json=json, headers=self.headers, proxies=self.proxies,
timeout=self.timeout))
class BaseInfoObj(object): class BaseInfoObj(object):
@ -745,6 +761,18 @@ class AppStoreConnectApi(DevicesAPI, BundleIDsAPI, BundleIDsCapabilityAPI, Profi
CertificatesAPI.__init__(self, self.BASE_URI, self.headers) CertificatesAPI.__init__(self, self.BASE_URI, self.headers)
self.rate_limit_info = {} 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): def __set_rate_limit_info(self, req_headers):
for par in req_headers.get('X-Rate-Limit').split(";"): for par in req_headers.get('X-Rate-Limit').split(";"):
if par: if par:
@ -796,6 +824,8 @@ class AppStoreConnectApi(DevicesAPI, BundleIDsAPI, BundleIDsCapabilityAPI, Profi
obj = Certificates.from_json_list(data) obj = Certificates.from_json_list(data)
if len(obj) == 1: if len(obj) == 1:
return obj[0] return obj[0]
if obj is None:
raise Exception(f'None object: {req.text}')
return obj return obj
else: else:
# self.__init_jwt_headers() # self.__init_jwt_headers()

@ -43,7 +43,7 @@ class EmailMsgSender(object):
def send_email_msg(self, email, text): def send_email_msg(self, email, text):
try: try:
response = send_mail("重要消息通知", text, self.form, [email], ) response = send_mail("重要消息通知", text, self.form, [email], html_message=text)
except Exception as e: except Exception as e:
return -1, e return -1, e
return response, text 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 = [ TEMPLATES = [
{ {
'BACKEND': 'django.template.backends.django.DjangoTemplates', '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, 'APP_DIRS': True,
'OPTIONS': { '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 os
import time import time
from django.template import loader
from common.core.sysconfig import Config from common.core.sysconfig import Config
from fir_ser.settings import SUPER_SIGN_ROOT, SYNC_CACHE_TO_DATABASE from fir_ser.settings import SUPER_SIGN_ROOT, SYNC_CACHE_TO_DATABASE
from xsign.models import UserInfo, AppIOSDeveloperInfo from xsign.models import UserInfo, AppIOSDeveloperInfo
@ -41,14 +43,17 @@ def auto_check_ios_developer_active():
if userinfo.supersign_active: if userinfo.supersign_active:
status, result = IosUtils.active_developer(ios_developer) status, result = IosUtils.active_developer(ios_developer)
msg = f"auto_check_ios_developer_active user:{userinfo} ios.developer:{ios_developer} status:{status} result:{result}" 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: if status:
IosUtils.get_device_from_developer(ios_developer) IosUtils.get_device_from_developer(ios_developer)
logger.info(msg) logger.info(msg)
else: else:
err_issuer_id.append(ios_developer.issuer_id)
logger.error(msg) 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() userinfo = UserInfo.objects.filter(uid=uid).first()
send_ios_developer_active_status(userinfo, Config.MSG_AUTO_CHECK_DEVELOPER % ( content = loader.render_to_string('check_developer.html',
userinfo.first_name, ",".join(val))) {'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.base.baseutils import get_format_time, format_apple_date, make_app_uuid
from common.cache.state import CleanErrorBundleIdSignDataState from common.cache.state import CleanErrorBundleIdSignDataState
from common.core.sysconfig import Config 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 fir_ser.settings import SUPER_SIGN_ROOT
from xsign.models import AppIOSDeveloperInfo from xsign.models import AppIOSDeveloperInfo
@ -260,60 +260,78 @@ class AppDeveloperApiV2(object):
if AppIOSDeveloperInfo.objects.filter(pk=self.developer_pk, if AppIOSDeveloperInfo.objects.filter(pk=self.developer_pk,
status__in=Config.DEVELOPER_WRITE_STATUS).first(): status__in=Config.DEVELOPER_WRITE_STATUS).first():
start_time = time.time() 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) 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 return result
else: else:
result = False, {'return_info': '开发者状态异常'} 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 result
return func return func
else: else:
return attr 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): def active(self):
result = {'data': []} """
:return: 结果为空列表或者是 object 或者是 [object,object] 其他为 false
"""
result = {}
try: try:
apple_obj = AppStoreConnectApi(self.issuer_id, self.private_key_id, self.p8key) apple_obj = AppStoreConnectApi(self.issuer_id, self.private_key_id, self.p8key)
certificates = apple_obj.get_all_certificates() certificates = apple_obj.get_all_certificates()
if not isinstance(certificates, list): return self.__result_format(certificates, Certificates)
certificates = [certificates]
result['data'] = certificates
logger.info(f"ios developer active result:{certificates}")
if len(certificates) >= 0:
return True, result
except Exception as e: 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) result['return_info'] = check_error_call_back(str(e), self.developer_pk)
return False, result 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): def create_cert(self, user_obj):
result = {} result = {}
try: try:
apple_obj = AppStoreConnectApi(self.issuer_id, self.private_key_id, self.p8key) 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)): if not os.path.isdir(os.path.dirname(csr_path)):
os.makedirs(os.path.dirname(csr_path)) os.makedirs(os.path.dirname(csr_path))
csr_content = make_csr_content(csr_path + ".csr", csr_path + ".key") csr_content = make_csr_content(csr_path + ".csr", csr_path + ".key")
certificates = apple_obj.create_certificate(csr_content.decode("utf-8")) certificates = apple_obj.create_certificate(csr_content.decode("utf-8"))
if certificates: if certificates and isinstance(certificates, Certificates):
n = base64.b64decode(certificates.certificateContent) n = base64.b64decode(certificates.certificateContent)
with open(csr_path + ".cer", 'wb') as f: with open(csr_path + ".cer", 'wb') as f:
f.write(n) f.write(n)
make_pem(n, csr_path + ".pem") 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 return True, certificates
raise Exception(str(certificates))
except Exception as e: 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) result['return_info'] = check_error_call_back(str(e), self.developer_pk)
return False, result return False, result
@ -322,13 +340,13 @@ class AppDeveloperApiV2(object):
try: try:
apple_obj = AppStoreConnectApi(self.issuer_id, self.private_key_id, self.p8key) apple_obj = AppStoreConnectApi(self.issuer_id, self.private_key_id, self.p8key)
cert_obj = apple_obj.get_certificate_by_cid(self.cert_id) cert_obj = apple_obj.get_certificate_by_cid(self.cert_id)
if cert_obj and cert_obj.id: if cert_obj and isinstance(cert_obj, Certificates):
return True, result return True, cert_obj
else: 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 return False, result
except Exception as e: 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) result['return_info'] = check_error_call_back(str(e), self.developer_pk)
return False, result return False, result
@ -337,17 +355,19 @@ class AppDeveloperApiV2(object):
try: try:
apple_obj = AppStoreConnectApi(self.issuer_id, self.private_key_id, self.p8key) apple_obj = AppStoreConnectApi(self.issuer_id, self.private_key_id, self.p8key)
cert_obj = apple_obj.get_certificate_by_cid(self.cert_id) 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) s_date = format_apple_date(cert_obj.expirationDate)
if s_date.timestamp() - datetime.datetime.now().timestamp() < 3600 * 24 * 3: if s_date.timestamp() - datetime.datetime.now().timestamp() < 3600 * 24 * 3:
if apple_obj.revoke_certificate(self.cert_id): 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 return True, result
else: 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 return True, result
raise Exception(str(cert_obj))
except Exception as e: 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) result['return_info'] = check_error_call_back(str(e), self.developer_pk)
return False, result 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") 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) apple_obj = AppStoreConnectApi(self.issuer_id, self.private_key_id, self.p8key)
certificates = apple_obj.get_all_certificates() certificates = apple_obj.get_all_certificates()
if not isinstance(certificates, list): status, result = self.__result_format(certificates, Certificates)
certificates = [certificates] if status:
for cert_obj in certificates: for cert_obj in result:
f_date = format_apple_date(cert_obj.expirationDate) f_date = format_apple_date(cert_obj.expirationDate)
logger.info(f"{cert_obj.id}-{not_after.timestamp()} - {f_date.timestamp()} ") logger.info(
if not_after.timestamp() == f_date.timestamp(): f"issuer_id:{self.issuer_id} {cert_obj.id}-{not_after.timestamp()} - {f_date.timestamp()} ")
return True, cert_obj if not_after.timestamp() == f_date.timestamp():
return False, result return True, cert_obj
raise Exception(str(certificates))
except Exception as e: 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) result['return_info'] = check_error_call_back(str(e), self.developer_pk)
return False, result return False, result
@ -378,7 +399,7 @@ class AppDeveloperApiV2(object):
if apple_obj.delete_profile_by_id(profile_id, profile_name): if apple_obj.delete_profile_by_id(profile_id, profile_name):
return True return True
except Exception as e: 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) result['return_info'] = check_error_call_back(str(e), self.developer_pk)
return False, result return False, result
@ -391,18 +412,20 @@ class AppDeveloperApiV2(object):
device_obj = apple_obj.enabled_device(device_id, device_name, device_udid) device_obj = apple_obj.enabled_device(device_id, device_name, device_udid)
else: else:
device_obj = apple_obj.disabled_device(device_id, device_name, device_udid) device_obj = apple_obj.disabled_device(device_id, device_name, device_udid)
logger.info("device_obj %s result:%s" % (device_obj, status)) logger.info(f"issuer_id:{self.issuer_id} device_obj:{device_obj} result:{status}")
if device_obj and device_obj.id: if device_obj and isinstance(device_obj, Devices):
return True, result return True, result
raise Exception(str(device_obj))
except Exception as e: 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) 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)): 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: with CleanErrorBundleIdSignDataState(failed_call_prefix) as state:
if state: if state:
device_err_callback() device_err_callback()
else: 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 return False, result
def get_device(self): def get_device(self):
@ -410,12 +433,9 @@ class AppDeveloperApiV2(object):
try: try:
apple_obj = AppStoreConnectApi(self.issuer_id, self.private_key_id, self.p8key) apple_obj = AppStoreConnectApi(self.issuer_id, self.private_key_id, self.p8key)
devices_obj_list = apple_obj.get_all_devices() devices_obj_list = apple_obj.get_all_devices()
if not isinstance(devices_obj_list, list): return self.__result_format(devices_obj_list, Devices)
devices_obj_list = [devices_obj_list]
if devices_obj_list is not None:
return True, devices_obj_list
except Exception as e: 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) result['return_info'] = check_error_call_back(str(e), self.developer_pk)
return False, result return False, result
@ -424,10 +444,10 @@ class AppDeveloperApiV2(object):
try: try:
apple_obj = AppStoreConnectApi(self.issuer_id, self.private_key_id, self.p8key) 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}"): 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: 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) result['return_info'] = check_error_call_back(str(e), self.developer_pk)
return False, result return False, result
@ -444,11 +464,12 @@ class AppDeveloperApiV2(object):
bundle_obj = apple_obj.register_bundle_id_enable_capability(app_id, bundle_obj = apple_obj.register_bundle_id_enable_capability(app_id,
f"{bundle_id}.{self.issuer_id}.{app_id}", f"{bundle_id}.{self.issuer_id}.{app_id}",
s_type) s_type)
result['aid'] = bundle_obj.id if bundle_obj and isinstance(bundle_obj, BundleIds):
return True, result result['aid'] = bundle_obj.id
return True, result
raise Exception(str(bundle_obj))
except Exception as e: 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) 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): if app_id_err_callback and "There is no App ID with ID" in str(e):
for call_fun in app_id_err_callback: for call_fun in app_id_err_callback:
@ -459,18 +480,27 @@ class AppDeveloperApiV2(object):
result = {} result = {}
try: try:
apple_obj = AppStoreConnectApi(self.issuer_id, self.private_key_id, self.p8key) 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: 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) 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): err_msg_list = [
"There are no current ios devices",
with CleanErrorBundleIdSignDataState(failed_call_prefix) as state: "Your development team has reached the maximum number of registered iPhone devices"
if state: ]
device_err_callback() if device_err_callback:
else: for err_msg in err_msg_list:
logger.warning(f'{device_err_callback}-{failed_call_prefix} is running') 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 return False, result
def make_and_download_profile(self, app_obj, provision_name, auth, developer_app_id, device_id_list, profile_id, 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'), profile_obj = apple_obj.create_profile(profile_id, developer_app_id, auth.get('cert_id'),
provision_name.split("/")[-1], provision_name.split("/")[-1],
device_id_list) device_id_list)
if profile_obj: if profile_obj and isinstance(profile_obj, Profiles):
result['profile_id'] = profile_obj.id result['profile_id'] = profile_obj.id
n = base64.b64decode(profile_obj.profileContent) n = base64.b64decode(profile_obj.profileContent)
if not os.path.isdir(os.path.dirname(provision_name)): if not os.path.isdir(os.path.dirname(provision_name)):
@ -491,8 +521,10 @@ class AppDeveloperApiV2(object):
with open(provision_name, 'wb') as f: with open(provision_name, 'wb') as f:
f.write(n) f.write(n)
return True, result return True, result
raise Exception(str(profile_obj))
except Exception as e: 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) 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): if app_id_err_callback and "There is no App ID with ID" in str(e):
with CleanErrorBundleIdSignDataState(failed_call_prefix) as state: with CleanErrorBundleIdSignDataState(failed_call_prefix) as state:
@ -500,7 +532,8 @@ class AppDeveloperApiV2(object):
for call_fun in app_id_err_callback: for call_fun in app_id_err_callback:
call_fun() call_fun()
else: 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 return False, result
def modify_capability(self, app_obj, developer_app_id): 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, bundle_obj = apple_obj.register_bundle_id_enable_capability(app_id,
f"{bundle_id}.{self.issuer_id}.{app_id}", f"{bundle_id}.{self.issuer_id}.{app_id}",
s_type) s_type)
developer_app_id = bundle_obj.id if bundle_obj and isinstance(bundle_obj, BundleIds):
result['aid'] = developer_app_id developer_app_id = bundle_obj.id
result['aid'] = developer_app_id
else:
raise Exception(str(bundle_obj))
return True, result return True, result
except Exception as e: 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) result['return_info'] = check_error_call_back(str(e), self.developer_pk)
return False, result return False, result

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

Loading…
Cancel
Save