代码优化

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

@ -87,7 +87,7 @@ class OrderPayView(APIView):
return Response(res.dict) return Response(res.dict)
obj = UserInfo.objects.filter(pk=pk).first() obj = UserInfo.objects.filter(pk=pk).first()
if obj: 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) use_storage_id = data.get("use_storage_id", None)
force = data.get("force", None) force = data.get("force", None)
if use_storage_id: if use_storage_id:

@ -88,7 +88,7 @@ class StorageChangeView(APIView):
return Response(res.dict) return Response(res.dict)
obj = UserInfo.objects.filter(pk=pk).first() obj = UserInfo.objects.filter(pk=pk).first()
if obj: 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) use_storage_id = data.get("use_storage_id", None)
force = data.get("force", None) force = data.get("force", None)
if use_storage_id: if use_storage_id:

@ -8,9 +8,9 @@ from api.utils.response import BaseResponse
from api.utils.app.supersignutils import IosUtils from api.utils.app.supersignutils import IosUtils
from api.utils.storage.storage import Storage from api.utils.storage.storage import Storage
from api.utils.storage.caches import del_cache_response_by_short, get_app_today_download_times, del_cache_by_delete_app, \ from api.utils.storage.caches import del_cache_response_by_short, del_cache_by_delete_app, \
del_cache_storage del_cache_storage
from api.models import Apps, AppReleaseInfo, APPToDeveloper, AppIOSDeveloperInfo, UserInfo, AppScreenShot, AppStorage from api.models import AppReleaseInfo, APPToDeveloper, UserInfo, AppScreenShot, AppStorage
import logging import logging
from api.utils.utils import delete_local_files, delete_app_screenshots_files, change_storage_and_change_head_img, \ from api.utils.utils import delete_local_files, delete_app_screenshots_files, change_storage_and_change_head_img, \
migrating_storage_data, clean_storage_data, check_storage_is_new_storage migrating_storage_data, clean_storage_data, check_storage_is_new_storage
@ -27,21 +27,19 @@ def app_delete(app_obj):
user_obj = app_obj.user_id user_obj = app_obj.user_id
count = APPToDeveloper.objects.filter(app_id=app_obj).count() count = APPToDeveloper.objects.filter(app_id=app_obj).count()
if app_obj.issupersign or count > 0: 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) IosUtils.clean_app_by_user_obj(app_obj, user_obj)
storage = Storage(user_obj) storage = Storage(user_obj)
has_combo = app_obj.has_combo has_combo = app_obj.has_combo
if has_combo: if has_combo:
logger.info( logger.info(
"app_id:%s has_combo ,delete this app need uncombo and clean del_cache_response_by_short" % ( f"app_id:{app_obj.app_id} has_combo ,delete this app need uncombo and clean del_cache_response_by_short")
app_obj.app_id))
has_combo.has_combo = None has_combo.has_combo = None
del_cache_response_by_short(app_obj.app_id) del_cache_response_by_short(app_obj.app_id)
del_cache_by_delete_app(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(): 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" % ( logger.info(f"delete app_id:{app_obj.app_id} need clean all release,release_id:{app_release_obj.release_id}")
app_obj.app_id, app_release_obj.release_id))
storage.delete_file(app_release_obj.release_id, app_release_obj.release_type) 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) delete_local_files(app_release_obj.release_id, app_release_obj.release_type)
storage.delete_file(app_release_obj.icon_url) 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() 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() appreleaseobj = AppReleaseInfo.objects.filter(app_id=app_obj, release_id=release_id).first()
if not appreleaseobj.is_master: 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) storage.delete_file(appreleaseobj.release_id, appreleaseobj.release_type)
delete_local_files(appreleaseobj.release_id, appreleaseobj.release_type) delete_local_files(appreleaseobj.release_id, appreleaseobj.release_type)
storage.delete_file(appreleaseobj.icon_url) storage.delete_file(appreleaseobj.icon_url)
appreleaseobj.delete() appreleaseobj.delete()
elif appreleaseobj.is_master and apprelease_count < 2: 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() count = APPToDeveloper.objects.filter(app_id=app_obj).count()
if app_obj.issupersign or count > 0: 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) IosUtils.clean_app_by_user_obj(app_obj, user_obj)
storage.delete_file(appreleaseobj.release_id, appreleaseobj.release_type) 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) UserInfo.objects.filter(pk=user_obj.pk).update(storage_id=use_storage_id)
except Exception as e: 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 force:
if use_storage_id == -1: if use_storage_id == -1:
UserInfo.objects.filter(pk=user_obj.pk).update(storage=None) 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 django.contrib.contenttypes.models import ContentType
from api.utils.app.randomstrings import make_random_uuid from api.utils.app.randomstrings import make_random_uuid
from django.contrib.auth.models import AbstractUser 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: if len(self.uid) < 8:
self.uid = make_random_uuid() self.uid = make_random_uuid()
if len(self.api_token) < 8: 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) super(UserInfo, self).save(*args, **kwargs)
@ -93,7 +93,7 @@ class VerifyName(models.Model):
verbose_name_plural = "实名认证" verbose_name_plural = "实名认证"
def __str__(self): def __str__(self):
return "%s" % (self.name) return f"self.name"
######################################## APP表 ######################################## ######################################## APP表 ########################################
@ -456,7 +456,7 @@ class DomainCnameInfo(models.Model):
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
if not self.domain_record or (self.domain_record and len(self.domain_record) < 26): # 最多3个启用的价格表 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) super(DomainCnameInfo, self).save(*args, **kwargs)
def __str__(self): def __str__(self):

