增加域名绑定功能

dependabot/npm_and_yarn/fir_admin/dns-packet-1.3.4
youngS 4 years ago
parent a82f2a3ec7
commit 250c07c1a6
  1. 189
      fir_client/src/components/FirBase.vue
  2. 3
      fir_client/src/components/FirHeader.vue
  3. 31
      fir_client/src/components/user/FirUserProfileInfo.vue
  4. 16
      fir_client/src/restful/index.js
  5. 7
      fir_client/src/store/index.js
  6. 2
      fir_ser/api/admin.py
  7. 47
      fir_ser/api/migrations/0047_domaincnameinfo_userdomaininfo.py
  8. 16
      fir_ser/api/migrations/0048_auto_20210519_1553.py
  9. 16
      fir_ser/api/migrations/0049_remove_userinfo_domain_name.py
  10. 33
      fir_ser/api/models.py
  11. 3
      fir_ser/api/urls.py
  12. 4
      fir_ser/api/utils/app/supersignutils.py
  13. 11
      fir_ser/api/utils/baseutils.py
  14. 7
      fir_ser/api/utils/serializer.py
  15. 9
      fir_ser/api/utils/utils.py
  16. 8
      fir_ser/api/views/apps.py
  17. 85
      fir_ser/api/views/domain.py
  18. 64
      fir_ser/api/views/login.py

