修改超级签名使用任务队列进行签名

dependabot/npm_and_yarn/fir_admin/dns-packet-1.3.4
youngS 4 years ago
parent 8b0fab87b5
commit 0df8cf68be
  1. 212
      fir_client/src/components/FirDownload.vue
  2. 190
      fir_client/src/components/ShortDownload.vue
  3. 11
      fir_client/src/restful/download.js
  4. 15
      fir_client/src/restful/index.js
  5. 11
      fir_ser/api/base_views.py
  6. 43
      fir_ser/api/tasks.py
  7. 3
      fir_ser/api/urls.py
  8. 59
      fir_ser/api/utils/app/supersignutils.py
  9. 5
      fir_ser/api/utils/pay/__init__.py
  10. 34
      fir_ser/api/utils/storage/caches.py
  11. 2
      fir_ser/api/utils/utils.py
  12. 48
      fir_ser/api/views/apps.py
  13. 22
      fir_ser/api/views/download.py
  14. 76
      fir_ser/api/views/receiveudids.py
  15. 8
      fir_ser/api/views/uploads.py
  16. 3
      fir_ser/fir_ser/__init__.py
  17. 43
      fir_ser/fir_ser/celery.py
  18. 41
      fir_ser/fir_ser/settings.py

@ -70,8 +70,8 @@
</el-button> </el-button>
<button type="button" v-else-if="wrong">{{ msg }}</button> <button type="button" v-else-if="wrong">{{ msg }}</button>
<div v-else> <div v-else style="margin-top: 20%;margin-bottom: 20%">
<div v-if="isdownload" style="margin-top: 20%;margin-bottom: 20%"> <div v-if="isdownload">
<div v-if="gomobile"> <div v-if="gomobile">
<button disabled="" class="loading" <button disabled="" class="loading"
style="min-width: 42px; width: 42px; padding: 21px 0; border-top-color: transparent; border-left-color: transparent;"> style="min-width: 42px; width: 42px; padding: 21px 0; border-top-color: transparent; border-left-color: transparent;">
@ -94,7 +94,7 @@
</div> </div>
</div> </div>
<div v-else style="margin-top: 20%;margin-bottom: 20%"> <div v-else>
<div v-if="currentappinfo.need_password" style="margin:0 auto; width:166px"> <div v-if="currentappinfo.need_password" style="margin:0 auto; width:166px">
<el-input prefix-icon="el-icon-lock" clearable <el-input prefix-icon="el-icon-lock" clearable
placeholder="请输入密码" v-model="password" placeholder="请输入密码" v-model="password"
@ -250,7 +250,7 @@
<script> <script>
import QRCode from 'qrcodejs2' import QRCode from 'qrcodejs2'
import {getdownloadurl, getShortAppinfo} from '@/restful' import {getdownloadurl, getShortAppinfo, gettask} from '@/restful'
export default { export default {
name: "FirDownload", name: "FirDownload",
@ -301,6 +301,46 @@
clearTimeout(this.timer); clearTimeout(this.timer);
}, },
methods: { methods: {
show_err_msg(msg) {
this.msg = msg;
this.$message({
message: msg,
type: 'error',
duration: 0
});
},
loop_check_task() {
let c_count = 1;
// eslint-disable-next-line no-unused-vars
const loop_t = window.setInterval(res => {
gettask(data => {
c_count += 1;
if (c_count > 120) {
window.clearInterval(loop_t);
}
if (data.code === 1000) {
window.clearInterval(loop_t);
if (data.msg) {
this.show_err_msg(data.msg);
} else {
this.$message.success('签名完成,请点击下载安装');
this.wrong = false;
}
} else {
if (data.code === 1002) {
window.clearInterval(loop_t);
data.msg = '应用不存在'
}
if (data.msg) {
this.msg = data.msg + ' ○ ' + c_count;
}
}
}, {
"short": this.$route.params.short,
data: {"task_id": this.$route.query.task_id}
})
}, 3000)
},
jiaocheng(act) { jiaocheng(act) {
let signhelp = this.$refs.signhelp; let signhelp = this.$refs.signhelp;
let bg = this.$refs.signhelp; let bg = this.$refs.signhelp;
@ -316,104 +356,99 @@
gomobileaction() { gomobileaction() {
window.location.href = this.mobileprovision; window.location.href = this.mobileprovision;
}, },
check_msg(callback) { check_msg() {
if (this.$route.query.msg && this.$route.query.udid) { if (this.$route.query.udid) {
this.wrong = true; if (this.$route.query.task_id) {
this.msg = this.$route.query.msg; this.wrong = true;
this.$message({ this.msg = '签名处理中,请耐心等待';
message: this.msg, this.loop_check_task()
type: 'error', } else if (this.$route.query.msg) {
duration: 0 this.wrong = true;
}); this.show_err_msg(this.$route.query.msg);
} else ( }
callback() }
)
}, },
download() { download() {
if (this.currentappinfo.app_id) { if (this.currentappinfo.app_id) {
// eslint-disable-next-line no-unused-vars this.isdownload = true;
this.check_msg(_ => { getdownloadurl(res => {
this.isdownload = true; if (res.code === 1000) {
getdownloadurl(res => { if (res.data.download_url === "") {
if (res.code === 1000) { window.location.href = this.full_url.split("?")[0];
if (res.data.download_url === "") { return
window.location.href = this.full_url.split("?")[0]; }
return if (this.currentappinfo.type === 1) {
} if (this.currentappinfo.issupersign) {
if (this.currentappinfo.type === 1) { if (this.$route.query.udid && this.udid === this.$route.query.udid) {
if (this.currentappinfo.issupersign) { if (this.agent !== '') {
if (this.$route.query.udid && this.udid === this.$route.query.udid) { let download_url = res.data.download_url;
if (this.agent !== '') { this.downloadurl = "itms-services://?action=download-manifest&url=" + encodeURIComponent(download_url);
let download_url = res.data.download_url;
this.downloadurl = "itms-services://?action=download-manifest&url=" + encodeURIComponent(download_url);
// eslint-disable-next-line no-unused-vars
this.timmer = setTimeout(data => {
this.gomobile = false;
}, 5000);
}
} else {
if (this.agent !== '') {
this.downloadurl = res.data.download_url;
window.location.href = this.downloadurl;
if (res.data.extra_url !== "") {
// eslint-disable-next-line no-unused-vars
this.timmer = setTimeout(data => {
window.location.href = res.data.extra_url;
}, 3000);
}
return;
}
}
} else {
let download_url = res.data.download_url;
this.downloadurl = "itms-services://?action=download-manifest&url=" + encodeURIComponent(download_url);
if (res.data.extra_url !== "") {
this.mobileprovision = res.data.extra_url;
// eslint-disable-next-line no-unused-vars // eslint-disable-next-line no-unused-vars
this.timmer = setTimeout(data => { this.timmer = setTimeout(data => {
this.gomobile = false; this.gomobile = false;
}, 5000); }, 5000);
} }
} else {
if (this.agent !== '') {
this.downloadurl = res.data.download_url;
window.location.href = this.downloadurl;
if (res.data.extra_url !== "") {
// eslint-disable-next-line no-unused-vars
this.timmer = setTimeout(data => {
window.location.href = res.data.extra_url;
}, 3000);
}
return;
}
} }
} else { } else {
if (this.agent !== '') { let download_url = res.data.download_url;
this.downloadurl = res.data.download_url; this.downloadurl = "itms-services://?action=download-manifest&url=" + encodeURIComponent(download_url);
if (res.data.extra_url !== "") {
this.mobileprovision = res.data.extra_url;
// eslint-disable-next-line no-unused-vars
this.timmer = setTimeout(data => {
this.gomobile = false;
}, 5000);
} }
} }
window.location.href = this.downloadurl;
} else if (res.code === 1009) {
this.isdownload = false;
document.title = res.msg;
this.wrong = true;
this.msg = res.msg;
this.$message({
message: res.msg,
type: 'error',
});
} else { } else {
this.isdownload = false; if (this.agent !== '') {
this.$message({ this.downloadurl = res.data.download_url;
message: "密码错误,或者下载链接失效",
type: 'error',
});
if (!this.password) {
window.location.reload();
} }
this.password = '';
} }
}, {
'data': { window.location.href = this.downloadurl;
'token': this.mcurrentappinfo.download_token, } else if (res.code === 1009) {
'short': this.currentappinfo.short, this.isdownload = false;
'release_id': this.mcurrentappinfo.release_id, document.title = res.msg;
'password': this.password, this.wrong = true;
'udid': this.udid, this.msg = res.msg;
}, this.$message({
'app_id': this.currentappinfo.app_id message: res.msg,
}) type: 'error',
});
} else {
this.isdownload = false;
this.$message({
message: "密码错误,或者下载链接失效",
type: 'error',
});
if (!this.password) {
window.location.reload();
}
this.password = '';
}
}, {
'data': {
'token': this.mcurrentappinfo.download_token,
'short': this.currentappinfo.short,
'release_id': this.mcurrentappinfo.release_id,
'password': this.password,
'udid': this.udid,
},
'app_id': this.currentappinfo.app_id
}) })
} }
}, },
@ -626,6 +661,9 @@
this.getDownloadTokenFun(); this.getDownloadTokenFun();
this.full_url = location.href; this.full_url = location.href;
this.qrcode(); this.qrcode();
if (this.agent !== '') {
this.check_msg();
}
}, filters: { }, filters: {
formatName: function (name) { formatName: function (name) {
if (name) { if (name) {

@ -91,8 +91,8 @@
</button> </button>
<button type="button" v-else-if="wrong">{{ msg }}</button> <button type="button" v-else-if="wrong">{{ msg }}</button>
<div v-else> <div v-else style="margin-top: 20%;margin-bottom: 20%">
<div v-if="isdownload" style="margin-top: 20%;margin-bottom: 20%"> <div v-if="isdownload">
<div v-if="gomobile"> <div v-if="gomobile">
<button disabled="" class="loading" <button disabled="" class="loading"
style="min-width: 42px; width: 42px; padding: 21px 0; border-top-color: transparent; border-left-color: transparent;"> style="min-width: 42px; width: 42px; padding: 21px 0; border-top-color: transparent; border-left-color: transparent;">
@ -115,11 +115,11 @@
</div> </div>
</div> </div>
<div v-else style="margin-top: 20%;margin-bottom: 20%"> <div v-else>
<div v-if="currentappinfo.need_password" style="margin:0 auto; width:166px"> <div v-if="currentappinfo.need_password" style="margin:0 auto; width:166px">
<input class="passwd" placeholder="请输入密码" v-model="password"/> <input class="passwd" placeholder="请输入密码" v-model="password"/>
</div> </div>
<br/> <br v-if="currentappinfo.need_password"/>
<button @click="download"> <button @click="download">
<a :underline="false"> 下载安装 </a> <a :underline="false"> 下载安装 </a>
</button> </button>
@ -247,7 +247,7 @@
<script> <script>
import QRCode from 'qrcodejs2' import QRCode from 'qrcodejs2'
import {getdownloadurl, getShortAppinfo} from '@/restful/download' import {getdownloadurl, getShortAppinfo, gettask} from '@/restful/download'
export default { export default {
name: "ShortDownload", name: "ShortDownload",
@ -300,6 +300,41 @@
clearTimeout(this.timer); clearTimeout(this.timer);
}, },
methods: { methods: {
show_err_msg(msg) {
this.msg = msg;
alert(this.msg)
},
loop_check_task() {
let c_count = 1;
// eslint-disable-next-line no-unused-vars
const loop_t = window.setInterval(res => {
gettask(data => {
c_count += 1;
if (c_count > 120) {
window.clearInterval(loop_t);
}
if (data.code === 1000) {
window.clearInterval(loop_t);
if (data.msg) {
this.show_err_msg(data.msg);
} else {
this.wrong = false;
}
} else {
if (data.code === 1002) {
window.clearInterval(loop_t);
data.msg = '应用不存在'
}
if (data.msg) {
this.msg = data.msg + ' ○ ' + c_count;
}
}
}, {
"short": this.$route.params.short,
data: {"task_id": this.$route.query.task_id}
})
}, 3000)
},
jiaocheng(act) { jiaocheng(act) {
let signhelp = this.$refs.signhelp; let signhelp = this.$refs.signhelp;
let bg = this.$refs.signhelp; let bg = this.$refs.signhelp;
@ -315,92 +350,92 @@
gomobileaction() { gomobileaction() {
window.location.href = this.mobileprovision; window.location.href = this.mobileprovision;
}, },
check_msg(callback) { check_msg() {
if (this.$route.query.msg && this.$route.query.udid) { if (this.$route.query.udid) {
this.wrong = true; if (this.$route.query.task_id) {
this.msg = this.$route.query.msg; this.wrong = true;
alert(this.msg) this.msg = '签名处理中,请耐心等待';
} else ( this.loop_check_task()
callback() } else if (this.$route.query.msg) {
) this.wrong = true;
this.show_err_msg(this.$route.query.msg);
}
}
}, },
download() { download() {
if (this.currentappinfo.app_id) { if (this.currentappinfo.app_id) {
// eslint-disable-next-line no-unused-vars this.isdownload = true;
this.check_msg(_ => { getdownloadurl(res => {
this.isdownload = true; if (res.code === 1000) {
getdownloadurl(res => { if (res.data.download_url === "") {
if (res.code === 1000) { window.location.href = this.full_url.split("?")[0];
if (res.data.download_url === "") { return
window.location.href = this.full_url.split("?")[0]; }
return if (this.currentappinfo.type === 1) {
} if (this.currentappinfo.issupersign) {
if (this.currentappinfo.type === 1) { if (this.$route.query.udid && this.udid === this.$route.query.udid) {
if (this.currentappinfo.issupersign) { if (this.agent !== '') {
if (this.$route.query.udid && this.udid === this.$route.query.udid) { let download_url = res.data.download_url;
if (this.agent !== '') { this.downloadurl = "itms-services://?action=download-manifest&url=" + encodeURIComponent(download_url);
let download_url = res.data.download_url;
this.downloadurl = "itms-services://?action=download-manifest&url=" + encodeURIComponent(download_url);
// eslint-disable-next-line no-unused-vars
this.timmer = setTimeout(data => {
this.gomobile = false;
}, 5000);
}
} else {
if (this.agent !== '') {
this.downloadurl = res.data.download_url;
window.location.href = this.downloadurl;
if (res.data.extra_url !== "") {
// eslint-disable-next-line no-unused-vars
this.timmer = setTimeout(data => {
window.location.href = res.data.extra_url;
}, 3000);
}
return;
}
}
} else {
let download_url = res.data.download_url;
this.downloadurl = "itms-services://?action=download-manifest&url=" + encodeURIComponent(download_url);
if (res.data.extra_url !== "") {
this.mobileprovision = res.data.extra_url;
// eslint-disable-next-line no-unused-vars // eslint-disable-next-line no-unused-vars
this.timmer = setTimeout(data => { this.timmer = setTimeout(data => {
this.gomobile = false; this.gomobile = false;
}, 5000); }, 5000);
} }
} else {
if (this.agent !== '') {
this.downloadurl = res.data.download_url;
window.location.href = this.downloadurl;
if (res.data.extra_url !== "") {
// eslint-disable-next-line no-unused-vars
this.timmer = setTimeout(data => {
window.location.href = res.data.extra_url;
}, 3000);
}
return;
}
} }
} else { } else {
if (this.agent !== '') { let download_url = res.data.download_url;
this.downloadurl = res.data.download_url; this.downloadurl = "itms-services://?action=download-manifest&url=" + encodeURIComponent(download_url);
if (res.data.extra_url !== "") {
this.mobileprovision = res.data.extra_url;
// eslint-disable-next-line no-unused-vars
this.timmer = setTimeout(data => {
this.gomobile = false;
}, 5000);
} }
} }
window.location.href = this.downloadurl;
} else if (res.code === 1009) {
this.isdownload = false;
document.title = res.msg;
this.wrong = true;
this.msg = res.msg;
} else { } else {
this.isdownload = false; if (this.agent !== '') {
alert("密码错误,或者下载链接失效"); this.downloadurl = res.data.download_url;
if (!this.password) {
window.location.reload();
} }
this.password = '';
} }
}, {
'data': { window.location.href = this.downloadurl;
'token': this.mcurrentappinfo.download_token, } else if (res.code === 1009) {
'short': this.currentappinfo.short, this.isdownload = false;
'release_id': this.mcurrentappinfo.release_id, document.title = res.msg;
'password': this.password, this.wrong = true;
'udid': this.udid, this.msg = res.msg;
}, } else {
'app_id': this.currentappinfo.app_id this.isdownload = false;
}) alert("密码错误,或者下载链接失效");
if (!this.password) {
window.location.reload();
}
this.password = '';
}
}, {
'data': {
'token': this.mcurrentappinfo.download_token,
'short': this.currentappinfo.short,
'release_id': this.mcurrentappinfo.release_id,
'password': this.password,
'udid': this.udid,
},
'app_id': this.currentappinfo.app_id
}) })
} }
}, },
@ -612,6 +647,9 @@
this.getDownloadTokenFun(); this.getDownloadTokenFun();
this.full_url = location.href; this.full_url = location.href;
this.qrcode(); this.qrcode();
if (this.agent !== '') {
this.check_msg();
}
}, filters: { }, filters: {
formatName: function (name) { formatName: function (name) {
if (name) { if (name) {

@ -86,3 +86,14 @@ export function getdownloadurl(callBack, params) {
}, },
); );
} }
/**获取签名任务状态 */
export function gettask(callBack, params) {
getData(
USERSEVER + '/task/' + params.short,
params.data,
data => {
callBack(data);
},
);
}

@ -555,3 +555,18 @@ export function domainFun(callBack, params, load = true) {
true true
); );
} }
/**获取签名任务状态 */
export function gettask(callBack, params, load = true) {
getData(
'GET',
USERSEVER + '/task/' + params.short,
params.data,
data => {
callBack(data);
},
load,
true,
true
);
}

@ -4,23 +4,16 @@
# author: NinEveN # author: NinEveN
# date: 2021/4/13 # date: 2021/4/13
from rest_framework.views import APIView
from api.utils.response import BaseResponse from api.utils.response import BaseResponse
from api.utils.auth import ExpiringTokenAuthentication
from rest_framework.response import Response from api.utils.app.supersignutils import IosUtils
from django.db.models import Sum
from api.utils.app.supersignutils import IosUtils, resign_by_app_obj
from api.utils.storage.storage import Storage from api.utils.storage.storage import Storage
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, \
del_cache_storage del_cache_storage
from api.models import Apps, AppReleaseInfo, APPToDeveloper, AppIOSDeveloperInfo, UserInfo, AppScreenShot, AppStorage from api.models import Apps, AppReleaseInfo, APPToDeveloper, AppIOSDeveloperInfo, UserInfo, AppScreenShot, AppStorage
from api.utils.serializer import AppsSerializer, AppReleaseSerializer
from rest_framework.pagination import PageNumberPagination
import logging import logging
from fir_ser.settings import SERVER_DOMAIN
from api.utils.utils import delete_local_files, delete_app_screenshots_files, change_storage_and_change_head_img, \ from api.utils.utils import delete_local_files, delete_app_screenshots_files, change_storage_and_change_head_img, \
migrating_storage_data, clean_storage_data, check_storage_is_new_storage migrating_storage_data, clean_storage_data, check_storage_is_new_storage
from api.utils.baseutils import is_valid_domain
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)

@ -0,0 +1,43 @@
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# project: 5月
# author: NinEveN
# date: 2021/5/27
from celery import shared_task
from django.core.cache import cache
from api.models import Apps
from api.utils.app.supersignutils import IosUtils, resign_by_app_id
@shared_task
def run_sign_task(format_udid_info, short):
app_info = Apps.objects.filter(short=short).first()
with cache.lock("%s_%s_%s" % ('task_sign', app_info.app_id, format_udid_info.get('udid')), timeout=60 * 10):
ios_obj = IosUtils(format_udid_info, app_info.user_id, app_info)
status, msg = ios_obj.sign()
if not status:
code = msg.get("code", -1)
if code == 0:
msg = ""
elif code == 1005:
msg = "签名余额不足"
elif code == 1002:
msg = "维护中"
elif code == 1003:
msg = "应用余额不足"
elif code in [1004, 1001, 1009]:
msg = msg.get('msg', '未知错误')
else:
msg = '系统内部错误'
else:
msg = ""
return msg
@shared_task
def run_resign_task(app_id, need_download_profile=True):
app_obj = Apps.objects.filter(app_id=app_id).first()
with cache.lock("%s_%s" % ('task_resign', app_id), timeout=60 * 60):
return resign_by_app_id(app_obj, need_download_profile)

@ -22,7 +22,7 @@ from api.views.apps import AppsView, AppInfoView, AppReleaseinfoView
from api.views.download import ShortDownloadView from api.views.download import ShortDownloadView
from api.views.uploads import AppAnalyseView, UploadView from api.views.uploads import AppAnalyseView, UploadView
from api.views.storage import StorageView from api.views.storage import StorageView
from api.views.receiveudids import IosUDIDView from api.views.receiveudids import IosUDIDView, TaskView
from api.views.order import PriceView, OrderView, PaySuccess from api.views.order import PriceView, OrderView, PaySuccess
from api.views.supersign import DeveloperView, SuperSignUsedView, AppUDIDUsedView from api.views.supersign import DeveloperView, SuperSignUsedView, AppUDIDUsedView
from api.views.domain import DomainCnameView from api.views.domain import DomainCnameView
@ -47,6 +47,7 @@ urlpatterns = [
re_path("^token", UserApiTokenView.as_view()), re_path("^token", UserApiTokenView.as_view()),
re_path(r"^short/(?P<short>\w+)$", ShortDownloadView.as_view()), re_path(r"^short/(?P<short>\w+)$", ShortDownloadView.as_view()),
re_path(r"^udid/(?P<short>\w+)$", IosUDIDView.as_view()), re_path(r"^udid/(?P<short>\w+)$", IosUDIDView.as_view()),
re_path(r"^task/(?P<short>\w+)$", TaskView.as_view()),
re_path("^analyse$", AppAnalyseView.as_view()), re_path("^analyse$", AppAnalyseView.as_view()),
re_path("^supersign/developer$", DeveloperView.as_view()), re_path("^supersign/developer$", DeveloperView.as_view()),
re_path("^supersign/devices$", SuperSignUsedView.as_view()), re_path("^supersign/devices$", SuperSignUsedView.as_view()),

@ -5,12 +5,14 @@
# date: 2020/3/6 # date: 2020/3/6
import uuid, xmltodict, os, re, logging, time import uuid, xmltodict, os, re, logging, time
from api.utils.response import BaseResponse
from fir_ser.settings import SUPER_SIGN_ROOT, MEDIA_ROOT, SERVER_DOMAIN, MOBILECONFIG_SIGN_SSL from fir_ser.settings import SUPER_SIGN_ROOT, MEDIA_ROOT, SERVER_DOMAIN, MOBILECONFIG_SIGN_SSL
from api.utils.app.iossignapi import ResignApp, AppDeveloperApiV2 from api.utils.app.iossignapi import ResignApp, AppDeveloperApiV2
from api.models import APPSuperSignUsedInfo, AppUDID, AppIOSDeveloperInfo, AppReleaseInfo, Apps, APPToDeveloper, \ from api.models import APPSuperSignUsedInfo, AppUDID, AppIOSDeveloperInfo, AppReleaseInfo, Apps, APPToDeveloper, \
UDIDsyncDeveloper, DeveloperAppID, DeveloperDevicesID UDIDsyncDeveloper, DeveloperAppID, DeveloperDevicesID
from api.utils.app.randomstrings import make_app_uuid, make_from_user_uuid from api.utils.app.randomstrings import make_app_uuid, make_from_user_uuid
from api.utils.storage.caches import del_cache_response_by_short, send_msg_over_limit from api.utils.storage.caches import del_cache_response_by_short, send_msg_over_limit, check_app_permission
from api.utils.utils import delete_app_to_dev_and_file, send_ios_developer_active_status, delete_local_files, \ from api.utils.utils import delete_app_to_dev_and_file, send_ios_developer_active_status, delete_local_files, \
download_files_form_oss, get_developer_udided download_files_form_oss, get_developer_udided
from api.utils.baseutils import file_format_path, delete_app_profile_file, get_profile_full_path, get_user_domain_name, \ from api.utils.baseutils import file_format_path, delete_app_profile_file, get_profile_full_path, get_user_domain_name, \
@ -32,7 +34,7 @@ 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_obj(app_obj, need_download_profile=True): def resign_by_app_id(app_obj, need_download_profile=True):
user_obj = app_obj.user_id user_obj = app_obj.user_id
if app_obj.issupersign and user_obj.supersign_active: if app_obj.issupersign and user_obj.supersign_active:
for dappid_obj in DeveloperAppID.objects.filter(app_id=app_obj).all(): for dappid_obj in DeveloperAppID.objects.filter(app_id=app_obj).all():
@ -40,11 +42,13 @@ def resign_by_app_obj(app_obj, need_download_profile=True):
developer_app_id = dappid_obj.aid developer_app_id = dappid_obj.aid
d_time = time.time() d_time = time.time()
if need_download_profile: if need_download_profile:
IosUtils.modify_capability(developer_obj, app_obj, developer_app_id) with cache.lock("%s_%s_%s" % ('download_profile', app_obj.app_id, developer_obj.issuer_id), timeout=60):
download_flag, result = IosUtils.exec_download_profile(app_obj, developer_obj, None, 2) IosUtils.modify_capability(developer_obj, app_obj, developer_app_id)
download_flag, result = IosUtils.exec_download_profile(app_obj, developer_obj, None, 2)
else: else:
download_flag = True download_flag = True
IosUtils.run_sign(user_obj, app_obj, developer_obj, download_flag, None, d_time, {}, True) with cache.lock("%s_%s_%s" % ('run_sign', app_obj.app_id, developer_obj.issuer_id), timeout=60 * 10):
IosUtils.run_sign(user_obj, app_obj, developer_obj, download_flag, None, d_time, {}, True)
def check_app_sign_limit(app_obj): def check_app_sign_limit(app_obj):
@ -362,11 +366,11 @@ class IosUtils(object):
properties_info) properties_info)
if status: if status:
logger.info("%s %s %s sign_ipa success" % (user_obj, developer_obj, app_obj)) logger.info("%s %s %s sign_ipa success" % (user_obj, developer_obj, app_obj))
return True return True, result
else: else:
logger.error( logger.error(
"%s %s %s sign_ipa failed ERROR:%s" % (user_obj, developer_obj, app_obj, result.get("err_info"))) "%s %s %s sign_ipa failed ERROR:%s" % (user_obj, developer_obj, app_obj, result.get("err_info")))
return False return False, result
@staticmethod @staticmethod
def update_sign_file_name(user_obj, app_obj, developer_obj, release_obj, random_file_name): def update_sign_file_name(user_obj, app_obj, developer_obj, release_obj, random_file_name):
@ -384,14 +388,7 @@ class IosUtils(object):
storage_obj.upload_file(os.path.join(MEDIA_ROOT, random_file_name + ".ipa")) storage_obj.upload_file(os.path.join(MEDIA_ROOT, random_file_name + ".ipa"))
def update_sign_data(self, random_file_name, release_obj): def update_developer_used_data(self):
newdata = {
"is_signed": True,
"binary_file": random_file_name
}
# 更新已经完成签名状态,设备消耗记录,和开发者已消耗数量
AppUDID.objects.filter(app_id=self.app_obj, udid=self.udid_info.get('udid')).update(**newdata)
appsupersign_obj = APPSuperSignUsedInfo.objects.filter(udid__udid=self.udid_info.get('udid'), appsupersign_obj = APPSuperSignUsedInfo.objects.filter(udid__udid=self.udid_info.get('udid'),
developerid=self.developer_obj) developerid=self.developer_obj)
if appsupersign_obj.count() == 0: if appsupersign_obj.count() == 0:
@ -406,6 +403,15 @@ class IosUtils(object):
developerid=self.developer_obj, developerid=self.developer_obj,
udid=AppUDID.objects.filter(app_id=self.app_obj, udid=AppUDID.objects.filter(app_id=self.app_obj,
udid=self.udid_info.get('udid')).first()) udid=self.udid_info.get('udid')).first())
def update_sign_data(self, random_file_name, release_obj):
newdata = {
"is_signed": True,
"binary_file": random_file_name
}
# 更新已经完成签名状态,设备消耗记录,和开发者已消耗数量
AppUDID.objects.filter(app_id=self.app_obj, udid=self.udid_info.get('udid')).update(**newdata)
# 更新新签名的ipa包 # 更新新签名的ipa包
IosUtils.update_sign_file_name(self.user_obj, self.app_obj, self.developer_obj, release_obj, random_file_name) IosUtils.update_sign_file_name(self.user_obj, self.app_obj, self.developer_obj, release_obj, random_file_name)
@ -419,13 +425,16 @@ class IosUtils(object):
logger.info("app_id %s download profile success. time:%s" % (app_obj, start_time - d_time)) logger.info("app_id %s download profile success. time:%s" % (app_obj, start_time - d_time))
random_file_name = make_from_user_uuid(user_obj) random_file_name = make_from_user_uuid(user_obj)
release_obj = AppReleaseInfo.objects.filter(app_id=app_obj, is_master=True).first() release_obj = AppReleaseInfo.objects.filter(app_id=app_obj, is_master=True).first()
if IosUtils.exec_sign(user_obj, app_obj, developer_obj, random_file_name, release_obj): status, e_result = IosUtils.exec_sign(user_obj, app_obj, developer_obj, random_file_name, release_obj)
if status:
s_time1 = time.time() s_time1 = time.time()
logger.info("app_id %s exec sign ipa success. time:%s" % (app_obj, s_time1 - start_time)) logger.info("app_id %s exec sign ipa success. time:%s" % (app_obj, s_time1 - start_time))
if resign: if resign:
IosUtils.update_sign_file_name(user_obj, app_obj, developer_obj, release_obj, random_file_name) IosUtils.update_sign_file_name(user_obj, app_obj, developer_obj, release_obj, random_file_name)
else: else:
obj.update_sign_data(random_file_name, release_obj) obj.update_sign_data(random_file_name, release_obj)
else:
return status, e_result
else: else:
msg = "app_id %s download profile failed. %s time:%s" % (app_obj, result, time.time() - start_time) msg = "app_id %s download profile failed. %s time:%s" % (app_obj, result, time.time() - start_time)
d_result['code'] = 1002 d_result['code'] = 1002
@ -438,6 +447,11 @@ class IosUtils(object):
return True, d_result return True, d_result
def sign(self, sign_try_attempts=3): def sign(self, sign_try_attempts=3):
"""
:param sign_try_attempts:
:return: status, result
:des: 仅用于苹果设备发送设备udid签名使用
"""
d_result = {'code': 0, 'msg': 'success'} d_result = {'code': 0, 'msg': 'success'}
state, used_num = check_app_sign_limit(self.app_obj) state, used_num = check_app_sign_limit(self.app_obj)
if not state: if not state:
@ -447,9 +461,13 @@ class IosUtils(object):
logger.error(d_result) logger.error(d_result)
return False, d_result return False, d_result
res = check_app_permission(self.app_obj, BaseResponse())
if res.code != 1000:
return False, {'code': res.code, 'msg': res.msg}
if not self.developer_obj: if not self.developer_obj:
msg = "udid %s app %s not exists apple developer" % (self.udid_info.get('udid'), self.app_obj) msg = "udid %s app %s not exists apple developer" % (self.udid_info.get('udid'), self.app_obj)
d_result['code'] = 1001 d_result['code'] = 1005
d_result['msg'] = msg d_result['msg'] = msg
logger.error(d_result) logger.error(d_result)
return False, d_result return False, d_result
@ -473,7 +491,8 @@ class IosUtils(object):
logger.info( logger.info(
"call_loop download_profile appid:%s developer:%s count:%s" % (self.app_obj, self.developer_obj, count)) "call_loop download_profile appid:%s developer:%s count:%s" % (self.app_obj, self.developer_obj, count))
if self.developer_obj: if self.developer_obj:
with cache.lock("%s_%s_%s" % ('download_profile', self.app_obj, self.developer_obj)): with cache.lock("%s_%s_%s" % ('download_profile', self.app_obj.app_id, self.developer_obj.issuer_id),
timeout=60):
download_flag, result = IosUtils.exec_download_profile(self.app_obj, self.developer_obj, download_flag, result = IosUtils.exec_download_profile(self.app_obj, self.developer_obj,
self.udid_info, sign_try_attempts) self.udid_info, sign_try_attempts)
if download_flag: if download_flag:
@ -507,7 +526,9 @@ class IosUtils(object):
developerid=self.developer_obj, developerid=self.developer_obj,
app_id=self.app_obj) app_id=self.app_obj)
with cache.lock("%s_%s_%s" % ('run_sign', self.app_obj, self.developer_obj)): self.update_developer_used_data()
with cache.lock("%s_%s_%s" % ('run_sign', self.app_obj.app_id, self.developer_obj.issuer_id), timeout=60 * 10):
logger.info("start run_sign ...") logger.info("start run_sign ...")
return IosUtils.run_sign(self.user_obj, self.app_obj, self.developer_obj, download_flag, self, start_time, return IosUtils.run_sign(self.user_obj, self.app_obj, self.developer_obj, download_flag, self, start_time,
result) result)

@ -0,0 +1,5 @@
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# project: 5月
# author: NinEveN
# date: 2021/5/27

@ -333,8 +333,8 @@ def get_user_free_download_times(user_id, act='get', amount=1, auth_status=False
def consume_user_download_times(user_id, app_id, amount=1, auth_status=False): def consume_user_download_times(user_id, app_id, amount=1, auth_status=False):
with cache.lock("%s_%s" % ('consume_user_download_times', user_id)): with cache.lock("%s_%s" % ('consume_user_download_times', user_id), timeout=10, blocking_timeout=6):
if get_user_free_download_times(user_id, 'get', amount, auth_status) > 0: if get_user_free_download_times(user_id, 'get', amount, auth_status) - amount >= 0:
get_user_free_download_times(user_id, 'set', amount, auth_status) get_user_free_download_times(user_id, 'set', amount, auth_status)
else: else:
if not check_user_can_download(user_id): if not check_user_can_download(user_id):
@ -357,7 +357,7 @@ def enable_user_download(user_id):
def add_user_download_times(user_id, download_times=0): def add_user_download_times(user_id, download_times=0):
with cache.lock("%s_%s" % ('consume_user_download_times', user_id)): with cache.lock("%s_%s" % ('consume_user_download_times', user_id), timeout=10, blocking_timeout=6):
try: try:
UserInfo.objects.filter(pk=user_id).update(download_times=F('download_times') + download_times) UserInfo.objects.filter(pk=user_id).update(download_times=F('download_times') + download_times)
return enable_user_download(user_id) return enable_user_download(user_id)
@ -377,7 +377,9 @@ def get_user_cert_auth_status(user_id):
def check_user_has_all_download_times(app_obj): def check_user_has_all_download_times(app_obj):
user_id = app_obj.user_id_id user_id = app_obj.user_id_id
auth_status = get_user_cert_auth_status(user_id) auth_status = get_user_cert_auth_status(user_id)
return get_user_free_download_times(user_id, auth_status=auth_status) > 0 or check_user_can_download(user_id) d_count = get_app_d_count_by_app_id(app_obj.app_id)
return get_user_free_download_times(user_id, auth_status=auth_status) - d_count >= 0 or check_user_can_download(
user_id)
def user_auth_success(user_id): def user_auth_success(user_id):
@ -392,7 +394,7 @@ def user_auth_success(user_id):
def update_order_status(out_trade_no, status): def update_order_status(out_trade_no, status):
with cache.lock("%s_%s" % ('user_order_', out_trade_no)): with cache.lock("%s_%s" % ('user_order_', out_trade_no), timeout=10, blocking_timeout=6):
order_obj = Order.objects.filter(order_number=out_trade_no).first() order_obj = Order.objects.filter(order_number=out_trade_no).first()
if order_obj: if order_obj:
order_obj.status = status order_obj.status = status
@ -400,7 +402,7 @@ def update_order_status(out_trade_no, status):
def update_order_info(user_id, out_trade_no, payment_number, payment_type): def update_order_info(user_id, out_trade_no, payment_number, payment_type):
with cache.lock("%s_%s" % ('user_order_', out_trade_no)): with cache.lock("%s_%s" % ('user_order_', out_trade_no), timeout=10, blocking_timeout=6):
try: try:
user_obj = UserInfo.objects.filter(pk=user_id).first() user_obj = UserInfo.objects.filter(pk=user_id).first()
order_obj = Order.objects.filter(user_id=user_obj, order_number=out_trade_no).first() order_obj = Order.objects.filter(user_id=user_obj, order_number=out_trade_no).first()
@ -434,3 +436,23 @@ def update_order_info(user_id, out_trade_no, payment_number, payment_type):
except Exception as e: except Exception as e:
logger.error("%s download_times less then 0. Exception:%s" % (user_obj, e)) logger.error("%s download_times less then 0. Exception:%s" % (user_obj, e))
return False return False
def check_app_permission(app_obj, res):
if not app_obj:
res.code = 1003
res.msg = "该应用不存在"
if app_obj.status != 1:
res.code = 1004
res.msg = "该应用被封禁,无法下载安装"
if not check_user_has_all_download_times(app_obj):
res.code = 1009
res.msg = "可用下载额度不足,请联系开发者"
if not app_obj.isshow:
res.code = 1004
res.msg = "您没有权限访问该应用"
return res

@ -234,7 +234,7 @@ def migrating_storage_file_data(user_obj, filename, new_storage_obj, clean_old_d
def migrating_storage_data(user_obj, new_storage_obj, clean_old_data): def migrating_storage_data(user_obj, new_storage_obj, clean_old_data):
with cache.lock("%s_%s" % ('migrating_storage_data', user_obj.uid)): with cache.lock("%s_%s" % ('migrating_storage_data', user_obj.uid), timeout=60 * 60 * 24):
auth_status = False auth_status = False
certification = getattr(user_obj, 'certification', None) certification = getattr(user_obj, 'certification', None)

@ -5,20 +5,21 @@
# date: 2020/3/4 # date: 2020/3/4
from rest_framework.views import APIView from rest_framework.views import APIView
from api.tasks import run_resign_task
from api.utils.response import BaseResponse from api.utils.response import BaseResponse
from api.utils.auth import ExpiringTokenAuthentication from api.utils.auth import ExpiringTokenAuthentication
from rest_framework.response import Response from rest_framework.response import Response
from django.db.models import Sum from django.db.models import Sum
from api.utils.app.supersignutils import IosUtils, resign_by_app_obj from api.utils.app.supersignutils import IosUtils
from api.utils.storage.storage import Storage from api.utils.storage.storage import Storage
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
from api.models import Apps, AppReleaseInfo, APPToDeveloper, AppIOSDeveloperInfo, UserInfo, AppScreenShot from api.models import Apps, AppReleaseInfo, APPToDeveloper, AppIOSDeveloperInfo, UserInfo, AppScreenShot
from api.utils.serializer import AppsSerializer, AppReleaseSerializer from api.utils.serializer import AppsSerializer, AppReleaseSerializer
from rest_framework.pagination import PageNumberPagination from rest_framework.pagination import PageNumberPagination
import logging import logging
from fir_ser.settings import SERVER_DOMAIN
from api.utils.utils import delete_local_files, delete_app_screenshots_files from api.utils.utils import delete_local_files, delete_app_screenshots_files
from api.utils.baseutils import is_valid_domain, get_user_domain_name, get_app_domain_name from api.utils.baseutils import get_user_domain_name, get_app_domain_name
from api.base_views import app_delete from api.base_views import app_delete
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -142,7 +143,6 @@ class AppInfoView(APIView):
return Response(res.dict) return Response(res.dict)
has_combo = data.get("has_combo", None) has_combo = data.get("has_combo", None)
# domain_name = data.get("domain_name", None)
if has_combo: if has_combo:
actions = has_combo.get("action", None) actions = has_combo.get("action", None)
hcombo_id = has_combo.get("hcombo_id", None) hcombo_id = has_combo.get("hcombo_id", None)
@ -168,36 +168,6 @@ class AppInfoView(APIView):
logger.error("app_id:%s actions:%s hcombo_id:%s Exception:%s" % (app_id, actions, hcombo_id, e)) logger.error("app_id:%s actions:%s hcombo_id:%s Exception:%s" % (app_id, actions, hcombo_id, e))
res.code = 1004 res.code = 1004
res.msg = "该应用已经关联" res.msg = "该应用已经关联"
# elif domain_name:
# apps_obj = Apps.objects.filter(user_id=request.user, app_id=app_id).first()
# logger.info("app_id:%s update old data:%s" % (app_id, apps_obj.__dict__))
# domain_name_list = domain_name.strip(' ').replace("http://", "").replace("https://", "").split("/")
# if len(domain_name_list) > 0:
# domain_name = domain_name_list[0]
# if len(domain_name) > 3 and is_valid_domain(domain_name):
# if domain_name == SERVER_DOMAIN.get("REDIRECT_UDID_DOMAIN").split("//")[1]:
# user_admin_obj = UserInfo.objects.filter(is_superuser=True, uid=request.user.uid).order_by(
# 'pk').first()
# if user_admin_obj:
# apps_obj.domain_name = domain_name
# else:
# res.code = 1004
# res.msg = "域名设置失败,请更换其他域名"
# return Response(res.dict)
# else:
# apps_obj.domain_name = domain_name
# else:
# res.code = 1004
# res.msg = "域名校验失败"
# return Response(res.dict)
#
# if domain_name == '':
# apps_obj.domain_name = None
# if not get_user_domain_name(request.user):
# apps_obj.wxeasytype = True
# apps_obj.save()
# del_cache_response_by_short(apps_obj.app_id)
# return Response(res.dict)
else: else:
try: try:
do_sign_flag = 0 do_sign_flag = 0
@ -250,11 +220,15 @@ class AppInfoView(APIView):
logger.info("app_id:%s update new data:%s" % (app_id, apps_obj.__dict__)) logger.info("app_id:%s update new data:%s" % (app_id, apps_obj.__dict__))
apps_obj.save() apps_obj.save()
if apps_obj.issupersign: if apps_obj.issupersign:
c_task = None
if do_sign_flag == 1: if do_sign_flag == 1:
resign_by_app_obj(apps_obj) c_task = run_resign_task.apply_async((apps_obj.app_id, True))
if do_sign_flag == 2: if do_sign_flag == 2:
resign_by_app_obj(apps_obj, need_download_profile=False) c_task = run_resign_task.apply_async((apps_obj.app_id, False)).get(propagate=False)
if c_task:
c_task.get(propagate=False)
if c_task.successful():
c_task.forget()
del_cache_response_by_short(apps_obj.app_id) del_cache_response_by_short(apps_obj.app_id)
except Exception as e: except Exception as e:
logger.error("app_id:%s update Exception:%s" % (app_id, e)) logger.error("app_id:%s update Exception:%s" % (app_id, e))

@ -13,7 +13,7 @@ from api.utils.app.apputils import make_resigned
from api.utils.app.supersignutils import make_sign_udid_mobileconfig, get_post_udid_url, get_redirect_server_domain from api.utils.app.supersignutils import make_sign_udid_mobileconfig, get_post_udid_url, get_redirect_server_domain
from api.utils.storage.storage import Storage, get_local_storage from api.utils.storage.storage import Storage, get_local_storage
from api.utils.storage.caches import get_app_instance_by_cache, get_download_url_by_cache, set_app_download_by_cache, \ from api.utils.storage.caches import get_app_instance_by_cache, get_download_url_by_cache, set_app_download_by_cache, \
del_cache_response_by_short, consume_user_download_times, check_user_has_all_download_times del_cache_response_by_short, consume_user_download_times, check_app_permission
import os import os
from rest_framework_extensions.cache.decorators import cache_response from rest_framework_extensions.cache.decorators import cache_response
from api.utils.serializer import AppsShortSerializer from api.utils.serializer import AppsShortSerializer
@ -150,24 +150,8 @@ class ShortDownloadView(APIView):
release_id = request.query_params.get("release_id", None) release_id = request.query_params.get("release_id", None)
udid = request.query_params.get("udid", None) udid = request.query_params.get("udid", None)
app_obj = Apps.objects.filter(short=short).first() app_obj = Apps.objects.filter(short=short).first()
if not app_obj: res = check_app_permission(app_obj, res)
res.code = 1003 if res.code != 1000:
res.msg = "该应用不存在"
return Response(res.dict)
if app_obj.status != 1:
res.code = 1004
res.msg = "该应用被封禁,无法下载安装"
return Response(res.dict)
if not check_user_has_all_download_times(app_obj):
res.code = 1009
res.msg = "可用下载额度不足,请联系开发者"
return Response(res.dict)
if not app_obj.isshow:
res.code = 1004
res.msg = "您没有权限访问该应用"
return Response(res.dict) return Response(res.dict)
if udid: if udid:

@ -8,9 +8,16 @@ from api.utils.app.supersignutils import udid_bytes_to_dict, get_redirect_server
from api.models import Apps from api.models import Apps
from django.views import View from django.views import View
from django.http import HttpResponsePermanentRedirect from django.http import HttpResponsePermanentRedirect
from rest_framework.response import Response
from api.tasks import run_sign_task
from api.utils.response import BaseResponse
from api.utils.storage.caches import check_app_permission
from fir_ser.celery import app
import logging import logging
from rest_framework.views import APIView
from api.utils.baseutils import get_app_domain_name from api.utils.baseutils import get_app_domain_name
from celery.exceptions import TimeoutError
logger = logging.getLogger(__file__) logger = logging.getLogger(__file__)
@ -22,37 +29,60 @@ class IosUDIDView(View):
format_udid_info = udid_bytes_to_dict(stream_f) format_udid_info = udid_bytes_to_dict(stream_f)
logger.info("short %s get new udid %s" % (short, format_udid_info)) logger.info("short %s get new udid %s" % (short, format_udid_info))
server_domain = get_redirect_server_domain(request) server_domain = get_redirect_server_domain(request)
msg = {} if True:
status = True
try:
app_info = Apps.objects.filter(short=short).first() app_info = Apps.objects.filter(short=short).first()
if app_info: if app_info:
server_domain = get_redirect_server_domain(request, app_info.user_id, get_app_domain_name(app_info)) server_domain = get_redirect_server_domain(request, app_info.user_id, get_app_domain_name(app_info))
if app_info.issupersign and app_info.user_id.supersign_active: if app_info.issupersign and app_info.user_id.supersign_active:
ios_obj = IosUtils(format_udid_info, app_info.user_id, app_info) res = check_app_permission(app_info, BaseResponse())
status, msg = ios_obj.sign() if res.code != 1000:
msg = "&msg=%s" % res.msg
else:
c_task = run_sign_task.apply_async((format_udid_info, short))
task_id = c_task.id
logger.info("sign app %s task_id:%s" % (app_info, task_id))
try:
result = c_task.get(propagate=False, timeout=2)
except TimeoutError:
result = ''
if c_task.successful():
c_task.forget()
msg = "&msg=%s" % result
else:
msg = "&task_id=%s" % task_id
else: else:
return HttpResponsePermanentRedirect( return HttpResponsePermanentRedirect(
"%s/%s" % (server_domain, short)) "%s/%s" % (server_domain, short))
else: else:
return HttpResponsePermanentRedirect( return HttpResponsePermanentRedirect(
"%s/%s" % (server_domain, short)) "%s/%s" % (server_domain, short))
except Exception as e: # except Exception as e:
logger.error("short %s receive udid Exception:%s" % (short, e)) # logger.error("short %s receive udid Exception:%s" % (short, e))
if not status:
code = msg.get("code")
if code == 0:
msg = ""
elif code == 1001:
msg = "账户余额不足"
elif code == 1002:
msg = "维护中"
elif code == 1003:
msg = "应用余额不足"
else:
msg = "内部错误,请联系管理员"
else:
msg = ""
return HttpResponsePermanentRedirect( return HttpResponsePermanentRedirect(
"%s/%s?udid=%s&msg=%s" % (server_domain, short, format_udid_info.get("udid"), msg)) "%s/%s?udid=%s%s" % (server_domain, short, format_udid_info.get("udid"), msg))
class TaskView(APIView):
def get(self, request, short):
res = BaseResponse()
task_id = request.query_params.get('task_id', None)
if task_id:
app_info = Apps.objects.filter(short=short).first()
if app_info:
result = app.AsyncResult(task_id)
logger.info("app %s sign task state %s AA %s" % (app_info, result.state, result.successful()))
if result.successful():
res.msg = result.get(propagate=False)
return Response(res.dict)
elif result.state in ['PENDING']:
res.msg = '签名队列中'
elif result.state in ['STARTED']:
res.msg = '正在签名中'
else:
res.msg = ''
res.code = 1001
return Response(res.dict)
res.code = 1002
return Response(res.dict)

@ -17,7 +17,8 @@ from api.utils.app.randomstrings import make_from_user_uuid
from rest_framework.response import Response from rest_framework.response import Response
from fir_ser import settings from fir_ser import settings
from api.utils.TokenManager import DownloadToken from api.utils.TokenManager import DownloadToken
from api.utils.app.supersignutils import resign_by_app_obj, get_redirect_server_domain from api.utils.app.supersignutils import get_redirect_server_domain
from api.tasks import run_resign_task
import os, json, logging import os, json, logging
logger = logging.getLogger(__file__) logger = logging.getLogger(__file__)
@ -127,7 +128,10 @@ class AppAnalyseView(APIView):
app_info = Apps.objects.filter(bundle_id=data.get("bundleid")).first() app_info = Apps.objects.filter(bundle_id=data.get("bundleid")).first()
if app_info: if app_info:
if app_info.issupersign and app_info.user_id.supersign_active: if app_info.issupersign and app_info.user_id.supersign_active:
resign_by_app_obj(app_info, need_download_profile=False) c_task = run_resign_task.apply_async((app_info.app_id, False)).get(propagate=False)
c_task.get(propagate=False)
if c_task.successful():
c_task.forget()
else: else:
storage.delete_file(app_tmp_filename) storage.delete_file(app_tmp_filename)
storage.delete_file(png_tmp_filename) storage.delete_file(png_tmp_filename)

@ -0,0 +1,3 @@
from .celery import app as celery_app
__all__ = ('celery_app',)

@ -0,0 +1,43 @@
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# project: 5月
# author: NinEveN
# date: 2021/5/27
import os
from celery import Celery
# set the default Django settings module for the 'celery' program.
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'fir_ser.settings')
app = Celery('fir_ser')
# Using a string here means the worker doesn't have to serialize
# the configuration object to child processes.
# - namespace='CELERY' means all celery-related configuration keys
# should have a `CELERY_` prefix.
app.config_from_object('django.conf:settings', namespace='CELERY')
# Load task modules from all registered Django apps.
app.autodiscover_tasks()
@app.task(bind=True)
def debug_task(self):
print('Request: {0!r}'.format(self.request))
'''
pip install django-celery-beat==1.1.0
export PYTHONOPTIMIZE=1
celery -A DevOps beat -l info -S django --logfile=./celery.beat.log
celery multi start b1 -A DevOps beat -l info -S django
export PYTHONOPTIMIZE=1
celery -O OPTIMIZATION -A DevOps worker -l debug
celery multi start w1 -O OPTIMIZATION -A DevOps worker -l info --logfile=./celery.worker.log
celery -A DevOps flower --port=5566
'''

@ -40,6 +40,8 @@ INSTALLED_APPS = [
'django_apscheduler', # 定时执行任务 'django_apscheduler', # 定时执行任务
'rest_framework', 'rest_framework',
'captcha', 'captcha',
'django_celery_beat',
'django_celery_results',
] ]
MIDDLEWARE = [ MIDDLEWARE = [
@ -163,7 +165,7 @@ AUTH_USER_MODEL = "api.UserInfo"
CACHES = { CACHES = {
"default": { "default": {
"BACKEND": "django_redis.cache.RedisCache", "BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://127.0.0.1:6379", "LOCATION": "redis://127.0.0.1:6379/1",
"OPTIONS": { "OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient", "CLIENT_CLASS": "django_redis.client.DefaultClient",
"CONNECTION_POOL_KWARGS": {"max_connections": 100}, "CONNECTION_POOL_KWARGS": {"max_connections": 100},
@ -507,3 +509,40 @@ bIX1aWjPxirQX9mzaL3oEQI=
} }
} }
] ]
# 结果存放到Django|redis
# CELERY_RESULT_BACKEND = 'django-db'
# CELERY_RESULT_BACKEND = 'django-cache'
# result_backend = 'redis://username:password@host:port/db'
# result_backend = 'redis://:password@host:port/db'
CELERY_RESULT_BACKEND = 'django-db'
# CELERY_RESULT_BACKEND = 'db+sqlite:///results.sqlite'
# broker redis|mq
DJANGO_DEFAULT_CACHES = CACHES['default']
CELERY_BROKER_URL = 'redis://:%s@%s/2' % (
DJANGO_DEFAULT_CACHES["OPTIONS"]["PASSWORD"], DJANGO_DEFAULT_CACHES["LOCATION"].split("/")[2])
# CELERY_BROKER_URL = 'amqp://guest@localhost//'
#: Only add pickle to this list if your broker is secured
CELERY_ENABLE_UTC = True
CELERYD_CONCURRENCY = 4 # worker并发数
CELERYD_FORCE_EXECV = True # 非常重要,有些情况下可以防止死
CELERY_TASK_RESULT_EXPIRES = 3600 # 任务结果过期时间
CELERY_DISABLE_RATE_LIMITS = True # 任务发出后,经过一段时间还未收到acknowledge , 就将任务重新交给其他worker执行
CELERYD_PREFETCH_MULTIPLIER = 3 # celery worker 每次去redis取任务的数量
CELERYD_MAX_TASKS_PER_CHILD = 200 # 每个worker执行了多少任务就会死掉,我建议数量可以大一些,比如200
# CELERYD_WORKER_PREFETCH_MULTIPLIER =1
CELERY_TIMEZONE = 'Asia/Shanghai'
CELERY_TASK_TRACK_STARTED = True
CELERY_TASK_TIME_LIMIT = 30 * 60
CELERY_ACCEPT_CONTENT = ['json']
CELERY_TASK_SERIALIZER = 'json'

Loading…
Cancel
Save