优化代码,修复已知Bug,增加本地存储支持阿里云cdn URL鉴权访问

pull/5/head
youngS 4 years ago
parent 504b27831d
commit 291dd950d5
  1. 25
      fir_ser/api/utils/app/supersignutils.py
  2. 4
      fir_ser/api/utils/crontab/run.py
  3. 4
      fir_ser/api/utils/storage/aliyunApi.py
  4. 15
      fir_ser/api/utils/storage/caches.py
  5. 12
      fir_ser/api/utils/storage/localApi.py
  6. 24
      fir_ser/api/utils/storage/storage.py
  7. 56
      fir_ser/api/views/apps.py
  8. 5
      fir_ser/api/views/download.py
  9. 12
      fir_ser/api/views/login.py
  10. 1
      fir_ser/api/views/receiveudids.py
  11. 10
      fir_ser/fir_ser/settings.py

@ -150,12 +150,6 @@ def make_udid_mobileconfig(udid_url, PayloadOrganization, appname, PayloadUUID=u
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_doamin(request)
# PATH_INFO = request.META.get('PATH_INFO')
# PATH_INFO_lists = PATH_INFO.strip('/').split('/')
# PATH_INFO_lists[-1] = 'udid'
# PATH_INFO_lists.pop(-2)
# PATH_INFO_lists.append(short)
# PATH_INFO_lists.insert(0, server_domain)
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
@ -198,8 +192,7 @@ def get_apple_udid_key(auth):
return mpkey return mpkey
def get_http_server_doamin(request): def get_server_domain_from_request(request, server_domain):
server_domain = SERVER_DOMAIN.get('POST_UDID_DOMAIN', None)
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')
@ -210,12 +203,19 @@ def get_http_server_doamin(request):
return server_domain return server_domain
def get_http_server_doamin(request):
server_domain = SERVER_DOMAIN.get('POST_UDID_DOMAIN', None)
return get_server_domain_from_request(request, server_domain)
def get_redirect_server_domain(request, user_obj=None, app_domain_name=None): def get_redirect_server_domain(request, user_obj=None, app_domain_name=None):
if user_obj: if user_obj:
if app_domain_name and len(app_domain_name) > 3: if app_domain_name and len(app_domain_name) > 3:
domain_name = app_domain_name domain_name = app_domain_name
else: else:
domain_name = user_obj.domain_name domain_name = user_obj.domain_name
elif app_domain_name and len(app_domain_name) > 3:
domain_name = app_domain_name
else: else:
domain_name = None domain_name = None
if domain_name and len(domain_name) > 3: if domain_name and len(domain_name) > 3:
@ -225,14 +225,7 @@ def get_redirect_server_domain(request, user_obj=None, app_domain_name=None):
server_domain = "%s://%s" % ('http', domain_name) # 第三方域名暂时不支持HTTPS server_domain = "%s://%s" % ('http', domain_name) # 第三方域名暂时不支持HTTPS
else: else:
server_domain = SERVER_DOMAIN.get('REDIRECT_UDID_DOMAIN', None) server_domain = SERVER_DOMAIN.get('REDIRECT_UDID_DOMAIN', None)
if not server_domain or not server_domain.startswith("http"): return get_server_domain_from_request(request, server_domain)
HTTP_HOST = request.META.get('HTTP_HOST')
SERVER_PROTOCOL = request.META.get('SERVER_PROTOCOL')
protocol = 'https'
if SERVER_PROTOCOL == 'HTTP/1.1':
protocol = 'http'
server_domain = "%s://%s" % (protocol, HTTP_HOST)
return server_domain
class IosUtils(object): class IosUtils(object):

@ -10,6 +10,7 @@ from fir_ser.settings import SYNC_CACHE_TO_DATABASE
from api.utils.crontab.ctasks import sync_download_times, auto_clean_upload_tmp_file, auto_delete_job_log, \ from api.utils.crontab.ctasks import sync_download_times, auto_clean_upload_tmp_file, auto_delete_job_log, \
auto_delete_tmp_file, auto_check_ios_developer_active auto_delete_tmp_file, auto_check_ios_developer_active
import logging import logging
from api.utils.storage.storage import get_local_storage
logger = logging.getLogger(__file__) logger = logging.getLogger(__file__)
@ -60,6 +61,9 @@ try:
register_events(scheduler) register_events(scheduler)
scheduler.start() scheduler.start()
get_local_storage(True)
except Exception as e: except Exception as e:
logger.error("scheduler failed,so shutdown it Exception:%s" % (e)) logger.error("scheduler failed,so shutdown it Exception:%s" % (e))
# 有错误就停止定时器 # 有错误就停止定时器

@ -73,7 +73,9 @@ class AliYunCdn(object):
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 = "%s/%s" % (self.domain, filename)
exp = int(time.time()) + expires exp = int(time.time()) + expires
return self.a_auth(uri, exp) download_url = self.a_auth(uri, exp)
logger.info("make cdn download url %s" % download_url)
return download_url
class StsToken(object): class StsToken(object):

@ -277,10 +277,13 @@ def send_msg_over_limit(act, email):
return limit_cache_util(act, auth_code_key, SYNC_CACHE_TO_DATABASE.get("try_send_msg_over_limit_times")) return limit_cache_util(act, auth_code_key, SYNC_CACHE_TO_DATABASE.get("try_send_msg_over_limit_times"))
def set_default_app_wx_easy(user_obj, app_obj=None): def set_default_app_wx_easy(user_obj, only_clean_cache=False):
if app_obj: app_obj_lists = Apps.objects.filter(user_id=user_obj)
del_cache_response_by_short(app_obj.app_id) for app_obj in app_obj_lists:
else: if only_clean_cache:
app_obj_lists = Apps.objects.filter(user_id=user_obj)
for app_obj in app_obj_lists:
del_cache_response_by_short(app_obj.app_id) del_cache_response_by_short(app_obj.app_id)
else:
if not app_obj.domain_name:
app_obj.wxeasytype = True
app_obj.save()
del_cache_response_by_short(app_obj.app_id)

@ -7,6 +7,7 @@
本地存储api 本地存储api
''' '''
from api.utils.TokenManager import DownloadToken from api.utils.TokenManager import DownloadToken
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
@ -15,9 +16,11 @@ logger = logging.getLogger(__file__)
class LocalStorage(object): class LocalStorage(object):
def __init__(self, domain_name, is_https): def __init__(self, domain_name, is_https, download_auth_type=1, cnd_auth_key=None):
self.domain_name = domain_name self.domain_name = domain_name
self.is_https = is_https self.is_https = is_https
self.download_auth_type = download_auth_type
self.cnd_auth_key = cnd_auth_key
def get_upload_token(self, name, expires): def get_upload_token(self, name, expires):
dtoken = DownloadToken() dtoken = DownloadToken()
@ -32,9 +35,14 @@ class LocalStorage(object):
def get_download_url(self, name, expires=600, force_new=False): def get_download_url(self, name, expires=600, force_new=False):
dtoken = DownloadToken() dtoken = DownloadToken()
download_url = '/'.join([self.get_base_url(), 'download', name]) download_url = '/'.join([self.get_base_url(), 'download', name])
if settings.DATA_DOWNLOAD_KEY_OPEN: if self.download_auth_type == 1:
download_url = "%s?%s=%s" % ( download_url = "%s?%s=%s" % (
download_url, settings.DATA_DOWNLOAD_KEY, dtoken.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:
cdn_obj = AliYunCdn(self.cnd_auth_key, self.is_https, self.domain_name)
download_url = cdn_obj.get_cdn_download_token(name, expires)
elif self.download_auth_type == 0:
pass
return download_url return download_url
def del_file(self, name): def del_file(self, name):

@ -155,3 +155,27 @@ class Storage(object):
storage_obj.user_id, storage_obj.additionalparameters, e)) storage_obj.user_id, storage_obj.additionalparameters, e))
additionalparameters = {} additionalparameters = {}
return {**auth_dict, **additionalparameters} return {**auth_dict, **additionalparameters}
def get_local_storage(clean_cache=False):
storage_lists = THIRD_PART_CONFIG.get('storage')
for storage in storage_lists:
storage_type = storage.get('type', None)
if storage_type == 0:
auth = storage.get('auth', {})
storage_key = "_".join(['local_storage_', CACHE_KEY_TEMPLATE.get('user_storage_key'), "_system_",
base64.b64encode(json.dumps(auth).encode("utf-8")).decode("utf-8")[0:64]])
if clean_cache:
logger.info("system clean local storage obj cache storage_key %s" % storage_key)
cache.delete(storage_key)
new_storage_obj = cache.get(storage_key)
if new_storage_obj:
logger.info("system get local storage obj cache %s" % new_storage_obj)
return new_storage_obj
else:
new_storage_obj = LocalStorage(**auth)
new_storage_obj.storage_type = 3
# cache.set(storage_key, new_storage_obj, 600)
logger.info("system get local storage obj, from settings "
"storage %s" % new_storage_obj)
return new_storage_obj