@ -1,9 +1,11 @@
<template> <template>
<div ref="appbase"> <div ref="appbase">
<el-dialog <el-dialog
title="绑定域名" title="绑定下载页域名"
:close-on-click-modal="false"
:close-on-press-escape="false"
:visible.sync="bind_domain_sure" :visible.sync="bind_domain_sure"
width="30%"> width="666px">
<div style="margin: 5px 20px"> <div style="margin: 5px 20px">
<el-steps :active="active" finish-status="success"> <el-steps :active="active" finish-status="success">
@ -20,25 +22,32 @@
<el-input clearable autofocus v-model="domain_name"></el-input> <el-input clearable autofocus v-model="domain_name"></el-input>
</div> </div>
<div v-else-if="active===2"> <div v-else-if="active===2">
<h3>还差一步绑定成功</h3> <div style="text-align: center;margin: 20px 0">
请联系域名管理员前往 {{ domain_name }} 域名 DNS 管理后台添加如下 CNAME 记录 <h3>还差一步绑定成功</h3>
</div>
请联系域名管理员前往 <strong>{{ domain_name }}</strong> 域名 DNS 管理后台添加如下 CNAME 记录
<el-table <el-table
:data="domain_tData" :data="domain_tData"
border border
style="width: 100%"> stripe
style="width: 100%;margin-top: 20px">
<el-table-column <el-table-column
prop="type" prop="type"
label="记录类型" label="记录类型"
align="center"
width="100"> width="100">
</el-table-column> </el-table-column>
<el-table-column <el-table-column
prop="host" prop="host"
align="center"
label="主机记录" label="主机记录"
width="180"> >
</el-table-column> </el-table-column>
<el-table-column <el-table-column
prop="dns" prop="dns"
label="记录值"> align="center"
label="记录值"
width="300">
</el-table-column> </el-table-column>
</el-table> </el-table>
<el-alert title="请在域名DNS配置成功后,点击“下一步”按钮" <el-alert title="请在域名DNS配置成功后,点击“下一步”按钮"
@ -47,11 +56,79 @@
:closable="false" :closable="false"
show-icon/> show-icon/>
</div> </div>
<div v-else-if="active===3">
<div v-if="!bind_status">
<div style="text-align: center;margin: 20px 0">
<el-link :underline="false" type="danger"
style="font-size: x-large">绑定失败
</el-link>
</div>
<p style="margin: 10px 0">您的账户正在绑定域名<strong>{{ domain_name }}</strong></p>
<el-row>
<el-col :span="16"><p>系统未检出到您的CNAME记录请检查您的配置</p></el-col>
<el-col :span="6">
<el-button type="danger" size="small" plain style="margin-top: 8px"
@click="remove_domain">
解除绑定
</el-button>
</el-col>
</el-row>
</div>
<div v-else>
<div style="text-align: center;margin: 20px 0">
<el-link :underline="false" type="success"
style="font-size: x-large">绑定成功
</el-link>
</div>
<el-row>
<el-col :span="16"><p>您的账户已绑定域名<strong>{{ domain_name }}</strong></p></el-col>
<el-col :span="6">
<el-button type="danger" size="small" plain style="margin-top: 8px"
@click="remove_domain">
解除绑定
</el-button>
</el-col>
</el-row>
</div>
<el-table
:data="domain_tData"
border
stripe
style="width: 100%;margin-top: 20px">
<el-table-column
prop="type"
label="记录类型"
align="center"
width="100">
</el-table-column>
<el-table-column
prop="host"
align="center"
label="主机记录"
>
</el-table-column>
<el-table-column
prop="dns"
align="center"
label="记录值"
width="300">
</el-table-column>
</el-table>
<div v-if="!bind_status" style="text-align: center;margin: 30px 0">
<el-button @click="check_cname" type="success" plain>已经修改配置再次检查绑定</el-button>
</div>
</div>
</div> </div>
</div> </div>
<span slot="footer" class="dialog-footer"> <span slot="footer" class="dialog-footer" v-if="active!==3">
<el-button style="margin-top: 12px;" @click="last">上一步</el-button> <el-button style="margin-top: 12px;" @click="last"
:disabled="bind_status|| active===1 ">上一步</el-button>
<el-button style="margin-top: 12px;" @click="next">下一步</el-button> <el-button style="margin-top: 12px;" @click="next">下一步</el-button>
</span> </span>
@ -66,8 +143,8 @@
:closable="false" :closable="false"
effect="dark"> effect="dark">
<div slot="title"> <div slot="title">
<span :underline="false" class="domian-tip-bar">应用分发请绑定您自己的域名平台域名可能会随时更换将导致您的应用无法访问</span> <span :underline="false" class="domian-tip-bar">应用分发请绑定您自己的域名平台分发域名可能因不可违因素更换将导致您的应用无法访问</span>
<el-button size="medium">立即绑定</el-button> <el-button size="medium" @click="bind_click">立即绑定</el-button>
</div> </div>
</el-alert> </el-alert>
</div> </div>
@ -95,6 +172,7 @@
import FirFooter from "@/components/FirFooter"; import FirFooter from "@/components/FirFooter";
import BackToTop from "@/components/base/BackToTop"; import BackToTop from "@/components/base/BackToTop";
import {show_beautpic,} from "@/utils"; import {show_beautpic,} from "@/utils";
import {domainFun} from "@/restful";
export default { export default {
name: "FirBase", name: "FirBase",
@ -102,10 +180,11 @@
data() { data() {
return { return {
mousePosition: {}, mousePosition: {},
bind_domain_sure: true, bind_domain_sure: false,
active: 1, active: 1,
domain_name: '', domain_name: '',
domain_tData: [{'type': 'CNAME', 'host': 'xxx', 'dns': 'sdfsaf'}], bind_status: false,
domain_tData: [{'type': 'CNAME', 'host': 'xxx', 'dns': 'demo.xxx.cn'}],
myBackToTopStyle: { myBackToTopStyle: {
right: '80px', right: '80px',
bottom: '100px', bottom: '100px',
@ -128,10 +207,92 @@
this.$store.dispatch("dodomainshow", true); this.$store.dispatch("dodomainshow", true);
} }
}, },
'$store.state.domain_action': function () {
if (this.$store.state.domain_action) {
this.$store.dispatch("dodomainaction", false);
this.bind_click()
}
},
} }
, methods: { , methods: {
check_cname() {
domainFun(data => {
if (data.code === 1000) {
if (this.active++ > 2) this.active = 3;
this.bind_status = true;
this.$store.dispatch("dodomainshow", false);
} else {
if (data.code === 1004) {
this.active = 1;
this.domain_name = '';
} else {
if (this.active++ > 2) this.active = 3;
}
this.bind_status = false;
this.$message.error("绑定失败 " + data.msg)
}
}, {methods: 'PUT', data: {}})
},
remove_domain() {
domainFun(data => {
if (data.code === 1000) {
this.bind_status = false;
this.active = 1;
this.$message.success("解除绑定成功 ");
this.$store.dispatch("dodomainshow", true);
} else {
this.$message.error("解除绑定失败 " + data.msg)
}
}, {methods: 'DELETE', data: {}});
},
bind_click() {
domainFun(data => {
if (data.code === 1000) {
if (data.data) {
if (data.data.domain_name) {
this.domain_name = data.data.domain_name;
}
if (data.data.domain_record) {
this.format_domain_tData(data.data.domain_record);
if (this.active++ > 2) this.active = 3;
}
if (data.data.is_enable) {
this.bind_status = true;
if (this.active++ > 2) this.active = 3;
}
this.bind_domain_sure = true;
}
} else {
this.$message.error("绑定失败 " + data.msg)
}
}, {methods: 'GET', data: {}});
},
format_domain_tData(cname_domain) {
let domain_name_list = this.domain_name.split('.');
const d_len = domain_name_list.length;
if (d_len === 2) {
this.domain_tData[0].host = '@'
} else if (d_len > 2) {
domain_name_list.splice(domain_name_list.length - 2, 2);
this.domain_tData[0].host = domain_name_list.join(".")
}
this.domain_tData[0].dns = cname_domain;
},
next() { next() {
if (this.active++ > 2) this.active = 3; if (this.active === 1) {
domainFun(data => {
if (data.code === 1000) {
if (data.data && data.data.cname_domain) {
this.format_domain_tData(data.data.cname_domain);
if (this.active++ > 2) this.active = 3;
}
} else {
this.$message.error("绑定失败 " + data.msg)
}
}, {methods: 'POST', data: {domain_name: this.domain_name}})
} else if (this.active === 2) {
this.check_cname()
}
}, },
last() { last() {
if (this.active-- < 2) this.active = 1; if (this.active-- < 2) this.active = 1;

@ -49,6 +49,7 @@
<el-dropdown-menu slot="dropdown"> <el-dropdown-menu slot="dropdown">
<el-dropdown-item command="userinfo">个人资料</el-dropdown-item> <el-dropdown-item command="userinfo">个人资料</el-dropdown-item>
<el-dropdown-item command="apitoken">API token</el-dropdown-item> <el-dropdown-item command="apitoken">API token</el-dropdown-item>
<el-dropdown-item command="setdomian">设置域名</el-dropdown-item>
<el-dropdown-item command="storage" v-if="$store.state.userinfo.storage_active">存储管理 <el-dropdown-item command="storage" v-if="$store.state.userinfo.storage_active">存储管理
</el-dropdown-item> </el-dropdown-item>
<el-dropdown-item command="supersign" v-if="$store.state.userinfo.supersign_active">超级签名 <el-dropdown-item command="supersign" v-if="$store.state.userinfo.supersign_active">超级签名
@ -117,6 +118,8 @@
} }
}, {methods: 'GET', token: this.token}); }, {methods: 'GET', token: this.token});
} else if (command === 'setdomian') {
this.$store.dispatch("dodomainaction", true);
} else if (command === 'myorder') { } else if (command === 'myorder') {
this.$router.push({"name": 'FirUserOrders'}) this.$router.push({"name": 'FirUserOrders'})
} else if (command === 'exit') { } else if (command === 'exit') {

@ -138,23 +138,32 @@
</el-row> </el-row>
</el-form-item> </el-form-item>
<!-- <el-form-item label="下载域名">-->
<!-- <el-row :gutter="36">-->
<!-- <el-col :span="16">-->
<!-- <el-input v-model="userinfo.domain_name" :readonly="editdomain_name !== true" ref="domain_name"-->
<!-- prefix-icon="el-icon-download"-->
<!-- placeholder="下载页域名" clearable/>-->
<!-- </el-col>-->
<!-- <el-col :span="1">-->
<!-- <el-button icon="el-icon-edit" @click="changeDomainValue">-->
<!-- </el-button>-->
<!-- </el-col>-->
<!-- <el-col :span="5" v-if="editdomain_name === true">-->
<!-- <el-button type="success" @click="saveDomain" plain-->
<!-- class="save-button">-->
<!-- 保存-->
<!-- </el-button>-->
<!-- </el-col>-->
<!-- </el-row>-->
<!-- </el-form-item>-->
<el-form-item label="下载域名"> <el-form-item label="下载域名">
<el-row :gutter="36"> <el-row :gutter="36">
<el-col :span="16"> <el-col :span="16">
<el-input v-model="userinfo.domain_name" :readonly="editdomain_name !== true" ref="domain_name" <el-input v-model="userinfo.domain_name" :readonly="true" ref="domain_name"
prefix-icon="el-icon-download" prefix-icon="el-icon-download"
placeholder="下载页域名" clearable/> placeholder="下载页域名" clearable/>
</el-col> </el-col>
<el-col :span="1">
<el-button icon="el-icon-edit" @click="changeDomainValue">
</el-button>
</el-col>
<el-col :span="5" v-if="editdomain_name === true">
<el-button type="success" @click="saveDomain" plain
class="save-button">
保存
</el-button>
</el-col>
</el-row> </el-row>
</el-form-item> </el-form-item>

@ -539,3 +539,19 @@ export function changeInfoFun(callBack, params, load = true) {
true true
); );
} }
/**用户绑定域名*/
export function domainFun(callBack, params, load = true) {
getData(
params.methods,
USERSEVER + '/cname_domain',
params.data,
data => {
callBack(data);
},
load,
true,
true
);
}

