优化代码,增加添加oss存储 校验功能

super_signature
nineven 5 years ago
parent b32a12a597
commit c46bbc6f75
  1. 6
      fir_client/babel.config.js
  2. 18
      fir_client/public/index.html
  3. 14
      fir_client/src/components/FirAppInfossecurity.vue
  4. 30
      fir_client/src/components/FirLogin.vue
  5. 3
      fir_client/src/components/FirUserProfileStorage.vue
  6. 10
      fir_client/src/restful/index.js
  7. 1
      fir_ser/api/migrations/0007_auto_20200520_1153.py
  8. 2
      fir_ser/api/utils/app/apputils.py
  9. 2
      fir_ser/api/utils/app/supersignutils.py
  10. 2
      fir_ser/api/utils/serializer.py
  11. 10
      fir_ser/api/utils/storage/aliyunApi.py
  12. 5
      fir_ser/api/utils/storage/localApi.py
  13. 11
      fir_ser/api/utils/storage/qiniuApi.py
  14. 36
      fir_ser/api/utils/storage/storage.py
  15. 9
      fir_ser/api/utils/utils.py
  16. 2
      fir_ser/api/views/download.py
  17. 36
      fir_ser/api/views/storage.py
  18. 2
      fir_ser/api/views/supersign.py

@ -1,5 +1,5 @@
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
]
presets: [
'@vue/cli-plugin-babel/preset'
]
};

@ -1,17 +1,17 @@
<!DOCTYPE html>
<html lang="en">
<head>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title>fly分发平台</title>
</head>
<body>
<noscript>
<strong>We're sorry but fly doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</head>
<body>
<noscript>
<strong>We're sorry but fly doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>

@ -22,7 +22,7 @@
</el-switch>
</el-tooltip>
<el-link :underline="false" style="margin-left: 20px" >设置密码之后用户需要输入密码才可以下载该应用</el-link>
<el-link :underline="false" style="margin-left: 20px">设置密码之后用户需要输入密码才可以下载该应用</el-link>
</el-form-item>
@ -38,7 +38,7 @@
inactive-value="off">
</el-switch>
</el-tooltip>
<el-link :underline="false" style="margin-left: 20px" >默认开启关闭之后用户无法通过短连接访问下载该应用</el-link>
<el-link :underline="false" style="margin-left: 20px">默认开启关闭之后用户无法通过短连接访问下载该应用</el-link>
</el-form-item>
@ -57,11 +57,11 @@
<el-button @click="clean_app" v-if="currentapp.issupersign === 0 && currentapp.count !== 0"
style="margin-left: 20px" size="small" type="info" plain>清理开发者账户脏数据
</el-button>
<el-link v-else :underline="false" style="margin-left: 20px" >超级签名iOS专用需要配置好苹果开发者账户方可开启</el-link>
<el-link v-else :underline="false" style="margin-left: 20px">超级签名iOS专用需要配置好苹果开发者账户方可开启</el-link>
</el-form-item>
<el-form-item label-width="200px" label="微信内访问简易模式">
<el-form-item label-width="200px" label="微信内访问简易模式">
<el-tooltip :content="wxeasytypetip.msg" placement="top">
<el-switch
@ -73,9 +73,9 @@
inactive-value="off">
</el-switch>
</el-tooltip>
<el-link :underline="false" style="margin-left: 20px" >默认开启可以最大限度避免微信内举报封停</el-link>
<el-link :underline="false" style="margin-left: 20px">默认开启可以最大限度避免微信内举报封停</el-link>
</el-form-item>
<el-form-item label-width="200px" label="微信内访问跳转第三方平台">
<el-form-item label-width="200px" label="微信内访问跳转第三方平台">
<el-tooltip :content="wxredirecttip.msg" placement="top">
<el-switch
@ -87,7 +87,7 @@
inactive-value="off">
</el-switch>
</el-tooltip>
<el-link :underline="false" style="margin-left: 20px" >默认开启如果配置第三方平台在微信内访问直接跳转</el-link>
<el-link :underline="false" style="margin-left: 20px">默认开启如果配置第三方平台在微信内访问直接跳转</el-link>
</el-form-item>

@ -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": {}
});
},
},

@ -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('此操作可能会导致程序异常, 是否继续?', '警告', {

@ -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});
});
}
}

@ -4,7 +4,6 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('api', '0006_udidsyncdeveloper'),
]

@ -60,7 +60,7 @@ def make_resigned(bin_url, img_url, bundle_id, app_version, name):
</dict>
</plist>""" % (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

@ -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():

@ -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()

@ -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

@ -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

@ -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

@ -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:

@ -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)

@ -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']

@ -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

@ -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:

Loading…
Cancel
Save