From d0b3396af788eeb258af5bca5455e1c6515587ef Mon Sep 17 00:00:00 2001 From: padreug Date: Sun, 16 Nov 2025 20:54:25 +0100 Subject: [PATCH] Fix unclaim permission bug - only show button for task owner MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously, users could see and click "Unclaim" button for tasks claimed by others, leading to failed deletion attempts and temporary UI inconsistencies. Changes: - Add auth service injection to ScheduledEventCard - Add canUnclaim computed property checking if current user created the current status - Only show "Unclaim" button when canUnclaim is true (user owns the current status) - Applies NIP-09 rule: users can only delete their own events Behavior: - Alice claims task → only Alice sees "Unclaim" button - Bob marks task in-progress → only Bob sees "Unclaim" button - Prevents failed deletion attempts and optimistic update bugs - Follows Nostr protocol permissions correctly This is a quick fix. Future enhancement will track per-user status for full collaborative workflow support. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .../components/ScheduledEventCard.vue | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/modules/nostr-feed/components/ScheduledEventCard.vue b/src/modules/nostr-feed/components/ScheduledEventCard.vue index 15270fe..51c8102 100644 --- a/src/modules/nostr-feed/components/ScheduledEventCard.vue +++ b/src/modules/nostr-feed/components/ScheduledEventCard.vue @@ -17,6 +17,8 @@ import { } from '@/components/ui/collapsible' import { Calendar, MapPin, Clock, CheckCircle, PlayCircle, Hand } from 'lucide-vue-next' import type { ScheduledEvent, EventCompletion, TaskStatus } from '../services/ScheduledEventService' +import { injectService, SERVICE_TOKENS } from '@/core/di-container' +import type { AuthService } from '@/modules/base/auth/auth-service' interface Props { event: ScheduledEvent @@ -39,6 +41,9 @@ const props = withDefaults(defineProps(), { const emit = defineEmits() +// Get auth service to check current user +const authService = injectService(SERVICE_TOKENS.AUTH_SERVICE) + // Confirmation dialog state const showConfirmDialog = ref(false) @@ -66,6 +71,15 @@ const isCompletable = computed(() => props.event.eventType === 'task') // Get completion data const completion = computed(() => props.getCompletion(eventAddress.value, occurrence.value)) +// Get current user's pubkey +const currentUserPubkey = computed(() => authService?.user.value?.pubkey) + +// Check if current user can unclaim (only if they created the current status) +const canUnclaim = computed(() => { + if (!completion.value || !currentUserPubkey.value) return false + return completion.value.pubkey === currentUserPubkey.value +}) + // Status badges configuration const statusConfig = computed(() => { switch (taskStatus.value) { @@ -394,6 +408,7 @@ const dialogContent = computed(() => { Mark Complete