@ -16,6 +16,7 @@ const store = new Vuex.Store({
appInfoIndex: [], appInfoIndex: [],
userInfoIndex: 0, userInfoIndex: 0,
show_domain_msg: false, show_domain_msg: false,
domain_action: false,
}, },
mutations: { mutations: {
setuserinfo(state, data) { setuserinfo(state, data) {
@ -32,9 +33,15 @@ const store = new Vuex.Store({
}, },
setdomainshow(state, val) { setdomainshow(state, val) {
state.show_domain_msg = val state.show_domain_msg = val
},
setdomainaction(state, val) {
state.domain_action = val
} }
}, },
actions: { actions: {
dodomainaction(context, data) {
context.commit('setdomainaction', data);
},
dodomainshow(context, data) { dodomainshow(context, data) {
context.commit('setdomainshow', data); context.commit('setdomainshow', data);
}, },

@ -16,3 +16,5 @@ admin.site.register(APPToDeveloper)
admin.site.register(UDIDsyncDeveloper) admin.site.register(UDIDsyncDeveloper)
admin.site.register(Price) admin.site.register(Price)
admin.site.register(Order) admin.site.register(Order)
admin.site.register(DomainCnameInfo)
admin.site.register(UserDomainInfo)

@ -0,0 +1,47 @@
# Generated by Django 3.0.3 on 2021-05-19 10:35
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('api', '0046_auto_20210423_1650'),
]
operations = [
migrations.CreateModel(
name='DomainCnameInfo',
fields=[
('domain_record',
models.CharField(max_length=128, primary_key=True, serialize=False, verbose_name='记录值')),
('ip_address', models.GenericIPAddressField(verbose_name='域名解析地址')),
('is_enable', models.BooleanField(default=True, verbose_name='是否启用该解析')),
('description', models.TextField(blank=True, default='', null=True, verbose_name='备注')),
('created_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
],
options={
'verbose_name': '分发域名信息',
'verbose_name_plural': '分发域名信息',
},
),
migrations.CreateModel(
name='UserDomainInfo',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('domain_name', models.CharField(db_index=True, max_length=64, verbose_name='下载页面域名')),
('is_enable', models.BooleanField(default=False, verbose_name='绑定成功')),
('created_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('cname_id', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='api.DomainCnameInfo',
verbose_name='cname解析ID')),
('user_id', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL,
verbose_name='用户ID')),
],
options={
'verbose_name': '分发域名绑定',
'verbose_name_plural': '分发域名绑定',
'unique_together': {('domain_name', 'is_enable')},
},
),
]

@ -0,0 +1,16 @@
# Generated by Django 3.0.3 on 2021-05-19 15:53
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('api', '0047_domaincnameinfo_userdomaininfo'),
]
operations = [
migrations.AlterUniqueTogether(
name='userdomaininfo',
unique_together=set(),
),
]