@ -6,7 +6,6 @@
from celery import shared_task from celery import shared_task
from django.core.cache import cache from django.core.cache import cache
from celery import Celery
from api.utils.storage.storage import get_local_storage 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 1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) 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, \ from api.views.login import LoginView, UserInfoView, RegistView, AuthorizationView, ChangeAuthorizationView, \
UserApiTokenView, CertificationView, ChangeInfoView UserApiTokenView, CertificationView, ChangeInfoView
from api.views.logout import LogoutView 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.download import ShortDownloadView
from api.views.uploads import AppAnalyseView, UploadView from api.views.uploads import AppAnalyseView, UploadView
from api.views.storage import StorageView from api.views.storage import StorageView
@ -41,7 +41,7 @@ urlpatterns = [
re_path("^apps$", AppsView.as_view()), re_path("^apps$", AppsView.as_view()),
re_path("^storage$", StorageView.as_view()), re_path("^storage$", StorageView.as_view()),
re_path(r"^apps/(?P<app_id>\w+)", AppInfoView.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("^upload$", UploadView.as_view()),
re_path("^userinfo", UserInfoView.as_view()), re_path("^userinfo", UserInfoView.as_view()),
re_path("^token", UserApiTokenView.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 from fir_ser.settings import CACHE_KEY_TEMPLATE
import logging 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): def verify_token(token, release_id):
try: try:
values = cache.get(token) values = cache.get(token)
if values and release_id == values.get("data", None): if values and release_id == values.get("data", None):
logger.debug("verify_token token:%s release_id:%s success" % (token, release_id)) logger.debug(f"verify_token token:{token} release_id:{release_id} success")
return True return True
except Exception as e: except Exception as e:
logger.error("verify_token token:%s release_id:%s failed Exception:%s" % (token, release_id, e)) logger.error(f"verify_token token:{token} release_id:{release_id} failed Exception:{e}")
return False
logger.error("verify_token token:%s release_id:%s failed" % (token, release_id))
return False 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': if medium == 'email':
return generateAlphanumericTokenOfLength(32) return generate_alphanumeric_token_of_length(32)
elif medium == 'wechat': elif medium == 'wechat':
return 'WeChat' return 'WeChat'
else: 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)]) return "".join([random.choice(string.digits + random_str) for _ in range(length)])
def generateAlphanumericTokenOfLength(length): def generate_alphanumeric_token_of_length(length):
return "".join( return "".join(
[random.choice(string.digits + string.ascii_lowercase + string.ascii_uppercase) for _ in range(length)]) [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 from api.utils.storage.caches import del_cache_response_by_short
import logging import logging
logger = logging.getLogger(__file__) logger = logging.getLogger(__name__)
def make_resigned(bin_url, img_url, bundle_id, app_version, 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> <key>kind</key>
<string>software-package</string> <string>software-package</string>
<key>url</key> <key>url</key>
<string><![CDATA[%s]]></string> <string><![CDATA[{bin_url}]]></string>
</dict> </dict>
<dict> <dict>
<key>kind</key> <key>kind</key>
@ -35,7 +35,7 @@ def make_resigned(bin_url, img_url, bundle_id, app_version, name):
<key>needs-shine</key> <key>needs-shine</key>
<integer>0</integer> <integer>0</integer>
<key>url</key> <key>url</key>
<string><![CDATA[%s]]></string> <string><![CDATA[{img_url}]]></string>
</dict> </dict>
<dict> <dict>
<key>kind</key> <key>kind</key>
@ -43,26 +43,26 @@ def make_resigned(bin_url, img_url, bundle_id, app_version, name):
<key>needs-shine</key> <key>needs-shine</key>
<true/> <true/>
<key>url</key> <key>url</key>
<string><![CDATA[%s]]></string> <string><![CDATA[{img_url}]]></string>
</dict> </dict>
</array> </array>
<key>metadata</key> <key>metadata</key>
<dict> <dict>
<key>bundle-identifier</key> <key>bundle-identifier</key>
<string>%s</string> <string>{bundle_id}</string>
<key>bundle-version</key> <key>bundle-version</key>
<string><![CDATA[%s]]></string> <string><![CDATA[{app_version}]]></string>
<key>kind</key> <key>kind</key>
<string>software</string> <string>software</string>
<key>title</key> <key>title</key>
<string><![CDATA[%s]]></string> <string><![CDATA[{name}]]></string>
</dict> </dict>
</dict> </dict>
</array> </array>
</dict> </dict>
</plist>""" % (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("make_resigned bin_url %s ,img_url %s, img_url %s, bundle_id %s, app_version %s, name %s" % ( logger.info(
bin_url, img_url, img_url, bundle_id, app_version, name)) 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 return ios_plist_tem
@ -78,10 +78,10 @@ def bytes2human(n):
return '%sB' % 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] extension = app_file_name.split(".")[1]
if extension == "ipa": if extension == "ipa":
release_type = appinfo.get("release_type") release_type = app_info.get("release_type")
if release_type == "Adhoc": # Adhoc: 内测版 Inhouse:企业版 if release_type == "Adhoc": # Adhoc: 内测版 Inhouse:企业版
return 1 return 1
elif release_type == "Inhouse": elif release_type == "Inhouse":
@ -106,94 +106,94 @@ def get_random_short():
short_url = ''.join(random.sample( 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', ['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)) 'e', 'd', 'c', 'b', 'a'], 4))
appobj = Apps.objects.filter(short=short_url).first() app_obj = Apps.objects.filter(short=short_url).first()
if appobj: if app_obj:
return get_random_short() return get_random_short()
else: else:
return short_url 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_uuid = make_app_uuid(user_obj, bundle_id + app_file_name.split(".")[1])
##判断是否存在该app ##判断是否存在该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) storage = Storage(user_obj)
newapp = False is_new_app = False
if not appmobj: if not app_obj:
newapp = True is_new_app = True
appdata = { appdata = {
"app_id": app_uuid, "app_id": app_uuid,
"user_id": user_obj, "user_id": user_obj,
"type": get_app_type(app_file_name), "type": get_app_type(app_file_name),
"name": appinfo["labelname"], "name": app_info["labelname"],
"new_bundle_name": appinfo["labelname"], "new_bundle_name": app_info["labelname"],
"short": short, "short": short,
"bundle_id": bundle_id, "bundle_id": bundle_id,
"count_hits": 0, "count_hits": 0,
"wxeasytype": False if get_user_domain_name(user_obj) else True "wxeasytype": False if get_user_domain_name(user_obj) else True
} }
try: try:
appmobj = Apps.objects.create(**appdata) app_obj = Apps.objects.create(**appdata)
except Exception as e: 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 return False
else: else:
try: try:
newapp = False is_new_app = False
appmobj.short = short app_obj.short = short
appmobj.name = appinfo["labelname"] app_obj.name = app_info["labelname"]
# appmobj.wxeasytype = False if user_obj.domain_name or appmobj.domain_name else True # appmobj.wxeasytype = False if user_obj.domain_name or appmobj.domain_name else True
appmobj.bundle_id = bundle_id app_obj.bundle_id = bundle_id
appmobj.save() app_obj.save()
del_cache_response_by_short(appmobj.app_id) del_cache_response_by_short(app_obj.app_id)
except Exception as e: except Exception as e:
logger.error("save app info failed,appmobj:%s Exception:%s" % (appmobj, e)) logger.error(f"save app info failed,app_obj:{app_obj} Exception:{e}")
appmobj.bundle_id = bundle_id app_obj.bundle_id = bundle_id
appmobj.name = appinfo["labelname"] app_obj.name = app_info["labelname"]
appmobj.save() 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 = { release_data = {
"app_id": appmobj, "app_id": app_obj,
"icon_url": app_img, "icon_url": app_img,
"release_id": app_file_name.split(".")[0], "release_id": app_file_name.split(".")[0],
"build_version": str(appinfo.get("version", "latest")), "build_version": str(app_info.get("version", "latest")),
"app_version": str(appinfo.get("versioncode", "latest")), "app_version": str(app_info.get("versioncode", "latest")),
"release_type": get_release_type(app_file_name, appinfo), "release_type": get_release_type(app_file_name, app_info),
"minimum_os_version": str(appinfo.get("miniOSversion", "latest")), "minimum_os_version": str(app_info.get("miniOSversion", "latest")),
"binary_size": size, "binary_size": size,
"is_master": True, "is_master": True,
"changelog": appinfo.get("changelog", ''), "changelog": app_info.get("changelog", ''),
"udid": appinfo.get("udid", ''), "udid": app_info.get("udid", ''),
"distribution_name": appinfo.get("distribution_name", ''), "distribution_name": app_info.get("distribution_name", ''),
} }
try: try:
AppReleaseInfo.objects.create(**release_data) AppReleaseInfo.objects.create(**release_data)
except Exception as e: except Exception as e:
logging.error("create app release failed,release_data:%s Exception:%s" % (release_data, e)) logger.error(f"create app release failed,release_data:{release_data} Exception:{e}")
if newapp: if is_new_app:
logger.info("create app release failed,release_data:%s ,and app is new ,so delete this app:%s" % ( logger.info(
release_data, appmobj)) f"create app release failed,release_data:{release_data} ,and app is new ,so delete this app:{app_obj}")
appmobj.delete() app_obj.delete()
return False return False
try: try:
history_release_limit = int(user_obj.history_release_limit) history_release_limit = int(user_obj.history_release_limit)
except Exception as e: except Exception as e:
logger.error("get history_release_limit failed,history_release_limit:%s Exception:%s" % ( logger.error(
user_obj.history_release_limit, e)) f"get history_release_limit failed,history_release_limit:{user_obj.history_release_limit} Exception:{e}")
return True return True
if history_release_limit != 0: 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: if release_queryset.count() > history_release_limit:
flag = 0 flag = 0
for release_obj in release_queryset: for release_obj in release_queryset:
flag += 1 flag += 1
if flag > history_release_limit: if flag > history_release_limit:
logging.info("history_release_limit:%s this release is to more,so delete it release_id:%s" % ( logger.info(
history_release_limit, release_obj.release_id)) 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, appmobj.type) storage.delete_file(release_obj.release_id, app_obj.type)
storage.delete_file(release_obj.icon_url) storage.delete_file(release_obj.icon_url)
release_obj.delete() release_obj.delete()
return True return True

@ -16,25 +16,25 @@ import base64
from OpenSSL.crypto import (load_pkcs12, dump_certificate_request, dump_privatekey, PKey, TYPE_RSA, X509Req, 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) 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): def exec_shell(cmd, remote=False, timeout=None):
if remote: if remote:
hostip = "10.66.6.66" host_ip = "10.66.6.66"
port = 65534 port = 65534
user = "root" user = "root"
passwd = "root" passwd = "root"
result = use_user_pass(hostip, port, user, passwd, cmd) result = use_user_pass(host_ip, port, user, passwd, cmd)
return result return result
else: else:
logger.info("exec_shell cmd:%s" % (cmd)) logger.info(f"exec_shell cmd:{cmd}")
result = shell_command(cmd, timeout) 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: if result.get("exit_code") != 0:
err_info = result.get("err_info", None) err_info = result.get("err_info", None)
if err_info: 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" result["err_info"] = "Unknown Error"
return False, result return False, result
return True, 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) self.cmd = "zsign -c '%s' -k '%s' " % (self.app_dev_pem, self.my_local_key)
@staticmethod @staticmethod
def sign_mobileconfig(mobilconfig_path, sign_mobilconfig_path, ssl_pem_path, ssl_key_path): def sign_mobile_config(mobile_config_path, sign_mobile_config_path, ssl_pem_path, ssl_key_path):
''' """
:param mobilconfig_path: 描述文件绝对路径 :param mobile_config_path: 描述文件绝对路径
:param sign_mobilconfig_path: 签名之后的文件绝对路径 :param sign_mobile_config_path: 签名之后的文件绝对路径
:param ssl_pem_path: pem证书的绝对路径 :param ssl_pem_path: pem证书的绝对路径
:param ssl_key_path: key证书的绝对路径 :param ssl_key_path: key证书的绝对路径
:return: :return:
''' """
cmd = "openssl smime -sign -in %s -out %s -signer %s " \ cmd = "openssl smime -sign -in %s -out %s -signer %s " \
"-inkey %s -certfile %s -outform der -nodetach " % ( "-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) return exec_shell(cmd)
def make_p12_from_cert(self, password): def make_p12_from_cert(self, password):
@ -132,12 +132,42 @@ class ResignApp(object):
return exec_shell(self.cmd) 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): 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.issuer_id = issuer_id
self.private_key_id = private_key_id self.private_key_id = private_key_id
self.p8key = p8key self.p8key = p8key
self.certid = certid self.cert_id = cert_id
def active(self): def active(self):
result = {'data': []} result = {'data': []}
@ -145,11 +175,11 @@ class AppDeveloperApiV2(object):
apple_obj = AppStoreConnectApi(self.issuer_id, self.private_key_id, self.p8key) apple_obj = AppStoreConnectApi(self.issuer_id, self.private_key_id, self.p8key)
certificates = apple_obj.get_all_certificates() certificates = apple_obj.get_all_certificates()
result['data'] = certificates result['data'] = certificates
logger.info("ios developer active result:%s" % certificates) logger.info(f"ios developer active result:{certificates}")
if len(certificates) > 0: if len(certificates) > 0:
return True, result return True, result
except Exception as e: 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 result['return_info'] = "%s" % e
return False, result return False, result
@ -160,34 +190,6 @@ class AppDeveloperApiV2(object):
os.makedirs(cert_dir_path) os.makedirs(cert_dir_path)
return os.path.join(cert_dir_path, cert_dir_name) 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): def create_cert(self, user_obj):
result = {} result = {}
try: try:
@ -195,51 +197,51 @@ class AppDeveloperApiV2(object):
csr_path = self.file_format_path_name(user_obj) csr_path = self.file_format_path_name(user_obj)
if not os.path.isdir(os.path.dirname(csr_path)): if not os.path.isdir(os.path.dirname(csr_path)):
os.makedirs(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")) certificates = apple_obj.create_certificate(csr_content.decode("utf-8"))
if certificates: if certificates:
n = base64.b64decode(certificates.certificateContent) n = base64.b64decode(certificates.certificateContent)
with open(csr_path + ".cer", 'wb') as f: with open(csr_path + ".cer", 'wb') as f:
f.write(n) f.write(n)
self.make_pem(n, csr_path + ".pem") make_pem(n, csr_path + ".pem")
logger.info("ios developer create cert result:%s" % certificates.certificateContent) logger.info(f"ios developer create cert result:{certificates.certificateContent}")
return True, certificates return True, certificates
except Exception as e: 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 result['return_info'] = "%s" % e
return False, result return False, result
def get_cert_obj_by_cid(self, cert_id): def get_cert_obj_by_cid(self):
result = {} result = {}
try: try:
apple_obj = AppStoreConnectApi(self.issuer_id, self.private_key_id, self.p8key) 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: if cert_obj and cert_obj.id:
return True, result return True, result
else: 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 return False, result
except Exception as e: 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 result['return_info'] = "%s" % e
return False, result return False, result
def revoke_cert(self, cert_id): def revoke_cert(self):
result = {} result = {}
try: try:
apple_obj = AppStoreConnectApi(self.issuer_id, self.private_key_id, self.p8key) 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: if cert_obj:
s_date = format_apple_date(cert_obj.expirationDate) s_date = format_apple_date(cert_obj.expirationDate)
if s_date.timestamp() - datetime.datetime.now().timestamp() < 3600 * 24 * 3: if s_date.timestamp() - datetime.datetime.now().timestamp() < 3600 * 24 * 3:
if apple_obj.revoke_certificate(cert_id): if apple_obj.revoke_certificate(self.cert_id):
logger.info("ios developer cert %s revoke" % cert_id) logger.info(f"ios developer cert {self.cert_id} revoke")
return True, result return True, result
else: 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 return True, result
except Exception as e: 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 result['return_info'] = "%s" % e
return False, result return False, result
@ -252,12 +254,12 @@ class AppDeveloperApiV2(object):
certificates = apple_obj.get_all_certificates() certificates = apple_obj.get_all_certificates()
for cert_obj in certificates: for cert_obj in certificates:
f_date = format_apple_date(cert_obj.expirationDate) 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(): if not_after.timestamp() == f_date.timestamp():
return True, cert_obj return True, cert_obj
return False, result return False, result
except Exception as e: 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 result['return_info'] = "%s" % e
return False, result return False, result
@ -297,7 +299,7 @@ class AppDeveloperApiV2(object):
f.write(n) f.write(n)
return True, result return True, result
except Exception as e: 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 result['return_info'] = "%s" % e
return False, result return False, result
@ -310,7 +312,7 @@ class AppDeveloperApiV2(object):
if apple_obj.delete_profile_by_id(profile_obj.id): if apple_obj.delete_profile_by_id(profile_obj.id):
return True, profile_obj return True, profile_obj
except Exception as e: 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 result['return_info'] = "%s" % e
return False, result return False, result

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

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

@ -13,7 +13,7 @@ import jwt
import logging import logging
from collections import namedtuple 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 # 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): def request_format_log(req):
try: 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: except Exception as e:
logger.error(e) logger.error(e)
return req return req
@ -273,6 +273,7 @@ class BundleIDsCapabilityAPI(object):
def disable_capability(self, bundle_id, capability_type): def disable_capability(self, bundle_id, capability_type):
""" """
:param capability_type:
:param bundle_id: :param bundle_id:
:return: :return:
204 No Content 204 No Content
@ -652,13 +653,13 @@ class AppStoreConnectApi(DevicesAPI, BundleIDsAPI, BundleIDsCapabilityAPI, Profi
JWT_ALG = 'ES256' JWT_ALG = 'ES256'
def __init__(self, issuer_id, private_key_id, p8_private_key, exp_seconds=1200): 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 根据 Apple 文档会话最长持续时间为 20 分钟https : //developer.apple.com/documentation/appstoreconnectapi/generating_tokens_for_api_requests
:param issuer_id: :param issuer_id:
:param private_key_id: :param private_key_id:
:param p8_private_key: :param p8_private_key:
:param exp_seconds: max 20*60 :param exp_seconds: max 20*60
''' """
self.issuer_id = issuer_id self.issuer_id = issuer_id
self.private_key_id = private_key_id self.private_key_id = private_key_id
self.p8_private_key = p8_private_key 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] self.rate_limit_info[limit_info_list[0]] = limit_info_list[1]
user_rem_info = self.rate_limit_info user_rem_info = self.rate_limit_info
if int(user_rem_info.get('user-hour-rem')) < 3595: 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.__init__(self.issuer_id, self.private_key_id, self.p8_private_key)
self.rate_limit_info = user_rem_info 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): def __make_jwt_headers(self):
data = { data = {
@ -700,7 +701,7 @@ class AppStoreConnectApi(DevicesAPI, BundleIDsAPI, BundleIDsCapabilityAPI, Profi
} }
self.headers = headers 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) # self.__set_rate_limit_info(req.headers)
if req.status_code == success_code: if req.status_code == success_code:
req_data = req.json() req_data = req.json()
@ -709,20 +710,20 @@ class AppStoreConnectApi(DevicesAPI, BundleIDsAPI, BundleIDsCapabilityAPI, Profi
obj = None obj = None
if isinstance(data, dict): if isinstance(data, dict):
data = [data] data = [data]
if stype == 'devices': if s_type == 'devices':
obj = Devices.from_json_list(data) obj = Devices.from_json_list(data)
elif stype == 'bundleIds': elif s_type == 'bundleIds':
obj = BundleIds.from_json_list(data) obj = BundleIds.from_json_list(data)
elif stype == 'profiles': elif s_type == 'profiles':
obj = Profiles.from_json_list(data) obj = Profiles.from_json_list(data)
elif stype == 'certificates': elif s_type == 'certificates':
obj = Certificates.from_json_list(data) obj = Certificates.from_json_list(data)
if len(obj) == 1: if len(obj) == 1:
return obj[0] return obj[0]
return obj return obj
else: else:
# self.__init_jwt_headers() # self.__init_jwt_headers()
raise Exception('error: %s' % (req.text)) raise Exception(f'error instance: {req.text}')
elif req.status_code == 401: # 授权问题 elif req.status_code == 401: # 授权问题
raise Exception(req.text) raise Exception(req.text)
elif req.status_code == 429: # 请求超过每小时限制 {'user-hour-lim': '3600', 'user-hour-rem': '3586'} 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: for capability in capability_list:
req = super().enable_capability(bundle_id, capability) req = super().enable_capability(bundle_id, capability)
if self.__do_success(req, 201): 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: 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 return True
def disable_capability_by_s_type(self, bundle_id, s_type=len(capability) - 1): 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: for capability in capability_list:
req = super().disable_capability(bundle_id, capability) req = super().disable_capability(bundle_id, capability)
if self.__do_success(req, 204): 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: 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 return True
def enable_push_vpn_capability(self, bundle_id): def enable_push_vpn_capability(self, bundle_id):
# 'PUSH_NOTIFICATIONS', # PERSONAL_VPN , NETWORK_EXTENSIONS
req = super().enable_capability(bundle_id, 'PUSH_NOTIFICATIONS') req = super().enable_capability(bundle_id, 'PUSH_NOTIFICATIONS')
if self.__do_success(req, 201): if self.__do_success(req, 201):
req = super().enable_capability(bundle_id, 'PERSONAL_VPN') req = super().enable_capability(bundle_id, 'PERSONAL_VPN')
@ -835,7 +835,6 @@ class AppStoreConnectApi(DevicesAPI, BundleIDsAPI, BundleIDsCapabilityAPI, Profi
return False return False
def disable_push_vpn_capability(self, bundle_id): def disable_push_vpn_capability(self, bundle_id):
# 'PUSH_NOTIFICATIONS', # PERSONAL_VPN
req = super().disable_capability(bundle_id, 'PUSH_NOTIFICATIONS') req = super().disable_capability(bundle_id, 'PUSH_NOTIFICATIONS')
if self.__do_success(req, 204): if self.__do_success(req, 204):
req = super().disable_capability(bundle_id, 'PERSONAL_VPN') 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): if os.path.isfile(file):
os.remove(file) os.remove(file)
except Exception as e: except Exception as e:
logger.error("delete_app_profile_file developer_obj:%s app_obj:%s file:%s Exception:%s" % ( logger.error(
developer_obj, app_obj, file, e)) f"delete_app_profile_file developer_obj:{developer_obj} app_obj:{app_obj} file:{file} Exception:{e}")
def is_valid_domain(value): def is_valid_domain(value):
pattern = re.compile( pattern = re.compile(
r'^(([a-zA-Z]{1})|([a-zA-Z]{1}[a-zA-Z]{1})|' r'^(([a-zA-Z])|([a-zA-Z][a-zA-Z])|'
r'([a-zA-Z]{1}[0-9]{1})|([0-9]{1}[a-zA-Z]{1})|' 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-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})$' 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 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): 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}$') # 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 # 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): def is_valid_email(email):
@ -112,9 +159,9 @@ def get_cname_from_domain(domain):
while count: while count:
try: try:
dns_resolver.nameservers = dns_list[len(dns_list) - count] 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: 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 count -= 1
time.sleep(0.3) time.sleep(0.3)
if count <= 0: 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 time, os
import logging import logging
logger = logging.getLogger(__file__) logger = logging.getLogger(__name__)
def sync_download_times(): def sync_download_times():
@ -23,7 +23,7 @@ def sync_download_times():
count_hits = cache.get(app_download) count_hits = cache.get(app_download)
app_id = app_download.split(down_tem_key)[1].strip('_') app_id = app_download.split(down_tem_key)[1].strip('_')
Apps.objects.filter(app_id=app_id).update(count_hits=count_hits) 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(): def auto_clean_upload_tmp_file():
@ -40,10 +40,10 @@ def auto_clean_upload_tmp_file():
filename = data.get("filename", None) filename = data.get("filename", None)
if filename: if filename:
storage.delete_file(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) 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(): def auto_delete_tmp_file():
@ -57,7 +57,7 @@ def auto_delete_tmp_file():
try: try:
os.remove(file_path) os.remove(file_path)
except Exception as e: 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(): def auto_check_ios_developer_active():
@ -66,8 +66,7 @@ def auto_check_ios_developer_active():
userinfo = ios_developer.user_id userinfo = ios_developer.user_id
if userinfo.supersign_active: if userinfo.supersign_active:
status, result = IosUtils.active_developer(ios_developer) status, result = IosUtils.active_developer(ios_developer)
msg = "auto_check_ios_developer_active user:%s ios.developer:%s status:%s result:%s" % ( msg = f"auto_check_ios_developer_active user:{userinfo} ios.developer:{ios_developer} status:{status} result:{result}"
userinfo, ios_developer, status, result)
if status: if status:
logger.info(msg) logger.info(msg)
else: else:

@ -81,14 +81,16 @@ class GeetestLib:
self.libResult.set_all(1, data, "") 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( self.gtlog(
"successValidate(): 开始二次验证 正常模式, challenge={0}, validate={1}, seccode={2}.".format(challenge, validate, "success_validate(): 开始二次验证 正常模式, challenge={0}, validate={1}, seccode={2}.".format(challenge, validate,
seccode)) seccode))
if not self.check_param(challenge, validate, seccode): if not self.check_param(challenge, validate, seccode):
self.libResult.set_all(0, "", "正常模式,本地校验,参数challenge、validate、seccode不可为空") self.libResult.set_all(0, "", "正常模式,本地校验,参数challenge、validate、seccode不可为空")
else: else:
response_seccode = self.requestValidate(challenge, validate, seccode, param_dict) response_seccode = self.request_validate(challenge, validate, seccode, param_dict)
if not response_seccode: if not response_seccode:
self.libResult.set_all(0, "", "请求极验validate接口失败") self.libResult.set_all(0, "", "请求极验validate接口失败")
elif response_seccode == "false": 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( self.gtlog(
"failValidate(): 开始二次验证 宕机模式, challenge={0}, validate={1}, seccode={2}.".format(challenge, validate, "fail_validate(): 开始二次验证 宕机模式, challenge={0}, validate={1}, seccode={2}.".format(challenge, validate,
seccode)) seccode))
if not self.check_param(challenge, validate, seccode): if not self.check_param(challenge, validate, seccode):
self.libResult.set_all(0, "", "宕机模式,本地校验,参数challenge、validate、seccode不可为空.") self.libResult.set_all(0, "", "宕机模式,本地校验,参数challenge、validate、seccode不可为空.")
else: else:
self.libResult.set_all(1, "", "") 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 return self.libResult
# 向极验发送二次验证的请求,POST方式 # 向极验发送二次验证的请求,POST方式
def requestValidate(self, challenge, validate, seccode, param_dict): def request_validate(self, challenge, validate, seccode, param_dict):
param_dict.update( param_dict.update(
{"seccode": seccode, "json_format": self.JSON_FORMAT, "challenge": challenge, "sdk": self.VERSION, {"seccode": seccode, "json_format": self.JSON_FORMAT, "challenge": challenge, "sdk": self.VERSION,
"captchaid": self.geetest_id}) "captchaid": self.geetest_id})

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

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

@ -13,7 +13,7 @@ from api.utils.storage.caches import update_order_info, update_order_status
import json import json
import logging import logging
logger = logging.getLogger(__file__) logger = logging.getLogger(__name__)
class Alipay(object): class Alipay(object):
@ -56,7 +56,7 @@ class Alipay(object):
signature = data.pop("sign") signature = data.pop("sign")
success = self.alipay.verify(data, signature) success = self.alipay.verify(data, signature)
if success and data["trade_status"] in ("TRADE_SUCCESS", "TRADE_FINISHED"): 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", "") app_id = data.get("app_id", "")
if app_id == self.ali_config.get("APP_ID"): if app_id == self.ali_config.get("APP_ID"):
out_trade_no = data.get("out_trade_no", "") # 服务器订单号 out_trade_no = data.get("out_trade_no", "") # 服务器订单号
@ -67,15 +67,15 @@ class Alipay(object):
payment_number = data.get("trade_no", "") payment_number = data.get("trade_no", "")
return update_order_info(user_id, out_trade_no, payment_number, 1) return update_order_info(user_id, out_trade_no, payment_number, 1)
else: else:
logger.error("passback_params %s user_id not exists" % passback_params) logger.error(f"passback_params {passback_params} user_id not exists")
else: 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 return False
def update_order_status(self, out_trade_no): def update_order_status(self, out_trade_no):
data = self.alipay.api_alipay_trade_query(out_trade_no=out_trade_no) data = self.alipay.api_alipay_trade_query(out_trade_no=out_trade_no)
code = data.get("code", '') 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': if code == '10000':
trade_status = data.get("trade_status", '') trade_status = data.get("trade_status", '')
if trade_status in ['TRADE_SUCCESS']: if trade_status in ['TRADE_SUCCESS']:

@ -210,7 +210,6 @@ class BaseAliPay:
data = self.build_body(api_name, biz_content, **kwargs) data = self.build_body(api_name, biz_content, **kwargs)
# alipay.trade.query => alipay_trade_query_response # alipay.trade.query => alipay_trade_query_response
response_type = api_name.replace(".", "_") + "_response" response_type = api_name.replace(".", "_") + "_response"
print(data)
return self.verified_sync_response(data, response_type) return self.verified_sync_response(data, response_type)
def api_alipay_trade_wap_pay( 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 json
import logging import logging
logger = logging.getLogger(__file__) logger = logging.getLogger(__name__)
class Weixinpay(object): class Weixinpay(object):
@ -54,7 +54,7 @@ class Weixinpay(object):
} }
result = self.wxpay.decrypt_callback(headers, request.body.decode('utf-8')) result = self.wxpay.decrypt_callback(headers, request.body.decode('utf-8'))
if result: if result:
logger.info("付款成功,等待下一步验证 %s" % result) logger.info(f"付款成功,等待下一步验证 {result}")
data = json.loads(result) data = json.loads(result)
passback_params = data.get("attach", "") passback_params = data.get("attach", "")
out_trade_no = data.get("out_trade_no", "") out_trade_no = data.get("out_trade_no", "")
@ -64,16 +64,16 @@ class Weixinpay(object):
transaction_id = data.get("transaction_id", "") transaction_id = data.get("transaction_id", "")
return update_order_info(user_id, out_trade_no, transaction_id, 0) return update_order_info(user_id, out_trade_no, transaction_id, 0)
else: else:
logger.error("passback_params %s user_id not exists" % passback_params) logger.error(f"passback_params {passback_params} user_id not exists")
else: else:
logger.error("消息解密失败") logger.error(f"消息解密失败 {request.body}")
return False return False
def update_order_status(self, out_trade_no): def update_order_status(self, out_trade_no):
code, data = self.wxpay.query(out_trade_no=out_trade_no) code, data = self.wxpay.query(out_trade_no=out_trade_no)
# (0, '交易成功'), (1, '待支付'), (2, '订单已创建'), (3, '退费申请中'), (4, '已退费'), (5, '主动取消'), (6, '超时取消') # (0, '交易成功'), (1, '待支付'), (2, '订单已创建'), (3, '退费申请中'), (4, '已退费'), (5, '主动取消'), (6, '超时取消')
data = json.loads(data) 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: if code == 200:
trade_status = data.get("trade_state", '') trade_status = data.get("trade_state", '')
if trade_status in ['SUCCESS']: if trade_status in ['SUCCESS']:

@ -1,11 +1,10 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import json
from enum import Enum from enum import Enum
from .core import Core, RequestType from .core import Core, RequestType
class WeChatPay(): class WeChatPay(object):
def __init__(self, def __init__(self,
wechatpay_type, wechatpay_type,
mchid, mchid,
@ -17,10 +16,10 @@ class WeChatPay():
""" """
:param wechatpay_type: 微信支付类型示例值WeChatPayType.MINIPROG :param wechatpay_type: 微信支付类型示例值WeChatPayType.MINIPROG
:param mchid: 直连商户号示例值'1230000109' :param mchid: 直连商户号示例值'1230000109'
:param mch_private_key: 商户证书私钥示例值'MIIEvwIBADANBgkqhkiG9w0BAQE...' :param parivate_key: 商户证书私钥示例值'MIIEvwIBADANBgkqhkiG9w0BAQE...'
:param mch_key_serial_no: 商户证书序列号示例值'444F4864EA9B34415...' :param cert_serial_no: 商户证书序列号示例值'444F4864EA9B34415...'
:param appid: 应用ID示例值'wxd678efh567hg6787' :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' :param notify_url: 通知地址示例值'https://www.weixin.qq.com/wxpay/pay.php'
""" """
self._type = wechatpay_type self._type = wechatpay_type
@ -58,10 +57,7 @@ class WeChatPay():
:param settle_info: 结算信息示例值{'profit_sharing':False} :param settle_info: 结算信息示例值{'profit_sharing':False}
:param notify_url: 通知地址示例值'https://www.weixin.qq.com/wxpay/pay.php' :param notify_url: 通知地址示例值'https://www.weixin.qq.com/wxpay/pay.php'
""" """
params = {} params = {'appid': self._appid, 'mchid': self._mchid, 'notify_url': notify_url or self._notify_url}
params['appid'] = self._appid
params['mchid'] = self._mchid
params['notify_url'] = notify_url or self._notify_url
if description: if description:
params.update({'description': description}) params.update({'description': description})
else: else:
@ -88,6 +84,7 @@ class WeChatPay():
params.update({'detail': detail}) params.update({'detail': detail})
if settle_info: if settle_info:
params.update({'settle_info': settle_info}) params.update({'settle_info': settle_info})
path = ""
if self._type in [WeChatPayType.JSAPI, WeChatPayType.MINIPROG]: if self._type in [WeChatPayType.JSAPI, WeChatPayType.MINIPROG]:
if not payer: if not payer:
raise Exception('payer is not assigned') raise Exception('payer is not assigned')
@ -100,7 +97,10 @@ class WeChatPay():
path = '/v3/pay/transactions/h5' path = '/v3/pay/transactions/h5'
elif self._type == WeChatPayType.NATIVE: elif self._type == WeChatPayType.NATIVE:
path = '/v3/pay/transactions/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): 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 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' :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: if out_refund_no:
params.update({'out_refund_no': out_refund_no}) params.update({'out_refund_no': out_refund_no})
else: else:
@ -281,8 +280,7 @@ class WeChatPay():
:param sub_orders: 子单信息, 示例值[{'mchid': '1900000109', 'out_trade_no': '20150806125346'}] :param sub_orders: 子单信息, 示例值[{'mchid': '1900000109', 'out_trade_no': '20150806125346'}]
:param combine_appid: 合单商户appid, 示例值'wxd678efh567hg6787' :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: if not combine_out_trade_no:
raise Exception('combine_out_trade_no is not assigned.') 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 from fir_ser.settings import THIRD_PART_CONFIG
import logging 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): class SendMessage(object):
def __init__(self, type): def __init__(self, send_type):
''' """
:param type: sms or email :param send_type: sms or email
''' """
self.type = type self.send_type = send_type
try: try:
if type == 'sms': if send_type == 'sms':
self.sender = self._get_sms_sender() self.sender = get_sms_sender()
elif type == 'email': elif send_type == 'email':
self.sender = self._get_email_sender() self.sender = get_email_sender()
if self.sender is None: if self.sender is None:
raise raise
except Exception as e: 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 self.sender = None
def send_register_msg(self, target, code): def send_register_msg(self, target, code):
status, msg = self.sender.send_register_msg(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 return status, msg
def send_change_msg(self, target, code): def send_change_msg(self, target, code):
status, msg = self.sender.send_change_msg(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 return status, msg
def send_login_msg(self, target, code): def send_login_msg(self, target, code):
status, msg = self.sender.send_login_msg(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 return status, msg
def send_email_msg(self, email, text): 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) 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 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 rest_framework import serializers
from api import models from api import models
from api.utils.TokenManager import make_token
from api.utils.app.apputils import bytes2human 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.app.supersignutils import get_redirect_server_domain
from api.utils.baseutils import get_user_domain_name, get_app_domain_name from api.utils.baseutils import get_user_domain_name, get_app_domain_name
from api.utils.storage.storage import Storage 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 from api.utils.storage.caches import get_user_free_download_times, get_user_cert_auth_status
import os, logging import os, logging
logger = logging.getLogger(__file__) logger = logging.getLogger(__name__)
token_obj = DownloadToken()
def get_download_url_from_context(self, obj, key, url, force_new=False): 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 storage = None
if storage: if storage:
download_url = storage.get_download_url(os.path.basename(url), 600, key, force_new) download_url = storage.get_download_url(os.path.basename(url), 600, key, force_new)
logger.info( logger.info(f'get {os.path.basename(url)} download_url {download_url} force_new:{force_new} key:{key}')
'get %s download_url %s force_new:%s key:%s' % (os.path.basename(url), download_url, force_new, key))
return download_url return download_url
@ -187,7 +184,7 @@ class AppsSerializer(serializers.ModelSerializer):
"binary_url": master_release_obj.binary_url, "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 datainfo["download_token"] = download_token
udid_lists = [] udid_lists = []
try: try:
@ -284,7 +281,7 @@ class AppsShortSerializer(serializers.ModelSerializer):
"binary_url": master_release_obj.binary_url, "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 datainfo["download_token"] = download_token
return datainfo return datainfo
else: else:
@ -322,7 +319,7 @@ class AppReleaseSerializer(serializers.ModelSerializer):
return bytes2human(obj.binary_size) return bytes2human(obj.binary_size)
def get_download_token(self, obj): 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): def get_icon_url(self, obj):
return get_download_url_from_context(self, obj, '', os.path.basename(obj.icon_url)) return get_download_url_from_context(self, obj, '', os.path.basename(obj.icon_url))

@ -16,7 +16,7 @@ import hashlib
import time import time
import logging import logging
logger = logging.getLogger(__file__) logger = logging.getLogger(__name__)
# 以下代码展示了STS的用法,包括角色扮演获取临时用户的密钥、使用临时用户的密钥访问OSS。 # 以下代码展示了STS的用法,包括角色扮演获取临时用户的密钥、使用临时用户的密钥访问OSS。
@ -62,19 +62,19 @@ class AliYunCdn(object):
if not args: args = "" if not args: args = ""
rand = "0" # "0" by default, other value is ok rand = "0" # "0" by default, other value is ok
uid = "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) ss_string = f"{path}-{exp}-{rand}-{uid}-{self.key}"
hashvalue = md5sum(sstring.encode("utf-8")) hash_value = md5sum(ss_string.encode("utf-8"))
auth_key = "%s-%s-%s-%s" % (exp, rand, uid, hashvalue) auth_key = f"{exp}-{rand}-{uid}-{hash_value}"
if args: 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: 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): 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 exp = int(time.time()) + expires
download_url = self.a_auth(uri, exp) 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 return download_url
@ -131,6 +131,7 @@ class AliYunOss(object):
req.set_RoleArn(self.sts_role_arn) req.set_RoleArn(self.sts_role_arn)
req.set_RoleSessionName(name) req.set_RoleSessionName(name)
req.set_DurationSeconds(expires) req.set_DurationSeconds(expires)
p_action = "oss:GetObject"
if only_put: if only_put:
p_action = ["oss:PutObject", "oss:AbortMultipartUpload"] p_action = ["oss:PutObject", "oss:AbortMultipartUpload"]
if only_get: 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.expiration = oss2.utils.to_unixtime(j['Credentials']['Expiration'], '%Y-%m-%dT%H:%M:%SZ')
token.bucket = self.bucket_name token.bucket = self.bucket_name
token.endpoint = self.endpoint.replace('-internal', '') 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 return token
def get_upload_token(self, name, expires=1800): def get_upload_token(self, name, expires=1800):
@ -191,9 +192,9 @@ class AliYunOss(object):
# bucket = oss2.Bucket(auth, self.endpoint,self.bucket_name) # bucket = oss2.Bucket(auth, self.endpoint,self.bucket_name)
return self.bucket.delete_object(name) return self.bucket.delete_object(name)
def rename_file(self, oldfilename, newfilename): def rename_file(self, old_filename, new_filename):
self.bucket.copy_object(self.bucket_name, oldfilename, newfilename) self.bucket.copy_object(self.bucket_name, old_filename, new_filename)
return self.del_file(oldfilename) return self.del_file(old_filename)
def upload_file(self, local_file_full_path): def upload_file(self, local_file_full_path):
if os.path.isfile(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) # self.bucket.put_object(os.path.basename(local_file_full_path), fileobj)
return True return True
else: 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): def download_file(self, name, local_file_full_path):
dir_path = os.path.dirname(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 import logging
from django.db.models import F from django.db.models import F
logger = logging.getLogger(__file__) logger = logging.getLogger(__name__)
def sync_download_times_by_app_id(app_ids): 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(): for k, v in down_times_lists.items():
app_id = k.split(CACHE_KEY_TEMPLATE.get("download_times_key"))[1].strip('_') app_id = k.split(CACHE_KEY_TEMPLATE.get("download_times_key"))[1].strip('_')
Apps.objects.filter(app_id=app_id).update(count_hits=v) 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): 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: else:
appudid_obj = AppUDID.objects.filter(app_id_id=app_obj.get("pk"), udid=udid, is_signed=True).first() appudid_obj = AppUDID.objects.filter(app_id_id=app_obj.get("pk"), udid=udid, is_signed=True).first()
if appudid_obj: if appudid_obj:
SuperSign_obj = APPSuperSignUsedInfo.objects.filter(udid__udid=udid, super_sign_obj = APPSuperSignUsedInfo.objects.filter(udid__udid=udid,
app_id_id=app_obj.get("pk")).first() app_id_id=app_obj.get("pk")).first()
if SuperSign_obj and SuperSign_obj.user_id.supersign_active: if super_sign_obj and super_sign_obj.user_id.supersign_active:
APPToDeveloper_obj = APPToDeveloper.objects.filter(app_id_id=app_obj.get("pk"), app_to_developer_obj = APPToDeveloper.objects.filter(app_id_id=app_obj.get("pk"),
developerid=SuperSign_obj.developerid).first() developerid=super_sign_obj.developerid).first()
if APPToDeveloper_obj: if app_to_developer_obj:
release_obj = AppReleaseInfo.objects.filter(app_id_id=app_obj.get("pk"), is_master=True).first() 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: if release_obj.release_id == app_to_developer_obj.release_file:
binary_file = APPToDeveloper_obj.binary_file binary_file = app_to_developer_obj.binary_file
else: else:
binary_file = APPToDeveloper_obj.release_file binary_file = app_to_developer_obj.release_file
return local_storage.get_download_url( return local_storage.get_download_url(
binary_file + "." + download_url_type, limit), "" binary_file + "." + download_url_type, limit), ""
else: 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): 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, '*']) key = "_".join([CACHE_KEY_TEMPLATE.get("download_short_key"), short, '*'])
for app_download_key in cache.iter_keys(key): for app_download_key in cache.iter_keys(key):
cache.delete(app_download_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): 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): for app_obj in Apps.objects.filter(user_id=user_obj):
del_cache_response_by_short(app_obj.app_id) del_cache_response_by_short(app_obj.app_id)
del_cache_by_app_id(app_obj.app_id, user_obj) 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: if cdata:
data["count"] = cdata["count"] + 1 data["count"] = cdata["count"] + 1
data["time"] = time.time() 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) cache.set(cache_key, data, cache_times)
elif act == "get": elif act == "get":
cdata = cache.get(cache_key) cdata = cache.get(cache_key)
if cdata: if cdata:
if cdata["count"] > limit_times: 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 False
return True return True
elif act == "del": elif act == "del":
@ -263,7 +263,7 @@ def limit_cache_util(act, cache_key, cache_limit_times):
def login_auth_failed(act, email): 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]) 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")) 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: try:
UserInfo.objects.filter(pk=user_id).update(download_times=F('download_times') - amount) UserInfo.objects.filter(pk=user_id).update(download_times=F('download_times') - amount)
except Exception as e: 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) disable_user_download_times_flag(user_id)
del_cache_response_by_short(app_id) del_cache_response_by_short(app_id)
return False 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) UserInfo.objects.filter(pk=user_id).update(download_times=F('download_times') + download_times)
return enable_user_download(user_id) return enable_user_download(user_id)
except Exception as e: 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 return False
@ -390,11 +390,11 @@ def consume_user_download_times_by_app_obj(app_obj):
def user_auth_success(user_id): def user_auth_success(user_id):
''' """
认证成功需要调用该方法增加次数 认证成功需要调用该方法增加次数
:param user_id: :param user_id:
:return: :return:
''' """
get_user_free_download_times(user_id, 'get') 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) get_user_free_download_times(user_id, 'set', USER_FREE_DOWNLOAD_TIMES - AUTH_USER_FREE_DOWNLOAD_TIMES)
return enable_user_download(user_id) 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) download_times, user_obj.download_times + download_times)
order_obj.save() order_obj.save()
add_user_download_times(user_id, download_times) 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 return True
except Exception as e: 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: elif order_obj.status == 0:
return True return True
else: else:
return False return False
else: else:
logger.error("%s 订单 %s 订单获取失败,或订单已经支付" % (user_obj, out_trade_no)) logger.error(f"{user_obj} 订单 {out_trade_no} 订单获取失败,或订单已经支付")
except Exception as e: 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 return False

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

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

