Compare commits

..

2 Commits

Author SHA1 Message Date
Matthieu 01856b147c fix(rbac) : gate les listes Gitea/BookStack par projects.manage (et non ROLE_USER)
Suite à la revue de sécurité : ROLE_ADMIN était trop strict (les ressources
sœurs sont en ROLE_USER) mais ROLE_USER brut est trop permissif — ces endpoints
listent TOUS les dépôts/étagères visibles par le token d'intégration global, sans
filtrage par utilisateur. Comme ils ne sont consommés que par le ProjectDrawer
(configuration du dépôt/étagère d'un projet), on les gate sur la permission métier
project-management.projects.manage. Les admins conservent l'accès via le bypass
ROLE_ADMIN du PermissionVoter.
2026-06-29 11:23:56 +02:00
Matthieu 4a1d611d3c fix(rbac) : ouvre la liste des repos Gitea et des étagères BookStack aux ROLE_USER
GiteaRepository (/gitea/repositories) et BookStackShelf (/bookstack/shelves)
étaient gardés par ROLE_ADMIN alors que toutes leurs ressources sœurs (branches,
pull requests, recherche, liens) sont en ROLE_USER. Un utilisateur non-admin
pouvait donc consommer les sous-ressources mais récupérait un 403 en listant les
dépôts / étagères racines. Aligné sur ROLE_USER (les *Settings et *TestConnection
restent ROLE_ADMIN : configuration réservée à l'admin).
2026-06-29 11:19:12 +02:00
4 changed files with 6 additions and 11 deletions
+1 -1
View File
@@ -1,2 +1,2 @@
parameters:
app.version: '0.4.53'
app.version: '0.4.49'
+5 -8
View File
@@ -60,16 +60,13 @@ const { sections } = useSidebar()
const isEmployee = computed(() => Boolean(auth.user?.isEmployee))
const { can } = usePermissions()
// L'onglet Messagerie est rendu côté layout (hors sidebar backend) : il faut donc
// reproduire ici le gate de permission. ROLE_ADMIN bypasse via can().
const isMailVisible = computed(() => can('mail.access'))
const isMailVisible = computed(() => {
const roles: string[] = auth.user?.roles ?? []
return roles.includes('ROLE_USER') || roles.includes('ROLE_ADMIN')
})
const { enabled: shareEnabled, ensureLoaded: ensureShareStatus } = useShareStatus()
// Documents = explorateur de partage : visible si le module est actif ET la
// permission d'accès au partage est accordée (alignement avec le middleware de page).
const isDocumentsVisible = computed(() => shareEnabled.value === true && can('integration.share.access'))
const isDocumentsVisible = computed(() => shareEnabled.value === true)
const currentProjectId = computed(() => {
const match = route.path.match(/^\/projects\/(\d+)/)
-1
View File
@@ -6,7 +6,6 @@ const { t } = useI18n()
const router = useRouter()
const route = useRoute()
definePageMeta({ middleware: ['permission'], permission: 'mail.access' })
useHead({ title: t('mail.title') })
// ─── Store ────────────────────────────────────────────────────────────────
-1
View File
@@ -85,7 +85,6 @@ import type { Breadcrumb, FileEntry } from '~/modules/integration/services/dto/s
import { useShareService } from '~/modules/integration/services/share'
import { formatFileSize } from '~/utils/format'
definePageMeta({ middleware: ['permission'], permission: 'integration.share.access' })
useHead({ title: 'Documents' })
const { browse, search } = useShareService()