@ -0,0 +1,16 @@
# Generated by Django 3.0.3 on 2021-05-19 16:53
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('api', '0048_auto_20210519_1553'),
]
operations = [
migrations.RemoveField(
model_name='userinfo',
name='domain_name',
),
]

@ -41,7 +41,7 @@ class UserInfo(AbstractUser):
date_joined = models.DateTimeField(auto_now_add=True, verbose_name="注册时间") date_joined = models.DateTimeField(auto_now_add=True, verbose_name="注册时间")
download_times = models.PositiveIntegerField(default=0, verbose_name="可用下载次数,需要用户充值") download_times = models.PositiveIntegerField(default=0, verbose_name="可用下载次数,需要用户充值")
all_download_times = models.BigIntegerField(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) # 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) history_release_limit = models.IntegerField(default=10, verbose_name="app 历史记录版本", blank=True, null=True)
storage = models.OneToOneField(to='AppStorage', related_name='app_storage', storage = models.OneToOneField(to='AppStorage', related_name='app_storage',
on_delete=models.SET_NULL, verbose_name="存储", null=True, blank=True) on_delete=models.SET_NULL, verbose_name="存储", null=True, blank=True)
@ -445,3 +445,34 @@ class CertificationInfo(models.Model):
def __str__(self): def __str__(self):
return "%s-%s" % (self.user_id, self.certification_url) return "%s-%s" % (self.user_id, self.certification_url)
class DomainCnameInfo(models.Model):
domain_record = models.CharField(max_length=128, primary_key=True, verbose_name="记录值")
ip_address = models.GenericIPAddressField(verbose_name="域名解析地址", null=False)
# reference_count = models.BigIntegerField(default=0, verbose_name="引用记录值")
is_enable = models.BooleanField(default=True, verbose_name="是否启用该解析")
description = models.TextField(verbose_name='备注', blank=True, null=True, default='')
created_time = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
class Meta:
verbose_name = '分发域名信息'
verbose_name_plural = "分发域名信息"
def __str__(self):
return "%s-%s-%s" % (self.domain_record, self.ip_address, self.is_enable)
class UserDomainInfo(models.Model):
user_id = models.ForeignKey(to="UserInfo", verbose_name="用户ID", on_delete=models.CASCADE)
cname_id = models.ForeignKey(to="DomainCnameInfo", verbose_name="cname解析ID", on_delete=models.CASCADE)
domain_name = models.CharField(verbose_name="下载页面域名", db_index=True, max_length=64, null=False, blank=False)
is_enable = models.BooleanField(default=False, verbose_name="绑定成功")
created_time = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
class Meta:
verbose_name = '分发域名绑定'
verbose_name_plural = "分发域名绑定"
def __str__(self):
return "%s-%s-%s" % (self.user_id, self.cname_id, self.domain_name)

