优化代码

dependabot/npm_and_yarn/fir_admin/url-parse-1.5.10
MMXX 3 years ago
parent c361d740bf
commit 59d7d905d3
  1. 1
      fir_client/src/components/FirBase.vue
  2. 4
      fir_client/src/components/apps/FirAppInfossecurity.vue
  3. 5
      fir_client/src/components/base/BindDomain.vue
  4. 87
      fir_client/src/components/user/FirSuperSignBase.vue
  5. 2
      fir_client/src/components/user/FirUserAdvert.vue
  6. 20
      fir_client/src/components/user/FirUserDomain.vue
  7. 17
      fir_client/src/components/user/FirUserOrders.vue
  8. 8
      fir_client/src/utils/index.js
  9. 13
      fir_ser/api/migrations/0028_auto_20211228_1454.py
  10. 5
      fir_ser/api/models.py
  11. 33
      fir_ser/api/utils/app/iossignapi.py
  12. 121
      fir_ser/api/utils/app/supersignutils.py
  13. 3
      fir_ser/api/utils/apple/appleapiv3.py
  14. 12
      fir_ser/api/utils/crontab/ctasks.py
  15. 3
      fir_ser/api/utils/serializer.py
  16. 4
      fir_ser/api/utils/utils.py
  17. 34
      fir_ser/api/views/supersign.py

@ -125,6 +125,7 @@ export default {
font-size: medium;
margin-right: 20px;
}
/deep/ .el-alert {
padding: 2px 16px;
}

@ -6,8 +6,8 @@
:visible.sync="bind_domain_sure"
title="绑定应用专属下载页域名"
width="666px">
<bind-domain v-if="bind_domain_sure" :app_id="this.currentapp.app_id" :domain_type="2"
:c_domain_name="this.currentapp.domain_name" transitionName="bind-app-domain"/>
<bind-domain v-if="bind_domain_sure" :app_id="this.currentapp.app_id" :c_domain_name="this.currentapp.domain_name"
:domain_type="2" transitionName="bind-app-domain"/>
</el-dialog>
<el-form label-width="80px">
<el-form-item label="访问密码" label-width="200px">

