代码优化

dependabot/npm_and_yarn/fir_admin/path-parse-1.0.7
youngS 3 years ago
parent 4501b5dc2a
commit 7599e5f3a2
  1. 18
      fir_ser/admin/views/login.py
  2. 2
      fir_ser/admin/views/order.py
  3. 2
      fir_ser/admin/views/storage.py
  4. 20
      fir_ser/api/base_views.py
  5. 8
      fir_ser/api/models.py
  6. 1
      fir_ser/api/tasks.py
  7. 6
      fir_ser/api/urls.py
  8. 74
      fir_ser/api/utils/TokenManager.py
  9. 106
      fir_ser/api/utils/app/apputils.py
  10. 126
      fir_ser/api/utils/app/iossignapi.py
  11. 8
      fir_ser/api/utils/app/shellcmds.py
  12. 177
      fir_ser/api/utils/app/supersignutils.py
  13. 35
      fir_ser/api/utils/apple/appleapiv3.py
  14. 63
      fir_ser/api/utils/baseutils.py
  15. 13
      fir_ser/api/utils/crontab/ctasks.py
  16. 20
      fir_ser/api/utils/geetest/geetest_lib.py
  17. 14
      fir_ser/api/utils/geetest/geetest_utils.py
  18. 2
      fir_ser/api/utils/middlewares.py
  19. 10
      fir_ser/api/utils/pay/ali.py
  20. 1
      fir_ser/api/utils/pay/alipay/__init__.py
  21. 10
      fir_ser/api/utils/pay/wx.py
  22. 26
      fir_ser/api/utils/pay/wxpay/__init__.py
  23. 91
      fir_ser/api/utils/sendmsg/sendmsg.py
  24. 15
      fir_ser/api/utils/serializer.py
  25. 27
      fir_ser/api/utils/storage/aliyunApi.py
  26. 48
      fir_ser/api/utils/storage/caches.py
  27. 35
      fir_ser/api/utils/storage/localApi.py
  28. 18
      fir_ser/api/utils/storage/qiniuApi.py
  29. 46
      fir_ser/api/utils/storage/storage.py
  30. 2
      fir_ser/api/utils/tempcaches.py
  31. 2
      fir_ser/api/utils/throttle.py
  32. 44
      fir_ser/api/utils/utils.py
  33. 203
      fir_ser/api/views/apps.py
  34. 23
      fir_ser/api/views/domain.py
  35. 90
      fir_ser/api/views/download.py
  36. 78
      fir_ser/api/views/login.py
  37. 4
      fir_ser/api/views/logout.py
  38. 20
      fir_ser/api/views/order.py
  39. 10
      fir_ser/api/views/receiveudids.py
  40. 28
      fir_ser/api/views/storage.py
  41. 91
      fir_ser/api/views/supersign.py
  42. 141
      fir_ser/api/views/uploads.py
  43. 4
      fir_ser/cli/urls.py
  44. 4
      fir_ser/cli/views/apps.py

@ -11,9 +11,8 @@ from api.utils.auth import ExpiringTokenAuthentication
from api.utils.serializer import UserInfoSerializer
from django.core.cache import cache
from rest_framework.views import APIView
import binascii
import os, datetime
from api.utils.utils import get_captcha, valid_captcha
from api.utils.utils import get_captcha, valid_captcha, set_user_token
from api.utils.response import BaseResponse
from fir_ser.settings import CACHE_KEY_TEMPLATE, LOGIN
from api.utils.storage.caches import login_auth_failed
@ -26,9 +25,6 @@ logger = logging.getLogger(__name__)
class LoginView(APIView):
throttle_classes = [VisitRegister1Throttle, VisitRegister2Throttle]
def generate_key(self):
return binascii.hexlify(os.urandom(32)).decode()
def post(self, request):
response = BaseResponse()
receive = request.data
@ -41,18 +37,12 @@ class LoginView(APIView):
if login_auth_failed("get", username):
password = receive.get("password")
user = auth.authenticate(username=username, password=password)
logger.info("username:%s password:%s" % (username, password))
logger.info(f"username:{username} password:{password}")
if user:
if user.is_active:
if user.role == 3:
login_auth_failed("del", username)
# update the token
key = self.generate_key()
now = datetime.datetime.now()
user_info = UserInfo.objects.get(pk=user.pk)
auth_key = "_".join([CACHE_KEY_TEMPLATE.get('user_auth_token_key'), key])
cache.set(auth_key, {'uid': user_info.uid, 'username': user_info.username}, 3600 * 24 * 7)
Token.objects.create(user=user, **{"access_token": key, "created": now})
key, user_info = set_user_token(user)
response.data = {
"username": user_info.username,
"token": key
@ -69,7 +59,7 @@ class LoginView(APIView):
response.code = 1002
else:
response.code = 1006
logger.error("username:%s failed too try , locked" % (username,))
logger.error(f"username:{username} failed too try , locked")
response.msg = "用户登录失败次数过多,已被锁定,请1小时之后再次尝试"
else:
response.code = 1001

@ -87,7 +87,7 @@ class OrderPayView(APIView):
return Response(res.dict)
obj = UserInfo.objects.filter(pk=pk).first()
if obj:
logger.info("user %s update storage data:%s" % (obj, data))
logger.info(f"user {obj} update storage data:{data}")
use_storage_id = data.get("use_storage_id", None)
force = data.get("force", None)
if use_storage_id:

@ -88,7 +88,7 @@ class StorageChangeView(APIView):
return Response(res.dict)
obj = UserInfo.objects.filter(pk=pk).first()
if obj:
logger.info("user %s update storage data:%s" % (obj, data))
logger.info(f"user {obj} update storage data:{data}")
use_storage_id = data.get("use_storage_id", None)
force = data.get("force", None)
if use_storage_id:

@ -8,9 +8,9 @@ from api.utils.response import BaseResponse
from api.utils.app.supersignutils import IosUtils
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, del_cache_by_delete_app, \
del_cache_storage
from api.models import Apps, AppReleaseInfo, APPToDeveloper, AppIOSDeveloperInfo, UserInfo, AppScreenShot, AppStorage
from api.models import AppReleaseInfo, APPToDeveloper, UserInfo, AppScreenShot, AppStorage
import logging
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
@ -27,21 +27,19 @@ def app_delete(app_obj):
user_obj = app_obj.user_id
count = APPToDeveloper.objects.filter(app_id=app_obj).count()
if app_obj.issupersign or count > 0:
logger.info("app_id:%s is supersign ,delete this app need clean IOS developer" % (app_obj.app_id))
logger.info(f"app_id:{app_obj.app_id} is supersign ,delete this app need clean IOS developer")
IosUtils.clean_app_by_user_obj(app_obj, user_obj)
storage = Storage(user_obj)
has_combo = app_obj.has_combo
if has_combo:
logger.info(
"app_id:%s has_combo ,delete this app need uncombo and clean del_cache_response_by_short" % (
app_obj.app_id))
f"app_id:{app_obj.app_id} has_combo ,delete this app need uncombo and clean del_cache_response_by_short")
has_combo.has_combo = None
del_cache_response_by_short(app_obj.app_id)
del_cache_by_delete_app(app_obj.app_id)
for app_release_obj in AppReleaseInfo.objects.filter(app_id=app_obj).all():
logger.info("delete app_id:%s need clean all release,release_id:%s" % (
app_obj.app_id, app_release_obj.release_id))
logger.info(f"delete app_id:{app_obj.app_id} need clean all release,release_id:{app_release_obj.release_id}")
storage.delete_file(app_release_obj.release_id, app_release_obj.release_type)
delete_local_files(app_release_obj.release_id, app_release_obj.release_type)
storage.delete_file(app_release_obj.icon_url)
@ -67,17 +65,17 @@ def app_release_delete(app_obj, release_id, storage):
apprelease_count = AppReleaseInfo.objects.filter(app_id=app_obj).values("release_id").count()
appreleaseobj = AppReleaseInfo.objects.filter(app_id=app_obj, release_id=release_id).first()
if not appreleaseobj.is_master:
logger.info("delete app release %s" % (appreleaseobj))
logger.info(f"delete app release {appreleaseobj}")
storage.delete_file(appreleaseobj.release_id, appreleaseobj.release_type)
delete_local_files(appreleaseobj.release_id, appreleaseobj.release_type)
storage.delete_file(appreleaseobj.icon_url)
appreleaseobj.delete()
elif appreleaseobj.is_master and apprelease_count < 2:
logger.info("delete app master release %s and clean app %s " % (appreleaseobj, app_obj))
logger.info(f"delete app master release {appreleaseobj} and clean app {app_obj} ")
count = APPToDeveloper.objects.filter(app_id=app_obj).count()
if app_obj.issupersign or count > 0:
logger.info("app_id:%s is supersign ,delete this app need clean IOS developer" % (app_obj.app_id))
logger.info(f"app_id:{app_obj.app_id} is supersign ,delete this app need clean IOS developer")
IosUtils.clean_app_by_user_obj(app_obj, user_obj)
storage.delete_file(appreleaseobj.release_id, appreleaseobj.release_type)
@ -118,7 +116,7 @@ def storage_change(use_storage_id, user_obj, force):
UserInfo.objects.filter(pk=user_obj.pk).update(storage_id=use_storage_id)
except Exception as e:
logger.error("update user %s storage failed Exception:%s" % (user_obj, e))
logger.error(f"update user {user_obj} storage failed Exception:{e}")
if force:
if use_storage_id == -1:
UserInfo.objects.filter(pk=user_obj.pk).update(storage=None)

@ -5,7 +5,7 @@ from django.db import models
from django.contrib.contenttypes.models import ContentType
from api.utils.app.randomstrings import make_random_uuid
from django.contrib.auth.models import AbstractUser
from api.utils.TokenManager import generateAlphanumericTokenOfLength, generateNumericTokenOfLength
from api.utils.TokenManager import generate_alphanumeric_token_of_length, generate_numeric_token_of_length
######################################## 用户表 ########################################
@ -58,7 +58,7 @@ class UserInfo(AbstractUser):
if len(self.uid) < 8:
self.uid = make_random_uuid()
if len(self.api_token) < 8:
self.api_token = self.uid + generateAlphanumericTokenOfLength(64)
self.api_token = self.uid + generate_alphanumeric_token_of_length(64)
super(UserInfo, self).save(*args, **kwargs)
@ -93,7 +93,7 @@ class VerifyName(models.Model):
verbose_name_plural = "实名认证"
def __str__(self):
return "%s" % (self.name)
return f"self.name"
######################################## APP表 ########################################
@ -456,7 +456,7 @@ class DomainCnameInfo(models.Model):
def save(self, *args, **kwargs):
if not self.domain_record or (self.domain_record and len(self.domain_record) < 26): # 最多3个启用的价格表
self.domain_record = '%s.%s' % (generateNumericTokenOfLength(24, 'abcdef'), self.domain_record)
self.domain_record = '%s.%s' % (generate_numeric_token_of_length(24, 'abcdef'), self.domain_record)
super(DomainCnameInfo, self).save(*args, **kwargs)
def __str__(self):

@ -6,7 +6,6 @@
from celery import shared_task
from django.core.cache import cache
from celery import Celery
from api.utils.storage.storage import get_local_storage