@ -17,7 +17,6 @@ from api.utils.serializer import AppsSerializer, AppReleaseSerializer, UserInfoS
from rest_framework.pagination import PageNumberPagination from rest_framework.pagination import PageNumberPagination
import logging import logging
from fir_ser.settings import SERVER_DOMAIN from fir_ser.settings import SERVER_DOMAIN
from api.utils.storage.caches import set_default_app_wx_easy
from api.utils.utils import is_valid_domain, delete_local_files from api.utils.utils import is_valid_domain, delete_local_files
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -187,34 +186,32 @@ class AppInfoView(APIView):
elif domain_name: elif domain_name:
apps_obj = Apps.objects.filter(user_id=request.user, app_id=app_id).first() apps_obj = Apps.objects.filter(user_id=request.user, app_id=app_id).first()
logger.info("app_id:%s update old data:%s" % (app_id, apps_obj.__dict__)) logger.info("app_id:%s update old data:%s" % (app_id, apps_obj.__dict__))
if domain_name: domain_name_list = domain_name.strip(' ').replace("http://", "").replace("https://", "").split("/")
domain_name_list = domain_name.strip(' ').replace("http://", "").replace("https://", "").split("/") if len(domain_name_list) > 0:
if len(domain_name_list) > 0: domain_name = domain_name_list[0]
domain_name = domain_name_list[0] if len(domain_name) > 3 and is_valid_domain(domain_name):
if len(domain_name) > 3 and is_valid_domain(domain_name_list[0]): if domain_name == SERVER_DOMAIN.get("REDIRECT_UDID_DOMAIN").split("//")[1]:
if domain_name == SERVER_DOMAIN.get("REDIRECT_UDID_DOMAIN").split("//")[1]: user_admin_obj = UserInfo.objects.filter(is_superuser=True, uid=request.user.uid).order_by(
admin_storage = UserInfo.objects.filter(is_superuser=True).order_by('pk').first() 'pk').first()
if admin_storage and admin_storage.uid == request.user.uid: if user_admin_obj:
apps_obj.domain_name = domain_name
set_default_app_wx_easy(request.user, apps_obj)
else:
serializer = UserInfoSerializer(request.user)
res.data = serializer.data
res.code = 1004
res.msg = "域名设置失败,请更换其他域名"
return Response(res.dict)
else:
apps_obj.domain_name = domain_name apps_obj.domain_name = domain_name
set_default_app_wx_easy(request.user, apps_obj) else:
serializer = UserInfoSerializer(request.user)
res.data = serializer.data
res.code = 1004
res.msg = "域名设置失败,请更换其他域名"
return Response(res.dict)
else: else:
res.code = 1004 apps_obj.domain_name = domain_name
res.msg = "域名校验失败" else:
return Response(res.dict) res.code = 1004
res.msg = "域名校验失败"
return Response(res.dict)
if domain_name == '': if domain_name == '':
apps_obj.domain_name = None apps_obj.domain_name = None
apps_obj.wxeasytype = True if not request.user.domain_name:
set_default_app_wx_easy(request.user, apps_obj) apps_obj.wxeasytype = True
apps_obj.save() apps_obj.save()
del_cache_response_by_short(apps_obj.app_id) del_cache_response_by_short(apps_obj.app_id)
return Response(res.dict) return Response(res.dict)
@ -230,17 +227,6 @@ class AppInfoView(APIView):
apps_obj.supersign_limit_number = data.get("supersign_limit_number", apps_obj.supersign_limit_number = data.get("supersign_limit_number",
apps_obj.supersign_limit_number) apps_obj.supersign_limit_number)
apps_obj.isshow = data.get("isshow", apps_obj.isshow) apps_obj.isshow = data.get("isshow", apps_obj.isshow)
domain_name = data.get("domain_name", None)
if domain_name:
domain_name_list = domain_name.strip(' ').replace("http://", "").replace("https://", "").split(
"/")
if len(domain_name_list) > 0:
domain_name = domain_name_list[0]
if len(domain_name) > 3 and is_valid_domain(domain_name):
apps_obj.domain_name = data.get("domain_name", apps_obj.domain_name)
if domain_name == '':
apps_obj.domain_name = None
if (request.user.domain_name and len(request.user.domain_name) > 3) or ( if (request.user.domain_name and len(request.user.domain_name) > 3) or (
apps_obj.domain_name and len(apps_obj.domain_name) > 3): apps_obj.domain_name and len(apps_obj.domain_name) > 3):

