From c46bbc6f7515c133f7d66af6fb73e7117d643d05 Mon Sep 17 00:00:00 2001 From: nineven Date: Mon, 1 Jun 2020 16:55:51 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=BB=A3=E7=A0=81=EF=BC=8C?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=B7=BB=E5=8A=A0oss=E5=AD=98=E5=82=A8=20?= =?UTF-8?q?=E6=A0=A1=E9=AA=8C=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fir_client/babel.config.js | 6 ++-- fir_client/public/index.html | 18 +++++----- .../src/components/FirAppInfossecurity.vue | 14 ++++---- fir_client/src/components/FirLogin.vue | 30 ++++++++-------- .../src/components/FirUserProfileStorage.vue | 3 +- fir_client/src/restful/index.js | 10 +++--- .../api/migrations/0007_auto_20200520_1153.py | 1 - fir_ser/api/utils/app/apputils.py | 2 +- fir_ser/api/utils/app/supersignutils.py | 2 +- fir_ser/api/utils/serializer.py | 2 +- fir_ser/api/utils/storage/aliyunApi.py | 10 ++++++ fir_ser/api/utils/storage/localApi.py | 5 +++ fir_ser/api/utils/storage/qiniuApi.py | 11 +++++- fir_ser/api/utils/storage/storage.py | 36 +++++++++++++------ fir_ser/api/utils/utils.py | 9 ++++- fir_ser/api/views/download.py | 2 +- fir_ser/api/views/storage.py | 36 ++++++++++++++++--- fir_ser/api/views/supersign.py | 2 +- 18 files changed, 136 insertions(+), 63 deletions(-) diff --git a/fir_client/babel.config.js b/fir_client/babel.config.js index 3f453d4..c5dc6a5 100644 --- a/fir_client/babel.config.js +++ b/fir_client/babel.config.js @@ -1,5 +1,5 @@ module.exports = { - presets: [ - '@vue/cli-plugin-babel/preset' - ] + presets: [ + '@vue/cli-plugin-babel/preset' + ] }; diff --git a/fir_client/public/index.html b/fir_client/public/index.html index c979540..12536f8 100644 --- a/fir_client/public/index.html +++ b/fir_client/public/index.html @@ -1,17 +1,17 @@ - + fly分发平台 - - - -
- - + + + +
+ + diff --git a/fir_client/src/components/FirAppInfossecurity.vue b/fir_client/src/components/FirAppInfossecurity.vue index 7daae95..5faa67a 100644 --- a/fir_client/src/components/FirAppInfossecurity.vue +++ b/fir_client/src/components/FirAppInfossecurity.vue @@ -22,7 +22,7 @@ - 设置密码之后,用户需要输入密码才可以下载该应用 + 设置密码之后,用户需要输入密码才可以下载该应用 @@ -38,7 +38,7 @@ inactive-value="off"> - 默认开启,关闭之后用户无法通过短连接访问下载该应用 + 默认开启,关闭之后用户无法通过短连接访问下载该应用 @@ -57,11 +57,11 @@ 清理开发者账户脏数据 - 超级签名,iOS专用,需要配置好苹果开发者账户,方可开启 + 超级签名,iOS专用,需要配置好苹果开发者账户,方可开启 - + - 默认开启,可以最大限度避免微信内举报封停 + 默认开启,可以最大限度避免微信内举报封停 - + - 默认开启,如果配置第三方平台,在微信内访问直接跳转 + 默认开启,如果配置第三方平台,在微信内访问直接跳转 diff --git a/fir_client/src/components/FirLogin.vue b/fir_client/src/components/FirLogin.vue index 4f704f9..25e9916 100644 --- a/fir_client/src/components/FirLogin.vue +++ b/fir_client/src/components/FirLogin.vue @@ -67,9 +67,9 @@ form: { email: '', password: '', - authcode:'' + authcode: '' }, - cptch:{"cptch_image": '', "cptch_key": '',"length":8}, + cptch: {"cptch_image": '', "cptch_key": '', "length": 8}, } }, methods: { @@ -77,7 +77,7 @@ let email = this.form.email; let password = this.form.password; let authcode = this.form.authcode; - if(authcode.length === this.cptch.length){ + if (authcode.length === this.cptch.length) { if (this.isEmail(email) && password.length > 6) { loginFun(data => { if (data.code == 1000) { @@ -86,9 +86,9 @@ type: 'success' }); this.$cookies.remove("auth_token"); - this.$cookies.set("token", data['token'],3600 * 24 * 30); - this.$cookies.set("username", data.userinfo.username,3600 * 24 * 30); - this.$cookies.set("first_name", data.userinfo.first_name,3600 * 24 * 30); + this.$cookies.set("token", data['token'], 3600 * 24 * 30); + this.$cookies.set("username", data.userinfo.username, 3600 * 24 * 30); + this.$cookies.set("first_name", data.userinfo.first_name, 3600 * 24 * 30); this.$store.dispatch("doUserinfo", data.userinfo); set_auth_token(); this.$router.push({name: 'FirApps'}) @@ -100,12 +100,12 @@ this.get_auth_code(); } }, { - "methods":"POST", - "data":{ + "methods": "POST", + "data": { "username": email, "password": password, - "authcode":authcode, - "cptch_key":this.cptch.cptch_key + "authcode": authcode, + "cptch_key": this.cptch.cptch_key } }); @@ -116,7 +116,7 @@ type: 'warning' }); } - }else { + } else { this.$message({ message: '验证码有误', type: 'warning' @@ -132,10 +132,10 @@ } return false; }, - get_auth_code(){ + get_auth_code() { loginFun(data => { if (data.code == 1000) { - this.cptch=data.data; + this.cptch = data.data; } else { this.$message({ message: data.msg, @@ -143,8 +143,8 @@ }); } }, { - "methods":"GET", - "data":{} + "methods": "GET", + "data": {} }); }, }, diff --git a/fir_client/src/components/FirUserProfileStorage.vue b/fir_client/src/components/FirUserProfileStorage.vue index 7b77d40..c90d6d9 100644 --- a/fir_client/src/components/FirUserProfileStorage.vue +++ b/fir_client/src/components/FirUserProfileStorage.vue @@ -273,9 +273,10 @@ } this.getstorageinfoFun(); + } else { + this.$message.error('操作失败,' + data.msg); } }, {"methods": methods, 'data': this.editstorageinfo}); - this.getstorageinfoFun(); }, del_storage_info(sinfo) { this.$confirm('此操作可能会导致程序异常, 是否继续?', '警告', { diff --git a/fir_client/src/restful/index.js b/fir_client/src/restful/index.js index 6f92c20..6b006c2 100644 --- a/fir_client/src/restful/index.js +++ b/fir_client/src/restful/index.js @@ -30,7 +30,7 @@ export function set_auth_token() { } else { let token = VueCookies.get('token'); let username = VueCookies.get('username'); - VueCookies.set("auth_token", Base64.encode(token + ':' + username),3600 * 24 * 30); + VueCookies.set("auth_token", Base64.encode(token + ':' + username), 3600 * 24 * 30); } } // 更改加载的样式 @@ -111,7 +111,7 @@ function getData(methods = true, url, params = {}, callBack, load, isCode = fals }) .catch(function (error) { ErrorMsg(error); - callBack({"code":-1}); + callBack({"code": -1}); }); } else if (methods === "PUT") { @@ -126,7 +126,7 @@ function getData(methods = true, url, params = {}, callBack, load, isCode = fals }) .catch(function (error) { ErrorMsg(error); - callBack({"code":-1}); + callBack({"code": -1}); }); } else if (methods === 'POST') { @@ -142,7 +142,7 @@ function getData(methods = true, url, params = {}, callBack, load, isCode = fals }) .catch(function (error) { ErrorMsg(error); - callBack({"code":-1}); + callBack({"code": -1}); }); } else { Axios @@ -152,7 +152,7 @@ function getData(methods = true, url, params = {}, callBack, load, isCode = fals }) .catch(function (error) { ErrorMsg(error); - callBack({"code":-1}); + callBack({"code": -1}); }); } } diff --git a/fir_ser/api/migrations/0007_auto_20200520_1153.py b/fir_ser/api/migrations/0007_auto_20200520_1153.py index 249c3de..7d49437 100644 --- a/fir_ser/api/migrations/0007_auto_20200520_1153.py +++ b/fir_ser/api/migrations/0007_auto_20200520_1153.py @@ -4,7 +4,6 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ ('api', '0006_udidsyncdeveloper'), ] diff --git a/fir_ser/api/utils/app/apputils.py b/fir_ser/api/utils/app/apputils.py index 5b52bce..2e77cdc 100644 --- a/fir_ser/api/utils/app/apputils.py +++ b/fir_ser/api/utils/app/apputils.py @@ -60,7 +60,7 @@ def make_resigned(bin_url, img_url, bundle_id, app_version, name): """ % (bin_url, img_url, img_url, bundle_id, app_version, name) logger.info("make_resigned bin_url %s ,img_url %s, img_url %s, bundle_id %s, app_version %s, name %s" % ( - bin_url, img_url, img_url, bundle_id, app_version, name)) + bin_url, img_url, img_url, bundle_id, app_version, name)) return ios_plist_tem diff --git a/fir_ser/api/utils/app/supersignutils.py b/fir_ser/api/utils/app/supersignutils.py index 9b810ea..b6f5bd7 100644 --- a/fir_ser/api/utils/app/supersignutils.py +++ b/fir_ser/api/utils/app/supersignutils.py @@ -203,7 +203,7 @@ class IosUtils(object): developer_obj = self.developer_obj developer_obj.use_number = developer_obj.use_number + 1 logger.info("developer %s use_number+1 now %s udid %s app_id %s" % ( - developer_obj, developer_obj.use_number, self.udid_info.get('udid'), self.app_obj)) + developer_obj, developer_obj.use_number, self.udid_info.get('udid'), self.app_obj)) developer_obj.save() if not appsupersign_obj.filter(app_id=self.app_obj, user_id=self.user_obj).first(): diff --git a/fir_ser/api/utils/serializer.py b/fir_ser/api/utils/serializer.py index 9443f14..3080bbe 100644 --- a/fir_ser/api/utils/serializer.py +++ b/fir_ser/api/utils/serializer.py @@ -88,7 +88,7 @@ class AppsShortSerializer(serializers.ModelSerializer): class Meta: model = models.Apps fields = ["app_id", "name", "short", "has_combo", "isshow", "description", "need_password", 'master_release', - 'type', 'issupersign','wxeasytype','wxredirect'] + 'type', 'issupersign', 'wxeasytype', 'wxredirect'] need_password = serializers.SerializerMethodField() diff --git a/fir_ser/api/utils/storage/aliyunApi.py b/fir_ser/api/utils/storage/aliyunApi.py index b225fd1..365323d 100644 --- a/fir_ser/api/utils/storage/aliyunApi.py +++ b/fir_ser/api/utils/storage/aliyunApi.py @@ -124,3 +124,13 @@ class AliYunOss(object): def rename_file(self, oldfilename, newfilename): self.bucket.copy_object(self.bucket_name, oldfilename, newfilename) return self.del_file(oldfilename) + + def upload_file(self, local_file_full_path): + if os.path.isfile(local_file_full_path): + with open(local_file_full_path, 'rb') as fileobj: + # Seek方法用于指定从第1000个字节位置开始读写。上传时会从您指定的第1000个字节位置开始上传,直到文件结束。 + fileobj.seek(1000, os.SEEK_SET) + # Tell方法用于返回当前位置。 + # current = fileobj.tell() + self.bucket.put_object(os.path.basename(local_file_full_path), fileobj) + return True diff --git a/fir_ser/api/utils/storage/localApi.py b/fir_ser/api/utils/storage/localApi.py index 60cf3ea..772f5ce 100644 --- a/fir_ser/api/utils/storage/localApi.py +++ b/fir_ser/api/utils/storage/localApi.py @@ -54,3 +54,8 @@ class LocalStorage(object): except Exception as e: logger.error("rename_file file %s to %s failed Exception %s" % (oldfilename, newfilename, e)) return False + + def upload_file(self, local_file_full_path): + if os.path.isfile(local_file_full_path): + return True + return False diff --git a/fir_ser/api/utils/storage/qiniuApi.py b/fir_ser/api/utils/storage/qiniuApi.py index 77a8fdf..c6f6c6e 100644 --- a/fir_ser/api/utils/storage/qiniuApi.py +++ b/fir_ser/api/utils/storage/qiniuApi.py @@ -6,8 +6,9 @@ ''' 主要是调用七牛云存储,处理七牛云存储的逻辑 ''' -from qiniu import Auth +from qiniu import Auth, put_file, etag from qiniu import BucketManager +import os class QiNiuOss(object): @@ -54,3 +55,11 @@ class QiNiuOss(object): bucket = BucketManager(self.qiniu_obj) ret, info = bucket.move(self.bucket_name, oldfilename, self.bucket_name, newfilename) return ret + + def upload_file(self, local_file_full_path): + if os.path.isfile(local_file_full_path): + filename = os.path.basename(local_file_full_path) + token = self.get_upload_token(filename) + ret, info = put_file(token, filename, local_file_full_path) + if ret['key'] == filename and ret['hash'] == etag(local_file_full_path): + return True diff --git a/fir_ser/api/utils/storage/storage.py b/fir_ser/api/utils/storage/storage.py index 53407f7..0daba5d 100644 --- a/fir_ser/api/utils/storage/storage.py +++ b/fir_ser/api/utils/storage/storage.py @@ -17,9 +17,9 @@ logger = logging.getLogger(__file__) class Storage(object): - def __init__(self, user): + def __init__(self, user, storage_obj=None): try: - self.storage = self.get_storage(user) + self.storage = self.get_storage(user, storage_obj) except Exception as e: logger.error("get %s storage failed Exception:%s" % (user, e)) self.storage = None @@ -48,21 +48,37 @@ class Storage(object): filename = filename + '.apk' else: filename = filename + '.ipa' - return self.storage.del_file(filename) + try: + return self.storage.del_file(filename) + except Exception as e: + logger.error("delete file %s failed Exception %s" % (filename, e)) def rename_file(self, oldfilename, newfilename): if self.storage: - return self.storage.rename_file(oldfilename, newfilename) + try: + return self.storage.rename_file(oldfilename, newfilename) + except Exception as e: + logger.error("rename %s to %s failed Exception %s" % (oldfilename, newfilename, e)) - def get_storage(self, user): - self.storage_obj = user.storage + def upload_file(self, local_file_full_path): + if self.storage: + try: + return self.storage.upload_file(local_file_full_path) + except Exception as e: + logger.error("oss upload %s failed Exception %s" % (local_file_full_path, e)) + + def get_storage(self, user, storage_obj): + if storage_obj: + self.storage_obj = storage_obj + else: + self.storage_obj = user.storage if self.storage_obj: auth = self.get_storage_auth(self.storage_obj) storage_key = "_".join([CACHE_KEY_TEMPLATE.get('user_storage_key'), user.uid, base64.b64encode(json.dumps(auth).encode("utf-8")).decode("utf-8")[0:64]]) storage_type = self.storage_obj.storage_type new_storage_obj = cache.get(storage_key) - if new_storage_obj: + if new_storage_obj and not storage_obj: return new_storage_obj else: if storage_type == 1: @@ -76,12 +92,12 @@ class Storage(object): cache.set(storage_key, new_storage_obj, 600) return new_storage_obj else: - return self.get_default_storage(user) + return self.get_default_storage(user, storage_obj) - def get_default_storage(self, user): + def get_default_storage(self, user, storage_obj): admin_obj = UserInfo.objects.filter(is_superuser=True).order_by('pk').first() if admin_obj and admin_obj.storage: - return self.get_storage(admin_obj) + return self.get_storage(admin_obj, storage_obj) else: storage_lists = THIRD_PART_CONFIG.get('storage') for storage in storage_lists: diff --git a/fir_ser/api/utils/utils.py b/fir_ser/api/utils/utils.py index b34d4db..2a27814 100644 --- a/fir_ser/api/utils/utils.py +++ b/fir_ser/api/utils/utils.py @@ -4,11 +4,12 @@ # author: liuyu # date: 2020/5/7 import os -from fir_ser.settings import SUPER_SIGN_ROOT, SERVER_DOMAIN, CAPTCHA_LENGTH +from fir_ser.settings import SUPER_SIGN_ROOT, SERVER_DOMAIN, CAPTCHA_LENGTH, MEDIA_ROOT from api.models import APPSuperSignUsedInfo, APPToDeveloper, \ UDIDsyncDeveloper from api.utils.app.randomstrings import make_app_uuid from api.utils.storage.localApi import LocalStorage +from api.utils.storage.storage import Storage from django.db.models import Sum from captcha.models import CaptchaStore from captcha.helpers import captcha_image_url @@ -104,3 +105,9 @@ def valid_captcha(cptch_key, code, username): if cptch_key and code and code.strip(" ").lower() == challenge.get("challenge").lower(): return True return False + + +def upload_oss_default_head_img(user_obj, storage_obj): + head_img_full_path = os.path.join(MEDIA_ROOT, "head_img.jpeg") + storage_obj = Storage(user_obj, storage_obj) + return storage_obj.upload_file(head_img_full_path) diff --git a/fir_ser/api/views/download.py b/fir_ser/api/views/download.py index 710cfe2..5c5692c 100644 --- a/fir_ser/api/views/download.py +++ b/fir_ser/api/views/download.py @@ -175,7 +175,7 @@ class InstallView(APIView): res.data = {"download_url": download_url} if download_url != "" and "mobileconifg" not in download_url: set_app_download_by_cache(app_id) - if request.META.get('HTTP_X_FORWARDED_FOR',None): + if request.META.get('HTTP_X_FORWARDED_FOR', None): ip = request.META['HTTP_X_FORWARDED_FOR'] else: ip = request.META['REMOTE_ADDR'] diff --git a/fir_ser/api/views/storage.py b/fir_ser/api/views/storage.py index 5971d15..2cf80f7 100644 --- a/fir_ser/api/views/storage.py +++ b/fir_ser/api/views/storage.py @@ -11,6 +11,7 @@ from rest_framework.response import Response import json from api.utils.storage.caches import del_cache_storage from api.models import AppStorage, UserInfo +from api.utils.utils import upload_oss_default_head_img from api.utils.serializer import StorageSerializer import logging @@ -65,9 +66,19 @@ class StorageView(APIView): serializer = StorageSerializer(data=data, context={'user_obj': request.user}) if serializer.is_valid(): - serializer.save() - res.msg = serializer.validated_data - logger.info("user %s add new storage success" % (request.user)) + storage_obj = serializer.save() + if storage_obj: + if upload_oss_default_head_img(request.user, storage_obj): + res.msg = serializer.validated_data + logger.info("user %s add new storage success" % (request.user)) + else: + logger.error("user %s add new storage failed" % (request.user)) + res.msg = "文件上传校验失败,请检查参数是否正确" + res.code = 1005 + else: + logger.info("user %s add new storage failed" % (request.user)) + res.msg = serializer.errors + res.code = 1005 else: logger.info("user %s add new storage failed" % (request.user)) res.msg = serializer.errors @@ -101,12 +112,27 @@ class StorageView(APIView): storage_id = data.get("id", None) if storage_id: + if storage_id == request.user.storage.id: + res.msg = '存储正在使用中,无法修改' + res.code = 1007 + return Response(res.dict) storage_obj = AppStorage.objects.filter(id=storage_id, user_id=request.user).first() serializer = StorageSerializer(instance=storage_obj, data=data, context={'user_obj': request.user}, partial=True) if serializer.is_valid(): - serializer.save() - res.msg = serializer.validated_data + storage_obj = serializer.save() + if storage_obj: + if upload_oss_default_head_img(request.user, storage_obj): + res.msg = serializer.validated_data + logger.info("user %s add new storage success" % (request.user)) + else: + logger.error("user %s add new storage failed" % (request.user)) + res.msg = "文件上传校验失败,请检查参数是否正确" + res.code = 1005 + else: + logger.info("user %s add new storage failed" % (request.user)) + res.msg = serializer.errors + res.code = 1005 else: res.msg = serializer.errors res.code = 1005 diff --git a/fir_ser/api/views/supersign.py b/fir_ser/api/views/supersign.py index 01b6029..8b23785 100644 --- a/fir_ser/api/views/supersign.py +++ b/fir_ser/api/views/supersign.py @@ -110,7 +110,7 @@ class DeveloperView(APIView): else: logger.info("user %s iosdeveloper %s update input data %s" % (request.user, developer_obj, data)) logger.info("user %s iosdeveloper %s update old data %s" % ( - request.user, developer_obj, developer_obj.__dict__)) + request.user, developer_obj, developer_obj.__dict__)) try: usable_number = int(data.get("usable_number", developer_obj.usable_number)) if usable_number >= 0 and usable_number <= 100: