diff --git a/fir_ser/api/migrations/0017_developerappid_profile_id.py b/fir_ser/api/migrations/0017_developerappid_profile_id.py new file mode 100644 index 0000000..215d605 --- /dev/null +++ b/fir_ser/api/migrations/0017_developerappid_profile_id.py @@ -0,0 +1,17 @@ +# Generated by Django 3.2.3 on 2021-11-02 17:44 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ('api', '0016_alter_appudid_udid'), + ] + + operations = [ + migrations.AddField( + model_name='developerappid', + name='profile_id', + field=models.CharField(blank=True, max_length=64, null=True), + ), + ] diff --git a/fir_ser/api/models.py b/fir_ser/api/models.py index 0e20654..263eeb8 100644 --- a/fir_ser/api/models.py +++ b/fir_ser/api/models.py @@ -341,6 +341,7 @@ class UDIDsyncDeveloper(models.Model): class DeveloperAppID(models.Model): aid = models.CharField(max_length=64, null=False) # ,apple APP 唯一标识 + profile_id = models.CharField(max_length=64, null=True, blank=True) # ,profile_id 唯一标识 developerid = models.ForeignKey(to="AppIOSDeveloperInfo", on_delete=models.CASCADE, verbose_name="所使用苹果开发者账户") app_id = models.ForeignKey(to="Apps", on_delete=models.CASCADE, verbose_name="属于哪个APP") diff --git a/fir_ser/api/utils/app/iossignapi.py b/fir_ser/api/utils/app/iossignapi.py index 2cda2df..4a55341 100644 --- a/fir_ser/api/utils/app/iossignapi.py +++ b/fir_ser/api/utils/app/iossignapi.py @@ -293,7 +293,7 @@ class AppDeveloperApiV2(object): return False, result def get_profile(self, app_obj, udid_info, provision_name, auth, developer_app_id, - device_id_list, err_callback): + device_id_list, profile_id, device_err_callback, app_id_err_callback): result = {} bundle_id = app_obj.bundle_id app_id = app_obj.app_id @@ -319,10 +319,11 @@ class AppDeveloperApiV2(object): result['did'] = device_obj.id device_id_list.append(device_obj.id) - profile_obj = apple_obj.create_profile(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], device_id_list) if profile_obj: + result['profile_id'] = profile_obj.id n = base64.b64decode(profile_obj.profileContent) if not os.path.isdir(os.path.dirname(provision_name)): os.makedirs(os.path.dirname(provision_name)) @@ -333,31 +334,31 @@ class AppDeveloperApiV2(object): logger.error(f"app_id {app_obj.app_id} ios developer make profile Failed Exception:{e}") result['return_info'] = "%s" % e if "There are no current ios devices" in str(e): - err_callback() + device_err_callback() + if "There is no App ID with ID" in str(e): + app_id_err_callback() return False, result - def del_profile(self, app_id): + def del_profile(self, profile_id, profile_name): result = {} try: apple_obj = AppStoreConnectApi(self.issuer_id, self.private_key_id, self.p8key) - profile_obj = apple_obj.list_profile_by_profile_name(app_id) - if profile_obj: - if apple_obj.delete_profile_by_id(profile_obj.id): - return True, profile_obj + 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}") result['return_info'] = "%s" % e return False, result - def set_device_status(self, status, device_udid): + def set_device_status(self, status, device_id, device_name, device_udid): result = {} try: apple_obj = AppStoreConnectApi(self.issuer_id, self.private_key_id, self.p8key) if status == "enable": - device_obj = apple_obj.enabled_device(device_udid) + device_obj = apple_obj.enabled_device(device_id, device_name, device_udid) else: - device_obj = apple_obj.disabled_device(device_udid) + 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: return True, result @@ -378,11 +379,11 @@ class AppDeveloperApiV2(object): result['return_info'] = "%s" % e return False, result - def del_app(self, bundle_id, app_id): + def del_app(self, identifier_id, bundle_id, app_id): result = {} try: apple_obj = AppStoreConnectApi(self.issuer_id, self.private_key_id, self.p8key) - if apple_obj.delete_bundle_by_identifier(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, {} except Exception as e: diff --git a/fir_ser/api/utils/app/supersignutils.py b/fir_ser/api/utils/app/supersignutils.py index 50a165f..454ab39 100644 --- a/fir_ser/api/utils/app/supersignutils.py +++ b/fir_ser/api/utils/app/supersignutils.py @@ -318,12 +318,14 @@ class IosUtils(object): developerid=developer_obj).values_list('did') device_id_lists = [did[0] for did in device_id_list] developer_app_id = None + profile_id = None add_did_flag = False sync_device_obj = None developer_app_id_obj = DeveloperAppID.objects.filter(developerid=developer_obj, app_id=app_obj).first() if developer_app_id_obj: developer_app_id = developer_app_id_obj.aid + profile_id = developer_app_id_obj.profile_id if udid_info: sync_device_obj = UDIDsyncDeveloper.objects.filter(udid=udid_info.get('udid'), developerid=developer_obj, status=True).first() @@ -339,9 +341,11 @@ class IosUtils(object): status, result = get_api_obj(auth).get_profile(app_obj, udid_info, get_profile_full_path(developer_obj, app_obj), - auth, developer_app_id, device_id_lists, + auth, developer_app_id, device_id_lists, profile_id, err_callback(IosUtils.get_device_from_developer, - developer_obj)) + developer_obj), + err_callback(IosUtils.clean_super_sign_things_by_app_obj, + app_obj, developer_obj)) if add_did_flag and sync_device_obj: result['did'] = sync_device_obj.serial result['did_exists'] = True @@ -363,6 +367,9 @@ class IosUtils(object): if not developer_app_id and result.get("aid", None): DeveloperAppID.objects.create(aid=result["aid"], developerid=developer_obj, app_id=app_obj) + if result.get("profile_id", None): + DeveloperAppID.objects.filter(developerid=developer_obj, app_id=app_obj).update( + profile_id=result.get("profile_id", None)) return True, result @@ -639,45 +646,38 @@ class IosUtils(object): usedeviceobj = APPSuperSignUsedInfo.objects.filter(udid=udid_obj, app_id_id=app_id) if usedeviceobj: developer_obj = usedeviceobj.first().developerid - auth = get_auth_form_developer(developer_obj) - # 需要判断该设备在同一个账户下 的多个应用,若存在,则不操作 udid_lists = list( APPSuperSignUsedInfo.objects.values_list("udid__udid__udid").filter(developerid=developer_obj)) - IosUtils.do_disable_device(developer_obj, udid_lists, udid_obj, auth) + IosUtils.do_disable_device(developer_obj, udid_lists, udid_obj) DeveloperDevicesID.objects.filter(udid__appudid=udid_obj, developerid=developer_obj, app_id_id=app_id).delete() udid_obj.delete() # 通过开发者id判断 app_id 是否多个,否则删除profile 文件 if APPSuperSignUsedInfo.objects.filter(developerid=developer_obj, app_id_id=app_id).count() == 0: - app_api_obj = get_api_obj(auth) app_obj = Apps.objects.filter(pk=app_id).first() - app_api_obj.del_profile(app_obj.app_id) - app_api_obj2 = get_api_obj(auth) - app_api_obj2.del_app(app_obj.bundle_id, app_obj.app_id) - DeveloperAppID.objects.filter(developerid=developer_obj, app_id=app_obj).delete() + IosUtils.clean_app_by_developer_obj(app_obj, developer_obj) delete_app_to_dev_and_file(developer_obj, app_id) delete_app_profile_file(developer_obj, app_obj) @staticmethod - def do_disable_device(developer_obj, udid_lists, udid_obj, auth): + def do_disable_device(developer_obj, udid_lists, udid_obj): if udid_lists.count((udid_obj.udid.udid,)) == 1: + auth = get_auth_form_developer(developer_obj) app_api_obj = get_api_obj(auth) - app_api_obj.set_device_status("disable", udid_obj.udid.udid) + app_api_obj.set_device_status("disable", udid_obj.udid.serial, udid_obj.udid.product, udid_obj.udid.udid) UDIDsyncDeveloper.objects.filter(udid=udid_obj.udid.udid, developerid=developer_obj).update(status=False) @staticmethod def clean_udid_by_app_obj(app_obj, developer_obj): - auth = get_auth_form_developer(developer_obj) - # 需要判断该设备在同一个账户下 的多个应用,若存在,则不操作 udid_lists = list( APPSuperSignUsedInfo.objects.values_list("udid__udid__udid").filter(developerid=developer_obj)) for SuperSignUsed_obj in APPSuperSignUsedInfo.objects.filter(app_id=app_obj, developerid=developer_obj): udid_obj = SuperSignUsed_obj.udid - IosUtils.do_disable_device(developer_obj, udid_lists, udid_obj, auth) + IosUtils.do_disable_device(developer_obj, udid_lists, udid_obj) SuperSignUsed_obj.delete() DeveloperDevicesID.objects.filter(udid__appudid=udid_obj, developerid=developer_obj, app_id=app_obj).delete() @@ -696,19 +696,31 @@ class IosUtils(object): for developer_id in developer_id_lists: developer_obj = AppIOSDeveloperInfo.objects.filter(pk=developer_id[0]).first() if developer_obj and developer_obj.user_id == app_obj.user_id: - IosUtils.clean_app_by_developer_obj(app_obj, developer_obj) - delete_app_to_dev_and_file(developer_obj, app_obj.id) - IosUtils.clean_udid_by_app_obj(app_obj, developer_obj) - delete_app_profile_file(developer_obj, app_obj) + IosUtils.clean_super_sign_things_by_app_obj(app_obj, developer_obj) + + @staticmethod + def clean_super_sign_things_by_app_obj(app_obj, developer_obj): + IosUtils.clean_app_by_developer_obj(app_obj, developer_obj) + delete_app_to_dev_and_file(developer_obj, app_obj.id) + IosUtils.clean_udid_by_app_obj(app_obj, developer_obj) + delete_app_profile_file(developer_obj, app_obj) @staticmethod def clean_app_by_developer_obj(app_obj, developer_obj): auth = get_auth_form_developer(developer_obj) - DeveloperAppID.objects.filter(developerid=developer_obj, app_id=app_obj).delete() + developer_app_id_obj = DeveloperAppID.objects.filter(developerid=developer_obj, app_id=app_obj).first() + identifier_id = None + profile_id = None + if developer_app_id_obj: + identifier_id = developer_app_id_obj.aid + profile_id = developer_app_id_obj.profile_id + app_api_obj = get_api_obj(auth) - app_api_obj.del_profile(app_obj.app_id) + app_api_obj.del_profile(profile_id, app_obj.app_id) app_api_obj2 = get_api_obj(auth) - app_api_obj2.del_app(app_obj.bundle_id, app_obj.app_id) + + app_api_obj2.del_app(identifier_id, app_obj.bundle_id, app_obj.app_id) + developer_app_id_obj.delete() @staticmethod def clean_developer(developer_obj, user_obj, delete_file=True): @@ -865,11 +877,7 @@ class IosUtils(object): for developer_device_obj in developer_device_list: app_obj = developer_device_obj.app_id if APPSuperSignUsedInfo.objects.filter(developerid=developer_obj, app_id=app_obj).count() == 0: - app_api_obj = get_api_obj(auth) - app_api_obj.del_profile(app_obj.app_id) - app_api_obj2 = get_api_obj(auth) - app_api_obj2.del_app(app_obj.bundle_id, app_obj.app_id) - DeveloperAppID.objects.filter(developerid=developer_obj, app_id=app_obj).delete() + IosUtils.clean_app_by_developer_obj(app_obj, developer_obj) delete_app_to_dev_and_file(developer_obj, app_obj.pk) delete_app_profile_file(developer_obj, app_obj) developer_device_obj.delete() diff --git a/fir_ser/api/utils/apple/appleapiv3.py b/fir_ser/api/utils/apple/appleapiv3.py index 6f906be..b73da4b 100644 --- a/fir_ser/api/utils/apple/appleapiv3.py +++ b/fir_ser/api/utils/apple/appleapiv3.py @@ -30,7 +30,7 @@ def request_format_log(req): # 需要和model里面的对应起来 -capability = [ +capability_info = [ [], ["PUSH_NOTIFICATIONS"], [ @@ -65,7 +65,7 @@ capability = [ def get_capability(s_type): - return capability[s_type] + return capability_info[s_type] class DevicesAPI(object): @@ -776,8 +776,8 @@ class AppStoreConnectApi(DevicesAPI, BundleIDsAPI, BundleIDsCapabilityAPI, Profi raise Exception('more than one Device obj') return device_obj_list - def register_device(self, device_name, dvice_udid, platform="IOS"): - device_obj_list = BaseInfoObj.filter(self.get_all_devices(), {"udid": dvice_udid}) + def register_device(self, device_name, device_udid, platform="IOS"): + device_obj_list = BaseInfoObj.filter(self.get_all_devices(), {"udid": device_udid}) # 发现同一个开发者账户里面有两个一样的udid,奇了怪 if device_obj_list and ( len(device_obj_list) == 1 or len(set([device_obj.udid for device_obj in device_obj_list])) == 1): @@ -785,20 +785,30 @@ class AppStoreConnectApi(DevicesAPI, BundleIDsAPI, BundleIDsCapabilityAPI, Profi req = self.modify_registered_device(device_obj.id, device_name, 'ENABLED') return self.__device_store(req) else: - req = super().register_device(device_name, dvice_udid, platform) + req = super().register_device(device_name, device_udid, platform) return self.__device_store(req, 201) - def enabled_device(self, udid, **kwargs): - device_obj_list = self.list_device_by_udid(udid) - for device_obj in device_obj_list: - req = self.modify_registered_device(device_obj.id, device_obj.name, 'ENABLED') - return self.__device_store(req) - - def disabled_device(self, udid, **kwargs): - device_obj_list = self.list_device_by_udid(udid) - for device_obj in device_obj_list: - req = self.modify_registered_device(device_obj.id, device_obj.name, 'DISABLED') - return self.__device_store(req) + def enabled_device(self, device_id, device_name, udid): + if device_id and device_name: + req = super().enabled_device(device_id, device_name) + if req.status_code == 200: + return self.__device_store(req) + if udid: + device_obj_list = self.list_device_by_udid(udid) + for device_obj in device_obj_list: + req = self.modify_registered_device(device_obj.id, device_obj.name, 'ENABLED') + return self.__device_store(req) + + def disabled_device(self, device_id, device_name, udid): + if device_id and device_name: + req = super().disabled_device(device_id, device_name) + if req.status_code == 200: + return self.__device_store(req) + if udid: + device_obj_list = self.list_device_by_udid(udid) + for device_obj in device_obj_list: + req = self.modify_registered_device(device_obj.id, device_obj.name, 'DISABLED') + return self.__device_store(req) def list_bundle_ids_by_identifier(self, identifier): req = super().list_bundle_id_by_identifier(identifier) @@ -820,7 +830,7 @@ class AppStoreConnectApi(DevicesAPI, BundleIDsAPI, BundleIDsCapabilityAPI, Profi logger.warning(f"{bundle_id} enable_capability {capability} failed {req.content}") return True - def disable_capability_by_s_type(self, bundle_id, s_type=len(capability) - 1): + def disable_capability_by_s_type(self, bundle_id, s_type=len(capability_info) - 1): capability_list = get_capability(s_type) if capability_list: for capability in capability_list: @@ -863,23 +873,28 @@ class AppStoreConnectApi(DevicesAPI, BundleIDsAPI, BundleIDsCapabilityAPI, Profi if self.enable_capability_by_s_type(bundle_ids.id, s_type): return bundle_ids - def delete_bundle_by_identifier(self, identifier): - identifier_obj = self.list_bundle_ids_by_identifier(identifier) + def delete_bundle_by_identifier(self, identifier_id, identifier_name): + if identifier_id: + req = self.delete_bundle_id_by_id(identifier_id) + if req.status_code == 204: + return True + identifier_obj = self.list_bundle_ids_by_identifier(identifier_name) if isinstance(identifier_obj, BundleIds): req = self.delete_bundle_id_by_id(identifier_obj.id) if req.status_code == 204: return True - def create_profile(self, bundle_id, certificate_id, profile_name, device_id_list=None, + def create_profile(self, profile_id, bundle_id, certificate_id, profile_name, device_id_list=None, profile_type='IOS_APP_ADHOC'): if device_id_list is None: device_id_list = [] if not device_id_list: device_id_list = [device.id for device in self.list_enabled_devices()] - profile_obj = self.list_profile_by_profile_name(profile_name) - if isinstance(profile_obj, Profiles): - self.delete_profile_by_id(profile_obj.id) + self.delete_profile_by_id(profile_id, profile_name) + # profile_obj = self.list_profile_by_profile_name(profile_name) + # if isinstance(profile_obj, Profiles): + # self.delete_profile_by_id(profile_obj.id, profile_name) req = super().create_profile(bundle_id, [certificate_id], profile_name, device_id_list) if req.status_code == 201: @@ -891,10 +906,16 @@ class AppStoreConnectApi(DevicesAPI, BundleIDsAPI, BundleIDsCapabilityAPI, Profi req = super().list_profile_by_profile_name(profile_name) return self.__profile_store(req) - def delete_profile_by_id(self, profile_id): - req = super().delete_profile(profile_id) - if self.__do_success(req): - return True + def delete_profile_by_id(self, profile_id, profile_name): + if profile_id: + req = super().delete_profile(profile_id) + if self.__do_success(req, 204): + return True + profile_obj = self.list_profile_by_profile_name(profile_name) + if profile_obj: + req = super().delete_profile(profile_obj.id) + if self.__do_success(req, 204): + return True def create_certificate(self, csr_content, certificate_type='IOS_DISTRIBUTION'): req = super().create_certificate(csr_content, certificate_type)