@ -11,7 +11,7 @@ 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_mobileconfig, get_post_udid_url, get_redirect_server_domain
from api.utils.storage.storage import 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 del_cache_response_by_short
import os import os
@ -35,7 +35,8 @@ class DownloadView(APIView):
downtoken = request.query_params.get(settings.DATA_DOWNLOAD_KEY, None) downtoken = request.query_params.get(settings.DATA_DOWNLOAD_KEY, None)
ftype = filename.split(".")[-1] ftype = filename.split(".")[-1]
flag = True flag = True
if settings.DATA_DOWNLOAD_KEY_OPEN: storage_obj = get_local_storage()
if storage_obj.download_auth_type == 1:
if not downtoken: if not downtoken:
res.code = 1004 res.code = 1004
res.msg = "缺失token" res.msg = "缺失token"

@ -360,12 +360,13 @@ class UserInfoView(APIView):
domain_name_list = domain_name.strip(' ').replace("http://", "").replace("https://", "").split("/") domain_name_list = domain_name.strip(' ').replace("http://", "").replace("https://", "").split("/")
if len(domain_name_list) > 0: if len(domain_name_list) > 0:
domain_name = domain_name_list[0] domain_name = domain_name_list[0]
if len(domain_name) > 3 and is_valid_domain(domain_name_list[0]): if len(domain_name) > 3 and is_valid_domain(domain_name):
if domain_name == SERVER_DOMAIN.get("REDIRECT_UDID_DOMAIN").split("//")[1]: if domain_name == SERVER_DOMAIN.get("REDIRECT_UDID_DOMAIN").split("//")[1]:
admin_storage = UserInfo.objects.filter(is_superuser=True).order_by('pk').first() user_admin_obj = UserInfo.objects.filter(is_superuser=True, uid=request.user.uid).order_by(
if admin_storage and admin_storage.uid == request.user.uid: 'pk').first()
if user_admin_obj:
request.user.domain_name = domain_name request.user.domain_name = domain_name
set_default_app_wx_easy(request.user) set_default_app_wx_easy(request.user, True)
else: else:
serializer = UserInfoSerializer(request.user) serializer = UserInfoSerializer(request.user)
res.data = serializer.data res.data = serializer.data
@ -374,7 +375,7 @@ class UserInfoView(APIView):
return Response(res.dict) return Response(res.dict)
else: else:
request.user.domain_name = domain_name request.user.domain_name = domain_name
set_default_app_wx_easy(request.user) set_default_app_wx_easy(request.user, True)
else: else:
serializer = UserInfoSerializer(request.user) serializer = UserInfoSerializer(request.user)
res.data = serializer.data res.data = serializer.data
@ -384,7 +385,6 @@ class UserInfoView(APIView):
if domain_name == '': if domain_name == '':
request.user.domain_name = None request.user.domain_name = None
Apps.objects.filter(user_id=request.user).update(wxeasytype=True)
set_default_app_wx_easy(request.user) set_default_app_wx_easy(request.user)
username = data.get("username", None) username = data.get("username", None)

@ -26,6 +26,7 @@ class IosUDIDView(View):
app_info = Apps.objects.filter(short=short).first() app_info = Apps.objects.filter(short=short).first()
if app_info: if app_info:
server_domain = get_redirect_server_domain(request, None, app_info.domain_name)
if app_info.issupersign and app_info.user_id.supersign_active: if app_info.issupersign and app_info.user_id.supersign_active:
ios_obj = IosUtils(format_udid_info, app_info.user_id, app_info) ios_obj = IosUtils(format_udid_info, app_info.user_id, app_info)
status, msg = ios_obj.sign() status, msg = ios_obj.sign()

@ -196,8 +196,10 @@ THIRD_PART_CONFIG = {
'name': 'local', 'name': 'local',
'type': 0, 'type': 0,
'auth': { 'auth': {
'domain_name': 'app.hehelucky.cn', # 正式环境需要填写正式的访问域名 'domain_name': 'app.hehelucky.cn', # 正式环境需要填写正式的访问域名,如果配置cdn,可以填写cdn的域名,仅支持阿里云 cdn
'is_https': True, 'is_https': True,
'download_auth_type': 0, # 0:不开启token 1:本地token 2:cdn 开启cdn,并且使用本地存储,使用阿里云cdn进行url鉴权,
'cnd_auth_key': '', # 当cdn为阿里云并且 download_auth_type=2 的时候 生效,需要 开启阿里云OSS私有Bucket回源
}, },
'active': True 'active': True
}, },
@ -212,7 +214,8 @@ THIRD_PART_CONFIG = {
'endpoint': 'oss-cn-beijing.aliyuncs.com', 'endpoint': 'oss-cn-beijing.aliyuncs.com',
'is_https': True, 'is_https': True,
'domain_name': 'aoud.xin', 'domain_name': 'aoud.xin',
'download_auth_type': 1 # 1:oss 2:cdn 'download_auth_type': 1, # 1:oss 2:cdn
'cnd_auth_key': '', # 当cdn为阿里云并且 download_auth_type=2 的时候 生效,需要 开启阿里云OSS私有Bucket回源
}, },
'active': False 'active': False
}, },
@ -299,7 +302,6 @@ CACHE_KEY_TEMPLATE = {
} }
DATA_DOWNLOAD_KEY = "d_token" DATA_DOWNLOAD_KEY = "d_token"
DATA_DOWNLOAD_KEY_OPEN = True # 是否开启图片和应用下载token,只本地存储支持该操作
FILE_UPLOAD_TMP_KEY = ".tmp" FILE_UPLOAD_TMP_KEY = ".tmp"
SYNC_CACHE_TO_DATABASE = { SYNC_CACHE_TO_DATABASE = {
@ -317,7 +319,7 @@ SERVER_DOMAIN = {
'IOS_PMFILE_DOWNLOAD_DOMAIN': { 'IOS_PMFILE_DOWNLOAD_DOMAIN': {
"domain_name": 'app.hehelucky.cn', "domain_name": 'app.hehelucky.cn',
'is_https': True, 'is_https': True,
}, # ios 描述文件和plist文件下载域名,该域名用于后端,一般为api访问域名 }, # 验证码,ios 描述文件和plist文件下载域名,该域名用于后端,一般为api访问域名
'POST_UDID_DOMAIN': 'https://app.hehelucky.cn', # 超级签名 安装签名时 向该域名 发送udid数据,该域名用于后端,一般为 api 访问域名 'POST_UDID_DOMAIN': 'https://app.hehelucky.cn', # 超级签名 安装签名时 向该域名 发送udid数据,该域名用于后端,一般为 api 访问域名
'REDIRECT_UDID_DOMAIN': 'https://app.hehelucky.cn', # 超级签名 安装完成之后,跳转域名,该域名为前端web访问域名,如果用户定义了自己的域名,则跳转用户域名 'REDIRECT_UDID_DOMAIN': 'https://app.hehelucky.cn', # 超级签名 安装完成之后,跳转域名,该域名为前端web访问域名,如果用户定义了自己的域名,则跳转用户域名
'FILE_UPLOAD_DOMAIN': 'https://app.hehelucky.cn', # 本地文件上传域名,使用本地存储必须配置 'FILE_UPLOAD_DOMAIN': 'https://app.hehelucky.cn', # 本地文件上传域名,使用本地存储必须配置

Loading…
Cancel
Save