diff --git a/fir_client/src/components/FirApps.vue b/fir_client/src/components/FirApps.vue index 7e1cb7c..af79605 100644 --- a/fir_client/src/components/FirApps.vue +++ b/fir_client/src/components/FirApps.vue @@ -397,25 +397,29 @@ firstloadflag:true, currentfile:null, uploadprocess:0, - uploadsuccess:0 + uploadsuccess:0, + loadingobj:null } }, methods: { + updateappinfo(file){ + this.uploadsuccess +=1; + if(this.uploadsuccess === 2){ + this.$message.success(file.name + '上传成功'); + analyseApps(data => { + if (data.code === 1000) { + let app_uuid = this.analyseappinfo.app_uuid; + this.closeUpload(); + this.$router.push({name: 'FirAppInfostimeline', params: {id: app_uuid}}); + } + },{'methods':'PUT','data':this.analyseappinfo}); + } + }, uploadtostorage(file,certinfo){ if(this.analyseappinfo.storage === 1){ // eslint-disable-next-line no-unused-vars,no-unreachable uploadqiniuoss(file,certinfo,this,res=>{ - this.uploadsuccess +=1; - if(this.uploadsuccess === 2){ - this.$message.success(file.name + '上传成功'); - analyseApps(data => { - if (data.code === 1000) { - let app_uuid = this.analyseappinfo.app_uuid; - this.closeUpload(); - this.$router.push({name: 'FirAppInfostimeline', params: {id: app_uuid}}); - } - },{'methods':'PUT','data':this.analyseappinfo}); - } + this.updateappinfo(file) },process=>{ if(this.uploadsuccess === 1) { this.uploadprocess = process; @@ -424,46 +428,27 @@ }else if(this.analyseappinfo.storage === 2){ // eslint-disable-next-line no-unused-vars uploadaliyunoss(file,certinfo,this,res=>{ - this.uploadsuccess +=1; - if(this.uploadsuccess === 2){ - this.$message.success(file.name + '上传成功'); - analyseApps(data => { - if (data.code === 1000) { - let app_uuid = this.analyseappinfo.app_uuid; - this.closeUpload(); - this.$router.push({name: 'FirAppInfostimeline', params: {id: app_uuid}}); - } - },{'methods':'PUT','data':this.analyseappinfo}); - } + this.updateappinfo(file) + },process=>{ if(this.uploadsuccess === 1) { this.uploadprocess = process; } }); - }else { //本地 certinfo.upload_url = getuploadurl(); + certinfo.ftype = 'app'; + certinfo.app_id = this.analyseappinfo.app_uuid; // eslint-disable-next-line no-unused-vars,no-unreachable uploadlocalstorage(file,certinfo,this,res=>{ - this.uploadsuccess +=1; - if(this.uploadsuccess === 2){ - this.$message.success(file.name + '上传成功'); - analyseApps(data => { - if (data.code === 1000) { - let app_uuid = this.analyseappinfo.app_uuid; - this.closeUpload(); - this.$router.push({name: 'FirAppInfostimeline', params: {id: app_uuid}}); - } - },{'methods':'PUT','data':this.analyseappinfo}); - } + this.updateappinfo(file) },process=>{ if(this.uploadsuccess === 1) { this.uploadprocess = process; } }) } - }, getuploadtoken(loading){ analyseApps(data =>{ @@ -573,7 +558,7 @@ }, getappsFun(parms) { - const loading = this.$loading({ + this.loadingobj = this.$loading({ lock: true, text: '加载中', spinner: 'el-icon-loading', @@ -581,7 +566,7 @@ }); getapps(data => { if (data.code === 1000) { - loading.close(); + this.loadingobj.close(); if(this.firstloadflag){ window.addEventListener('scroll',this.auto_load); this.firstloadflag = false @@ -608,12 +593,13 @@ // this.$store.dispatch('doucurrentapp', {'firapps':1}); } else { + this.loadingobj.close(); this.$router.push({name: 'FirLogin'}); } }, parms); }, - beforeAvatarUpload(file){ + beforeAvatarUpload(file){ const loading = this.$loading({ lock: true, text: '应用解析中', @@ -636,7 +622,6 @@ }); return false; }, - delApp() { this.willDeleteApp = false; deleteapp(data => { @@ -727,6 +712,7 @@ }, destroyed(){ window.removeEventListener('scroll', this.auto_load, false); + this.loadingobj.close(); }, watch: { diff --git a/fir_client/src/utils/index.js b/fir_client/src/utils/index.js index 8db575c..05d03b8 100644 --- a/fir_client/src/utils/index.js +++ b/fir_client/src/utils/index.js @@ -149,7 +149,7 @@ export function uploadaliyunoss(file,certinfo,app,successcallback,processcallbac }; const options = { progress, - partSize: 1000 * 1024, + partSize: 1024 * 1024 / 4, // meta: { // year: 2017, // people: 'test', diff --git a/fir_ser/api/migrations/0015_auto_20200326_1454.py b/fir_ser/api/migrations/0015_auto_20200326_1454.py new file mode 100644 index 0000000..ee94f36 --- /dev/null +++ b/fir_ser/api/migrations/0015_auto_20200326_1454.py @@ -0,0 +1,28 @@ +# Generated by Django 3.0.3 on 2020-03-26 06:54 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0014_userinfo_storage'), + ] + + operations = [ + migrations.AddField( + model_name='userinfo', + name='history_release_limit', + field=models.IntegerField(blank=True, default=10, null=True, verbose_name='app 历史记录版本'), + ), + migrations.AlterField( + model_name='userinfo', + name='all_download_times', + field=models.BigIntegerField(default=0, verbose_name='总共下载次数'), + ), + migrations.AlterField( + model_name='userinfo', + name='head_img', + field=models.CharField(default='head_img.jpeg', max_length=256, verbose_name='个人头像'), + ), + ] diff --git a/fir_ser/api/models.py b/fir_ser/api/models.py index b84c79f..713a0b7 100644 --- a/fir_ser/api/models.py +++ b/fir_ser/api/models.py @@ -22,33 +22,26 @@ class UserInfo(AbstractUser): uid = models.CharField(max_length=64, unique=True) # user_id,唯一标识 mobile = models.BigIntegerField(verbose_name="手机", unique=True, help_text="用于手机验证码登录", null=True) qq = models.BigIntegerField(verbose_name="QQ", blank=True, null=True, db_index=True) - is_active = models.BooleanField(default=True, verbose_name="账户状态") + is_active = models.BooleanField(default=True, verbose_name="账户状态,默认启用") job = models.TextField("职位", max_length=128, blank=True, null=True) company = models.CharField("公司", max_length=128, blank=True, null=True) gender_choices = ((0, '保密'), (1, '男'), (2, '女')) gender = models.SmallIntegerField(choices=gender_choices, default=0, verbose_name="性别") - # password = models.CharField('password', max_length=128, - # help_text=mark_safe('''重置密码''')) - head_img = models.CharField(max_length=256, default='head_img.jpeg', verbose_name="个人头像") role_choices = ((0, '普通会员'), (1, 'VIP'), (2, 'SVIP'), (3, '管理员')) role = models.SmallIntegerField(choices=role_choices, default=0, verbose_name="角色") + memo = models.TextField('备注', blank=True, null=True, default=None, ) date_joined = models.DateTimeField(auto_now_add=True, verbose_name="注册时间") download_times = models.IntegerField(default=100, verbose_name="下载次数") - all_download_times = models.IntegerField(default=0, verbose_name="总共下载次数") + all_download_times = models.BigIntegerField(default=0, verbose_name="总共下载次数") 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) - - # is_staff = models.BooleanField(verbose_name='staff status', default=False, help_text='决定着用户是否可登录管理后台') - # weixin = models.CharField(max_length=128, blank=True, null=True, db_index=True, verbose_name="微信") - # signature = models.CharField('个人签名', blank=True, null=True, max_length=255) - # openid = models.CharField(max_length=128, blank=True, null=True) - # alipay_card = models.CharField(max_length=128, blank=True, null=True, verbose_name="支付宝账户") + on_delete=models.SET_NULL, verbose_name="存储",null=True,blank=True) class Meta: verbose_name = '账户信息' @@ -155,7 +148,9 @@ class AppStorage(models.Model): secret_key =models.CharField(max_length=128,blank=True, null=True, verbose_name="存储访问secret") bucket_name=models.CharField(max_length=128,blank=True, null=True, verbose_name="存储空间bucket_name") additionalparameters = models.TextField(max_length=256,blank=True, null=True,verbose_name="额外参数", - help_text='阿里云:{"sts_role_arn":"arn信息","endpoint":""} 七牛云:{"domain_name":""}') + help_text='阿里云:{"sts_role_arn":"arn信息","endpoint":""} ' + ' 七牛云:{"domain_name":""} ' + '本地存储:{"domain_name":""}') created_time = models.DateTimeField(auto_now_add=True, verbose_name="创建时间") description = models.TextField('备注', blank=True, null=True, default=None, ) @@ -164,4 +159,4 @@ class AppStorage(models.Model): verbose_name_plural = "存储配置" def __str__(self): - return "%s %s" % (self.name,self.user_id.get_username()) + return "%s %s" % (self.user_id.get_username(),self.name) diff --git a/fir_ser/api/utils/app/apputils.py b/fir_ser/api/utils/app/apputils.py index 1775041..216d790 100644 --- a/fir_ser/api/utils/app/apputils.py +++ b/fir_ser/api/utils/app/apputils.py @@ -134,6 +134,7 @@ def SaveAppInfos(app_file_name,user_obj,appinfo,bundle_id,app_img,short,size): app_uuid = make_app_uuid(user_obj,bundle_id+app_file_name.split(".")[1]) ##判断是否存在该app appmobj = Apps.objects.filter(app_id=app_uuid, user_id=user_obj).first() + storage = Storage(user_obj) if not appmobj: appdata = { "app_id": app_uuid, @@ -148,7 +149,6 @@ def SaveAppInfos(app_file_name,user_obj,appinfo,bundle_id,app_img,short,size): appmobj = Apps.objects.create(**appdata) except Exception as e: print(e) - storage = Storage(user_obj) storage.delete_file(app_file_name) storage.delete_file(app_img) return @@ -178,3 +178,22 @@ def SaveAppInfos(app_file_name,user_obj,appinfo,bundle_id,app_img,short,size): } AppReleaseInfo.objects.create(**release_data) + try: + history_release_limit = int(user_obj.history_release_limit) + except Exception as e: + print(e) + return + + if history_release_limit == 0: + pass + else: + release_queryset = AppReleaseInfo.objects.filter(app_id=appmobj).order_by("-created_time") + if release_queryset.count() > history_release_limit: + flag = 0 + for release_obj in release_queryset: + flag +=1 + if flag > history_release_limit: + storage.delete_file(release_obj.release_id,appmobj.type) + storage.delete_file(release_obj.icon_url) + release_obj.delete() + diff --git a/fir_ser/api/utils/auth.py b/fir_ser/api/utils/auth.py index 107bb29..3f60064 100644 --- a/fir_ser/api/utils/auth.py +++ b/fir_ser/api/utils/auth.py @@ -63,4 +63,8 @@ class ExpiringTokenAuthentication(BaseAuthentication): raise AuthenticationFailed({"code": 1001, "error": "无效的token"}) if user_name != token_obj.user.username: raise AuthenticationFailed({"code": 1001, "error": "token校验失败"}) - return token_obj.user, token_obj + if token_obj.user.is_active: + return token_obj.user, token_obj + else: + raise AuthenticationFailed({"code": 1001, "error": "用户被禁用"}) + diff --git a/fir_ser/api/utils/storage/storage.py b/fir_ser/api/utils/storage/storage.py index c04814a..8cd316b 100644 --- a/fir_ser/api/utils/storage/storage.py +++ b/fir_ser/api/utils/storage/storage.py @@ -9,17 +9,18 @@ from .aliyunApi import AliYunOss from .qiniuApi import QiNiuOss from .localApi import LocalStorage import json +from fir_ser import settings class Storage(object): def __init__(self, user): self.storage = self.get_storage(user) - def get_upload_token(self, filename, expires=1800): + def get_upload_token(self, filename, expires=600): if self.storage: return self.storage.get_upload_token(filename, expires) - def get_download_url(self, filename, expires=1800,ftype=None): + def get_download_url(self, filename, expires=600,ftype=None): if self.storage: return self.storage.get_download_url(filename, expires,ftype) @@ -33,10 +34,10 @@ class Storage(object): return self.storage.del_file(filename) def get_storage(self, user): - storage_obj = user.storage - if storage_obj: - auth = self.get_storage_auth(storage_obj) - storage_type = storage_obj.storage_type + self.storage_obj = user.storage + if self.storage_obj: + auth = self.get_storage_auth(self.storage_obj) + storage_type = self.storage_obj.storage_type if storage_type == 1: new_storage_obj = QiNiuOss(**auth) elif storage_type == 2: @@ -44,8 +45,35 @@ class Storage(object): else: new_storage_obj = LocalStorage(**auth) return new_storage_obj + else: + return self.get_default_storage() + + def get_default_storage(self): + admin_storage = UserInfo.objects.first().storage + if admin_storage: + return self.get_storage(UserInfo) + else: + storage_lists = settings.THIRD_PART_CONFIG.get('storage') + for storage in storage_lists: + if storage.get("active",None): + storage_type= storage.get('type',None) + auth = storage.get('auth',{}) + if storage_type == 1: + new_storage_obj = QiNiuOss(**auth) + elif storage_type == 2: + new_storage_obj = AliYunOss(**auth) + else: + new_storage_obj = LocalStorage(**auth) + return new_storage_obj return None + + + + def get_storage_type(self): + if self.storage_obj: + return self.storage_obj.storage_type + def get_storage_auth(self, storage_obj): auth_dict = { 'access_key': storage_obj.access_key, diff --git a/fir_ser/api/views/download.py b/fir_ser/api/views/download.py index 17b37bd..e1c08ba 100644 --- a/fir_ser/api/views/download.py +++ b/fir_ser/api/views/download.py @@ -104,8 +104,12 @@ class InstallView(APIView): if dtoken.verify_token(downtoken,release_id): app_obj = Apps.objects.filter(app_id=app_id,short=short).first() if app_obj: + app_obj.count_hits = app_obj.count_hits+1 app_obj.save() + app_obj.user_id.all_download_times = app_obj.user_id.all_download_times+1 + app_obj.user_id.save() + release_obj = AppReleaseInfo.objects.filter(app_id=app_obj,release_id=release_id).first() if release_obj: storage = Storage(app_obj.user_id) diff --git a/fir_ser/api/views/login.py b/fir_ser/api/views/login.py index 3065cba..0b7865a 100644 --- a/fir_ser/api/views/login.py +++ b/fir_ser/api/views/login.py @@ -36,23 +36,27 @@ class LoginView(APIView): password = receive.get("password") user = auth.authenticate(username=username, password=password) if user is not None: - # update the token - key = self.generate_key() - now = datetime.datetime.now() - Token.objects.update_or_create(user=user, defaults={"access_token": key, "created": now}) - user_info = UserInfo.objects.get(pk=user.pk) - - serializer = UserInfoSerializer(user_info,) - data = serializer.data - - response.msg = "验证成功!" - response.userinfo = data - response.token = key - + if user.is_active: + + # update the token + key = self.generate_key() + now = datetime.datetime.now() + Token.objects.update_or_create(user=user, defaults={"access_token": key, "created": now}) + user_info = UserInfo.objects.get(pk=user.pk) + + serializer = UserInfoSerializer(user_info,) + data = serializer.data + + response.msg = "验证成功!" + response.userinfo = data + response.token = key + else: + response.msg = "用户被禁用" + response.code = 1002 else: try: UserInfo.objects.get(username=username) - response.msg = "密码错误!" + response.msg = "密码错误或者!" response.code = 1002 except UserInfo.DoesNotExist: response.msg = "用户不存在!" diff --git a/fir_ser/api/views/uploads.py b/fir_ser/api/views/uploads.py index 3804093..dd08bf2 100644 --- a/fir_ser/api/views/uploads.py +++ b/fir_ser/api/views/uploads.py @@ -6,7 +6,7 @@ from api.utils.app.apputils import get_random_short,SaveAppInfos from api.utils.storage.storage import Storage -from api.models import Apps,AppReleaseInfo +from api.models import Apps,AppReleaseInfo,UserInfo from api.utils.app.randomstrings import make_app_uuid from rest_framework.views import APIView from api.utils.response import BaseResponse @@ -45,8 +45,8 @@ class AppAnalyseView(APIView): upload_key = release_id+'.apk' png_key = png_id+'.png' storage = Storage(request.user) + storage_type =storage.get_storage_type() - storage_type = request.user.storage.storage_type if storage_type == 1: upload_token = storage.get_upload_token(upload_key) png_token = storage.get_upload_token(png_key) @@ -123,7 +123,7 @@ class UploadView(APIView): else: upload_key = make_from_user_uuid(request.user)+'.'+app_type upload_token = storage.get_upload_token(upload_key) - storage_type = request.user.storage.storage_type + storage_type = storage.get_storage_type() res.data = {"domain_name": request.user.domain_name, "upload_token": upload_token, "upload_key": upload_key, @@ -164,11 +164,12 @@ class UploadView(APIView): app_id = certinfo.get("app_id", None) ftype = certinfo.get("ftype",None) if ftype and ftype == 'app': - app_obj = Apps.objects.filter(app_id=app_id, user_id=request.user).first() - if not app_obj: - res.code = 1006 - res.msg = '该应用不存在' - return Response(res.dict) + pass + # app_obj = Apps.objects.filter(app_id=app_id, user_id=request.user).first() + # if not app_obj: + # res.code = 1006 + # res.msg = '该应用不存在' + # return Response(res.dict) elif ftype and ftype == 'head': if request.user.uid != app_id: res.code = 1007 diff --git a/fir_ser/fir_ser/settings.py b/fir_ser/fir_ser/settings.py index 3992fef..ba6134b 100644 --- a/fir_ser/fir_ser/settings.py +++ b/fir_ser/fir_ser/settings.py @@ -168,23 +168,14 @@ THIRD_PART_CONFIG = { "GEE_TEST": { }, - # 支付宝支付相关配置 - "ALI_PAY": { - # 默认使用配置 - "default": { - "version": "1.0", # 支付宝支付调用的接口版本(固定值1.0) - "debug": True, # 是否启用调试模式(False是正式环境) - "app_id": "2016091800539084", # 支付宝分配给开发者的应用ID(启用线上环境请更改), - "app_private_key_path": os.path.join( - BASE_DIR, 'keys', 'app_private_2048.txt' - ), # APP应用的私钥 - "alipay_public_key_path": os.path.join( - BASE_DIR, 'keys', 'alipay_public_2048.txt' - ), # 支付宝的公钥 - "callback_url": "http://47.94.172.250:8804/api/v1/trade/alipay/", # 添加回调域名 - }, - # 目前针对支付业务进行切换 - "pay": { + # APP存储配置 + 'storage': [ + { + 'name': 'local', + 'type': 0, + 'auth': {'domain_name': 'http://127.0.0.1:8000'}, # 正式环境需要填写正式的访问域名 + 'active': True } - } + ] + }