Skip to content

Phase 4: Secret Sharing UI #195

@kevalyq

Description

@kevalyq

🎯 Goal

Implement UI for sharing secrets with users and roles, including permission management (read/write/admin), expiration dates, and revoking access.


🔗 Parent Epic

Part of: #191 (Secret Management Frontend)


📋 Tasks

Share Dialog Component

  • Create ShareDialog.tsx modal component
  • User/Role selector (searchable dropdown)
  • Permission dropdown (read/write/admin)
  • Expiration date picker (optional)
  • Share button with loading state
  • Cancel button
  • Error handling
  • Accessibility (ARIA labels, focus management)

Shared-With List Component

  • Create SharedWithList.tsx component
  • Display list of users/roles with access
  • Show permission level per share
  • Show expiration date (if set)
  • Show granted by (user)
  • Show granted at (date)
  • Add "Revoke" button per share (with confirmation)
  • Empty state ("Not shared with anyone")

Integration with Secret Detail

  • Add "Share" button to SecretDetail.tsx (if admin permission)
  • Open share dialog on button click
  • Display SharedWithList on detail page
  • Refresh list after share/revoke

Integration with Secret List

  • Show shared indicator icon on SecretCard.tsx
  • Filter by "owned" vs "shared" secrets

API Service Extensions

  • Create services/shareApi.ts
  • Implement listShares(secretId) function
  • Implement createShare(secretId, data) function
  • Implement revokeShare(secretId, shareId) function
  • Add TypeScript interfaces for share types
  • Add error handling (400, 401, 403, 404, 422)

Tests

  • Unit tests for shareApi.ts (≥80% coverage)
  • Component tests for ShareDialog.tsx
  • Component tests for SharedWithList.tsx
  • Integration test: Share → View list flow
  • Integration test: Revoke → Update list flow

🎨 UI Mockup

Share Dialog

┌─────────────────────────────────────────────────────────┐
│ Share "Gmail Account"                           [✕]     │
├─────────────────────────────────────────────────────────┤
│ Share with:                                             │
│ [Search users or roles...       ▾]                      │
│                                                         │
│ Permission:                                             │
│ [Read ▾]                                                │
│                                                         │
│ Expires (optional):                                     │
│ [2025-12-31] [📅]                                       │
│                                                         │
│ Permission Levels:                                      │
│ • Read: View secret details                             │
│ • Write: View + edit secret                             │
│ • Admin: View + edit + share + delete                   │
│                                                         │
│                              [Cancel] [Share]           │
└─────────────────────────────────────────────────────────┘

Shared-With List (in Secret Detail)

┌─────────────────────────────────────────────────────────┐
│ Shared with: (3)                                        │
├─────────────────────────────────────────────────────────┤
│ 👤 John Doe (read)                          [Revoke]    │
│    Granted by You on 2025-11-01                         │
│                                                         │
│ 👤 Jane Smith (write)                       [Revoke]    │
│    Granted by Admin on 2025-11-15                       │
│    Expires: 2025-12-31                                  │
│                                                         │
│ 👥 Admins (admin)                           [Revoke]    │
│    Granted by You on 2025-10-20                         │
└─────────────────────────────────────────────────────────┘

🔗 API Endpoints (Backend)

// List shares for secret
GET /api/v1/secrets/{secretId}/shares

Response: 200 OK
{
  "data": [
    {
      "id": "uuid",
      "secret_id": "uuid",
      "user_id": "uuid", // or null if role_id is set
      "role_id": null,   // or role ID if user_id is null
      "permission": "read", // or "write", "admin"
      "granted_by": "uuid",
      "granted_at": "2025-11-01T10:00:00Z",
      "expires_at": "2025-12-31T23:59:59Z" // or null
    }
  ]
}

// Create share
POST /api/v1/secrets/{secretId}/shares
Body:
{
  "user_id": "uuid",        // XOR with role_id
  "role_id": null,
  "permission": "read",     // or "write", "admin"
  "expires_at": "2025-12-31T23:59:59Z" // optional
}

Response: 201 Created
{
  "data": { ...created share... }
}

// Revoke share
DELETE /api/v1/secrets/{secretId}/shares/{shareId}

Response: 204 No Content

✅ Acceptance Criteria

  • Share dialog opens correctly
  • User/Role selector searches and displays results
  • Permission dropdown works (read/write/admin)
  • Expiration date picker works
  • Share creates successfully via API
  • Shared-with list displays all shares
  • Revoke button works (with confirmation)
  • Share indicator shows on secret cards
  • Filter by owned/shared secrets works
  • All tests pass (≥80% coverage)
  • Accessibility: Keyboard navigation
  • Accessibility: Focus management in modal

🔒 Security Notes

  • ⚠️ Only secret owner can share (admin permission)
  • ⚠️ Respect XOR constraint (user OR role, not both)
  • ⚠️ Validate permission hierarchy (admin > write > read)
  • ⚠️ Show/hide Share button based on user permission
  • ⚠️ Confirm before revoking access

📊 Estimated Effort

Size: ~400-500 LOC (excluding tests)
Time: 3-4 days
PR Count: 1 PR


🔗 Dependencies


🔗 Blocks

  • Phase 5 (Offline Support & PWA Integration)

Type: Sub-Issue of #191
Priority: High
Estimated Effort: M (3-4 days)

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    Status

    ✅ Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions