From 291dd950d5932341e038afe03f57784a36fac372 Mon Sep 17 00:00:00 2001 From: youngS Date: Mon, 15 Mar 2021 16:37:55 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=BB=A3=E7=A0=81=EF=BC=8C?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=B7=B2=E7=9F=A5Bug,=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E6=9C=AC=E5=9C=B0=E5=AD=98=E5=82=A8=E6=94=AF=E6=8C=81=E9=98=BF?= =?UTF-8?q?=E9=87=8C=E4=BA=91cdn=20URL=E9=89=B4=E6=9D=83=E8=AE=BF=E9=97=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fir_ser/api/utils/app/supersignutils.py | 25 ++++------- fir_ser/api/utils/crontab/run.py | 4 ++ fir_ser/api/utils/storage/aliyunApi.py | 4 +- fir_ser/api/utils/storage/caches.py | 15 ++++--- fir_ser/api/utils/storage/localApi.py | 12 +++++- fir_ser/api/utils/storage/storage.py | 24 +++++++++++ fir_ser/api/views/apps.py | 56 ++++++++++--------------- fir_ser/api/views/download.py | 5 ++- fir_ser/api/views/login.py | 12 +++--- fir_ser/api/views/receiveudids.py | 1 + fir_ser/fir_ser/settings.py | 10 +++-- 11 files changed, 96 insertions(+), 72 deletions(-) diff --git a/fir_ser/api/utils/app/supersignutils.py b/fir_ser/api/utils/app/supersignutils.py index 914e6c4..9b851e4 100644 --- a/fir_ser/api/utils/app/supersignutils.py +++ b/fir_ser/api/utils/app/supersignutils.py @@ -150,12 +150,6 @@ def make_udid_mobileconfig(udid_url, PayloadOrganization, appname, PayloadUUID=u def get_post_udid_url(request, short): 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] udid_url = "/".join(PATH_INFO_lists) return udid_url @@ -198,8 +192,7 @@ def get_apple_udid_key(auth): return mpkey -def get_http_server_doamin(request): - server_domain = SERVER_DOMAIN.get('POST_UDID_DOMAIN', None) +def get_server_domain_from_request(request, server_domain): if not server_domain or not server_domain.startswith("http"): HTTP_HOST = request.META.get('HTTP_HOST') SERVER_PROTOCOL = request.META.get('SERVER_PROTOCOL') @@ -210,12 +203,19 @@ def get_http_server_doamin(request): 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): if user_obj: if app_domain_name and len(app_domain_name) > 3: domain_name = app_domain_name else: domain_name = user_obj.domain_name + elif app_domain_name and len(app_domain_name) > 3: + domain_name = app_domain_name else: domain_name = None 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 else: server_domain = SERVER_DOMAIN.get('REDIRECT_UDID_DOMAIN', None) - if not server_domain or not server_domain.startswith("http"): - 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 + return get_server_domain_from_request(request, server_domain) class IosUtils(object): diff --git a/fir_ser/api/utils/crontab/run.py b/fir_ser/api/utils/crontab/run.py index 78510ca..845d168 100644 --- a/fir_ser/api/utils/crontab/run.py +++ b/fir_ser/api/utils/crontab/run.py @@ -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, \ auto_delete_tmp_file, auto_check_ios_developer_active import logging +from api.utils.storage.storage import get_local_storage logger = logging.getLogger(__file__) @@ -60,6 +61,9 @@ try: register_events(scheduler) scheduler.start() + + get_local_storage(True) + except Exception as e: logger.error("scheduler failed,so shutdown it Exception:%s" % (e)) # 有错误就停止定时器 diff --git a/fir_ser/api/utils/storage/aliyunApi.py b/fir_ser/api/utils/storage/aliyunApi.py index 75fab9c..a4f0f36 100644 --- a/fir_ser/api/utils/storage/aliyunApi.py +++ b/fir_ser/api/utils/storage/aliyunApi.py @@ -73,7 +73,9 @@ class AliYunCdn(object): def get_cdn_download_token(self, filename, expires=1800): uri = "%s/%s" % (self.domain, filename) 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): diff --git a/fir_ser/api/utils/storage/caches.py b/fir_ser/api/utils/storage/caches.py index cbb7c66..fbf0ad4 100644 --- a/fir_ser/api/utils/storage/caches.py +++ b/fir_ser/api/utils/storage/caches.py @@ -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")) -def set_default_app_wx_easy(user_obj, app_obj=None): - if app_obj: - del_cache_response_by_short(app_obj.app_id) - else: - app_obj_lists = Apps.objects.filter(user_id=user_obj) - for app_obj in app_obj_lists: +def set_default_app_wx_easy(user_obj, only_clean_cache=False): + app_obj_lists = Apps.objects.filter(user_id=user_obj) + for app_obj in app_obj_lists: + if only_clean_cache: 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) diff --git a/fir_ser/api/utils/storage/localApi.py b/fir_ser/api/utils/storage/localApi.py index 772f5ce..31525cb 100644 --- a/fir_ser/api/utils/storage/localApi.py +++ b/fir_ser/api/utils/storage/localApi.py @@ -7,6 +7,7 @@ 本地存储api ''' from api.utils.TokenManager import DownloadToken +from api.utils.storage.aliyunApi import AliYunCdn from fir_ser import settings import os import logging @@ -15,9 +16,11 @@ logger = logging.getLogger(__file__) 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.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): dtoken = DownloadToken() @@ -32,9 +35,14 @@ class LocalStorage(object): def get_download_url(self, name, expires=600, force_new=False): dtoken = DownloadToken() 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, 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 def del_file(self, name): diff --git a/fir_ser/api/utils/storage/storage.py b/fir_ser/api/utils/storage/storage.py index 6a91635..3615819 100644 --- a/fir_ser/api/utils/storage/storage.py +++ b/fir_ser/api/utils/storage/storage.py @@ -155,3 +155,27 @@ class Storage(object): storage_obj.user_id, storage_obj.additionalparameters, e)) 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 diff --git a/fir_ser/api/views/apps.py b/fir_ser/api/views/apps.py index 5ed5c69..226eda8 100644 --- a/fir_ser/api/views/apps.py +++ b/fir_ser/api/views/apps.py @@ -17,7 +17,6 @@ from api.utils.serializer import AppsSerializer, AppReleaseSerializer, UserInfoS from rest_framework.pagination import PageNumberPagination import logging 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 logger = logging.getLogger(__name__) @@ -187,34 +186,32 @@ class AppInfoView(APIView): elif domain_name: apps_obj = Apps.objects.filter(user_id=request.user, app_id=app_id).first() logger.info("app_id:%s update old data:%s" % (app_id, apps_obj.__dict__)) - 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_list[0]): - if domain_name == SERVER_DOMAIN.get("REDIRECT_UDID_DOMAIN").split("//")[1]: - admin_storage = UserInfo.objects.filter(is_superuser=True).order_by('pk').first() - if admin_storage and admin_storage.uid == request.user.uid: - 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: + domain_name_list = domain_name.strip(' ').replace("http://", "").replace("https://", "").split("/") + if len(domain_name_list) > 0: + domain_name = domain_name_list[0] + if len(domain_name) > 3 and is_valid_domain(domain_name): + if domain_name == SERVER_DOMAIN.get("REDIRECT_UDID_DOMAIN").split("//")[1]: + user_admin_obj = UserInfo.objects.filter(is_superuser=True, uid=request.user.uid).order_by( + 'pk').first() + if user_admin_obj: apps_obj.domain_name = domain_name - 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: - res.code = 1004 - res.msg = "域名校验失败" - return Response(res.dict) + apps_obj.domain_name = domain_name + else: + res.code = 1004 + res.msg = "域名校验失败" + return Response(res.dict) if domain_name == '': apps_obj.domain_name = None - apps_obj.wxeasytype = True - set_default_app_wx_easy(request.user, apps_obj) + if not request.user.domain_name: + apps_obj.wxeasytype = True apps_obj.save() del_cache_response_by_short(apps_obj.app_id) 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) 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 ( apps_obj.domain_name and len(apps_obj.domain_name) > 3): diff --git a/fir_ser/api/views/download.py b/fir_ser/api/views/download.py index 4f6d834..d0f8a6a 100644 --- a/fir_ser/api/views/download.py +++ b/fir_ser/api/views/download.py @@ -11,7 +11,7 @@ from api.utils.TokenManager import DownloadToken from api.utils.app.randomstrings import make_random_uuid from api.utils.app.apputils import make_resigned from api.utils.app.supersignutils import make_sign_udid_mobileconfig, get_post_udid_url, get_redirect_server_domain -from api.utils.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, \ del_cache_response_by_short import os @@ -35,7 +35,8 @@ class DownloadView(APIView): downtoken = request.query_params.get(settings.DATA_DOWNLOAD_KEY, None) ftype = filename.split(".")[-1] flag = True - if settings.DATA_DOWNLOAD_KEY_OPEN: + storage_obj = get_local_storage() + if storage_obj.download_auth_type == 1: if not downtoken: res.code = 1004 res.msg = "缺失token" diff --git a/fir_ser/api/views/login.py b/fir_ser/api/views/login.py index dceb109..bec89cf 100644 --- a/fir_ser/api/views/login.py +++ b/fir_ser/api/views/login.py @@ -360,12 +360,13 @@ class UserInfoView(APIView): 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_list[0]): + if len(domain_name) > 3 and is_valid_domain(domain_name): if domain_name == SERVER_DOMAIN.get("REDIRECT_UDID_DOMAIN").split("//")[1]: - admin_storage = UserInfo.objects.filter(is_superuser=True).order_by('pk').first() - if admin_storage and admin_storage.uid == request.user.uid: + user_admin_obj = UserInfo.objects.filter(is_superuser=True, uid=request.user.uid).order_by( + 'pk').first() + if user_admin_obj: request.user.domain_name = domain_name - set_default_app_wx_easy(request.user) + set_default_app_wx_easy(request.user, True) else: serializer = UserInfoSerializer(request.user) res.data = serializer.data @@ -374,7 +375,7 @@ class UserInfoView(APIView): return Response(res.dict) else: request.user.domain_name = domain_name - set_default_app_wx_easy(request.user) + set_default_app_wx_easy(request.user, True) else: serializer = UserInfoSerializer(request.user) res.data = serializer.data @@ -384,7 +385,6 @@ class UserInfoView(APIView): if domain_name == '': request.user.domain_name = None - Apps.objects.filter(user_id=request.user).update(wxeasytype=True) set_default_app_wx_easy(request.user) username = data.get("username", None) diff --git a/fir_ser/api/views/receiveudids.py b/fir_ser/api/views/receiveudids.py index 586ae0b..be0f3fe 100644 --- a/fir_ser/api/views/receiveudids.py +++ b/fir_ser/api/views/receiveudids.py @@ -26,6 +26,7 @@ class IosUDIDView(View): app_info = Apps.objects.filter(short=short).first() 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: ios_obj = IosUtils(format_udid_info, app_info.user_id, app_info) status, msg = ios_obj.sign() diff --git a/fir_ser/fir_ser/settings.py b/fir_ser/fir_ser/settings.py index ad1caa5..5650d74 100644 --- a/fir_ser/fir_ser/settings.py +++ b/fir_ser/fir_ser/settings.py @@ -196,8 +196,10 @@ THIRD_PART_CONFIG = { 'name': 'local', 'type': 0, 'auth': { - 'domain_name': 'app.hehelucky.cn', # 正式环境需要填写正式的访问域名 + 'domain_name': 'app.hehelucky.cn', # 正式环境需要填写正式的访问域名,如果配置cdn,可以填写cdn的域名,仅支持阿里云 cdn '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 }, @@ -212,7 +214,8 @@ THIRD_PART_CONFIG = { 'endpoint': 'oss-cn-beijing.aliyuncs.com', 'is_https': True, '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 }, @@ -299,7 +302,6 @@ CACHE_KEY_TEMPLATE = { } DATA_DOWNLOAD_KEY = "d_token" -DATA_DOWNLOAD_KEY_OPEN = True # 是否开启图片和应用下载token,只本地存储支持该操作 FILE_UPLOAD_TMP_KEY = ".tmp" SYNC_CACHE_TO_DATABASE = { @@ -317,7 +319,7 @@ SERVER_DOMAIN = { 'IOS_PMFILE_DOWNLOAD_DOMAIN': { "domain_name": 'app.hehelucky.cn', 'is_https': True, - }, # ios 描述文件和plist文件下载域名,该域名用于后端,一般为api访问域名 + }, # 验证码,ios 描述文件和plist文件下载域名,该域名用于后端,一般为api访问域名 'POST_UDID_DOMAIN': 'https://app.hehelucky.cn', # 超级签名 安装签名时 向该域名 发送udid数据,该域名用于后端,一般为 api 访问域名 'REDIRECT_UDID_DOMAIN': 'https://app.hehelucky.cn', # 超级签名 安装完成之后,跳转域名,该域名为前端web访问域名,如果用户定义了自己的域名,则跳转用户域名 'FILE_UPLOAD_DOMAIN': 'https://app.hehelucky.cn', # 本地文件上传域名,使用本地存储必须配置