Respect per-user visibility; only 'vorstand' overrides visibility; UI shows contactHidden per-member
Some checks failed
Code Analysis (JS/Vue) / analyze (push) Failing after 47s
Some checks failed
Code Analysis (JS/Vue) / analyze (push) Failing after 47s
This commit is contained in:
@@ -115,7 +115,10 @@
|
||||
</div>
|
||||
</td>
|
||||
<td class="px-4 py-3 whitespace-nowrap">
|
||||
<template v-if="canViewContactData">
|
||||
<template v-if="member.contactHidden">
|
||||
<span class="text-sm text-gray-400">Kontaktdaten nur für Vorstand sichtbar</span>
|
||||
</template>
|
||||
<template v-else>
|
||||
<a
|
||||
v-if="member.email"
|
||||
:href="`mailto:${member.email}`"
|
||||
@@ -123,18 +126,14 @@
|
||||
>
|
||||
{{ member.email }}
|
||||
</a>
|
||||
<span
|
||||
v-else
|
||||
class="text-sm text-gray-400"
|
||||
>-</span>
|
||||
<span v-else class="text-sm text-gray-400">-</span>
|
||||
</template>
|
||||
<span
|
||||
v-else
|
||||
class="text-sm text-gray-400"
|
||||
>Nur für Vorstand</span>
|
||||
</td>
|
||||
<td class="px-4 py-3 whitespace-nowrap">
|
||||
<template v-if="canViewContactData">
|
||||
<template v-if="member.contactHidden">
|
||||
<span class="text-sm text-gray-400">Kontaktdaten nur für Vorstand sichtbar</span>
|
||||
</template>
|
||||
<template v-else>
|
||||
<a
|
||||
v-if="member.phone"
|
||||
:href="`tel:${member.phone}`"
|
||||
@@ -142,15 +141,8 @@
|
||||
>
|
||||
{{ member.phone }}
|
||||
</a>
|
||||
<span
|
||||
v-else
|
||||
class="text-sm text-gray-400"
|
||||
>-</span>
|
||||
<span v-else class="text-sm text-gray-400">-</span>
|
||||
</template>
|
||||
<span
|
||||
v-else
|
||||
class="text-sm text-gray-400"
|
||||
>Nur für Vorstand</span>
|
||||
</td>
|
||||
<td class="px-4 py-3 whitespace-nowrap">
|
||||
<button
|
||||
@@ -296,44 +288,22 @@
|
||||
</div>
|
||||
|
||||
<div class="grid sm:grid-cols-2 gap-3 text-gray-600">
|
||||
<template v-if="canViewContactData">
|
||||
<div
|
||||
v-if="member.email"
|
||||
class="flex items-center"
|
||||
>
|
||||
<Mail
|
||||
:size="16"
|
||||
class="mr-2 text-primary-600"
|
||||
/>
|
||||
<a
|
||||
:href="`mailto:${member.email}`"
|
||||
class="hover:text-primary-600"
|
||||
>{{ member.email }}</a>
|
||||
</div>
|
||||
<div
|
||||
v-if="member.phone"
|
||||
class="flex items-center"
|
||||
>
|
||||
<Phone
|
||||
:size="16"
|
||||
class="mr-2 text-primary-600"
|
||||
/>
|
||||
<a
|
||||
:href="`tel:${member.phone}`"
|
||||
class="hover:text-primary-600"
|
||||
>{{ member.phone }}</a>
|
||||
</div>
|
||||
</template>
|
||||
<div
|
||||
v-else
|
||||
class="col-span-2 flex items-center text-gray-500 text-sm italic"
|
||||
>
|
||||
<Mail
|
||||
:size="16"
|
||||
class="mr-2"
|
||||
/>
|
||||
<template v-if="member.contactHidden">
|
||||
<div class="col-span-2 flex items-center text-gray-500 text-sm italic">
|
||||
<Mail :size="16" class="mr-2" />
|
||||
Kontaktdaten nur für Vorstand sichtbar
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div v-if="member.email" class="flex items-center">
|
||||
<Mail :size="16" class="mr-2 text-primary-600" />
|
||||
<a :href="`mailto:${member.email}`" class="hover:text-primary-600">{{ member.email }}</a>
|
||||
</div>
|
||||
<div v-if="member.phone" class="flex items-center">
|
||||
<Phone :size="16" class="mr-2 text-primary-600" />
|
||||
<a :href="`tel:${member.phone}`" class="hover:text-primary-600">{{ member.phone }}</a>
|
||||
</div>
|
||||
</template>
|
||||
<div
|
||||
v-if="member.address"
|
||||
class="flex items-start col-span-2"
|
||||
|
||||
@@ -152,6 +152,8 @@ export default defineEventHandler(async (event) => {
|
||||
// Respektiere individuelle Sichtbarkeitspräferenzen (user.visibility)
|
||||
const currentUserToken = token
|
||||
const isViewerAuthenticated = !!currentUser
|
||||
// Only 'vorstand' may override member visibility
|
||||
const isPrivilegedViewer = currentUser ? hasRole(currentUser, 'vorstand') : false
|
||||
|
||||
const sanitizedMembers = mergedMembers.map(member => {
|
||||
// Default: show email/phone/address to other logged-in members unless member.visibility explicitly hides them
|
||||
@@ -161,6 +163,15 @@ export default defineEventHandler(async (event) => {
|
||||
const showPhone = visibility.showPhone === undefined ? true : Boolean(visibility.showPhone)
|
||||
const showAddress = visibility.showAddress === undefined ? false : Boolean(visibility.showAddress)
|
||||
|
||||
// Determine if contact info existed but was hidden to the viewer
|
||||
const hadEmail = !!member.email
|
||||
const hadPhone = !!member.phone
|
||||
const hadAddress = !!member.address
|
||||
const emailVisible = (isPrivilegedViewer || (isViewerAuthenticated && showEmail))
|
||||
const phoneVisible = (isPrivilegedViewer || (isViewerAuthenticated && showPhone))
|
||||
const addressVisible = (isPrivilegedViewer || (isViewerAuthenticated && showAddress))
|
||||
const contactHidden = (!emailVisible && hadEmail) || (!phoneVisible && hadPhone) || (!addressVisible && hadAddress)
|
||||
|
||||
return {
|
||||
id: member.id,
|
||||
name: member.name,
|
||||
@@ -172,10 +183,12 @@ export default defineEventHandler(async (event) => {
|
||||
lastLogin: member.lastLogin,
|
||||
isMannschaftsspieler: member.isMannschaftsspieler,
|
||||
notes: member.notes || '',
|
||||
// Only include contact fields when viewer is authenticated and the member allows it
|
||||
email: (isViewerAuthenticated && showEmail) ? member.email : undefined,
|
||||
phone: (isViewerAuthenticated && showPhone) ? member.phone : undefined,
|
||||
address: (isViewerAuthenticated && showAddress) ? member.address : undefined
|
||||
// Privileged viewers (vorstand) always see contact fields
|
||||
email: emailVisible ? member.email : undefined,
|
||||
phone: phoneVisible ? member.phone : undefined,
|
||||
address: addressVisible ? member.address : undefined,
|
||||
// Flag for UI: data existed but is hidden to the current viewer
|
||||
contactHidden
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -64,9 +64,10 @@ export default defineEventHandler(async (event) => {
|
||||
const visibility = body.visibility || body.visibilityPreferences || null
|
||||
if (visibility && typeof visibility === 'object') {
|
||||
user.visibility = user.visibility || {}
|
||||
if (typeof visibility.showEmail === 'boolean') user.visibility.showEmail = visibility.showEmail
|
||||
if (typeof visibility.showPhone === 'boolean') user.visibility.showPhone = visibility.showPhone
|
||||
if (typeof visibility.showAddress === 'boolean') user.visibility.showAddress = visibility.showAddress
|
||||
// Coerce values to booleans to be robust against string values from clients
|
||||
if (visibility.showEmail !== undefined) user.visibility.showEmail = Boolean(visibility.showEmail)
|
||||
if (visibility.showPhone !== undefined) user.visibility.showPhone = Boolean(visibility.showPhone)
|
||||
if (visibility.showAddress !== undefined) user.visibility.showAddress = Boolean(visibility.showAddress)
|
||||
}
|
||||
|
||||
// Handle password change
|
||||
|
||||
Reference in New Issue
Block a user