Oprávnění

Jaká oprávnění potřebují návrháři a uživatelé a jak je řízen zápis konfigurace.

Přehled modelu

Konfigurace formuláře je soubor v knihovně Site Assets, takže ji chrání oprávnění SharePointu. Model má tři vrstvy:

  1. Kdo smí otevřít návrháře (role návrháře v konfiguraci): vlastníci webu, nebo vlastníci a vybraná skupina návrhářů.
  2. Kdo smí konfiguraci zapsat: určuje zámek složky SiteAssets/FormCustomizer (unikátní oprávnění).
  3. Kdo ji smí číst: běh formuláře čte konfiguraci jako přihlášený uživatel, proto musí mít čtení každý, kdo formulář otevírá.

Heslo „zámek editoru“ v návrháři není bezpečnostní hranice. Chrání před nechtěným otevřením editoru, ne před čtením nebo přepsáním souboru. Skutečnou ochranu dává pouze zámek složky popsaný níže.

Tlačítko Nastavení formuláře (ozubené kolo) a příkaz Vlastní formulář vidí jen oprávnění uživatelé. Role se nastavuje v konfiguraci (securityConfig.allowedEditorRole, viz Zabezpečení konfigurace a uživatelská stránka o zabezpečení).

Hodnota allowedEditorRoleKdo smí návrháře otevřít
manageWeb (výchozí pro nové formuláře)Vlastníci webu: uživatelé s oprávněním ManageWeb na seznamu.
groupVlastníci webu a členové SharePoint skupiny z allowedEditorGroup (podle názvu skupiny).
manageLists (starší hodnota)Chová se jako manageWeb: konfiguraci mění vlastníci webu. Samotné oprávnění „Správa seznamů“ nestačí, protože ho má i člen s úrovní Upravit.

Oprávnění se ověřuje voláním effectiveBasePermissions seznamu a členství ve skupinách. Selže-li ověření (chyba REST), tlačítka se nezobrazí a uživatel se považuje za neoprávněného.

Pro samotné zamčení úložiště je potřeba oprávnění ManagePermissions na webu (vlastník webu). Návrhář ze skupiny může konfiguraci ukládat, ale oprávnění složek měnit nemůže.

Vytváření sloupců z návrháře

Nový sloupec seznamu smí z návrháře založit jen uživatel s oprávněním ManageLists (Správa seznamů) na seznamu. Oprávnění se bere z pageContext.list.permissions a poskytovatel dat ho hlásí jako canCreateFields; bez něj se akce vytvoření sloupce nenabízí. Je to samostatné od role návrháře výše: sloupec se vytváří pod identitou přihlášeného uživatele, takže ho SharePoint stejně nepustí bez práv. Sloupec se přidá jen do typů obsahu, které uživatel vybral. Selže-li přidání do některého typu (např. chybí oprávnění na typ obsahu), sloupec v seznamu zůstane a návrhář vypíše, kam se nepřidal.

Zamčené úložiště konfigurace

Dokud je úložiště nezamčené, dědí složka oprávnění knihovny Site Assets. Kdokoli s oprávněním zapisovat do knihovny (typicky člen webu s úrovní Upravit) pak může konfiguraci přepsat, a tím i podstrčit vlastní akce. Zámek tomu brání.

Co zámek dělá

Kořenová složka SiteAssets/FormCustomizer dostane unikátní oprávnění:

  1. Rozpojí se dědičnost s kopií dosavadních oprávnění (čtenáři nepřijdou o přístup).
  2. Skupina vlastníků webu a přihlášený uživatel, který zamyká, dostanou Full Control.
  3. Všem ostatním principálům se ponechá jen Read a Limited Access. Cokoli víc (Contribute, Edit, Design i vlastní role s oprávněním Správa seznamů nebo Správa oprávnění) se nahradí rolí Read. Role se určují podle typu, ne podle jazykového názvu.
  4. Pro celou organizaci (Everyone except external users, EEEU) a pro hosty (Everyone) se přidá Read. Obojí lze v návrháři vypnout: Čtení konfigurace pro celou organizaci (securityConfig.configReadAllUsers) a Čtení konfigurace i pro externí uživatele (hosty) (securityConfig.configReadGuests); výchozí je zapnuto.
  5. Vnořené položky s vlastními oprávněními se vrátí k dědění z kořene. Výjimkou jsou podsložky seznamů (viz dále).

Přístup se při změnách nejdřív přidává a teprve potom ubírá, takže nikdo nepřijde dočasně o čtení. Když zamčení selže, původní dědičnost se vrátí. Když se nepodaří ani návrat, zobrazí návrhář varování s příkazem pro opravu.