@ -25,6 +25,7 @@ from api.views.storage import StorageView
from api.views.receiveudids import IosUDIDView from api.views.receiveudids import IosUDIDView
from api.views.order import PriceView, OrderView, PaySuccess from api.views.order import PriceView, OrderView, PaySuccess
from api.views.supersign import DeveloperView, SuperSignUsedView, AppUDIDUsedView from api.views.supersign import DeveloperView, SuperSignUsedView, AppUDIDUsedView
from api.views.domain import DomainCnameView
# router=DefaultRouter() # router=DefaultRouter()
# router.register("apps", AppsView) # router.register("apps", AppsView)
@ -54,4 +55,6 @@ urlpatterns = [
re_path("^orders$", OrderView.as_view()), re_path("^orders$", OrderView.as_view()),
re_path("^certification$", CertificationView.as_view()), re_path("^certification$", CertificationView.as_view()),
re_path(r"^pay_success/(?P<name>\w+)$", PaySuccess.as_view()), re_path(r"^pay_success/(?P<name>\w+)$", PaySuccess.as_view()),
re_path("^cname_domain$", DomainCnameView.as_view()),
] ]

@ -13,7 +13,7 @@ from api.utils.app.randomstrings import make_app_uuid, make_from_user_uuid
from api.utils.storage.caches import del_cache_response_by_short, send_msg_over_limit from api.utils.storage.caches import del_cache_response_by_short, send_msg_over_limit
from api.utils.utils import delete_app_to_dev_and_file, send_ios_developer_active_status, delete_local_files, \ from api.utils.utils import delete_app_to_dev_and_file, send_ios_developer_active_status, delete_local_files, \
download_files_form_oss, \ download_files_form_oss, \
get_developer_udided get_developer_udided, get_user_domain_name
from api.utils.baseutils import file_format_path, delete_app_profile_file, get_profile_full_path from api.utils.baseutils import file_format_path, delete_app_profile_file, get_profile_full_path
from api.utils.storage.storage import Storage from api.utils.storage.storage import Storage
from django.core.cache import cache from django.core.cache import cache
@ -214,7 +214,7 @@ def get_redirect_server_domain(request, user_obj=None, app_domain_name=None):
if app_domain_name and len(app_domain_name) > 3: if app_domain_name and len(app_domain_name) > 3:
domain_name = app_domain_name domain_name = app_domain_name
else: else:
domain_name = user_obj.domain_name domain_name = get_user_domain_name(user_obj)
elif app_domain_name and len(app_domain_name) > 3: elif app_domain_name and len(app_domain_name) > 3:
domain_name = app_domain_name domain_name = app_domain_name
else: else:

