Skip to content

Commit 6742249

Browse files
author
Lasim
committed
feat: Enhance credential management by implementing team-based credential retrieval and success message handling
1 parent 780df9f commit 6742249

File tree

3 files changed

+71
-44
lines changed

3 files changed

+71
-44
lines changed

services/frontend/src/services/credentialsService.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -288,9 +288,6 @@ export class CredentialsService {
288288

289289
const response = await fetch(`${apiUrl}/api/teams/${teamId}/cloud-credentials/${credentialId}`, {
290290
method: 'DELETE',
291-
headers: {
292-
'Content-Type': 'application/json',
293-
},
294291
credentials: 'include',
295292
})
296293

services/frontend/src/views/CredentialDetail.vue

Lines changed: 41 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -42,19 +42,47 @@ const error = ref<string | null>(null)
4242
const showDeleteModal = ref(false)
4343
const isDeleting = ref(false)
4444
const deleteError = ref<string | null>(null)
45-
const successMessage = ref<string | null>(null)
4645
4746
const credentialId = route.params.id as string
4847
49-
// Fetch credential details from API
50-
async function fetchCredential(): Promise<void> {
51-
if (!selectedTeam.value) return
52-
48+
// Find which team owns the credential by trying each team
49+
async function findCredentialTeam(): Promise<void> {
5350
try {
5451
isLoading.value = true
5552
error.value = null
5653
57-
credential.value = await CredentialsService.getCredential(selectedTeam.value.id, credentialId)
54+
const userTeams = await TeamService.getUserTeams()
55+
56+
if (userTeams.length === 0) {
57+
error.value = 'No teams found for user'
58+
return
59+
}
60+
61+
// Try each team to find the one that owns this credential
62+
for (const team of userTeams) {
63+
try {
64+
const foundCredential = await CredentialsService.getCredential(team.id, credentialId)
65+
66+
// If we successfully found the credential, this is the correct team
67+
credential.value = foundCredential
68+
selectedTeam.value = team
69+
userRole.value = team.role || 'team_user'
70+
return
71+
72+
} catch (err) {
73+
// If credential not found in this team, continue to next team
74+
if (err instanceof Error && err.message.includes('not found')) {
75+
continue
76+
}
77+
// If it's a different error (auth, permissions, etc.), re-throw
78+
throw err
79+
}
80+
}
81+
82+
// If we get here, credential wasn't found in any team
83+
error.value = 'Credential not found in any of your teams'
84+
credential.value = null
85+
5886
} catch (err) {
5987
error.value = err instanceof Error ? err.message : 'An unknown error occurred'
6088
credential.value = null
@@ -63,25 +91,9 @@ async function fetchCredential(): Promise<void> {
6391
}
6492
}
6593
66-
// Initialize team context
67-
async function initializeTeamContext(): Promise<void> {
68-
try {
69-
const userTeams = await TeamService.getUserTeams()
70-
if (userTeams.length > 0) {
71-
selectedTeam.value = userTeams[0] // Default to first team
72-
userRole.value = selectedTeam.value.role || 'team_user'
73-
}
74-
} catch (error) {
75-
console.error('Error initializing team context:', error)
76-
}
77-
}
78-
7994
// Load data on component mount
8095
onMounted(async () => {
81-
await initializeTeamContext()
82-
if (selectedTeam.value) {
83-
await fetchCredential()
84-
}
96+
await findCredentialTeam()
8597
})
8698
8799
// Computed properties for display
@@ -148,16 +160,14 @@ const confirmDelete = async () => {
148160
// Emit general credentials updated event
149161
eventBus.emit('credentials-updated')
150162
151-
// Set success message
152-
successMessage.value = `Credential "${credential.value.name}" has been successfully deleted.`
153-
154-
// Close modal and navigate back to credentials list
163+
// Close modal and navigate back to credentials list with success message
155164
showDeleteModal.value = false
156165
157-
// Navigate back with a slight delay to show success message
158-
setTimeout(() => {
159-
router.push('/credentials')
160-
}, 1500)
166+
// Navigate back with success message in query params
167+
router.push({
168+
path: '/credentials',
169+
query: { deleted: credential.value.name }
170+
})
161171
162172
} catch (err) {
163173
console.error('Error deleting credential:', err)
@@ -223,14 +233,6 @@ const handleUpdateSecrets = () => {
223233
</DropdownMenu>
224234
</div>
225235

226-
<!-- Success Message -->
227-
<Alert v-if="successMessage" class="mb-4">
228-
<CheckCircle class="h-4 w-4" />
229-
<AlertDescription>
230-
{{ successMessage }}
231-
</AlertDescription>
232-
</Alert>
233-
234236
<!-- Loading State -->
235237
<div v-if="isLoading" class="text-muted-foreground">
236238
{{ t('credentials.detail.loading') }}

services/frontend/src/views/Credentials.vue

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
<script setup lang="ts">
22
import { ref, onMounted, onUnmounted, computed, watch } from 'vue'
33
import { useI18n } from 'vue-i18n'
4-
import { useRouter } from 'vue-router'
4+
import { useRouter, useRoute } from 'vue-router'
55
import { Input } from '@/components/ui/input'
66
import { Button } from '@/components/ui/button'
7-
import { Plus, Loader2, Search } from 'lucide-vue-next'
7+
import { Alert, AlertDescription } from '@/components/ui/alert'
8+
import { Plus, Loader2, Search, CheckCircle } from 'lucide-vue-next'
89
import DashboardLayout from '@/components/DashboardLayout.vue'
910
import { CredentialsService } from '@/services/credentialsService'
1011
import { UserService } from '@/services/userService'
@@ -27,6 +28,7 @@ function debounce<T extends (...args: any[]) => any>(func: T, wait: number): T {
2728
2829
const { t } = useI18n()
2930
const router = useRouter()
31+
const route = useRoute()
3032
const eventBus = useEventBus()
3133
3234
// State
@@ -39,6 +41,7 @@ const showAddModal = ref(false)
3941
const canCreateCredentials = ref(false)
4042
const userPermissions = ref<string[]>([])
4143
const searchQuery = ref('')
44+
const deleteSuccessMessage = ref<string | null>(null)
4245
4346
// Team context (same pattern as teams page)
4447
const selectedTeam = ref<Team | null>(null)
@@ -190,8 +193,27 @@ const handleCredentialCreated = async () => {
190193
eventBus.emit('credentials-updated')
191194
}
192195
196+
// Check for delete success message from query params
197+
const checkDeleteSuccess = () => {
198+
const deletedCredentialName = route.query.deleted as string
199+
if (deletedCredentialName) {
200+
deleteSuccessMessage.value = `Credential "${deletedCredentialName}" has been successfully deleted.`
201+
202+
// Clear the query parameter from URL
203+
router.replace({ path: '/credentials' })
204+
205+
// Clear the message after 5 seconds
206+
setTimeout(() => {
207+
deleteSuccessMessage.value = null
208+
}, 5000)
209+
}
210+
}
211+
193212
// Load data on component mount
194213
onMounted(async () => {
214+
// Check for delete success message first
215+
checkDeleteSuccess()
216+
195217
await Promise.all([
196218
checkPermissions(),
197219
initializeSelectedTeam()
@@ -238,6 +260,12 @@ onUnmounted(() => {
238260
</Button>
239261
</div>
240262

263+
<!-- Delete Success Message -->
264+
<Alert v-if="deleteSuccessMessage" class="border-green-200 bg-green-50 text-green-800">
265+
<CheckCircle class="h-4 w-4" />
266+
<AlertDescription>{{ deleteSuccessMessage }}</AlertDescription>
267+
</Alert>
268+
241269
<!-- No team selected state -->
242270
<div v-if="!selectedTeam" class="text-center py-12">
243271
<p class="text-muted-foreground">{{ t('credentials.permissions.noAccess') }}</p>

0 commit comments

Comments
 (0)