diff --git a/fir_client/src/components/FirAppInfosbaseinfo.vue b/fir_client/src/components/FirAppInfosbaseinfo.vue index 7a61130..247c0c6 100644 --- a/fir_client/src/components/FirAppInfosbaseinfo.vue +++ b/fir_client/src/components/FirAppInfosbaseinfo.vue @@ -106,7 +106,11 @@ } else { //本地 - certinfo.upload_url = getuploadurl(); + if (certinfo.domain_name) { + certinfo.upload_url = getuploadurl(certinfo.domain_name) + } else { + certinfo.upload_url = getuploadurl(); + } // eslint-disable-next-line no-unused-vars,no-unreachable uploadlocalstorage(file, certinfo, this, res => { this.updateimgs(certinfo); diff --git a/fir_client/src/components/FirAppInfossecurity.vue b/fir_client/src/components/FirAppInfossecurity.vue index 5faa67a..2089bf6 100644 --- a/fir_client/src/components/FirAppInfossecurity.vue +++ b/fir_client/src/components/FirAppInfossecurity.vue @@ -65,6 +65,7 @@ - 默认开启,可以最大限度避免微信内举报封停 + 默认开启,可以最大限度避免微信内举报封停,如果绑定域名,可以关闭 @@ -119,7 +120,8 @@ showsupersignflag: false, wxeasytypeflag: false, wxredirectflag: false, - clecount: 0 + clecount: 0, + wxeasy_disable:false } }, methods: { @@ -186,6 +188,9 @@ this.wxeasytypetip.val = 'off'; } this.wxeasytypeflag = true; + if(!this.$store.state.userinfo.domain_name){ + this.wxeasy_disable=true; + } }, setwxredirectshow(currentapp) { if (currentapp.wxredirect === 1) { diff --git a/fir_client/src/components/FirApps.vue b/fir_client/src/components/FirApps.vue index 1f5208b..60a1b82 100644 --- a/fir_client/src/components/FirApps.vue +++ b/fir_client/src/components/FirApps.vue @@ -480,7 +480,11 @@ }); } else { //本地 - certinfo.upload_url = getuploadurl(); + if (this.analyseappinfo.domain_name) { + certinfo.upload_url = getuploadurl(this.analyseappinfo.domain_name) + } else { + certinfo.upload_url = getuploadurl(); + } certinfo.ftype = 'app'; certinfo.app_id = this.analyseappinfo.app_uuid; // eslint-disable-next-line no-unused-vars,no-unreachable diff --git a/fir_client/src/components/FirDownload.vue b/fir_client/src/components/FirDownload.vue index a305ad0..8b1585c 100644 --- a/fir_client/src/components/FirDownload.vue +++ b/fir_client/src/components/FirDownload.vue @@ -256,6 +256,19 @@ } }, + auto_redircet_url(domain_name) { + if (domain_name) { + let nurl = location.href.split("//")[1].split("/"); + const user_hostname = domain_name.split("//"); + if (nurl[0] === user_hostname[1]) { + return true; + } else { + nurl[0] = user_hostname[1]; + window.location.href = user_hostname[0] + "//" + nurl.join("/"); + return false; + } + } + }, getDownloadTokenFun() { let params = {"short": this.$route.params.short, "time": new Date().getTime()}; if (this.$route.query.release_id) { @@ -268,6 +281,9 @@ } getShortAppinfo(data => { if (data.code === 1000) { + if (!this.auto_redircet_url(data.domain_name)) { + return; + } this.udid = data.udid; if (!data.data.master_release.release_id) { this.$message({ diff --git a/fir_client/src/components/FirUserProfileBase.vue b/fir_client/src/components/FirUserProfileBase.vue index 3aa6f25..2c4acf0 100644 --- a/fir_client/src/components/FirUserProfileBase.vue +++ b/fir_client/src/components/FirUserProfileBase.vue @@ -108,7 +108,11 @@ } else { //本地 - certinfo.upload_url = getuploadurl(); + if (certinfo.domain_name) { + certinfo.upload_url = getuploadurl(certinfo.domain_name) + } else { + certinfo.upload_url = getuploadurl(); + } // eslint-disable-next-line no-unused-vars,no-unreachable uploadlocalstorage(file, certinfo, this, res => { this.updateimgs(certinfo); diff --git a/fir_client/src/components/FirUserProfileInfo.vue b/fir_client/src/components/FirUserProfileInfo.vue index 2eab141..39719e8 100644 --- a/fir_client/src/components/FirUserProfileInfo.vue +++ b/fir_client/src/components/FirUserProfileInfo.vue @@ -13,15 +13,15 @@ - + - + 保存 @@ -98,7 +98,7 @@ srccode: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg', }, editphone: false, - editqq: false, + editdomain_name: false, editposition: false } }, methods: { @@ -154,11 +154,11 @@ }, changeQQValue() { - this.editqq = !this.editqq; - if (this.$refs.qq.$el.children[0].style.backgroundColor) { - this.$refs.qq.$el.children[0].style.backgroundColor = '' + this.editdomain_name = !this.editdomain_name; + if (this.$refs.domain_name.$el.children[0].style.backgroundColor) { + this.$refs.domain_name.$el.children[0].style.backgroundColor = '' } else { - this.$refs.qq.$el.children[0].style.backgroundColor = '#f6ffdc'; + this.$refs.domain_name.$el.children[0].style.backgroundColor = '#f6ffdc'; } }, getphonecode() { diff --git a/fir_client/src/restful/index.js b/fir_client/src/restful/index.js index 6b006c2..c1f1e8b 100644 --- a/fir_client/src/restful/index.js +++ b/fir_client/src/restful/index.js @@ -289,8 +289,12 @@ export function getapppicurl(app_id) { return USERSEVER + '/apps/' + app_id } -export function getuploadurl() { - return USERSEVER + '/upload' +export function getuploadurl(domain_name=null) { + if (domain_name) { + return domain_name + APIPATH + '/upload' + } else { + return USERSEVER + '/upload'; + } } diff --git a/fir_download/src/components/FirDownload.vue b/fir_download/src/components/FirDownload.vue index ee8cb36..ef0524d 100644 --- a/fir_download/src/components/FirDownload.vue +++ b/fir_download/src/components/FirDownload.vue @@ -1,1583 +1,1601 @@ + + diff --git a/fir_ser/api/models.py b/fir_ser/api/models.py index d601ce5..24edddd 100644 --- a/fir_ser/api/models.py +++ b/fir_ser/api/models.py @@ -38,7 +38,7 @@ class UserInfo(AbstractUser): date_joined = models.DateTimeField(auto_now_add=True, verbose_name="注册时间") download_times = models.IntegerField(default=100, verbose_name="下载次数") all_download_times = models.BigIntegerField(default=0, verbose_name="总共下载次数") - domain_name = models.CharField(verbose_name="域名", blank=True, null=True, max_length=64) + domain_name = models.CharField(verbose_name="下载页面域名", blank=True, null=True, max_length=64) history_release_limit = models.IntegerField(default=10, verbose_name="app 历史记录版本", blank=True, null=True) storage = models.OneToOneField(to='AppStorage', related_name='app_storage', on_delete=models.SET_NULL, verbose_name="存储", null=True, blank=True) diff --git a/fir_ser/api/utils/app/supersignutils.py b/fir_ser/api/utils/app/supersignutils.py index d5f3c60..0cac03c 100644 --- a/fir_ser/api/utils/app/supersignutils.py +++ b/fir_ser/api/utils/app/supersignutils.py @@ -97,8 +97,15 @@ def get_http_server_doamin(request): return server_domain -def get_redirect_server_domain(request): - server_domain = SERVER_DOMAIN.get('REDIRECT_UDID_DOMAIN', None) +def get_redirect_server_domain(request, user_obj=None): + if user_obj: + domain_name = user_obj.domain_name + else: + domain_name = request.user.domain_name + if domain_name and len(domain_name) > 3: + 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') @@ -178,7 +185,7 @@ class IosUtils(object): status, result = self.download_profile() if not status: logger.error("udid %s app %s developer %s sign failed %s" % ( - self.udid_info.get('udid'), self.app_obj, self.developer_obj, result)) + self.udid_info.get('udid'), self.app_obj, self.developer_obj, result)) self.developer_obj.is_actived = False self.developer_obj.save() return diff --git a/fir_ser/api/utils/serializer.py b/fir_ser/api/utils/serializer.py index 3080bbe..9d63915 100644 --- a/fir_ser/api/utils/serializer.py +++ b/fir_ser/api/utils/serializer.py @@ -16,7 +16,7 @@ class UserInfoSerializer(serializers.ModelSerializer): model = models.UserInfo # fields="__all__" # exclude = ["password","is_active","user_permissions","role",] - fields = ["username", "uid", "qq", "mobile", "job", "email", "domain_name", "last_login", "first_name", + fields = ["username", "uid", "mobile", "job", "email", "domain_name", "last_login", "first_name", 'head_img'] head_img = serializers.SerializerMethodField() diff --git a/fir_ser/api/utils/storage/caches.py b/fir_ser/api/utils/storage/caches.py index b33b71d..d141c70 100644 --- a/fir_ser/api/utils/storage/caches.py +++ b/fir_ser/api/utils/storage/caches.py @@ -219,3 +219,9 @@ def login_auth_failed(act, email): return True elif act == "del": cache.delete(auth_code_key) + + +def set_default_app_wx_easy(user_obj): + 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) diff --git a/fir_ser/api/views/apps.py b/fir_ser/api/views/apps.py index 5b26e54..170bc47 100644 --- a/fir_ser/api/views/apps.py +++ b/fir_ser/api/views/apps.py @@ -182,12 +182,15 @@ class AppInfoView(APIView): apps_obj = Apps.objects.filter(user_id=request.user, app_id=app_id).first() logger.info("app_id:%s update old data:%s" % (app_id, apps_obj.__dict__)) apps_obj.description = data.get("description", apps_obj.description) - del_cache_response_by_short(apps_obj.app_id) apps_obj.short = data.get("short", apps_obj.short) apps_obj.name = data.get("name", apps_obj.name) apps_obj.password = data.get("password", apps_obj.password) apps_obj.isshow = data.get("isshow", apps_obj.isshow) - apps_obj.wxeasytype = data.get("wxeasytype", apps_obj.wxeasytype) + if request.user.domain_name and len(request.user.domain_name) > 3: + apps_obj.wxeasytype = data.get("wxeasytype", apps_obj.wxeasytype) + else: + apps_obj.wxeasytype = 1 + apps_obj.wxredirect = data.get("wxredirect", apps_obj.wxredirect) if apps_obj.type == 1: # 为啥注释掉,就是该udid已经在该平台使用了,虽然已经没有余额,但是其他应用也是可以超级签名的 @@ -206,6 +209,7 @@ class AppInfoView(APIView): apps_obj.issupersign = data.get("issupersign", apps_obj.issupersign) logger.info("app_id:%s update new data:%s" % (app_id, apps_obj.__dict__)) apps_obj.save() + del_cache_response_by_short(apps_obj.app_id) except Exception as e: logger.error("app_id:%s update Exception:%s" % (app_id, e)) res.code = 1005 @@ -213,60 +217,6 @@ class AppInfoView(APIView): return Response(res.dict) - # def post(self, request, app_id): - # res = BaseResponse() - # - # # 获取多个file - # files = request.FILES.getlist('file', None) - # for file_obj in files: - # # 将文件缓存到本地后上传 - # try: - # app_type = file_obj.name.split(".")[-1] - # if app_type in ['png', 'jpeg', 'jpg']: - # # 上传图片 - # pass - # else: - # raise - # except Exception as e: - # res.code = 1003 - # res.msg = "错误的类型" - # return Response(res.dict) - # - # if app_id: - # apps_obj = Apps.objects.filter(user_id=request.user, app_id=app_id).first() - # if apps_obj: - # release_obj = AppReleaseInfo.objects.filter(app_id=apps_obj, is_master=True).first() - # if release_obj: - # - # random_file_name = make_from_user_uuid(request.user) - # old_file_name = os.path.basename(release_obj.icon_url) - # local_file = os.path.join(settings.MEDIA_ROOT, "icons", - # random_file_name + "." + old_file_name.split(".")[1]) - # # 读取传入的文件 - # try: - # destination = open(local_file, 'wb+') - # for chunk in file_obj.chunks(): - # # 写入本地文件 - # destination.write(chunk) - # destination.close() - # except Exception as e: - # res.code = 1003 - # res.msg = "数据写入失败" - # return Response(res.dict) - # release_obj.icon_url = release_obj.icon_url.replace(old_file_name.split(".")[0], - # random_file_name) - # release_obj.save() - # del_cache_response_by_short(apps_obj.short, apps_obj.app_id) - # - # storage = Storage(request.user) - # storage.delete_file(old_file_name) - # - # else: - # res.code = 1003 - # else: - # res.code = 1003 - # return Response(res.dict) - class AppReleaseinfoView(APIView): authentication_classes = [ExpiringTokenAuthentication, ] diff --git a/fir_ser/api/views/download.py b/fir_ser/api/views/download.py index 5c5692c..3dc49bd 100644 --- a/fir_ser/api/views/download.py +++ b/fir_ser/api/views/download.py @@ -10,7 +10,7 @@ from fir_ser import settings from api.utils.TokenManager import DownloadToken from api.utils.app.randomstrings import make_random_uuid from api.utils.app.apputils import make_resigned -from api.utils.app.supersignutils import make_udid_mobileconfig, get_post_udid_url +from api.utils.app.supersignutils import make_udid_mobileconfig, get_post_udid_url, get_redirect_server_domain from api.utils.storage.storage import 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 @@ -120,6 +120,7 @@ class ShortDownloadView(APIView): "storage": Storage(app_obj.user_id)}) res.data = app_serializer.data res.udid = udid + res.domain_name = get_redirect_server_domain(request, app_obj.user_id) return Response(res.dict) # key的设置 diff --git a/fir_ser/api/views/login.py b/fir_ser/api/views/login.py index 05cea26..c7ed63c 100644 --- a/fir_ser/api/views/login.py +++ b/fir_ser/api/views/login.py @@ -12,7 +12,7 @@ from api.utils.auth import ExpiringTokenAuthentication from api.utils.response import BaseResponse from django.middleware import csrf from fir_ser.settings import CACHE_KEY_TEMPLATE -from api.utils.storage.caches import login_auth_failed +from api.utils.storage.caches import login_auth_failed, del_cache_storage, set_default_app_wx_easy import logging logger = logging.getLogger(__name__) @@ -106,12 +106,10 @@ class UserInfoView(APIView): data = request.data logger.info("user:%s update old data:%s" % (request.user, request.user.__dict__)) logger.info("user:%s update new data:%s" % (request.user, data)) - request.user.qq = data.get("qq", request.user.qq) - request.user.job = data.get("job", request.user.job) - request.user.first_name = data.get("first_name", request.user.first_name) oldpassword = data.get("oldpassword", None) surepassword = data.get("surepassword", None) + if oldpassword and surepassword: user = auth.authenticate(username=request.user.username, password=oldpassword) if user is not None: @@ -131,6 +129,18 @@ class UserInfoView(APIView): res.code = 1004 res.msg = "老密码校验失败" else: + # 修改个人资料 + domain_name = data.get("domain_name", None) + if domain_name and len(domain_name.strip(' ')) > 3: + request.user.domain_name = domain_name.strip(' ') + set_default_app_wx_easy(request.user) + + if domain_name == '': + request.user.domain_name = None + set_default_app_wx_easy(request.user) + + request.user.job = data.get("job", request.user.job) + request.user.first_name = data.get("first_name", request.user.first_name) sms_token = data.get("sms_token", None) if sms_token: diff --git a/fir_ser/api/views/uploads.py b/fir_ser/api/views/uploads.py index 3019d49..4798fb8 100644 --- a/fir_ser/api/views/uploads.py +++ b/fir_ser/api/views/uploads.py @@ -25,6 +25,11 @@ class AppAnalyseView(APIView): authentication_classes = [ExpiringTokenAuthentication, ] def post(self, request): + ''' + 应用上传前 分析数据,并返回应用上传信息 + :param request: + :return: + ''' res = BaseResponse() # 1.接收 bundelid ,返回随机应用名称和短连接 bundleid = request.data.get("bundleid", None) @@ -68,7 +73,7 @@ class AppAnalyseView(APIView): upload_file_tmp_name("set", png_key, request.user.id) upload_file_tmp_name("set", upload_key, request.user.id) res.data = {"app_uuid": app_uuid, "short": short, - "domain_name": request.user.domain_name, + "domain_name": settings.SERVER_DOMAIN.get("FILE_UPLOAD_DOMAIN", None), "upload_token": upload_token, "upload_key": upload_key, "png_token": png_token, @@ -81,6 +86,11 @@ class AppAnalyseView(APIView): return Response(res.dict) def put(self, request): + ''' + 该方法就是 应用上传完成之后的回调方法,更新或者创建新应用信息 + :param request: + :return: + ''' res = BaseResponse() data = request.data appinfo = { @@ -103,7 +113,6 @@ class AppAnalyseView(APIView): logger.info("user %s create or update app %s data:%s" % (request.user, data.get("bundleid"), data)) if SaveAppInfos(app_new_filename, request.user, appinfo, data.get("bundleid"), png_new_filename, data.get("short"), data.get('filesize')): - pass # 需要将tmp 文件修改为正式文件 storage.rename_file(app_tmp_filename, app_new_filename) storage.rename_file(png_tmp_filename, png_new_filename) @@ -127,6 +136,11 @@ class UploadView(APIView): authentication_classes = [ExpiringTokenAuthentication, ] def get(self, request): + ''' + 该方法 主要是本地上传,通过该方法获取上传的 应用图片或者用户头像 的上传信息 + :param request: + :return: + ''' res = BaseResponse() storage = Storage(request.user) request_upload_key = request.query_params.get("upload_key", None) @@ -155,12 +169,14 @@ class UploadView(APIView): upload_key = make_from_user_uuid(request.user) + '.' + app_type upload_token = storage.get_upload_token(upload_key) storage_type = storage.get_storage_type() - res.data = {"domain_name": request.user.domain_name, - "upload_token": upload_token, - "upload_key": upload_key, - "storage": storage_type, - "app_id": app_id, - "ftype": ftype} + res.data = { + "domain_name": settings.SERVER_DOMAIN.get("FILE_UPLOAD_DOMAIN", None), + "upload_token": upload_token, + "upload_key": upload_key, + "storage": storage_type, + "app_id": app_id, + "ftype": ftype + } else: res.code = 1006 res.msg = '该应用不存在' @@ -169,6 +185,11 @@ class UploadView(APIView): return Response(res.dict) def post(self, request): + ''' + 该方法 主要是本地上传文件接口,负责上传 应用图片,应用文件或者用户头像 + :param request: + :return: + ''' res = BaseResponse() # 获取多个file @@ -252,11 +273,12 @@ class UploadView(APIView): return Response(res.dict) - ''' - 应用图片上传之后 - ''' - def put(self, request): + ''' + 该方法就是 应用图片或者用户头像上传完成之后的回调方法,为了更新上传完成的信息 + :param request: + :return: + ''' res = BaseResponse() certinfo = request.data.get('certinfo', None) if certinfo: diff --git a/fir_ser/fir_ser/settings.py b/fir_ser/fir_ser/settings.py index 1bb9063..57e190f 100644 --- a/fir_ser/fir_ser/settings.py +++ b/fir_ser/fir_ser/settings.py @@ -147,7 +147,6 @@ SUPER_SIGN_ROOT = os.path.join(BASE_DIR, "supersign") AUTH_USER_MODEL = "api.UserInfo" - CACHES = { "default": { "BACKEND": "django_redis.cache.RedisCache", @@ -241,15 +240,15 @@ SERVER_DOMAIN = { 'is_https': True, }, # ios 描述文件和plist文件下载域名,该域名用于后端,一般为api访问域名 'POST_UDID_DOMAIN': 'https://fly.harmonygames.cn', # 超级签名 安装签名时 向该域名 发送udid数据,该域名用于后端,一般为 api 访问域名 - 'REDIRECT_UDID_DOMAIN': 'https://fly.harmonygames.cn', # 超级签名 安装完成之后,跳转域名,该域名为前端web访问域名 + 'REDIRECT_UDID_DOMAIN': 'https://fly.harmonygames.cn', # 超级签名 安装完成之后,跳转域名,该域名为前端web访问域名,如果用户定义了自己的域名,则跳转用户域名 + 'FILE_UPLOAD_DOMAIN': 'https://fly.harmonygames.cn', # 本地文件上传域名,使用本地存储必须配置 } SESSION_ENGINE = "django.contrib.sessions.backends.cache" SESSION_CACHE_ALIAS = "default" -CAPTCHA_TIMEOUT=5 # Minutes -CAPTCHA_LENGTH= 6 # Chars - +CAPTCHA_TIMEOUT = 5 # Minutes +CAPTCHA_LENGTH = 6 # Chars BASE_LOG_DIR = os.path.join(BASE_DIR, "logs") LOGGING = { @@ -302,4 +301,4 @@ LOGGING = { 'propagate': True, }, }, -} \ No newline at end of file +}