@ -11,6 +11,7 @@ from api.utils.app.randomstrings import make_app_uuid
from django.core.validators import validate_email from django.core.validators import validate_email
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
import logging import logging
from dns.resolver import Resolver
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -102,3 +103,13 @@ def format_storage_selection(storage_info_list, storage_choice_list):
if not storage_choice['storage_info']: if not storage_choice['storage_info']:
storage_choice_list.remove(storage_choice) storage_choice_list.remove(storage_choice)
return storage_choice_list return storage_choice_list
def get_cname_from_domain(domain):
dns_resolver = Resolver()
dns_resolver.nameservers = ["8.8.8.8", "8.8.4.4"]
domain = domain.lower().strip()
try:
return dns_resolver.query(domain, 'CNAME')[0].to_text()
except Exception:
return str(None)

@ -4,7 +4,7 @@ from api.utils.app.apputils import bytes2human
from api.utils.TokenManager import DownloadToken from api.utils.TokenManager import DownloadToken
from api.utils.app.supersignutils import get_redirect_server_domain from api.utils.app.supersignutils import get_redirect_server_domain
from api.utils.storage.storage import Storage from api.utils.storage.storage import Storage
from api.utils.utils import get_developer_udided, get_choices_dict, get_choices_name_from_key from api.utils.utils import get_developer_udided, get_choices_dict, get_choices_name_from_key, get_user_domain_name
from api.utils.storage.caches import get_user_free_download_times, get_user_cert_auth_status from api.utils.storage.caches import get_user_free_download_times, get_user_cert_auth_status
import os, json, logging import os, json, logging
@ -75,6 +75,11 @@ class UserInfoSerializer(serializers.ModelSerializer):
auth_status = certification_obj.status auth_status = certification_obj.status
return auth_status return auth_status
domain_name = serializers.SerializerMethodField()
def get_domain_name(self, obj):
return get_user_domain_name(obj)
class AdminUserInfoSerializer(UserInfoSerializer): class AdminUserInfoSerializer(UserInfoSerializer):
class Meta: class Meta:

@ -6,7 +6,7 @@
import os, json, requests, datetime, random import os, json, requests, datetime, random
from fir_ser.settings import SERVER_DOMAIN, CAPTCHA_LENGTH, MEDIA_ROOT from fir_ser.settings import SERVER_DOMAIN, CAPTCHA_LENGTH, MEDIA_ROOT
from api.models import APPSuperSignUsedInfo, APPToDeveloper, \ from api.models import APPSuperSignUsedInfo, APPToDeveloper, \
UDIDsyncDeveloper, UserInfo, AppReleaseInfo, AppScreenShot UDIDsyncDeveloper, UserInfo, AppReleaseInfo, AppScreenShot, UserDomainInfo
from api.utils.storage.caches import get_app_d_count_by_app_id from api.utils.storage.caches import get_app_d_count_by_app_id
from api.utils.storage.localApi import LocalStorage from api.utils.storage.localApi import LocalStorage
from api.utils.storage.storage import Storage from api.utils.storage.storage import Storage
@ -306,3 +306,10 @@ def get_choices_name_from_key(choices, key):
if choice[0] == key: if choice[0] == key:
return choice[1] return choice[1]
return '' return ''
def get_user_domain_name(obj):
domain_obj = UserDomainInfo.objects.filter(user_id=obj, is_enable=True).first()
if domain_obj:
return domain_obj.domain_name
return ''

