Skip to content

enhancement: Add file upload to backend API for Secret attachments #141

@kevalyq

Description

@kevalyq

Context

PR #140 implemented frontend file sharing via Share Target API with POST method support. Files are currently:

  • ✅ Received from OS share menu
  • ✅ Validated (type, size)
  • ✅ Previewed in UI (Base64)
  • NOT uploaded to backend

Problem

Files shared to the PWA are only displayed locally and lost on page reload (sessionStorage). Users cannot:

  • Attach files to Secrets
  • Store files permanently
  • Share files with other devices
  • Access shared files offline (beyond session)

Dependencies

UNBLOCKED: Backend API is now complete!

Required Backend Issues (completed):

Status: Ready to start implementation (19.11.2025)

Proposed Solution

NOTE: This is the frontend integration for the backend API implemented in SecPal/api#175.

Frontend Integration

Extend ShareTarget.tsx to integrate with backend API:

// 1. Provide "Save to Secret" button
// 2. Upload files via backend API (POST /api/v1/secrets/{id}/attachments)
// 3. Show upload progress
// 4. Handle upload errors
// 5. Display success message with link to secret

Data Flow

  1. User shares file from OS → PWA receives via Share Target API
  2. User selects/creates Secret → File uploaded to backend (Phase 2: File Attachments API (Upload/Download/Encryption) api#175)
  3. Backend encrypts file and stores metadata
  4. File appears in Secret's attachment list
  5. User can download/preview file later

Tasks

Backend API Endpoints (provided by SecPal/api#175)

// Upload file to secret
POST /api/v1/secrets/{secretId}/attachments
Content-Type: multipart/form-data

// Response
{
  "data": {
    "id": "uuid",
    "filename": "document.pdf",
    "size": 1024000,
    "mime_type": "application/pdf",
    "created_at": "2025-11-16T10:00:00Z"
  }
}

// List attachments
GET /api/v1/secrets/{secretId}/attachments

// Download attachment
GET /api/v1/attachments/{attachmentId}/download

// Delete attachment
DELETE /api/v1/attachments/{attachmentId}

Technical Implementation Notes

API Integration

// services/secretApi.ts
export async function uploadAttachment(
  secretId: string,
  file: File
): Promise<AttachmentResponse> {
  const formData = new FormData();
  formData.append('file', file);

  const response = await fetch(`/api/v1/secrets/${secretId}/attachments`, {
    method: 'POST',
    headers: getAuthHeaders(), // Exclude Content-Type for FormData
    body: formData,
  });

  if (!response.ok) {
    throw new Error(`Upload failed: ${response.statusText}`);
  }

  return response.json();
}

ShareTarget Component Updates

// Add to ShareTarget.tsx
const [selectedSecretId, setSelectedSecretId] = useState<string | null>(null);
const [uploadProgress, setUploadProgress] = useState<Map<string, number>>(new Map());
const [uploadErrors, setUploadErrors] = useState<Map<string, string>>(new Map());

async function handleUploadFiles() {
  if (!sharedData?.files || !selectedSecretId) return;
  
  for (const file of sharedData.files) {
    try {
      setUploadProgress(prev => new Map(prev).set(file.name, 0));
      await uploadAttachment(selectedSecretId, file);
      setUploadProgress(prev => new Map(prev).set(file.name, 100));
    } catch (error) {
      setUploadErrors(prev => new Map(prev).set(file.name, error.message));
    }
  }
}

Benefits

  • 🔐 Secure file storage with encryption
  • 📎 Attach files to Secrets
  • 🔄 Sync files across devices
  • 💾 Persistent storage (not just sessionStorage)

Non-Goals (Handled by Other Issues)

References

Priority

High - Backend API is complete, frontend integration can now proceed.

Implementation Order:

  1. ✅ Share Target POST method (PR feat: Add POST method file sharing support to Share Target API (#101) #140 - merged)
  2. ✅ Backend Secret Model (Phase 1: Secret Model + CRUD API (Backend Foundation) api#174 - merged)
  3. ✅ Backend File API (Phase 2: File Attachments API (Upload/Download/Encryption) api#175 - merged)
  4. 🔄 Frontend Integration (this issue - READY TO START)

Part of: #64 (PWA Infrastructure Epic)

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    Status

    ✅ Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions