679 lines
18 KiB
Python
679 lines
18 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""
|
|
domain_info_api.py
|
|
"""
|
|
from __future__ import print_function, unicode_literals, absolute_import, division
|
|
|
|
import json
|
|
from datetime import datetime
|
|
from operator import itemgetter
|
|
|
|
from flask import request, g
|
|
from peewee import fn
|
|
from playhouse.shortcuts import model_to_dict
|
|
|
|
from domain_admin.enums.operation_enum import OperationEnum
|
|
from domain_admin.enums.role_enum import RoleEnum
|
|
from domain_admin.model.domain_info_model import DomainInfoModel
|
|
from domain_admin.model.domain_model import DomainModel
|
|
from domain_admin.model.group_model import GroupModel
|
|
from domain_admin.model.group_user_model import GroupUserModel
|
|
from domain_admin.service import domain_info_service, async_task_service, file_service, group_service, \
|
|
operation_service, group_user_service, domain_service, common_service, domain_icp_service, tag_service, auth_service
|
|
from domain_admin.utils import domain_util, time_util, icp_util
|
|
from domain_admin.utils.flask_ext.app_exception import AppException, DataNotFoundAppException
|
|
from domain_admin.utils.open_api import crtsh_api
|
|
|
|
|
|
@auth_service.permission(role=RoleEnum.USER)
|
|
@operation_service.operation_log_decorator(
|
|
model=DomainInfoModel,
|
|
operation_type_id=OperationEnum.CREATE,
|
|
primary_key='domain_info_id'
|
|
)
|
|
def add_domain_info():
|
|
"""
|
|
添加域名
|
|
:return:
|
|
"""
|
|
|
|
current_user_id = g.user_id
|
|
|
|
domain = request.json['domain']
|
|
root_domain = domain_util.get_root_domain(domain)
|
|
if not root_domain:
|
|
raise AppException("不能解析根域名:{}".format(domain))
|
|
else:
|
|
domain = root_domain
|
|
|
|
domain_start_time = request.json.get('domain_start_time')
|
|
domain_expire_time = request.json.get('domain_expire_time')
|
|
is_auto_update = request.json.get('is_auto_update', True)
|
|
is_auto_subdomain = request.json.get('is_auto_subdomain', False)
|
|
comment = request.json.get('comment', '')
|
|
tags = request.json.get('tags')
|
|
icp_company = request.json.get('icp_company', '')
|
|
icp_licence = request.json.get('icp_licence', '')
|
|
group_id = request.json.get('group_id') or 0
|
|
user_id = request.json.get('user_id')
|
|
|
|
row = domain_info_service.add_domain_info(
|
|
domain=domain,
|
|
domain_start_time=domain_start_time,
|
|
domain_expire_time=domain_expire_time,
|
|
comment=comment,
|
|
tags=tags,
|
|
group_id=group_id,
|
|
user_id=user_id or current_user_id,
|
|
icp_company=icp_company,
|
|
icp_licence=icp_licence,
|
|
is_auto_update=is_auto_update
|
|
)
|
|
|
|
# 异步提交
|
|
if is_auto_subdomain:
|
|
domain_service.auto_import_from_domain_async(
|
|
root_domain=domain,
|
|
group_id=group_id,
|
|
user_id=current_user_id
|
|
)
|
|
# async_task_service.submit_task(
|
|
# fn=domain_service.auto_import_from_domain,
|
|
# root_domain=domain,
|
|
# group_id=group_id,
|
|
# user_id=current_user_id
|
|
# )
|
|
|
|
tag_service.add_tags(tags)
|
|
|
|
return {'domain_info_id': row.id}
|
|
|
|
|
|
@auth_service.permission(role=RoleEnum.USER)
|
|
@operation_service.operation_log_decorator(
|
|
model=DomainInfoModel,
|
|
operation_type_id=OperationEnum.UPDATE,
|
|
primary_key='domain_info_id'
|
|
)
|
|
def update_domain_info_by_id():
|
|
"""
|
|
更新数据
|
|
:return:
|
|
"""
|
|
|
|
current_user_id = g.user_id
|
|
|
|
domain_info_id = request.json['domain_info_id']
|
|
|
|
domain = domain_util.get_root_domain(request.json['domain'])
|
|
domain_start_time = request.json.get('domain_start_time')
|
|
domain_expire_time = request.json.get('domain_expire_time')
|
|
is_auto_update = request.json.get('is_auto_update', True)
|
|
is_auto_subdomain = request.json.get('is_auto_subdomain', False)
|
|
comment = request.json.get('comment', '')
|
|
group_id = request.json.get('group_id') or 0
|
|
tags = request.json.get('tags')
|
|
icp_company = request.json.get('icp_company', '')
|
|
icp_licence = request.json.get('icp_licence', '')
|
|
user_id = request.json.get('user_id')
|
|
|
|
# check data
|
|
domain_info_row = DomainInfoModel.select().where(
|
|
DomainInfoModel.id == domain_info_id,
|
|
DomainInfoModel.user_id == current_user_id
|
|
).first()
|
|
|
|
if not domain_info_row:
|
|
raise DataNotFoundAppException()
|
|
|
|
# is_auto_update = request.json.get('is_auto_update', True)
|
|
# is_expire_monitor = request.json.get('is_expire_monitor', True)
|
|
|
|
data = {
|
|
'domain': domain,
|
|
'comment': comment,
|
|
'group_id': group_id,
|
|
'tags_raw': json.dumps(tags, ensure_ascii=False),
|
|
'icp_company': icp_company,
|
|
'icp_licence': icp_licence,
|
|
'is_auto_update': is_auto_update
|
|
}
|
|
|
|
# 不自动更新,才可以提交开始时间和结束时间
|
|
if is_auto_update is False:
|
|
data['domain_start_time'] = domain_start_time
|
|
data['domain_expire_time'] = domain_expire_time
|
|
|
|
if domain_expire_time:
|
|
data['domain_expire_days'] = time_util.get_diff_days(datetime.now(),
|
|
time_util.parse_time(domain_expire_time))
|
|
else:
|
|
data['domain_expire_days'] = 0
|
|
|
|
if user_id:
|
|
data['user_id'] = user_id
|
|
|
|
DomainInfoModel.update(data).where(
|
|
DomainInfoModel.id == domain_info_id
|
|
).execute()
|
|
|
|
if domain_info_row.domain != domain and is_auto_update:
|
|
# 需要自动更新
|
|
domain_info_service.update_domain_info_row(domain_info_row)
|
|
|
|
if is_auto_subdomain:
|
|
domain_service.auto_import_from_domain_async(
|
|
root_domain=domain,
|
|
group_id=group_id,
|
|
user_id=current_user_id
|
|
)
|
|
#
|
|
# async_task_service.submit_task(
|
|
# fn=domain_service.auto_import_from_domain,
|
|
# root_domain=domain,
|
|
# group_id=group_id,
|
|
# user_id=current_user_id
|
|
# )
|
|
|
|
tag_service.add_tags(tags)
|
|
|
|
|
|
@auth_service.permission(role=RoleEnum.USER)
|
|
@operation_service.operation_log_decorator(
|
|
model=DomainInfoModel,
|
|
operation_type_id=OperationEnum.UPDATE,
|
|
primary_key='domain_info_id'
|
|
)
|
|
def update_domain_info_field_by_id():
|
|
"""
|
|
更新单个数据
|
|
:return:
|
|
"""
|
|
|
|
current_user_id = g.user_id
|
|
|
|
domain_info_id = request.json['domain_info_id']
|
|
field = request.json.get('field')
|
|
value = request.json.get('value')
|
|
|
|
if field not in ['is_auto_update', 'is_expire_monitor']:
|
|
raise AppException("not allow field")
|
|
|
|
data = {
|
|
field: value,
|
|
}
|
|
|
|
# check data
|
|
domain_info_row = DomainInfoModel.select().where(
|
|
DomainInfoModel.id == domain_info_id,
|
|
DomainInfoModel.user_id == current_user_id
|
|
).first()
|
|
|
|
if not domain_info_row:
|
|
raise DataNotFoundAppException()
|
|
|
|
DomainInfoModel.update(data).where(
|
|
DomainInfoModel.id == domain_info_row.id
|
|
).execute()
|
|
|
|
|
|
@auth_service.permission(role=RoleEnum.USER)
|
|
@operation_service.operation_log_decorator(
|
|
model=DomainInfoModel,
|
|
operation_type_id=OperationEnum.DELETE,
|
|
primary_key='domain_info_id'
|
|
)
|
|
def delete_domain_info_by_id():
|
|
"""
|
|
删除
|
|
:return:
|
|
"""
|
|
current_user_id = g.user_id
|
|
|
|
domain_info_id = request.json['domain_info_id']
|
|
|
|
# check data
|
|
domain_info_row = DomainInfoModel.select().where(
|
|
DomainInfoModel.id == domain_info_id,
|
|
DomainInfoModel.user_id == current_user_id
|
|
).first()
|
|
|
|
if not domain_info_row:
|
|
raise DataNotFoundAppException()
|
|
|
|
DomainInfoModel.delete_by_id(domain_info_row.id)
|
|
|
|
|
|
@auth_service.permission(role=RoleEnum.USER)
|
|
@operation_service.operation_log_decorator(
|
|
model=DomainInfoModel,
|
|
operation_type_id=OperationEnum.BATCH_DELETE,
|
|
primary_key='domain_info_ids'
|
|
)
|
|
def delete_domain_info_by_ids():
|
|
"""
|
|
批量删除
|
|
"""
|
|
current_user_id = g.user_id
|
|
|
|
domain_info_ids = request.json['domain_info_ids']
|
|
|
|
DomainInfoModel.delete().where(
|
|
DomainInfoModel.id.in_(domain_info_ids),
|
|
DomainInfoModel.user_id == current_user_id
|
|
).execute()
|
|
|
|
|
|
@auth_service.permission(role=RoleEnum.USER)
|
|
def get_domain_info_by_id():
|
|
"""
|
|
获取
|
|
:return:
|
|
"""
|
|
current_user_id = g.user_id
|
|
|
|
domain_info_id = request.json['domain_info_id']
|
|
|
|
# check data
|
|
if g.current_user_row.role == RoleEnum.ADMIN:
|
|
domain_info_row = DomainInfoModel.select().where(
|
|
DomainInfoModel.id == domain_info_id
|
|
).first()
|
|
else:
|
|
domain_info_row = DomainInfoModel.select().where(
|
|
DomainInfoModel.id == domain_info_id,
|
|
DomainInfoModel.user_id == current_user_id
|
|
).first()
|
|
|
|
if not domain_info_row:
|
|
raise DataNotFoundAppException()
|
|
|
|
domain_row = model_to_dict(
|
|
model=domain_info_row,
|
|
extra_attrs=[
|
|
'real_domain_expire_days',
|
|
'update_time_label',
|
|
'tags',
|
|
],
|
|
exclude=['tags_raw'],
|
|
)
|
|
|
|
# 主机数量
|
|
ssl_count = DomainModel.select().where(
|
|
DomainModel.root_domain == domain_row['domain'],
|
|
DomainModel.user_id == current_user_id
|
|
).count()
|
|
|
|
domain_row['ssl_count'] = ssl_count
|
|
domain_row['group_name'] = group_service.get_group_name_by_id(domain_row['group_id'])
|
|
|
|
# 编辑权限
|
|
group_user_permission_map = group_user_service.get_group_user_permission_map(current_user_id)
|
|
|
|
if domain_row['user_id'] == current_user_id:
|
|
has_edit_permission = True
|
|
else:
|
|
has_edit_permission = group_user_permission_map.get(domain_row['group_id'], False)
|
|
|
|
domain_row['has_edit_permission'] = has_edit_permission
|
|
|
|
common_service.load_user_name([domain_row])
|
|
|
|
return domain_row
|
|
|
|
|
|
@auth_service.permission(role=RoleEnum.USER)
|
|
def update_domain_info_row_by_id():
|
|
"""
|
|
更新当前行的域名信息
|
|
:return:
|
|
"""
|
|
current_user_id = g.user_id
|
|
|
|
domain_info_id = request.json['domain_info_id']
|
|
|
|
# check data
|
|
domain_info_row = DomainInfoModel.select().where(
|
|
DomainInfoModel.id == domain_info_id,
|
|
DomainInfoModel.user_id == current_user_id
|
|
).first()
|
|
|
|
if not domain_info_row:
|
|
raise DataNotFoundAppException()
|
|
|
|
domain_info_service.update_domain_info_row(row=domain_info_row)
|
|
|
|
|
|
@auth_service.permission(role=RoleEnum.USER)
|
|
def update_all_domain_info_of_user():
|
|
"""
|
|
更新当前用户的域名信息
|
|
:return:
|
|
"""
|
|
current_user_id = g.user_id
|
|
|
|
domain_info_service.update_all_domain_info_of_user(user_id=current_user_id)
|
|
# async_task_service.submit_task(fn=domain_info_service.update_all_domain_info_of_user, user_id=current_user_id)
|
|
|
|
|
|
@auth_service.permission(role=RoleEnum.USER)
|
|
def update_all_domain_icp_of_user():
|
|
"""
|
|
更新当前用户的域名icp信息
|
|
:return:
|
|
"""
|
|
current_user_id = g.user_id
|
|
|
|
domain_info_service.update_all_domain_icp_of_user(current_user_id)
|
|
|
|
# async_task_service.submit_task(fn=domain_info_service.update_all_domain_icp_of_user, user_id=current_user_id)
|
|
|
|
|
|
@auth_service.permission(role=RoleEnum.USER)
|
|
def update_domain_row_icp():
|
|
"""
|
|
更新当前域名icp信息
|
|
:return:
|
|
"""
|
|
current_user_id = g.user_id
|
|
|
|
domain_info_id = request.json['domain_info_id']
|
|
|
|
# check data
|
|
domain_info_row = DomainInfoModel.select().where(
|
|
DomainInfoModel.id == domain_info_id,
|
|
DomainInfoModel.user_id == current_user_id
|
|
).first()
|
|
|
|
if not domain_info_row:
|
|
raise DataNotFoundAppException()
|
|
|
|
domain_info_service.update_domain_row_icp(row=domain_info_row)
|
|
|
|
|
|
@auth_service.permission(role=RoleEnum.USER)
|
|
def import_domain_info_from_file():
|
|
"""
|
|
从文件导入域名
|
|
支持格式: txt、xlsx、csv
|
|
:return:
|
|
"""
|
|
current_user_id = g.user_id
|
|
|
|
update_file = request.files.get('file')
|
|
|
|
filename = file_service.save_temp_file(update_file)
|
|
|
|
# 导入数据
|
|
domain_info_service.add_domain_from_file(filename, current_user_id)
|
|
|
|
# 异步查询
|
|
domain_info_service.handle_auto_import_domain_info(current_user_id)
|
|
# async_task_service.submit_task(fn=domain_info_service.update_all_domain_info_of_user, user_id=current_user_id)
|
|
|
|
|
|
@auth_service.permission(role=RoleEnum.USER)
|
|
def export_domain_info_file():
|
|
"""
|
|
导出域名文件
|
|
csv格式
|
|
:return:
|
|
"""
|
|
current_user_id = g.user_id
|
|
|
|
keyword = request.json.get('keyword')
|
|
group_ids = request.json.get('group_ids')
|
|
domain_expire_days = request.json.get('domain_expire_days')
|
|
role = request.json.get('role')
|
|
ext = request.json.get('ext', 'csv')
|
|
|
|
order_prop = request.json.get('order_prop') or 'domain_expire_days'
|
|
order_type = request.json.get('order_type') or 'ascending'
|
|
|
|
params = {
|
|
'keyword': keyword,
|
|
'group_ids': group_ids,
|
|
'domain_expire_days': domain_expire_days,
|
|
'role': role,
|
|
'user_id': current_user_id
|
|
}
|
|
|
|
# 列表数据
|
|
query = domain_info_service.get_domain_info_query(**params)
|
|
|
|
ordering = domain_info_service.get_ordering(order_prop=order_prop, order_type=order_type)
|
|
|
|
rows = query.order_by(*ordering)
|
|
|
|
lst = [model_to_dict(
|
|
model=row,
|
|
extra_attrs=[
|
|
'domain_start_date',
|
|
'domain_expire_date',
|
|
'real_domain_expire_days',
|
|
'update_time_label',
|
|
'tags',
|
|
'tags_str',
|
|
]
|
|
) for row in rows]
|
|
|
|
# 分组名
|
|
group_service.load_group_name(lst)
|
|
|
|
filename = domain_info_service.export_domain_to_file(ext=ext, rows=lst)
|
|
|
|
return {
|
|
'name': filename,
|
|
'url': file_service.resolve_temp_url(filename)
|
|
}
|
|
|
|
|
|
@auth_service.permission(role=RoleEnum.USER)
|
|
def get_domain_info_list():
|
|
"""
|
|
获取域名列表
|
|
:return:
|
|
"""
|
|
current_user_id = g.user_id
|
|
|
|
page = request.json.get('page', 1)
|
|
size = request.json.get('size', 10)
|
|
|
|
keyword = request.json.get('keyword')
|
|
group_ids = request.json.get('group_ids')
|
|
domain_expire_days = request.json.get('domain_expire_days')
|
|
role = request.json.get('role')
|
|
|
|
order_prop = request.json.get('order_prop') or 'domain_expire_days'
|
|
order_type = request.json.get('order_type') or 'ascending'
|
|
|
|
group_user_permission_map = {}
|
|
|
|
if role == RoleEnum.ADMIN:
|
|
pass
|
|
|
|
else:
|
|
# 所在分组
|
|
group_user_rows = GroupUserModel.select().where(
|
|
GroupUserModel.user_id == current_user_id
|
|
)
|
|
|
|
group_user_list = list(group_user_rows)
|
|
# 组员权限
|
|
group_user_permission_map = {row.group_id: row.has_edit_permission for row in group_user_list}
|
|
|
|
params = {
|
|
'keyword': keyword,
|
|
'group_ids': group_ids,
|
|
'domain_expire_days': domain_expire_days,
|
|
'role': role,
|
|
'user_id': current_user_id
|
|
}
|
|
|
|
# 列表数据
|
|
query = domain_info_service.get_domain_info_query(**params)
|
|
|
|
total = query.count()
|
|
|
|
lst = []
|
|
if total > 0:
|
|
|
|
ordering = domain_info_service.get_ordering(order_prop=order_prop, order_type=order_type)
|
|
|
|
rows = query.order_by(*ordering).paginate(page, size)
|
|
|
|
lst = [model_to_dict(
|
|
model=row,
|
|
extra_attrs=[
|
|
'real_domain_expire_days',
|
|
'update_time_label',
|
|
'tags',
|
|
]
|
|
) for row in rows]
|
|
|
|
domain_list = [row['domain'] for row in lst]
|
|
|
|
# 域名证书
|
|
root_domain_groups = DomainModel.select(
|
|
DomainModel.root_domain,
|
|
fn.COUNT(DomainModel.id).alias('count')
|
|
).where(
|
|
DomainModel.root_domain.in_(domain_list),
|
|
DomainModel.user_id == current_user_id
|
|
).group_by(DomainModel.root_domain)
|
|
|
|
root_domain_groups_map = {
|
|
row.root_domain: row.count
|
|
for row in root_domain_groups
|
|
}
|
|
|
|
for row in lst:
|
|
row['ssl_count'] = root_domain_groups_map.get(row['domain'], 0)
|
|
|
|
if role == RoleEnum.ADMIN:
|
|
has_edit_permission = True
|
|
|
|
elif row['user_id'] == current_user_id:
|
|
has_edit_permission = True
|
|
else:
|
|
has_edit_permission = group_user_permission_map.get(row['group_id'], False)
|
|
|
|
row['has_edit_permission'] = has_edit_permission
|
|
|
|
# 分组名
|
|
group_service.load_group_name(lst)
|
|
# 用户名
|
|
common_service.load_user_name(lst)
|
|
|
|
return {
|
|
'list': lst,
|
|
'total': total,
|
|
}
|
|
|
|
|
|
@auth_service.permission(role=RoleEnum.USER)
|
|
def get_domain_info_group_filter():
|
|
"""
|
|
获取域名分组筛选器
|
|
:return:
|
|
"""
|
|
|
|
current_user_id = g.user_id
|
|
|
|
# 分组列表数据
|
|
query = GroupModel.select().where(
|
|
GroupModel.user_id == current_user_id
|
|
)
|
|
|
|
total = query.count()
|
|
lst = []
|
|
if total > 0:
|
|
|
|
# 证书分组统计
|
|
cert_groups = DomainInfoModel.select(
|
|
DomainInfoModel.group_id,
|
|
fn.COUNT(DomainInfoModel.id).alias('count')
|
|
).group_by(DomainInfoModel.group_id)
|
|
|
|
groups_map = {
|
|
str(row.group_id): row.count
|
|
for row in cert_groups
|
|
}
|
|
|
|
lst = []
|
|
for row in query:
|
|
row_dict = model_to_dict(row)
|
|
row_dict['domain_count'] = groups_map.get(str(row.id), 0)
|
|
lst.append(row_dict)
|
|
|
|
if groups_map.get('0'):
|
|
lst.append({
|
|
'domain_count': groups_map.get('0'),
|
|
'id': 0,
|
|
'name': '未分组',
|
|
})
|
|
|
|
lst.sort(key=itemgetter('domain_count'), reverse=True)
|
|
|
|
return {
|
|
'list': lst,
|
|
'total': len(lst),
|
|
}
|
|
|
|
|
|
@auth_service.permission(role=RoleEnum.USER)
|
|
def get_icp():
|
|
"""
|
|
查询icp信息
|
|
"""
|
|
domain = request.json['domain']
|
|
|
|
# 解析域名
|
|
resolve_domain = domain_util.parse_domain(domain)
|
|
|
|
item = domain_icp_service.get_domain_icp(resolve_domain)
|
|
|
|
if not item:
|
|
raise AppException('没有查到icp信息')
|
|
|
|
res = item.to_dict()
|
|
res['resolve_domain'] = resolve_domain
|
|
|
|
return res
|
|
|
|
|
|
@auth_service.permission(role=RoleEnum.USER)
|
|
def get_sub_domain_cert():
|
|
"""
|
|
获取子域证书列表
|
|
:return:
|
|
"""
|
|
keyword = request.json.get('keyword', 1)
|
|
|
|
lst = crtsh_api.search(keyword)
|
|
|
|
return {
|
|
'list': lst,
|
|
'total': len(lst)
|
|
}
|
|
|
|
|
|
@auth_service.permission(role=RoleEnum.USER)
|
|
def auto_import_subdomain_by_ids():
|
|
"""
|
|
批量导入子域证书
|
|
@since v1.6.30
|
|
:return:
|
|
"""
|
|
current_user_id = g.user_id
|
|
|
|
domain_ids = request.json['domain_ids']
|
|
|
|
rows = DomainInfoModel.select().where(
|
|
DomainInfoModel.id.in_(domain_ids),
|
|
DomainInfoModel.user_id == current_user_id
|
|
)
|
|
|
|
# 异步提交
|
|
domain_service.auto_import_from_domain_batch_async(rows=rows, user_id=current_user_id)
|