69 lines
3.3 KiB
Python
69 lines
3.3 KiB
Python
from rest_framework import serializers
|
|
from .models import GmailCredential
|
|
import json
|
|
|
|
class GmailCredentialSerializer(serializers.ModelSerializer):
|
|
client_secret_json = serializers.JSONField(write_only=True, required=False, allow_null=True)
|
|
client_secret_file = serializers.FileField(write_only=True, required=False, allow_null=True)
|
|
auth_code = serializers.CharField(write_only=True, required=False, allow_blank=True)
|
|
email = serializers.EmailField(required=False, allow_blank=True) # Make email optional
|
|
|
|
class Meta:
|
|
model = GmailCredential
|
|
fields = ['id', 'email', 'is_default', 'created_at', 'updated_at', 'is_valid',
|
|
'client_secret_json', 'client_secret_file', 'auth_code']
|
|
read_only_fields = ['created_at', 'updated_at', 'is_valid']
|
|
|
|
def validate(self, data):
|
|
"""Validate client_secret input (either JSON or file)."""
|
|
client_secret_json = data.get('client_secret_json')
|
|
client_secret_file = data.get('client_secret_file')
|
|
auth_code = data.get('auth_code')
|
|
|
|
# For auth initiation, only client_secret is required
|
|
if not auth_code: # Initiation phase
|
|
if not client_secret_json and not client_secret_file:
|
|
raise serializers.ValidationError(
|
|
"Either client_secret_json or client_secret_file is required."
|
|
)
|
|
if client_secret_json and client_secret_file:
|
|
raise serializers.ValidationError(
|
|
"Provide only one of client_secret_json or client_secret_file."
|
|
)
|
|
|
|
# For auth completion, both auth_code and client_secret are required
|
|
if auth_code and not (client_secret_json or client_secret_file):
|
|
raise serializers.ValidationError(
|
|
"client_secret_json or client_secret_file is required with auth_code."
|
|
)
|
|
|
|
# Parse client_secret_json if provided
|
|
if client_secret_json:
|
|
try:
|
|
json.dumps(client_secret_json)
|
|
except (TypeError, ValueError):
|
|
raise serializers.ValidationError("client_secret_json must be valid JSON.")
|
|
|
|
# Parse client_secret_file if provided
|
|
if client_secret_file:
|
|
try:
|
|
content = client_secret_file.read().decode('utf-8')
|
|
client_secret_json = json.loads(content)
|
|
data['client_secret_json'] = client_secret_json
|
|
except (json.JSONDecodeError, UnicodeDecodeError):
|
|
raise serializers.ValidationError("client_secret_file must contain valid JSON.")
|
|
|
|
return data
|
|
|
|
def validate_email(self, value):
|
|
"""Ensure email is unique for the user (only for completion)."""
|
|
if not value: # Email is optional during initiation
|
|
return value
|
|
user = self.context['request'].user
|
|
if self.instance: # Update case
|
|
if GmailCredential.objects.filter(user=user, email=value).exclude(id=self.instance.id).exists():
|
|
raise serializers.ValidationError("This Gmail account is already added.")
|
|
else: # Create case
|
|
if GmailCredential.objects.filter(user=user, email=value).exists():
|
|
raise serializers.ValidationError("This Gmail account is already added.")
|
|
return value |