优化代码,修改已知问题

publicsignpoll
youngS 3 years ago
parent 4c29d32d67
commit 002c90d5e3
  1. 7
      fir_client/src/components/apps/FirApps.vue
  2. 174
      fir_client/src/components/user/FirSuperSignBase.vue
  3. 6
      fir_client/src/utils/index.js
  4. 19
      fir_ser/api/migrations/0022_iosdeveloperpublicpoolbill_app_id.py
  5. 16
      fir_ser/api/migrations/0023_remove_appudid_binary_file.py
  6. 6
      fir_ser/api/models.py
  7. 4
      fir_ser/api/tasks.py
  8. 9
      fir_ser/api/utils/app/apputils.py
  9. 73
      fir_ser/api/utils/app/supersignutils.py
  10. 52
      fir_ser/api/utils/modelutils.py
  11. 10
      fir_ser/api/utils/serializer.py
  12. 19
      fir_ser/api/utils/storage/caches.py
  13. 12
      fir_ser/api/views/apps.py
  14. 34
      fir_ser/api/views/supersign.py
  15. 17
      fir_ser/api/views/uploads.py

@ -175,6 +175,9 @@
}} UDID }} UDID
</el-link> </el-link>
</el-col> </el-col>
<el-col :span="6" v-if="analyseappinfo.sign && analyseappinfo.type === 'iOS'">
<el-checkbox v-model="enable_sign">开启超级签</el-checkbox>
</el-col>
</el-row> </el-row>
<el-row :gutter="20" style="margin-top: 18px;"> <el-row :gutter="20" style="margin-top: 18px;">
<el-col :span="18"> <el-col :span="18">
@ -597,6 +600,7 @@
pay_choices: [], pay_choices: [],
analyseappinfo: {icon: ''}, analyseappinfo: {icon: ''},
short: '', short: '',
enable_sign: '',
keysearch: '', keysearch: '',
searchfromtype: '', searchfromtype: '',
applists: [], applists: [],
@ -672,6 +676,7 @@
analyseApps(data => { analyseApps(data => {
if (data.code === 1000) { if (data.code === 1000) {
this.short = data.data.short; this.short = data.data.short;
this.enable_sign = data.data.enable_sign;
for (let name of Object.keys(data.data)) { for (let name of Object.keys(data.data)) {
analyseappinfo[name] = data.data[name] analyseappinfo[name] = data.data[name]
} }
@ -773,6 +778,7 @@
this.$message.success(file.raw.name + '上传成功'); this.$message.success(file.raw.name + '上传成功');
if (!multiFlag) { if (!multiFlag) {
analyseappinfo.short = this.short; analyseappinfo.short = this.short;
analyseappinfo.enable_sign = this.enable_sign;
} }
const loading = this.$loading({ const loading = this.$loading({
lock: true, lock: true,
@ -817,6 +823,7 @@
const pnumber = 20; const pnumber = 20;
this.uploadprocess[process_key].process = process; this.uploadprocess[process_key].process = process;
this.uploadprocess[process_key].short = analyseappinfo.short; this.uploadprocess[process_key].short = analyseappinfo.short;
this.uploadprocess[process_key].enable_sign = analyseappinfo.enable_sign;
this.uploadprocess[process_key].appname = analyseappinfo.appname; this.uploadprocess[process_key].appname = analyseappinfo.appname;
if (process > 0) { if (process > 0) {
let percent = this.uploadprocess[process_key].percent; let percent = this.uploadprocess[process_key].percent;

@ -94,6 +94,81 @@
</el-form> </el-form>
</el-dialog> </el-dialog>
<el-dialog title="设备消耗详细信息" :destroy-on-close="true" :visible.sync="dialogShowDeviceBillInfo"
:close-on-click-modal="false" center width="750px">
<el-table
:data="app_bill_info_lists"
v-loading="loading"
border
stripe
style="width: 100%">
<el-table-column
prop="app_name"
align="center"
label="应用名称"
>
</el-table-column>
<el-table-column
prop="remote_addr"
align="center"
label="客户端IP">
</el-table-column>
<el-table-column
prop="action"
label="账单类型"
align="center"
width="100">
</el-table-column>
<el-table-column
:formatter="deviceformatter"
align="center"
prop="created_time"
label="日期"
width="160">
</el-table-column>
<el-table-column
label="应用状态"
align="center"
width="110">
<template slot-scope="scope">
<el-tag v-if="scope.row.app_status===false" type="info">应用删除</el-tag>
<el-tag v-else>
应用存在
</el-tag>
</template>
</el-table-column>
<el-table-column
label="设备状态"
align="center"
width="110">
<template slot-scope="scope">
<el-tag v-if="scope.row.is_used===false" type="info">已经释放</el-tag>
<el-tag v-else>
使用中
</el-tag>
</template>
</el-table-column>
</el-table>
<div style="margin-top: 20px">
<el-pagination
@size-change="billhandleSizeChange"
@current-change="billhandleCurrentChange"
:current-page.sync="billpagination.currentPage"
:page-sizes="[10, 20, 50, 100]"
:page-size="billpagination.pagesize"
layout="total,sizes, prev, pager, next"
:total="billpagination.total">
</el-pagination>
</div>
<span slot="footer">
<el-button @click="closeDeviceBillInfo">关闭</el-button>
</span>
</el-dialog>
<el-tabs v-model="activeName" type="border-card" @tab-click="handleClick" tab-position="top"> <el-tabs v-model="activeName" type="border-card" @tab-click="handleClick" tab-position="top">
<el-tab-pane label="开发者账户" name="iosdeveloper"> <el-tab-pane label="开发者账户" name="iosdeveloper">
<el-input <el-input
@ -298,7 +373,7 @@
<h1>注意事项</h1> <h1>注意事项</h1>
<p>1.添加后请勿撤销 API 密钥否则会导致用户安装的软件闪退或无法安装</p> <p>1.添加后请勿撤销 API 密钥否则会导致用户安装的软件闪退或无法安装</p>
<p>2.每个开发者账号最多可创建两本证书请确保至少还可以创建一本证书</p> <p>2.每个开发者账号最多可创建两本证书请确保至少还可以创建一本证书</p>
<p>3.添加后系统自动创建证书设备和描述文件请勿删除这些文件否则会导致用户安装的软件闪退或无法安装</p> <p>3.添加后激活开发者账户然后您就可以上传p12证书或者通过系统自动创建证书设备和描述文件请勿删除这些文件否则会导致用户安装的软件闪退或无法安装</p>
</el-card> </el-card>
</el-tab-pane> </el-tab-pane>
@ -499,47 +574,34 @@
align="center" align="center"
label="设备ID" label="设备ID"
> >
<template slot-scope="scope">
<el-tooltip effect="dark" content="点击查看设备安装详细信息" placement="top">
<el-link :underline="false" @click="showDeviceBill(scope.row.udid)">
{{ scope.row.udid }}
</el-link>
</el-tooltip>
</template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
prop="version" prop="product"
label="设备名称" label="设备名称"
width="200"
align="center"> align="center">
<template slot-scope="scope">
{{scope.row.product}} {{scope.row.version}}
</template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
width="100" prop="version"
prop="app_name"
align="center" align="center"
label="消费者" label="设备版本"
> >
</el-table-column> </el-table-column>
<el-table-column <el-table-column
prop="remote_addr" prop="counts"
align="center"
label="客户端IP"
width="100">
</el-table-column>
<el-table-column
prop="action"
label="账单类型"
align="center"
width="100">
</el-table-column>
<el-table-column
prop="description"
label="备注"
align="center" align="center"
width="200"> label="设备安装次数"
</el-table-column> width="110">
<el-table-column
:formatter="deviceformatter"
align="center"
prop="created_time"
label="生成日期"
width="160">
</el-table-column> </el-table-column>
<el-table-column <el-table-column
@ -547,7 +609,7 @@
align="center" align="center"
width="110"> width="110">
<template slot-scope="scope"> <template slot-scope="scope">
<el-tag v-if="scope.row.is_used===false" type="info">已经释放</el-tag> <el-tag v-if="!scope.row.udid_sync_info_id" type="info">已经释放</el-tag>
<el-tag v-else> <el-tag v-else>
使用中 使用中
</el-tag> </el-tag>
@ -582,10 +644,13 @@
name: "FirSuperSignBase", name: "FirSuperSignBase",
data() { data() {
return { return {
dialogShowDeviceBillInfo: false,
currentudid: '',
fileList: [], fileList: [],
app_developer_lists: [], app_developer_lists: [],
app_devices_lists: [], app_devices_lists: [],
app_bill_lists: [], app_bill_lists: [],
app_bill_info_lists: [],
app_udid_lists: [], app_udid_lists: [],
activeName: "iosdeveloper", activeName: "iosdeveloper",
udidsearch: "", udidsearch: "",
@ -598,6 +663,7 @@
isedit: false, isedit: false,
placeholder: "", placeholder: "",
pagination: {"currentPage": 1, "total": 0, "pagesize": 10}, pagination: {"currentPage": 1, "total": 0, "pagesize": 10},
billpagination: {"currentPage": 1, "total": 0, "pagesize": 10},
developer_used_info: {"all_usable_number": 0, "other_used_sum": 0, "all_use_number": 0}, developer_used_info: {"all_usable_number": 0, "other_used_sum": 0, "all_use_number": 0},
percentage: 0, percentage: 0,
apple_auth_list: [], apple_auth_list: [],
@ -614,6 +680,38 @@
} }
}, },
methods: { methods: {
closeDeviceBillInfo() {
this.dialogShowDeviceBillInfo = false;
this.currentudid = '';
this.app_bill_info_lists = [];
},
showDeviceBill(udid) {
this.currentudid = udid;
this.iosdevicebillFun({"methods": "GET", "data": {'udid': udid, 'act': 'info'}});
this.dialogShowDeviceBillInfo = true;
},
billhandleSizeChange(val) {
this.billpagination.pagesize = val;
this.iosdevicebillFun({
"methods": "GET", "data": {
"size": this.billpagination.pagesize,
"page": 1,
"act": "info",
'udid': this.currentudid
}
})
},
billhandleCurrentChange(val) {
this.billpagination.currentPage = val;
this.iosdevicebillFun({
"methods": "GET", "data": {
"size": this.billpagination.pagesize,
"page": this.billpagination.currentPage,
"act": "info",
'udid': this.currentudid
}
})
},
beforeAvatarUpload(file) { beforeAvatarUpload(file) {
const isLt2M = file.size / 1024 / 1024 < 2; const isLt2M = file.size / 1024 / 1024 < 2;
if (file.type === 'application/x-pkcs12') { if (file.type === 'application/x-pkcs12') {
@ -889,18 +987,22 @@
} }
}, params) }, params)
}, },
iosdevicebillFun(data) { iosdevicebillFun(params) {
this.loading = true; this.loading = true;
DeviceBillInfo(data => { DeviceBillInfo(data => {
if (data.code === 1000) { if (data.code === 1000) {
this.app_bill_lists = data.data; if (params.data.act && params.data.act === 'info') {
this.pagination.total = data.count; this.app_bill_info_lists = data.data;
this.billpagination.total = data.count;
} else {
this.app_bill_lists = data.data;
this.pagination.total = data.count;
}
} else { } else {
this.$message.error("操作失败了 " + data.msg); this.$message.error("操作失败了 " + data.msg);
} }
this.loading = false this.loading = false
}, data) }, params)
}, },
iosdevicesudidFun(action, data, scope) { iosdevicesudidFun(action, data, scope) {
if (action !== 'GET') { if (action !== 'GET') {

@ -140,7 +140,7 @@ function get_file_type(upload_key) {
function get_filename(app_info, upload_key) { function get_filename(app_info, upload_key) {
if (app_info) { if (app_info) {
let app_type = app_info.type; let app_type = app_info.type;
if (app_type === 'iOS' || app_info === 'Android') { if (app_type === 'iOS' || app_type === 'Android') {
return app_info.appname + '-' + app_info.version + '-' + app_info.short + '.' + get_file_type(upload_key) return app_info.appname + '-' + app_info.version + '-' + app_info.short + '.' + get_file_type(upload_key)
} }
} }
@ -196,6 +196,10 @@ export function uploadaliyunoss(file, certinfo, app, successcallback, processcal
'Content-Disposition': 'attachment; filename="' + encodeURIComponent(filename) + '"', 'Content-Disposition': 'attachment; filename="' + encodeURIComponent(filename) + '"',
'Cache-Control': '' 'Cache-Control': ''
} }
} else {
options['headers'] = {
'Cache-Control': ''
}
} }
if (currentCheckpoint) { if (currentCheckpoint) {

@ -0,0 +1,19 @@
# Generated by Django 3.2.3 on 2021-11-06 13:04
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('api', '0021_appreportinfo'),
]
operations = [
migrations.AddField(
model_name='iosdeveloperpublicpoolbill',
name='app_id',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='api.apps',
verbose_name='属于哪个APP'),
),
]

@ -0,0 +1,16 @@
# Generated by Django 3.2.3 on 2021-11-06 16:14
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('api', '0022_iosdeveloperpublicpoolbill_app_id'),
]
operations = [
migrations.RemoveField(
model_name='appudid',
name='binary_file',
),
]

@ -236,7 +236,6 @@ class AppStorage(models.Model):
class AppUDID(models.Model): class AppUDID(models.Model):
app_id = models.ForeignKey(to="Apps", on_delete=models.CASCADE, verbose_name="属于哪个APP") app_id = models.ForeignKey(to="Apps", on_delete=models.CASCADE, verbose_name="属于哪个APP")
# udid = models.CharField(max_length=64, verbose_name="udid唯一标识", db_index=True)
udid = models.ForeignKey(to="UDIDsyncDeveloper", verbose_name="udid唯一标识", on_delete=models.CASCADE) udid = models.ForeignKey(to="UDIDsyncDeveloper", verbose_name="udid唯一标识", on_delete=models.CASCADE)
product = models.CharField(max_length=64, verbose_name="产品", blank=True, null=True, ) product = models.CharField(max_length=64, verbose_name="产品", blank=True, null=True, )
serial = models.CharField(max_length=64, verbose_name="序列号", blank=True, null=True, ) serial = models.CharField(max_length=64, verbose_name="序列号", blank=True, null=True, )
@ -247,7 +246,6 @@ class AppUDID(models.Model):
updated_time = models.DateTimeField(auto_now=True, verbose_name="更新时间") updated_time = models.DateTimeField(auto_now=True, verbose_name="更新时间")
is_signed = models.BooleanField(verbose_name="是否完成签名打包", default=False) is_signed = models.BooleanField(verbose_name="是否完成签名打包", default=False)
is_download = models.BooleanField(verbose_name="描述文件是否已经下载", default=False) is_download = models.BooleanField(verbose_name="描述文件是否已经下载", default=False)
binary_file = models.CharField(max_length=128, blank=True, verbose_name="签名包名称", null=True)
class Meta: class Meta:
verbose_name = '设备详情' verbose_name = '设备详情'
@ -541,9 +539,7 @@ class IosDeveloperPublicPoolBill(models.Model):
developer_info = models.JSONField(max_length=256, verbose_name="开发者信息", null=True, blank=True) developer_info = models.JSONField(max_length=256, verbose_name="开发者信息", null=True, blank=True)
udid_sync_info = models.ForeignKey(to="UDIDsyncDeveloper", on_delete=models.SET_NULL, verbose_name="关联同步设备信息", udid_sync_info = models.ForeignKey(to="UDIDsyncDeveloper", on_delete=models.SET_NULL, verbose_name="关联同步设备信息",
null=True, blank=True) null=True, blank=True)
# app_id = models.ForeignKey(to="Apps", on_delete=models.CASCADE, verbose_name="属于哪个APP",null=True,blank=True) app_id = models.ForeignKey(to="Apps", on_delete=models.SET_NULL, verbose_name="属于哪个APP", null=True, blank=True)
# udid = models.ForeignKey(to="AppUDID", on_delete=models.CASCADE, verbose_name="所消耗的udid",null=True,blank=True)
# developerid = models.ForeignKey(to="AppIOSDeveloperInfo", on_delete=models.CASCADE, verbose_name="所使用苹果开发者账户",null=True,blank=True)
description = models.CharField(verbose_name="操作描述", max_length=128, default='', blank=True) description = models.CharField(verbose_name="操作描述", max_length=128, default='', blank=True)
remote_addr = models.GenericIPAddressField(verbose_name="远程IP地址") remote_addr = models.GenericIPAddressField(verbose_name="远程IP地址")
created_time = models.DateTimeField(auto_now_add=True, verbose_name="添加时间") created_time = models.DateTimeField(auto_now_add=True, verbose_name="添加时间")

@ -49,10 +49,10 @@ def run_sign_task(format_udid_info, short, client_ip):
@shared_task @shared_task
def run_resign_task(app_id, need_download_profile=True): def run_resign_task(app_id, need_download_profile=True, force=True):
app_obj = Apps.objects.filter(app_id=app_id).first() app_obj = Apps.objects.filter(app_id=app_id).first()
with cache.lock("%s_%s" % ('task_resign', app_id), timeout=60 * 60): with cache.lock("%s_%s" % ('task_resign', app_id), timeout=60 * 60):
return resign_by_app_id(app_obj, need_download_profile) return resign_by_app_id(app_obj, need_download_profile, force)
@app.task @app.task

@ -114,7 +114,7 @@ def get_random_short(number=4):
return short_url return short_url
def save_app_infos(app_file_name, user_obj, app_info, bundle_id, app_img, short, size): def save_app_infos(app_file_name, user_obj, app_info, bundle_id, app_img, short, size, issupersign):
app_uuid = make_app_uuid(user_obj, bundle_id + app_file_name.split(".")[1]) app_uuid = make_app_uuid(user_obj, bundle_id + app_file_name.split(".")[1])
##判断是否存在该app ##判断是否存在该app
app_obj = Apps.objects.filter(app_id=app_uuid, user_id=user_obj).first() app_obj = Apps.objects.filter(app_id=app_uuid, user_id=user_obj).first()
@ -129,6 +129,7 @@ def save_app_infos(app_file_name, user_obj, app_info, bundle_id, app_img, short,
"name": app_info["labelname"], "name": app_info["labelname"],
"new_bundle_name": app_info["labelname"], "new_bundle_name": app_info["labelname"],
"short": short, "short": short,
"issupersign": issupersign,
"bundle_id": bundle_id, "bundle_id": bundle_id,
"count_hits": 0, "count_hits": 0,
"wxeasytype": False if get_user_domain_name(user_obj) else True "wxeasytype": False if get_user_domain_name(user_obj) else True
@ -145,14 +146,16 @@ def save_app_infos(app_file_name, user_obj, app_info, bundle_id, app_img, short,
is_new_app = False is_new_app = False
app_obj.short = short app_obj.short = short
app_obj.name = app_info["labelname"] app_obj.name = app_info["labelname"]
app_obj.issupersign = issupersign
# appmobj.wxeasytype = False if user_obj.domain_name or appmobj.domain_name else True # appmobj.wxeasytype = False if user_obj.domain_name or appmobj.domain_name else True
app_obj.bundle_id = bundle_id app_obj.bundle_id = bundle_id
app_obj.save(update_fields=["short", "name", "bundle_id"]) app_obj.save(update_fields=["short", "name", "bundle_id", "issupersign"])
except Exception as e: except Exception as e:
logger.error(f"save app info failed,app_obj:{app_obj} Exception:{e}") logger.error(f"save app info failed,app_obj:{app_obj} Exception:{e}")
app_obj.bundle_id = bundle_id app_obj.bundle_id = bundle_id
app_obj.issupersign = issupersign
app_obj.name = app_info["labelname"] app_obj.name = app_info["labelname"]
app_obj.save(update_fields=["name", "bundle_id"]) app_obj.save(update_fields=["name", "bundle_id", "issupersign"])
del_cache_response_by_short(app_obj.app_id) del_cache_response_by_short(app_obj.app_id)
AppReleaseInfo.objects.filter(app_id=app_obj).update(is_master=False) AppReleaseInfo.objects.filter(app_id=app_obj).update(is_master=False)

@ -12,13 +12,13 @@ import zipfile
import xmltodict import xmltodict
from django.core.cache import cache from django.core.cache import cache
from django.db.models import Sum
from api.models import APPSuperSignUsedInfo, AppUDID, AppIOSDeveloperInfo, AppReleaseInfo, Apps, APPToDeveloper, \ from api.models import APPSuperSignUsedInfo, AppUDID, AppIOSDeveloperInfo, AppReleaseInfo, Apps, APPToDeveloper, \
UDIDsyncDeveloper, DeveloperAppID, DeveloperDevicesID, IosDeveloperPublicPoolBill UDIDsyncDeveloper, DeveloperAppID, DeveloperDevicesID, IosDeveloperPublicPoolBill
from api.utils.app.iossignapi import ResignApp, AppDeveloperApiV2 from api.utils.app.iossignapi import ResignApp, AppDeveloperApiV2
from api.utils.baseutils import file_format_path, delete_app_profile_file, get_profile_full_path, format_apple_date, \ from api.utils.baseutils import file_format_path, delete_app_profile_file, get_profile_full_path, format_apple_date, \
get_format_time, make_app_uuid, make_from_user_uuid get_format_time, make_app_uuid, make_from_user_uuid
from api.utils.modelutils import get_ios_developer_public_num, check_ipa_is_latest_sign
from api.utils.response import BaseResponse from api.utils.response import BaseResponse
from api.utils.serializer import BillAppInfoSerializer, BillDeveloperInfoSerializer from api.utils.serializer import BillAppInfoSerializer, BillDeveloperInfoSerializer
from api.utils.storage.caches import del_cache_response_by_short, send_msg_over_limit, check_app_permission, \ from api.utils.storage.caches import del_cache_response_by_short, send_msg_over_limit, check_app_permission, \
@ -42,12 +42,14 @@ def check_org_file(user_obj, org_file):
return download_files_form_oss(storage_obj, org_file) return download_files_form_oss(storage_obj, org_file)
def resign_by_app_id(app_obj, need_download_profile=True): def resign_by_app_id(app_obj, need_download_profile=True, force=True):
user_obj = app_obj.user_id user_obj = app_obj.user_id
info_list = [] info_list = []
if app_obj.issupersign and user_obj.supersign_active: if app_obj.issupersign and user_obj.supersign_active:
for developer_app_id_obj in DeveloperAppID.objects.filter(app_id=app_obj).all(): for developer_app_id_obj in DeveloperAppID.objects.filter(app_id=app_obj).all():
developer_obj = developer_app_id_obj.developerid developer_obj = developer_app_id_obj.developerid
if check_ipa_is_latest_sign(app_obj, developer_obj) and not force:
continue
developer_app_id = developer_app_id_obj.aid developer_app_id = developer_app_id_obj.aid
d_time = time.time() d_time = time.time()
if need_download_profile: if need_download_profile:
@ -57,8 +59,7 @@ def resign_by_app_id(app_obj, need_download_profile=True):
else: else:
download_flag = True download_flag = True
with cache.lock("%s_%s_%s" % ('run_sign', app_obj.app_id, developer_obj.issuer_id), timeout=60 * 10): with cache.lock("%s_%s_%s" % ('run_sign', app_obj.app_id, developer_obj.issuer_id), timeout=60 * 10):
status, result = IosUtils.run_sign(user_obj, app_obj, developer_obj, download_flag, None, d_time, {}, status, result = IosUtils.run_sign(user_obj, app_obj, developer_obj, download_flag, '', d_time, {})
True)
info_list.append({'developer_id': developer_obj.issuer_id, 'result': (status, result)}) info_list.append({'developer_id': developer_obj.issuer_id, 'result': (status, result)})
return info_list return info_list
@ -199,21 +200,6 @@ def err_callback(func, *args, **kwargs):
return wrapper return wrapper
def get_ios_developer_public_num(user_obj):
add_number = IosDeveloperPublicPoolBill.objects.filter(to_user_id=user_obj, action__in=[1, 2]).aggregate(
number=Sum('number'))
used_number = IosDeveloperPublicPoolBill.objects.filter(user_id=user_obj, action=0,
udid_sync_info__isnull=False).aggregate(
number=Sum('number'))
add_number = add_number.get("number", 0)
if not add_number:
add_number = -99
used_number = used_number.get("number", 0)
if not used_number:
used_number = 0
return add_number - used_number
def get_developer_user_by_app_udid(user_obj, udid): def get_developer_user_by_app_udid(user_obj, udid):
use_device_obj = APPSuperSignUsedInfo.objects.filter(udid__udid__udid=udid, use_device_obj = APPSuperSignUsedInfo.objects.filter(udid__udid__udid=udid,
user_id=user_obj, developerid__is_actived=True, user_id=user_obj, developerid__is_actived=True,
@ -458,7 +444,8 @@ class IosUtils(object):
self.developer_obj).data, self.developer_obj).data,
action=0, number=1, udid_sync_info=udid_sync_info, action=0, number=1, udid_sync_info=udid_sync_info,
remote_addr=client_ip, product=udid_sync_info.product, remote_addr=client_ip, product=udid_sync_info.product,
udid=self.udid, version=udid_sync_info.version udid=self.udid, version=udid_sync_info.version,
app_id=self.app_obj
) )
@staticmethod @staticmethod
@ -466,18 +453,14 @@ class IosUtils(object):
# 更新新签名的ipa包 # 更新新签名的ipa包
if IosUtils.update_sign_file_name(user_obj, app_obj, developer_obj, release_obj, if IosUtils.update_sign_file_name(user_obj, app_obj, developer_obj, release_obj,
random_file_name): random_file_name):
newdata = { if udid:
"is_signed": True, udid_obj = UDIDsyncDeveloper.objects.filter(developerid=developer_obj, udid=udid).first()
"binary_file": random_file_name AppUDID.objects.filter(app_id=app_obj, udid=udid_obj).update(**{"is_signed": True})
}
# 更新已经完成签名状态,设备消耗记录,和开发者已消耗数量
udid_obj = UDIDsyncDeveloper.objects.filter(developerid=developer_obj, udid=udid).first()
AppUDID.objects.filter(app_id=app_obj, udid=udid_obj).update(**newdata)
del_cache_response_by_short(app_obj.app_id, udid=udid) del_cache_response_by_short(app_obj.app_id, udid=udid)
return True return True
@staticmethod @staticmethod
def run_sign(user_obj, app_obj, developer_obj, download_flag, udid, d_time, result, resign=False): def run_sign(user_obj, app_obj, developer_obj, download_flag, udid, d_time, result):
d_result = {'code': 0, 'msg': 'success'} d_result = {'code': 0, 'msg': 'success'}
start_time = time.time() start_time = time.time()
if download_flag: if download_flag:
@ -489,18 +472,11 @@ class IosUtils(object):
if status: if status:
s_time1 = time.time() s_time1 = time.time()
logger.info(f"app_id {app_obj} exec sign ipa success. time:{s_time1 - start_time}") logger.info(f"app_id {app_obj} exec sign ipa success. time:{s_time1 - start_time}")
if resign: if not IosUtils.update_sign_data(user_obj, app_obj, developer_obj, random_file_name, release_obj,
if not IosUtils.update_sign_file_name(user_obj, app_obj, developer_obj, release_obj, udid):
random_file_name): d_result['code'] = 1004
d_result['code'] = 1004 d_result['msg'] = '数据更新失败,请稍后重试'
d_result['msg'] = '数据更新失败,请稍后重试' return status, d_result
return status, d_result
else:
if not IosUtils.update_sign_data(user_obj, app_obj, developer_obj, random_file_name, release_obj,
udid):
d_result['code'] = 1004
d_result['msg'] = '数据更新失败,请稍后重试'
return status, d_result
else: else:
d_result['code'] = 1004 d_result['code'] = 1004
d_result['msg'] = '签名失败,请检查包是否正常' d_result['msg'] = '签名失败,请检查包是否正常'
@ -553,13 +529,16 @@ class IosUtils(object):
udid__developerid=self.developer_obj).first() udid__developerid=self.developer_obj).first()
if app_udid_obj and app_udid_obj.is_download: if app_udid_obj and app_udid_obj.is_download:
if app_udid_obj.is_signed: if app_udid_obj.is_signed:
release_obj = AppReleaseInfo.objects.filter(app_id=self.app_obj, is_master=True).first() # release_obj = AppReleaseInfo.objects.filter(app_id=self.app_obj, is_master=True).first()
for apptodev_obj in APPToDeveloper.objects.filter(app_id=self.app_obj).all():
if release_obj.release_id == apptodev_obj.release_file: if check_ipa_is_latest_sign(self.app_obj, self.developer_obj):
msg = "udid %s exists app_id %s" % (self.udid, self.app_obj) #
d_result['msg'] = msg # for apptodev_obj in APPToDeveloper.objects.filter(app_id=self.app_obj).all():
logger.info(d_result) # if release_obj.release_id == apptodev_obj.release_file:
return True, d_result msg = "udid %s exists app_id %s" % (self.udid, self.app_obj)
d_result['msg'] = msg
logger.info(d_result)
return True, d_result
else: else:
with cache.lock("%s_%s_%s" % ('run_sign', self.app_obj.app_id, self.developer_obj.issuer_id), with cache.lock("%s_%s_%s" % ('run_sign', self.app_obj.app_id, self.developer_obj.issuer_id),
timeout=60 * 10): timeout=60 * 10):

@ -9,9 +9,10 @@ import logging
import random import random
from urllib.parse import urljoin from urllib.parse import urljoin
from django.db.models import Count from django.db.models import Count, Sum
from api.models import AppReleaseInfo, UserDomainInfo, DomainCnameInfo, UserAdDisplayInfo, RemoteClientInfo from api.models import AppReleaseInfo, UserDomainInfo, DomainCnameInfo, UserAdDisplayInfo, RemoteClientInfo, \
AppIOSDeveloperInfo, IosDeveloperPublicPoolBill, APPToDeveloper
from api.utils.baseutils import get_server_domain_from_request, get_user_default_domain_name, get_real_ip_address, \ from api.utils.baseutils import get_server_domain_from_request, get_user_default_domain_name, get_real_ip_address, \
get_origin_domain_name get_origin_domain_name
@ -116,10 +117,51 @@ def check_app_domain_name_access(app_obj, access_domain_name, user_obj, extra_do
if extra_domain: if extra_domain:
domain_list.append(extra_domain) domain_list.append(extra_domain)
app_domain_name = get_app_domain_name(app_obj) app_domain_name = get_app_domain_name(app_obj)
if app_domain_name: domain_list.append(app_domain_name) if app_domain_name:
domain_list.append(app_domain_name)
user_domain_name = get_user_domain_name(user_obj) user_domain_name = get_user_domain_name(user_obj)
if user_domain_name: domain_list.append(user_domain_name) if user_domain_name:
domain_list.append(user_domain_name)
user_qr_domain_name = get_user_domain_name(user_obj, 0) user_qr_domain_name = get_user_domain_name(user_obj, 0)
if user_qr_domain_name: domain_list.append(user_qr_domain_name) if user_qr_domain_name:
domain_list.append(user_qr_domain_name)
if access_domain_name in domain_list: if access_domain_name in domain_list:
return True return True
def get_ios_developer_public_num(user_obj):
add_number = IosDeveloperPublicPoolBill.objects.filter(to_user_id=user_obj, action__in=[1, 2]).aggregate(
number=Sum('number'))
used_number = IosDeveloperPublicPoolBill.objects.filter(user_id=user_obj, action=0,
udid_sync_info__isnull=False).aggregate(
number=Sum('number'))
add_number = add_number.get("number", 0)
if not add_number:
add_number = -99
used_number = used_number.get("number", 0)
if not used_number:
used_number = 0
return add_number - used_number
def check_super_sign_permission(user_obj):
developer_count = AppIOSDeveloperInfo.objects.filter(user_id=user_obj).count()
if not user_obj.supersign_active:
return False
if developer_count == 0 and get_ios_developer_public_num(user_obj) < 0:
return False
return True
def check_ipa_is_latest_sign(app_obj, developer_obj=None):
release_obj = AppReleaseInfo.objects.filter(app_id=app_obj, is_master=True).first()
all_app_to_dev = APPToDeveloper.objects.filter(app_id=app_obj)
if developer_obj:
all_app_to_dev = all_app_to_dev.filter(developerid=developer_obj)
all_app_to_dev = all_app_to_dev.all()
t_count = 0
for apptodev_obj in all_app_to_dev:
if release_obj.release_id == apptodev_obj.release_file:
t_count += 1
if t_count == all_app_to_dev.count():
return True

@ -553,7 +553,7 @@ class DeviceUDIDSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = models.AppUDID model = models.AppUDID
# depth = 1 # depth = 1
exclude = ["binary_file", "updated_time", "is_signed"] exclude = ["updated_time", "is_signed"]
bundle_id = serializers.SerializerMethodField() bundle_id = serializers.SerializerMethodField()
bundle_name = serializers.SerializerMethodField() bundle_name = serializers.SerializerMethodField()
@ -742,12 +742,18 @@ class BillDeveloperInfoSerializer(serializers.ModelSerializer):
class BillInfoSerializer(serializers.ModelSerializer): class BillInfoSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = models.IosDeveloperPublicPoolBill model = models.IosDeveloperPublicPoolBill
exclude = ["user_id", "to_user_id", "developer_info", "app_info", "udid_sync_info"] exclude = ["user_id", "to_user_id", "developer_info", "app_info", "udid_sync_info", "app_id"]
app_name = serializers.SerializerMethodField() app_name = serializers.SerializerMethodField()
action = serializers.SerializerMethodField() action = serializers.SerializerMethodField()
description = serializers.SerializerMethodField() description = serializers.SerializerMethodField()
is_used = serializers.SerializerMethodField() is_used = serializers.SerializerMethodField()
app_status = serializers.SerializerMethodField()
def get_app_status(self, obj):
if obj.app_id:
return True
return False
def get_is_used(self, obj): def get_is_used(self, obj):
if obj.udid_sync_info or obj.to_user_id: if obj.udid_sync_info or obj.to_user_id:

@ -502,25 +502,24 @@ def get_wx_ticket_login_info_cache(ticket):
class CacheBaseState(object): class CacheBaseState(object):
prefix = ''
def __init__(self, prefix):
CacheBaseState.prefix = prefix
@classmethod @classmethod
def get_state(cls, key): def get_state(cls, key):
return cache.get(f"{cls.prefix}_{key}") return cache.get(f"{cls.__name__}_{key}")
@classmethod @classmethod
def set_state(cls, key, value=time.time(), timeout=3600 * 24): def set_state(cls, key, value=time.time(), timeout=3600 * 24):
cls.del_state(f"{cls.prefix}_{key}") cls.del_state(f"{cls.__name__}_{key}")
cache.set(f"{cls.prefix}_{key}", value, timeout) cache.set(f"{cls.__name__}_{key}", value, timeout)
@classmethod @classmethod
def del_state(cls, key): def del_state(cls, key):
cache.delete(f"{cls.prefix}_{key}") cache.delete(f"{cls.__name__}_{key}")
class MigrateStorageState(CacheBaseState): class MigrateStorageState(CacheBaseState):
def __init__(self): ...
super().__init__('migrate_storage')
class CleanSignDataState(CacheBaseState):
...

@ -12,11 +12,11 @@ from rest_framework.response import Response
from rest_framework.views import APIView from rest_framework.views import APIView
from api.base_views import app_delete from api.base_views import app_delete
from api.models import Apps, AppReleaseInfo, APPToDeveloper, AppIOSDeveloperInfo, UserInfo, AppScreenShot from api.models import Apps, AppReleaseInfo, APPToDeveloper, UserInfo, AppScreenShot
from api.tasks import run_resign_task from api.tasks import run_resign_task
from api.utils.app.supersignutils import IosUtils, get_ios_developer_public_num from api.utils.app.supersignutils import IosUtils
from api.utils.auth import ExpiringTokenAuthentication from api.utils.auth import ExpiringTokenAuthentication
from api.utils.modelutils import get_user_domain_name, get_app_domain_name from api.utils.modelutils import get_user_domain_name, get_app_domain_name, check_super_sign_permission
from api.utils.response import BaseResponse from api.utils.response import BaseResponse
from api.utils.serializer import AppsSerializer, AppReleaseSerializer, AppsListSerializer from api.utils.serializer import AppsSerializer, AppReleaseSerializer, AppsListSerializer
from api.utils.storage.caches import del_cache_response_by_short, get_app_today_download_times, del_cache_by_delete_app from api.utils.storage.caches import del_cache_response_by_short, get_app_today_download_times, del_cache_by_delete_app
@ -223,12 +223,12 @@ class AppInfoView(APIView):
# res.code = 1008 # res.code = 1008
# res.msg = "超级签余额不足,无法开启" # res.msg = "超级签余额不足,无法开启"
# return Response(res.dict) # return Response(res.dict)
developer_count = AppIOSDeveloperInfo.objects.filter(user_id=request.user).count() if not check_super_sign_permission(request.user):
if developer_count == 0 and get_ios_developer_public_num(request.user) < 0:
logger.error(f"app_id:{app_id} can't open super_sign,owner has no ios developer") logger.error(f"app_id:{app_id} can't open super_sign,owner has no ios developer")
res.code = 1008 res.code = 1008
res.msg = "超级签余额不足,无法开启" res.msg = "超级签余额不足,无法开启"
return Response(res.dict) return Response(res.dict)
do_sign_flag = 3
app_obj.issupersign = data.get("issupersign", app_obj.issupersign) app_obj.issupersign = data.get("issupersign", app_obj.issupersign)
update_fields.append("issupersign") update_fields.append("issupersign")
logger.info(f"app_id:{app_id} update new data:{app_obj.__dict__}") logger.info(f"app_id:{app_id} update new data:{app_obj.__dict__}")
@ -239,6 +239,8 @@ class AppInfoView(APIView):
c_task = run_resign_task.apply_async((app_obj.app_id, True)) c_task = run_resign_task.apply_async((app_obj.app_id, True))
if do_sign_flag == 2: if do_sign_flag == 2:
c_task = run_resign_task.apply_async((app_obj.app_id, False)) c_task = run_resign_task.apply_async((app_obj.app_id, False))
if do_sign_flag == 3:
c_task = run_resign_task.apply_async((app_obj.app_id, False, False))
if c_task: if c_task:
msg = c_task.get(propagate=False) msg = c_task.get(propagate=False)
logger.info(f"app {app_obj} run_resign_task msg:{msg}") logger.info(f"app {app_obj} run_resign_task msg:{msg}")

@ -5,7 +5,7 @@
# date: 2020/3/4 # date: 2020/3/4
import logging import logging
from django.db.models import Q from django.db.models import Count
from django.http.response import FileResponse from django.http.response import FileResponse
from rest_framework.pagination import PageNumberPagination from rest_framework.pagination import PageNumberPagination
from rest_framework.response import Response from rest_framework.response import Response
@ -16,6 +16,7 @@ from api.utils.app.supersignutils import IosUtils
from api.utils.auth import ExpiringTokenAuthentication, SuperSignPermission from api.utils.auth import ExpiringTokenAuthentication, SuperSignPermission
from api.utils.response import BaseResponse from api.utils.response import BaseResponse
from api.utils.serializer import DeveloperSerializer, SuperSignUsedSerializer, DeviceUDIDSerializer, BillInfoSerializer from api.utils.serializer import DeveloperSerializer, SuperSignUsedSerializer, DeviceUDIDSerializer, BillInfoSerializer
from api.utils.storage.caches import CleanSignDataState
from api.utils.utils import get_developer_devices, get_choices_dict from api.utils.utils import get_developer_devices, get_choices_dict
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -113,7 +114,13 @@ class DeveloperView(APIView):
return Response(res.dict) return Response(res.dict)
elif act == "cleandevice": elif act == "cleandevice":
if CleanSignDataState.get_state(request.user.uid):
res.code = 1008
res.msg = "数据清理中,请耐心等待"
return Response(res.dict)
CleanSignDataState.set_state(request.user.uid, timeout=60 * 10)
status, result = IosUtils.clean_developer(developer_obj, request.user, False) status, result = IosUtils.clean_developer(developer_obj, request.user, False)
CleanSignDataState.del_state(request.user.uid)
if not status: if not status:
res.code = 1008 res.code = 1008
res.msg = result.get("err_info") res.msg = result.get("err_info")
@ -317,14 +324,29 @@ class DeviceUsedBillView(APIView):
def get(self, request): def get(self, request):
res = BaseResponse() res = BaseResponse()
udid = request.query_params.get("udid", None) udid = request.query_params.get("udid", None)
act = request.query_params.get("act", None)
user_used_list = IosDeveloperPublicPoolBill.objects.filter(user_id=request.user)
page_obj = PageNumber() page_obj = PageNumber()
user_used_list = IosDeveloperPublicPoolBill.objects.filter(Q(to_user_id=request.user) | Q(user_id=request.user))
if udid: if udid:
user_used_list = user_used_list.filter(udid=udid) user_used_list = user_used_list.filter(udid=udid)
app_page_serializer = page_obj.paginate_queryset(queryset=user_used_list.order_by("-created_time"), else:
user_used_list = user_used_list.filter(udid__isnull=False)
if act and act == 'info':
app_page_serializer = page_obj.paginate_queryset(queryset=user_used_list.order_by("-created_time"),
request=request,
view=self)
app_serializer = BillInfoSerializer(app_page_serializer, many=True, context={'user_obj': request.user})
res.data = app_serializer.data
res.count = user_used_list.count()
else:
user_used_list3 = user_used_list.values('udid', 'product', 'version', 'udid_sync_info_id').annotate(
counts=Count('udid')).order_by("-created_time")
res.count = user_used_list3.count()
user_used_list3 = page_obj.paginate_queryset(queryset=user_used_list3.order_by("-created_time"),
request=request, request=request,
view=self) view=self)
app_serializer = BillInfoSerializer(app_page_serializer, many=True, context={'user_obj': request.user}) for user_used in user_used_list3:
res.data = app_serializer.data user_used['counts'] = user_used_list.filter(udid=user_used.get('udid')).count()
res.count = user_used_list.count() res.data = user_used_list3
return Response(res.dict) return Response(res.dict)

@ -16,7 +16,7 @@ from api.utils.TokenManager import verify_token
from api.utils.app.apputils import get_random_short, save_app_infos from api.utils.app.apputils import get_random_short, save_app_infos
from api.utils.auth import ExpiringTokenAuthentication from api.utils.auth import ExpiringTokenAuthentication
from api.utils.baseutils import make_app_uuid, make_from_user_uuid from api.utils.baseutils import make_app_uuid, make_from_user_uuid
from api.utils.modelutils import get_app_domain_name, get_redirect_server_domain from api.utils.modelutils import get_app_domain_name, get_redirect_server_domain, check_super_sign_permission
from api.utils.response import BaseResponse from api.utils.response import BaseResponse
from api.utils.storage.caches import upload_file_tmp_name, del_cache_response_by_short from api.utils.storage.caches import upload_file_tmp_name, del_cache_response_by_short
from api.utils.storage.storage import Storage from api.utils.storage.storage import Storage
@ -48,8 +48,10 @@ class AppAnalyseView(APIView):
png_id = make_from_user_uuid(request.user) png_id = make_from_user_uuid(request.user)
app_obj = Apps.objects.filter(app_id=app_uuid).first() app_obj = Apps.objects.filter(app_id=app_uuid).first()
binary_url = '' binary_url = ''
enable_sign = False
if app_obj: if app_obj:
is_new = False is_new = False
enable_sign = app_obj.issupersign
short = app_obj.short short = app_obj.short
app_release_obj = AppReleaseInfo.objects.filter(app_id=app_obj, is_master=True).first() app_release_obj = AppReleaseInfo.objects.filter(app_id=app_obj, is_master=True).first()
short_domain_name = get_redirect_server_domain(request, request.user, get_app_domain_name(app_obj)) short_domain_name = get_redirect_server_domain(request, request.user, get_app_domain_name(app_obj))
@ -77,7 +79,11 @@ class AppAnalyseView(APIView):
"png_token": png_token, "png_token": png_token,
"png_key": png_key, "png_key": png_key,
"storage": storage_type, "storage": storage_type,
"is_new": is_new, "binary_url": binary_url} "is_new": is_new,
"binary_url": binary_url,
"sign": check_super_sign_permission(request.user),
"enable_sign": enable_sign
}
if storage_type not in [1, 2]: if storage_type not in [1, 2]:
res.data['domain_name'] = settings.SERVER_DOMAIN.get("FILE_UPLOAD_DOMAIN", None) res.data['domain_name'] = settings.SERVER_DOMAIN.get("FILE_UPLOAD_DOMAIN", None)
else: else:
@ -113,15 +119,16 @@ class AppAnalyseView(APIView):
png_new_filename = data.get("png_key").strip(settings.FILE_UPLOAD_TMP_KEY) png_new_filename = data.get("png_key").strip(settings.FILE_UPLOAD_TMP_KEY)
logger.info(f"user {request.user} create or update app {data.get('bundleid')} data:{data}") logger.info(f"user {request.user} create or update app {data.get('bundleid')} data:{data}")
if save_app_infos(app_new_filename, request.user, app_info, if save_app_infos(app_new_filename, request.user, app_info,
data.get("bundleid"), png_new_filename, data.get("short"), data.get('filesize')): data.get("bundleid"), png_new_filename, data.get("short"), data.get('filesize'),
data.get('enable_sign')):
# 需要将tmp 文件修改为正式文件 # 需要将tmp 文件修改为正式文件
storage.rename_file(app_tmp_filename, app_new_filename) storage.rename_file(app_tmp_filename, app_new_filename)
storage.rename_file(png_tmp_filename, png_new_filename) storage.rename_file(png_tmp_filename, png_new_filename)
app_obj = Apps.objects.filter(bundle_id=data.get("bundleid")).first() app_obj = Apps.objects.filter(bundle_id=data.get("bundleid"), user_id=request.user).first()
if app_obj: if app_obj:
if app_obj.issupersign and app_obj.user_id.supersign_active: if app_obj.issupersign and app_obj.user_id.supersign_active:
c_task = run_resign_task.apply_async((app_obj.app_id, False)) c_task = run_resign_task.apply_async((app_obj.app_id, False, False))
msg = c_task.get(propagate=False) msg = c_task.get(propagate=False)
logger.info(f"app {app_obj} run_resign_task msg:{msg}") logger.info(f"app {app_obj} run_resign_task msg:{msg}")
if c_task.successful(): if c_task.successful():

Loading…
Cancel
Save