@ -14,7 +14,7 @@ from fir_ser.settings import THIRD_PART_CONFIG, CACHE_KEY_TEMPLATE
from django.core.cache import cache from django.core.cache import cache
import logging import logging
logger = logging.getLogger(__file__) logger = logging.getLogger(__name__)
def get_storage_auth(storage_obj): 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 storage_type = storage_obj.storage_type
new_storage_obj = cache.get(storage_key) new_storage_obj = cache.get(storage_key)
if new_storage_obj and not assigned_storage_obj: 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 return new_storage_obj
else: else:
if storage_type == 1: if storage_type == 1:
@ -47,12 +47,12 @@ def get_storage(user, assigned_storage_obj, use_default_storage):
new_storage_obj = AliYunOss(**auth) new_storage_obj = AliYunOss(**auth)
else: else:
new_storage_obj = LocalStorage(**auth) 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 new_storage_obj.storage_type = storage_type
cache.set(storage_key, new_storage_obj, 600) cache.set(storage_key, new_storage_obj, 600)
return new_storage_obj return new_storage_obj
else: 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 self.get_default_storage(user, storage_obj, False)
# 不需要管理存储,直接从配置文件获取默认存储 # 不需要管理存储,直接从配置文件获取默认存储
return get_storage_form_conf(user) 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): def get_default_storage(user, storage_obj, use_default_storage):
admin_obj = UserInfo.objects.filter(is_superuser=True).order_by('pk').first() 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: if admin_obj and admin_obj.storage and admin_obj.pk != user.pk:
logger.info("user %s has not storage obj, from admin " logger.info(f"user {user} has not storage obj, from admin get default storage")
"get default storage" % user)
return get_storage(admin_obj, storage_obj, use_default_storage) return get_storage(admin_obj, storage_obj, use_default_storage)
else: else:
return get_storage_form_conf(user) 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): 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) self.storage = get_storage(user, assigned_storage_obj, use_default_storage)
except Exception as e: 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 self.storage = None
def get_upload_token(self, filename, expires=900): 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) cache.set(down_key, {"download_url": download_url, "time": now + expires}, expires)
return download_url return download_url
def delete_file(self, filename, apptype=None): def delete_file(self, filename, app_type=None):
if self.storage: if self.storage:
if apptype is not None: if app_type is not None:
if apptype == 0: if app_type == 0:
filename = filename + '.apk' filename = filename + '.apk'
else: else:
filename = filename + '.ipa' filename = filename + '.ipa'
try: 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) return self.storage.del_file(filename)
except Exception as e: 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: if self.storage:
try: try:
return self.storage.rename_file(oldfilename, newfilename) return self.storage.rename_file(old_filename, new_filename)
except Exception as e: 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): def upload_file(self, local_file_full_path):
if self.storage: if self.storage:
try: try:
return self.storage.upload_file(local_file_full_path) return self.storage.upload_file(local_file_full_path)
except Exception as e: 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): def download_file(self, file_name, local_file_full_path):
if self.storage: if self.storage:
try: try:
return self.storage.download_file(file_name, local_file_full_path) return self.storage.download_file(file_name, local_file_full_path)
except Exception as e: 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): def get_storage_type(self):
if self.storage: 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_", 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]]) base64.b64encode(json.dumps(auth).encode("utf-8")).decode("utf-8")[0:64]])
if clean_cache: 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) cache.delete(storage_key)
new_storage_obj = cache.get(storage_key) new_storage_obj = cache.get(storage_key)
if new_storage_obj: 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 return new_storage_obj
else: else:
new_storage_obj = LocalStorage(**auth) new_storage_obj = LocalStorage(**auth)
new_storage_obj.storage_type = 3 new_storage_obj.storage_type = 3
cache.set(storage_key, new_storage_obj, 600) cache.set(storage_key, new_storage_obj, 600)
logger.info("system get local storage obj, from settings " logger.info(f"system get local storage obj, from settings storage {new_storage_obj}")
"storage %s" % new_storage_obj)
return 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]]) base64.b64encode(json.dumps(auth).encode("utf-8")).decode("utf-8")[0:64]])
new_storage_obj = cache.get(storage_key) new_storage_obj = cache.get(storage_key)
if new_storage_obj: 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 return new_storage_obj
else: else:
if storage_type == 1: if storage_type == 1:
@ -183,7 +181,7 @@ def get_storage_form_conf(user):
new_storage_obj = LocalStorage(**auth) new_storage_obj = LocalStorage(**auth)
new_storage_obj.storage_type = 3 new_storage_obj.storage_type = 3
cache.set(storage_key, new_storage_obj, 600) cache.set(storage_key, new_storage_obj, 600)
logger.warning("user %s has not storage obj, from settings " logger.warning(
"get default storage key:%s obj:%s" % (user, storage_key, new_storage_obj)) f"user {user} has not storage obj, from settings get default storage key:{storage_key} obj:{new_storage_obj}")
return new_storage_obj return new_storage_obj
return None return None

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

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