@ -17,7 +17,7 @@ from api.utils.serializer import AppsSerializer, AppReleaseSerializer
from rest_framework.pagination import PageNumberPagination from rest_framework.pagination import PageNumberPagination
import logging import logging
from fir_ser.settings import SERVER_DOMAIN from fir_ser.settings import SERVER_DOMAIN
from api.utils.utils import delete_local_files, delete_app_screenshots_files from api.utils.utils import delete_local_files, delete_app_screenshots_files, get_user_domain_name
from api.utils.baseutils import is_valid_domain from api.utils.baseutils import is_valid_domain
from api.base_views import app_delete from api.base_views import app_delete
@ -51,7 +51,7 @@ class AppsView(APIView):
app_type = request.query_params.get("type", None) app_type = request.query_params.get("type", None)
act_type = request.query_params.get("act", None) act_type = request.query_params.get("act", None)
res = BaseResponse() res = BaseResponse()
res.hdata = {"all_hits_count": 0, "upload_domain": request.user.domain_name, res.hdata = {"all_hits_count": 0,
"ios_count": Apps.objects.filter(type=1, user_id=request.user).values('app_id').count(), "ios_count": Apps.objects.filter(type=1, user_id=request.user).values('app_id').count(),
"android_count": Apps.objects.filter(type=0, user_id=request.user).values('app_id').count()} "android_count": Apps.objects.filter(type=0, user_id=request.user).values('app_id').count()}
@ -193,7 +193,7 @@ class AppInfoView(APIView):
if domain_name == '': if domain_name == '':
apps_obj.domain_name = None apps_obj.domain_name = None
if not request.user.domain_name: if not get_user_domain_name(request.user):
apps_obj.wxeasytype = True apps_obj.wxeasytype = True
apps_obj.save() apps_obj.save()
del_cache_response_by_short(apps_obj.app_id) del_cache_response_by_short(apps_obj.app_id)
@ -211,7 +211,7 @@ class AppInfoView(APIView):
apps_obj.supersign_limit_number) apps_obj.supersign_limit_number)
apps_obj.isshow = data.get("isshow", apps_obj.isshow) apps_obj.isshow = data.get("isshow", apps_obj.isshow)
if (request.user.domain_name and len(request.user.domain_name) > 3) or ( if get_user_domain_name(request.user) or (
apps_obj.domain_name and len(apps_obj.domain_name) > 3): apps_obj.domain_name and len(apps_obj.domain_name) > 3):
apps_obj.wxeasytype = data.get("wxeasytype", apps_obj.wxeasytype) apps_obj.wxeasytype = data.get("wxeasytype", apps_obj.wxeasytype)
else: else:

@ -0,0 +1,85 @@
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# project: 3月
# author: NinEveN
# date: 2021/3/29
from rest_framework.views import APIView
from api.utils.baseutils import is_valid_domain, get_cname_from_domain
from api.utils.response import BaseResponse
from api.utils.auth import ExpiringTokenAuthentication
from rest_framework.response import Response
from api.models import UserDomainInfo, DomainCnameInfo
from django.db.models import Count
import logging
from api.utils.storage.caches import set_default_app_wx_easy
logger = logging.getLogger(__name__)
class DomainCnameView(APIView):
authentication_classes = [ExpiringTokenAuthentication, ]
def get(self, request):
res = BaseResponse()
res.data = {'domain_name': '', 'domain_record': '', 'is_enable': False}
user_domain_obj = UserDomainInfo.objects.filter(user_id=request.user).first()
if user_domain_obj:
res.data['domain_name'] = user_domain_obj.domain_name
res.data['is_enable'] = user_domain_obj.is_enable
if user_domain_obj.cname_id:
res.data['domain_record'] = user_domain_obj.cname_id.domain_record
return Response(res.dict)
def post(self, request):
res = BaseResponse()
domain_name = request.data.get("domain_name", None)
if domain_name:
domain_name = domain_name.strip(" ")
if domain_name and len(domain_name) > 3 and is_valid_domain(domain_name):
if UserDomainInfo.objects.filter(domain_name=domain_name, is_enable=True).count() != 0:
res.code = 1001
res.msg = "该域名已经被绑定,请更换其他域名"
else:
user_domian_obj = UserDomainInfo.objects.filter(user_id=request.user, domain_name=domain_name).first()
if user_domian_obj:
res.data = {'cname_domain': user_domian_obj.cname_id.domain_record}
else:
UserDomainInfo.objects.filter(user_id=request.user, is_enable=False).delete()
min_domian_cname_info_obj = min(
DomainCnameInfo.objects.annotate(Count('userdomaininfo')).filter(is_enable=True),
key=lambda x: x.userdomaininfo__count)
if min_domian_cname_info_obj:
res.data = {'cname_domain': min_domian_cname_info_obj.domain_record}
UserDomainInfo.objects.create(user_id=request.user, cname_id=min_domian_cname_info_obj,
domain_name=domain_name)
else:
res.code = 1002
res.msg = "该域名校验失败,请检查"
return Response(res.dict)
def put(self, request):
res = BaseResponse()
user_domian_obj = UserDomainInfo.objects.filter(user_id=request.user).first()
if user_domian_obj:
cname = get_cname_from_domain(user_domian_obj.domain_name)
if cname == user_domian_obj.cname_id.domain_record + '.':
user_domian_obj.is_enable = True
user_domian_obj.save()
UserDomainInfo.objects.filter(domain_name=user_domian_obj.domain_name, is_enable=False).delete()
set_default_app_wx_easy(request.user, True)
else:
res.code = 1003
res.msg = "系统未检出到您的CNAME记录"
else:
res.code = 1004
res.msg = "域名已经被绑定或者域名有误"
return Response(res.dict)
def delete(sele, request):
res = BaseResponse()
if UserDomainInfo.objects.filter(user_id=request.user).delete()[0]:
set_default_app_wx_easy(request.user)
return Response(res.dict)

