diff --git a/fir_client/src/components/FirDownload.vue b/fir_client/src/components/FirDownload.vue index bec5d7b..c0910b6 100644 --- a/fir_client/src/components/FirDownload.vue +++ b/fir_client/src/components/FirDownload.vue @@ -56,7 +56,8 @@ placeholder="验证码" prefix-icon="el-icon-mobile"/> - 获取验证码 diff --git a/fir_client/src/components/FirHeader.vue b/fir_client/src/components/FirHeader.vue index 1d31a6c..bb19535 100644 --- a/fir_client/src/components/FirHeader.vue +++ b/fir_client/src/components/FirHeader.vue @@ -91,7 +91,7 @@ export default { this.$message.success('复制剪切板成功'); }, maketoken() { - this.$confirm('确认重新生成新的密钥么?', '警告', { + this.$confirm('该操作将导致老秘钥失效,确认重新生成新的密钥么?', '警告', { type: 'warning' }) // eslint-disable-next-line no-unused-vars diff --git a/fir_client/src/components/FirLogin.vue b/fir_client/src/components/FirLogin.vue index bb3cebd..5a10fc3 100644 --- a/fir_client/src/components/FirLogin.vue +++ b/fir_client/src/components/FirLogin.vue @@ -86,7 +86,8 @@ 微信 + size="small" style="color: #1fc939;border: 1px solid rgba(31,201,57,.5); width: 110px" + @click="wxLogin">微信 diff --git a/fir_client/src/components/ShortDownload.vue b/fir_client/src/components/ShortDownload.vue index dd72986..b9edfe2 100644 --- a/fir_client/src/components/ShortDownload.vue +++ b/fir_client/src/components/ShortDownload.vue @@ -44,7 +44,7 @@
- 验证码 + 验证码
@@ -119,7 +119,7 @@

超级签

-

{{mcurrentappinfo.release_type|getiOStype}}

+

{{ mcurrentappinfo.release_type|getiOStype }}

- 保存信息 diff --git a/fir_client/src/components/apps/FirApps.vue b/fir_client/src/components/apps/FirApps.vue index d520772..4c117d3 100644 --- a/fir_client/src/components/apps/FirApps.vue +++ b/fir_client/src/components/apps/FirApps.vue @@ -28,7 +28,8 @@
此套餐 - @@ -46,7 +47,8 @@ class="pay-icon alipay"/> - @@ -301,12 +303,16 @@ {{ uploadprocess[uploadprocessList[multiFileList.indexOf(currentfile)]].speed }}/s - + {{ analyseappinfo.is_new|get_upload_text }} + @click="uploadcloud(analyseappinfo,currentfile,false,getappsFun)">{{ + analyseappinfo.is_new|get_upload_text + }} diff --git a/fir_client/src/components/index/FirIndexBody.vue b/fir_client/src/components/index/FirIndexBody.vue index 6affc71..54159ec 100644 --- a/fir_client/src/components/index/FirIndexBody.vue +++ b/fir_client/src/components/index/FirIndexBody.vue @@ -45,9 +45,10 @@
您身边的应用托管分发专家
7x24小时提供出色的不间断服务
- 联系我们
diff --git a/fir_client/src/components/user/FirSuperSignBase.vue b/fir_client/src/components/user/FirSuperSignBase.vue index 40047b6..855cbad 100644 --- a/fir_client/src/components/user/FirSuperSignBase.vue +++ b/fir_client/src/components/user/FirSuperSignBase.vue @@ -593,7 +593,7 @@ align="center" label="设备名称" prop="product" - width="200"> + width="160"> @@ -172,6 +173,7 @@ @@ -179,12 +181,14 @@ @@ -207,6 +211,7 @@ diff --git a/fir_client/src/components/user/FirUserProfileCertification.vue b/fir_client/src/components/user/FirUserProfileCertification.vue index 490564e..927e270 100644 --- a/fir_client/src/components/user/FirUserProfileCertification.vue +++ b/fir_client/src/components/user/FirUserProfileCertification.vue @@ -130,7 +130,9 @@ placeholder="请输入您收到的验证码" prefix-icon="el-icon-mobile"/> - 获取验证码 diff --git a/fir_client/src/components/user/FirUserProfileInfo.vue b/fir_client/src/components/user/FirUserProfileInfo.vue index ab4c79b..ead33cd 100644 --- a/fir_client/src/components/user/FirUserProfileInfo.vue +++ b/fir_client/src/components/user/FirUserProfileInfo.vue @@ -247,8 +247,9 @@ -
+

绑定第三方账户 diff --git a/fir_client/src/components/user/FirUserStorage.vue b/fir_client/src/components/user/FirUserStorage.vue index 497b818..6236ed5 100644 --- a/fir_client/src/components/user/FirUserStorage.vue +++ b/fir_client/src/components/user/FirUserStorage.vue @@ -175,21 +175,25 @@ style="width: 100%"> @@ -197,15 +201,18 @@ diff --git a/fir_ser/admin/views/login.py b/fir_ser/admin/views/login.py index 8dea498..07debc5 100644 --- a/fir_ser/admin/views/login.py +++ b/fir_ser/admin/views/login.py @@ -41,7 +41,7 @@ class LoginView(APIView): if user.is_active: if user.role == 3: login_auth_failed("del", username) - key, user_info = set_user_token(user) + key, user_info = set_user_token(user, request) response.data = { "username": user_info.username, "token": key diff --git a/fir_ser/admin/views/order.py b/fir_ser/admin/views/order.py index 37aa786..ab33027 100644 --- a/fir_ser/admin/views/order.py +++ b/fir_ser/admin/views/order.py @@ -15,8 +15,7 @@ from api.utils.auth import AdminTokenAuthentication from api.utils.baseutils import get_dict_from_filter_fields from api.utils.response import BaseResponse from api.utils.serializer import AdminOrdersSerializer -from api.utils.storage.caches import update_order_info -from api.utils.utils import get_order_num +from api.utils.storage.caches import update_order_info, admin_change_user_download_times logger = logging.getLogger(__name__) @@ -95,12 +94,7 @@ class OrderInfoView(APIView): obj = UserInfo.objects.filter(pk=pk).first() if obj: if amount > 0: - order_number = get_order_num() - order_obj = Order.objects.create(payment_type=2, order_number=order_number, payment_number=order_number, - user_id=obj, status=1, order_type=1, actual_amount=0, - actual_download_times=amount, payment_name='后台管理员充值', - actual_download_gift_times=0) - if update_order_info(obj.pk, order_obj.order_number, order_obj.order_number, order_obj.payment_type): + if admin_change_user_download_times(obj, amount): return Response(res.dict) else: res.code = 1005 diff --git a/fir_ser/admin/views/user.py b/fir_ser/admin/views/user.py index 1a1bdc5..d78c835 100644 --- a/fir_ser/admin/views/user.py +++ b/fir_ser/admin/views/user.py @@ -15,6 +15,8 @@ from api.utils.auth import AdminTokenAuthentication from api.utils.baseutils import get_dict_from_filter_fields from api.utils.response import BaseResponse from api.utils.serializer import AdminUserInfoSerializer, AdminUserCertificationSerializer, AdminThirdWxSerializer +from api.utils.storage.caches import auth_user_download_times_gift +from fir_ser.settings import AUTH_USER_GIVE_DOWNLOAD_TIMES logger = logging.getLogger(__name__) @@ -65,7 +67,12 @@ class UserInfoView(APIView): users_serializer.save() certification = data.get("certification", None) if certification and certification != -1: - UserCertificationInfo.objects.filter(user_id=user_obj).update(status=data["certification"]) + user_cert_obj = UserCertificationInfo.objects.filter(user_id=user_obj).first() + if user_cert_obj: + status = user_cert_obj.status + UserCertificationInfo.objects.filter(user_id=user_obj).update(status=data["certification"]) + if status != 1 and UserCertificationInfo.objects.filter(user_id=user_obj).first().status == 1: + auth_user_download_times_gift(user_obj, AUTH_USER_GIVE_DOWNLOAD_TIMES) res.data = users_serializer.data return Response(res.dict) res.code = 1004 @@ -101,9 +108,12 @@ class UserCertificationInfoView(APIView): obj = UserCertificationInfo.objects.filter(id=pk).first() if obj: data['pk'] = pk + status = obj.status users_serializer = AdminUserCertificationSerializer(obj, data=data, partial=True) if users_serializer.is_valid(): users_serializer.save() + if status != 1 and users_serializer.data.get('status') == 1: + auth_user_download_times_gift(obj.user_id, AUTH_USER_GIVE_DOWNLOAD_TIMES) res.data = users_serializer.data return Response(res.dict) res.code = 1004 diff --git a/fir_ser/api/migrations/0024_auto_20211108_1755.py b/fir_ser/api/migrations/0024_auto_20211108_1755.py new file mode 100644 index 0000000..c64e6f8 --- /dev/null +++ b/fir_ser/api/migrations/0024_auto_20211108_1755.py @@ -0,0 +1,23 @@ +# Generated by Django 3.2.3 on 2021-11-08 17:55 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0023_remove_appudid_binary_file'), + ] + + operations = [ + migrations.AddField( + model_name='token', + name='remote_addr', + field=models.GenericIPAddressField(blank=True, null=True, verbose_name='远程IP地址'), + ), + migrations.AlterField( + model_name='order', + name='order_type', + field=models.SmallIntegerField(choices=[(0, '用户下单'), (1, '后台充值'), (2, '系统赠送')], default=0, verbose_name='订单类型'), + ), + ] diff --git a/fir_ser/api/models.py b/fir_ser/api/models.py index ade1129..98d6c5e 100644 --- a/fir_ser/api/models.py +++ b/fir_ser/api/models.py @@ -92,6 +92,7 @@ class Token(models.Model): UserInfo, related_name='auth_token', on_delete=models.CASCADE, verbose_name="关联用户" ) + remote_addr = models.GenericIPAddressField(verbose_name="远程IP地址",null=True,blank=True) created = models.DateTimeField(verbose_name="创建时间", auto_now_add=True) def __str__(self): @@ -389,7 +390,7 @@ class Order(models.Model): actual_download_gift_times = models.BigIntegerField(verbose_name="实际赠送的数量", default=0) status_choices = ((0, '交易成功'), (1, '待支付'), (2, '订单已创建'), (3, '退费申请中'), (4, '已退费'), (5, '主动取消'), (6, '超时取消')) status = models.SmallIntegerField(choices=status_choices, verbose_name="状态") - order_type_choices = ((0, '用户下单'), (1, '后台充值'),) + order_type_choices = ((0, '用户下单'), (1, '后台充值'), (2, '系统赠送')) order_type = models.SmallIntegerField(choices=order_type_choices, default=0, verbose_name="订单类型") pay_time = models.DateTimeField(blank=True, null=True, verbose_name="付款时间") cancel_time = models.DateTimeField(blank=True, null=True, verbose_name="订单取消时间") diff --git a/fir_ser/api/utils/baseutils.py b/fir_ser/api/utils/baseutils.py index 3343fb8..994927e 100644 --- a/fir_ser/api/utils/baseutils.py +++ b/fir_ser/api/utils/baseutils.py @@ -12,6 +12,7 @@ import os import re import time import uuid +import random from Crypto import Random from Crypto.Cipher import AES @@ -291,3 +292,11 @@ def format_get_uri(domain, short, data): if uri: uri = '?' + uri[1:] return f'{domain}/{short}{uri}' + + +def get_order_num(order_type=1): + now = datetime.datetime.now() + date_str = "{0}{1}{2}{3}{4}{5}{6}".format(order_type, now.year, now.month, now.day, now.hour, now.minute, + now.second) + return date_str + str(random.randint(1000, 9999)) + str(random.randint(1000, 9999)) + str( + random.randint(1000, 9999)) diff --git a/fir_ser/api/utils/storage/caches.py b/fir_ser/api/utils/storage/caches.py index 1f155f1..7870120 100644 --- a/fir_ser/api/utils/storage/caches.py +++ b/fir_ser/api/utils/storage/caches.py @@ -14,7 +14,7 @@ from django.utils import timezone from api.models import Apps, UserInfo, AppReleaseInfo, AppUDID, APPToDeveloper, APPSuperSignUsedInfo, \ UserCertificationInfo, Order -from api.utils.baseutils import check_app_password +from api.utils.baseutils import check_app_password, get_order_num from api.utils.modelutils import get_app_d_count_by_app_id, get_app_domain_name, get_user_domain_name from api.utils.storage.storage import Storage, LocalStorage from fir_ser.settings import CACHE_KEY_TEMPLATE, SERVER_DOMAIN, SYNC_CACHE_TO_DATABASE, DEFAULT_MOBILEPROVISION, \ @@ -430,7 +430,7 @@ def update_order_status(out_trade_no, status): order_obj.save(update_fields=['status']) -def update_order_info(user_id, out_trade_no, payment_number, payment_type): +def update_order_info(user_id, out_trade_no, payment_number, payment_type, description=None): with cache.lock("%s_%s" % ('user_order_', out_trade_no), timeout=10, blocking_timeout=6): try: user_obj = UserInfo.objects.filter(pk=user_id).first() @@ -446,7 +446,10 @@ def update_order_info(user_id, out_trade_no, payment_number, payment_type): if not timezone.is_naive(now): now = timezone.make_naive(now, timezone.utc) order_obj.pay_time = now - order_obj.description = "充值成功,充值下载次数 %s ,现共可用次数 %s" % ( + default_description = "充值成功,充值下载次数 %s ,现共可用次数 %s" + if description: + default_description = description + order_obj.description = default_description % ( download_times, user_obj.download_times + download_times) order_obj.save( update_fields=["status", "payment_type", "payment_number", "pay_time", @@ -523,3 +526,30 @@ class MigrateStorageState(CacheBaseState): class CleanSignDataState(CacheBaseState): ... + + +def add_download_times_free_base(user_obj, amount, payment_name, description, order_type=1): + order_number = get_order_num() + order_obj = Order.objects.create(payment_type=2, order_number=order_number, payment_number=order_number, + user_id=user_obj, status=1, order_type=order_type, actual_amount=0, + actual_download_times=amount, payment_name=payment_name, + actual_download_gift_times=0) + if update_order_info(user_obj.pk, order_obj.order_number, order_obj.order_number, order_obj.payment_type, + description): + return True + return False + + +def new_user_download_times_gift(user_obj, amount=200): + description = '新用户赠送下载次数 %s ,现共可用次数 %s' + return add_download_times_free_base(user_obj, amount, '系统', description, 2) + + +def admin_change_user_download_times(user_obj, amount=200): + description = '后台管理员充值下载次数 %s ,现共可用次数 %s' + return add_download_times_free_base(user_obj, amount, '后台管理员充值', description) + + +def auth_user_download_times_gift(user_obj, amount=200): + description = '实名认证赠送充值下载次数 %s ,现共可用次数 %s' + return add_download_times_free_base(user_obj, amount, '系统', description, 2) diff --git a/fir_ser/api/utils/utils.py b/fir_ser/api/utils/utils.py index 316ba13..fe3eea2 100644 --- a/fir_ser/api/utils/utils.py +++ b/fir_ser/api/utils/utils.py @@ -17,6 +17,7 @@ from api.models import APPSuperSignUsedInfo, APPToDeveloper, \ UDIDsyncDeveloper, UserInfo, AppReleaseInfo, AppScreenShot, Token, DeveloperDevicesID, UserAdDisplayInfo from api.utils.TokenManager import generate_numeric_token_of_length, generate_alphanumeric_token_of_length, make_token, \ verify_token +from api.utils.baseutils import get_real_ip_address from api.utils.modelutils import get_app_d_count_by_app_id from api.utils.sendmsg.sendmsg import SendMessage from api.utils.storage.caches import consume_user_download_times @@ -289,14 +290,6 @@ def clean_storage_data(user_obj, storage_obj=None): return True -def get_order_num(order_type=1): - now = datetime.datetime.now() - date_str = "{0}{1}{2}{3}{4}{5}{6}".format(order_type, now.year, now.month, now.day, now.hour, now.minute, - now.second) - return date_str + str(random.randint(1000, 9999)) + str(random.randint(1000, 9999)) + str( - random.randint(1000, 9999)) - - def get_choices_dict(choices): result = [] choices_org_list = list(choices) @@ -313,11 +306,23 @@ def get_choices_name_from_key(choices, key): return '' -def set_user_token(user_obj): +def set_user_token(user_obj, request): key = binascii.hexlify(os.urandom(32)).decode() now = datetime.datetime.now() user_info = UserInfo.objects.get(pk=user_obj.pk) auth_key = "_".join([CACHE_KEY_TEMPLATE.get('user_auth_token_key'), key]) cache.set(auth_key, {'uid': user_info.uid, 'username': user_info.username}, 3600 * 24 * 7) - Token.objects.create(user=user_obj, **{"access_token": key, "created": now}) + Token.objects.create(user=user_obj, + **{"access_token": key, "created": now, "remote_addr": get_real_ip_address(request)}) return key, user_info + + +def clean_user_token_and_cache(user_obj, white_token_list=None): + if white_token_list is None: + white_token_list = [] + for token_obj in Token.objects.filter(user=user_obj): + if token_obj.access_token in white_token_list: + continue + auth_key = "_".join([CACHE_KEY_TEMPLATE.get('user_auth_token_key'), token_obj.access_token]) + cache.delete(auth_key) + token_obj.delete() diff --git a/fir_ser/api/views/login.py b/fir_ser/api/views/login.py index 27e8313..8420e45 100644 --- a/fir_ser/api/views/login.py +++ b/fir_ser/api/views/login.py @@ -13,12 +13,13 @@ from api.utils.modelutils import get_min_default_domain_cname_obj, add_remote_in from api.utils.mp.wechat import make_wx_login_qrcode, show_qrcode_url from api.utils.response import BaseResponse from api.utils.serializer import UserInfoSerializer, CertificationSerializer, UserCertificationSerializer -from api.utils.storage.caches import login_auth_failed, set_wx_ticket_login_info_cache, get_wx_ticket_login_info_cache +from api.utils.storage.caches import login_auth_failed, set_wx_ticket_login_info_cache, get_wx_ticket_login_info_cache, \ + new_user_download_times_gift from api.utils.throttle import VisitRegister1Throttle, VisitRegister2Throttle, GetAuthC1Throttle, GetAuthC2Throttle from api.utils.utils import get_captcha, valid_captcha, \ get_sender_sms_token, is_valid_sender_code, get_sender_email_token, get_random_username, \ - check_username_exists, set_user_token -from fir_ser.settings import REGISTER, LOGIN, CHANGER, REPORT + check_username_exists, set_user_token, clean_user_token_and_cache +from fir_ser.settings import REGISTER, LOGIN, CHANGER, REPORT, NEW_USER_GIVE_DOWNLOAD_TIMES logger = logging.getLogger(__name__) @@ -36,9 +37,7 @@ def reset_user_pwd(user, sure_password, old_password=''): user.set_password(sure_password) user.save(update_fields=["password"]) logger.info(f"user:{user} change password success,old {old_password} new {sure_password}") - for token_obj in Token.objects.filter(user=user): - cache.delete(token_obj.access_token) - token_obj.delete() + clean_user_token_and_cache(user) def get_authenticate(target, password, act, allow_type): @@ -328,7 +327,7 @@ class LoginView(APIView): if user.is_active: login_auth_failed("del", username) # update the token - key, user_info = set_user_token(user) + key, user_info = set_user_token(user, request) serializer = UserInfoSerializer(user_info, ) data = serializer.data response.msg = "验证成功!" @@ -438,6 +437,10 @@ class RegistView(APIView): response.msg = "注册异常" response.code = 1000 if user_obj: + try: + new_user_download_times_gift(user_obj, NEW_USER_GIVE_DOWNLOAD_TIMES) + except Exception as e: + logger.error(f"用户{user_obj}赠送下载次数失败{e}") response.msg = "注册成功" response.code = 1000 else: @@ -524,10 +527,7 @@ class UserInfoView(APIView): logger.info(f"user:{request.user} change password success,old {old_password} new {sure_password}") auth_token = request.auth - for token_obj in Token.objects.filter(user=user): - if token_obj.access_token != auth_token: - cache.delete(token_obj.access_token) - token_obj.delete() + clean_user_token_and_cache(user, [auth_token]) return Response(res.dict) else: @@ -844,7 +844,7 @@ class WeChatLoginCheckView(APIView): else: user = UserInfo.objects.filter(pk=wx_ticket_data['pk']).first() if user.is_active: - key, user_info = set_user_token(user) + key, user_info = set_user_token(user, request) serializer = UserInfoSerializer(user_info) data = serializer.data ret.msg = "验证成功!" diff --git a/fir_ser/api/views/order.py b/fir_ser/api/views/order.py index a39d6b2..e98f27b 100644 --- a/fir_ser/api/views/order.py +++ b/fir_ser/api/views/order.py @@ -12,11 +12,12 @@ from rest_framework.views import APIView from api.models import Price, Order from api.utils.auth import ExpiringTokenAuthentication +from api.utils.baseutils import get_order_num from api.utils.pay.util import get_pay_obj_form_name, get_enable_pay_choices, get_payment_type from api.utils.response import BaseResponse from api.utils.serializer import PriceSerializer, OrdersSerializer from api.utils.storage.caches import update_order_status -from api.utils.utils import get_order_num, get_choices_dict +from api.utils.utils import get_choices_dict logger = logging.getLogger(__name__) diff --git a/fir_ser/fir_ser/settings.py b/fir_ser/fir_ser/settings.py index d904d0f..859cf91 100644 --- a/fir_ser/fir_ser/settings.py +++ b/fir_ser/fir_ser/settings.py @@ -219,8 +219,10 @@ CACHE_KEY_TEMPLATE = { DATA_DOWNLOAD_KEY = "d_token" FILE_UPLOAD_TMP_KEY = ".tmp" -USER_FREE_DOWNLOAD_TIMES = 20 -AUTH_USER_FREE_DOWNLOAD_TIMES = 60 +USER_FREE_DOWNLOAD_TIMES = 5 +AUTH_USER_FREE_DOWNLOAD_TIMES = 10 +NEW_USER_GIVE_DOWNLOAD_TIMES = 100 +AUTH_USER_GIVE_DOWNLOAD_TIMES = 200 SYNC_CACHE_TO_DATABASE = { 'download_times': 10, # 下载次数同步时间