Composables

useFogliAcl

ACL foglio. CRUD permessi lettura/scrittura per utente.

Signature

function useFogliAcl(): UseFogliAclReturn

Gestisce le ACL (Access Control List) di un foglio: lista permessi attivi e CRUD su foglidicalcoloacl.

Risultato

interface UseFogliAclReturn {
  acl: Ref<FoglioAcl[]>
  isLoading: Ref<boolean>
  isSaving: Ref<boolean>
  error: Ref<string | null>
  load(idfolio: number): Promise<void>
  aggiungi(idfolio: number, idutente: number, permesso: 'lettura' | 'scrittura'): Promise<void>
  modifica(idacl: number, permesso: 'lettura' | 'scrittura'): Promise<void>
  rimuovi(idacl: number): Promise<void>
}

FoglioAcl

interface FoglioAcl {
  idacl: number
  idfolio: number
  idutente: number
  permesso: 'lettura' | 'scrittura'
  datacreazione: string         // ISO 8601
  nomeUtente?: string           // join opzionale lato vista (es. join su anagrafica)
}

Modello permessi

Tre livelli di permesso effettivo, calcolati server-side dalla vista v_foglidicalcolo_lista:

PermessoOrigineCapabilities
proprietariofoglidicalcolo.idproprietario = $current_userTutto: read/write/share/delete
scritturaRiga in foglidicalcoloacl con permesso='scrittura'Read + write (no share/delete)
letturaRiga in foglidicalcoloacl con permesso='lettura' o ispubblico=trueSolo read

Operazioni

load(idfolio)

GET /foglidicalcoloacl?idfolio=eq.{id} con Accept-Profile: foglidicalcolo. Popola acl.value.

aggiungi(idfolio, idutente, permesso)

POST /foglidicalcoloacl con { idfolio, idutente, permesso }. La riga creata viene aggiunta a acl.value.

await aclComposable.aggiungi(42, 15, 'scrittura')
// → POST { idfolio: 42, idutente: 15, permesso: 'scrittura' }
Il backend rifiuta l'INSERT se l'utente corrente non è proprietario del foglio. L'errore PostgREST viene propagato in error.value.

modifica(idacl, permesso)

PATCH /foglidicalcoloacl?idacl=eq.{id} con { permesso }. Aggiorna la riga in acl.value.

await aclComposable.modifica(123, 'lettura')
// → PATCH /foglidicalcoloacl?idacl=eq.123 con { permesso: 'lettura' }

rimuovi(idacl)

DELETE /foglidicalcoloacl?idacl=eq.{id}. Rimuove la riga da acl.value.

Pattern: dialog ACL

<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { useFogliAcl } from '@pzeta/vue-foglidicalcolo'

const props = defineProps<{ idfolio: number }>()

const acl = useFogliAcl()
await acl.load(props.idfolio)

const utenteSelezionato = ref<number | null>(null)
const permessoSelezionato = ref<'lettura' | 'scrittura'>('lettura')

async function condividi() {
  if (utenteSelezionato.value === null) return
  await acl.aggiungi(props.idfolio, utenteSelezionato.value, permessoSelezionato.value)
}
</script>

<template>
  <ul>
    <li v-for="a in acl.acl.value" :key="a.idacl">
      {{ a.nomeUtente ?? `Utente ${a.idutente}` }} — {{ a.permesso }}

      <select :value="a.permesso" @change="acl.modifica(a.idacl, $event.target.value)">
        <option value="lettura">Lettura</option>
        <option value="scrittura">Scrittura</option>
      </select>

      <button @click="acl.rimuovi(a.idacl)">Rimuovi</button>
    </li>
  </ul>

  <form @submit.prevent="condividi">
    <!-- lookup utente esterno (es. <SelectRemote> di @pzeta/vue-form) -->
    <select v-model="permessoSelezionato">
      <option value="lettura">Lettura</option>
      <option value="scrittura">Scrittura</option>
    </select>
    <button type="submit" :disabled="acl.isSaving.value">Aggiungi</button>
  </form>

  <p v-if="acl.error.value" class="text-red-600">{{ acl.error.value }}</p>
</template>

Pubblicazione foglio

Il flag foglidicalcolo.ispubblico è separato dalle ACL. Quando attivato, tutti gli utenti della shell ottengono permesso_effettivo = 'lettura' anche senza essere nella ACL. Gestiscilo via FogliPostgrestService.aggiornaDati(idfolio, { ispubblico: true }), non via useFogliAcl.

Tipi correlati