fix: Collaboration-Rolle explizit validieren statt still auf WRITE fallen
parseCollaborationRole warnt bei fehlendem oder ungültigem role-Feld und wird bei Einladung sowie Logbuch-Sync genutzt. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -10,6 +10,7 @@ import {
|
|||||||
} from '../services/auth.js'
|
} from '../services/auth.js'
|
||||||
import { decryptJson, encryptBuffer } from '../services/crypto.js'
|
import { decryptJson, encryptBuffer } from '../services/crypto.js'
|
||||||
import { saveLogbookKey } from '../services/logbookKeys.js'
|
import { saveLogbookKey } from '../services/logbookKeys.js'
|
||||||
|
import { parseCollaborationRole } from '../services/logbook.js'
|
||||||
import { syncLogbook } from '../services/sync.js'
|
import { syncLogbook } from '../services/sync.js'
|
||||||
import { db } from '../services/db.js'
|
import { db } from '../services/db.js'
|
||||||
import { PlausibleEvents, trackPlausibleEvent } from '../services/analytics.js'
|
import { PlausibleEvents, trackPlausibleEvent } from '../services/analytics.js'
|
||||||
@@ -183,6 +184,7 @@ export default function InvitationAcceptance({ onAccepted, onCancel }: Invitatio
|
|||||||
}
|
}
|
||||||
|
|
||||||
const acceptResult = await res.json()
|
const acceptResult = await res.json()
|
||||||
|
const collaborationRole = parseCollaborationRole(acceptResult.role, 'invitation accept')
|
||||||
|
|
||||||
await saveLogbookKey(logbookId, logbookKey)
|
await saveLogbookKey(logbookId, logbookKey)
|
||||||
|
|
||||||
@@ -193,7 +195,7 @@ export default function InvitationAcceptance({ onAccepted, onCancel }: Invitatio
|
|||||||
updatedAt: new Date().toISOString(),
|
updatedAt: new Date().toISOString(),
|
||||||
isSynced: 1,
|
isSynced: 1,
|
||||||
isShared: 1,
|
isShared: 1,
|
||||||
collaborationRole: acceptResult.role === 'READ' ? 'READ' : 'WRITE'
|
collaborationRole
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,22 @@ import { PlausibleEvents, trackPlausibleEvent } from './analytics.js'
|
|||||||
const API_BASE = '/api/logbooks'
|
const API_BASE = '/api/logbooks'
|
||||||
|
|
||||||
export type LogbookAccessRole = 'OWNER' | 'READ' | 'WRITE'
|
export type LogbookAccessRole = 'OWNER' | 'READ' | 'WRITE'
|
||||||
|
export type CollaborationRole = 'READ' | 'WRITE'
|
||||||
|
|
||||||
|
/** Validates server/cached collaboration role; warns and falls back to WRITE if missing or invalid. */
|
||||||
|
export function parseCollaborationRole(role: unknown, context: string): CollaborationRole {
|
||||||
|
if (role === 'READ' || role === 'WRITE') {
|
||||||
|
return role
|
||||||
|
}
|
||||||
|
|
||||||
|
if (role === undefined || role === null || role === '') {
|
||||||
|
console.warn(`[collaboration] Missing role in ${context}; defaulting to WRITE.`)
|
||||||
|
} else {
|
||||||
|
console.warn(`[collaboration] Unexpected role in ${context}:`, role, '— defaulting to WRITE.')
|
||||||
|
}
|
||||||
|
|
||||||
|
return 'WRITE'
|
||||||
|
}
|
||||||
|
|
||||||
export interface DecryptedLogbook {
|
export interface DecryptedLogbook {
|
||||||
id: string
|
id: string
|
||||||
@@ -112,7 +128,9 @@ export async function fetchLogbooks(): Promise<DecryptedLogbook[]> {
|
|||||||
updatedAt: lb.updatedAt || new Date().toISOString(),
|
updatedAt: lb.updatedAt || new Date().toISOString(),
|
||||||
isSynced: 1,
|
isSynced: 1,
|
||||||
isShared: isShared ? 1 : 0,
|
isShared: isShared ? 1 : 0,
|
||||||
collaborationRole: isShared ? (lb.collaborators?.[0]?.role || 'WRITE') : undefined,
|
collaborationRole: isShared
|
||||||
|
? parseCollaborationRole(lb.collaborators?.[0]?.role, `fetch logbook ${lb.id}`)
|
||||||
|
: undefined,
|
||||||
isDemo: localById.get(lb.id)?.isDemo
|
isDemo: localById.get(lb.id)?.isDemo
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -138,7 +156,9 @@ export async function fetchLogbooks(): Promise<DecryptedLogbook[]> {
|
|||||||
updatedAt: lb.updatedAt,
|
updatedAt: lb.updatedAt,
|
||||||
isSynced: lb.isSynced === 1,
|
isSynced: lb.isSynced === 1,
|
||||||
isShared: lb.isShared === 1,
|
isShared: lb.isShared === 1,
|
||||||
accessRole: lb.isShared === 1 ? (lb.collaborationRole || 'WRITE') : 'OWNER',
|
accessRole: lb.isShared === 1
|
||||||
|
? parseCollaborationRole(lb.collaborationRole, `cached logbook ${lb.id}`)
|
||||||
|
: 'OWNER',
|
||||||
isDemo: lb.isDemo === 1
|
isDemo: lb.isDemo === 1
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user