Součástí zámku je úklid vnořených položek pod FormCustomizer, které mají vlastní oprávnění (vrátí se k dědění). Dotaz najde vnořené položky podle FileRef a u každé zvlášť přečte příznak vlastních oprávnění (HasUniqueRoleAssignments). Pokud odpověď SharePointu některý z nich neobsahuje, zámek skončí chybou lockFailed a nic se nepovažuje za bezpečné.

Návrhář, Zabezpečení, sekce „Úložiště konfigurace“: stav „Zamčeno: zápis mají jen vlastníci webu a skupina návrhářů“, přepínače čtení pro organizaci a hosty a tlačítko Zamknout nyní
Stránka „Oprávnění“ složky FormCustomizer v Site Assets (Spravovat přístup) po zamčení: Full Control pro vlastníky, Read pro ostatní a organizaci

Kdy se zamkne

Neoprávněný uživatel (návrhář bez práva měnit oprávnění) zamknout nemůže. Návrhář dostane po uložení do nezamčeného úložiště varování „Úložiště konfigurace není zamčené“ s příkazem pro vlastníka.

Sladění oprávnění při dalším uložení

Když je úložiště už zamčené, vlastník webu při uložení konfigurace oprávnění znovu nenastavuje, pokud se nezměnily jeho vstupy: přihlášený vlastník, skupina návrhářů, čtení pro organizaci a pro hosty a tenant. Uložení je tak rychlé a nespouští desítky REST volání. Otisk těchto vstupů se ukládá do souboru SiteAssets/FormCustomizer/<listId>.perm.json v kořeni úložiště, do kterého smí zapisovat jen vlastník, takže přežije načtení stránky a návrhář ho nemůže podvrhnout. Zapíše se až po čistém sladění, tedy bez chyby a bez varování.

Potvrzení při prvním zamčení

Pokud konfigurační soubor vznikl před zámkem (nebo se importuje ze starého umístění), mohl ho do té doby změnit kdokoli. Builder proto před zapečetěním ukáže dialog Zamknout a uložit tuto konfiguraci? s bezpečnostním souhrnem:

Teprve po Potvrdit, zamknout a uložit se úložiště zapečetí. Při „Zamknout nyní“ nad existujícím souborem se nabízí Zamknout a zapečetit stávající soubor. Nedůvěřujete-li obsahu, zrušte dialog a formulář uložte z návrháře: soubor se přepíše vaším konceptem. Při prvním zamčení se navíc smaže historie z doby před zámkem a záloha se nahradí zapečetěným souborem.

Dialog „Zamknout a uložit tuto konfiguraci?“ se souhrnem: zdroj souboru, skripty, tlačítka s akcemi, pravidla, role a skupina návrhářů a tlačítka Potvrdit, zamknout a uložit / Zrušit

Skupina návrhářů

Chcete-li konfiguraci svěřit i lidem, kteří nejsou vlastníky webu, nastavte roli group a název SharePoint skupiny (allowedEditorGroup).

Odmítnuté skupiny

Uložení se odmítne a oprávnění se nezmění, pokud je skupina návrhářů:

Skupina, která na webu neexistuje, se uloží s varováním „skupina návrhářů … na webu neexistuje“: nemá zápis. Zkontrolujte přesný název.

Licenční soubor

Soubor license.txt leží přímo v kořenové složce FormCustomizer, takže po zamčení dědí její oprávnění: zapsat ho smí jen vlastník webu, členové a návrháři dostanou 403 a dialog licence jim to vysvětlí. Čtení zůstává všem (licence se čte i neoprávněným uživatelem). Je-li úložiště nezamčené, může soubor přepsat každý s právem zápisu do Site Assets, ale klíč je podepsaný, takže vlastní platný klíč nelze podvrhnout. Viz Licence.

Ruční zamčení a oprava v PowerShellu

Návrhář nabízí příkaz v části Zabezpečení, sekci Úložiště konfigurace, a zobrazí ho i varování po uložení (notLocked, lockFailed, rollbackFailed). Příkaz je určený pro PnP.PowerShell a vlastníka webu. Podsložku seznamu doplní, pokud je zvolena skupina návrhářů. V ukázce jsou zástupné hodnoty, skutečný příkaz si zkopírujte z návrháře (obsahuje URL webu, <listId> a název skupiny).

