签名账户设备转移功能

dependabot/npm_and_yarn/fir_admin/url-parse-1.5.10
nineven 3 years ago
parent adc71de160
commit f5ffc3632f
  1. 1
      fir_admin/.env.development
  2. 68
      fir_client/src/components/user/FirSuperSignBase.vue
  3. 2
      fir_ser/admin/utils/exception.py
  4. 5
      fir_ser/api/utils/modelutils.py
  5. 37
      fir_ser/api/utils/serializer.py
  6. 42
      fir_ser/api/views/supersign.py
  7. 12
      fir_ser/common/base/baseutils.py
  8. 1
      fir_ser/fir_ser/settings.py

@ -3,3 +3,4 @@ ENV = 'development'
# base api
VUE_APP_BASE_API = 'https://flyapps.cn/api/v3/fir/server'
#VUE_APP_BASE_API = 'https://app.hehelucky.cn/api/v3/fir/server'

@ -777,21 +777,29 @@
width="200">
<template slot-scope="scope">
<el-popover placement="top" trigger="hover">
<p>开发者ID: {{ scope.row.developer_id }}</p>
<p>开发者ID: {{ get_developer_uid(scope.row.developer_id) }}</p>
<p>开发者备注: {{ scope.row.developer_description }}</p>
<p>开发者状态: {{ scope.row.developer_status }}</p>
<div slot="reference" class="name-wrapper">
<span>{{ scope.row.developer_id }}</span>
<span>{{ get_developer_uid(scope.row.developer_id) }}</span>
</div>
</el-popover>
</template>
</el-table-column>
<el-table-column
align="center"
label="已经分配其他用户"
prop="other_uid">
<template slot-scope="scope">
<el-popover v-if="scope.row.other_uid" placement="top" trigger="hover">
<p>分配用户uid: {{ scope.row.other_uid.uid }}</p>
<p>分配用户昵称: {{ scope.row.other_uid.name }}</p>
<div slot="reference" class="name-wrapper">
<span>{{ scope.row.other_uid.uid }}</span>
</div>
</el-popover>
</template>
</el-table-column>
<!-- <el-table-column-->
<!-- v-if="$store.state.userinfo&&$store.state.userinfo.role === 3"-->
<!-- align="center"-->
<!-- label="被使用户uid"-->
<!-- prop="other_uid">-->
<!-- </el-table-column>-->
<el-table-column
:formatter="deviceformatter"
align="center"
@ -885,21 +893,29 @@
prop="issuer_id">
<template slot-scope="scope">
<el-popover placement="top" trigger="hover">
<p>开发者ID: {{ scope.row.issuer_id }}</p>
<p>开发者ID: {{ get_developer_uid(scope.row.issuer_id) }}</p>
<p>开发者备注: {{ scope.row.developer_description }}</p>
<p>开发者状态: {{ scope.row.developer_status }}</p>
<div slot="reference" class="name-wrapper">
<span>{{ scope.row.issuer_id }}</span>
<span>{{ get_developer_uid(scope.row.issuer_id) }}</span>
</div>
</el-popover>
</template>
</el-table-column>
<el-table-column
align="center"
label="已经分配其他用户"
prop="other_uid">
<template slot-scope="scope">
<el-popover v-if="scope.row.other_uid" placement="top" trigger="hover">
<p>分配用户uid: {{ scope.row.other_uid.uid }}</p>
<p>分配用户昵称: {{ scope.row.other_uid.name }}</p>
<div slot="reference" class="name-wrapper">
<span>{{ scope.row.other_uid.uid }}</span>
</div>
</el-popover>
</template>
</el-table-column>
<!-- <el-table-column-->
<!-- v-if="$store.state.userinfo&&$store.state.userinfo.role === 3"-->
<!-- align="center"-->
<!-- label="被使用户uid"-->
<!-- prop="other_uid">-->
<!-- </el-table-column>-->
<el-table-column
:formatter="deviceformatter"
align="center"
@ -922,7 +938,7 @@
</el-button>
</el-tooltip>
</div>
<div style="margin-top: 5px">
<div v-if="!(scope.row.issuer_id && scope.row.issuer_id.indexOf(':')> -1)" style="margin-top: 5px">
<el-tooltip content="删除的同时,会检测并同时禁用苹果开发者设备" placement="bottom">
<el-button
size="mini"
@ -1212,6 +1228,12 @@ export default {
}
},
methods: {
get_developer_uid(uid) {
if (uid && uid.indexOf(':') > -1) {
return '公共账号池'
} else
return uid
},
changeDevice(info, disabled) {
this.iosudevicesFun("PUT", {developer_id: info.developer_id, udid: info.udid, disabled: disabled})
},
@ -1403,7 +1425,17 @@ export default {
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.iosdevicesudidFun('DELETE', {id: scope.row.id, aid: scope.row.app_id, disabled: disabled}, scope);
let other_uid = scope.row.other_uid
let uid = ''
if (other_uid && other_uid.uid) {
uid = other_uid.uid
}
this.iosdevicesudidFun('DELETE', {
id: scope.row.id,
aid: scope.row.app_id,
disabled: disabled,
uid: uid
}, scope);
}).catch(() => {
this.$message({
type: 'info',

@ -20,4 +20,4 @@ def common_exception_handler(exc, context):
if not ret: # drf内置处理不了,丢给django 的,我们自己来处理
return ApiResponse(msg='error', result=str(exc))
else:
return ApiResponse(msg='error', data=ret.data)
return ApiResponse(msg='error', status=ret.status_code, **ret.data, )

@ -258,6 +258,11 @@ def update_or_create_developer_udid_info(device_obj, developer_obj):
return UDIDsyncDeveloper.objects.update_or_create(developerid=developer_obj, udid=device_obj.udid, defaults=device)
def check_uid_has_relevant(user_uid, to_user_uid):
if user_uid and to_user_uid:
return IosDeveloperPublicPoolBill.objects.filter(user_id__uid=user_uid, to_user_id__uid=to_user_uid).first()
class PageNumber(PageNumberPagination):
page_size = 10 # 每页显示多少条
page_size_query_param = 'size' # URL中每页显示条数的参数

@ -11,9 +11,9 @@ from api.utils.modelutils import get_user_domain_name, get_app_domain_name, get_
from api.utils.storage.caches import get_user_free_download_times, get_user_cert_auth_status
from api.utils.storage.storage import Storage
from api.utils.utils import get_developer_udided
from common.base.baseutils import get_choices_dict, get_choices_name_from_key
from common.base.baseutils import get_choices_dict, get_choices_name_from_key, AppleDeveloperUid
from common.cache.storage import AdPicShowCache
from fir_ser.settings import DEVELOPER_USE_STATUS
from fir_ser.settings import DEVELOPER_USE_STATUS, DEVELOPER_UID_KEY
logger = logging.getLogger(__name__)
@ -470,16 +470,14 @@ class SuperSignUsedSerializer(serializers.ModelSerializer):
developer_status = serializers.SerializerMethodField()
def get_developer_status(self, obj):
if self.context.get('mine'):
return obj.developerid.get_status_display()
else:
return '公共账号池'
def get_developer_id(self, obj):
issuer_id = obj.developerid.issuer_id
if self.context.get('mine'):
return obj.developerid.issuer_id
return issuer_id
else:
return '公共账号池'
return f"{DEVELOPER_UID_KEY}{AppleDeveloperUid().get_encrypt_uid(issuer_id)}"
def get_developer_description(self, obj):
if self.context.get('mine'):
@ -489,12 +487,9 @@ class SuperSignUsedSerializer(serializers.ModelSerializer):
def get_other_uid(self, obj):
user_obj = self.context.get('user_obj')
role = 0
if user_obj:
role = user_obj.role
if role == 3:
if obj.user_id != obj.developerid.user_id:
return obj.user_id.uid
if user_obj.uid != obj.user_id.uid:
return {'uid': obj.user_id.uid, 'name': obj.user_id.first_name}
class DeveloperDeviceSerializer(serializers.ModelSerializer):
@ -529,16 +524,14 @@ class DeviceUDIDSerializer(serializers.ModelSerializer):
other_uid = serializers.SerializerMethodField()
def get_issuer_id(self, obj):
issuer_id = obj.udid.developerid.issuer_id
if self.context.get('mine'):
return obj.udid.developerid.issuer_id
return issuer_id
else:
return '公共账号池'
return f"{DEVELOPER_UID_KEY}{AppleDeveloperUid().get_encrypt_uid(issuer_id)}"
def get_developer_status(self, obj):
if self.context.get('mine'):
return obj.udid.developerid.get_status_display()
else:
return '公共账号池'
def get_developer_description(self, obj):
if self.context.get('mine'):
@ -548,13 +541,11 @@ class DeviceUDIDSerializer(serializers.ModelSerializer):
def get_other_uid(self, obj):
user_obj = self.context.get('user_obj')
role = 0
if user_obj:
role = user_obj.role
if role == 3:
user_obj_new = obj.app_id.user_id
if user_obj.pk != user_obj_new.pk:
super_user_obj = models.APPSuperSignUsedInfo.objects.filter(udid=obj, app_id=obj.app_id).first()
if super_user_obj.developerid.user_id != obj.app_id.user_id:
return obj.app_id.user_id.uid
if super_user_obj.developerid.user_id != user_obj_new:
return {'uid': user_obj_new.uid, 'name': user_obj_new.first_name}
def get_is_mine(self, obj):
return self.context.get('mine')

@ -16,15 +16,16 @@ from api.models import AppIOSDeveloperInfo, APPSuperSignUsedInfo, AppUDID, IosDe
UDIDsyncDeveloper, AppleDeveloperToAppUse, Apps, DeveloperAppID, APPToDeveloper, DeveloperDevicesID
from api.utils.app.supersignutils import IosUtils
from api.utils.auth import ExpiringTokenAuthentication, SuperSignPermission
from api.utils.modelutils import get_user_public_used_sign_num, get_user_public_sign_num, PageNumber
from api.utils.modelutils import get_user_public_used_sign_num, get_user_public_sign_num, PageNumber, \
check_uid_has_relevant
from api.utils.response import BaseResponse
from api.utils.serializer import DeveloperSerializer, SuperSignUsedSerializer, DeviceUDIDSerializer, BillInfoSerializer, \
DeveloperDeviceSerializer, AppleDeveloperToAppUseSerializer, AppleDeveloperToAppUseAppsSerializer
from api.utils.storage.caches import get_app_download_url
from api.utils.utils import get_developer_devices
from common.base.baseutils import get_choices_dict, get_choices_name_from_key
from common.base.baseutils import get_choices_dict, get_choices_name_from_key, AppleDeveloperUid
from common.cache.state import CleanSignDataState
from fir_ser.settings import DEVELOPER_USE_STATUS, DEVELOPER_DISABLED_STATUS
from fir_ser.settings import DEVELOPER_USE_STATUS, DEVELOPER_DISABLED_STATUS, DEVELOPER_UID_KEY
logger = logging.getLogger(__name__)
@ -315,8 +316,17 @@ class SuperSignUsedView(APIView):
device_udid = data.get('device_udid', '')
developer_id = data.get('developer_id', '')
bundle_id = data.get('bundle_id', '')
other_uid_info = data.get('other_uid', '')
if device_udid and developer_id and bundle_id:
app_obj = Apps.objects.filter(user_id=request.user, bundle_id=bundle_id).first()
if app_obj is None and not developer_id.startswith(DEVELOPER_UID_KEY):
if other_uid_info:
other_uid = other_uid_info.get('uid')
if other_uid and check_uid_has_relevant(request.user.uid, other_uid):
app_obj = Apps.objects.filter(bundle_id=bundle_id).first()
if developer_id.startswith(DEVELOPER_UID_KEY):
developer_id = AppleDeveloperUid().get_decrypt_uid(developer_id.lstrip('T:'))
app_to_dev_obj = APPToDeveloper.objects.filter(app_id=app_obj, developerid__issuer_id=developer_id).first()
if app_obj and app_to_dev_obj:
res = get_app_download_url(request, res, app_obj.app_id, app_obj.short, app_obj.password,
@ -346,6 +356,7 @@ class AppUDIDUsedView(APIView):
def delete(self, request):
res = BaseResponse()
pk = request.query_params.get("id", None)
other_uid = request.query_params.get("uid", None)
app_id = request.query_params.get("aid", None)
disabled = request.query_params.get("disabled", None)
if disabled is not None and disabled == '1':
@ -353,15 +364,22 @@ class AppUDIDUsedView(APIView):
else:
disabled = False
app_udid_obj = AppUDID.objects.filter(pk=pk, app_id__user_id=request.user)
if not app_udid_obj and check_uid_has_relevant(request.user.uid, other_uid):
app_udid_obj = AppUDID.objects.filter(pk=pk, app_id__user_id__uid=other_uid)
if app_udid_obj:
super_sign_used_obj = APPSuperSignUsedInfo.objects.filter(udid=app_udid_obj.first()).first()
if super_sign_used_obj and super_sign_used_obj.developerid.user_id.pk == request.user.pk:
if super_sign_used_obj:
if super_sign_used_obj.developerid.user_id.pk == request.user.pk:
logger.error(f"user {request.user} delete devices {app_udid_obj}")
IosUtils.disable_udid(app_udid_obj.first(), app_id, disabled)
else:
IosUtils.disable_udid(app_udid_obj.first(), app_id)
# res.code = 10002
# res.msg = '公共账号池不允许禁用删除'
app_udid_obj.delete()
else:
res.code = 10002
res.msg = '公共账号池不允许删除'
res.code = 10003
res.msg = '数据异常,删除失败'
return Response(res.dict)
@ -468,8 +486,12 @@ class DeviceUsedBillView(APIView):
res = BaseResponse()
udid = request.query_params.get("udid", None)
act = request.query_params.get("act", None)
receive_user_id_list = IosDeveloperPublicPoolBill.objects.filter(user_id=request.user,
to_user_id__isnull=False).values(
'to_user_id').distinct()
user_used_list = IosDeveloperPublicPoolBill.objects.filter(
Q(to_user_id=request.user) | Q(user_id=request.user))
Q(to_user_id=request.user) | Q(user_id=request.user) | Q(user_id_id__in=receive_user_id_list))
page_obj = PageNumber()
if udid:
user_used_list = user_used_list.filter(udid=udid)
@ -512,7 +534,11 @@ class DeviceUsedRankInfoView(APIView):
search_key = request.query_params.get("appnamesearch")
start_time = request.query_params.get("start_time")
end_time = request.query_params.get("end_time")
app_used_sign_objs = APPSuperSignUsedInfo.objects.filter(user_id=request.user)
receive_user_id_list = IosDeveloperPublicPoolBill.objects.filter(user_id=request.user,
to_user_id__isnull=False).values(
'to_user_id').distinct()
app_used_sign_objs = APPSuperSignUsedInfo.objects.filter(
Q(user_id=request.user) | Q(user_id_id__in=receive_user_id_list))
if search_key:
app_used_sign_objs = app_used_sign_objs.filter(
Q(app_id__name=search_key) | Q(app_id__bundle_id=search_key) | Q(

@ -56,6 +56,18 @@ class AESCipher(object):
return data
class AppleDeveloperUid(object):
def __init__(self):
self.cipher = AESCipher(self.__class__.__name__)
def get_encrypt_uid(self, raw):
return self.cipher.encrypt(raw.encode('utf-8')).decode('utf-8')
def get_decrypt_uid(self, enc):
return self.cipher.decrypt(enc)
def make_from_user_uuid(uid):
random_str = uuid.uuid1().__str__().split("-")[0:-1]
user_ran_str = uuid.uuid5(uuid.NAMESPACE_DNS, uid).__str__().split("-")

@ -280,6 +280,7 @@ CACHE_KEY_TEMPLATE = {
DATA_DOWNLOAD_KEY = "d_token"
FILE_UPLOAD_TMP_KEY = ".tmp"
DEVELOPER_UID_KEY = "T:"
USER_FREE_DOWNLOAD_TIMES = 5
AUTH_USER_FREE_DOWNLOAD_TIMES = 10
NEW_USER_GIVE_DOWNLOAD_TIMES = 100

Loading…
Cancel
Save