优化代码,增加苹果api访问代理

存储迁移只允许读操作
qrnn
youngS 3 years ago
parent 49c35275b6
commit 26e6efeaf4
  1. 32
      fir_client/src/components/apps/FirApps.vue
  2. 50
      fir_client/src/components/user/FirUserStorage.vue
  3. 14
      fir_client/src/restful/index.js
  4. 5
      fir_client/src/utils/index.js
  5. 6
      fir_ser/api/base_views.py
  6. 6
      fir_ser/api/tasks.py
  7. 3
      fir_ser/api/urls.py
  8. 30
      fir_ser/api/utils/app/apputils.py
  9. 28
      fir_ser/api/utils/app/iossignapi.py
  10. 4
      fir_ser/api/utils/app/supersignutils.py
  11. 56
      fir_ser/api/utils/apple/appleapiv3.py
  12. 33
      fir_ser/api/utils/storage/caches.py
  13. 36
      fir_ser/api/views/apps.py
  14. 48
      fir_ser/api/views/storage.py
  15. 21
      fir_ser/api/views/supersign.py
  16. 26
      fir_ser/api/views/uploads.py
  17. 6
      fir_ser/config.py
  18. 6
      fir_ser/fir_ser/settings.py

@ -144,7 +144,7 @@
</el-table>
<span slot="footer" class="dialog-footer">
<el-button plain @click="closeUpload"> </el-button>
<el-button :disabled="multiuploaddisable" plain @click="closeUpload"> </el-button>
<el-button :disabled="multiuploaddisable" plain type="primary"
@click="multiuploadFun">开始上传</el-button>
</span>
@ -609,6 +609,7 @@ export default {
multiupload: false,
multiuploaddisable: false,
multiFileList: [],
trymultiFileList: [],
default_pay_radio: '',
default_price_radio: '',
pay_choices: [],
@ -657,7 +658,7 @@ export default {
"app_id": short
})
},
multirun(process, keylist, func) {
multirun(process, keylist, func, failback) {
let thr = [];
for (let i = 0; i < process; i++) {
thr.push(Promise.resolve())
@ -671,7 +672,10 @@ export default {
}
}
if (failback) {
// eslint-disable-next-line no-unused-vars
thr[process - 1].then(_ => failback())
}
},
uploadasync(file) {
return new Promise((resolve, reject) => {
@ -703,7 +707,9 @@ export default {
} else {
this.$message.error("应用 " + analyseappinfo.appname + " 上传token获取失败,请刷新重试")
this.multiFileList.splice(this.multiFileList.indexOf(file), 1)
resolve()
this.trymultiFileList.push(file);
// this.multiFileList.splice(this.multiFileList.indexOf(file), 1)
}
loading.close();
}, {
@ -713,12 +719,16 @@ export default {
} else {
this.$message.error("文件 " + file.raw.name + " 解析失败,请检查是否为APP应用")
this.multiFileList.splice(this.multiFileList.indexOf(file), 1)
resolve()
this.trymultiFileList.push(file);
// this.multiFileList.splice(this.multiFileList.indexOf(file), 1)
}
}, err => {
loading.close();
this.$message.error("应用解析失败,请检查是否为APP应用");
this.multiFileList.splice(this.multiFileList.indexOf(file), 1)
resolve()
this.trymultiFileList.push(file);
// this.multiFileList.splice(this.multiFileList.indexOf(file), 1)
// eslint-disable-next-line no-console
console.log('Error ', err);
});
@ -731,8 +741,16 @@ export default {
multiuploadFun() {
this.multiuploaddisable = true;
if (this.multiFileList && this.multiFileList.length > 0) {
this.multirun(3, this.multiFileList, this.uploadasync)
// eslint-disable-next-line no-unused-vars
this.multirun(3, this.multiFileList, this.uploadasync, _ => {
// eslint-disable-next-line no-console
console.log('upload file ' + this.trymultiFileList.length + ' failed. try again')
if (this.trymultiFileList && this.trymultiFileList.length > 0) {
this.multirun(3, this.trymultiFileList, this.uploadasync, null)
}
})
}
},
show_package_prices() {
get_package_prices(res => {

@ -101,6 +101,18 @@
强制迁移忽略数据迁移失败错误可能会导致数据丢失
</el-button>
</div>
<div v-else style="margin-top: 20px">
<el-button round style="margin-left: 10px"
type="danger"
@click="clean_storage_data('all')">
清理所有app数据
</el-button>
<el-button round style="margin-left: 10px"
type="danger"
@click="clean_storage_data('history')">
清理app历史版本数据只保留最新数据
</el-button>
</div>
<el-divider/>
<el-form v-if="storageinfo.id && storageinfo.id !==-1" ref="storageinfoform" :model="storageinfo"
label-width="80px" style="width: 39%;margin:0 auto;">
@ -308,7 +320,7 @@
</template>
<script>
import {getStorageinfo} from "@/restful";
import {cleanStorageData, getStorageinfo} from "@/restful";
import {deepCopy, getUserInfoFun} from "@/utils";
export default {
@ -394,6 +406,42 @@ export default {
});
},
validFun(val) {
if (val && val.length > 6) {
return true
}
return false
},
clean_storage_data(act) {
this.$prompt('此操作属于危险操作,请悉知你操作将导致的影响,输入登录密码进行确认该操作', '警告', {
confirmButtonText: '确定',
cancelButtonText: '取消',
inputPlaceholder: '该用户的登录密码',
inputValidator: this.validFun
}).then(({value}) => {
const loading = this.$loading({
lock: true,
text: '执行中,请耐心等待...',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
});
cleanStorageData(data => {
loading.close();
if (data.code === 1000) {
this.$message.success('清理成功');
} else {
this.$message.error(data.msg)
}
}, {"methods": 'POST', 'data': {'act': act, 'confirm_pwd': value}});
}).catch(() => {
this.$message({
type: 'info',
message: '已取消操作'
});
});
},
change_storage_info(force) {
this.$confirm('此操作将导致应用,图片,显示下载异常, 是否继续?', '警告', {
confirmButtonText: '确定',

@ -388,6 +388,20 @@ export function getStorageinfo(callBack, params, load = true) {
);
}
/**用户app清理操作 */
export function cleanStorageData(callBack, params, load = true) {
getData(
params.methods,
USERSEVER + '/storage/clean',
params.data,
data => {
callBack(data);
},
load,
true,
true
);
}
/**用户个人信息 */
export function userinfos(callBack, params, load = true) {

@ -217,7 +217,10 @@ export function uploadaliyunoss(file, certinfo, app, successcallback, processcal
retryCount++;
// eslint-disable-next-line no-console
console.error("retryCount : " + retryCount);
uploadFile('')
// eslint-disable-next-line no-unused-vars
setTimeout(_ => {
uploadFile('')
}, 1000);
} else {
app.$message({
message: file.name + ' 重试了' + retryCount + '次,还是上传失败了,请刷新页面重试',

@ -25,6 +25,11 @@ def app_delete(app_obj):
res.msg = "应用不存在"
return res
user_obj = app_obj.user_id
if MigrateStorageState(user_obj.uid).get_state():
res.code = 1001
res.msg = "数据迁移中"
return res
count = APPToDeveloper.objects.filter(app_id=app_obj).count()
if app_obj.issupersign or count > 0:
logger.info(f"app_id:{app_obj.app_id} is supersign ,delete this app need clean IOS developer")
@ -127,5 +132,4 @@ def storage_change(use_storage_id, user_obj, force):
else:
return False
del_cache_storage(user_obj)
MigrateStorageState.del_state(user_obj.uid)
return True

@ -15,6 +15,7 @@ from api.utils.crontab.ctasks import sync_download_times, auto_clean_upload_tmp_
auto_check_ios_developer_active
from api.utils.geetest.geetest_utils import check_bypass_status
from api.utils.mp.wechat import sync_wx_access_token
from api.utils.storage.caches import MigrateStorageState
from api.utils.storage.storage import get_local_storage
from api.views.login import get_login_type
from fir_ser.celery import app
@ -26,6 +27,11 @@ logger = logging.getLogger(__name__)
@shared_task
def run_sign_task(format_udid_info, short, client_ip):
app_obj = Apps.objects.filter(short=short).first()
if MigrateStorageState(app_obj.user_id.uid).get_state():
msg = "数据迁移中,无法处理该操作"
return msg
ios_obj = IosUtils(format_udid_info, app_obj.user_id, app_obj)
status, msg = ios_obj.sign_ipa(client_ip)
if not status:

@ -25,7 +25,7 @@ from api.views.logout import LogoutView
from api.views.order import PriceView, OrderView, PaySuccess
from api.views.receiveudids import IosUDIDView, TaskView
from api.views.report import ReportView
from api.views.storage import StorageView
from api.views.storage import StorageView, CleanStorageView
from api.views.supersign import DeveloperView, SuperSignUsedView, AppUDIDUsedView, SuperSignCertView, \
DeviceUsedBillView, DeveloperDeviceView, DeviceUsedRankInfoView
from api.views.thirdlogin import ValidWxChatToken, ThirdWxAccount
@ -44,6 +44,7 @@ urlpatterns = [
re_path("^logout", LogoutView.as_view()),
re_path("^apps$", AppsView.as_view()),
re_path("^storage$", StorageView.as_view()),
re_path("^storage/clean$", CleanStorageView.as_view()),
re_path(r"^apps/(?P<app_id>\w+)", AppInfoView.as_view()),
re_path(r"^appinfos/(?P<app_id>\w+)/(?P<act>\w+)", AppReleaseInfoView.as_view()),
re_path("^upload$", UploadView.as_view()),

@ -9,7 +9,7 @@ import random
from api.models import AppReleaseInfo, Apps
from api.utils.baseutils import make_app_uuid
from api.utils.modelutils import get_user_domain_name
from api.utils.storage.caches import del_cache_response_by_short
from api.utils.storage.caches import del_cache_response_by_short, MigrateStorageState
from api.utils.storage.storage import Storage
logger = logging.getLogger(__name__)
@ -114,6 +114,22 @@ def get_random_short(number=4):
return short_url
def clean_history_apps(app_obj, user_obj, history_release_limit=20):
storage_obj = Storage(user_obj)
if not MigrateStorageState(user_obj.uid).get_state():
release_queryset = AppReleaseInfo.objects.filter(app_id=app_obj).order_by("-created_time")
if release_queryset.count() > history_release_limit:
flag = 0
for release_obj in release_queryset:
flag += 1
if flag > history_release_limit:
logger.info(
f"history_release_limit:{history_release_limit} this release is to more,so delete it release_id:{release_obj.release_id}")
storage_obj.delete_file(release_obj.release_id, app_obj.type)
storage_obj.delete_file(release_obj.icon_url)
release_obj.delete()
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
@ -193,15 +209,5 @@ def save_app_infos(app_file_name, user_obj, app_info, bundle_id, app_img, short,
return True
if history_release_limit != 0:
release_queryset = AppReleaseInfo.objects.filter(app_id=app_obj).order_by("-created_time")
if release_queryset.count() > history_release_limit:
flag = 0
for release_obj in release_queryset:
flag += 1
if flag > history_release_limit:
logger.info(
f"history_release_limit:{history_release_limit} this release is to more,so delete it release_id:{release_obj.release_id}")
storage.delete_file(release_obj.release_id, app_obj.type)
storage.delete_file(release_obj.icon_url)
release_obj.delete()
clean_history_apps(app_obj, user_obj, history_release_limit)
return True

@ -327,9 +327,11 @@ class AppDeveloperApiV2(object):
logger.error("ios developer set devices status Failed Exception:%s" % e)
result['return_info'] = "%s" % e
if device_err_callback and ("There are no current ios devices" in str(e) or "Device obj is None" in str(e)):
CleanErrorBundleIdSignDataState.set_state(failed_call_prefix)
device_err_callback()
CleanErrorBundleIdSignDataState.del_state(failed_call_prefix)
with CleanErrorBundleIdSignDataState(failed_call_prefix) as state:
if state:
device_err_callback()
else:
logger.warning(f'{device_err_callback}-{failed_call_prefix} is running')
return False, result
def get_device(self):
@ -391,9 +393,13 @@ class AppDeveloperApiV2(object):
logger.error("ios developer register device Failed Exception:%s" % e)
result['return_info'] = "%s" % e
if device_err_callback and "There are no current ios devices" in str(e):
CleanErrorBundleIdSignDataState.set_state(failed_call_prefix)
device_err_callback()
CleanErrorBundleIdSignDataState.del_state(failed_call_prefix)
with CleanErrorBundleIdSignDataState(failed_call_prefix) as state:
if state:
device_err_callback()
else:
logger.warning(f'{device_err_callback}-{failed_call_prefix} is running')
return False, result
def make_and_download_profile(self, app_obj, provision_name, auth, developer_app_id, device_id_list, profile_id,
@ -418,10 +424,12 @@ class AppDeveloperApiV2(object):
logger.error(f"app_id {app_obj.app_id} ios developer make profile Failed Exception:{e}")
result['return_info'] = "%s" % e
if app_id_err_callback and "There is no App ID with ID" in str(e):
CleanErrorBundleIdSignDataState.set_state(failed_call_prefix)
for call_fun in app_id_err_callback:
call_fun()
CleanErrorBundleIdSignDataState.del_state(failed_call_prefix)
with CleanErrorBundleIdSignDataState(failed_call_prefix) as state:
if state:
for call_fun in app_id_err_callback:
call_fun()
else:
logger.warning(f'{app_id_err_callback}-{failed_call_prefix} is running')
return False, result
def modify_capability(self, app_obj, developer_app_id):

@ -52,7 +52,7 @@ def resign_by_app_id_and_developer(app_id, developer_id, developer_app_id, need_
if check_ipa_is_latest_sign(app_obj, developer_obj) and not force:
return
add_new_bundles_prefix = f"check_or_add_new_bundles_{developer_obj.issuer_id}_{app_obj.app_id}"
if CleanErrorBundleIdSignDataState.get_state(add_new_bundles_prefix):
if CleanErrorBundleIdSignDataState(add_new_bundles_prefix).get_state():
return False, '清理执行中,请等待'
d_time = time.time()
if need_download_profile:
@ -664,7 +664,7 @@ class IosUtils(object):
download_profile_prefix = f"make_and_download_profile_{self.developer_obj.issuer_id}_{self.app_obj.app_id}"
with cache.lock(register_devices_prefix, timeout=60):
if CleanErrorBundleIdSignDataState.get_state(add_new_bundles_prefix):
if CleanErrorBundleIdSignDataState(add_new_bundles_prefix).get_state():
return True, True # 程序错误,进行清理的时候,拦截多余的设备注册
if not get_developer_obj_by_others(self.user_obj, self.udid, self.app_obj):
d_result['code'] = 1005

@ -15,14 +15,19 @@ from functools import wraps
import jwt
import requests
from django.conf import settings
logger = logging.getLogger(__name__)
# https://developer.apple.com/documentation/appstoreconnectapi/creating_api_keys_for_app_store_connect_api
# https://appstoreconnect.apple.com/access/api 去申请秘钥
#
proxies = settings.APPLE_DEVELOPER_API_PROXY if settings.APPLE_DEVELOPER_API_PROXY else {}
timeout = settings.APPLE_DEVELOPER_API_TIMEOUT if settings.APPLE_DEVELOPER_API_TIMEOUT else 180
def request_format_log(req):
try:
logger.info(f"url:{req.url} header:{req.headers} code:{req.status_code} body:{req.content}")
@ -93,7 +98,8 @@ class DevicesAPI(object):
if query_parameters:
for k, v in query_parameters.items():
params[k] = v
return request_format_log(requests.get(self.devices_url, params=params, headers=self.headers))
return request_format_log(
requests.get(self.devices_url, params=params, headers=self.headers, proxies=proxies, timeout=timeout))
def list_enabled_devices(self):
return self.list_devices({"filter[status]": "ENABLED"})
@ -126,7 +132,8 @@ class DevicesAPI(object):
}
}
}
return request_format_log(requests.post(self.devices_url, json=json, headers=self.headers))
return request_format_log(
requests.post(self.devices_url, json=json, headers=self.headers, proxies=proxies, timeout=timeout))
def read_device_information(self, device_id):
"""
@ -141,7 +148,8 @@ class DevicesAPI(object):
params = {
"fields[devices]": "addedDate, deviceClass, model, name, platform, status, udid",
}
return request_format_log(requests.get(base_url, params=params, headers=self.headers))
return request_format_log(
requests.get(base_url, params=params, headers=self.headers, proxies=proxies, timeout=timeout))
def enabled_device(self, device_id, device_name):
return self.modify_registered_device(device_id, device_name, 'ENABLED')
@ -172,7 +180,8 @@ class DevicesAPI(object):
}
}
}
return request_format_log(requests.patch(base_url, json=json, headers=self.headers))
return request_format_log(
requests.patch(base_url, json=json, headers=self.headers, proxies=proxies, timeout=timeout))
class BundleIDsAPI(object):
@ -204,7 +213,8 @@ class BundleIDsAPI(object):
}
}
}
return request_format_log(requests.post(self.bundle_ids_url, json=json, headers=self.headers))
return request_format_log(
requests.post(self.bundle_ids_url, json=json, headers=self.headers, proxies=proxies, timeout=timeout))
def delete_bundle_id_by_id(self, bundle_id):
"""
@ -218,7 +228,8 @@ class BundleIDsAPI(object):
"""
base_url = '%s/%s' % (self.bundle_ids_url, bundle_id)
json = {}
return request_format_log(requests.delete(base_url, json=json, headers=self.headers))
return request_format_log(
requests.delete(base_url, json=json, headers=self.headers, proxies=proxies, timeout=timeout))
def list_bundle_ids(self, query_parameters=None):
"""
@ -236,7 +247,8 @@ class BundleIDsAPI(object):
if query_parameters:
for k, v in query_parameters.items():
params[k] = v
return request_format_log(requests.get(self.bundle_ids_url, params=params, headers=self.headers))
return request_format_log(
requests.get(self.bundle_ids_url, params=params, headers=self.headers, proxies=proxies, timeout=timeout))
def list_bundle_id_by_identifier(self, identifier):
return self.list_bundle_ids({"filter[identifier]": identifier})
@ -265,7 +277,8 @@ class BundleIDsAPI(object):
}
}
}
return request_format_log(requests.patch(base_url, json=json, headers=self.headers))
return request_format_log(
requests.patch(base_url, json=json, headers=self.headers, proxies=proxies, timeout=timeout))
class BundleIDsCapabilityAPI(object):
@ -287,7 +300,8 @@ class BundleIDsCapabilityAPI(object):
"""
base_url = '%s/%s_%s' % (self.bundle_ids_capability_url, bundle_id, capability_type)
json = {}
return request_format_log(requests.delete(base_url, json=json, headers=self.headers))
return request_format_log(
requests.delete(base_url, json=json, headers=self.headers, proxies=proxies, timeout=timeout))
def enable_capability(self, bundle_id, capability_type):
"""
@ -316,7 +330,9 @@ class BundleIDsCapabilityAPI(object):
}
}
}
return request_format_log(requests.post(self.bundle_ids_capability_url, json=json, headers=self.headers))
return request_format_log(
requests.post(self.bundle_ids_capability_url, json=json, headers=self.headers, proxies=proxies,
timeout=timeout))
class ProfilesAPI(object):
@ -368,7 +384,8 @@ class ProfilesAPI(object):
}
}
}
return request_format_log(requests.post(self.profiles_url, json=json, headers=self.headers))
return request_format_log(
requests.post(self.profiles_url, json=json, headers=self.headers, proxies=proxies, timeout=timeout))
def delete_profile(self, profile_id):
"""
@ -382,7 +399,8 @@ class ProfilesAPI(object):
"""
base_url = '%s/%s' % (self.profiles_url, profile_id)
json = {}
return request_format_log(requests.delete(base_url, json=json, headers=self.headers))
return request_format_log(
requests.delete(base_url, json=json, headers=self.headers, proxies=proxies, timeout=timeout))
def download_profile(self, profile_id):
# n=base64.b64decode(profileContent)
@ -407,7 +425,8 @@ class ProfilesAPI(object):
if query_parameters:
for k, v in query_parameters.items():
params[k] = v
return request_format_log(requests.get(self.profiles_url, params=params, headers=self.headers))
return request_format_log(
requests.get(self.profiles_url, params=params, headers=self.headers, proxies=proxies, timeout=timeout))
def list_profile_by_profile_id(self, profile_id):
return self.list_profiles({"filter[id]": profile_id, "include": ""})
@ -442,7 +461,8 @@ class CertificatesAPI(object):
}
}
}
return request_format_log(requests.post(self.certificates_url, json=json, headers=self.headers))
return request_format_log(
requests.post(self.certificates_url, json=json, headers=self.headers, proxies=proxies, timeout=timeout))
def download_certificate(self, certificate_id):
# req.json()['data'][0]['attributes']['certificateContent']
@ -467,7 +487,8 @@ class CertificatesAPI(object):
if query_parameters:
for k, v in query_parameters.items():
params[k] = v
return request_format_log(requests.get(self.certificates_url, params=params, headers=self.headers))
return request_format_log(
requests.get(self.certificates_url, params=params, headers=self.headers, proxies=proxies, timeout=timeout))
def list_certificate_by_certificate_id(self, certificate_id):
return self.list_certificate({"filter[id]": certificate_id, })
@ -484,7 +505,8 @@ class CertificatesAPI(object):
"""
base_url = '%s/%s' % (self.certificates_url, certificate_id)
json = {}
return request_format_log(requests.delete(base_url, json=json, headers=self.headers))
return request_format_log(
requests.delete(base_url, json=json, headers=self.headers, proxies=proxies, timeout=timeout))
class BaseInfoObj(object):

@ -514,18 +514,27 @@ def get_wx_ticket_login_info_cache(ticket):
class CacheBaseState(object):
@classmethod
def get_state(cls, key):
return cache.get(f"{cls.__name__}_{key}")
@classmethod
def set_state(cls, key, value=time.time(), timeout=3600 * 24):
cls.del_state(f"{cls.__name__}_{key}")
cache.set(f"{cls.__name__}_{key}", value, timeout)
@classmethod
def del_state(cls, key):
cache.delete(f"{cls.__name__}_{key}")
def __init__(self, key, value=time.time(), timeout=3600 * 24):
self.key = f"CacheBaseState_{self.__class__.__name__}_{key}"
self.value = value
self.timeout = timeout
self.active = False
def get_state(self):
return cache.get(self.key)
def __enter__(self):
if cache.get(self.key):
return False
else:
cache.set(self.key, self.value, self.timeout)
self.active = True
return True
def __exit__(self, exc_type, exc_val, exc_tb):
if self.active:
cache.delete(self.key)
logger.info(f"cache base state __exit__ {exc_type}, {exc_val}, {exc_tb}")
class MigrateStorageState(CacheBaseState):

@ -20,7 +20,7 @@ from api.utils.modelutils import get_user_domain_name, get_app_domain_name, chec
from api.utils.response import BaseResponse
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, \
CleanAppSignDataState
CleanAppSignDataState, MigrateStorageState
from api.utils.storage.storage import Storage
from api.utils.utils import delete_local_files, delete_app_screenshots_files
@ -133,19 +133,21 @@ class AppInfoView(APIView):
res = BaseResponse()
if app_id:
data = request.data
if MigrateStorageState(request.user.uid).get_state():
res.code = 1008
res.msg = "数据迁移中,无法处理该操作"
return Response(res.dict)
clean = data.get("clean", None)
if clean:
if CleanAppSignDataState.get_state(request.user.uid):
res.code = 1008
res.msg = "数据清理中,请耐心等待"
return Response(res.dict)
logger.info(f"app_id:{app_id} clean:{clean} ,close super_sign should clean_app_by_user_obj")
CleanAppSignDataState.set_state(request.user.uid, timeout=60 * 10)
app_obj = Apps.objects.filter(user_id=request.user, app_id=app_id).first()
IosUtils.clean_app_by_user_obj(app_obj)
CleanAppSignDataState.del_state(request.user.uid)
with CleanAppSignDataState(request.user.uid) as state:
if state:
logger.info(f"app_id:{app_id} clean:{clean} ,close super_sign should clean_app_by_user_obj")
app_obj = Apps.objects.filter(user_id=request.user, app_id=app_id).first()
IosUtils.clean_app_by_user_obj(app_obj)
else:
res.code = 1008
res.msg = "数据清理中,请耐心等待"
return Response(res.dict)
has_combo = data.get("has_combo", None)
@ -285,6 +287,12 @@ class AppReleaseInfoView(APIView):
def delete(self, request, app_id, act):
res = BaseResponse()
if app_id:
if MigrateStorageState(request.user.uid).get_state():
res.code = 1008
res.msg = "数据迁移中,无法处理该操作"
return Response(res.dict)
app_obj = Apps.objects.filter(user_id=request.user, app_id=app_id).first()
if app_obj:
storage = Storage(request.user)
@ -338,6 +346,12 @@ class AppReleaseInfoView(APIView):
res = BaseResponse()
res.data = {}
if app_id:
if MigrateStorageState(request.user.uid).get_state():
res.code = 1008
res.msg = "数据迁移中,无法处理该操作"
return Response(res.dict)
app_obj = Apps.objects.filter(user_id=request.user, app_id=app_id).first()
if app_obj:
app_release_objs = AppReleaseInfo.objects.filter(app_id=app_obj, release_id=act)

@ -9,8 +9,9 @@ import logging
from rest_framework.response import Response
from rest_framework.views import APIView
from api.base_views import storage_change
from api.models import AppStorage, UserInfo
from api.base_views import storage_change, app_delete
from api.models import AppStorage, UserInfo, Apps
from api.utils.app.apputils import clean_history_apps
from api.utils.auth import ExpiringTokenAuthentication, StoragePermission
from api.utils.response import BaseResponse
from api.utils.serializer import StorageSerializer
@ -96,14 +97,15 @@ class StorageView(APIView):
use_storage_id = data.get("use_storage_id", None)
force = data.get("force", None)
if use_storage_id:
if MigrateStorageState.get_state(request.user.uid):
res.code = 1007
res.msg = "数据迁移中,请耐心等待"
return Response(res.dict)
MigrateStorageState.set_state(request.user.uid)
if not storage_change(use_storage_id, request.user, force):
res.code = 1006
res.msg = '修改失败'
with MigrateStorageState(request.user.uid) as state:
if state:
if not storage_change(use_storage_id, request.user, force):
res.code = 1006
res.msg = '修改失败'
else:
res.code = 1007
res.msg = "数据迁移中,请耐心等待"
return Response(res.dict)
storage_id = data.get("id", None)
@ -152,3 +154,29 @@ class StorageView(APIView):
res.code = 1004
res.msg = '该存储不存在'
return Response(res.dict)
class CleanStorageView(APIView):
authentication_classes = [ExpiringTokenAuthentication, ]
permission_classes = [StoragePermission, ]
def post(self, request):
res = BaseResponse()
data = request.data
logger.info(f"user {request.user} clean storage data:{data}")
act = data.get('act', '')
if act in ['history', 'all']:
if request.user.check_password(data.get('confirm_pwd', '')):
app_obj_lists = Apps.objects.filter(user_id=request.user).all()
for app_obj in app_obj_lists:
if act == 'all':
res = app_delete(app_obj)
elif act == 'history':
clean_history_apps(app_obj, request.user, 1)
else:
res.code = 1007
res.msg = "密码有误,请检查"
else:
res.code = 1007
res.msg = "参数不合法,清理失败"
return Response(res.dict)

@ -128,17 +128,16 @@ class DeveloperView(APIView):
res.msg = result.get("err_info")
return Response(res.dict)
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)
CleanSignDataState.del_state(request.user.uid)
if not status:
res.code = 1008
res.msg = result.get("err_info")
return Response(res.dict)
with CleanSignDataState(request.user.uid) as state:
if state:
status, result = IosUtils.clean_developer(developer_obj, request.user, False)
if not status:
res.code = 1008
res.msg = result.get("err_info")
else:
res.code = 1008
res.msg = "数据清理中,请耐心等待"
return Response(res.dict)
elif act == 'disable':
developer_obj.is_actived = False
developer_obj.save(update_fields=['is_actived'])

@ -18,7 +18,7 @@ from api.utils.auth import ExpiringTokenAuthentication
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, check_super_sign_permission
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, MigrateStorageState
from api.utils.storage.storage import Storage
from fir_ser import settings
@ -39,6 +39,11 @@ class AppAnalyseView(APIView):
bundle_id = request.data.get("bundleid", None)
app_type = request.data.get("type", None)
if MigrateStorageState(request.user.uid).get_state():
res.code = 1008
res.msg = "数据迁移中,无法处理该操作"
return Response(res.dict)
if bundle_id and app_type:
ap = 'apk'
if app_type.lower() == 'iOS'.lower():
@ -99,6 +104,12 @@ class AppAnalyseView(APIView):
:return:
"""
res = BaseResponse()
if MigrateStorageState(request.user.uid).get_state():
res.code = 1008
res.msg = "数据迁移中,无法处理该操作"
return Response(res.dict)
data = request.data
app_info = {
"labelname": data.get("appname"),
@ -129,7 +140,7 @@ class AppAnalyseView(APIView):
app_obj = Apps.objects.filter(bundle_id=data.get("bundleid"), user_id=request.user).first()
if app_obj:
c_task = run_resign_task(app_obj.pk, False, False)
logger.info(f"app {app_obj} run_resign_task msg:{c_task}")
logger.info(f"app {app_obj} run_resign_task end msg:{c_task}")
else:
storage.delete_file(app_tmp_filename)
storage.delete_file(png_tmp_filename)
@ -212,6 +223,11 @@ class UploadView(APIView):
"""
res = BaseResponse()
if MigrateStorageState(request.user.uid).get_state():
res.code = 1008
res.msg = "数据迁移中,无法处理该操作"
return Response(res.dict)
# 获取多个file
files = request.FILES.getlist('file', None)
cert_info = request.data.get('certinfo', None)
@ -299,6 +315,12 @@ class UploadView(APIView):
:return:
"""
res = BaseResponse()
if MigrateStorageState(request.user.uid).get_state():
res.code = 1008
res.msg = "数据迁移中,无法处理该操作"
return Response(res.dict)
cert_info = request.data.get('certinfo', None)
if cert_info:
app_id = cert_info.get("app_id", None)

@ -246,6 +246,12 @@ class SENDERCONF(object):
class IPACONF(object):
APPLE_DEVELOPER_API_PROXY = {
# 代理的作用,主要是为了加快苹果api的访问,在国内会出现卡死,访问超时等问题,怀疑是被苹果服务器拦截了
# 'http': '47.243.172.202:17897',
# 'https': '47.243.172.202:17897'
}
APPLE_DEVELOPER_API_TIMEOUT = 180 # 访问苹果api超时时间,默认3分钟
MOBILE_CONFIG_SIGN_SSL = {
# 描述文件是否签名,默认是关闭状态;如果开启,并且ssl_key_path 和 ssl_pem_path 正常,则使用填写的ssl进行签名,否则默认不签名
'open': True,

@ -261,6 +261,10 @@ SERVER_DOMAIN = BASECONF.SERVER_DOMAIN
MOBILE_CONFIG_SIGN_SSL = IPACONF.MOBILE_CONFIG_SIGN_SSL
APPLE_DEVELOPER_API_PROXY = IPACONF.APPLE_DEVELOPER_API_PROXY
APPLE_DEVELOPER_API_TIMEOUT = IPACONF.APPLE_DEVELOPER_API_TIMEOUT
DEFAULT_MOBILEPROVISION = IPACONF.DEFAULT_MOBILEPROVISION
# DEFAULT_MOBILEPROVISION = {
# # 默认描述文件路径或者下载路径,用户企业签名或者超级签名 跳转 [设置 - 通用 - 描述文件|设备管理] 页面
@ -305,7 +309,7 @@ LOGGING = {
},
'handlers': {
'console': {
'level': 'DEBUG',
'level': 'INFO',
'filters': ['require_debug_true'], # 只有在Django debug为True时才在屏幕打印日志
'class': 'logging.StreamHandler',
'formatter': 'simple'

Loading…
Cancel
Save