@ -397,38 +397,38 @@ class UserInfoView(APIView):
res.code = 1004 res.code = 1004
res.msg = "老密码校验失败" res.msg = "老密码校验失败"
else: else:
# 修改个人资料 # # 修改个人资料
domain_name = data.get("domain_name", None) # domain_name = data.get("domain_name", None)
if domain_name: # if domain_name:
domain_name_list = domain_name.strip(' ').replace("http://", "").replace("https://", "").split("/") # domain_name_list = domain_name.strip(' ').replace("http://", "").replace("https://", "").split("/")
if len(domain_name_list) > 0: # if len(domain_name_list) > 0:
domain_name = domain_name_list[0] # domain_name = domain_name_list[0]
if len(domain_name) > 3 and is_valid_domain(domain_name): # if len(domain_name) > 3 and is_valid_domain(domain_name):
if domain_name == SERVER_DOMAIN.get("REDIRECT_UDID_DOMAIN").split("//")[1]: # if domain_name == SERVER_DOMAIN.get("REDIRECT_UDID_DOMAIN").split("//")[1]:
user_admin_obj = UserInfo.objects.filter(is_superuser=True, uid=request.user.uid).order_by( # user_admin_obj = UserInfo.objects.filter(is_superuser=True, uid=request.user.uid).order_by(
'pk').first() # 'pk').first()
if user_admin_obj: # if user_admin_obj:
request.user.domain_name = domain_name # request.user.domain_name = domain_name
set_default_app_wx_easy(request.user, True) # set_default_app_wx_easy(request.user, True)
else: # else:
serializer = UserInfoSerializer(request.user) # serializer = UserInfoSerializer(request.user)
res.data = serializer.data # res.data = serializer.data
res.code = 1004 # res.code = 1004
res.msg = "域名设置失败,请更换其他域名" # res.msg = "域名设置失败,请更换其他域名"
return Response(res.dict) # return Response(res.dict)
else: # else:
request.user.domain_name = domain_name # request.user.domain_name = domain_name
set_default_app_wx_easy(request.user, True) # set_default_app_wx_easy(request.user, True)
else: # else:
serializer = UserInfoSerializer(request.user) # serializer = UserInfoSerializer(request.user)
res.data = serializer.data # res.data = serializer.data
res.code = 1004 # res.code = 1004
res.msg = "域名校验失败" # res.msg = "域名校验失败"
return Response(res.dict) # return Response(res.dict)
#
if domain_name == '': # if domain_name == '':
request.user.domain_name = None # request.user.domain_name = None
set_default_app_wx_easy(request.user) # set_default_app_wx_easy(request.user)
username = data.get("username", None) username = data.get("username", None)
if username and username != request.user.username: if username and username != request.user.username:

Loading…
Cancel
Save