NODEDC_TASKMANAGER/plane-src/apps/api/plane/app/serializers/voice_tasker.py

96 lines
3.7 KiB
Python

# Copyright (c) 2023-present Plane Software, Inc. and contributors
# SPDX-License-Identifier: AGPL-3.0-only
# See the LICENSE file for details.
from rest_framework import serializers
from plane.db.models import Project, WorkspaceAICredential, WorkspaceAISettings
from plane.license.utils.encryption import encrypt_data
from .base import BaseSerializer
class WorkspaceAISettingsSerializer(BaseSerializer):
default_project_id = serializers.UUIDField(required=False, allow_null=True)
openai_api_key = serializers.CharField(required=False, allow_blank=True, write_only=True, trim_whitespace=False)
credential = serializers.SerializerMethodField(read_only=True)
class Meta:
model = WorkspaceAISettings
fields = [
"id",
"workspace_id",
"voice_tasker_enabled",
"provider",
"transcription_model",
"structuring_model",
"default_project_id",
"access_mode",
"max_audio_duration_seconds",
"per_user_hourly_limit",
"workspace_hourly_limit",
"credential",
"openai_api_key",
"created_at",
"updated_at",
]
read_only_fields = ["id", "workspace_id", "provider", "created_at", "updated_at", "credential"]
def get_credential(self, obj):
credential = WorkspaceAICredential.objects.filter(workspace=obj.workspace, provider=obj.provider).first()
return {
"provider": obj.provider,
"has_key": bool(credential and credential.encrypted_api_key and credential.is_active),
"key_last4": credential.key_last4 if credential else "",
"updated_at": credential.updated_at if credential else None,
}
def validate_default_project_id(self, value):
if value is None:
return None
workspace = self.context["workspace"]
if not Project.objects.filter(workspace=workspace, id=value, archived_at__isnull=True).exists():
raise serializers.ValidationError("Default project must belong to this workspace.")
return value
def validate_max_audio_duration_seconds(self, value):
if value < 10 or value > 600:
raise serializers.ValidationError("Max audio duration must be between 10 and 600 seconds.")
return value
def validate_per_user_hourly_limit(self, value):
if value < 1 or value > 1000:
raise serializers.ValidationError("Per-user hourly limit must be between 1 and 1000.")
return value
def validate_workspace_hourly_limit(self, value):
if value < 1 or value > 10000:
raise serializers.ValidationError("Workspace hourly limit must be between 1 and 10000.")
return value
def update(self, instance, validated_data):
api_key = validated_data.pop("openai_api_key", None)
default_project_id = validated_data.pop("default_project_id", serializers.empty)
if default_project_id is not serializers.empty:
instance.default_project_id = default_project_id
for key, value in validated_data.items():
setattr(instance, key, value)
instance.save()
if api_key:
cleaned_api_key = api_key.strip()
credential, _ = WorkspaceAICredential.objects.get_or_create(
workspace=instance.workspace,
provider=instance.provider,
)
credential.encrypted_api_key = encrypt_data(cleaned_api_key)
credential.key_last4 = cleaned_api_key[-4:] if len(cleaned_api_key) >= 4 else cleaned_api_key
credential.is_active = True
credential.save()
return instance