v0.0.22 | NHN Cloud 프로젝트 수정 API 추가
Some checks failed
Build And Test / build-and-push (push) Failing after 49s

- PUT /api/auth/nhn-cloud/projects/{id}/ 수정 API
- GET /api/auth/nhn-cloud/projects/{id}/ 상세 조회 API
- 프로젝트 생성 로직 수정 (encrypted_password 설정)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-14 21:43:02 +09:00
parent c97b3c6c3b
commit e102d6766a
2 changed files with 95 additions and 3 deletions

View File

@ -503,7 +503,9 @@ class NHNCloudProjectListView(APIView):
storage_account=storage_account, storage_account=storage_account,
is_active=is_first, is_active=is_first,
) )
project.save_credentials(password) # 암호화된 비밀번호 설정 후 저장
project.encrypted_password = project.encrypt_password(password)
project.save()
logger.info( logger.info(
f"[NHN PROJECT CREATE] user={email} | project={name} | is_active={is_first} | IP={ip} | UA={ua}" f"[NHN PROJECT CREATE] user={email} | project={name} | is_active={is_first} | IP={ip} | UA={ua}"
@ -528,7 +530,7 @@ class NHNCloudProjectListView(APIView):
class NHNCloudProjectDetailView(APIView): class NHNCloudProjectDetailView(APIView):
"""NHN Cloud 프로젝트 상세 (삭제)""" """NHN Cloud 프로젝트 상세 (조회/수정/삭제)"""
permission_classes = [IsAuthenticated] permission_classes = [IsAuthenticated]
def get_project(self, request, project_id): def get_project(self, request, project_id):
@ -538,6 +540,96 @@ class NHNCloudProjectDetailView(APIView):
except NHNCloudProject.DoesNotExist: except NHNCloudProject.DoesNotExist:
return None return None
def get(self, request, project_id):
"""프로젝트 상세 조회"""
with tracer.start_as_current_span("NHNCloudProjectDetailView GET") as span:
email, ip, ua = get_request_info(request)
project = self.get_project(request, project_id)
if not project:
return Response({"error": "프로젝트를 찾을 수 없습니다."}, status=404)
span.add_event("NHN project retrieved", attributes={"email": email, "project": project.name})
return Response({
"id": project.id,
"name": project.name,
"tenant_id": project.tenant_id,
"username": project.username,
"storage_account": project.storage_account or "",
"is_active": project.is_active,
"created_at": project.created_at.isoformat(),
})
def put(self, request, project_id):
"""프로젝트 수정"""
with tracer.start_as_current_span("NHNCloudProjectDetailView PUT") as span:
email, ip, ua = get_request_info(request)
project = self.get_project(request, project_id)
if not project:
logger.warning(
f"[NHN PROJECT UPDATE] user={email} | status=fail | reason=not_found | IP={ip} | UA={ua}"
)
return Response({"error": "프로젝트를 찾을 수 없습니다."}, status=404)
# 수정 가능한 필드
name = request.data.get("name")
tenant_id = request.data.get("tenant_id")
username = request.data.get("username")
password = request.data.get("password") # 비어있으면 변경 안함
storage_account = request.data.get("storage_account")
# 필수 필드 검증
if not name or not tenant_id or not username:
return Response(
{"error": "name, tenant_id, username은 필수입니다."},
status=status.HTTP_400_BAD_REQUEST,
)
# tenant_id 중복 체크 (자기 자신 제외)
if NHNCloudProject.objects.filter(
user=request.user, tenant_id=tenant_id
).exclude(id=project_id).exists():
return Response(
{"error": "이미 등록된 Tenant ID입니다."},
status=status.HTTP_400_BAD_REQUEST,
)
try:
project.name = name
project.tenant_id = tenant_id
project.username = username
if storage_account is not None:
project.storage_account = storage_account
# 비밀번호가 제공된 경우에만 변경
if password:
project.encrypted_password = project.encrypt_password(password)
project.save()
logger.info(
f"[NHN PROJECT UPDATE] user={email} | project={name} | IP={ip} | UA={ua}"
)
span.add_event("NHN project updated", attributes={"email": email, "project": name})
return Response({
"id": project.id,
"name": project.name,
"tenant_id": project.tenant_id,
"username": project.username,
"storage_account": project.storage_account or "",
"is_active": project.is_active,
"created_at": project.created_at.isoformat(),
})
except Exception as e:
logger.exception(
f"[NHN PROJECT UPDATE] user={email} | status=fail | reason=exception | IP={ip} | UA={ua}"
)
return Response({"error": f"프로젝트 수정 실패: {str(e)}"}, status=500)
def delete(self, request, project_id): def delete(self, request, project_id):
"""프로젝트 삭제""" """프로젝트 삭제"""
with tracer.start_as_current_span("NHNCloudProjectDetailView DELETE") as span: with tracer.start_as_current_span("NHNCloudProjectDetailView DELETE") as span:

View File

@ -1 +1 @@
v0.0.21 v0.0.22