Connect-PnPOnline -Url "https://<tenant>.sharepoint.com/sites/<site>" -Interactive
$web = Get-PnPWeb -Includes AssociatedOwnerGroup,CurrentUser,RoleDefinitions
$ctx = Get-PnPContext
$role = { param($t) $web.RoleDefinitions | Where-Object { $_.RoleTypeKind -eq $t } | Select-Object -First 1 }
$full = & $role "Administrator"; $read = & $role "Reader"; $contrib = & $role "Contributor"
function Grant($item, $principal, $def) {
  $b = New-Object Microsoft.SharePoint.Client.RoleDefinitionBindingCollection($ctx); $b.Add($def)
  $null = $item.RoleAssignments.Add($principal, $b)
}
# 1) kořen FormCustomizer: rozpojit dědičnost S kopií (čtenáři nepřijdou o přístup)
$root = (Get-PnPFolder -Url "/sites/<site>/SiteAssets/FormCustomizer" -Includes ListItemAllFields).ListItemAllFields
$root.BreakRoleInheritance($true, $true); Invoke-PnPQuery
# 2) vlastníci a spouštějící uživatel = Full Control
Grant $root $web.AssociatedOwnerGroup $full; Grant $root $web.CurrentUser $full; Invoke-PnPQuery
# 3) ostatním ponechat jen Read a Limited Access
$null = Get-PnPProperty -ClientObject $root -Property RoleAssignments
foreach ($ra in @($root.RoleAssignments)) {
  $null = Get-PnPProperty -ClientObject $ra -Property Member, RoleDefinitionBindings
  if ($ra.Member.Id -eq $web.AssociatedOwnerGroup.Id -or $ra.Member.Id -eq $web.CurrentUser.Id) { continue }
  $keep = @($ra.RoleDefinitionBindings | Where-Object { $_.RoleTypeKind -in 'Reader','Guest' })
  if ($keep.Count -ne @($ra.RoleDefinitionBindings).Count) {
    $ra.RoleDefinitionBindings.RemoveAll(); $ra.RoleDefinitionBindings.Add($read)
    foreach ($k in $keep) { if ($k.RoleTypeKind -eq 'Guest') { $ra.RoleDefinitionBindings.Add($k) } }
    $ra.Update()
  }
}
Invoke-PnPQuery
# 4) čtení pro celou organizaci a hosty (vynechte, co nechcete)
$eeeu = "c:0-.f|rolemanager|spo-grid-all-users/$(Get-PnPTenantId)"
foreach ($login in $eeeu, "c:0(.s|true") { Grant $root ($web.EnsureUser($login)) $read }
Invoke-PnPQuery
# 5) jen při skupině návrhářů: podsložka seznamu (kopie z kořene + Contribute)
$sub = (Get-PnPFolder -Url "/sites/<site>/SiteAssets/FormCustomizer/<listId>" -Includes ListItemAllFields).ListItemAllFields
$sub.BreakRoleInheritance($true, $true); Invoke-PnPQuery
Grant $sub $web.SiteGroups.GetByName("Návrháři formulářů") $contrib; Invoke-PnPQuery

Příkaz vytvořený návrhářem nebyl ověřen proti živému tenantu (upozorňuje na to komentář v kódu). Před nasazením ho vyzkoušejte na testovacím webu a zkontrolujte výsledek na stránce oprávnění složky.

Zbytková rizika

Oprávnění koncových uživatelů

Formulář nemá vlastní oprávnění k datům: pracuje s právy přihlášeného uživatele. Uživatel proto potřebuje:

Pole, jejichž načtení selže (např. kvůli oprávnění nebo chybě v dávce dotazů), jsou ve formuláři jen ke čtení a při uložení se nezapisují. Viz Nenačtená pole. Režim zobrazení (DisplayForm) nikdy nehlásí neuložené změny.

Uživatelé mimo skupiny webu

Uživatel, který nemá čtení složky konfigurace (např. přístup jen přes sdílení položky, host s vypnutým čtením pro hosty), konfiguraci přečíst nemůže. Formulář pro něj běží s výchozím rozložením vygenerovaným ze sloupců seznamu, bez vašich záložek, pravidel a tlačítek. Správci webu se v takovém případě zobrazí upozornění na nepřečtenou konfiguraci, běžný uživatel dostane hlášku „Formulář se nepodařilo načíst v plném rozsahu. Kontaktujte vlastníka webu.“ Řešením je ponechat zapnuté čtení pro organizaci (a hosty, pokud je potřebujete), nebo uživatele přidat do skupiny webu.

Pokud na formulářích spoléháte na pravidla pro skrytí citlivých polí nebo blokaci uložení, zajistěte, aby ji všichni uživatelé přečetli. Pravidla nejsou bezpečnostní mechanismus: skutečnou ochranu dat poskytují jen oprávnění seznamu a sloupců v SharePointu.

NoScript weby

Na webech s DenyAddAndCustomizePages (NoScript, výchozí u moderních webů) nelze zapisovat do property bagu webu, ani to nemají vlastníci. Produkt proto property bag webu nezapisuje: konfigurace i licence se ukládají jako soubory v Site Assets. Starý klíč v property bagu se ještě čte. Nepotřebujete oprávnění AddAndCustomizePages.