@ -13,12 +13,12 @@ Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.urls import path, re_path, include
from django.urls import re_path
from api.views.login import LoginView, UserInfoView, RegistView, AuthorizationView, ChangeAuthorizationView, \
UserApiTokenView, CertificationView, ChangeInfoView
from api.views.logout import LogoutView
from api.views.apps import AppsView, AppInfoView, AppReleaseinfoView
from api.views.apps import AppsView, AppInfoView, AppReleaseInfoView
from api.views.download import ShortDownloadView
from api.views.uploads import AppAnalyseView, UploadView
from api.views.storage import StorageView
@ -41,7 +41,7 @@ urlpatterns = [
re_path("^apps$", AppsView.as_view()),
re_path("^storage$", StorageView.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(r"^appinfos/(?P<app_id>\w+)/(?P<act>\w+)", AppReleaseInfoView.as_view()),
re_path("^upload$", UploadView.as_view()),
re_path("^userinfo", UserInfoView.as_view()),
re_path("^token", UserApiTokenView.as_view()),

@ -11,59 +11,57 @@ from django.core.cache import cache
from fir_ser.settings import CACHE_KEY_TEMPLATE
import logging
logger = logging.getLogger(__file__)
logger = logging.getLogger(__name__)
class DownloadToken(object):
def make_token(release_id, time_limit=60, key='', force_new=False):
token_key = "_".join([key.lower(), CACHE_KEY_TEMPLATE.get("make_token_key"), release_id])
token = cache.get(token_key)
if token and not force_new:
logger.debug(
f"make_token cache exists get token:{token} release_id:{release_id} force_new:{force_new} token_key:{token_key}")
return token
else:
random_str = uuid.uuid1().__str__().split("-")[0:-1]
user_ran_str = uuid.uuid5(uuid.NAMESPACE_DNS, release_id).__str__().split("-")
user_ran_str.extend(random_str)
token = "".join(user_ran_str)
cache.set(token, {
"atime": time.time() + time_limit,
"data": release_id
}, time_limit)
cache.set(token_key, token, time_limit - 1)
logger.debug(
f"make_token cache not exists get token:{token} release_id:{release_id} force_new:{force_new} token_key:{token_key}")
return token
def make_token(self, release_id, time_limit=60, key='', force_new=False):
token_key = "_".join([key.lower(), CACHE_KEY_TEMPLATE.get("make_token_key"), release_id])
token = cache.get(token_key)
if token and not force_new:
logger.debug("make_token cache exists get token:%s release_id:%s force_new:%s token_key:%s" % (
token, release_id, force_new, token_key))
return token
else:
random_str = uuid.uuid1().__str__().split("-")[0:-1]
user_ran_str = uuid.uuid5(uuid.NAMESPACE_DNS, release_id).__str__().split("-")
user_ran_str.extend(random_str)
token = "".join(user_ran_str)
cache.set(token, {
"atime": time.time() + time_limit,
"data": release_id
}, time_limit)
cache.set(token_key, token, time_limit - 1)
logger.debug(
"make_token cache not exists get token:%s release_id:%s force_new:%s token_key:%s" % (
token, release_id, force_new, token_key))
return token
def verify_token(self, token, release_id):
try:
values = cache.get(token)
if values and release_id == values.get("data", None):
logger.debug("verify_token token:%s release_id:%s success" % (token, release_id))
return True
except Exception as e:
logger.error("verify_token token:%s release_id:%s failed Exception:%s" % (token, release_id, e))
return False
logger.error("verify_token token:%s release_id:%s failed" % (token, release_id))
def verify_token(token, release_id):
try:
values = cache.get(token)
if values and release_id == values.get("data", None):
logger.debug(f"verify_token token:{token} release_id:{release_id} success")
return True
except Exception as e:
logger.error(f"verify_token token:{token} release_id:{release_id} failed Exception:{e}")
return False
logger.error(f"verify_token token:{token} release_id:{release_id} failed")
return False
def generateTokenForMedium(medium):
def generate_token_for_medium(medium):
if medium == 'email':
return generateAlphanumericTokenOfLength(32)
return generate_alphanumeric_token_of_length(32)
elif medium == 'wechat':
return 'WeChat'
else:
return generateNumericTokenOfLength(6)
return generate_numeric_token_of_length(6)
def generateNumericTokenOfLength(length, random_str=''):
def generate_numeric_token_of_length(length, random_str=''):
return "".join([random.choice(string.digits + random_str) for _ in range(length)])
def generateAlphanumericTokenOfLength(length):
def generate_alphanumeric_token_of_length(length):
return "".join(
[random.choice(string.digits + string.ascii_lowercase + string.ascii_uppercase) for _ in range(length)])

@ -12,7 +12,7 @@ from api.utils.storage.storage import Storage
from api.utils.storage.caches import del_cache_response_by_short
import logging
logger = logging.getLogger(__file__)
logger = logging.getLogger(__name__)
def make_resigned(bin_url, img_url, bundle_id, app_version, name):
@ -27,7 +27,7 @@ def make_resigned(bin_url, img_url, bundle_id, app_version, name):
<key>kind</key>
<string>software-package</string>
<key>url</key>
<string><![CDATA[%s]]></string>
<string><![CDATA[{bin_url}]]></string>
</dict>
<dict>
<key>kind</key>
@ -35,7 +35,7 @@ def make_resigned(bin_url, img_url, bundle_id, app_version, name):
<key>needs-shine</key>
<integer>0</integer>
<key>url</key>
<string><![CDATA[%s]]></string>
<string><![CDATA[{img_url}]]></string>
</dict>
<dict>
<key>kind</key>
@ -43,26 +43,26 @@ def make_resigned(bin_url, img_url, bundle_id, app_version, name):
<key>needs-shine</key>
<true/>
<key>url</key>
<string><![CDATA[%s]]></string>
<string><![CDATA[{img_url}]]></string>
</dict>
</array>
<key>metadata</key>
<dict>
<key>bundle-identifier</key>
<string>%s</string>
<string>{bundle_id}</string>
<key>bundle-version</key>
<string><![CDATA[%s]]></string>
<string><![CDATA[{app_version}]]></string>
<key>kind</key>
<string>software</string>
<key>title</key>
<string><![CDATA[%s]]></string>
<string><![CDATA[{name}]]></string>
</dict>
</dict>
</array>
</dict>
</plist>""" % (bin_url, img_url, img_url, bundle_id, app_version, name)
logger.info("make_resigned bin_url %s ,img_url %s, img_url %s, bundle_id %s, app_version %s, name %s" % (
bin_url, img_url, img_url, bundle_id, app_version, name))
</plist>""".format(bin_url=bin_url, img_url=img_url, bundle_id=bundle_id, app_version=app_version, name=name)
logger.info(
f"make_resigned bin_url {bin_url} ,img_url {img_url}, bundle_id {bundle_id}, app_version {app_version}, name {name}")
return ios_plist_tem
@ -78,10 +78,10 @@ def bytes2human(n):
return '%sB' % n
def get_release_type(app_file_name, appinfo):
def get_release_type(app_file_name, app_info):
extension = app_file_name.split(".")[1]
if extension == "ipa":
release_type = appinfo.get("release_type")
release_type = app_info.get("release_type")
if release_type == "Adhoc": # Adhoc: 内测版 Inhouse:企业版
return 1
elif release_type == "Inhouse":
@ -106,94 +106,94 @@ def get_random_short():
short_url = ''.join(random.sample(
['z', 'y', 'x', 'w', 'v', 'u', 't', 's', 'r', 'q', 'p', 'o', 'n', 'm', 'l', 'k', 'j', 'i', 'h', 'g', 'f',
'e', 'd', 'c', 'b', 'a'], 4))
appobj = Apps.objects.filter(short=short_url).first()
if appobj:
app_obj = Apps.objects.filter(short=short_url).first()
if app_obj:
return get_random_short()
else:
return short_url
def SaveAppInfos(app_file_name, user_obj, appinfo, bundle_id, app_img, short, size):
def save_app_infos(app_file_name, user_obj, app_info, bundle_id, app_img, short, size):
app_uuid = make_app_uuid(user_obj, bundle_id + app_file_name.split(".")[1])
##判断是否存在该app
appmobj = 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()
storage = Storage(user_obj)
newapp = False
if not appmobj:
newapp = True
is_new_app = False
if not app_obj:
is_new_app = True
appdata = {
"app_id": app_uuid,
"user_id": user_obj,
"type": get_app_type(app_file_name),
"name": appinfo["labelname"],
"new_bundle_name": appinfo["labelname"],
"name": app_info["labelname"],
"new_bundle_name": app_info["labelname"],
"short": short,
"bundle_id": bundle_id,
"count_hits": 0,
"wxeasytype": False if get_user_domain_name(user_obj) else True
}
try:
appmobj = Apps.objects.create(**appdata)
app_obj = Apps.objects.create(**appdata)
except Exception as e:
logger.error("create new app failed,appdata:%s Exception:%s" % (appdata, e))
logger.error(f"create new app failed,appdata:{appdata} Exception:{e}")
return False
else:
try:
newapp = False
appmobj.short = short
appmobj.name = appinfo["labelname"]
is_new_app = False
app_obj.short = short
app_obj.name = app_info["labelname"]
# appmobj.wxeasytype = False if user_obj.domain_name or appmobj.domain_name else True
appmobj.bundle_id = bundle_id
appmobj.save()
del_cache_response_by_short(appmobj.app_id)
app_obj.bundle_id = bundle_id
app_obj.save()
del_cache_response_by_short(app_obj.app_id)
except Exception as e:
logger.error("save app info failed,appmobj:%s Exception:%s" % (appmobj, e))
appmobj.bundle_id = bundle_id
appmobj.name = appinfo["labelname"]
appmobj.save()
logger.error(f"save app info failed,app_obj:{app_obj} Exception:{e}")
app_obj.bundle_id = bundle_id
app_obj.name = app_info["labelname"]
app_obj.save()
AppReleaseInfo.objects.filter(app_id=appmobj).update(**{"is_master": False})
AppReleaseInfo.objects.filter(app_id=app_obj).update(**{"is_master": False})
release_data = {
"app_id": appmobj,
"app_id": app_obj,
"icon_url": app_img,
"release_id": app_file_name.split(".")[0],
"build_version": str(appinfo.get("version", "latest")),
"app_version": str(appinfo.get("versioncode", "latest")),
"release_type": get_release_type(app_file_name, appinfo),
"minimum_os_version": str(appinfo.get("miniOSversion", "latest")),
"build_version": str(app_info.get("version", "latest")),
"app_version": str(app_info.get("versioncode", "latest")),
"release_type": get_release_type(app_file_name, app_info),
"minimum_os_version": str(app_info.get("miniOSversion", "latest")),
"binary_size": size,
"is_master": True,
"changelog": appinfo.get("changelog", ''),
"udid": appinfo.get("udid", ''),
"distribution_name": appinfo.get("distribution_name", ''),
"changelog": app_info.get("changelog", ''),
"udid": app_info.get("udid", ''),
"distribution_name": app_info.get("distribution_name", ''),
}
try:
AppReleaseInfo.objects.create(**release_data)
except Exception as e:
logging.error("create app release failed,release_data:%s Exception:%s" % (release_data, e))
if newapp:
logger.info("create app release failed,release_data:%s ,and app is new ,so delete this app:%s" % (
release_data, appmobj))
appmobj.delete()
logger.error(f"create app release failed,release_data:{release_data} Exception:{e}")
if is_new_app:
logger.info(
f"create app release failed,release_data:{release_data} ,and app is new ,so delete this app:{app_obj}")
app_obj.delete()
return False
try:
history_release_limit = int(user_obj.history_release_limit)
except Exception as e:
logger.error("get history_release_limit failed,history_release_limit:%s Exception:%s" % (
user_obj.history_release_limit, e))
logger.error(
f"get history_release_limit failed,history_release_limit:{user_obj.history_release_limit} Exception:{e}")
return True
if history_release_limit != 0:
release_queryset = AppReleaseInfo.objects.filter(app_id=appmobj).order_by("-created_time")
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:
logging.info("history_release_limit:%s this release is to more,so delete it release_id:%s" % (
history_release_limit, release_obj.release_id))
storage.delete_file(release_obj.release_id, appmobj.type)
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()
return True

@ -16,25 +16,25 @@ import base64
from OpenSSL.crypto import (load_pkcs12, dump_certificate_request, dump_privatekey, PKey, TYPE_RSA, X509Req,
dump_certificate, load_privatekey, load_certificate, PKCS12, FILETYPE_PEM, FILETYPE_ASN1)
logger = logging.getLogger(__file__)
logger = logging.getLogger(__name__)
def exec_shell(cmd, remote=False, timeout=None):
if remote:
hostip = "10.66.6.66"
host_ip = "10.66.6.66"
port = 65534
user = "root"
passwd = "root"
result = use_user_pass(hostip, port, user, passwd, cmd)
result = use_user_pass(host_ip, port, user, passwd, cmd)
return result
else:
logger.info("exec_shell cmd:%s" % (cmd))
logger.info(f"exec_shell cmd:{cmd}")
result = shell_command(cmd, timeout)
logger.info("exec_shell cmd:%s result:%s" % (cmd, result))
logger.info(f"exec_shell cmd:{cmd} result:{result}")
if result.get("exit_code") != 0:
err_info = result.get("err_info", None)
if err_info:
logger.error("exec_shell cmd:%s failed: %s" % (cmd, err_info))
logger.error(f"exec_shell cmd:{cmd} failed: {err_info}")
result["err_info"] = "Unknown Error"
return False, result
return True, result
@ -49,17 +49,17 @@ class ResignApp(object):
self.cmd = "zsign -c '%s' -k '%s' " % (self.app_dev_pem, self.my_local_key)
@staticmethod
def sign_mobileconfig(mobilconfig_path, sign_mobilconfig_path, ssl_pem_path, ssl_key_path):
'''
:param mobilconfig_path: 描述文件绝对路径
:param sign_mobilconfig_path: 签名之后的文件绝对路径
def sign_mobile_config(mobile_config_path, sign_mobile_config_path, ssl_pem_path, ssl_key_path):
"""
:param mobile_config_path: 描述文件绝对路径
:param sign_mobile_config_path: 签名之后的文件绝对路径
:param ssl_pem_path: pem证书的绝对路径
:param ssl_key_path: key证书的绝对路径
:return:
'''
"""
cmd = "openssl smime -sign -in %s -out %s -signer %s " \
"-inkey %s -certfile %s -outform der -nodetach " % (
mobilconfig_path, sign_mobilconfig_path, ssl_pem_path, ssl_key_path, ssl_pem_path)
mobile_config_path, sign_mobile_config_path, ssl_pem_path, ssl_key_path, ssl_pem_path)
return exec_shell(cmd)
def make_p12_from_cert(self, password):
@ -132,12 +132,42 @@ class ResignApp(object):
return exec_shell(self.cmd)
def make_csr_content(csr_file_path, private_key_path):
# create public/private key
key = PKey()
key.generate_key(TYPE_RSA, 2048)
# Generate CSR
req = X509Req()
req.get_subject().CN = 'FLY APP'
req.get_subject().O = 'FLY APP Inc'
req.get_subject().OU = 'IT'
req.get_subject().L = 'BJ'
req.get_subject().ST = 'BJ'
req.get_subject().C = 'CN'
req.get_subject().emailAddress = 'flyapps@126.com'
req.set_pubkey(key)
req.sign(key, 'sha256')
csr_content = dump_certificate_request(FILETYPE_PEM, req)
with open(csr_file_path, 'wb+') as f:
f.write(csr_content)
with open(private_key_path, 'wb+') as f:
f.write(dump_privatekey(FILETYPE_PEM, key))
return csr_content
def make_pem(cer_content, pem_path):
cert = load_certificate(FILETYPE_ASN1, cer_content)
with open(pem_path, 'wb+') as f:
f.write(dump_certificate(FILETYPE_PEM, cert))
class AppDeveloperApiV2(object):
def __init__(self, issuer_id, private_key_id, p8key, certid):
def __init__(self, issuer_id, private_key_id, p8key, cert_id):
self.issuer_id = issuer_id
self.private_key_id = private_key_id
self.p8key = p8key
self.certid = certid
self.cert_id = cert_id
def active(self):
result = {'data': []}
@ -145,11 +175,11 @@ class AppDeveloperApiV2(object):
apple_obj = AppStoreConnectApi(self.issuer_id, self.private_key_id, self.p8key)
certificates = apple_obj.get_all_certificates()
result['data'] = certificates
logger.info("ios developer active result:%s" % certificates)
logger.info(f"ios developer active result:{certificates}")
if len(certificates) > 0:
return True, result
except Exception as e:
logger.error("ios developer active Failed Exception:%s" % e)
logger.error(f"ios developer active Failed Exception:{e}")
result['return_info'] = "%s" % e
return False, result
@ -160,34 +190,6 @@ class AppDeveloperApiV2(object):
os.makedirs(cert_dir_path)
return os.path.join(cert_dir_path, cert_dir_name)
def make_csr_content(self, csr_file_path, private_key_path):
# create public/private key
key = PKey()
key.generate_key(TYPE_RSA, 2048)
# Generate CSR
req = X509Req()
req.get_subject().CN = 'FLY APP'
req.get_subject().O = 'FLY APP Inc'
req.get_subject().OU = 'IT'
req.get_subject().L = 'BJ'
req.get_subject().ST = 'BJ'
req.get_subject().C = 'CN'
req.get_subject().emailAddress = 'flyapps@126.com'
req.set_pubkey(key)
req.sign(key, 'sha256')
csr_content = dump_certificate_request(FILETYPE_PEM, req)
with open(csr_file_path, 'wb+') as f:
f.write(csr_content)
with open(private_key_path, 'wb+') as f:
f.write(dump_privatekey(FILETYPE_PEM, key))
return csr_content
def make_pem(self, cer_content, pem_path):
cert = load_certificate(FILETYPE_ASN1, cer_content)
with open(pem_path, 'wb+') as f:
f.write(dump_certificate(FILETYPE_PEM, cert))
def create_cert(self, user_obj):
result = {}
try:
@ -195,51 +197,51 @@ class AppDeveloperApiV2(object):
csr_path = self.file_format_path_name(user_obj)
if not os.path.isdir(os.path.dirname(csr_path)):
os.makedirs(os.path.dirname(csr_path))
csr_content = self.make_csr_content(csr_path + ".csr", csr_path + ".key")
csr_content = make_csr_content(csr_path + ".csr", csr_path + ".key")
certificates = apple_obj.create_certificate(csr_content.decode("utf-8"))
if certificates:
n = base64.b64decode(certificates.certificateContent)
with open(csr_path + ".cer", 'wb') as f:
f.write(n)
self.make_pem(n, csr_path + ".pem")
logger.info("ios developer create cert result:%s" % certificates.certificateContent)
make_pem(n, csr_path + ".pem")
logger.info(f"ios developer create cert result:{certificates.certificateContent}")
return True, certificates
except Exception as e:
logger.error("ios developer create cert Failed Exception:%s" % e)
logger.error(f"ios developer create cert Failed Exception:{e}")
result['return_info'] = "%s" % e
return False, result
def get_cert_obj_by_cid(self, cert_id):
def get_cert_obj_by_cid(self):
result = {}
try:
apple_obj = AppStoreConnectApi(self.issuer_id, self.private_key_id, self.p8key)
cert_obj = apple_obj.get_certificate_by_cid(cert_id)
cert_obj = apple_obj.get_certificate_by_cid(self.cert_id)
if cert_obj and cert_obj.id:
return True, result
else:
logger.info("ios developer get cert %s failed" % cert_id)
logger.info(f"ios developer get cert {self.cert_id} failed")
return False, result
except Exception as e:
logger.error("ios developer get cert %s Failed Exception:%s" % (cert_id, e))
logger.error(f"ios developer get cert {self.cert_id} Failed Exception:{e}")
result['return_info'] = "%s" % e
return False, result
def revoke_cert(self, cert_id):
def revoke_cert(self):
result = {}
try:
apple_obj = AppStoreConnectApi(self.issuer_id, self.private_key_id, self.p8key)
cert_obj = apple_obj.get_certificate_by_cid(cert_id)
cert_obj = apple_obj.get_certificate_by_cid(self.cert_id)
if cert_obj:
s_date = format_apple_date(cert_obj.expirationDate)
if s_date.timestamp() - datetime.datetime.now().timestamp() < 3600 * 24 * 3:
if apple_obj.revoke_certificate(cert_id):
logger.info("ios developer cert %s revoke" % cert_id)
if apple_obj.revoke_certificate(self.cert_id):
logger.info(f"ios developer cert {self.cert_id} revoke")
return True, result
else:
logger.info("ios developer cert %s not revoke.because expire time < 3 day " % cert_id)
logger.info(f"ios developer cert {self.cert_id} not revoke.because expire time < 3 day ")
return True, result
except Exception as e:
logger.error("ios developer cert %s revoke Failed Exception:%s" % (cert_id, e))
logger.error(f"ios developer cert {self.cert_id} revoke Failed Exception:{e}")
result['return_info'] = "%s" % e
return False, result
@ -252,12 +254,12 @@ class AppDeveloperApiV2(object):
certificates = apple_obj.get_all_certificates()
for cert_obj in certificates:
f_date = format_apple_date(cert_obj.expirationDate)
logger.info("%s-%s - %s " % (cert_obj.id, not_after.timestamp(), f_date.timestamp()))
logger.info(f"{cert_obj.id}-{not_after.timestamp()} - {f_date.timestamp()} ")
if not_after.timestamp() == f_date.timestamp():
return True, cert_obj
return False, result
except Exception as e:
logger.error("ios developer cert %s auto get Failed Exception:%s" % (111, e))
logger.error(f"ios developer cert {app_dev_pem} auto get Failed Exception:{e}")
result['return_info'] = "%s" % e
return False, result
@ -297,7 +299,7 @@ class AppDeveloperApiV2(object):
f.write(n)
return True, result
except Exception as e:
logger.error("ios developer make profile Failed Exception:%s" % e)
logger.error(f"app_id {app_obj.app_id} ios developer make profile Failed Exception:{e}")
result['return_info'] = "%s" % e
return False, result
@ -310,7 +312,7 @@ class AppDeveloperApiV2(object):
if apple_obj.delete_profile_by_id(profile_obj.id):
return True, profile_obj
except Exception as e:
logger.error("ios developer delete profile Failed Exception:%s" % e)
logger.error(f"ios developer delete profile Failed Exception:{e}")
result['return_info'] = "%s" % e
return False, result

@ -9,7 +9,7 @@ import logging
import paramiko, json
import socket
logger = logging.getLogger(__file__)
logger = logging.getLogger(__name__)
def default_result():
@ -109,7 +109,7 @@ def shell_command(cmdstrs, timeout):
out = out.strip(b'\n')
result['return_info'] = out
result['exit_code'] = child.returncode
logging.info(u'shell: %s - %s%s - %s%d' % (cmdstrs, 'return_info: ', out, 'exit_code: ', child.returncode))
logger.info(f'shell: {cmdstrs} - return_info:{out} - exit_code:{child.returncode}')
return result
@ -131,8 +131,6 @@ def use_user_pass(hostip, port, user, passwd, cmdstrs):
outs = outs.strip('\n')
result['return_info'] = outs
result['exit_code'] = out['status']
# logging.info(u'shell: %s - %s%s - %s%d' % (cmdstrs, 'return_info: ', out, 'exit_code: ', out['status']))
logger.info('host: %s user:%s - shell: %s - %s%s - %s%d' % (
hostip, user, cmdstrs, 'return_info: ', out, 'exit_code: ', out['status']))
logger.info(f'host: {hostip} user:{user} - shell: {cmdstrs} - return_info:{out} - exit_code:{out["status"]}')
conn.close()
return result

@ -6,7 +6,6 @@
import uuid, xmltodict, os, re, logging, time
from django.utils import timezone
import zipfile
from api.utils.response import BaseResponse
from fir_ser.settings import SUPER_SIGN_ROOT, MEDIA_ROOT, SERVER_DOMAIN, MOBILECONFIG_SIGN_SSL, MSGTEMPLATE
@ -23,7 +22,7 @@ from api.utils.baseutils import file_format_path, delete_app_profile_file, get_p
from api.utils.storage.storage import Storage
from django.core.cache import cache
logger = logging.getLogger(__file__)
logger = logging.getLogger(__name__)
def check_org_file(user_obj, org_file):
@ -41,9 +40,9 @@ def resign_by_app_id(app_obj, need_download_profile=True):
user_obj = app_obj.user_id
info_list = []
if app_obj.issupersign and user_obj.supersign_active:
for dappid_obj in DeveloperAppID.objects.filter(app_id=app_obj).all():
developer_obj = dappid_obj.developerid
developer_app_id = dappid_obj.aid
for developer_app_id_obj in DeveloperAppID.objects.filter(app_id=app_obj).all():
developer_obj = developer_app_id_obj.developerid
developer_app_id = developer_app_id_obj.aid
d_time = time.time()
if need_download_profile:
with cache.lock("%s_%s_%s" % ('download_profile', app_obj.app_id, developer_obj.issuer_id), timeout=60):
@ -77,59 +76,59 @@ def udid_bytes_to_dict(xml_stream):
for i in range(len(xml_dict['plist']['dict']['key'])):
new_uuid_info[xml_dict['plist']['dict']['key'][i].lower()] = xml_dict['plist']['dict']['string'][i]
except Exception as e:
logger.error("udid_xml_stream:%s Exception:%s" % (xml_stream, e))
logger.error(f"udid_xml_stream:{xml_stream} Exception:{e}")
return None
return new_uuid_info
def make_sign_udid_mobileconfig(udid_url, PayloadOrganization, appname):
def make_sign_udid_mobile_config(udid_url, payload_organization, app_name):
if MOBILECONFIG_SIGN_SSL.get("open"):
ssl_key_path = MOBILECONFIG_SIGN_SSL.get("ssl_key_path", None)
ssl_pem_path = MOBILECONFIG_SIGN_SSL.get("ssl_pem_path", None)
if ssl_key_path and ssl_pem_path and os.path.isfile(ssl_key_path) and os.path.isfile(ssl_pem_path):
mobileconfig_tmp_dir = os.path.join(SUPER_SIGN_ROOT, 'tmp', 'mobileconfig')
if not os.path.exists(mobileconfig_tmp_dir):
os.makedirs(mobileconfig_tmp_dir)
mobile_config_tmp_dir = os.path.join(SUPER_SIGN_ROOT, 'tmp', 'mobile_config')
if not os.path.exists(mobile_config_tmp_dir):
os.makedirs(mobile_config_tmp_dir)
mobileconfig_filename = PayloadOrganization + str(uuid.uuid1())
mobilconfig_path = os.path.join(mobileconfig_tmp_dir, mobileconfig_filename)
mobile_config_filename = payload_organization + str(uuid.uuid1())
mobile_config_path = os.path.join(mobile_config_tmp_dir, mobile_config_filename)
sign_mobilconfig_path = os.path.join(mobileconfig_tmp_dir, 'sign_' + mobileconfig_filename)
with open(mobilconfig_path, "w") as f:
f.write(make_udid_mobileconfig(udid_url, PayloadOrganization, appname))
sign_mobile_config_path = os.path.join(mobile_config_tmp_dir, 'sign_' + mobile_config_filename)
with open(mobile_config_path, "w") as f:
f.write(make_udid_mobile_config(udid_url, payload_organization, app_name))
status, result = ResignApp.sign_mobileconfig(mobilconfig_path, sign_mobilconfig_path, ssl_pem_path,
ssl_key_path)
status, result = ResignApp.sign_mobile_config(mobile_config_path, sign_mobile_config_path, ssl_pem_path,
ssl_key_path)
if status:
mobileconfig_body = open(sign_mobilconfig_path, 'rb')
mobile_config_body = open(sign_mobile_config_path, 'rb')
else:
logger.error(
"%s %s sign_mobileconfig failed ERROR:%s" % (PayloadOrganization, appname, result.get("err_info")))
return make_udid_mobileconfig(udid_url, PayloadOrganization, appname)
f"{payload_organization} {app_name} sign_mobile_config failed ERROR:{result.get('err_info')}")
return make_udid_mobile_config(udid_url, payload_organization, app_name)
return mobileconfig_body
return mobile_config_body
else:
logger.error("sign_mobileconfig %s or %s is not exists" % (ssl_key_path, ssl_pem_path))
return make_udid_mobileconfig(udid_url, PayloadOrganization, appname)
logger.error(f"sign_mobile_config {ssl_key_path} or {ssl_pem_path} is not exists")
return make_udid_mobile_config(udid_url, payload_organization, app_name)
else:
return make_udid_mobileconfig(udid_url, PayloadOrganization, appname)
return make_udid_mobile_config(udid_url, payload_organization, app_name)
def make_udid_mobileconfig(udid_url, PayloadOrganization, appname, PayloadUUID=uuid.uuid1(),
PayloadDescription='该文件仅用来获取设备ID,帮助用户安装授权',
PayloadDisplayName='设备安装授权'):
def make_udid_mobile_config(udid_url, payload_organization, app_name, payload_uuid=uuid.uuid1(),
payload_description='该文件仅用来获取设备ID,帮助用户安装授权',
display_name='设备安装授权'):
# <!--参考:https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/iPhoneOTAConfiguration/ConfigurationProfileExamples/ConfigurationProfileExamples.html-->
mobileconfig = '''<?xml version="1.0" encoding="UTF-8"?>
return f'''<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PayloadContent</key>
<dict>
<key>URL</key>
<string>%s</string>
<string>{udid_url}</string>
<key>DeviceAttributes</key>
<array>
<string>SERIAL</string>
@ -141,29 +140,27 @@ def make_udid_mobileconfig(udid_url, PayloadOrganization, appname, PayloadUUID=u
</array>
</dict>
<key>PayloadOrganization</key>
<string>%s</string>
<string>{payload_organization}</string>
<key>PayloadDisplayName</key>
<string>%s</string>
<string>{app_name}--{display_name}</string>
<key>PayloadVersion</key>
<integer>1</integer>
<key>PayloadUUID</key>
<string>%s</string>
<string>{payload_uuid}</string>
<key>PayloadIdentifier</key>
<string>%s.profile-service</string>
<string>{payload_organization}.profile-service</string>
<key>PayloadDescription</key>
<string>%s</string>
<string>{payload_description}</string>
<key>PayloadType</key>
<string>Profile Service</string>
</dict>
</plist>''' % (udid_url, PayloadOrganization, appname + " -- " + PayloadDisplayName, PayloadUUID, PayloadOrganization,
PayloadDescription)
return mobileconfig
</plist>'''
def get_post_udid_url(request, short):
server_domain = get_http_server_doamin(request)
PATH_INFO_lists = [server_domain, "udid", short]
udid_url = "/".join(PATH_INFO_lists)
server_domain = get_http_server_domain(request)
path_info_lists = [server_domain, "udid", short]
udid_url = "/".join(path_info_lists)
return udid_url
@ -189,24 +186,24 @@ def get_api_obj(auth):
def get_apple_udid_key(auth):
mpkey = ''
m_key = ''
if auth.get("issuer_id"):
mpkey = auth.get("issuer_id")
return mpkey
m_key = auth.get("issuer_id")
return m_key
def get_server_domain_from_request(request, server_domain):
if not server_domain or not server_domain.startswith("http"):
HTTP_HOST = request.META.get('HTTP_HOST')
SERVER_PROTOCOL = request.META.get('SERVER_PROTOCOL')
http_host = request.META.get('HTTP_HOST')
server_protocol = request.META.get('SERVER_PROTOCOL')
protocol = 'https'
if SERVER_PROTOCOL == 'HTTP/1.1':
if server_protocol == 'HTTP/1.1':
protocol = 'http'
server_domain = "%s://%s" % (protocol, HTTP_HOST)
server_domain = "%s://%s" % (protocol, http_host)
return server_domain
def get_http_server_doamin(request):
def get_http_server_domain(request):
server_domain = SERVER_DOMAIN.get('POST_UDID_DOMAIN', None)
return get_server_domain_from_request(request, server_domain)
@ -245,7 +242,7 @@ class IosUtils(object):
if self.developer_obj:
self.auth = get_auth_form_developer(self.developer_obj)
else:
logger.error("user %s has no actived apple developer" % self.user_obj)
logger.error(f"user {self.user_obj} has no active apple developer")
if self.user_obj.email:
if send_msg_over_limit("get", self.user_obj.email):
send_msg_over_limit("set", self.user_obj.email)
@ -253,15 +250,15 @@ class IosUtils(object):
% (
self.user_obj.first_name, self.app_obj.name))
else:
logger.error("user %s send msg failed. over limit" % self.user_obj)
logger.error(f"user {self.user_obj} send msg failed. over limit")
def get_developer_user_by_app_udid(self):
usedeviceobj = APPSuperSignUsedInfo.objects.filter(udid__udid=self.udid_info.get('udid'),
user_id=self.user_obj, developerid__is_actived=True,
developerid__certid__isnull=False).first()
use_device_obj = APPSuperSignUsedInfo.objects.filter(udid__udid=self.udid_info.get('udid'),
user_id=self.user_obj, developerid__is_actived=True,
developerid__certid__isnull=False).first()
# 只要账户下面存在udid,就可以使用该苹果开发者账户,避免多个开发者账户下面出现同一个udid
if usedeviceobj:
developer_obj = usedeviceobj.developerid
if use_device_obj:
developer_obj = use_device_obj.developerid
else:
developer_udid_obj = UDIDsyncDeveloper.objects.filter(udid=self.udid_info.get('udid'),
developerid__is_actived=True,
@ -271,9 +268,7 @@ class IosUtils(object):
else:
for developer_obj in AppIOSDeveloperInfo.objects.filter(user_id=self.user_obj, is_actived=True,
certid__isnull=False).order_by("created_time"):
usable_number = developer_obj.usable_number
flyapp_used = get_developer_udided(developer_obj)[1]
if flyapp_used < usable_number:
if get_developer_udided(developer_obj)[1] < developer_obj.usable_number:
return developer_obj
return None
return developer_obj
@ -307,19 +302,20 @@ class IosUtils(object):
def exec_download_profile(app_obj, developer_obj, udid_info, sign_try_attempts=3):
result = {}
developer_app_id = None
add_did_flag = False
auth = get_auth_form_developer(developer_obj)
while sign_try_attempts > 0:
logger.info("exec_download_profile appid:%s developer:%s sign_try_attempts:%s" % (
app_obj, developer_obj, sign_try_attempts))
logger.info(
f"exec_download_profile app_id:{app_obj} developer:{developer_obj} sign_try_attempts:{sign_try_attempts}")
device_id_list = DeveloperDevicesID.objects.filter(app_id=app_obj,
developerid=developer_obj).values_list('did')
device_id_lists = [did[0] for did in device_id_list]
developer_app_id = None
developer_appid_obj = DeveloperAppID.objects.filter(developerid=developer_obj,
app_id=app_obj).first()
if developer_appid_obj:
developer_app_id = developer_appid_obj.aid
add_did_flag = False
sync_device_obj = None
developer_app_id_obj = DeveloperAppID.objects.filter(developerid=developer_obj,
app_id=app_obj).first()
if developer_app_id_obj:
developer_app_id = developer_app_id_obj.aid
if udid_info:
sync_device_obj = UDIDsyncDeveloper.objects.filter(udid=udid_info.get('udid'),
developerid=developer_obj).first()
@ -327,23 +323,22 @@ class IosUtils(object):
device_id_lists.append(sync_device_obj.serial)
udid_info = None
add_did_flag = True
logger.info(
"app %s device %s already in developer %s" % (app_obj, sync_device_obj.serial, developer_obj))
logger.info(f"app {app_obj} device {sync_device_obj.serial} already in developer {developer_obj}")
status, result = get_api_obj(auth).get_profile(app_obj, udid_info,
get_profile_full_path(developer_obj, app_obj),
auth, developer_app_id, device_id_lists)
if add_did_flag:
if add_did_flag and sync_device_obj:
result['did'] = sync_device_obj.serial
result['did_exists'] = True
if not status:
sign_try_attempts -= 1
logger.warning("app %s developer %s sign failed %s .try again " % (app_obj, developer_obj, result))
logger.warning(f"app {app_obj} developer {developer_obj} sign failed {result} .try again ")
time.sleep(3)
else:
sign_try_attempts = -1
if sign_try_attempts != -1:
logger.error("app %s developer %s sign failed %s" % (app_obj, developer_obj, result))
logger.error(f"app {app_obj} developer {developer_obj} sign failed {result}")
developer_obj.is_actived = False
developer_obj.save()
send_ios_developer_active_status(developer_obj.user_id,
@ -394,11 +389,10 @@ class IosUtils(object):
status, result = resign_app_obj.sign(get_profile_full_path(developer_obj, app_obj), org_file, new_file,
properties_info)
if status:
logger.info("%s %s %s sign_ipa success" % (user_obj, developer_obj, app_obj))
logger.info(f"{user_obj} {developer_obj} {app_obj} sign_ipa success")
return True, result
else:
logger.error(
"%s %s %s sign_ipa failed ERROR:%s" % (user_obj, developer_obj, app_obj, result.get("err_info")))
logger.error(f"{user_obj} {developer_obj} {app_obj} sign_ipa failed ERROR:{result.get('err_info')}")
return False, result
@staticmethod
@ -423,8 +417,8 @@ class IosUtils(object):
if appsupersign_obj.count() == 0:
developer_obj = self.developer_obj
developer_obj.use_number = developer_obj.use_number + 1
logger.info("developer %s use_number+1 now %s udid %s app_id %s" % (
developer_obj, developer_obj.use_number, self.udid_info.get('udid'), self.app_obj))
logger.info(
f"developer {developer_obj} use_number+1 now {developer_obj.use_number} udid {self.udid_info.get('udid')} app_id {self.app_obj}")
developer_obj.save()
if not appsupersign_obj.filter(app_id=self.app_obj, user_id=self.user_obj).first():
@ -451,13 +445,13 @@ class IosUtils(object):
d_result = {'code': 0, 'msg': 'success'}
start_time = time.time()
if download_flag:
logger.info("app_id %s download profile success. time:%s" % (app_obj, start_time - d_time))
logger.info(f"app_id {app_obj} download profile success. time:{start_time - d_time}")
random_file_name = make_from_user_uuid(user_obj)
release_obj = AppReleaseInfo.objects.filter(app_id=app_obj, is_master=True).first()
status, e_result = IosUtils.exec_sign(user_obj, app_obj, developer_obj, random_file_name, release_obj)
if status:
s_time1 = time.time()
logger.info("app_id %s exec sign ipa success. time:%s" % (app_obj, s_time1 - start_time))
logger.info(f"app_id {app_obj} exec sign ipa success. time:{s_time1 - start_time}")
if resign:
IosUtils.update_sign_file_name(user_obj, app_obj, developer_obj, release_obj, random_file_name)
else:
@ -465,12 +459,12 @@ class IosUtils(object):
else:
return status, e_result
else:
msg = "app_id %s download profile failed. %s time:%s" % (app_obj, result, time.time() - start_time)
msg = f"app_id {app_obj} download profile failed. {result} time:{time.time() - start_time}"
d_result['code'] = 1002
d_result['msg'] = msg
logger.error(d_result)
return False, d_result
msg = "app_id %s developer %s sign end... time:%s" % (app_obj, developer_obj, time.time() - start_time)
msg = f"app_id {app_obj} developer {developer_obj} sign end... time:{time.time() - start_time}"
logger.info(msg)
d_result['msg'] = msg
return True, d_result
@ -627,16 +621,16 @@ class IosUtils(object):
@staticmethod
def clean_app_by_user_obj(app_obj, user_obj):
'''
"""
该APP为超级签删除app的时候需要清理一下开发者账户里面的profile bundleid
:param app_obj:
:param user_obj:
:return:
'''
SuperSign_obj_lists = list(
"""
super_sign_obj_lists = list(
set(APPSuperSignUsedInfo.objects.values_list("developerid").filter(user_id=user_obj, app_id=app_obj)))
for SuperSign_obj in SuperSign_obj_lists:
developer_obj = AppIOSDeveloperInfo.objects.filter(pk=SuperSign_obj[0]).first()
for super_sign_obj in super_sign_obj_lists:
developer_obj = AppIOSDeveloperInfo.objects.filter(pk=super_sign_obj[0]).first()
if developer_obj:
IosUtils.clean_app_by_developer_obj(app_obj, developer_obj)
delete_app_to_dev_and_file(developer_obj, app_obj.id)
@ -655,13 +649,13 @@ class IosUtils(object):
@staticmethod
def clean_developer(developer_obj, user_obj, cert_id=None):
'''
"""
根据消耗记录 删除该苹果账户下所有信息
:param user_obj:
:param cert_id:
:param developer_obj:
:return:
'''
"""
for APPToDeveloper_obj in APPToDeveloper.objects.filter(developerid=developer_obj):
app_obj = APPToDeveloper_obj.app_id
IosUtils.clean_app_by_developer_obj(app_obj, developer_obj, cert_id)
@ -688,12 +682,11 @@ class IosUtils(object):
@staticmethod
def active_developer(developer_obj):
'''
"""
激活开发者账户
:param developer_obj:
:param code:
:return:
'''
"""
auth = get_auth_form_developer(developer_obj)
app_api_obj = get_api_obj(auth)
status, result = app_api_obj.active()
@ -742,7 +735,7 @@ class IosUtils(object):
def revoke_developer_cert(developer_obj, user_obj):
auth = get_auth_form_developer(developer_obj)
app_api_obj = get_api_obj(auth)
status, result = app_api_obj.revoke_cert(developer_obj.certid)
status, result = app_api_obj.revoke_cert()
if not status:
logger.warning('%s revoke cert failed,but i need clean cert_id %s' % (developer_obj.issuer_id, result))
AppIOSDeveloperInfo.objects.filter(user_id=user_obj, issuer_id=auth.get("issuer_id")).update(
@ -755,14 +748,14 @@ class IosUtils(object):
# 暂时无用
auth = get_auth_form_developer(developer_obj)
app_api_obj = get_api_obj(auth)
status, result = app_api_obj.get_cert_obj_by_cid(developer_obj.certid)
status, result = app_api_obj.get_cert_obj_by_cid()
if not status:
AppIOSDeveloperInfo.objects.filter(user_id=user_obj, issuer_id=auth.get("issuer_id")).update(
certid=None, cert_expire_time=None)
return status, result
@staticmethod
def auto_get_certid_by_p12(developer_obj, user_obj):
def auto_get_cert_id_by_p12(developer_obj, user_obj):
auth = get_auth_form_developer(developer_obj)
app_api_obj = get_api_obj(auth)
file_format_path_name = file_format_path(user_obj, auth)

@ -13,7 +13,7 @@ import jwt
import logging
from collections import namedtuple
logger = logging.getLogger(__file__)
logger = logging.getLogger(__name__)
# https://developer.apple.com/documentation/appstoreconnectapi/creating_api_keys_for_app_store_connect_api
@ -22,7 +22,7 @@ logger = logging.getLogger(__file__)
def request_format_log(req):
try:
logger.info("url:%s header:%s code:%s body:%s" % (req.url, req.headers, req.status_code, req.content))
logger.info(f"url:{req.url} header:{req.headers} code:{req.status_code} body:{req.content}")
except Exception as e:
logger.error(e)
return req
@ -273,6 +273,7 @@ class BundleIDsCapabilityAPI(object):
def disable_capability(self, bundle_id, capability_type):
"""
:param capability_type:
:param bundle_id:
:return:
204 No Content
@ -652,13 +653,13 @@ class AppStoreConnectApi(DevicesAPI, BundleIDsAPI, BundleIDsCapabilityAPI, Profi
JWT_ALG = 'ES256'
def __init__(self, issuer_id, private_key_id, p8_private_key, exp_seconds=1200):
'''
"""
根据 Apple 文档会话最长持续时间为 20 分钟https : //developer.apple.com/documentation/appstoreconnectapi/generating_tokens_for_api_requests
:param issuer_id:
:param private_key_id:
:param p8_private_key:
:param exp_seconds: max 20*60
'''
"""
self.issuer_id = issuer_id
self.private_key_id = private_key_id
self.p8_private_key = p8_private_key
@ -678,10 +679,10 @@ class AppStoreConnectApi(DevicesAPI, BundleIDsAPI, BundleIDsCapabilityAPI, Profi
self.rate_limit_info[limit_info_list[0]] = limit_info_list[1]
user_rem_info = self.rate_limit_info
if int(user_rem_info.get('user-hour-rem')) < 3595:
logger.warning("user-hour-rem over limit. so get jwt headers")
logger.warning(f"user-hour-rem over limit. so get jwt headers")
self.__init__(self.issuer_id, self.private_key_id, self.p8_private_key)
self.rate_limit_info = user_rem_info
logger.info("rate_limit_info:%s" % self.rate_limit_info)
logger.info(f"rate_limit_info:{self.rate_limit_info}")
def __make_jwt_headers(self):
data = {
@ -700,7 +701,7 @@ class AppStoreConnectApi(DevicesAPI, BundleIDsAPI, BundleIDsCapabilityAPI, Profi
}
self.headers = headers
def __base_format(self, stype, req, success_code):
def __base_format(self, s_type, req, success_code):
# self.__set_rate_limit_info(req.headers)
if req.status_code == success_code:
req_data = req.json()
@ -709,20 +710,20 @@ class AppStoreConnectApi(DevicesAPI, BundleIDsAPI, BundleIDsCapabilityAPI, Profi
obj = None
if isinstance(data, dict):
data = [data]
if stype == 'devices':
if s_type == 'devices':
obj = Devices.from_json_list(data)
elif stype == 'bundleIds':
elif s_type == 'bundleIds':
obj = BundleIds.from_json_list(data)
elif stype == 'profiles':
elif s_type == 'profiles':
obj = Profiles.from_json_list(data)
elif stype == 'certificates':
elif s_type == 'certificates':
obj = Certificates.from_json_list(data)
if len(obj) == 1:
return obj[0]
return obj
else:
# self.__init_jwt_headers()
raise Exception('error: %s' % (req.text))
raise Exception(f'error instance: {req.text}')
elif req.status_code == 401: # 授权问题
raise Exception(req.text)
elif req.status_code == 429: # 请求超过每小时限制 {'user-hour-lim': '3600', 'user-hour-rem': '3586'}
@ -809,9 +810,9 @@ class AppStoreConnectApi(DevicesAPI, BundleIDsAPI, BundleIDsCapabilityAPI, Profi
for capability in capability_list:
req = super().enable_capability(bundle_id, capability)
if self.__do_success(req, 201):
logger.info("%s enable_capability %s success" % (bundle_id, capability))
logger.info(f"{bundle_id} enable_capability {capability} success")
else:
logger.warning("%s enable_capability %s failed %s" % (bundle_id, capability, req.content))
logger.warning(f"{bundle_id} enable_capability {capability} failed {req.content}")
return True
def disable_capability_by_s_type(self, bundle_id, s_type=len(capability) - 1):
@ -820,13 +821,12 @@ class AppStoreConnectApi(DevicesAPI, BundleIDsAPI, BundleIDsCapabilityAPI, Profi
for capability in capability_list:
req = super().disable_capability(bundle_id, capability)
if self.__do_success(req, 204):
logger.info("%s enable_capability %s success" % (bundle_id, capability))
logger.info(f"{bundle_id} enable_capability {capability} success")
else:
logger.warning("%s enable_capability %s failed %s" % (bundle_id, capability, req.content))
logger.warning(f"{bundle_id} enable_capability {capability} failed {req.content}")
return True
def enable_push_vpn_capability(self, bundle_id):
# 'PUSH_NOTIFICATIONS', # PERSONAL_VPN , NETWORK_EXTENSIONS
req = super().enable_capability(bundle_id, 'PUSH_NOTIFICATIONS')
if self.__do_success(req, 201):
req = super().enable_capability(bundle_id, 'PERSONAL_VPN')
@ -835,7 +835,6 @@ class AppStoreConnectApi(DevicesAPI, BundleIDsAPI, BundleIDsCapabilityAPI, Profi
return False
def disable_push_vpn_capability(self, bundle_id):
# 'PUSH_NOTIFICATIONS', # PERSONAL_VPN
req = super().disable_capability(bundle_id, 'PUSH_NOTIFICATIONS')
if self.__do_success(req, 204):
req = super().disable_capability(bundle_id, 'PERSONAL_VPN')

@ -50,23 +50,70 @@ def delete_app_profile_file(developer_obj, app_obj):
if os.path.isfile(file):
os.remove(file)
except Exception as e:
logger.error("delete_app_profile_file developer_obj:%s app_obj:%s file:%s Exception:%s" % (
developer_obj, app_obj, file, e))
logger.error(
f"delete_app_profile_file developer_obj:{developer_obj} app_obj:{app_obj} file:{file} Exception:{e}")
def is_valid_domain(value):
pattern = re.compile(
r'^(([a-zA-Z]{1})|([a-zA-Z]{1}[a-zA-Z]{1})|'
r'([a-zA-Z]{1}[0-9]{1})|([0-9]{1}[a-zA-Z]{1})|'
r'^(([a-zA-Z])|([a-zA-Z][a-zA-Z])|'
r'([a-zA-Z][0-9])|([0-9][a-zA-Z])|'
r'([a-zA-Z0-9][-_.a-zA-Z0-9]{0,61}[a-zA-Z0-9]))\.'
r'([a-zA-Z]{2,13}|[a-zA-Z0-9-]{2,30}.[a-zA-Z]{2,3})$'
)
return True if pattern.match(value) else False
def is_telephone_number(telephone):
if len(telephone) == 11:
if re.match(r"^1(?:749)\d{7}$", telephone):
return 'MSC' # 海事卫星通信的
elif re.match(r"^174(?:0[6-9]|1[0-2])\d{6}$", telephone):
return 'MCC' # 工信部应急通信的
elif re.match(r"^1(?:349)\d{7}$", telephone):
return 'CM_SMC' # 中国移动卫星通信
elif re.match(r"^1(?:740[0-5])\d{6}$", telephone):
return 'CT_SMC' # 中国电信卫星通信
elif re.match(r"^1(?:47)\d{8}$", telephone):
return 'CM_IDC' # 中国移动上网数据卡
elif re.match(r"^1(?:45)\d{8}$", telephone):
return 'CU_IDC' # 中国联通上网数据卡
elif re.match(r"^1(?:49)\d{8}$", telephone):
return 'CT_IDC' # 中国电信上网数据卡
elif re.match(r"^1(?:70[356]|65\d)\d{7}$", telephone):
return 'CM_VNO' # 中国移动虚拟运营商
elif re.match(r"^1(?:70[4,7-9]|71\d|67\d)\d{7}$", telephone):
return 'CU_VNO' # 中国联通虚拟运营商
elif re.match(r"^1(?:70[0-2]|62\d)\d{7}$", telephone):
return 'CT_VNO' # 中国电信虚拟运营商
elif re.match(r"^1(?:34[0-8]|3[5-9]\d|5[0-2,7-9]\d|7[28]\d|8[2-4,7-8]\d|9[5,7,8]\d)\d{7}$", telephone):
return 'CM_BO' # 中国移动
elif re.match(r"^1(?:3[0-2]|[578][56]|66|96)\d{8}$", telephone):
return 'CU_BO' # 中国联通
elif re.match(r"^1(?:33|53|7[37]|8[019]|9[0139])\d{8}$", telephone):
return 'CT_BO' # 中国电信
elif re.match(r"^1(?:92)\d{8}$", telephone):
return 'CBN_BO' # 中国广电
else:
return False
elif len(telephone) == 13:
if re.match(r"^14(?:40|8\d)\d{9}$", telephone):
return 'CM_IoT' # 中国移动物联网数据卡
elif re.match(r"^14(?:00|6\d)\d{9}$", telephone):
return 'CU_IoT' # 中国联通物联网数据卡
elif re.match(r"^14(?:10)\d{9}$", telephone):
return 'CT_IoT' # 中国电信物联网数据卡
else:
return False
else:
return False
def is_valid_phone(value):
phone_pat = re.compile('^(13\d|14[5|7]|15\d|166|17[3|6|7]|18\d)\d{8}$')
return True if str(value) and re.search(phone_pat, str(value)) else False
# phone_pat = re.compile('^(13\d|14[5|7]|15\d|166|17[3|6|7]|18\d)\d{8}$')
# return True if str(value) and re.search(phone_pat, str(value)) else False
logger.info(f"valid phone {value}")
return str(value) and is_telephone_number(str(value))
def is_valid_email(email):
@ -112,9 +159,9 @@ def get_cname_from_domain(domain):
while count:
try:
dns_resolver.nameservers = dns_list[len(dns_list) - count]
return dns_resolver.query(domain, 'CNAME')[0].to_text()
return dns_resolver.resolve(domain, 'CNAME')[0].to_text()
except Exception as e:
logger.error("dns %s resolve %s failed Exception:%s" % (dns_resolver.nameservers, domain, e))
logger.error(f"dns {dns_resolver.nameservers} resolve {domain} failed Exception:{e}")
count -= 1
time.sleep(0.3)
if count <= 0:

@ -13,7 +13,7 @@ from fir_ser.settings import CACHE_KEY_TEMPLATE, SYNC_CACHE_TO_DATABASE, SUPER_S
import time, os
import logging
logger = logging.getLogger(__file__)
logger = logging.getLogger(__name__)
def sync_download_times():
@ -23,7 +23,7 @@ def sync_download_times():
count_hits = cache.get(app_download)
app_id = app_download.split(down_tem_key)[1].strip('_')
Apps.objects.filter(app_id=app_id).update(count_hits=count_hits)
logger.info("sync_download_times app_id:%s count_hits:%s" % (app_id, count_hits))
logger.info(f"sync_download_times app_id:{app_id} count_hits:{count_hits}")
def auto_clean_upload_tmp_file():
@ -40,10 +40,10 @@ def auto_clean_upload_tmp_file():
filename = data.get("filename", None)
if filename:
storage.delete_file(filename)
logger.info("auto_clean_upload_tmp_file delete_file :%s " % (filename))
logger.info(f"auto_clean_upload_tmp_file delete_file :{filename}")
cache.delete(upload_tem_file_key)
logger.info("auto_clean_upload_tmp_file upload_tem_file_key :%s " % (upload_tem_file_key))
logger.info(f"auto_clean_upload_tmp_file upload_tem_file_key :{upload_tem_file_key}")
def auto_delete_tmp_file():
@ -57,7 +57,7 @@ def auto_delete_tmp_file():
try:
os.remove(file_path)
except Exception as e:
logger.error("auto_delete_tmp_file %s Failed . Exception %s" % (file_path, e))
logger.error(f"auto_delete_tmp_file {file_path} Failed . Exception {e}")
def auto_check_ios_developer_active():
@ -66,8 +66,7 @@ def auto_check_ios_developer_active():
userinfo = ios_developer.user_id
if userinfo.supersign_active:
status, result = IosUtils.active_developer(ios_developer)
msg = "auto_check_ios_developer_active user:%s ios.developer:%s status:%s result:%s" % (
userinfo, ios_developer, status, result)
msg = f"auto_check_ios_developer_active user:{userinfo} ios.developer:{ios_developer} status:{status} result:{result}"
if status:
logger.info(msg)
else:

@ -81,14 +81,16 @@ class GeetestLib:
self.libResult.set_all(1, data, "")
# 正常流程下(即验证初始化成功),二次验证
def successValidate(self, challenge, validate, seccode, param_dict={}):
def success_validate(self, challenge, validate, seccode, param_dict=None):
if param_dict is None:
param_dict = {}
self.gtlog(
"successValidate(): 开始二次验证 正常模式, challenge={0}, validate={1}, seccode={2}.".format(challenge, validate,
seccode))
"success_validate(): 开始二次验证 正常模式, challenge={0}, validate={1}, seccode={2}.".format(challenge, validate,
seccode))
if not self.check_param(challenge, validate, seccode):
self.libResult.set_all(0, "", "正常模式,本地校验,参数challenge、validate、seccode不可为空")
else:
response_seccode = self.requestValidate(challenge, validate, seccode, param_dict)
response_seccode = self.request_validate(challenge, validate, seccode, param_dict)
if not response_seccode:
self.libResult.set_all(0, "", "请求极验validate接口失败")
elif response_seccode == "false":
@ -100,19 +102,19 @@ class GeetestLib:
# 异常流程下(即验证初始化失败,宕机模式),二次验证
# 注意:由于是宕机模式,初衷是保证验证业务不会中断正常业务,所以此处只作简单的参数校验,可自行设计逻辑。
def failValidate(self, challenge, validate, seccode):
def fail_validate(self, challenge, validate, seccode):
self.gtlog(
"failValidate(): 开始二次验证 宕机模式, challenge={0}, validate={1}, seccode={2}.".format(challenge, validate,
seccode))
"fail_validate(): 开始二次验证 宕机模式, challenge={0}, validate={1}, seccode={2}.".format(challenge, validate,
seccode))
if not self.check_param(challenge, validate, seccode):
self.libResult.set_all(0, "", "宕机模式,本地校验,参数challenge、validate、seccode不可为空.")
else:
self.libResult.set_all(1, "", "")
self.gtlog("failValidate(): 二次验证 宕机模式, lib包返回信息={0}.".format(self.libResult))
self.gtlog("fail_validate(): 二次验证 宕机模式, lib包返回信息={0}.".format(self.libResult))
return self.libResult
# 向极验发送二次验证的请求,POST方式
def requestValidate(self, challenge, validate, seccode, param_dict):
def request_validate(self, challenge, validate, seccode, param_dict):
param_dict.update(
{"seccode": seccode, "json_format": self.JSON_FORMAT, "challenge": challenge, "sdk": self.VERSION,
"captchaid": self.geetest_id})

@ -12,7 +12,7 @@ from fir_ser.settings import GEETEST_ID, GEETEST_KEY, GEETEST_BYPASS_URL, \
GEETEST_BYPASS_STATUS_KEY
from api.utils.geetest.geetest_lib import GeetestLib
logger = logging.getLogger(__file__)
logger = logging.getLogger(__name__)
# 发送bypass请求,获取bypass状态并进行缓存(如何缓存可根据自身情况合理选择,这里是使用redis进行缓存)
@ -22,16 +22,16 @@ def check_bypass_status():
try:
response = requests.get(url=GEETEST_BYPASS_URL, params=params)
except Exception as e:
logger.error("check_bypass_status failed Exception:%s" % e)
logger.error(f"check_bypass_status failed Exception:{e}")
if response and response.status_code == 200:
logger.debug("check_bypass_status success %s" % response.content)
logger.debug(f"check_bypass_status success {response.content}")
bypass_status_str = response.content.decode("utf-8")
bypass_status = json.loads(bypass_status_str).get("status")
redis_connect.set(GEETEST_BYPASS_STATUS_KEY, bypass_status)
else:
bypass_status = "fail"
redis_connect.set(GEETEST_BYPASS_STATUS_KEY, bypass_status)
logger.debug("bypass状态已经获取并存入redis,当前状态为 {}".format(bypass_status))
logger.debug(f"bypass状态已经获取并存入redis,当前状态为 {bypass_status}")
# 从缓存中取出当前缓存的bypass状态(success/fail)
@ -70,13 +70,13 @@ def second_validate(rdata):
bypass_status = get_bypass_cache()
gt_lib = GeetestLib(GEETEST_ID, GEETEST_KEY)
if bypass_status == "success":
result = gt_lib.successValidate(challenge, validate, seccode)
result = gt_lib.success_validate(challenge, validate, seccode)
else:
result = gt_lib.failValidate(challenge, validate, seccode)
result = gt_lib.fail_validate(challenge, validate, seccode)
# 注意,不要更改返回的结构和值类型
if result.status == 1:
response = {"result": "success", "version": GeetestLib.VERSION}
else:
response = {"result": "fail", "version": GeetestLib.VERSION, "msg": result.msg}
logger.info("geetest second_validate info %s" % response)
logger.info(f"geetest second_validate info {response}")
return response

@ -1,7 +1,7 @@
from django.utils.deprecation import MiddlewareMixin
import logging
logger = logging.getLogger(__file__)
logger = logging.getLogger(__name__)
class CorsMiddleWare(MiddlewareMixin):

@ -13,7 +13,7 @@ from api.utils.storage.caches import update_order_info, update_order_status
import json
import logging
logger = logging.getLogger(__file__)
logger = logging.getLogger(__name__)
class Alipay(object):
@ -56,7 +56,7 @@ class Alipay(object):
signature = data.pop("sign")
success = self.alipay.verify(data, signature)
if success and data["trade_status"] in ("TRADE_SUCCESS", "TRADE_FINISHED"):
logger.info("付款成功,等待下一步验证 %s" % data)
logger.info(f"付款成功,等待下一步验证 {data}")
app_id = data.get("app_id", "")
if app_id == self.ali_config.get("APP_ID"):
out_trade_no = data.get("out_trade_no", "") # 服务器订单号
@ -67,15 +67,15 @@ class Alipay(object):
payment_number = data.get("trade_no", "")
return update_order_info(user_id, out_trade_no, payment_number, 1)
else:
logger.error("passback_params %s user_id not exists" % passback_params)
logger.error(f"passback_params {passback_params} user_id not exists")
else:
logger.error("APP_ID 校验失败 response: %s server: %s" % (app_id, self.ali_config.get("APP_ID")))
logger.error(f"APP_ID 校验失败 response: {app_id} server: {self.ali_config.get('APP_ID')}")
return False
def update_order_status(self, out_trade_no):
data = self.alipay.api_alipay_trade_query(out_trade_no=out_trade_no)
code = data.get("code", '')
logger.info("out_trade_no: %s info:%s" % (out_trade_no, data))
logger.info(f"out_trade_no: {out_trade_no} info:{data}")
if code == '10000':
trade_status = data.get("trade_status", '')
if trade_status in ['TRADE_SUCCESS']:

@ -210,7 +210,6 @@ class BaseAliPay:
data = self.build_body(api_name, biz_content, **kwargs)
# alipay.trade.query => alipay_trade_query_response
response_type = api_name.replace(".", "_") + "_response"
print(data)
return self.verified_sync_response(data, response_type)
def api_alipay_trade_wap_pay(

@ -10,7 +10,7 @@ from api.utils.storage.caches import update_order_info, update_order_status
import json
import logging
logger = logging.getLogger(__file__)
logger = logging.getLogger(__name__)
class Weixinpay(object):
@ -54,7 +54,7 @@ class Weixinpay(object):
}
result = self.wxpay.decrypt_callback(headers, request.body.decode('utf-8'))
if result:
logger.info("付款成功,等待下一步验证 %s" % result)
logger.info(f"付款成功,等待下一步验证 {result}")
data = json.loads(result)
passback_params = data.get("attach", "")
out_trade_no = data.get("out_trade_no", "")
@ -64,16 +64,16 @@ class Weixinpay(object):
transaction_id = data.get("transaction_id", "")
return update_order_info(user_id, out_trade_no, transaction_id, 0)
else:
logger.error("passback_params %s user_id not exists" % passback_params)
logger.error(f"passback_params {passback_params} user_id not exists")
else:
logger.error("消息解密失败")
logger.error(f"消息解密失败 {request.body}")
return False
def update_order_status(self, out_trade_no):
code, data = self.wxpay.query(out_trade_no=out_trade_no)
# (0, '交易成功'), (1, '待支付'), (2, '订单已创建'), (3, '退费申请中'), (4, '已退费'), (5, '主动取消'), (6, '超时取消')
data = json.loads(data)
logger.info("out_trade_no: %s info:%s" % (out_trade_no, data))
logger.info(f"out_trade_no: {out_trade_no} info:{data}")
if code == 200:
trade_status = data.get("trade_state", '')
if trade_status in ['SUCCESS']:

@ -1,11 +1,10 @@
# -*- coding: utf-8 -*-
import json
from enum import Enum
from .core import Core, RequestType
class WeChatPay():
class WeChatPay(object):
def __init__(self,
wechatpay_type,
mchid,
@ -17,10 +16,10 @@ class WeChatPay():
"""
:param wechatpay_type: 微信支付类型示例值WeChatPayType.MINIPROG
:param mchid: 直连商户号示例值'1230000109'
:param mch_private_key: 商户证书私钥示例值'MIIEvwIBADANBgkqhkiG9w0BAQE...'
:param mch_key_serial_no: 商户证书序列号示例值'444F4864EA9B34415...'
:param parivate_key: 商户证书私钥示例值'MIIEvwIBADANBgkqhkiG9w0BAQE...'
:param cert_serial_no: 商户证书序列号示例值'444F4864EA9B34415...'
:param appid: 应用ID示例值'wxd678efh567hg6787'
:param mch_apiv3_key: 商户APIv3密钥示例值'a12d3924fd499edac8a5efc...'
:param apiv3_key: 商户APIv3密钥示例值'a12d3924fd499edac8a5efc...'
:param notify_url: 通知地址示例值'https://www.weixin.qq.com/wxpay/pay.php'
"""
self._type = wechatpay_type
@ -58,10 +57,7 @@ class WeChatPay():
:param settle_info: 结算信息示例值{'profit_sharing':False}
:param notify_url: 通知地址示例值'https://www.weixin.qq.com/wxpay/pay.php'
"""
params = {}
params['appid'] = self._appid
params['mchid'] = self._mchid
params['notify_url'] = notify_url or self._notify_url
params = {'appid': self._appid, 'mchid': self._mchid, 'notify_url': notify_url or self._notify_url}
if description:
params.update({'description': description})
else:
@ -88,6 +84,7 @@ class WeChatPay():
params.update({'detail': detail})
if settle_info:
params.update({'settle_info': settle_info})
path = ""
if self._type in [WeChatPayType.JSAPI, WeChatPayType.MINIPROG]:
if not payer:
raise Exception('payer is not assigned')
@ -100,7 +97,10 @@ class WeChatPay():
path = '/v3/pay/transactions/h5'
elif self._type == WeChatPayType.NATIVE:
path = '/v3/pay/transactions/native'
return self._core.request(path, method=RequestType.POST, data=params)
if path:
return self._core.request(path, method=RequestType.POST, data=params)
else:
raise Exception('path is not assigned')
def close(self, out_trade_no):
"""关闭订单
@ -145,8 +145,7 @@ class WeChatPay():
:param goods_detail: 退款商品示例值{'merchant_goods_id':'1217752501201407033233368018', 'wechatpay_goods_id':'1001', 'goods_name':'iPhone6s 16G', 'unit_price':528800, 'refund_amount':528800, 'refund_quantity':1}
:param notify_url: 通知地址示例值'https://www.weixin.qq.com/wxpay/pay.php'
"""
params = {}
params['notify_url'] = notify_url or self._notify_url
params = {'notify_url': notify_url or self._notify_url}
if out_refund_no:
params.update({'out_refund_no': out_refund_no})
else:
@ -281,8 +280,7 @@ class WeChatPay():
:param sub_orders: 子单信息, 示例值[{'mchid': '1900000109', 'out_trade_no': '20150806125346'}]
:param combine_appid: 合单商户appid, 示例值'wxd678efh567hg6787'
"""
params = {}
params['combine_appid'] = combine_appid or self._appid
params = {'combine_appid': combine_appid or self._appid}
if not combine_out_trade_no:
raise Exception('combine_out_trade_no is not assigned.')

@ -10,71 +10,74 @@ from .jiguangApi import JiGuangMsgSender
from fir_ser.settings import THIRD_PART_CONFIG
import logging
logger = logging.getLogger(__file__)
logger = logging.getLogger(__name__)
def get_default_sender(send_type):
"""
sender_type :
0: 邮件
1: 阿里云
2: 极光
"""
sender_lists = THIRD_PART_CONFIG.get('sender')
for sender in sender_lists:
if sender.get("active", None):
sender_type = sender.get('type', None)
auth = sender.get('auth', {})
if sender_type == 0 and send_type == 0:
return EmailMsgSender(**auth)
if sender_type == 1:
return AliMsgSender(**auth)
elif sender_type == 2:
return JiGuangMsgSender(**auth)
else:
continue
return None
def get_sms_sender():
return get_default_sender(1)
def get_email_sender():
return get_default_sender(0)
class SendMessage(object):
def __init__(self, type):
'''
:param type: sms or email
'''
self.type = type
def __init__(self, send_type):
"""
:param send_type: sms or email
"""
self.send_type = send_type
try:
if type == 'sms':
self.sender = self._get_sms_sender()
elif type == 'email':
self.sender = self._get_email_sender()
if send_type == 'sms':
self.sender = get_sms_sender()
elif send_type == 'email':
self.sender = get_email_sender()
if self.sender is None:
raise
except Exception as e:
logger.error("get %s sender failed Exception:%s" % (type, e))
logger.error(f"get {send_type} sender failed Exception:{e}")
self.sender = None
def send_register_msg(self, target, code):
status, msg = self.sender.send_register_msg(target, code)
logger.info("send_register_msg target:%s code:%s status:%s msg:%s" % (target, code, status, msg))
logger.info(f"send_register_msg target:{target} code:{code} status:{status} msg:{msg}")
return status, msg
def send_change_msg(self, target, code):
status, msg = self.sender.send_change_msg(target, code)
logger.info("send_change_msg target:%s code:%s status:%s msg:%s" % (target, code, status, msg))
logger.info(f"send_change_msg target:{target} code:{code} status:{status} msg:{msg}")
return status, msg
def send_login_msg(self, target, code):
status, msg = self.sender.send_login_msg(target, code)
logger.info("send_login_msg target:%s code:%s status:%s msg:%s" % (target, code, status, msg))
logger.info(f"send_login_msg target:{target} code:{code} status:{status} msg:{msg}")
return status, msg
def send_email_msg(self, email, text):
if self.type == 'email':
if self.send_type == 'email':
status, msg = self.sender.send_email_msg(email, text)
logger.info("send_email_msg target:%s text:%s status:%s msg:%s" % (email, text, status, msg))
logger.info(f"send_email_msg target:{email} text:{text} status:{status} msg:{msg}")
return status, msg
def _get_email_sender(self):
return self._get_default_sender(0)
def _get_sms_sender(self):
return self._get_default_sender(1)
def _get_default_sender(self, type):
'''
sender_type :
0: 邮件
1: 阿里云
2: 极光
'''
sender_lists = THIRD_PART_CONFIG.get('sender')
for sender in sender_lists:
if sender.get("active", None):
sender_type = sender.get('type', None)
auth = sender.get('auth', {})
if sender_type == 0 and type == 0:
return EmailMsgSender(**auth)
if sender_type == 1:
return AliMsgSender(**auth)
elif sender_type == 2:
return JiGuangMsgSender(**auth)
else:
continue
return None

@ -1,7 +1,7 @@
from rest_framework import serializers
from api import models
from api.utils.TokenManager import make_token
from api.utils.app.apputils import bytes2human
from api.utils.TokenManager import DownloadToken
from api.utils.app.supersignutils import get_redirect_server_domain
from api.utils.baseutils import get_user_domain_name, get_app_domain_name
from api.utils.storage.storage import Storage
@ -9,9 +9,7 @@ from api.utils.utils import get_developer_udided, get_choices_dict, get_choices_
from api.utils.storage.caches import get_user_free_download_times, get_user_cert_auth_status
import os, logging
logger = logging.getLogger(__file__)
token_obj = DownloadToken()
logger = logging.getLogger(__name__)
def get_download_url_from_context(self, obj, key, url, force_new=False):
@ -33,8 +31,7 @@ def get_download_url_from_context(self, obj, key, url, force_new=False):
storage = None
if storage:
download_url = storage.get_download_url(os.path.basename(url), 600, key, force_new)
logger.info(
'get %s download_url %s force_new:%s key:%s' % (os.path.basename(url), download_url, force_new, key))
logger.info(f'get {os.path.basename(url)} download_url {download_url} force_new:{force_new} key:{key}')
return download_url
@ -187,7 +184,7 @@ class AppsSerializer(serializers.ModelSerializer):
"binary_url": master_release_obj.binary_url,
}
download_token = token_obj.make_token(master_release_obj.release_id, 600, key=key)
download_token = make_token(master_release_obj.release_id, 600, key=key)
datainfo["download_token"] = download_token
udid_lists = []
try:
@ -284,7 +281,7 @@ class AppsShortSerializer(serializers.ModelSerializer):
"binary_url": master_release_obj.binary_url,
}
download_token = token_obj.make_token(master_release_obj.release_id, 600, key=key, force_new=True)
download_token = make_token(master_release_obj.release_id, 600, key=key, force_new=True)
datainfo["download_token"] = download_token
return datainfo
else:
@ -322,7 +319,7 @@ class AppReleaseSerializer(serializers.ModelSerializer):
return bytes2human(obj.binary_size)
def get_download_token(self, obj):
return token_obj.make_token(obj.release_id, 600)
return make_token(obj.release_id, 600)
def get_icon_url(self, obj):
return get_download_url_from_context(self, obj, '', os.path.basename(obj.icon_url))

@ -16,7 +16,7 @@ import hashlib
import time
import logging
logger = logging.getLogger(__file__)
logger = logging.getLogger(__name__)
# 以下代码展示了STS的用法,包括角色扮演获取临时用户的密钥、使用临时用户的密钥访问OSS。
@ -62,19 +62,19 @@ class AliYunCdn(object):
if not args: args = ""
rand = "0" # "0" by default, other value is ok
uid = "0" # "0" by default, other value is ok
sstring = "%s-%s-%s-%s-%s" % (path, exp, rand, uid, self.key)
hashvalue = md5sum(sstring.encode("utf-8"))
auth_key = "%s-%s-%s-%s" % (exp, rand, uid, hashvalue)
ss_string = f"{path}-{exp}-{rand}-{uid}-{self.key}"
hash_value = md5sum(ss_string.encode("utf-8"))
auth_key = f"{exp}-{rand}-{uid}-{hash_value}"
if args:
return "%s%s%s%s&auth_key=%s" % (scheme, host, path, args, auth_key)
return f"{scheme}{host}{path}{args}&auth_key={auth_key}"
else:
return "%s%s%s%s?auth_key=%s" % (scheme, host, path, args, auth_key)
return f"{scheme}{host}{path}{args}?auth_key={auth_key}"
def get_cdn_download_token(self, filename, expires=1800):
uri = "%s/%s" % (self.domain, filename)
uri = f"{self.domain}/{filename}"
exp = int(time.time()) + expires
download_url = self.a_auth(uri, exp)
logger.info("make cdn download url %s" % download_url)
logger.info(f"make cdn download url {download_url}")
return download_url
@ -131,6 +131,7 @@ class AliYunOss(object):
req.set_RoleArn(self.sts_role_arn)
req.set_RoleSessionName(name)
req.set_DurationSeconds(expires)
p_action = "oss:GetObject"
if only_put:
p_action = ["oss:PutObject", "oss:AbortMultipartUpload"]
if only_get:
@ -159,7 +160,7 @@ class AliYunOss(object):
token.expiration = oss2.utils.to_unixtime(j['Credentials']['Expiration'], '%Y-%m-%dT%H:%M:%SZ')
token.bucket = self.bucket_name
token.endpoint = self.endpoint.replace('-internal', '')
logger.info("get aliyun sts token %s" % token.__dict__)
logger.info(f"get aliyun sts token {token.__dict__}")
return token
def get_upload_token(self, name, expires=1800):
@ -191,9 +192,9 @@ class AliYunOss(object):
# bucket = oss2.Bucket(auth, self.endpoint,self.bucket_name)
return self.bucket.delete_object(name)
def rename_file(self, oldfilename, newfilename):
self.bucket.copy_object(self.bucket_name, oldfilename, newfilename)
return self.del_file(oldfilename)
def rename_file(self, old_filename, new_filename):
self.bucket.copy_object(self.bucket_name, old_filename, new_filename)
return self.del_file(old_filename)
def upload_file(self, local_file_full_path):
if os.path.isfile(local_file_full_path):
@ -210,7 +211,7 @@ class AliYunOss(object):
# self.bucket.put_object(os.path.basename(local_file_full_path), fileobj)
return True
else:
logger.error("file %s is not file" % local_file_full_path)
logger.error(f"file {local_file_full_path} is not file")
def download_file(self, name, local_file_full_path):
dir_path = os.path.dirname(local_file_full_path)

@ -16,7 +16,7 @@ from api.utils.baseutils import get_app_d_count_by_app_id, get_app_domain_name,
import logging
from django.db.models import F
logger = logging.getLogger(__file__)
logger = logging.getLogger(__name__)
def sync_download_times_by_app_id(app_ids):
@ -28,7 +28,7 @@ def sync_download_times_by_app_id(app_ids):
for k, v in down_times_lists.items():
app_id = k.split(CACHE_KEY_TEMPLATE.get("download_times_key"))[1].strip('_')
Apps.objects.filter(app_id=app_id).update(count_hits=v)
logger.info("sync_download_times_by_app_id app_id:%s count_hits:%s" % (app_id, v))
logger.info(f"sync_download_times_by_app_id app_id:{app_id} count_hits:{v}")
def get_download_url_by_cache(app_obj, filename, limit, isdownload=True, key='', udid=None):
@ -42,17 +42,17 @@ def get_download_url_by_cache(app_obj, filename, limit, isdownload=True, key='',
else:
appudid_obj = AppUDID.objects.filter(app_id_id=app_obj.get("pk"), udid=udid, is_signed=True).first()
if appudid_obj:
SuperSign_obj = APPSuperSignUsedInfo.objects.filter(udid__udid=udid,
app_id_id=app_obj.get("pk")).first()
if SuperSign_obj and SuperSign_obj.user_id.supersign_active:
APPToDeveloper_obj = APPToDeveloper.objects.filter(app_id_id=app_obj.get("pk"),
developerid=SuperSign_obj.developerid).first()
if APPToDeveloper_obj:
super_sign_obj = APPSuperSignUsedInfo.objects.filter(udid__udid=udid,
app_id_id=app_obj.get("pk")).first()
if super_sign_obj and super_sign_obj.user_id.supersign_active:
app_to_developer_obj = APPToDeveloper.objects.filter(app_id_id=app_obj.get("pk"),
developerid=super_sign_obj.developerid).first()
if app_to_developer_obj:
release_obj = AppReleaseInfo.objects.filter(app_id_id=app_obj.get("pk"), is_master=True).first()
if release_obj.release_id == APPToDeveloper_obj.release_file:
binary_file = APPToDeveloper_obj.binary_file
if release_obj.release_id == app_to_developer_obj.release_file:
binary_file = app_to_developer_obj.binary_file
else:
binary_file = APPToDeveloper_obj.release_file
binary_file = app_to_developer_obj.release_file
return local_storage.get_download_url(
binary_file + "." + download_url_type, limit), ""
else:
@ -146,7 +146,7 @@ def del_cache_response_by_short(app_id, udid=''):
def del_cache_response_by_short_util(short, app_id, udid):
logger.info("del_cache_response_by_short short:%s app_id:%s udid:%s" % (short, app_id, udid))
logger.info(f"del_cache_response_by_short short:{short} app_id:{app_id} udid:{udid}")
key = "_".join([CACHE_KEY_TEMPLATE.get("download_short_key"), short, '*'])
for app_download_key in cache.iter_keys(key):
cache.delete(app_download_key)
@ -188,7 +188,7 @@ def del_cache_by_app_id(app_id, user_obj):
def del_cache_storage(user_obj):
logger.info("del_cache_storage user:%s" % user_obj)
logger.info(f"del_cache_storage user:{user_obj}")
for app_obj in Apps.objects.filter(user_id=user_obj):
del_cache_response_by_short(app_obj.app_id)
del_cache_by_app_id(app_obj.app_id, user_obj)
@ -249,13 +249,13 @@ def limit_cache_util(act, cache_key, cache_limit_times):
if cdata:
data["count"] = cdata["count"] + 1
data["time"] = time.time()
logger.info("limit_cache_util cache_key:%s data:%s" % (cache_key, data))
logger.info(f"limit_cache_util cache_key:{cache_key} data:{data}")
cache.set(cache_key, data, cache_times)
elif act == "get":
cdata = cache.get(cache_key)
if cdata:
if cdata["count"] > limit_times:
logging.error("limit_cache_util cache_key %s over limit ,is locked . cdata:%s" % (cache_key, cdata))
logger.error(f"limit_cache_util cache_key {cache_key} over limit ,is locked . cdata:{cdata}")
return False
return True
elif act == "del":
@ -263,7 +263,7 @@ def limit_cache_util(act, cache_key, cache_limit_times):
def login_auth_failed(act, email):
logger.error("login email:%s act:%s" % (email, act))
logger.error(f"login email:{email} act:{act}")
auth_code_key = "_".join([CACHE_KEY_TEMPLATE.get("login_failed_try_times_key"), email])
return limit_cache_util(act, auth_code_key, SYNC_CACHE_TO_DATABASE.get("try_login_times"))
@ -340,7 +340,7 @@ def consume_user_download_times(user_id, app_id, amount=1, auth_status=False):
try:
UserInfo.objects.filter(pk=user_id).update(download_times=F('download_times') - amount)
except Exception as e:
logger.error("%s download_times less then 0. Exception:%s" % (user_id, e))
logger.error(f"{user_id} download_times less then 0. Exception:{e}")
disable_user_download_times_flag(user_id)
del_cache_response_by_short(app_id)
return False
@ -360,7 +360,7 @@ def add_user_download_times(user_id, download_times=0):
UserInfo.objects.filter(pk=user_id).update(download_times=F('download_times') + download_times)
return enable_user_download(user_id)
except Exception as e:
logger.error("%s download_times less then 0. Exception:%s" % (user_id, e))
logger.error(f"{user_id} download_times less then 0. Exception:{e}")
return False
@ -390,11 +390,11 @@ def consume_user_download_times_by_app_obj(app_obj):
def user_auth_success(user_id):
'''
"""
认证成功需要调用该方法增加次数
:param user_id:
:return:
'''
"""
get_user_free_download_times(user_id, 'get')
get_user_free_download_times(user_id, 'set', USER_FREE_DOWNLOAD_TIMES - AUTH_USER_FREE_DOWNLOAD_TIMES)
return enable_user_download(user_id)
@ -429,19 +429,19 @@ def update_order_info(user_id, out_trade_no, payment_number, payment_type):
download_times, user_obj.download_times + download_times)
order_obj.save()
add_user_download_times(user_id, download_times)
logger.info("%s 订单 %s msg:%s" % (user_obj, out_trade_no, order_obj.description))
logger.info(f"{user_obj} 订单 {out_trade_no} msg:{order_obj.description}")
return True
except Exception as e:
logger.error("%s 订单 %s 更新失败 Exception:%s" % (user_obj, out_trade_no, e))
logger.error(f"{user_obj} 订单 {out_trade_no} 更新失败 Exception:{e}")
elif order_obj.status == 0:
return True
else:
return False
else:
logger.error("%s 订单 %s 订单获取失败,或订单已经支付" % (user_obj, out_trade_no))
logger.error(f"{user_obj} 订单 {out_trade_no} 订单获取失败,或订单已经支付")
except Exception as e:
logger.error("%s download_times less then 0. Exception:%s" % (user_obj, e))
logger.error(f"{user_obj} download_times less then 0. Exception:{e}")
return False

@ -3,16 +3,16 @@
# project: 3月
# author: liuyu
# date: 2020/3/18
'''
"""
本地存储api
'''
from api.utils.TokenManager import DownloadToken
"""
from api.utils.TokenManager import make_token
from api.utils.storage.aliyunApi import AliYunCdn
from fir_ser import settings
import os
import logging
logger = logging.getLogger(__file__)
logger = logging.getLogger(__name__)
class LocalStorage(object):
@ -22,22 +22,20 @@ class LocalStorage(object):
self.download_auth_type = download_auth_type
self.cnd_auth_key = cnd_auth_key
def get_upload_token(self, name, expires):
dtoken = DownloadToken()
return dtoken.make_token(name, expires)
@staticmethod
def get_upload_token(name, expires):
return make_token(name, expires)
def get_base_url(self):
uri = 'http://'
if self.is_https:
uri = 'https://'
return "%s%s" % (uri, self.domain_name)
return f"{uri}${self.domain_name}"
def get_download_url(self, name, expires=600, force_new=False):
dtoken = DownloadToken()
download_url = '/'.join([self.get_base_url(), 'download', name])
if self.download_auth_type == 1:
download_url = "%s?%s=%s" % (
download_url, settings.DATA_DOWNLOAD_KEY, dtoken.make_token(name, expires, force_new=force_new))
download_url = f"{download_url}?{settings.DATA_DOWNLOAD_KEY}={make_token(name, expires, force_new=force_new)}"
elif self.download_auth_type == 2:
cdn_obj = AliYunCdn(self.cnd_auth_key, self.is_https, self.domain_name)
download_url = cdn_obj.get_cdn_download_token(name, expires)
@ -45,25 +43,28 @@ class LocalStorage(object):
pass
return download_url
def del_file(self, name):
@staticmethod
def del_file(name):
file = os.path.join(settings.MEDIA_ROOT, name)
try:
if os.path.isfile(file):
os.remove(file)
return True
except Exception as e:
logger.error("delete file %s failed Exception %s" % (file, e))
logger.error(f"delete file {file} failed Exception {e}")
return False
def rename_file(self, oldfilename, newfilename):
@staticmethod
def rename_file(old_filename, new_filename):
try:
os.rename(os.path.join(settings.MEDIA_ROOT, oldfilename), os.path.join(settings.MEDIA_ROOT, newfilename))
os.rename(os.path.join(settings.MEDIA_ROOT, old_filename), os.path.join(settings.MEDIA_ROOT, new_filename))
return True
except Exception as e:
logger.error("rename_file file %s to %s failed Exception %s" % (oldfilename, newfilename, e))
logger.error(f"rename_file file {old_filename} to {new_filename} failed Exception {e}")
return False
def upload_file(self, local_file_full_path):
@staticmethod
def upload_file(local_file_full_path):
if os.path.isfile(local_file_full_path):
return True
return False

@ -3,15 +3,15 @@
# project: 3月
# author: liuyu
# date: 2020/3/18
'''
"""
主要是调用七牛云存储处理七牛云存储的逻辑
'''
"""
from qiniu import Auth, put_file, etag
from qiniu import BucketManager
import os, requests
import logging
logger = logging.getLogger(__file__)
logger = logging.getLogger(__name__)
class QiNiuOss(object):
@ -41,7 +41,7 @@ class QiNiuOss(object):
uri = 'http://'
if self.is_https:
uri = 'https://'
base_url = '%s%s/%s' % (uri, self.domain_name, name)
base_url = f'{uri}{self.domain_name}/{name}'
# 或者直接输入url的方式下载
# 可以设置token过期时间
private_url = self.qiniu_obj.private_download_url(base_url, expires=expires)
@ -54,9 +54,9 @@ class QiNiuOss(object):
ret, info = bucket.delete(self.bucket_name, name)
return ret
def rename_file(self, oldfilename, newfilename):
def rename_file(self, old_filename, new_filename):
bucket = BucketManager(self.qiniu_obj)
ret, info = bucket.move(self.bucket_name, oldfilename, self.bucket_name, newfilename)
ret, info = bucket.move(self.bucket_name, old_filename, self.bucket_name, new_filename)
return ret
def upload_file(self, local_file_full_path):
@ -73,15 +73,15 @@ class QiNiuOss(object):
os.makedirs(dir_path)
req = requests.get(self.get_download_url(name))
if req.status_code != 200:
logger.error("download file %s failed %s" % (name, req.content))
logger.error(f"download file {name} failed {req.content}")
return False
try:
with open(local_file_full_path, "wb") as f:
for chunk in req.iter_content(chunk_size=5120):
if chunk:
f.write(chunk)
logger.info("save download file %s success" % local_file_full_path)
logger.info(f"save download file {local_file_full_path} success")
return True
except Exception as e:
logger.error("check download file and move file %s failed Exception %s" % (local_file_full_path, e))
logger.error(f"check download file and move file {local_file_full_path} failed Exception {e}")
return False

@ -14,7 +14,7 @@ from fir_ser.settings import THIRD_PART_CONFIG, CACHE_KEY_TEMPLATE
from django.core.cache import cache
import logging
logger = logging.getLogger(__file__)
logger = logging.getLogger(__name__)
def get_storage_auth(storage_obj):
@ -38,7 +38,7 @@ def get_storage(user, assigned_storage_obj, use_default_storage):
storage_type = storage_obj.storage_type
new_storage_obj = cache.get(storage_key)
if new_storage_obj and not assigned_storage_obj:
logger.info("user %s get storage obj %s cache %s" % (user, storage_key, new_storage_obj))
logger.info(f"user {user} get storage obj {storage_key} cache {new_storage_obj}")
return new_storage_obj
else:
if storage_type == 1:
@ -47,12 +47,12 @@ def get_storage(user, assigned_storage_obj, use_default_storage):
new_storage_obj = AliYunOss(**auth)
else:
new_storage_obj = LocalStorage(**auth)
logger.warning("user %s make storage obj key:%s obj: %s" % (user, storage_key, new_storage_obj))
logger.warning(f"user {user} make storage obj key:{storage_key} obj: {new_storage_obj}")
new_storage_obj.storage_type = storage_type
cache.set(storage_key, new_storage_obj, 600)
return new_storage_obj
else:
logger.info("user %s has not storage obj, so get default" % user)
logger.info(f"user {user} has not storage obj, so get default")
# return self.get_default_storage(user, storage_obj, False)
# 不需要管理存储,直接从配置文件获取默认存储
return get_storage_form_conf(user)
@ -61,8 +61,7 @@ def get_storage(user, assigned_storage_obj, use_default_storage):
def get_default_storage(user, storage_obj, use_default_storage):
admin_obj = UserInfo.objects.filter(is_superuser=True).order_by('pk').first()
if admin_obj and admin_obj.storage and admin_obj.pk != user.pk:
logger.info("user %s has not storage obj, from admin "
"get default storage" % user)
logger.info(f"user {user} has not storage obj, from admin get default storage")
return get_storage(admin_obj, storage_obj, use_default_storage)
else:
return get_storage_form_conf(user)
@ -74,7 +73,7 @@ class Storage(object):
with cache.lock("%s_%s" % ('make_storage_cache', user.uid), timeout=10, blocking_timeout=6):
self.storage = get_storage(user, assigned_storage_obj, use_default_storage)
except Exception as e:
logger.error("get %s storage failed Exception:%s" % (user, e))
logger.error(f"get {user} storage failed Exception:{e}")
self.storage = None
def get_upload_token(self, filename, expires=900):
@ -97,39 +96,39 @@ class Storage(object):
cache.set(down_key, {"download_url": download_url, "time": now + expires}, expires)
return download_url
def delete_file(self, filename, apptype=None):
def delete_file(self, filename, app_type=None):
if self.storage:
if apptype is not None:
if apptype == 0:
if app_type is not None:
if app_type == 0:
filename = filename + '.apk'
else:
filename = filename + '.ipa'
try:
logger.info("storage %s delete file %s" % (self.storage, filename))
logger.info(f"storage {self.storage} delete file {filename}")
return self.storage.del_file(filename)
except Exception as e:
logger.error("delete file %s failed Exception %s" % (filename, e))
logger.error(f"delete file {filename} failed Exception {e}")
def rename_file(self, oldfilename, newfilename):
def rename_file(self, old_filename, new_filename):
if self.storage:
try:
return self.storage.rename_file(oldfilename, newfilename)
return self.storage.rename_file(old_filename, new_filename)
except Exception as e:
logger.error("rename %s to %s failed Exception %s" % (oldfilename, newfilename, e))
logger.error(f"rename {old_filename} to {new_filename} failed Exception {e}")
def upload_file(self, local_file_full_path):
if self.storage:
try:
return self.storage.upload_file(local_file_full_path)
except Exception as e:
logger.error("oss upload %s failed Exception %s" % (local_file_full_path, e))
logger.error(f"oss upload {local_file_full_path} failed Exception {e}")
def download_file(self, file_name, local_file_full_path):
if self.storage:
try:
return self.storage.download_file(file_name, local_file_full_path)
except Exception as e:
logger.error("oss download %s failed Exception %s" % (local_file_full_path, e))
logger.error(f"oss download {local_file_full_path} failed Exception {e}")
def get_storage_type(self):
if self.storage:
@ -145,18 +144,17 @@ def get_local_storage(clean_cache=False):
storage_key = "_".join(['local_storage_', CACHE_KEY_TEMPLATE.get('user_storage_key'), "_system_",
base64.b64encode(json.dumps(auth).encode("utf-8")).decode("utf-8")[0:64]])
if clean_cache:
logger.info("system clean local storage obj cache storage_key %s" % storage_key)
logger.info(f"system clean local storage obj cache storage_key {storage_key}")
cache.delete(storage_key)
new_storage_obj = cache.get(storage_key)
if new_storage_obj:
logger.info("system get local storage obj cache %s" % new_storage_obj)
logger.info(f"system get local storage obj cache {new_storage_obj}")
return new_storage_obj
else:
new_storage_obj = LocalStorage(**auth)
new_storage_obj.storage_type = 3
cache.set(storage_key, new_storage_obj, 600)
logger.info("system get local storage obj, from settings "
"storage %s" % new_storage_obj)
logger.info(f"system get local storage obj, from settings storage {new_storage_obj}")
return new_storage_obj
@ -170,7 +168,7 @@ def get_storage_form_conf(user):
base64.b64encode(json.dumps(auth).encode("utf-8")).decode("utf-8")[0:64]])
new_storage_obj = cache.get(storage_key)
if new_storage_obj:
logger.info("user %s get default storage %s obj cache %s " % (user, storage_key, new_storage_obj))
logger.info(f"user {user} get default storage {storage_key} obj cache {new_storage_obj} ")
return new_storage_obj
else:
if storage_type == 1:
@ -183,7 +181,7 @@ def get_storage_form_conf(user):
new_storage_obj = LocalStorage(**auth)
new_storage_obj.storage_type = 3
cache.set(storage_key, new_storage_obj, 600)
logger.warning("user %s has not storage obj, from settings "
"get default storage key:%s obj:%s" % (user, storage_key, new_storage_obj))
logger.warning(
f"user {user} has not storage obj, from settings get default storage key:{storage_key} obj:{new_storage_obj}")
return new_storage_obj
return None

@ -8,7 +8,7 @@ from django.core.cache import cache
import base64
class tmpCache(object):
class TmpCache(object):
@staticmethod
def set_tmp_cache(key, token, target, limit=60 * 5):

@ -7,8 +7,6 @@
from rest_framework.throttling import SimpleRateThrottle
import hashlib
from rest_framework.exceptions import Throttled
class VisitShortThrottle(SimpleRateThrottle):
"""短连接用户访问频率限制1"""

@ -3,15 +3,17 @@
# project: 5月
# author: liuyu
# date: 2020/5/7
import os, json, requests, datetime, random
from fir_ser.settings import SERVER_DOMAIN, CAPTCHA_LENGTH, MEDIA_ROOT
import os, datetime, random
import binascii
from fir_ser.settings import SERVER_DOMAIN, CAPTCHA_LENGTH, MEDIA_ROOT, CACHE_KEY_TEMPLATE
from api.models import APPSuperSignUsedInfo, APPToDeveloper, \
UDIDsyncDeveloper, UserInfo, AppReleaseInfo, AppScreenShot, UserDomainInfo
UDIDsyncDeveloper, UserInfo, AppReleaseInfo, AppScreenShot, Token
from api.utils.storage.caches import get_app_d_count_by_app_id
from api.utils.storage.localApi import LocalStorage
from api.utils.storage.storage import Storage
from api.utils.tempcaches import tmpCache
from api.utils.TokenManager import DownloadToken, generateNumericTokenOfLength, generateAlphanumericTokenOfLength
from api.utils.tempcaches import TmpCache
from api.utils.TokenManager import generate_numeric_token_of_length, generate_alphanumeric_token_of_length, make_token, \
verify_token
from api.utils.sendmsg.sendmsg import SendMessage
from django.db.models import Sum
from captcha.models import CaptchaStore
@ -77,7 +79,7 @@ def get_captcha():
def valid_captcha(cptch_key, code, username):
if username:
challenge = CaptchaStore.objects.filter(hashkey=cptch_key).values("challenge").first()
logger.info("cptch_key:%s code:%s challenge:%s" % ((cptch_key, code, challenge)))
logger.info(f"cptch_key:{cptch_key} code:{code} challenge:{challenge}")
if challenge:
if cptch_key and code and code.strip(" ").lower() == challenge.get("challenge").lower():
return True
@ -92,10 +94,9 @@ def upload_oss_default_head_img(user_obj, storage_obj):
def get_sender_token(sender, user_id, target, action, msg=None):
sms_token_obj = DownloadToken()
code = generateNumericTokenOfLength(6)
token = sms_token_obj.make_token(code, time_limit=300, key=user_id)
tmpCache.set_tmp_cache(user_id, token, target)
code = generate_numeric_token_of_length(6)
token = make_token(code, time_limit=300, key=user_id)
TmpCache.set_tmp_cache(user_id, token, target)
if action == 'change':
sender.send_change_msg(target, code)
elif action == 'register':
@ -105,7 +106,7 @@ def get_sender_token(sender, user_id, target, action, msg=None):
elif action == 'msg':
sender.send_email_msg(target, msg)
else:
logger.error("get_sender_token failed. action is %s" % (action))
logger.error(f"get_sender_token failed. action is {action}")
return None, None
return token, code
@ -116,8 +117,7 @@ def get_sender_sms_token(key, phone, action):
def is_valid_sender_code(key, token, code):
sms_token_obj = DownloadToken()
return sms_token_obj.verify_token(token, code), tmpCache.get_tmp_cache(key, token)
return verify_token(token, code), TmpCache.get_tmp_cache(key, token)
def get_sender_email_token(key, email, action, msg=None):
@ -133,7 +133,7 @@ def check_username_exists(username):
def get_random_username(length=16):
username = generateAlphanumericTokenOfLength(length)
username = generate_alphanumeric_token_of_length(length)
if check_username_exists(username):
return get_random_username(length)
return username
@ -145,7 +145,7 @@ def send_ios_developer_active_status(user_info, msg):
if email:
get_sender_email_token(act, email, 'msg', msg)
else:
logger.warning("user %s has no email. so %s can't send!" % (user_info, msg))
logger.warning(f"user {user_info} has no email. so {msg} can't send!")
def get_filename_from_apptype(filename, apptype):
@ -163,7 +163,7 @@ def delete_local_files(filename, apptype=None):
try:
return storage.del_file(filename)
except Exception as e:
logger.error("delete file %s failed Exception %s" % (filename, e))
logger.error(f"delete file {filename} failed Exception {e}")
def delete_app_screenshots_files(storage_obj, app_obj):
@ -262,7 +262,7 @@ def migrating_storage_data(user_obj, new_storage_obj, clean_old_data):
def clean_storage_data(user_obj, storage_obj=None):
storage_obj = Storage(user_obj, storage_obj)
logger.info("%s clean_storage_data %s" % (user_obj, storage_obj))
logger.info(f"{user_obj} clean_storage_data {storage_obj}")
for app_release_obj in AppReleaseInfo.objects.filter(app_id__user_id=user_obj).all():
storage_obj.delete_file(app_release_obj.release_id, app_release_obj.release_type)
storage_obj.delete_file(app_release_obj.icon_url)
@ -295,3 +295,13 @@ def get_choices_name_from_key(choices, key):
if choice[0] == key:
return choice[1]
return ''
def set_user_token(user_obj):
key = binascii.hexlify(os.urandom(32)).decode()
now = datetime.datetime.now()
user_info = UserInfo.objects.get(pk=user_obj.pk)
auth_key = "_".join([CACHE_KEY_TEMPLATE.get('user_auth_token_key'), key])
cache.set(auth_key, {'uid': user_info.uid, 'username': user_info.username}, 3600 * 24 * 7)
Token.objects.create(user=user_obj, **{"access_token": key, "created": now})
return key, user_info

@ -68,8 +68,7 @@ class AppsView(APIView):
if count_hits:
if count_hits > 0:
logger.info(
"update user all_download_times old:%s now:%s" % (
count_hits, request.user.all_download_times))
f"update user all_download_times old:{count_hits} now:{request.user.all_download_times}")
UserInfo.objects.filter(pk=request.user.id).update(
all_download_times=count_hits)
else:
@ -110,14 +109,14 @@ class AppInfoView(APIView):
def get(self, request, app_id):
res = BaseResponse()
if app_id:
apps_obj = Apps.objects.filter(user_id=request.user, app_id=app_id).first()
if apps_obj:
app_serializer = AppsSerializer(apps_obj, context={"storage": Storage(request.user)})
app_obj = Apps.objects.filter(user_id=request.user, app_id=app_id).first()
if app_obj:
app_serializer = AppsSerializer(app_obj, context={"storage": Storage(request.user)})
res.data = app_serializer.data
count = APPToDeveloper.objects.filter(app_id=apps_obj).count()
count = APPToDeveloper.objects.filter(app_id=app_obj).count()
res.data["count"] = count
else:
logger.error("app_id:%s is not found in user:%s " % (app_id, request.user))
logger.error(f"app_id:{app_id} is not found in user:{request.user}")
res.msg = "未找到该应用"
res.code = 1003
@ -126,8 +125,8 @@ class AppInfoView(APIView):
def delete(self, request, app_id):
res = BaseResponse()
if app_id:
apps_obj = Apps.objects.filter(user_id=request.user, app_id=app_id).first()
res = app_delete(apps_obj)
app_obj = Apps.objects.filter(user_id=request.user, app_id=app_id).first()
res = app_delete(app_obj)
return Response(res.dict)
def put(self, request, app_id):
@ -137,16 +136,16 @@ class AppInfoView(APIView):
clean = data.get("clean", None)
if clean:
logger.info("app_id:%s clean:%s ,close supersign should clean_app_by_user_obj" % (app_id, clean))
apps_obj = Apps.objects.filter(user_id=request.user, app_id=app_id).first()
IosUtils.clean_app_by_user_obj(apps_obj, request.user)
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, request.user)
return Response(res.dict)
has_combo = data.get("has_combo", None)
if has_combo:
actions = has_combo.get("action", None)
hcombo_id = has_combo.get("hcombo_id", None)
logger.info("app_id:%s actions:%s hcombo_id:%s" % (app_id, actions, hcombo_id))
logger.info(f"app_id:{app_id} actions:{actions} hcombo_id:{hcombo_id}")
if actions and hcombo_id:
has_combo = Apps.objects.filter(user_id=request.user, app_id=hcombo_id)
@ -166,54 +165,54 @@ class AppInfoView(APIView):
del_cache_response_by_short(has_combo.first().app_id)
except Exception as e:
logger.error("app_id:%s actions:%s hcombo_id:%s Exception:%s" % (app_id, actions, hcombo_id, e))
logger.error(f"app_id:{app_id} actions:{actions} hcombo_id:{hcombo_id} Exception:{e}")
res.code = 1004
res.msg = "该应用已经关联"
else:
try:
do_sign_flag = 0
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__))
apps_obj.description = data.get("description", apps_obj.description)
apps_obj.short = data.get("short", apps_obj.short)
apps_obj.name = data.get("name", apps_obj.name)
apps_obj.password = data.get("password", apps_obj.password)
apps_obj.supersign_limit_number = data.get("supersign_limit_number",
apps_obj.supersign_limit_number)
apps_obj.isshow = data.get("isshow", apps_obj.isshow)
if get_user_domain_name(request.user) or get_app_domain_name(apps_obj):
apps_obj.wxeasytype = data.get("wxeasytype", apps_obj.wxeasytype)
app_obj = Apps.objects.filter(user_id=request.user, app_id=app_id).first()
logger.info("app_id:%s update old data:%s" % (app_id, app_obj.__dict__))
app_obj.description = data.get("description", app_obj.description)
app_obj.short = data.get("short", app_obj.short)
app_obj.name = data.get("name", app_obj.name)
app_obj.password = data.get("password", app_obj.password)
app_obj.supersign_limit_number = data.get("supersign_limit_number",
app_obj.supersign_limit_number)
app_obj.isshow = data.get("isshow", app_obj.isshow)
if get_user_domain_name(request.user) or get_app_domain_name(app_obj):
app_obj.wxeasytype = data.get("wxeasytype", app_obj.wxeasytype)
else:
apps_obj.wxeasytype = 1
app_obj.wxeasytype = 1
if apps_obj.issupersign:
if apps_obj.supersign_type in [x[0] for x in list(apps_obj.supersign_type_choices)]:
if apps_obj.supersign_type != data.get("supersign_type", apps_obj.supersign_type):
if app_obj.issupersign:
if app_obj.supersign_type in [x[0] for x in list(app_obj.supersign_type_choices)]:
if app_obj.supersign_type != data.get("supersign_type", app_obj.supersign_type):
do_sign_flag = 1
apps_obj.supersign_type = data.get("supersign_type", apps_obj.supersign_type)
app_obj.supersign_type = data.get("supersign_type", app_obj.supersign_type)
new_bundle_id = data.get("new_bundle_id", None)
new_bundle_name = data.get("new_bundle_name", None)
if new_bundle_id and new_bundle_id != apps_obj.bundle_id and len(new_bundle_id) > 3:
if new_bundle_id != apps_obj.new_bundle_id:
if new_bundle_id and new_bundle_id != app_obj.bundle_id and len(new_bundle_id) > 3:
if new_bundle_id != app_obj.new_bundle_id:
do_sign_flag = 2
apps_obj.new_bundle_id = new_bundle_id
app_obj.new_bundle_id = new_bundle_id
if new_bundle_id == '':
if new_bundle_id != apps_obj.new_bundle_id:
if new_bundle_id != app_obj.new_bundle_id:
do_sign_flag = 2
apps_obj.new_bundle_id = None
app_obj.new_bundle_id = None
if new_bundle_name and new_bundle_name != apps_obj.name and len(new_bundle_name) > 0:
if new_bundle_name != apps_obj.new_bundle_name:
if new_bundle_name and new_bundle_name != app_obj.name and len(new_bundle_name) > 0:
if new_bundle_name != app_obj.new_bundle_name:
do_sign_flag = 2
apps_obj.new_bundle_name = new_bundle_name
app_obj.new_bundle_name = new_bundle_name
if new_bundle_name == '':
# if new_bundle_name != apps_obj.new_bundle_name:
# do_sign_flag = 2
apps_obj.new_bundle_name = apps_obj.name
app_obj.new_bundle_name = app_obj.name
apps_obj.wxredirect = data.get("wxredirect", apps_obj.wxredirect)
if apps_obj.type == 1 and data.get('issupersign', -1) != -1:
app_obj.wxredirect = data.get("wxredirect", app_obj.wxredirect)
if app_obj.type == 1 and data.get('issupersign', -1) != -1:
# 为啥注释掉,就是该udid已经在该平台使用了,虽然已经没有余额,但是其他应用也是可以超级签名的
# developer_obj = AppIOSDeveloperInfo.objects.filter(user_id=request.user)
# use_num = get_developer_devices(developer_obj)
@ -223,45 +222,45 @@ class AppInfoView(APIView):
# return Response(res.dict)
developer_count = AppIOSDeveloperInfo.objects.filter(user_id=request.user).count()
if developer_count == 0:
logger.error("app_id:%s can't open supersign,owner has no ios developer" % (app_id))
logger.error(f"app_id:{app_id} can't open super_sign,owner has no ios developer")
res.code = 1008
res.msg = "超级签开发者不存在,无法开启"
return Response(res.dict)
apps_obj.issupersign = data.get("issupersign", apps_obj.issupersign)
logger.info("app_id:%s update new data:%s" % (app_id, apps_obj.__dict__))
apps_obj.save()
if apps_obj.issupersign:
app_obj.issupersign = data.get("issupersign", app_obj.issupersign)
logger.info(f"app_id:{app_id} update new data:{app_obj.__dict__}")
app_obj.save()
if app_obj.issupersign:
c_task = None
if do_sign_flag == 1:
c_task = run_resign_task.apply_async((apps_obj.app_id, True))
c_task = run_resign_task.apply_async((app_obj.app_id, True))
if do_sign_flag == 2:
c_task = run_resign_task.apply_async((apps_obj.app_id, False))
c_task = run_resign_task.apply_async((app_obj.app_id, False))
if c_task:
msg = c_task.get(propagate=False)
logger.info("app %s run_resign_task msg:%s" % (apps_obj, msg))
logger.info(f"app {app_obj} run_resign_task msg:{msg}")
if c_task.successful():
c_task.forget()
del_cache_response_by_short(apps_obj.app_id)
del_cache_response_by_short(app_obj.app_id)
except Exception as e:
logger.error("app_id:%s update Exception:%s" % (app_id, e))
logger.error(f"app_id:{app_id} update Exception:{e}")
res.code = 1005
res.msg = "短连接已经存在"
return Response(res.dict)
class AppReleaseinfoView(APIView):
class AppReleaseInfoView(APIView):
authentication_classes = [ExpiringTokenAuthentication, ]
def get(self, request, app_id, act):
res = BaseResponse()
res.data = {}
if app_id:
apps_obj = Apps.objects.filter(user_id=request.user, app_id=app_id).first()
if apps_obj:
app_obj = Apps.objects.filter(user_id=request.user, app_id=app_id).first()
if app_obj:
storage = Storage(request.user)
app_serializer = AppsSerializer(apps_obj, context={"storage": storage})
res = get_release_apps(request, res, app_serializer, apps_obj, storage)
app_serializer = AppsSerializer(app_obj, context={"storage": storage})
res = get_release_apps(request, res, app_serializer, app_obj, storage)
else:
res.msg = "未找到该应用"
res.code = 1003
@ -270,52 +269,52 @@ class AppReleaseinfoView(APIView):
def delete(self, request, app_id, act):
res = BaseResponse()
if app_id:
apps_obj = Apps.objects.filter(user_id=request.user, app_id=app_id).first()
if apps_obj:
app_obj = Apps.objects.filter(user_id=request.user, app_id=app_id).first()
if app_obj:
storage = Storage(request.user)
if act == 'screen':
screen_id = request.query_params.get('screen_id', None)
if screen_id:
screen_obj = AppScreenShot.objects.filter(pk=screen_id, app_id=apps_obj).first()
screen_obj = AppScreenShot.objects.filter(pk=screen_id, app_id=app_obj).first()
if screen_obj:
storage.delete_file(screen_obj.screenshot_url)
screen_obj.delete()
del_cache_response_by_short(apps_obj.app_id)
del_cache_response_by_short(app_obj.app_id)
return Response(res.dict)
apprelease_count = AppReleaseInfo.objects.filter(app_id=apps_obj).values("release_id").count()
appreleaseobj = AppReleaseInfo.objects.filter(app_id=apps_obj, release_id=act).first()
if appreleaseobj:
if not appreleaseobj.is_master:
logger.info("delete app release %s" % (appreleaseobj))
storage.delete_file(appreleaseobj.release_id, appreleaseobj.release_type)
delete_local_files(appreleaseobj.release_id, appreleaseobj.release_type)
storage.delete_file(appreleaseobj.icon_url)
appreleaseobj.delete()
elif appreleaseobj.is_master and apprelease_count < 2:
logger.info("delete app master release %s and clean app %s " % (appreleaseobj, apps_obj))
count = APPToDeveloper.objects.filter(app_id=apps_obj).count()
if apps_obj.issupersign or count > 0:
logger.info("app_id:%s is supersign ,delete this app need clean IOS developer" % (app_id))
IosUtils.clean_app_by_user_obj(apps_obj, request.user)
storage.delete_file(appreleaseobj.release_id, appreleaseobj.release_type)
delete_local_files(appreleaseobj.release_id, appreleaseobj.release_type)
storage.delete_file(appreleaseobj.icon_url)
del_cache_by_delete_app(apps_obj.app_id)
appreleaseobj.delete()
delete_app_screenshots_files(storage, apps_obj)
has_combo = apps_obj.has_combo
app_release_count = AppReleaseInfo.objects.filter(app_id=app_obj).values("release_id").count()
app_release_obj = AppReleaseInfo.objects.filter(app_id=app_obj, release_id=act).first()
if app_release_obj:
if not app_release_obj.is_master:
logger.info(f"delete app release {app_release_obj}")
storage.delete_file(app_release_obj.release_id, app_release_obj.release_type)
delete_local_files(app_release_obj.release_id, app_release_obj.release_type)
storage.delete_file(app_release_obj.icon_url)
app_release_obj.delete()
elif app_release_obj.is_master and app_release_count < 2:
logger.info(f"delete app master release {app_release_obj} and clean app {app_obj}")
count = APPToDeveloper.objects.filter(app_id=app_obj).count()
if app_obj.issupersign or count > 0:
logger.info(f"app_id:{app_id} is super_sign ,delete this app need clean IOS developer")
IosUtils.clean_app_by_user_obj(app_obj, request.user)
storage.delete_file(app_release_obj.release_id, app_release_obj.release_type)
delete_local_files(app_release_obj.release_id, app_release_obj.release_type)
storage.delete_file(app_release_obj.icon_url)
del_cache_by_delete_app(app_obj.app_id)
app_release_obj.delete()
delete_app_screenshots_files(storage, app_obj)
has_combo = app_obj.has_combo
if has_combo:
has_combo.has_combo = None
has_combo.save()
del_cache_response_by_short(has_combo.app_id)
apps_obj.delete()
app_obj.delete()
else:
pass
del_cache_response_by_short(apps_obj.app_id)
del_cache_response_by_short(app_obj.app_id)
return Response(res.dict)
@ -323,36 +322,36 @@ class AppReleaseinfoView(APIView):
res = BaseResponse()
res.data = {}
if app_id:
apps_obj = Apps.objects.filter(user_id=request.user, app_id=app_id).first()
if apps_obj:
appreleaseobj = AppReleaseInfo.objects.filter(app_id=apps_obj, release_id=act)
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)
data = request.data
make_master = data.get("make_master", None)
try:
if make_master and make_master == act:
AppReleaseInfo.objects.filter(app_id=apps_obj).update(**{"is_master": False})
appreleaseobj.update(**{"is_master": True})
AppReleaseInfo.objects.filter(app_id=app_obj).update(**{"is_master": False})
app_release_objs.update(**{"is_master": True})
else:
appreleaseobj.update(
**{"changelog": data.get("changelog", appreleaseobj.first().changelog)})
app_release_objs.update(
**{"changelog": data.get("changelog", app_release_objs.first().changelog)})
binary_url = data.get("binary_url", None)
if binary_url != '':
if binary_url:
if not binary_url.startswith('http'):
binary_url = 'http://%s' % binary_url
else:
binary_url = appreleaseobj.first().binary_url
binary_url = app_release_objs.first().binary_url
appreleaseobj.update(**{"binary_url": binary_url})
logger.info("update app:%s release:%s data:%s" % (apps_obj, appreleaseobj, data))
app_release_objs.update(**{"binary_url": binary_url})
logger.info(f"update app:{app_obj} release:{app_release_objs} data:{data}")
except Exception as e:
logger.error("update app:%s release:%s failed Exception:%s" % (apps_obj, appreleaseobj, e))
logger.error(f"update app:{app_obj} release:{app_release_objs} failed Exception:{e}")
res.code = 1006
res.msg = "更新失败"
return Response(res.dict)
del_cache_response_by_short(apps_obj.app_id)
app_serializer = AppsSerializer(apps_obj)
res = get_release_apps(request, res, app_serializer, apps_obj, Storage(request.user))
del_cache_response_by_short(app_obj.app_id)
app_serializer = AppsSerializer(app_obj)
res = get_release_apps(request, res, app_serializer, app_obj, Storage(request.user))
return Response(res.dict)

@ -11,8 +11,7 @@ from api.utils.baseutils import is_valid_domain, get_cname_from_domain, get_user
from api.utils.response import BaseResponse
from api.utils.auth import ExpiringTokenAuthentication
from rest_framework.response import Response
from api.models import UserDomainInfo, DomainCnameInfo, Apps
from django.db.models import Count
from api.models import UserDomainInfo, Apps
import logging
from api.utils.storage.caches import set_default_app_wx_easy, del_cache_response_by_short
@ -52,10 +51,10 @@ class DomainCnameView(APIView):
res.code = 1001
res.msg = "该域名已经被绑定,请更换其他域名"
else:
user_domian_obj = UserDomainInfo.objects.filter(**get_domain_filter(request),
user_domain_obj = UserDomainInfo.objects.filter(**get_domain_filter(request),
domain_name=domain_name).first()
if user_domian_obj:
res.data = {'cname_domain': user_domian_obj.cname_id.domain_record}
if user_domain_obj:
res.data = {'cname_domain': user_domain_obj.cname_id.domain_record}
else:
UserDomainInfo.objects.filter(**get_domain_filter(request), is_enable=False).delete()
min_domain_cname_info_obj = get_min_default_domain_cname_obj(False)
@ -80,13 +79,13 @@ class DomainCnameView(APIView):
def put(self, request):
res = BaseResponse()
user_domian_obj = UserDomainInfo.objects.filter(**get_domain_filter(request)).first()
if user_domian_obj:
cname = get_cname_from_domain(user_domian_obj.domain_name)
if cname == user_domian_obj.cname_id.domain_record + '.':
user_domian_obj.is_enable = True
user_domian_obj.save()
UserDomainInfo.objects.filter(domain_name=user_domian_obj.domain_name, is_enable=False).delete()
user_domain_obj = UserDomainInfo.objects.filter(**get_domain_filter(request)).first()
if user_domain_obj:
cname = get_cname_from_domain(user_domain_obj.domain_name)
if cname == user_domain_obj.cname_id.domain_record + '.':
user_domain_obj.is_enable = True
user_domain_obj.save()
UserDomainInfo.objects.filter(domain_name=user_domain_obj.domain_name, is_enable=False).delete()
app_id = request.data.get("app_id", None)
if app_id:
app_obj = Apps.objects.filter(app_id=app_id).first()

@ -4,13 +4,14 @@
# author: liuyu
# date: 2020/3/6
from rest_framework.views import APIView
from api.utils.TokenManager import verify_token
from api.utils.response import BaseResponse
from rest_framework.response import Response
from fir_ser import settings
from api.utils.TokenManager import DownloadToken
from api.utils.app.randomstrings import make_random_uuid
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_mobile_config, get_post_udid_url, get_redirect_server_domain
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, \
del_cache_response_by_short, consume_user_download_times, check_app_permission
@ -23,35 +24,36 @@ import logging
from api.utils.baseutils import get_profile_full_path, get_app_domain_name
from api.utils.throttle import VisitShortThrottle, InstallShortThrottle, InstallThrottle1, InstallThrottle2
logger = logging.getLogger(__file__)
logger = logging.getLogger(__name__)
class DownloadView(APIView):
'''
"""
文件下载接口,适用于本地存储和所有plist文件下载
'''
"""
def get(self, request, filename):
res = BaseResponse()
downtoken = request.query_params.get(settings.DATA_DOWNLOAD_KEY, None)
ftype = filename.split(".")[-1]
down_token = request.query_params.get(settings.DATA_DOWNLOAD_KEY, None)
f_type = filename.split(".")[-1]
flag = True
storage_obj = get_local_storage()
if storage_obj.download_auth_type == 1:
if not downtoken:
if not down_token:
res.code = 1004
res.msg = "缺失token"
logger.error(f"file {filename} download failed lost down_token")
return Response(res.dict)
dtoken = DownloadToken()
flag = dtoken.verify_token(downtoken, filename)
flag = verify_token(down_token, filename)
if flag:
if ftype == 'plist':
if f_type == 'plist':
release_id = filename.split('.')[0]
apptodev_obj = APPToDeveloper.objects.filter(binary_file=release_id).first()
if apptodev_obj:
release_obj = AppReleaseInfo.objects.filter(is_master=True, app_id=apptodev_obj.app_id).first()
app_to_developer_obj = APPToDeveloper.objects.filter(binary_file=release_id).first()
if app_to_developer_obj:
release_obj = AppReleaseInfo.objects.filter(is_master=True,
app_id=app_to_developer_obj.app_id).first()
else:
release_obj = AppReleaseInfo.objects.filter(release_id=release_id).first()
if release_obj:
@ -67,32 +69,32 @@ class DownloadView(APIView):
response['Content-Disposition'] = 'attachment; filename=' + make_random_uuid()
return response
res.msg = "plist release_id error"
elif ftype == 'mobileconifg':
elif f_type == 'mobileconifg':
release_obj = AppReleaseInfo.objects.filter(release_id=filename.split('.')[0]).first()
if release_obj:
bundle_id = release_obj.app_id.bundle_id
udid_url = get_post_udid_url(request, release_obj.app_id.short)
ios_udid_mobileconfig = make_sign_udid_mobileconfig(udid_url, bundle_id, release_obj.app_id.name)
response = FileResponse(ios_udid_mobileconfig)
ios_udid_mobile_config = make_sign_udid_mobile_config(udid_url, bundle_id, release_obj.app_id.name)
response = FileResponse(ios_udid_mobile_config)
response['Content-Type'] = "application/x-apple-aspen-config"
response['Content-Disposition'] = 'attachment; filename=' + make_random_uuid() + '.mobileconfig'
return response
res.msg = "mobileconifg release_id error"
elif ftype == 'mobileprovision':
res.msg = "mobile_config release_id error"
elif f_type == 'mobileprovision':
release_obj = AppReleaseInfo.objects.filter(release_id=filename.split('.')[0]).first()
if release_obj:
appsuper_obj = APPSuperSignUsedInfo.objects.filter(app_id=release_obj.app_id).last()
if not appsuper_obj:
appsuper_obj = APPSuperSignUsedInfo.objects.last()
app_super_obj = APPSuperSignUsedInfo.objects.filter(app_id=release_obj.app_id).last()
if not app_super_obj:
app_super_obj = APPSuperSignUsedInfo.objects.last()
if not appsuper_obj:
if not app_super_obj:
file_path = settings.DEFAULT_MOBILEPROVISION.get("supersign").get('path')
if os.path.isfile(file_path):
response = FileResponse(open(file_path, 'rb'))
else:
response = FileResponse()
else:
developer_obj = appsuper_obj.developerid
developer_obj = app_super_obj.developerid
file_path = get_profile_full_path(developer_obj, release_obj.app_id)
if os.path.isfile(file_path):
response = FileResponse(open(file_path, 'rb'))
@ -105,8 +107,8 @@ class DownloadView(APIView):
response['Content-Type'] = "application/x-apple-aspen-config"
response['Content-Disposition'] = 'attachment; filename=' + make_random_uuid() + '.mobileprovision'
return response
res.msg = "mobileprovision release_id error"
elif ftype == 'dmobileprovision':
res.msg = "mobile_provision release_id error"
elif f_type == 'dmobileprovision':
release_obj = AppReleaseInfo.objects.filter(release_id=filename.split('.')[0]).first()
if release_obj:
file_path = settings.DEFAULT_MOBILEPROVISION.get("supersign").get('path')
@ -117,7 +119,7 @@ class DownloadView(APIView):
response['Content-Type'] = "application/x-apple-aspen-config"
response['Content-Disposition'] = 'attachment; filename=' + make_random_uuid() + '.mobileprovision'
return response
res.msg = "dmobileprovision release_id error"
res.msg = "d_mobile_provision release_id error"
else:
file_path = os.path.join(settings.MEDIA_ROOT, filename)
@ -127,7 +129,7 @@ class DownloadView(APIView):
else:
response = FileResponse()
except Exception as e:
logger.error("read %s failed Exception:%s" % (file_path, e))
logger.error(f"read {file_path} failed Exception:{e}")
response = FileResponse()
response['content_type'] = "application/octet-stream"
response['Content-Disposition'] = 'attachment; filename=' + filename
@ -135,6 +137,7 @@ class DownloadView(APIView):
res.code = 1004
res.msg = "token校验失败"
logger.error(f"file {filename} download failed. down_token verify failed")
return Response(res.dict)
@ -178,8 +181,7 @@ class ShortDownloadView(APIView):
udid = time
if not udid:
udid = ""
logging.info(
"get or make cache_response short:%s release_id:%s udid:%s" % (kwargs.get("short", ''), release_id, udid))
logging.info(f"get or make cache_response short:{kwargs.get('short', '')} release_id:{release_id} udid:{udid}")
return "_".join(
[settings.CACHE_KEY_TEMPLATE.get("download_short_key"), kwargs.get("short", ''), release_id, udid])
@ -192,32 +194,32 @@ class InstallView(APIView):
def get(self, request, app_id):
res = BaseResponse()
downtoken = request.query_params.get("token", None)
short = request.query_params.get("short", None)
release_id = request.query_params.get("release_id", None)
isdownload = request.query_params.get("isdownload", None)
password = request.query_params.get("password", None)
udid = request.query_params.get("udid", None)
query_params = request.query_params
downtoken = query_params.get("token", None)
short = query_params.get("short", None)
release_id = query_params.get("release_id", None)
isdownload = query_params.get("isdownload", None)
password = query_params.get("password", None)
udid = query_params.get("udid", None)
if not downtoken or not short or not release_id:
res.code = 1004
res.msg = "参数丢失"
return Response(res.dict)
dtoken = DownloadToken()
if dtoken.verify_token(downtoken, release_id):
if verify_token(downtoken, release_id):
app_obj = get_app_instance_by_cache(app_id, password, 900, udid)
if app_obj:
if app_obj.get("type") == 0:
apptype = '.apk'
download_url, extra_url = get_download_url_by_cache(app_obj, release_id + apptype, 600)
app_type = '.apk'
download_url, extra_url = get_download_url_by_cache(app_obj, release_id + app_type, 600)
else:
apptype = '.ipa'
app_type = '.ipa'
if isdownload:
download_url, extra_url = get_download_url_by_cache(app_obj, release_id + apptype, 600,
download_url, extra_url = get_download_url_by_cache(app_obj, release_id + app_type, 600,
udid=udid)
else:
download_url, extra_url = get_download_url_by_cache(app_obj, release_id + apptype, 600,
download_url, extra_url = get_download_url_by_cache(app_obj, release_id + app_type, 600,
isdownload,
udid=udid)
@ -227,7 +229,7 @@ class InstallView(APIView):
ip = request.META['HTTP_X_FORWARDED_FOR']
else:
ip = request.META['REMOTE_ADDR']
logger.info("remote ip %s short %s download_url %s app_obj %s" % (ip, short, download_url, app_obj))
logger.info(f"remote ip {ip} short {short} download_url {download_url} app_obj {app_obj}")
set_app_download_by_cache(app_id)
amount = app_obj.get("d_count")
# # 超级签需要多消耗2倍下载次数

@ -5,15 +5,13 @@ from rest_framework.response import Response
from api.utils.serializer import UserInfoSerializer, CertificationSerializer, UserCertificationSerializer
from django.core.cache import cache
from rest_framework.views import APIView
import binascii
import os, datetime
from api.utils.utils import get_captcha, valid_captcha, \
get_sender_sms_token, is_valid_sender_code, get_sender_email_token, get_random_username, \
check_username_exists
check_username_exists, set_user_token
from api.utils.baseutils import is_valid_phone, is_valid_email, get_min_default_domain_cname_obj
from api.utils.auth import ExpiringTokenAuthentication
from api.utils.response import BaseResponse
from fir_ser.settings import CACHE_KEY_TEMPLATE, REGISTER, LOGIN, CHANGER
from fir_ser.settings import REGISTER, LOGIN, CHANGER
from api.utils.storage.caches import login_auth_failed
import logging
from api.utils.geetest.geetest_utils import first_register, second_validate
@ -31,17 +29,17 @@ def get_register_type():
return REGISTER.get("register_type")
def reset_user_pwd(user, surepassword, oldpassword=''):
def reset_user_pwd(user, sure_password, old_password=''):
if user is not None:
user.set_password(surepassword)
user.set_password(sure_password)
user.save()
logger.info("user:%s change password success,old %s new %s" % (user, oldpassword, surepassword))
logger.info(f"user:{user} change password success,old {old_password} new {sure_password}")
for token_obj in Token.objects.filter(user=user):
cache.delete(token_obj.access_token)
token_obj.delete()
def GetAuthenticate(target, password, act, allow_type):
def get_authenticate(target, password, act, allow_type):
user_obj = None
if act == 'email' and allow_type[act]:
if is_valid_email(target):
@ -58,7 +56,7 @@ def GetAuthenticate(target, password, act, allow_type):
return user_obj
def CheckRegisterUerinfo(target, act, key):
def check_register_userinfo(target, act, key):
res = BaseResponse()
res.data = {}
times_key = "%s_%s_%s" % (key, act, target)
@ -121,7 +119,7 @@ def CheckRegisterUerinfo(target, act, key):
return res
def CheckChangeUerinfo(target, act, key, user, ftype=None):
def check_change_userinfo(target, act, key, user, ftype=None):
res = BaseResponse()
res.data = {}
@ -186,9 +184,6 @@ def CheckChangeUerinfo(target, act, key, user, ftype=None):
class LoginView(APIView):
throttle_classes = [VisitRegister1Throttle, VisitRegister2Throttle]
def generate_key(self):
return binascii.hexlify(os.urandom(32)).decode()
def post(self, request):
response = BaseResponse()
receive = request.data
@ -217,7 +212,7 @@ class LoginView(APIView):
msg = '您的新密码为 %s 请用新密码登录之后,及时修改密码' % password
a, b = get_sender_email_token('email', username, 'msg', msg)
if a and b:
reset_user_pwd(user_obj, password, oldpassword='')
reset_user_pwd(user_obj, password)
login_auth_failed("del", username)
else:
response.code = 1002
@ -228,20 +223,13 @@ class LoginView(APIView):
return Response(response.dict)
password = receive.get("password")
user = GetAuthenticate(username, password, login_type, get_login_type())
logger.info("username:%s password:%s" % (username, password))
user = get_authenticate(username, password, login_type, get_login_type())
logger.info(f"username:{username} password:{password}")
if user:
if user.is_active:
login_auth_failed("del", username)
# update the token
key = self.generate_key()
now = datetime.datetime.now()
user_info = UserInfo.objects.get(pk=user.pk)
auth_key = "_".join([CACHE_KEY_TEMPLATE.get('user_auth_token_key'), key])
cache.set(auth_key, {'uid': user_info.uid, 'username': user_info.username}, 3600 * 24 * 7)
Token.objects.create(user=user, **{"access_token": key, "created": now})
key, user_info = set_user_token(user)
serializer = UserInfoSerializer(user_info, )
data = serializer.data
response.msg = "验证成功!"
@ -262,7 +250,7 @@ class LoginView(APIView):
# response.code = 1003
else:
response.code = 1006
logger.error("username:%s failed too try , locked" % (username,))
logger.error(f"username:{username} failed too try , locked")
response.msg = "用户登录失败次数过多,已被锁定,请1小时之后再次尝试"
else:
response.code = 1001
@ -298,9 +286,6 @@ class LoginView(APIView):
class RegistView(APIView):
throttle_classes = [VisitRegister1Throttle, VisitRegister2Throttle]
def generate_key(self):
return binascii.hexlify(os.urandom(32)).decode()
def post(self, request):
response = BaseResponse()
receive = request.data
@ -395,11 +380,11 @@ class UserInfoView(APIView):
def put(self, request):
res = BaseResponse()
data = request.data
logger.info("user:%s update old data:%s" % (request.user, request.user.__dict__))
logger.info("user:%s update new data:%s" % (request.user, data))
logger.info(f"user:{request.user} update old data:{request.user.__dict__}")
logger.info(f"user:{request.user} update new data:{data}")
oldpassword = data.get("oldpassword", None)
surepassword = data.get("surepassword", None)
old_password = data.get("oldpassword", None)
sure_password = data.get("surepassword", None)
mobile = data.get("mobile", None)
email = data.get("email", None)
@ -411,13 +396,13 @@ class UserInfoView(APIView):
res.msg = "图片验证码异常"
return Response(res.dict)
if oldpassword and surepassword:
user = auth.authenticate(username=request.user.username, password=oldpassword)
if old_password and sure_password:
user = auth.authenticate(username=request.user.username, password=old_password)
if user is not None:
user.set_password(surepassword)
user.set_password(sure_password)
user.save()
res.msg = "密码修改成功"
logger.info("user:%s change password success,old %s new %s" % (request.user, oldpassword, surepassword))
logger.info(f"user:{request.user} change password success,old {old_password} new {sure_password}")
auth_token = request.auth
for token_obj in Token.objects.filter(user=user):
@ -435,7 +420,7 @@ class UserInfoView(APIView):
if check_username_exists(username):
res.msg = "用户名已经存在"
res.code = 1005
logger.error("User %s info save failed. Excepiton:%s" % (request.user, 'username already exists'))
logger.error(f"User {request.user} info save failed. username already exists")
return Response(res.dict)
if len(username) < 6:
res.msg = "用户名至少6位"
@ -480,7 +465,7 @@ class UserInfoView(APIView):
res.data = serializer.data
res.code = 1004
res.msg = "信息保存失败"
logger.error("User %s info save failed. Excepiton:%s" % (request.user, e))
logger.error(f"User {request.user} info save failed. Exception:{e}")
return Response(res.dict)
serializer = UserInfoSerializer(request.user)
res.data = serializer.data
@ -525,7 +510,7 @@ class AuthorizationView(APIView):
res.msg = "geetest验证有误"
return Response(res.dict)
res = CheckRegisterUerinfo(target, act, 'register')
res = check_register_userinfo(target, act, 'register')
return Response(res.dict)
@ -540,7 +525,7 @@ class ChangeAuthorizationView(APIView):
act = request.data.get("act", None)
target = request.data.get("target", None)
ext = request.data.get("ext", None)
ftype = request.data.get("ftype", None)
f_type = request.data.get("ftype", None)
if REGISTER.get("captcha"):
if ext and valid_captcha(ext.get("cptch_key", None), ext.get("authcode", None), target):
pass
@ -558,7 +543,7 @@ class ChangeAuthorizationView(APIView):
res.msg = "geetest验证有误"
return Response(res.dict)
res = CheckChangeUerinfo(target, act, 'change', request.user, ftype)
res = check_change_userinfo(target, act, 'change', request.user, f_type)
return Response(res.dict)
@ -576,13 +561,13 @@ class UserApiTokenView(APIView):
res = BaseResponse()
data = request.data
oldtoken = data.get("token", None)
if oldtoken == request.user.api_token:
old_token = data.get("token", None)
if old_token == request.user.api_token:
request.user.api_token = 'reset'
try:
request.user.save()
except Exception as e:
logger.error("User %s api_token save failed. Excepiton:%s" % (request.user, e))
logger.error(f"User {request.user} api_token save failed. Exception:{e}")
res.code = 1002
res.msg = "token 生成失败"
return Response(res.dict)
@ -616,7 +601,6 @@ class CertificationView(APIView):
if 'certpic' in act:
certification_obj = CertificationInfo.objects.filter(user_id=request.user).all()
if certification_obj:
storage = Storage(request.user)
certification_serializer = CertificationSerializer(certification_obj, many=True)
res.data["certification"] = certification_serializer.data
return Response(res.dict)
@ -655,7 +639,7 @@ class CertificationView(APIView):
return Response(res.dict)
else:
res.code = 1006
logger.error("username:%s failed too try , locked" % (request.user,))
logger.error(f"username:{request.user} failed too try , locked")
res.msg = "用户注册失败次数过多,已被锁定,请1小时之后再次尝试"
else:
res.code = 1001
@ -670,7 +654,7 @@ class CertificationView(APIView):
return Response(res.dict)
return self.get(request)
except Exception as e:
logger.error("%s UserCertificationInfo save %s failed Exception: %s" % (request.user, data, e))
logger.error(f"{request.user} UserCertificationInfo save {data} failed Exception: {e}")
res.msg = "数据异常,请检查"
res.code = 1002
return Response(res.dict)

@ -6,14 +6,14 @@ from rest_framework.response import Response
from django.contrib import auth
import logging
logger = logging.getLogger(__file__)
logger = logging.getLogger(__name__)
class LogoutView(APIView):
authentication_classes = [ExpiringTokenAuthentication]
def delete(self, request):
logger.info("user:%s logout" % (request.user))
logger.info(f"user:{request.user} logout")
user = request.user.pk
auth_token = request.auth
cache.delete(auth_token)

@ -62,7 +62,7 @@ class OrderView(APIView):
pay_url = pay_obj.get_pay_pc_url(order_number, int(order_obj.actual_amount),
{'user_id': request.user.id})
res.data = pay_url
logger.info("%s 下单成功 %s" % (request.user, res.dict))
logger.info(f"{request.user} 下单成功 {res.dict}")
return Response(res.dict)
if price_obj:
try:
@ -75,14 +75,14 @@ class OrderView(APIView):
actual_download_times=price_obj.package_size, payment_name=pay_obj.name,
actual_download_gift_times=price_obj.download_count_gift)
res.data = pay_url
logger.info("%s 下单成功 %s" % (request.user, res.dict))
logger.info(f"{request.user} 下单成功 {res.dict}")
return Response(res.dict)
except Exception as e:
logger.error("%s 订单 %s 保存失败 Exception:%s" % (request.user, price_id, e))
logger.error(f"{request.user} 订单 {price_id} 保存失败 Exception:{e}")
res.code = 1003
res.msg = "订单保存失败"
else:
logger.error("%s 价格 %s 获取失败" % (request.user, price_id))
logger.error(f"{request.user} 价格 {price_id} 获取失败")
res.code = 1002
res.msg = "价格获取失败,请稍后重试"
else:
@ -107,11 +107,11 @@ class OrderView(APIView):
# wxpay = Weixinpay()
# wxpay.update_order_status(order_obj.order_number)
except Exception as e:
logger.error("%s 订单 %s 更新失败 Exception:%s" % (request.user, order_number, e))
logger.error(f"{request.user} 订单 {order_number} 更新失败 Exception:{e}")
res.code = 1003
return Response(res.dict)
else:
logger.error("%s 订单 %s 获取失败" % (request.user, order_number))
logger.error(f"{request.user} 订单 {order_number} 获取失败")
res.code = 1003
res.msg = "订单获取失败,或订单已经支付"
else:
@ -130,11 +130,11 @@ class PriceView(APIView):
res.pay_choices = get_enable_pay_choices()
return Response(res.dict)
def delete(self, request, price_id):
def delete(self, request):
res = BaseResponse()
return Response(res.dict)
def put(self, request, price_id):
def put(self, request):
res = BaseResponse()
return Response(res.dict)
@ -149,8 +149,8 @@ class PaySuccess(APIView):
pay_obj = get_pay_obj_form_name(name)
msg = 'failure'
if pay_obj:
logger.info("支付回调参数:%s" % request.body)
logger.info("支付回调头部:%s" % request.META)
logger.info(f"支付回调参数:{request.body}")
logger.info(f"支付回调头部:{request.META}")
if pay_obj.p_type == 'ALI':
if pay_obj.valid_order(request):
msg = 'success'

@ -20,7 +20,7 @@ from rest_framework.views import APIView
from api.utils.baseutils import get_app_domain_name
from celery.exceptions import TimeoutError
logger = logging.getLogger(__file__)
logger = logging.getLogger(__name__)
class IosUDIDView(View):
@ -29,7 +29,7 @@ class IosUDIDView(View):
def post(self, request, short):
stream_f = str(request.body)
format_udid_info = udid_bytes_to_dict(stream_f)
logger.info("short %s get new udid %s" % (short, format_udid_info))
logger.info(f"short {short} receive new udid {format_udid_info}")
server_domain = get_redirect_server_domain(request)
try:
app_info = Apps.objects.filter(short=short).first()
@ -42,7 +42,7 @@ class IosUDIDView(View):
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))
logger.info(f"sign app {app_info} task_id:{task_id}")
try:
result = c_task.get(propagate=False, timeout=2)
except TimeoutError:
@ -60,7 +60,7 @@ class IosUDIDView(View):
"%s/%s" % (server_domain, short))
except Exception as e:
msg = "&msg=系统内部错误"
logger.error("short %s receive udid Exception:%s" % (short, e))
logger.error(f"short {short} receive udid Exception:{e}")
return HttpResponsePermanentRedirect(
"%s/%s?udid=%s%s" % (server_domain, short, format_udid_info.get("udid"), msg))
@ -75,7 +75,7 @@ class TaskView(APIView):
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()))
logger.info(f"app {app_info} sign task state {result.state} AA {result.successful()}")
if result.successful():
res.msg = result.get(propagate=False)
return Response(res.dict)

@ -10,14 +10,12 @@ from api.base_views import storage_change
from api.utils.response import BaseResponse
from api.utils.auth import ExpiringTokenAuthentication, StoragePermission
from rest_framework.response import Response
from api.utils.storage.caches import del_cache_storage
from api.models import AppStorage, UserInfo
from api.utils.utils import upload_oss_default_head_img, \
change_storage_and_change_head_img, migrating_storage_data, clean_storage_data, get_choices_dict
from api.utils.utils import upload_oss_default_head_img, get_choices_dict
from api.utils.serializer import StorageSerializer
import logging
logger = logging.getLogger(__file__)
logger = logging.getLogger(__name__)
class StorageView(APIView):
@ -65,25 +63,25 @@ class StorageView(APIView):
def post(self, request):
res = BaseResponse()
data = request.data
logger.info("user %s add new storage data:%s" % (request.user, data))
logger.info(f"user {request.user} add new storage data:{data}")
serializer = StorageSerializer(data=data, context={'user_obj': request.user})
if serializer.is_valid():
storage_obj = serializer.save()
if storage_obj:
if upload_oss_default_head_img(request.user, storage_obj):
res.msg = serializer.validated_data
logger.info("user %s add new storage success" % (request.user))
logger.info(f"user {request.user} add new storage success")
else:
storage_obj.delete()
logger.error("user %s add new storage failed" % (request.user))
logger.error(f"user {request.user} add new storage failed")
res.msg = "文件上传校验失败,请检查参数是否正确"
res.code = 1005
else:
logger.info("user %s add new storage failed" % (request.user))
logger.info(f"user {request.user} add new storage failed")
res.msg = serializer.errors
res.code = 1005
else:
logger.info("user %s add new storage failed" % (request.user))
logger.info(f"user {request.user} add new storage failed")
res.msg = serializer.errors
res.code = 1005
return Response(res.dict)
@ -91,7 +89,7 @@ class StorageView(APIView):
def put(self, request):
res = BaseResponse()
data = request.data
logger.info("user %s update storage data:%s" % (request.user, data))
logger.info(f"user {request.user} update storage data:{data}")
use_storage_id = data.get("use_storage_id", None)
force = data.get("force", None)
if use_storage_id:
@ -115,14 +113,14 @@ class StorageView(APIView):
if new_storage_obj:
if upload_oss_default_head_img(request.user, new_storage_obj):
res.msg = serializer.validated_data
logger.info("user %s update storage success" % (request.user))
logger.info(f"user {request.user} update storage success")
else:
storage_obj_bak.save()
logger.error("user %s update storage failed" % (request.user))
logger.error(f"user {request.user} update storage failed")
res.msg = "文件上传校验失败,请检查参数是否正确"
res.code = 1005
else:
logger.info("user %s update storage failed" % (request.user))
logger.info(f"user {request.user} update storage failed")
res.msg = serializer.errors
res.code = 1005
else:
@ -139,9 +137,9 @@ class StorageView(APIView):
if storage_id:
try:
AppStorage.objects.filter(user_id=request.user, id=storage_id).delete()
logger.error("user %s delete storage id:%s success" % (request.user, storage_id))
logger.error(f"user {request.user} delete storage id:{storage_id} success")
except Exception as e:
logger.error("user %s delete storage id:%s failed Exception:%s" % (request.user, storage_id, e))
logger.error(f"user {request.user} delete storage id:{storage_id} failed Exception:{e}")
else:
res.code = 1004
res.msg = '该存储不存在'

@ -6,19 +6,17 @@
from django.http.response import FileResponse
from rest_framework.views import APIView
from api.utils.app.iossignapi import ResignApp
from api.utils.baseutils import file_format_path
from api.utils.response import BaseResponse
from api.utils.auth import ExpiringTokenAuthentication, SuperSignPermission
from rest_framework.response import Response
from api.models import AppIOSDeveloperInfo, APPSuperSignUsedInfo, AppUDID
from api.utils.serializer import DeveloperSerializer, SuperSignUsedSerializer, DeviceUDIDSerializer
from rest_framework.pagination import PageNumberPagination
from api.utils.app.supersignutils import IosUtils, get_auth_form_developer
from api.utils.app.supersignutils import IosUtils
from api.utils.utils import get_developer_devices, get_choices_dict
import logging
logger = logging.getLogger(__file__)
logger = logging.getLogger(__name__)
class PageNumber(PageNumberPagination):
@ -36,11 +34,11 @@ class DeveloperView(APIView):
res = BaseResponse()
appid = request.query_params.get("appid", None)
app_id = request.query_params.get("appid", None)
developer_obj = AppIOSDeveloperInfo.objects.filter(user_id=request.user)
res.use_num = get_developer_devices(developer_obj)
if appid:
developer_obj = developer_obj.filter(issuer_id=appid)
if app_id:
developer_obj = developer_obj.filter(issuer_id=app_id)
page_obj = PageNumber()
app_page_serializer = page_obj.paginate_queryset(queryset=developer_obj.order_by("-updated_time"),
@ -66,7 +64,7 @@ class DeveloperView(APIView):
act = data.get("act", None)
if act:
res = BaseResponse()
logger.info("user %s iosdeveloper %s act %s" % (request.user, developer_obj, act))
logger.info(f"user {request.user} ios developer {developer_obj} act {act}")
if act == "checkauth":
status, result = IosUtils.active_developer(developer_obj)
if status:
@ -112,16 +110,16 @@ class DeveloperView(APIView):
res.msg = result.get("err_info")
return Response(res.dict)
else:
logger.info("user %s iosdeveloper %s update input data %s" % (request.user, developer_obj, data))
logger.info("user %s iosdeveloper %s update old data %s" % (
request.user, developer_obj, developer_obj.__dict__))
logger.info(f"user {request.user} ios developer {developer_obj} update input data {data}")
logger.info(
f"user {request.user} ios developer {developer_obj} update old data {developer_obj.__dict__}")
try:
usable_number = int(data.get("usable_number", developer_obj.usable_number))
if 0 <= usable_number <= 100:
developer_obj.usable_number = usable_number
except Exception as e:
logger.error("developer %s usable_number %s get failed Exception:%s" % (
developer_obj, data.get("usable_number", developer_obj.usable_number), e))
logger.error(
f"developer {developer_obj} usable_number {data.get('usable_number', developer_obj.usable_number)} get failed Exception:{e}")
developer_obj.description = data.get("description", developer_obj.description)
private_key_id = data.get("private_key_id", developer_obj.private_key_id)
p8key = data.get("p8key", developer_obj.p8key)
@ -133,19 +131,19 @@ class DeveloperView(APIView):
developer_obj.is_actived = False
try:
developer_obj.save()
logger.info("user %s iosdeveloper %s update now data %s" % (
request.user, developer_obj, developer_obj.__dict__))
logger.info(
f"user {request.user} ios developer {developer_obj} update now data {developer_obj.__dict__}")
except Exception as e:
logger.error("user %s iosdeveloper %s update error data %s Exception %s" % (
request.user, developer_obj, data, e))
logger.error(
f"user {request.user} ios developer {developer_obj} update error data {data} Exception {e}")
return self.get(request)
def post(self, request):
data = request.data
datainfo = {}
data_info = {}
if data.get("auth_type") == 0:
datainfo = {
data_info = {
"usable_number": data.get("usable_number", ""),
"description": data.get("description", ""),
"issuer_id": data.get("issuer_id", ""),
@ -154,13 +152,11 @@ class DeveloperView(APIView):
"auth_type": 0
}
try:
logger.error("user %s add new developer %s data %s" % (
request.user, data.get("issuer_id", ""), datainfo))
developer_obj = AppIOSDeveloperInfo.objects.create(user_id=request.user, **datainfo)
logger.error(f"user {request.user} add new developer {data.get('issuer_id', '')} data {data_info}")
developer_obj = AppIOSDeveloperInfo.objects.create(user_id=request.user, **data_info)
IosUtils.create_developer_space(developer_obj, request.user)
except Exception as e:
logger.error("user %s create developer %s failed Exception:%s" % (
request.user, datainfo, e))
logger.error(f"user {request.user} create developer {data_info} failed Exception:{e}")
res = BaseResponse()
res.code = 1005
res.msg = "添加失败"
@ -176,8 +172,7 @@ class DeveloperView(APIView):
return self.get(request)
if developer_obj:
logger.error("user %s delete developer %s " % (
request.user, developer_obj))
logger.error(f"user {request.user} delete developer {developer_obj}")
IosUtils.clean_developer(developer_obj, request.user)
IosUtils.revoke_developer_cert(developer_obj, request.user)
developer_obj.delete()
@ -193,25 +188,25 @@ class SuperSignUsedView(APIView):
res = BaseResponse()
udid = request.query_params.get("udid", None)
bundleid = request.query_params.get("bundleid", None)
developerid = request.query_params.get("appid", None)
bundle_id = request.query_params.get("bundleid", None)
developer_id = request.query_params.get("appid", None)
SuperSignUsed_obj = APPSuperSignUsedInfo.objects.filter(user_id=request.user, )
super_sign_used_objs = APPSuperSignUsedInfo.objects.filter(user_id=request.user, )
if developerid:
SuperSignUsed_obj = SuperSignUsed_obj.filter(developerid__issuer_id=developerid)
if developer_id:
super_sign_used_objs = super_sign_used_objs.filter(developerid__issuer_id=developer_id)
if udid:
SuperSignUsed_obj = SuperSignUsed_obj.filter(udid__udid=udid)
if bundleid:
SuperSignUsed_obj = SuperSignUsed_obj.filter(app_id__bundle_id=bundleid)
super_sign_used_objs = super_sign_used_objs.filter(udid__udid=udid)
if bundle_id:
super_sign_used_objs = super_sign_used_objs.filter(app_id__bundle_id=bundle_id)
page_obj = PageNumber()
app_page_serializer = page_obj.paginate_queryset(queryset=SuperSignUsed_obj.order_by("-created_time"),
app_page_serializer = page_obj.paginate_queryset(queryset=super_sign_used_objs.order_by("-created_time"),
request=request,
view=self)
app_serializer = SuperSignUsedSerializer(app_page_serializer, many=True, )
res.data = app_serializer.data
res.count = SuperSignUsed_obj.count()
res.count = super_sign_used_objs.count()
return Response(res.dict)
@ -223,29 +218,29 @@ class AppUDIDUsedView(APIView):
res = BaseResponse()
udid = request.query_params.get("udid", None)
bundleid = request.query_params.get("bundleid", None)
AppUDID_obj = AppUDID.objects.filter(app_id__user_id_id=request.user)
bundle_id = request.query_params.get("bundleid", None)
app_udid_objs = AppUDID.objects.filter(app_id__user_id_id=request.user)
if udid:
AppUDID_obj = AppUDID_obj.filter(udid=udid)
if bundleid:
AppUDID_obj = AppUDID_obj.filter(app_id__bundle_id=bundleid)
app_udid_objs = app_udid_objs.filter(udid=udid)
if bundle_id:
app_udid_objs = app_udid_objs.filter(app_id__bundle_id=bundle_id)
page_obj = PageNumber()
app_page_serializer = page_obj.paginate_queryset(queryset=AppUDID_obj.order_by("-created_time"),
app_page_serializer = page_obj.paginate_queryset(queryset=app_udid_objs.order_by("-created_time"),
request=request,
view=self)
app_serializer = DeviceUDIDSerializer(app_page_serializer, many=True, )
res.data = app_serializer.data
res.count = AppUDID_obj.count()
res.count = app_udid_objs.count()
return Response(res.dict)
def delete(self, request):
res = BaseResponse()
id = request.query_params.get("id", None)
pk = request.query_params.get("id", None)
app_id = request.query_params.get("aid", None)
app_udid_obj = AppUDID.objects.filter(app_id__user_id_id=request.user, pk=id)
app_udid_obj = AppUDID.objects.filter(app_id__user_id_id=request.user, pk=pk)
if app_udid_obj:
logger.error("user %s delete devices %s" % (request.user, app_udid_obj))
logger.error(f"user {request.user} delete devices {app_udid_obj}")
IosUtils.disable_udid(app_udid_obj.first(), app_id)
app_udid_obj.delete()
return Response(res.dict)
@ -281,12 +276,12 @@ class SuperSignCertView(APIView):
status, result = resign_app_obj.make_cert_from_p12(request.data.get('cert_pwd', ''),
request.data.get('cert_content', None))
if status:
status, result = IosUtils.auto_get_certid_by_p12(developer_obj, request.user)
status, result = IosUtils.auto_get_cert_id_by_p12(developer_obj, request.user)
if status:
resign_app_obj.write_cert()
else:
res.code = 1003
res.msg = str('证书未在开发者账户找到,请检查推送证书是否属于该开发者')
res.msg = '证书未在开发者账户找到,请检查推送证书是否属于该开发者'
else:
res.code = 1002
res.msg = str(result['err_info'])

@ -3,10 +3,10 @@
# project: 3月
# author: liuyu
# date: 2020/3/6
from api.utils.app.apputils import get_random_short, SaveAppInfos
from api.utils.TokenManager import verify_token
from api.utils.app.apputils import get_random_short, save_app_infos
from api.utils.baseutils import get_app_domain_name
from api.utils.storage.storage import Storage, get_local_storage
from api.utils.storage.storage import Storage
from api.utils.storage.caches import upload_file_tmp_name, del_cache_response_by_short
from api.models import Apps, AppReleaseInfo, UserInfo, AppScreenShot, CertificationInfo
from api.utils.app.randomstrings import make_app_uuid
@ -16,33 +16,32 @@ from api.utils.auth import ExpiringTokenAuthentication
from api.utils.app.randomstrings import make_from_user_uuid
from rest_framework.response import Response
from fir_ser import settings
from api.utils.TokenManager import DownloadToken
from api.utils.app.supersignutils import get_redirect_server_domain
from api.tasks import run_resign_task
import os, json, logging
logger = logging.getLogger(__file__)
logger = logging.getLogger(__name__)
class AppAnalyseView(APIView):
authentication_classes = [ExpiringTokenAuthentication, ]
def post(self, request):
'''
"""
应用上传前 分析数据并返回应用上传信息
:param request:
:return:
'''
"""
res = BaseResponse()
# 1.接收 bundelid ,返回随机应用名称和短连接
bundleid = request.data.get("bundleid", None)
bundle_id = request.data.get("bundleid", None)
app_type = request.data.get("type", None)
if bundleid and app_type:
if bundle_id and app_type:
ap = 'apk'
if app_type.lower() == 'iOS'.lower():
ap = 'ipa'
app_uuid = make_app_uuid(request.user, bundleid + ap)
app_uuid = make_app_uuid(request.user, bundle_id + ap)
release_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()
@ -85,14 +84,14 @@ class AppAnalyseView(APIView):
return Response(res.dict)
def put(self, request):
'''
"""
该方法就是 应用上传完成之后的回调方法更新或者创建新应用信息
:param request:
:return:
'''
"""
res = BaseResponse()
data = request.data
appinfo = {
app_info = {
"labelname": data.get("appname"),
"version": data.get("buildversion"),
"versioncode": data.get("version"),
@ -110,19 +109,19 @@ class AppAnalyseView(APIView):
png_tmp_filename = data.get("png_key")
png_new_filename = data.get("png_key").strip(settings.FILE_UPLOAD_TMP_KEY)
logger.info("user %s create or update app %s data:%s" % (request.user, data.get("bundleid"), data))
if SaveAppInfos(app_new_filename, request.user, appinfo,
data.get("bundleid"), png_new_filename, data.get("short"), data.get('filesize')):
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,
data.get("bundleid"), png_new_filename, data.get("short"), data.get('filesize')):
# 需要将tmp 文件修改为正式文件
storage.rename_file(app_tmp_filename, app_new_filename)
storage.rename_file(png_tmp_filename, png_new_filename)
app_info = Apps.objects.filter(bundle_id=data.get("bundleid")).first()
if app_info:
if app_info.issupersign and app_info.user_id.supersign_active:
c_task = run_resign_task.apply_async((app_info.app_id, False))
app_obj = Apps.objects.filter(bundle_id=data.get("bundleid")).first()
if app_obj:
if app_obj.issupersign and app_obj.user_id.supersign_active:
c_task = run_resign_task.apply_async((app_obj.app_id, False))
msg = c_task.get(propagate=False)
logger.info("app %s run_resign_task msg:%s" % (app_info, msg))
logger.info(f"app {app_obj} run_resign_task msg:{msg}")
if c_task.successful():
c_task.forget()
else:
@ -133,7 +132,7 @@ class AppAnalyseView(APIView):
upload_file_tmp_name("del", png_tmp_filename, request.user.id)
except Exception as e:
logger.error("user %s %s save app info failed Exception:%s" % (request.user, data.get("bundleid"), e))
logger.error(f"user {request.user} save app {data.get('bundleid')} info {app_info} failed Exception:{e}")
res.code = 10003
res.msg = 'save app info failed'
@ -141,27 +140,27 @@ class AppAnalyseView(APIView):
class UploadView(APIView):
'''
"""
上传文件接口
'''
"""
authentication_classes = [ExpiringTokenAuthentication, ]
def get(self, request):
'''
"""
该方法 主要是本地上传通过该方法获取上传的 应用图片或者用户头像 的上传信息
:param request:
:return:
'''
"""
res = BaseResponse()
storage = Storage(request.user)
request_upload_key = request.query_params.get("upload_key", None)
app_id = request.query_params.get("app_id", None)
ftype = request.query_params.get("ftype", None)
if ftype and app_id and request_upload_key:
if ftype == 'app' or ftype == 'screen':
f_type = request.query_params.get("ftype", None)
if f_type and app_id and request_upload_key:
if f_type == 'app' or f_type == 'screen':
app_obj = Apps.objects.filter(app_id=app_id, user_id=request.user).first()
elif ftype and ftype in ['head', 'certification']:
elif f_type and f_type in ['head', 'certification']:
if request.user.uid != app_id:
res.code = 1007
res.msg = '该用户不存在'
@ -177,7 +176,7 @@ class UploadView(APIView):
res.code = 1006
res.msg = '类型不允许'
else:
if ftype and ftype == 'certification':
if f_type and f_type == 'certification':
storage = Storage(request.user, None, True)
upload_key = make_from_user_uuid(request.user) + '.' + app_type + settings.FILE_UPLOAD_TMP_KEY
upload_token = storage.get_upload_token(upload_key)
@ -188,7 +187,7 @@ class UploadView(APIView):
"upload_key": upload_key,
"storage": storage_type,
"app_id": app_id,
"ftype": ftype
"ftype": f_type
}
else:
res.code = 1006
@ -198,43 +197,42 @@ class UploadView(APIView):
return Response(res.dict)
def post(self, request):
'''
"""
该方法 主要是本地上传文件接口负责上传 应用图片应用文件或者用户头像
:param request:
:return:
'''
"""
res = BaseResponse()
# 获取多个file
files = request.FILES.getlist('file', None)
certinfo = request.data.get('certinfo', None)
cert_info = request.data.get('certinfo', None)
try:
certinfo = json.loads(certinfo)
if not certinfo:
cert_info = json.loads(cert_info)
if not cert_info:
res.msg = "数据信息 校验失败"
res.code = 1006
return Response(res.dict)
except Exception as e:
logger.error("%s certinfo:%s get failed Exception:%s" % (request.user, certinfo, e))
logger.error(f"{request.user} cert_info:{cert_info} get failed Exception:{e}")
res.msg = "token 校验失败"
res.code = 1006
return Response(res.dict)
token_obj = DownloadToken()
if token_obj.verify_token(token=certinfo.get("upload_token", None),
release_id=certinfo.get("upload_key", None)):
if verify_token(token=cert_info.get("upload_token", None),
release_id=cert_info.get("upload_key", None)):
app_id = certinfo.get("app_id", None)
ftype = certinfo.get("ftype", None)
if ftype and ftype in ['app', 'screen']:
app_id = cert_info.get("app_id", None)
f_type = cert_info.get("ftype", None)
if f_type and f_type in ['app', 'screen']:
pass
# app_obj = Apps.objects.filter(app_id=app_id, user_id=request.user).first()
# if not app_obj:
# res.code = 1006
# res.msg = '该应用不存在'
# return Response(res.dict)
elif ftype and ftype in ['head', 'certification']:
elif f_type and f_type in ['head', 'certification']:
if request.user.uid != app_id:
res.code = 1007
res.msg = '该用户不存在'
@ -252,18 +250,18 @@ class UploadView(APIView):
if app_type == "tmp":
app_type = file_obj.name.split(".")[-2]
if app_type not in ["apk", "ipa", 'png', 'jpeg', 'jpg']:
logger.error("user:%s upload file type error file:%s " % (request.user, file_obj.name))
logger.error(f"user:{request.user} upload file type error file:{file_obj.name}")
raise TypeError
except Exception as e:
logger.error("user:%s upload file type error Exception:%s " % (request.user, e))
logger.error(f"user:{request.user} upload file type error Exception:{e}")
res.code = 1003
res.msg = "错误的类型"
return Response(res.dict)
random_file_name = make_from_user_uuid(request.user)
local_file = os.path.join(settings.MEDIA_ROOT, certinfo.get("upload_key", random_file_name))
local_file = os.path.join(settings.MEDIA_ROOT, cert_info.get("upload_key", random_file_name))
# 读取传入的文件
logger.info("user:%s save file:%s" % (request.user, local_file))
logger.info(f"user:{request.user} save file:{local_file}")
try:
destination = open(local_file, 'wb+')
for chunk in file_obj.chunks():
@ -271,14 +269,14 @@ class UploadView(APIView):
destination.close()
except Exception as e:
logger.error("user:%s save file:%s error Exception:%s " % (request.user, local_file, e))
logger.error(f"user:{request.user} save file:{local_file} error Exception:{e}")
res.code = 1003
res.msg = "数据写入失败"
try:
if os.path.isfile(local_file):
os.remove(local_file)
except Exception as e:
logger.error("user:%s delete file:%s error Exception:%s " % (request.user, local_file, e))
logger.error(f"user:{request.user} delete file:{local_file} error Exception:{e}")
return Response(res.dict)
else:
res.msg = "token 校验失败"
@ -287,27 +285,27 @@ class UploadView(APIView):
return Response(res.dict)
def put(self, request):
'''
"""
该方法就是 应用图片或者用户头像上传完成之后的回调方法为了更新上传完成的信息
:param request:
:return:
'''
"""
res = BaseResponse()
certinfo = request.data.get('certinfo', None)
if certinfo:
app_id = certinfo.get("app_id", None)
logger.info("user %s update img %s info" % (request.user, app_id))
cert_info = request.data.get('certinfo', None)
if cert_info:
app_id = cert_info.get("app_id", None)
logger.info(f"user {request.user} update img {app_id} info")
ftype = certinfo.get('ftype', None)
upload_key = certinfo.get("upload_key", None)
if ftype and upload_key:
f_type = cert_info.get('ftype', None)
upload_key = cert_info.get("upload_key", None)
if f_type and upload_key:
storage = Storage(request.user)
new_upload_key = upload_key.strip(settings.FILE_UPLOAD_TMP_KEY)
else:
res.msg = '参数有误'
res.code = 1008
return Response(res.dict)
if ftype and app_id and ftype == 'app':
if f_type and app_id and f_type == 'app':
app_obj = Apps.objects.filter(app_id=app_id, user_id=request.user).first()
if app_obj:
release_obj = AppReleaseInfo.objects.filter(app_id=app_obj, is_master=True).first()
@ -319,11 +317,10 @@ class UploadView(APIView):
del_cache_response_by_short(app_id)
storage.delete_file(old_file_key)
return Response(res.dict)
elif ftype and app_id and ftype == 'screen':
elif f_type and app_id and f_type == 'screen':
app_obj = Apps.objects.filter(app_id=app_id, user_id=request.user).first()
if app_obj:
scount = AppScreenShot.objects.filter(app_id=app_obj).count()
if scount >= 5:
if AppScreenShot.objects.filter(app_id=app_obj).count() >= 5:
storage.delete_file(upload_key)
res.msg = '最多支持五张截图'
res.code = 1009
@ -333,32 +330,32 @@ class UploadView(APIView):
del_cache_response_by_short(app_id)
return Response(res.dict)
elif ftype and app_id and ftype in ['head', 'certification']:
elif f_type and app_id and f_type in ['head', 'certification']:
if request.user.uid != app_id:
res.code = 1007
res.msg = '该用户不存在'
return Response(res.dict)
if ftype == 'head':
if f_type == 'head':
old_file_key = request.user.head_img
UserInfo.objects.filter(pk=request.user.id).update(head_img=new_upload_key)
if old_file_key != "" or old_file_key != 'head_img.jpeg':
storage.delete_file(old_file_key)
storage.rename_file(upload_key, new_upload_key)
elif ftype == 'certification':
ext = certinfo.get('ext', None)
elif f_type == 'certification':
ext = cert_info.get('ext', None)
if ext:
ptype = ext.get('ptype', None)
if ptype is not None and ptype in [1, 2, 3]:
p_type = ext.get('ptype', None)
if p_type is not None and p_type in [1, 2, 3]:
storage = Storage(request.user, None, True)
certification_obj = CertificationInfo.objects.filter(user_id=request.user,
type=ptype).first()
type=p_type).first()
if certification_obj:
old_certification_url = certification_obj.certification_url
certification_obj.certification_url = new_upload_key
certification_obj.save()
storage.delete_file(old_certification_url)
else:
CertificationInfo.objects.create(user_id=request.user, type=ptype,
CertificationInfo.objects.create(user_id=request.user, type=p_type,
certification_url=new_upload_key)
storage.rename_file(upload_key, new_upload_key)

@ -16,13 +16,13 @@ Including another URLconf
from django.urls import path, re_path, include
from cli.views.login import CliUserInfoView
from cli.views.apps import CliAppsView, CliAppInfoView, CliAppReleaseinfoView
from cli.views.apps import CliAppsView, CliAppInfoView, CliAppReleaseInfoView
from cli.views.uploads import CliAppAnalyseView, CliUploadView
urlpatterns = [
re_path("^apps$", CliAppsView.as_view()),
re_path("^apps/(?P<app_id>\w+)", CliAppInfoView.as_view()),
re_path("^appinfos/(?P<app_id>\w+)/(?P<act>\w+)", CliAppReleaseinfoView.as_view()),
re_path("^appinfos/(?P<app_id>\w+)/(?P<act>\w+)", CliAppReleaseInfoView.as_view()),
re_path("^upload$", CliUploadView.as_view()),
re_path("^userinfo", CliUserInfoView.as_view()),
re_path("^analyse$", CliAppAnalyseView.as_view()),

@ -5,7 +5,7 @@
# date: 2020/3/4
from api.utils.auth import ApiTokenAuthentication
from api.views.apps import AppsView, AppInfoView, AppReleaseinfoView
from api.views.apps import AppsView, AppInfoView, AppReleaseInfoView
import logging
logger = logging.getLogger(__name__)
@ -19,5 +19,5 @@ class CliAppInfoView(AppInfoView):
authentication_classes = [ApiTokenAuthentication, ]
class CliAppReleaseinfoView(AppReleaseinfoView):
class CliAppReleaseInfoView(AppReleaseInfoView):
authentication_classes = [ApiTokenAuthentication, ]

Loading…
Cancel
Save