@ -3,15 +3,17 @@
# project: 5月 # project: 5月
# author: liuyu # author: liuyu
# date: 2020/5/7 # date: 2020/5/7
import os, json, requests, datetime, random import os, datetime, random
from fir_ser.settings import SERVER_DOMAIN, CAPTCHA_LENGTH, MEDIA_ROOT import binascii
from fir_ser.settings import SERVER_DOMAIN, CAPTCHA_LENGTH, MEDIA_ROOT, CACHE_KEY_TEMPLATE
from api.models import APPSuperSignUsedInfo, APPToDeveloper, \ 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.caches import get_app_d_count_by_app_id
from api.utils.storage.localApi import LocalStorage from api.utils.storage.localApi import LocalStorage
from api.utils.storage.storage import Storage from api.utils.storage.storage import Storage
from api.utils.tempcaches import tmpCache from api.utils.tempcaches import TmpCache
from api.utils.TokenManager import DownloadToken, generateNumericTokenOfLength, generateAlphanumericTokenOfLength 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 api.utils.sendmsg.sendmsg import SendMessage
from django.db.models import Sum from django.db.models import Sum
from captcha.models import CaptchaStore from captcha.models import CaptchaStore
@ -77,7 +79,7 @@ def get_captcha():
def valid_captcha(cptch_key, code, username): def valid_captcha(cptch_key, code, username):
if username: if username:
challenge = CaptchaStore.objects.filter(hashkey=cptch_key).values("challenge").first() 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 challenge:
if cptch_key and code and code.strip(" ").lower() == challenge.get("challenge").lower(): if cptch_key and code and code.strip(" ").lower() == challenge.get("challenge").lower():
return True 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): def get_sender_token(sender, user_id, target, action, msg=None):
sms_token_obj = DownloadToken() code = generate_numeric_token_of_length(6)
code = generateNumericTokenOfLength(6) token = make_token(code, time_limit=300, key=user_id)
token = sms_token_obj.make_token(code, time_limit=300, key=user_id) TmpCache.set_tmp_cache(user_id, token, target)
tmpCache.set_tmp_cache(user_id, token, target)
if action == 'change': if action == 'change':
sender.send_change_msg(target, code) sender.send_change_msg(target, code)
elif action == 'register': elif action == 'register':
@ -105,7 +106,7 @@ def get_sender_token(sender, user_id, target, action, msg=None):
elif action == 'msg': elif action == 'msg':
sender.send_email_msg(target, msg) sender.send_email_msg(target, msg)
else: 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 None, None
return token, code return token, code
@ -116,8 +117,7 @@ def get_sender_sms_token(key, phone, action):
def is_valid_sender_code(key, token, code): def is_valid_sender_code(key, token, code):
sms_token_obj = DownloadToken() return verify_token(token, code), TmpCache.get_tmp_cache(key, token)
return sms_token_obj.verify_token(token, code), tmpCache.get_tmp_cache(key, token)
def get_sender_email_token(key, email, action, msg=None): 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): def get_random_username(length=16):
username = generateAlphanumericTokenOfLength(length) username = generate_alphanumeric_token_of_length(length)
if check_username_exists(username): if check_username_exists(username):
return get_random_username(length) return get_random_username(length)
return username return username
@ -145,7 +145,7 @@ def send_ios_developer_active_status(user_info, msg):
if email: if email:
get_sender_email_token(act, email, 'msg', msg) get_sender_email_token(act, email, 'msg', msg)
else: 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): def get_filename_from_apptype(filename, apptype):
@ -163,7 +163,7 @@ def delete_local_files(filename, apptype=None):
try: try:
return storage.del_file(filename) return storage.del_file(filename)
except Exception as e: 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): 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): def clean_storage_data(user_obj, storage_obj=None):
storage_obj = Storage(user_obj, storage_obj) 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(): 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.release_id, app_release_obj.release_type)
storage_obj.delete_file(app_release_obj.icon_url) 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: if choice[0] == key:
return choice[1] return choice[1]
return '' 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:
if count_hits > 0: if count_hits > 0:
logger.info( logger.info(
"update user all_download_times old:%s now:%s" % ( f"update user all_download_times old:{count_hits} now:{request.user.all_download_times}")
count_hits, request.user.all_download_times))
UserInfo.objects.filter(pk=request.user.id).update( UserInfo.objects.filter(pk=request.user.id).update(
all_download_times=count_hits) all_download_times=count_hits)
else: else:
@ -110,14 +109,14 @@ class AppInfoView(APIView):
def get(self, request, app_id): def get(self, request, app_id):
res = BaseResponse() res = BaseResponse()
if app_id: if app_id:
apps_obj = Apps.objects.filter(user_id=request.user, app_id=app_id).first() app_obj = Apps.objects.filter(user_id=request.user, app_id=app_id).first()
if apps_obj: if app_obj:
app_serializer = AppsSerializer(apps_obj, context={"storage": Storage(request.user)}) app_serializer = AppsSerializer(app_obj, context={"storage": Storage(request.user)})
res.data = app_serializer.data 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 res.data["count"] = count
else: 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.msg = "未找到该应用"
res.code = 1003 res.code = 1003
@ -126,8 +125,8 @@ class AppInfoView(APIView):
def delete(self, request, app_id): def delete(self, request, app_id):
res = BaseResponse() res = BaseResponse()
if app_id: if app_id:
apps_obj = Apps.objects.filter(user_id=request.user, app_id=app_id).first() app_obj = Apps.objects.filter(user_id=request.user, app_id=app_id).first()
res = app_delete(apps_obj) res = app_delete(app_obj)
return Response(res.dict) return Response(res.dict)
def put(self, request, app_id): def put(self, request, app_id):
@ -137,16 +136,16 @@ class AppInfoView(APIView):
clean = data.get("clean", None) clean = data.get("clean", None)
if clean: if clean:
logger.info("app_id:%s clean:%s ,close supersign should clean_app_by_user_obj" % (app_id, clean)) logger.info(f"app_id:{app_id} clean:{clean} ,close super_sign should clean_app_by_user_obj")
apps_obj = Apps.objects.filter(user_id=request.user, app_id=app_id).first() app_obj = Apps.objects.filter(user_id=request.user, app_id=app_id).first()
IosUtils.clean_app_by_user_obj(apps_obj, request.user) IosUtils.clean_app_by_user_obj(app_obj, request.user)
return Response(res.dict) return Response(res.dict)
has_combo = data.get("has_combo", None) has_combo = data.get("has_combo", None)
if has_combo: if has_combo:
actions = has_combo.get("action", None) actions = has_combo.get("action", None)
hcombo_id = has_combo.get("hcombo_id", None) hcombo_id = has_combo.get("hcombo_id", None)
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: if actions and hcombo_id:
has_combo = Apps.objects.filter(user_id=request.user, app_id=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) del_cache_response_by_short(has_combo.first().app_id)
except Exception as e: 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.code = 1004
res.msg = "该应用已经关联" res.msg = "该应用已经关联"
else: else:
try: try:
do_sign_flag = 0 do_sign_flag = 0
apps_obj = Apps.objects.filter(user_id=request.user, app_id=app_id).first() 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, apps_obj.__dict__)) logger.info("app_id:%s update old data:%s" % (app_id, app_obj.__dict__))
apps_obj.description = data.get("description", apps_obj.description) app_obj.description = data.get("description", app_obj.description)
apps_obj.short = data.get("short", apps_obj.short) app_obj.short = data.get("short", app_obj.short)
apps_obj.name = data.get("name", apps_obj.name) app_obj.name = data.get("name", app_obj.name)
apps_obj.password = data.get("password", apps_obj.password) app_obj.password = data.get("password", app_obj.password)
apps_obj.supersign_limit_number = data.get("supersign_limit_number", app_obj.supersign_limit_number = data.get("supersign_limit_number",
apps_obj.supersign_limit_number) app_obj.supersign_limit_number)
apps_obj.isshow = data.get("isshow", apps_obj.isshow) app_obj.isshow = data.get("isshow", app_obj.isshow)
if get_user_domain_name(request.user) or get_app_domain_name(apps_obj): if get_user_domain_name(request.user) or get_app_domain_name(app_obj):
apps_obj.wxeasytype = data.get("wxeasytype", apps_obj.wxeasytype) app_obj.wxeasytype = data.get("wxeasytype", app_obj.wxeasytype)
else: else:
apps_obj.wxeasytype = 1 app_obj.wxeasytype = 1
if apps_obj.issupersign: if app_obj.issupersign:
if apps_obj.supersign_type in [x[0] for x in list(apps_obj.supersign_type_choices)]: if app_obj.supersign_type in [x[0] for x in list(app_obj.supersign_type_choices)]:
if apps_obj.supersign_type != data.get("supersign_type", apps_obj.supersign_type): if app_obj.supersign_type != data.get("supersign_type", app_obj.supersign_type):
do_sign_flag = 1 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_id = data.get("new_bundle_id", None)
new_bundle_name = data.get("new_bundle_name", 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 and new_bundle_id != app_obj.bundle_id and len(new_bundle_id) > 3:
if new_bundle_id != apps_obj.new_bundle_id: if new_bundle_id != app_obj.new_bundle_id:
do_sign_flag = 2 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 == '':
if new_bundle_id != apps_obj.new_bundle_id: if new_bundle_id != app_obj.new_bundle_id:
do_sign_flag = 2 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 and new_bundle_name != app_obj.name and len(new_bundle_name) > 0:
if new_bundle_name != apps_obj.new_bundle_name: if new_bundle_name != app_obj.new_bundle_name:
do_sign_flag = 2 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 == '':
# if new_bundle_name != apps_obj.new_bundle_name: # if new_bundle_name != apps_obj.new_bundle_name:
# do_sign_flag = 2 # 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) app_obj.wxredirect = data.get("wxredirect", app_obj.wxredirect)
if apps_obj.type == 1 and data.get('issupersign', -1) != -1: if app_obj.type == 1 and data.get('issupersign', -1) != -1:
# 为啥注释掉,就是该udid已经在该平台使用了,虽然已经没有余额,但是其他应用也是可以超级签名的 # 为啥注释掉,就是该udid已经在该平台使用了,虽然已经没有余额,但是其他应用也是可以超级签名的
# developer_obj = AppIOSDeveloperInfo.objects.filter(user_id=request.user) # developer_obj = AppIOSDeveloperInfo.objects.filter(user_id=request.user)
# use_num = get_developer_devices(developer_obj) # use_num = get_developer_devices(developer_obj)
@ -223,45 +222,45 @@ class AppInfoView(APIView):
# return Response(res.dict) # return Response(res.dict)
developer_count = AppIOSDeveloperInfo.objects.filter(user_id=request.user).count() developer_count = AppIOSDeveloperInfo.objects.filter(user_id=request.user).count()
if developer_count == 0: 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.code = 1008
res.msg = "超级签开发者不存在,无法开启" res.msg = "超级签开发者不存在,无法开启"
return Response(res.dict) return Response(res.dict)
apps_obj.issupersign = data.get("issupersign", apps_obj.issupersign) app_obj.issupersign = data.get("issupersign", app_obj.issupersign)
logger.info("app_id:%s update new data:%s" % (app_id, apps_obj.__dict__)) logger.info(f"app_id:{app_id} update new data:{app_obj.__dict__}")
apps_obj.save() app_obj.save()
if apps_obj.issupersign: if app_obj.issupersign:
c_task = None c_task = None
if do_sign_flag == 1: 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: 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: if c_task:
msg = c_task.get(propagate=False) 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(): if c_task.successful():
c_task.forget() 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: 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.code = 1005
res.msg = "短连接已经存在" res.msg = "短连接已经存在"
return Response(res.dict) return Response(res.dict)
class AppReleaseinfoView(APIView): class AppReleaseInfoView(APIView):
authentication_classes = [ExpiringTokenAuthentication, ] authentication_classes = [ExpiringTokenAuthentication, ]
def get(self, request, app_id, act): def get(self, request, app_id, act):
res = BaseResponse() res = BaseResponse()
res.data = {} res.data = {}
if app_id: if app_id:
apps_obj = Apps.objects.filter(user_id=request.user, app_id=app_id).first() app_obj = Apps.objects.filter(user_id=request.user, app_id=app_id).first()
if apps_obj: if app_obj:
storage = Storage(request.user) storage = Storage(request.user)
app_serializer = AppsSerializer(apps_obj, context={"storage": storage}) app_serializer = AppsSerializer(app_obj, context={"storage": storage})
res = get_release_apps(request, res, app_serializer, apps_obj, storage) res = get_release_apps(request, res, app_serializer, app_obj, storage)
else: else:
res.msg = "未找到该应用" res.msg = "未找到该应用"
res.code = 1003 res.code = 1003
@ -270,52 +269,52 @@ class AppReleaseinfoView(APIView):
def delete(self, request, app_id, act): def delete(self, request, app_id, act):
res = BaseResponse() res = BaseResponse()
if app_id: if app_id:
apps_obj = Apps.objects.filter(user_id=request.user, app_id=app_id).first() app_obj = Apps.objects.filter(user_id=request.user, app_id=app_id).first()
if apps_obj: if app_obj:
storage = Storage(request.user) storage = Storage(request.user)
if act == 'screen': if act == 'screen':
screen_id = request.query_params.get('screen_id', None) screen_id = request.query_params.get('screen_id', None)
if screen_id: 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: if screen_obj:
storage.delete_file(screen_obj.screenshot_url) storage.delete_file(screen_obj.screenshot_url)
screen_obj.delete() 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) return Response(res.dict)
apprelease_count = AppReleaseInfo.objects.filter(app_id=apps_obj).values("release_id").count() app_release_count = AppReleaseInfo.objects.filter(app_id=app_obj).values("release_id").count()
appreleaseobj = AppReleaseInfo.objects.filter(app_id=apps_obj, release_id=act).first() app_release_obj = AppReleaseInfo.objects.filter(app_id=app_obj, release_id=act).first()
if appreleaseobj: if app_release_obj:
if not appreleaseobj.is_master: if not app_release_obj.is_master:
logger.info("delete app release %s" % (appreleaseobj)) logger.info(f"delete app release {app_release_obj}")
storage.delete_file(appreleaseobj.release_id, appreleaseobj.release_type) storage.delete_file(app_release_obj.release_id, app_release_obj.release_type)
delete_local_files(appreleaseobj.release_id, appreleaseobj.release_type) delete_local_files(app_release_obj.release_id, app_release_obj.release_type)
storage.delete_file(appreleaseobj.icon_url) storage.delete_file(app_release_obj.icon_url)
appreleaseobj.delete() app_release_obj.delete()
elif appreleaseobj.is_master and apprelease_count < 2: elif app_release_obj.is_master and app_release_count < 2:
logger.info("delete app master release %s and clean app %s " % (appreleaseobj, apps_obj)) logger.info(f"delete app master release {app_release_obj} and clean app {app_obj}")
count = APPToDeveloper.objects.filter(app_id=apps_obj).count() count = APPToDeveloper.objects.filter(app_id=app_obj).count()
if apps_obj.issupersign or count > 0: if app_obj.issupersign or count > 0:
logger.info("app_id:%s is supersign ,delete this app need clean IOS developer" % (app_id)) logger.info(f"app_id:{app_id} is super_sign ,delete this app need clean IOS developer")
IosUtils.clean_app_by_user_obj(apps_obj, request.user) IosUtils.clean_app_by_user_obj(app_obj, request.user)
storage.delete_file(appreleaseobj.release_id, appreleaseobj.release_type) storage.delete_file(app_release_obj.release_id, app_release_obj.release_type)
delete_local_files(appreleaseobj.release_id, appreleaseobj.release_type) delete_local_files(app_release_obj.release_id, app_release_obj.release_type)
storage.delete_file(appreleaseobj.icon_url) storage.delete_file(app_release_obj.icon_url)
del_cache_by_delete_app(apps_obj.app_id) del_cache_by_delete_app(app_obj.app_id)
appreleaseobj.delete() app_release_obj.delete()
delete_app_screenshots_files(storage, apps_obj) delete_app_screenshots_files(storage, app_obj)
has_combo = apps_obj.has_combo has_combo = app_obj.has_combo
if has_combo: if has_combo:
has_combo.has_combo = None has_combo.has_combo = None
has_combo.save() has_combo.save()
del_cache_response_by_short(has_combo.app_id) del_cache_response_by_short(has_combo.app_id)
apps_obj.delete() app_obj.delete()
else: else:
pass pass
del_cache_response_by_short(apps_obj.app_id) del_cache_response_by_short(app_obj.app_id)
return Response(res.dict) return Response(res.dict)
@ -323,36 +322,36 @@ class AppReleaseinfoView(APIView):
res = BaseResponse() res = BaseResponse()
res.data = {} res.data = {}
if app_id: if app_id:
apps_obj = Apps.objects.filter(user_id=request.user, app_id=app_id).first() app_obj = Apps.objects.filter(user_id=request.user, app_id=app_id).first()
if apps_obj: if app_obj:
appreleaseobj = AppReleaseInfo.objects.filter(app_id=apps_obj, release_id=act) app_release_objs = AppReleaseInfo.objects.filter(app_id=app_obj, release_id=act)
data = request.data data = request.data
make_master = data.get("make_master", None) make_master = data.get("make_master", None)
try: try:
if make_master and make_master == act: if make_master and make_master == act:
AppReleaseInfo.objects.filter(app_id=apps_obj).update(**{"is_master": False}) AppReleaseInfo.objects.filter(app_id=app_obj).update(**{"is_master": False})
appreleaseobj.update(**{"is_master": True}) app_release_objs.update(**{"is_master": True})
else: else:
appreleaseobj.update( app_release_objs.update(
**{"changelog": data.get("changelog", appreleaseobj.first().changelog)}) **{"changelog": data.get("changelog", app_release_objs.first().changelog)})
binary_url = data.get("binary_url", None) binary_url = data.get("binary_url", None)
if binary_url != '': if binary_url != '':
if binary_url: if binary_url:
if not binary_url.startswith('http'): if not binary_url.startswith('http'):
binary_url = 'http://%s' % binary_url binary_url = 'http://%s' % binary_url
else: else:
binary_url = appreleaseobj.first().binary_url binary_url = app_release_objs.first().binary_url
appreleaseobj.update(**{"binary_url": binary_url}) app_release_objs.update(**{"binary_url": binary_url})
logger.info("update app:%s release:%s data:%s" % (apps_obj, appreleaseobj, data)) logger.info(f"update app:{app_obj} release:{app_release_objs} data:{data}")
except Exception as e: 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.code = 1006
res.msg = "更新失败" res.msg = "更新失败"
return Response(res.dict) return Response(res.dict)
del_cache_response_by_short(apps_obj.app_id) del_cache_response_by_short(app_obj.app_id)
app_serializer = AppsSerializer(apps_obj) app_serializer = AppsSerializer(app_obj)
res = get_release_apps(request, res, app_serializer, apps_obj, Storage(request.user)) res = get_release_apps(request, res, app_serializer, app_obj, Storage(request.user))
return Response(res.dict) 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.response import BaseResponse
from api.utils.auth import ExpiringTokenAuthentication from api.utils.auth import ExpiringTokenAuthentication
from rest_framework.response import Response from rest_framework.response import Response
from api.models import UserDomainInfo, DomainCnameInfo, Apps from api.models import UserDomainInfo, Apps
from django.db.models import Count
import logging import logging
from api.utils.storage.caches import set_default_app_wx_easy, del_cache_response_by_short 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.code = 1001
res.msg = "该域名已经被绑定,请更换其他域名" res.msg = "该域名已经被绑定,请更换其他域名"
else: 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() domain_name=domain_name).first()
if user_domian_obj: if user_domain_obj:
res.data = {'cname_domain': user_domian_obj.cname_id.domain_record} res.data = {'cname_domain': user_domain_obj.cname_id.domain_record}
else: else:
UserDomainInfo.objects.filter(**get_domain_filter(request), is_enable=False).delete() UserDomainInfo.objects.filter(**get_domain_filter(request), is_enable=False).delete()
min_domain_cname_info_obj = get_min_default_domain_cname_obj(False) min_domain_cname_info_obj = get_min_default_domain_cname_obj(False)
@ -80,13 +79,13 @@ class DomainCnameView(APIView):
def put(self, request): def put(self, request):
res = BaseResponse() res = BaseResponse()
user_domian_obj = UserDomainInfo.objects.filter(**get_domain_filter(request)).first() user_domain_obj = UserDomainInfo.objects.filter(**get_domain_filter(request)).first()
if user_domian_obj: if user_domain_obj:
cname = get_cname_from_domain(user_domian_obj.domain_name) cname = get_cname_from_domain(user_domain_obj.domain_name)
if cname == user_domian_obj.cname_id.domain_record + '.': if cname == user_domain_obj.cname_id.domain_record + '.':
user_domian_obj.is_enable = True user_domain_obj.is_enable = True
user_domian_obj.save() user_domain_obj.save()
UserDomainInfo.objects.filter(domain_name=user_domian_obj.domain_name, is_enable=False).delete() UserDomainInfo.objects.filter(domain_name=user_domain_obj.domain_name, is_enable=False).delete()
app_id = request.data.get("app_id", None) app_id = request.data.get("app_id", None)
if app_id: if app_id:
app_obj = Apps.objects.filter(app_id=app_id).first() app_obj = Apps.objects.filter(app_id=app_id).first()

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

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