@ -244,7 +244,10 @@ export default {
} else {
this.$message.error("解除绑定失败 " + data.msg)
}
}, {methods: 'DELETE', data: {app_id: this.app_id, domain_type: this.domain_type, domain_name:this.domain_name}});
}, {
methods: 'DELETE',
data: {app_id: this.app_id, domain_type: this.domain_type, domain_name: this.domain_name}
});
},
bind_click() {
this.$store.dispatch("dosetdomainstate", false);

@ -67,6 +67,18 @@
{{ editdeveloperinfo.app_used_count }} 个应用
</el-tag>
</el-form-item>
<el-form-item label="维护模式" label-width="110px" style="text-align: left">
<el-switch
v-model="read_only_mode"
:disabled="read_only_mode==='on'"
active-color="#13ce66"
active-value="on"
inactive-color="#ff4949"
inactive-value="off">
</el-switch>
<el-tag style="margin-left: 10px" type="warning"> 该模式下新设备新应用无法进行注册安装但是已经安装的不影响</el-tag>
<el-tag v-if="read_only_mode==='on'" style="margin-left: 50px" type="warning"> 通过账户激活进行关闭维护模式</el-tag>
</el-form-item>
<el-form-item label="证书id" label-width="110px">
<el-input v-model="editdeveloperinfo.certid" :disabled='isedit'/>
</el-form-item>
@ -84,7 +96,7 @@
type="danger"
@click="cleandevices">清理签名数据
</el-button>
<el-button v-if="isedit && editdeveloperinfo.is_actived || editdeveloperinfo.certid" size="small"
<el-button v-if="isedit && editdeveloperinfo.status!==0 || editdeveloperinfo.certid" size="small"
@click="syncdevices">同步设备信息
</el-button>
<el-tooltip content="发布证书只能创建两个,请谨慎操作">
@ -100,7 +112,7 @@
@click="isorenewcert">删除发布证书
</el-button>
</el-tooltip>
<el-button v-if="isedit && editdeveloperinfo.is_actived" size="small" type="success"
<el-button v-if="isedit && editdeveloperinfo.status!==0" size="small" type="success"
@click="activedeveloperFun(editdeveloperinfo,'checkauth')">账户激活检测
</el-button>
<!-- <el-button v-if="isedit && editdeveloperinfo.is_actived" size="small" @click="bindAppletoapp(editdeveloperinfo)">专属应用</el-button>-->
@ -268,10 +280,10 @@
<el-table-column
align="center"
label="是否激活"
prop="is_actived"
prop="status"
width="110">
<template slot-scope="scope">
<el-tooltip v-if="scope.row.is_actived === true" content="点击禁用">
<el-tooltip v-if="scope.row.status!==0" content="点击禁用">
<el-button size="small" type="success" @click="disabledeveloperFun(scope.row,'disable')">已激活</el-button>
</el-tooltip>
<el-button v-else size="small" type="danger"
@ -284,15 +296,24 @@
align="center"
label="账户状态"
prop="certid"
width="100">
sortable
width="110">
<template slot-scope="scope">
<el-popover placement="top" trigger="hover">
<p v-if="!scope.row.certid && scope.row.is_actived === true">
<p v-if="!scope.row.certid && scope.row.status!==0">
开发证书不可用请在编辑中导入或手动创建发布证书</p>
<p v-if="!scope.row.certid && scope.row.is_actived !== true">请先激活开发者账户</p>
<p v-if="scope.row.certid && scope.row.is_actived === true">账户已经启用</p>
<p v-if="!scope.row.certid && scope.row.status=== 0">请先激活开发者账户</p>
<p v-if="scope.row.certid && scope.row.status!==0">{{ format_status(scope.row) }}</p>
<div slot="reference" class="name-wrapper">
<el-button v-if="scope.row.certid " size="small" type="success">可用</el-button>
<div v-if="scope.row.certid">
<el-button v-if="scope.row.status === 1" size="small" type="success">
{{ format_status(scope.row) }}
</el-button>
<el-button v-else size="small" type="warning" @click="activedeveloperFun(scope.row,'checkauth')">
{{ format_status(scope.row) }}
</el-button>
</div>
<el-button v-else size="small" type="danger">不可用</el-button>
</div>
</el-popover>
@ -300,22 +321,17 @@
</template>
</el-table-column>
<el-table-column
:formatter="formatter_usable_number"
align="center"
label="可用设备"
prop="usable_number"
width="60">
sortable
width="70">
<template slot-scope="scope">
<el-popover placement="top" trigger="hover">
<p>可用设备数: {{
scope.row.usable_number - scope.row.developer_used_number > 0
? scope.row.usable_number - scope.row.developer_used_number : 0
}}</p>
<p>可用设备数: {{ formatter_usable_number(scope.row) }}</p>
<div slot="reference" class="name-wrapper">
<el-tag size="medium"> {{
scope.row.usable_number - scope.row.developer_used_number >
0 ? scope.row.usable_number - scope.row.developer_used_number : 0
}}
</el-tag>
<el-tag size="medium"> {{ formatter_usable_number(scope.row) }}</el-tag>
</div>
</el-popover>
</template>
@ -946,7 +962,7 @@ import {
iosdevicesudid,
iosudevices
} from "@/restful";
import {getUserInfoFun, removeAaary} from "@/utils";
import {format_choices, getUserInfoFun, removeAaary} from "@/utils";
import AppleDeveloperBindApp from "@/components/base/AppleDeveloperBindApp";
export default {
@ -1033,7 +1049,9 @@ export default {
],
developer_choice: '',
bind_appletoapp_sure: false,
appletoapp_title: ''
appletoapp_title: '',
status_choices: [],
read_only_mode: 'off'
}
}, watch: {
'dialogaddDeveloperVisible': function () {
@ -1043,6 +1061,12 @@ export default {
}
},
methods: {
formatter_usable_number(row) {
return row.usable_number - row.developer_used_number > 0 ? row.usable_number - row.developer_used_number : 0
},
format_status(row) {
return format_choices(row.status, this.status_choices)
},
downloadipa(info) {
this.loading = true;
iosdevices(data => {
@ -1268,9 +1292,15 @@ export default {
this.dialogaddDeveloperVisible = true;
this.isedit = true;
this.placeholder = "为空表示不修改该信息"
if (this.editdeveloperinfo.status === 3) {
this.read_only_mode = 'on'
} else {
this.read_only_mode = 'off'
}
},
updateorcreate() {
if (this.isedit) {
this.editdeveloperinfo.read_only_mode = this.read_only_mode
this.iosdeveloperFun({"methods": "PUT", "data": this.editdeveloperinfo})
} else {
if (this.editdeveloperinfo.auth_type === 0) {
@ -1385,11 +1415,17 @@ export default {
} else {
this.loading = true
}
if (params.methods === 'PUT') {
params.data.size = this.pagination.pagesize
params.data.page = this.pagination.currentPage
}
iosdeveloper(data => {
if (data.code === 1000) {
if (params.methods !== 'PUT') {
this.app_developer_lists = data.data;
this.pagination.total = data.count;
this.apple_auth_list = data.apple_auth_list;
this.status_choices = data.status_choices;
if (data.use_num) {
this.developer_used_info = data.use_num;
if (this.developer_used_info.all_usable_number !== 0) {
@ -1400,6 +1436,7 @@ export default {
this.percentage = p;
}
}
}
if (this.dialogaddDeveloperVisible) {
this.canceledit();
@ -1407,7 +1444,7 @@ export default {
this.activeName = "iosdeveloper";
this.editdeveloperinfo = {auth_type: 0, usable_number: 100, app_limit_number: 100};
}
if (!this.edit && this.editdeveloperinfo.issuer_id) {
if (params.methods === 'POST') {
this.$message.success("添加成功");
this.activeName = "iosdeveloper";
this.editdeveloperinfo = {auth_type: 0, usable_number: 100, app_limit_number: 100};
@ -1417,6 +1454,12 @@ export default {
} else {
this.$message.error("操作失败")
}
if (params.methods === 'PUT') {
this.get_data_from_tabname(this.activeName, {
"size": this.pagination.pagesize,
"page": this.pagination.currentPage
})
}
if (params.methods !== 'GET') {
this.loadingfun.close();
} else {

@ -54,7 +54,7 @@
action="#"
drag
style="max-height: 200px">
<img v-if="upload_pic_b" :src="upload_pic_b" class="avatar" alt="">
<img v-if="upload_pic_b" :src="upload_pic_b" alt="" class="avatar">
<i v-else class="el-icon-plus avatar-uploader-icon"></i>
</el-upload>
</el-form-item>

@ -6,8 +6,10 @@
:title="domain_title"
:visible.sync="bind_domain_sure"
width="666px">
<bind-domain v-if="bind_domain_sure" :app_id="current_domain_info.app_id" :domain_state="true"
:domain_type="current_domain_info.domain_type" :c_domain_name="current_domain_info.domain_name" transitionName="bind-app-domain"/>
<bind-domain v-if="bind_domain_sure" :app_id="current_domain_info.app_id"
:c_domain_name="current_domain_info.domain_name"
:domain_state="true" :domain_type="current_domain_info.domain_type"
transitionName="bind-app-domain"/>
</el-dialog>
<div>
<el-input
@ -106,7 +108,7 @@
prop="weight"
width="110">
<template slot-scope="scope">
<el-popover placement="top" trigger="hover" v-if="scope.row.domain_type === 1">
<el-popover v-if="scope.row.domain_type === 1" placement="top" trigger="hover">
<p>绑定域名{{ scope.row.domain_name }}</p>
<p>域名类型{{ format_domain_type(scope.row) }}</p>
<p>权重越大下载域名使用频率越高</p>
@ -154,7 +156,7 @@
import {domaininfo} from "@/restful";
import BindDomain from "@/components/base/BindDomain";
import {getUserInfoFun} from '@/utils'
import {format_choices, getUserInfoFun} from '@/utils'
export default {
name: "FirUserDomain",
@ -234,20 +236,12 @@ export default {
this.loading = false;
}, {methods: 'GET', data: params})
},
format_choices(key, obj) {
for (let i = 0; i < obj.length; i++) {
if (key === obj[i].id) {
return obj[i].name
}
}
return "未知"
},
format_domain_type(row) {
if (row.domain_type === 2) {
return "应用" + row.app_info.name + "域名"
}
return this.format_choices(row.domain_type, this.domain_type_choices)
return format_choices(row.domain_type, this.domain_type_choices)
},
format_create_time(row) {

@ -248,7 +248,7 @@
<script>
import {my_order} from "@/restful";
import {getUserInfoFun} from '@/utils'
import {format_choices, getUserInfoFun} from '@/utils'
import VueQr from 'vue-qr';
export default {
@ -364,25 +364,16 @@ export default {
this.MyOrderFun(data)
},
format_choices(key, obj) {
for (let i = 0; i < obj.length; i++) {
if (key === obj[i].id) {
return obj[i].name
}
}
return "未知"
},
format_payment_type(row) {
return this.format_choices(row.payment_type, this.payment_type_choices)
return format_choices(row.payment_type, this.payment_type_choices)
},
format_status_type(row) {
return this.format_choices(row.status, this.status_choices)
return format_choices(row.status, this.status_choices)
},
format_order_type(row) {
return this.format_choices(row.order_type, this.order_type_choices)
return format_choices(row.order_type, this.order_type_choices)
},
format_actual_amount(row) {

@ -688,3 +688,11 @@ export function sort_compare(propertyName) {
}
}
export function format_choices(key, obj) {
for (let i = 0; i < obj.length; i++) {
if (key === obj[i].id) {
return obj[i].name
}
}
return "未知"
}

@ -1,4 +1,4 @@
# Generated by Django 3.2.3 on 2021-12-20 17:11
# Generated by Django 3.2.3 on 2021-12-28 14:54
from django.db import migrations, models
@ -9,6 +9,17 @@ class Migration(migrations.Migration):
]
operations = [
migrations.RemoveField(
model_name='appiosdeveloperinfo',
name='is_actived',
),
migrations.AddField(
model_name='appiosdeveloperinfo',
name='status',
field=models.SmallIntegerField(
choices=[(0, '未激活'), (1, '已激活'), (2, '协议待同意'), (3, '维护中'), (4, '证书过期'), (5, '状态异常')], default=0,
verbose_name='账户状态'),
),
migrations.AddField(
model_name='userdomaininfo',
name='is_https',

@ -270,7 +270,7 @@ class AppIOSDeveloperInfo(models.Model):
private_key_id = models.CharField(max_length=64, null=False, verbose_name="密钥 ID")
# p8key = models.TextField(max_length=512, null=False, verbose_name="p8key")
p8key = AESCharField(max_length=512, null=False, verbose_name="p8key")
is_actived = models.BooleanField(default=False, verbose_name="是否已经激活")
# is_actived = models.BooleanField(default=False, verbose_name="是否已经激活")
certid = models.CharField(max_length=64, blank=True, verbose_name="超级签名自动创建证书ID", null=True)
usable_number = models.IntegerField(verbose_name="可使用设备数", default=100)
app_limit_number = models.IntegerField(verbose_name="可分配应用数,最大160", default=100)
@ -280,6 +280,9 @@ class AppIOSDeveloperInfo(models.Model):
description = models.TextField('备注', blank=True, null=True, default='')
auth_type_choices = ((0, 'p8key认证'),)
auth_type = models.SmallIntegerField(choices=auth_type_choices, default=0, verbose_name="认证类型")
status_choices = (
(0, '未激活'), (1, '已激活'), (2, '协议待同意'), (3, '维护中'), (4, '证书过期'), (5, '状态异常')) # 协议待同意和维护中:代表只读,不可创建和注册新设备号
status = models.SmallIntegerField(choices=status_choices, verbose_name="账户状态", default=0)
class Meta:
verbose_name = '苹果开发者账户'

@ -12,6 +12,7 @@ import re
from OpenSSL.crypto import (load_pkcs12, dump_certificate_request, dump_privatekey, PKey, TYPE_RSA, X509Req,
dump_certificate, load_privatekey, load_certificate, PKCS12, FILETYPE_PEM, FILETYPE_ASN1)
from api.models import AppIOSDeveloperInfo
from api.utils.app.shellcmds import shell_command, use_user_pass
from api.utils.apple.appleapiv3 import AppStoreConnectApi
from common.base.baseutils import get_format_time, format_apple_date, make_app_uuid
@ -195,7 +196,7 @@ def make_pem(cer_content, pem_path):
f.write(dump_certificate(FILETYPE_PEM, cert))
def check_error_call_back(error):
def check_error_call_back(error, developer_pk):
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')
@ -206,16 +207,18 @@ def check_error_call_back(error):
msg = '认证失败,请检查开发者信息填写是否正确'
if 'FORBIDDEN.REQUIRED_AGREEMENTS_MISSING_OR_EXPIRED' in error:
msg = '请登录 https://developer.apple.com/account/ 并同意最新协议'
AppIOSDeveloperInfo.objects.filter(pk=developer_pk).update(status=2)
logger.error(f"{msg} {error}")
return msg if msg else error
class AppDeveloperApiV2(object):
def __init__(self, issuer_id, private_key_id, p8key, cert_id):
def __init__(self, issuer_id, private_key_id, p8key, cert_id, developer_pk):
self.issuer_id = issuer_id
self.private_key_id = private_key_id
self.p8key = p8key
self.cert_id = cert_id
self.developer_pk = developer_pk
def active(self):
result = {'data': []}
@ -230,7 +233,7 @@ class AppDeveloperApiV2(object):
return True, result
except Exception as e:
logger.error(f"ios developer active Failed Exception:{e}")
result['return_info'] = check_error_call_back(str(e))
result['return_info'] = check_error_call_back(str(e), self.developer_pk)
return False, result
def file_format_path_name(self, user_obj):
@ -258,7 +261,7 @@ class AppDeveloperApiV2(object):
return True, certificates
except Exception as e:
logger.error(f"ios developer create cert Failed Exception:{e}")
result['return_info'] = check_error_call_back(str(e))
result['return_info'] = check_error_call_back(str(e), self.developer_pk)
return False, result
def get_cert_obj_by_cid(self):
@ -273,7 +276,7 @@ class AppDeveloperApiV2(object):
return False, result
except Exception as e:
logger.error(f"ios developer get cert {self.cert_id} Failed Exception:{e}")
result['return_info'] = check_error_call_back(str(e))
result['return_info'] = check_error_call_back(str(e), self.developer_pk)
return False, result
def revoke_cert(self):
@ -292,7 +295,7 @@ class AppDeveloperApiV2(object):
return True, result
except Exception as e:
logger.error(f"ios developer cert {self.cert_id} revoke Failed Exception:{e}")
result['return_info'] = check_error_call_back(str(e))
result['return_info'] = check_error_call_back(str(e), self.developer_pk)
return False, result
def auto_set_certid_by_p12(self, app_dev_pem):
@ -312,7 +315,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}")
result['return_info'] = check_error_call_back(str(e))
result['return_info'] = check_error_call_back(str(e), self.developer_pk)
return False, result
def del_profile(self, profile_id, profile_name):
@ -323,7 +326,7 @@ class AppDeveloperApiV2(object):
return True
except Exception as e:
logger.error(f"ios developer delete profile Failed Exception:{e}")
result['return_info'] = check_error_call_back(str(e))
result['return_info'] = check_error_call_back(str(e), self.developer_pk)
return False, result
def set_device_status(self, status, device_id, device_name, device_udid, failed_call_prefix,
@ -340,7 +343,7 @@ class AppDeveloperApiV2(object):
return True, result
except Exception as e:
logger.error("ios developer set devices status Failed Exception:%s" % e)
result['return_info'] = check_error_call_back(str(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:
@ -360,7 +363,7 @@ class AppDeveloperApiV2(object):
return True, devices_obj_list
except Exception as e:
logger.error("ios developer get device Failed Exception:%s" % e)
result['return_info'] = check_error_call_back(str(e))
result['return_info'] = check_error_call_back(str(e), self.developer_pk)
return False, result
def del_app(self, identifier_id, bundle_id, app_id):
@ -372,7 +375,7 @@ class AppDeveloperApiV2(object):
except Exception as e:
logger.error("ios developer delete app Failed Exception:%s" % e)
result['return_info'] = check_error_call_back(str(e))
result['return_info'] = check_error_call_back(str(e), self.developer_pk)
return False, result
def create_app(self, bundle_id, app_id, s_type, app_id_err_callback=None):
@ -393,7 +396,7 @@ class AppDeveloperApiV2(object):
except Exception as e:
logger.error("ios developer create app Failed Exception:%s" % e)
result['return_info'] = check_error_call_back(str(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:
call_fun()
@ -406,7 +409,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)
result['return_info'] = check_error_call_back(str(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:
@ -437,7 +440,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}")
result['return_info'] = check_error_call_back(str(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:
if state:
@ -471,5 +474,5 @@ class AppDeveloperApiV2(object):
return True, result
except Exception as e:
logger.error("ios developer modify_capability Failed Exception:%s" % e)
result['return_info'] = check_error_call_back(str(e))
result['return_info'] = check_error_call_back(str(e), self.developer_pk)
return False, result

@ -187,9 +187,10 @@ def get_auth_form_developer(developer_obj):
return auth
def get_api_obj(auth):
def get_api_obj(developer_obj):
auth = get_auth_form_developer(developer_obj)
if auth.get("issuer_id"):
app_api_obj = AppDeveloperApiV2(**auth)
app_api_obj = AppDeveloperApiV2(**auth, developer_pk=developer_obj.pk)
else:
app_api_obj = None
return app_api_obj
@ -212,17 +213,16 @@ def err_callback(func, *args, **kwargs):
def disable_developer_and_send_email(app_obj, developer_obj):
logger.error(f"app {app_obj} developer {developer_obj} sign failed. so disabled")
developer_obj.is_actived = False
developer_obj.save(update_fields=['is_actived'])
developer_obj.status = 5
developer_obj.save(update_fields=['status'])
send_ios_developer_active_status(developer_obj.user_id,
MSGTEMPLATE.get('ERROR_DEVELOPER') % (
developer_obj.user_id.first_name, app_obj.name,
developer_obj.issuer_id))
def get_new_developer_by_app_obj(user_objs, app_obj, apple_to_app=False):
def get_new_developer_by_app_obj(app_obj, obj_base_filter, apple_to_app=False):
can_used_developer_pk_list = []
obj_base_filter = AppIOSDeveloperInfo.objects.filter(user_id__in=user_objs, is_actived=True, certid__isnull=False)
if apple_to_app:
# 存在指定开发者,则新设备优先注册到指定开发者
developer_obj_lists = obj_base_filter.filter(appledevelopertoappuse__app_id=app_obj)
@ -250,9 +250,7 @@ def get_new_developer_by_app_obj(user_objs, app_obj, apple_to_app=False):
def filter_developer_by_pk_list(developer_pk_list, f_key, app_search_flag=True):
developer_obj_dict = AppIOSDeveloperInfo.objects.filter(pk__in=developer_pk_list,
is_actived=True,
certid__isnull=False).values(
developer_obj_dict = AppIOSDeveloperInfo.objects.filter(pk__in=developer_pk_list).values(
f_key, 'pk').annotate(count=Count('pk'))
if not app_search_flag:
developer_obj_dict = developer_obj_dict.filter(count__lt=F('app_limit_number'))
@ -268,18 +266,24 @@ def get_developer_by_pk_list(developer_pk_list, f_key, app_search_flag=True):
return developer_obj
def get_developer_user_by_app_udid(user_objs, udid, app_obj, private_first=True):
def get_developer_user_by_app_udid(user_objs, udid, app_obj, private_first=True, read_only=True):
"""
:param read_only:
:param user_objs: [user_obj]
:param udid: udid
:param app_obj: app_obj
:param private_first: 专属应用优先使用专属开发者而不是公共开发者
:return: (developer_obj, is_exist_devices)
"""
if read_only:
status_choice = [1, 2, 3, 4, 5]
else:
status_choice = [1]
status_filter = {'developerid__certid__isnull': False, 'developerid__status__in': status_choice}
developer_udid_queryset = UDIDsyncDeveloper.objects.filter(developerid__user_id__in=user_objs,
developerid__is_actived=True,
developerid__certid__isnull=False).values(
'developerid').all().distinct()
**status_filter).values('developerid').all().distinct()
# 根据udid和应用查找该用户开发者账户【主要可能是开发者未激活】
developer_pk_list = developer_udid_queryset.filter(udid=udid, developerid__apptodeveloper__app_id=app_obj)
@ -317,8 +321,7 @@ def get_developer_user_by_app_udid(user_objs, udid, app_obj, private_first=True)
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()
apple_to_app = AppleDeveloperToAppUse.objects.filter(app_id=app_obj, **status_filter).first()
# 存在专属开发者账户,但是也同时存在已经安装的设备,优先选择已经安装设备的开发者账户?是or否
# 是:使应用趋向于一个开发者,为后期更新提供方便
@ -326,12 +329,15 @@ def get_developer_user_by_app_udid(user_objs, udid, app_obj, private_first=True)
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)
status_filter = {'certid__isnull': False, 'status__in': status_choice}
obj_base_filter = AppIOSDeveloperInfo.objects.filter(user_id__in=user_objs, **status_filter)
can_used_developer_pk_list = get_new_developer_by_app_obj(app_obj, obj_base_filter, 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)
can_used_developer_pk_list = get_new_developer_by_app_obj(app_obj, obj_base_filter)
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))
@ -346,14 +352,14 @@ def get_developer_user_by_app_udid(user_objs, udid, app_obj, private_first=True)
return None, None
def get_developer_obj_by_others(user_obj, udid, app_obj):
result, is_exist = get_developer_user_by_app_udid([user_obj], udid, app_obj)
def get_developer_obj_by_others(user_obj, udid, app_obj, read_only):
result, is_exist = get_developer_user_by_app_udid([user_obj], udid, app_obj, read_only=read_only)
if result:
return result
receive_user_id_list = IosDeveloperPublicPoolBill.objects.filter(to_user_id=user_obj).values('user_id').distinct()
if receive_user_id_list:
result, is_exist = get_developer_user_by_app_udid(UserInfo.objects.filter(pk__in=receive_user_id_list), udid,
app_obj)
app_obj, read_only=read_only)
f_count = get_ios_developer_public_num(user_obj)
if (f_count == 0 and is_exist) or f_count > 0:
@ -370,8 +376,8 @@ class IosUtils(object):
self.user_obj = user_obj
self.get_developer_auth()
def get_developer_auth(self):
self.developer_obj = get_developer_obj_by_others(self.user_obj, self.udid, self.app_obj)
def get_developer_auth(self, read_only=True):
self.developer_obj = get_developer_obj_by_others(self.user_obj, self.udid, self.app_obj, read_only)
if self.developer_obj:
self.auth = get_auth_form_developer(self.developer_obj)
else:
@ -399,8 +405,7 @@ class IosUtils(object):
@staticmethod
def modify_capability(developer_obj, app_obj, developer_app_id):
auth = get_auth_form_developer(developer_obj)
return get_api_obj(auth).modify_capability(app_obj, developer_app_id)
return get_api_obj(developer_obj).modify_capability(app_obj, developer_app_id)
def get_profile_full_path(self):
cert_dir_name = make_app_uuid(self.user_obj, get_apple_udid_key(self.auth))
@ -553,16 +558,18 @@ class IosUtils(object):
return True, 'continue'
sync_device_obj = UDIDsyncDeveloper.objects.filter(udid=device_udid,
developerid=developer_obj).first()
auth = get_auth_form_developer(developer_obj)
# auth = get_auth_form_developer(developer_obj)
# 库里面存在,并且设备是可用状态,因此无需api注册
if sync_device_obj:
logger.info(f"app {app_obj} device {sync_device_obj.serial} already in developer {developer_obj}")
if not sync_device_obj.status:
# 库里面存在,并且设备是禁用状态,需要调用api启用
status, result = get_api_obj(auth).set_device_status("enable", sync_device_obj.serial,
sync_device_obj.product, sync_device_obj.udid,
status, result = get_api_obj(developer_obj).set_device_status("enable", sync_device_obj.serial,
sync_device_obj.product,
sync_device_obj.udid,
failed_call_prefix,
err_callback(IosUtils.get_device_from_developer,
err_callback(
IosUtils.get_device_from_developer,
developer_obj))
if not status: # 已经包含异常操作,暂定
return status, result
@ -570,8 +577,10 @@ class IosUtils(object):
sync_device_obj.save(update_fields=['status'])
else:
# 库里面不存在,注册设备,新设备注册默认就是启用状态
status, device_obj = get_api_obj(auth).register_device(device_udid, device_name, failed_call_prefix,
err_callback(IosUtils.get_device_from_developer,
status, device_obj = get_api_obj(developer_obj).register_device(device_udid, device_name,
failed_call_prefix,
err_callback(
IosUtils.get_device_from_developer,
developer_obj))
if not status:
return status, device_obj
@ -620,11 +629,10 @@ class IosUtils(object):
developer_app_id_obj = DeveloperAppID.objects.filter(developerid=developer_obj,
app_id=app_obj).first()
if not developer_app_id_obj:
auth = get_auth_form_developer(developer_obj)
bundle_id = app_obj.bundle_id
app_id = app_obj.app_id
s_type = app_obj.supersign_type
status, result = get_api_obj(auth).create_app(bundle_id, app_id, s_type, failed_callback)
status, result = get_api_obj(developer_obj).create_app(bundle_id, app_id, s_type, failed_callback)
if status and result.get('aid'):
developer_app_id_obj = DeveloperAppID.objects.create(aid=result.get('aid'), developerid=developer_obj,
app_id=app_obj)
@ -659,8 +667,9 @@ class IosUtils(object):
developer_app_id = developer_app_id_obj.aid
profile_id = developer_app_id_obj.profile_id
auth = get_auth_form_developer(developer_obj)
status, result = get_api_obj(auth).make_and_download_profile(app_obj,
get_profile_full_path(developer_obj, app_obj),
status, result = get_api_obj(developer_obj).make_and_download_profile(app_obj,
get_profile_full_path(developer_obj,
app_obj),
auth, developer_app_id,
device_id_lists, profile_id,
failed_call_prefix, failed_callback,
@ -690,6 +699,8 @@ class IosUtils(object):
if result:
return result
self.get_developer_auth(read_only=False)
logger.info("udid %s not exists app_id %s ,need sign" % (self.udid, self.app_obj))
if consume_user_download_times_by_app_obj(self.app_obj):
@ -835,8 +846,7 @@ class IosUtils(object):
@staticmethod
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 = get_api_obj(developer_obj)
app_api_obj.set_device_status("disable", udid_obj.udid.serial, udid_obj.udid.product, udid_obj.udid.udid,
udid_obj.udid.udid)
UDIDsyncDeveloper.objects.filter(udid=udid_obj.udid.udid, developerid=developer_obj).update(status=False)
@ -883,12 +893,11 @@ class IosUtils(object):
@staticmethod
def clean_app_by_developer_obj(app_obj, developer_obj):
auth = get_auth_form_developer(developer_obj)
developer_app_id_obj = DeveloperAppID.objects.filter(developerid=developer_obj, app_id=app_obj).first()
if developer_app_id_obj:
app_api_obj = get_api_obj(auth)
app_api_obj = get_api_obj(developer_obj)
app_api_obj.del_profile(developer_app_id_obj.profile_id, app_obj.app_id)
app_api_obj2 = get_api_obj(auth)
app_api_obj2 = get_api_obj(developer_obj)
app_api_obj2.del_app(developer_app_id_obj.aid, app_obj.bundle_id, app_obj.app_id)
developer_app_id_obj.delete()
@ -930,8 +939,7 @@ class IosUtils(object):
:param developer_obj:
:return:
"""
auth = get_auth_form_developer(developer_obj)
app_api_obj = get_api_obj(auth)
app_api_obj = get_api_obj(developer_obj)
status, result = app_api_obj.active()
if status:
cert_is_exists = True
@ -946,10 +954,8 @@ class IosUtils(object):
IosUtils.clean_developer(developer_obj, developer_obj.user_id)
developer_obj.certid = None
developer_obj.cert_expire_time = None
developer_obj.is_actived = True
else:
developer_obj.is_actived = False
developer_obj.save(update_fields=['certid', 'cert_expire_time', 'is_actived'])
developer_obj.status = 1
developer_obj.save(update_fields=['certid', 'cert_expire_time', 'status'])
return status, result
@staticmethod
@ -961,14 +967,12 @@ class IosUtils(object):
@staticmethod
def create_developer_cert(developer_obj, user_obj):
auth = get_auth_form_developer(developer_obj)
app_api_obj = get_api_obj(auth)
app_api_obj = get_api_obj(developer_obj)
status, result = app_api_obj.create_cert(user_obj)
if status:
if auth.get("issuer_id"):
cert_id = result.id
AppIOSDeveloperInfo.objects.filter(user_id=user_obj, issuer_id=auth.get("issuer_id")).update(
is_actived=True,
status=1,
certid=cert_id, cert_expire_time=format_apple_date(result.expirationDate))
resign_app_obj = IosUtils.get_resign_obj(user_obj, developer_obj)
resign_app_obj.make_p12_from_cert(cert_id)
@ -976,21 +980,19 @@ class IosUtils(object):
@staticmethod
def revoke_developer_cert(developer_obj, user_obj):
auth = get_auth_form_developer(developer_obj)
app_api_obj = get_api_obj(auth)
app_api_obj = get_api_obj(developer_obj)
status, result = app_api_obj.revoke_cert()
if not status:
logger.warning('%s revoke cert failed,but i need clean cert_id %s' % (developer_obj.issuer_id, result))
AppIOSDeveloperInfo.objects.filter(user_id=user_obj, issuer_id=auth.get("issuer_id")).update(
is_actived=True,
AppIOSDeveloperInfo.objects.filter(user_id=user_obj, issuer_id=developer_obj.issuer_id).update(
status=4,
certid=None, cert_expire_time=None)
return status, result
@staticmethod
def check_developer_cert(developer_obj, user_obj):
# 暂时无用
auth = get_auth_form_developer(developer_obj)
app_api_obj = get_api_obj(auth)
app_api_obj = get_api_obj(developer_obj)
status, result = app_api_obj.get_cert_obj_by_cid()
if not status:
AppIOSDeveloperInfo.objects.filter(user_id=user_obj, issuer_id=auth.get("issuer_id")).update(
@ -1000,22 +1002,21 @@ class IosUtils(object):
@staticmethod
def auto_get_cert_id_by_p12(developer_obj, user_obj):
auth = get_auth_form_developer(developer_obj)
app_api_obj = get_api_obj(auth)
app_api_obj = get_api_obj(developer_obj)
file_format_path_name = file_format_path(user_obj, auth)
app_dev_pem = file_format_path_name + ".pem.bak"
status, result = app_api_obj.auto_set_certid_by_p12(app_dev_pem)
if status:
AppIOSDeveloperInfo.objects.filter(user_id=user_obj, issuer_id=auth.get("issuer_id")).update(
is_actived=True,
status=1,
certid=result.id, cert_expire_time=format_apple_date(result.expirationDate))
return status, result
@staticmethod
def get_device_from_developer(developer_obj):
auth = get_auth_form_developer(developer_obj)
app_api_obj = get_api_obj(auth)
app_api_obj = get_api_obj(developer_obj)
status, result = app_api_obj.get_device()
if status and auth.get("issuer_id"):
if status and developer_obj.issuer_id:
udid_developer_obj_list = UDIDsyncDeveloper.objects.filter(developerid=developer_obj).values_list('udid')
udid_developer_list = [x[0] for x in udid_developer_obj_list if len(x) > 0]

@ -703,7 +703,8 @@ def call_function_try_attempts(try_attempts=5, sleep_time=3):
f'exec {func} failed. Failed:{e} {try_attempts} times in total. now {sleep_time} later try '
f'again...{i}')
res = str(e)
if 'Authentication credentials are missing or invalid' in str(e):
if 'Authentication credentials are missing or invalid' in str(
e) or 'FORBIDDEN.REQUIRED_AGREEMENTS_MISSING_OR_EXPIRED' in str(e):
raise Exception(res)
time.sleep(sleep_time)
logger.info(f"exec {func} finished. time:{time.time() - start_time}")

@ -65,9 +65,11 @@ def auto_delete_ios_mobile_tmp_file():
def auto_check_ios_developer_active():
all_ios_developer = AppIOSDeveloperInfo.objects.filter(is_actived=True)
all_ios_developer = AppIOSDeveloperInfo.objects.filter(status=1)
error_issuer_id = {}
for ios_developer in all_ios_developer:
userinfo = ios_developer.user_id
err_issuer_id = error_issuer_id.get(userinfo.uid, [])
if userinfo.supersign_active:
count = 3
while count > 0:
@ -81,8 +83,10 @@ def auto_check_ios_developer_active():
count -= 1
time.sleep(5)
if count == 0:
ios_developer.is_actived = False
ios_developer.save(update_fields=['is_actived'])
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():
userinfo = UserInfo.objects.filter(uid=uid).first()
send_ios_developer_active_status(userinfo, MSGTEMPLATE.get('AUTO_CHECK_DEVELOPER') % (
userinfo.first_name, ios_developer.issuer_id))
userinfo.first_name, ",".join(val)))

@ -526,7 +526,8 @@ class DeveloperSerializer(serializers.ModelSerializer):
def get_is_disabled(self, obj):
app_id = self.context.get('app_id', '')
if app_id:
developer_app_obj = models.DeveloperAppID.objects.filter(developerid=obj, developerid__is_actived=True,
developer_app_obj = models.DeveloperAppID.objects.filter(developerid=obj,
developerid__status__in=[1, 2, 3, 4, 5],
developerid__certid__isnull=False)
if developer_app_obj.filter(app_id__app_id=app_id).distinct().count():
return False

@ -61,13 +61,13 @@ def get_developer_devices(developer_obj_lists):
other_used_sum = 0
flyapp_used_sum = 0
max_total = 0
for dev_obj in developer_obj_lists.filter(is_actived=True):
for dev_obj in developer_obj_lists.filter(status__in=[1, 2, 3, 4, 5]):
other_used, flyapp_used, _ = get_developer_udided(dev_obj)
other_used_sum += other_used
flyapp_used_sum += flyapp_used
max_total += 100
use_number_obj_list = developer_obj_lists.filter(is_actived=True)
use_number_obj_list = developer_obj_lists.filter(status__in=[1, 2, 3, 4, 5])
all_use_number = 0
all_usable_number = 0
for use_number_obj in use_number_obj_list:

@ -64,12 +64,13 @@ class DeveloperView(APIView):
res.data = developer_serializer.data
res.count = developer_obj.count()
res.status_choices = get_choices_dict(AppIOSDeveloperInfo.status_choices)
res.apple_auth_list = get_choices_dict(AppIOSDeveloperInfo.auth_type_choices)
return Response(res.dict)
def put(self, request):
data = request.data
res = BaseResponse()
issuer_id = data.get("issuer_id", "").strip()
if issuer_id:
developer_obj = AppIOSDeveloperInfo.objects.filter(user_id=request.user, issuer_id=issuer_id).first()
@ -78,26 +79,26 @@ class DeveloperView(APIView):
if act == "syncalldevice":
res = BaseResponse()
result_list = []
for developer_s_obj in AppIOSDeveloperInfo.objects.filter(user_id=request.user, is_actived=True).all():
for developer_s_obj in AppIOSDeveloperInfo.objects.filter(user_id=request.user,
status__in=[1, 2, 3, 4, 5]).all():
status, result = IosUtils.get_device_from_developer(developer_s_obj)
if not status:
result_list.append(result.get("err_info"))
if len(result_list):
logger.warning(result_list)
return Response(res.dict)
return self.get(request)
return Response(res.dict)
if developer_obj:
act = data.get("act", "").strip()
if act:
res = BaseResponse()
logger.info(f"user {request.user} ios developer {developer_obj} act {act}")
if act == "checkauth":
status, result = IosUtils.active_developer(developer_obj)
if status:
if not developer_obj.certid:
IosUtils.get_device_from_developer(developer_obj)
return self.get(request)
return Response(res.dict)
else:
res.code = 1008
res.msg = result.get("return_info", "未知错误")
@ -148,9 +149,9 @@ class DeveloperView(APIView):
res.msg = "数据清理中,请耐心等待"
return Response(res.dict)
elif act == 'disable':
developer_obj.is_actived = False
developer_obj.save(update_fields=['is_actived'])
return self.get(request)
developer_obj.status = 0
developer_obj.save(update_fields=['status'])
return Response(res.dict)
else:
update_fields = []
logger.info(f"user {request.user} ios developer {developer_obj} update input data {data}")
@ -175,14 +176,20 @@ class DeveloperView(APIView):
p8key = data.get("p8key", developer_obj.p8key)
if private_key_id != "" and private_key_id != developer_obj.private_key_id:
developer_obj.private_key_id = private_key_id
developer_obj.is_actived = False
developer_obj.status = 0
update_fields.append("private_key_id")
if p8key != "" and p8key != developer_obj.p8key:
developer_obj.p8key = p8key
developer_obj.is_actived = False
developer_obj.status = 0
update_fields.append("p8key")
read_only_mode = data.get("read_only_mode", '')
if developer_obj.status == 1 and read_only_mode == 'on':
developer_obj.status = 3
update_fields.append("status")
try:
update_fields.append("is_actived")
update_fields.append("status")
developer_obj.save(update_fields=update_fields)
logger.info(
f"user {request.user} ios developer {developer_obj} update now data {developer_obj.__dict__}")
@ -190,7 +197,7 @@ class DeveloperView(APIView):
logger.error(
f"user {request.user} ios developer {developer_obj} update error data {data} Exception {e}")
return self.get(request)
return Response(res.dict)
def post(self, request):
data = request.data
@ -538,7 +545,8 @@ class AppleDeveloperBindAppsView(APIView):
for item in add_issuer_ids:
developer_obj = AppIOSDeveloperInfo.objects.filter(issuer_id=item, user_id=request.user,
is_actived=True, certid__isnull=False).first()
status__in=[1, 2, 3, 4, 5],
certid__isnull=False).first()
developer_aid_obj = DeveloperAppID.objects.filter(developerid=developer_obj)
is_exist = developer_aid_obj.filter(app_id=app_obj).count()
if developer_obj:

Loading…
Cancel
Save