mirror of
https://github.com/opsre/LiteOps.git
synced 2026-02-20 22:11:09 +08:00
392 lines
14 KiB
Python
392 lines
14 KiB
Python
import json
|
|
import uuid
|
|
import hashlib
|
|
import logging
|
|
from django.http import JsonResponse
|
|
from django.views import View
|
|
from django.utils.decorators import method_decorator
|
|
from django.views.decorators.csrf import csrf_exempt
|
|
from django.db import transaction
|
|
from django.db.models import Q
|
|
from ..models import Project, User
|
|
from ..utils.auth import jwt_auth_required
|
|
from ..utils.permissions import get_user_permissions
|
|
|
|
logger = logging.getLogger('apps')
|
|
|
|
def generate_id():
|
|
"""生成唯一ID"""
|
|
return hashlib.sha256(str(uuid.uuid4()).encode()).hexdigest()[:32]
|
|
|
|
@method_decorator(csrf_exempt, name='dispatch')
|
|
class ProjectView(View):
|
|
@method_decorator(jwt_auth_required)
|
|
def get(self, request):
|
|
"""获取项目列表"""
|
|
try:
|
|
# 获取当前用户的权限信息
|
|
user_permissions = get_user_permissions(request.user_id)
|
|
data_permissions = user_permissions.get('data', {})
|
|
|
|
# 检查用户是否有项目查看权限
|
|
function_permissions = user_permissions.get('function', {})
|
|
project_permissions = function_permissions.get('project', [])
|
|
|
|
if 'view' not in project_permissions:
|
|
logger.warning(f'用户[{request.user_id}]没有项目查看权限')
|
|
return JsonResponse({
|
|
'code': 403,
|
|
'message': '没有权限查看项目'
|
|
}, status=403)
|
|
|
|
project_id = request.GET.get('project_id')
|
|
name = request.GET.get('name')
|
|
category = request.GET.get('category')
|
|
|
|
# 构建查询条件
|
|
query = Q()
|
|
|
|
if project_id:
|
|
query &= Q(project_id=project_id)
|
|
if name:
|
|
query &= Q(name__icontains=name) # 使用 icontains 进行不区分大小写的模糊查询
|
|
if category:
|
|
query &= Q(category=category)
|
|
|
|
# 应用项目权限过滤
|
|
project_scope = data_permissions.get('project_scope', 'all')
|
|
if project_scope == 'custom':
|
|
permitted_project_ids = data_permissions.get('project_ids', [])
|
|
if not permitted_project_ids:
|
|
# 如果设置了自定义项目权限但列表为空,意味着没有权限查看任何项目
|
|
logger.info(f'用户[{request.user_id}]没有权限查看任何项目')
|
|
return JsonResponse({
|
|
'code': 200,
|
|
'message': '获取项目列表成功',
|
|
'data': []
|
|
})
|
|
|
|
# 限制只能查看有权限的项目
|
|
query &= Q(project_id__in=permitted_project_ids)
|
|
|
|
# 使用查询条件过滤项目
|
|
projects = Project.objects.select_related('creator').filter(query)
|
|
|
|
project_list = []
|
|
for project in projects:
|
|
project_list.append({
|
|
'project_id': project.project_id,
|
|
'name': project.name,
|
|
'description': project.description,
|
|
'category': project.category,
|
|
'repository': project.repository,
|
|
'creator': {
|
|
'user_id': project.creator.user_id,
|
|
'username': project.creator.username,
|
|
'name': project.creator.name
|
|
},
|
|
'create_time': project.create_time.strftime('%Y-%m-%d %H:%M:%S'),
|
|
'update_time': project.update_time.strftime('%Y-%m-%d %H:%M:%S')
|
|
})
|
|
|
|
return JsonResponse({
|
|
'code': 200,
|
|
'message': '获取项目列表成功',
|
|
'data': project_list
|
|
})
|
|
except Exception as e:
|
|
logger.error(f'获取项目列表失败: {str(e)}', exc_info=True)
|
|
return JsonResponse({
|
|
'code': 500,
|
|
'message': f'服务器错误: {str(e)}'
|
|
})
|
|
|
|
@method_decorator(jwt_auth_required)
|
|
def post(self, request):
|
|
"""创建项目"""
|
|
try:
|
|
with transaction.atomic():
|
|
data = json.loads(request.body)
|
|
name = data.get('name')
|
|
description = data.get('description')
|
|
category = data.get('category')
|
|
repository = data.get('repository')
|
|
|
|
if not name:
|
|
return JsonResponse({
|
|
'code': 400,
|
|
'message': '项目名称不能为空'
|
|
})
|
|
|
|
# 检查项目名称是否已存在
|
|
if Project.objects.filter(name=name).exists():
|
|
return JsonResponse({
|
|
'code': 400,
|
|
'message': '项目名称已存在'
|
|
})
|
|
|
|
# 创建项目
|
|
creator = User.objects.get(user_id=request.user_id)
|
|
project = Project.objects.create(
|
|
project_id=generate_id(),
|
|
name=name,
|
|
description=description,
|
|
category=category,
|
|
repository=repository,
|
|
creator=creator
|
|
)
|
|
|
|
return JsonResponse({
|
|
'code': 200,
|
|
'message': '创建项目成功',
|
|
'data': {
|
|
'project_id': project.project_id,
|
|
'name': project.name
|
|
}
|
|
})
|
|
except Exception as e:
|
|
logger.error(f'创建项目失败: {str(e)}', exc_info=True)
|
|
return JsonResponse({
|
|
'code': 500,
|
|
'message': f'服务器错误: {str(e)}'
|
|
})
|
|
|
|
@method_decorator(jwt_auth_required)
|
|
def put(self, request):
|
|
"""编辑项目"""
|
|
try:
|
|
with transaction.atomic():
|
|
data = json.loads(request.body)
|
|
project_id = data.get('project_id')
|
|
name = data.get('name')
|
|
description = data.get('description')
|
|
category = data.get('category')
|
|
repository = data.get('repository')
|
|
|
|
if not project_id:
|
|
return JsonResponse({
|
|
'code': 400,
|
|
'message': '项目ID不能为空'
|
|
})
|
|
|
|
try:
|
|
project = Project.objects.get(project_id=project_id)
|
|
except Project.DoesNotExist:
|
|
return JsonResponse({
|
|
'code': 404,
|
|
'message': '项目不存在'
|
|
})
|
|
|
|
# 检查项目名称是否已存在
|
|
if name and name != project.name:
|
|
if Project.objects.filter(name=name).exists():
|
|
return JsonResponse({
|
|
'code': 400,
|
|
'message': '项目名称已存在'
|
|
})
|
|
project.name = name
|
|
|
|
if description is not None:
|
|
project.description = description
|
|
if category:
|
|
project.category = category
|
|
if repository:
|
|
project.repository = repository
|
|
|
|
project.save()
|
|
|
|
return JsonResponse({
|
|
'code': 200,
|
|
'message': '更新项目成功'
|
|
})
|
|
except Exception as e:
|
|
logger.error(f'更新项目失败: {str(e)}', exc_info=True)
|
|
return JsonResponse({
|
|
'code': 500,
|
|
'message': f'服务器错误: {str(e)}'
|
|
})
|
|
|
|
@method_decorator(jwt_auth_required)
|
|
def delete(self, request):
|
|
"""删除项目"""
|
|
try:
|
|
with transaction.atomic():
|
|
data = json.loads(request.body)
|
|
project_id = data.get('project_id')
|
|
|
|
if not project_id:
|
|
return JsonResponse({
|
|
'code': 400,
|
|
'message': '项目ID不能为空'
|
|
})
|
|
|
|
try:
|
|
project = Project.objects.get(project_id=project_id)
|
|
project.delete()
|
|
return JsonResponse({
|
|
'code': 200,
|
|
'message': '删除项目成功'
|
|
})
|
|
except Project.DoesNotExist:
|
|
return JsonResponse({
|
|
'code': 404,
|
|
'message': '项目不存在'
|
|
})
|
|
|
|
except Exception as e:
|
|
logger.error(f'删除项目失败: {str(e)}', exc_info=True)
|
|
return JsonResponse({
|
|
'code': 500,
|
|
'message': f'服务器错误: {str(e)}'
|
|
})
|
|
|
|
|
|
@method_decorator(csrf_exempt, name='dispatch')
|
|
class ProjectServiceView(View):
|
|
@method_decorator(jwt_auth_required)
|
|
def post(self, request):
|
|
"""创建项目服务"""
|
|
try:
|
|
with transaction.atomic():
|
|
data = json.loads(request.body)
|
|
project_id = data.get('project_id')
|
|
name = data.get('name')
|
|
description = data.get('description')
|
|
category = data.get('category')
|
|
repository = data.get('repository')
|
|
|
|
if not all([project_id, name, category, repository]):
|
|
return JsonResponse({
|
|
'code': 400,
|
|
'message': '项目ID、服务名称、类别和仓库地址不能为空'
|
|
})
|
|
|
|
try:
|
|
project = Project.objects.get(project_id=project_id)
|
|
except Project.DoesNotExist:
|
|
return JsonResponse({
|
|
'code': 404,
|
|
'message': '项目不存在'
|
|
})
|
|
|
|
# 检查服务名称在项目下是否已存在
|
|
if ProjectService.objects.filter(project=project, name=name).exists():
|
|
return JsonResponse({
|
|
'code': 400,
|
|
'message': '该项目下已存在同名服务'
|
|
})
|
|
|
|
creator = User.objects.get(user_id=request.user_id)
|
|
service = ProjectService.objects.create(
|
|
service_id=generate_id(),
|
|
project=project,
|
|
name=name,
|
|
description=description,
|
|
category=category,
|
|
repository=repository,
|
|
creator=creator
|
|
)
|
|
|
|
return JsonResponse({
|
|
'code': 200,
|
|
'message': '创建服务成功',
|
|
'data': {
|
|
'service_id': service.service_id,
|
|
'name': service.name
|
|
}
|
|
})
|
|
except Exception as e:
|
|
logger.error(f'创建服务失败: {str(e)}', exc_info=True)
|
|
return JsonResponse({
|
|
'code': 500,
|
|
'message': f'服务器错误: {str(e)}'
|
|
})
|
|
|
|
@method_decorator(jwt_auth_required)
|
|
def put(self, request):
|
|
"""更新项目服务"""
|
|
try:
|
|
with transaction.atomic():
|
|
data = json.loads(request.body)
|
|
service_id = data.get('service_id')
|
|
name = data.get('name')
|
|
description = data.get('description')
|
|
category = data.get('category')
|
|
repository = data.get('repository')
|
|
|
|
if not service_id:
|
|
return JsonResponse({
|
|
'code': 400,
|
|
'message': '服务ID不能为空'
|
|
})
|
|
|
|
try:
|
|
service = ProjectService.objects.get(service_id=service_id)
|
|
except ProjectService.DoesNotExist:
|
|
return JsonResponse({
|
|
'code': 404,
|
|
'message': '服务不存在'
|
|
})
|
|
|
|
# 检查服务名称是否已存在
|
|
if name and name != service.name:
|
|
if ProjectService.objects.filter(project=service.project, name=name).exists():
|
|
return JsonResponse({
|
|
'code': 400,
|
|
'message': '该项目下已存在同名服务'
|
|
})
|
|
service.name = name
|
|
|
|
if description is not None:
|
|
service.description = description
|
|
if category:
|
|
service.category = category
|
|
if repository:
|
|
service.repository = repository
|
|
|
|
service.save()
|
|
|
|
return JsonResponse({
|
|
'code': 200,
|
|
'message': '更新服务成功'
|
|
})
|
|
except Exception as e:
|
|
logger.error(f'更新服务失败: {str(e)}', exc_info=True)
|
|
return JsonResponse({
|
|
'code': 500,
|
|
'message': f'服务器错误: {str(e)}'
|
|
})
|
|
|
|
@method_decorator(jwt_auth_required)
|
|
def delete(self, request):
|
|
"""删除项目服务"""
|
|
try:
|
|
with transaction.atomic():
|
|
data = json.loads(request.body)
|
|
service_id = data.get('service_id')
|
|
|
|
if not service_id:
|
|
return JsonResponse({
|
|
'code': 400,
|
|
'message': '服务ID不能为空'
|
|
})
|
|
|
|
try:
|
|
service = ProjectService.objects.get(service_id=service_id)
|
|
service.delete()
|
|
return JsonResponse({
|
|
'code': 200,
|
|
'message': '删除服务成功'
|
|
})
|
|
except ProjectService.DoesNotExist:
|
|
return JsonResponse({
|
|
'code': 404,
|
|
'message': '服务不存在'
|
|
})
|
|
|
|
except Exception as e:
|
|
logger.error(f'删除服务失败: {str(e)}', exc_info=True)
|
|
return JsonResponse({
|
|
'code': 500,
|
|
'message': f'服务器错误: {str(e)}'
|
|
}) |