@ -6,14 +6,14 @@ from rest_framework.response import Response
from django.contrib import auth from django.contrib import auth
import logging import logging
logger = logging.getLogger(__file__) logger = logging.getLogger(__name__)
class LogoutView(APIView): class LogoutView(APIView):
authentication_classes = [ExpiringTokenAuthentication] authentication_classes = [ExpiringTokenAuthentication]
def delete(self, request): def delete(self, request):
logger.info("user:%s logout" % (request.user)) logger.info(f"user:{request.user} logout")
user = request.user.pk user = request.user.pk
auth_token = request.auth auth_token = request.auth
cache.delete(auth_token) 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), pay_url = pay_obj.get_pay_pc_url(order_number, int(order_obj.actual_amount),
{'user_id': request.user.id}) {'user_id': request.user.id})
res.data = pay_url res.data = pay_url
logger.info("%s 下单成功 %s" % (request.user, res.dict)) logger.info(f"{request.user} 下单成功 {res.dict}")
return Response(res.dict) return Response(res.dict)
if price_obj: if price_obj:
try: try:
@ -75,14 +75,14 @@ class OrderView(APIView):
actual_download_times=price_obj.package_size, payment_name=pay_obj.name, actual_download_times=price_obj.package_size, payment_name=pay_obj.name,
actual_download_gift_times=price_obj.download_count_gift) actual_download_gift_times=price_obj.download_count_gift)
res.data = pay_url res.data = pay_url
logger.info("%s 下单成功 %s" % (request.user, res.dict)) logger.info(f"{request.user} 下单成功 {res.dict}")
return Response(res.dict) return Response(res.dict)
except Exception as e: 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.code = 1003
res.msg = "订单保存失败" res.msg = "订单保存失败"
else: else:
logger.error("%s 价格 %s 获取失败" % (request.user, price_id)) logger.error(f"{request.user} 价格 {price_id} 获取失败")
res.code = 1002 res.code = 1002
res.msg = "价格获取失败,请稍后重试" res.msg = "价格获取失败,请稍后重试"
else: else:
@ -107,11 +107,11 @@ class OrderView(APIView):
# wxpay = Weixinpay() # wxpay = Weixinpay()
# wxpay.update_order_status(order_obj.order_number) # wxpay.update_order_status(order_obj.order_number)
except Exception as e: 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 res.code = 1003
return Response(res.dict) return Response(res.dict)
else: else:
logger.error("%s 订单 %s 获取失败" % (request.user, order_number)) logger.error(f"{request.user} 订单 {order_number} 获取失败")
res.code = 1003 res.code = 1003
res.msg = "订单获取失败,或订单已经支付" res.msg = "订单获取失败,或订单已经支付"
else: else:
@ -130,11 +130,11 @@ class PriceView(APIView):
res.pay_choices = get_enable_pay_choices() res.pay_choices = get_enable_pay_choices()
return Response(res.dict) return Response(res.dict)
def delete(self, request, price_id): def delete(self, request):
res = BaseResponse() res = BaseResponse()
return Response(res.dict) return Response(res.dict)
def put(self, request, price_id): def put(self, request):
res = BaseResponse() res = BaseResponse()
return Response(res.dict) return Response(res.dict)
@ -149,8 +149,8 @@ class PaySuccess(APIView):
pay_obj = get_pay_obj_form_name(name) pay_obj = get_pay_obj_form_name(name)
msg = 'failure' msg = 'failure'
if pay_obj: if pay_obj:
logger.info("支付回调参数:%s" % request.body) logger.info(f"支付回调参数:{request.body}")
logger.info("支付回调头部:%s" % request.META) logger.info(f"支付回调头部:{request.META}")
if pay_obj.p_type == 'ALI': if pay_obj.p_type == 'ALI':
if pay_obj.valid_order(request): if pay_obj.valid_order(request):
msg = 'success' msg = 'success'

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

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

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

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

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

Loading…
Cancel
Save