You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

615 lines
19 KiB

<?php
/**
* Définit les autorisations du plugin Albums
*
* @note
* Expérimentation : Certains tests sont déportés dans une fonction à part
* à la fois pour les perfs et pour la lisibilité du code :
* - Dans les autorisations on veut que la logique soit claire,
* c.à.d que la structure de la condition soit compréhensible en 1 coup d'oeil.
* - On ne veut faire que les tests strictement nécessaires,
* tout en gardant un code concis et lisible.
*
* @plugin Albums
* @copyright 2014
* @author Tetue, Tcharlss
* @licence GNU/GPL
* @package SPIP\Albums\Autorisations
*/
// Sécurité
if (!defined('_ECRIRE_INC_VERSION')) {
return;
}
/**
* Fonction d'appel pour le pipeline
* @pipeline autoriser */
function albums_autoriser() {
}
/**
* Autorisation à afficher l'icone de création rapide.
*
* Il faut être autorisé à créer un album.
*
* @uses autoriser_album_creer_dist()
*
* @param string $faire Action demandée
* @param string $type Type d'objet sur lequel appliquer l'action
* @param int $id Identifiant de l'objet
* @param array $qui Description de l'auteur demandant l'autorisation
* @param array $options Options de cette autorisation
* @return bool true s'il a le droit, false sinon
*/
function autoriser_albumcreer_menu_dist($faire, $type, $id, $qui, $options) {
return autoriser('creer', 'album', $id, $qui, $options);
}
/**
* Autorisation de voir les albums dans le menu d'édition.
*
* Il faut être autorisé à administrer les albums.
*
* @uses autoriser_albums_administrer_dist()
*
* @param string $faire Action demandée
* @param string $type Type d'objet sur lequel appliquer l'action
* @param int $id Identifiant de l'objet
* @param array $qui Description de l'auteur demandant l'autorisation
* @param array $options Options de cette autorisation
* @return bool true s'il a le droit, false sinon
*/
function autoriser_albums_menu_dist($faire, $type, $id, $qui, $options) {
return autoriser('administrer', 'albumotheque', $id, $qui, $options);
}
/**
* Autorisation de créer un album
*
* Il faut être admin ou rédacteur.
*
* @uses tester_autorisation_album()
*
* @param string $faire Action demandée
* @param string $type Type d'objet sur lequel appliquer l'action
* @param int $id Identifiant de l'objet
* @param array $qui Description de l'auteur demandant l'autorisation
* @param array $options Options de cette autorisation
* @return bool true s'il a le droit, false sinon
**/
function autoriser_album_creer_dist($faire, $type, $id, $qui, $options) {
$args = func_get_args();
$autoriser = tester_autorisation_album('admin_redac', $args);
return $autoriser;
}
/**
* Autorisation à voir un album
*
* Open bar pour tout le monde.
*
* @param string $faire Action demandée
* @param string $type Type d'objet sur lequel appliquer l'action
* @param int $id Identifiant de l'objet
* @param array $qui Description de l'auteur demandant l'autorisation
* @param array $options Options de cette autorisation
* @return bool true s'il a le droit, false sinon
*/
function autoriser_album_voir_dist($faire, $type, $id, $qui, $options) {
return true;
}
/**
* Autorisation à accéder à l'albumothèque.
*
* Il faut être admin ou rédacteur.
*
* @uses tester_autorisation_album()
*
* @param string $faire Action demandée
* @param string $type Type d'objet sur lequel appliquer l'action
* @param int $id Identifiant de l'objet
* @param array $qui Description de l'auteur demandant l'autorisation
* @param array $options Options de cette autorisation
* @return bool true s'il a le droit, false sinon
*/
function autoriser_albumotheque_administrer_dist($faire, $type, $id, $qui, $options) {
$args = func_get_args();
$autoriser = tester_autorisation_album('admin_redac', $args);
return $autoriser;
}
/**
* Autorisation d'ajouter un album, optionnellement en le liant à un objet.
*
* Cette autorisation est prévue pour le formulaire ajouter_album.
*
* Il faut avoir le droit de créer un album,
* et si un objet est indiqué, que l'ajout d'albums soit activé sur ce type,
* et avoir le droit de modifier l'objet ou être admin complet.
*
* @example
* ```
* #AUTORISER{ajouteralbum}
* #AUTORISER{ajouteralbum, #OBJET, #ID_OBJET}
* ```
*
* @uses tester_autorisation_album()
* @uses autoriser_album_creer_dist()
*
* @param string $faire Action demandée
* @param string $type Type d'objet à lier à l'album (optionnel)
* @param int $id Identifiant de l'objet à lier à l'album
* @param array $qui Description de l'auteur demandant l'autorisation
* @param array $options Options de cette autorisation
* @return bool true s'il a le droit, false sinon
*/
function autoriser_ajouteralbum_dist($faire, $type, $id, $qui, $options) {
$args = func_get_args();
// On est autorisé à créer
$autoriser = autoriser('creer', 'album');
// Si un objet est indiqué, tests supplémentaires
if ($type and $id) {
$autoriser_objet = (
// c'est un des objets configurés...
tester_autorisation_album('objet_config', $args)
// ...et soit on est admin complet, soit on a le droit de modifier l'objet
and (
tester_autorisation_album('admin_complet', $args)
or tester_autorisation_album('modifier_objet', $args)
)
);
$autoriser = ($autoriser and $autoriser_objet);
}
return $autoriser;
}
/**
* Autorisation à modifier un album.
*
* Il faut être l'auteur ou admin complet,
* ou si plugin autorité, que l'album soit dans un secteur wiki
*
* @uses tester_autorisation_album()
*
* @staticvar <type> $autorisations
* @param string $faire Action demandée
* @param string $type Type d'objet sur lequel appliquer l'action
* @param int $id Identifiant de l'objet
* @param array $qui Description de l'auteur demandant l'autorisation
* @param array $options Options de cette autorisation
* @return bool true s'il a le droit, false sinon
*/
function autoriser_album_modifier_dist($faire, $type, $id, $qui, $options) {
// Perf : un static car cette autorisation est appelée par d'autres,
// donc potentiellement plusieurs fois dans le même hit
static $autorisations;
$id_auteur = (int) ($qui['id_auteur'] ?? 0);
$hash = "$id_auteur-$id";
if (isset($autorisations[$hash])) {
return $autorisations[$hash];
}
$args = func_get_args();
$autoriser = (
(
// On est connecté
tester_autorisation_album('connecte', $args)
// ...et on est admin complet ou auteur de l'album
and (
tester_autorisation_album('admin_complet', $args)
or tester_autorisation_album('auteur_album', $args)
)
// ...et s'il y a des objets liés, on a le droit de les modifier tous
and tester_autorisation_album('objets_lies_modifiables', $args)
)
// ...ou bien l'album est dans un wiki : c'est open bar (plugin autorité)
or tester_autorisation_album('wiki', $args)
);
// Garder pour les passages suivants
$autorisations[$hash] = $autoriser;
return $autoriser;
}
/**
* Autorisation à supprimer définitivement un album.
*
* Il faut avoir le droit de le modifier
* et qu'il soit à la poubelle, ou vide et inutilisé.
*
* @uses tester_autorisation_album()
*
* @param string $faire Action demandée
* @param string $type Type d'objet sur lequel appliquer l'action
* @param int $id Identifiant de l'objet
* @param array $qui Description de l'auteur demandant l'autorisation
* @param array $options Options de cette autorisation
* @return bool true s'il a le droit, false sinon
*/
function autoriser_album_supprimer_dist($faire, $type, $id, $qui, $options) {
$args = func_get_args();
$autoriser = (
// On peut modifier l'album
autoriser('modifier', $type, $id, $qui)
and (
// ...et il est à la poubelle
tester_autorisation_album('poubelle', $args)
// ...ou bien vide et orphelin
or (
tester_autorisation_album('vide', $args)
and tester_autorisation_album('orphelin', $args)
)
)
);
return $autoriser;
}
/**
* Autorisation à associer un album à un objet donné.
*
* Il faut pouvoir modifier l'objet ou être admin complet
*
* @note
* Les infos sur l'objet dont dans les options (5ème paramètre)
*
* @example
* ````
* #AUTORISER{associer,album,#ID_ALBUM,'',#ARRAY{objet,#OBJET,id_objet,#ID_OBJET}}
* ````
*
* @uses tester_autorisation_album()
*
* @param string $faire Action demandée
* @param string $type Type d'objet auquel on veut associer ou dissocier un album
* @param int $id Identifiant de l'objet auquel on veut associer ou dissocier un album
* @param array $qui Description de l'auteur demandant l'autorisation
* @param array $options Options de cette autorisation
* Doit contenir les clés `objet` et `id_objet`
* pour rensigner le type et l'identifiant de l'objet
* @return bool true s'il a le droit, false sinon
*/
function autoriser_album_associer_dist($faire, $type, $id, $qui, $options) {
$args = func_get_args();
// Si c'est un nouvel objet pas encore en base,
// son identifiant correspond à l'id négatif de l'auteur.
$id_auteur_session = (int) ($GLOBALS['visiteur_session']['id_auteur'] ?? 0);
$is_id_objet_temporaire = ((int) $options['id_objet'] === -$id_auteur_session);
$autoriser = (
// On est admin
tester_autorisation_album('est_admin', $args)
// ...ou bien c'est un objet pas encore en base
or $is_id_objet_temporaire
// ...ou bien l'objet existe et on a le droit de modifier
or autoriser('modifier', $options['objet'], $options['id_objet'], $qui)
);
return $autoriser;
}
/**
* Autorisation à dissocier un album d'un objet donné.
*
* Il faut pouvoir modifier l'objet ou être admin complet,
* et que l'album ne soit pas inséré dans le texte.
*
* @note
* Les infos sur l'objet dont dans les options (5ème paramètre)
*
* @example
* ````
* #AUTORISER{dissocier,album,#ID_ALBUM,'',#ARRAY{objet,#OBJET,id_objet,#ID_OBJET}}
* ````
*
* @uses tester_autorisation_album()
*
* @param string $faire Action demandée
* @param string $type Type d'objet sur lequel appliquer l'action
* @param int $id Identifiant de l'objet
* @param array $qui Description de l'auteur demandant l'autorisation
* @param array $options Options de cette autorisation
* Doit contenir les clés `objet` et `id_objet`
* pour renseigner le type et l'identifiant de l'objet
* @return bool true s'il a le droit, false sinon
*/
function autoriser_album_dissocier_dist($faire, $type, $id, $qui, $options) {
$args = func_get_args();
$objet = $options['objet'] ?? null;
$id_objet = $options['id_objet'] ?? null;
// Si c'est un nouvel objet pas encore en base,
// son identifiant correspond à l'id négatif de l'auteur.
$id_auteur_session = (int) ($GLOBALS['visiteur_session']['id_auteur'] ?? 0);
$is_id_objet_temporaire = ((int) $options['id_objet'] === -$id_auteur_session);
$autoriser = (
(
// On est admin
tester_autorisation_album('est_admin', $args)
// ...ou bien c'est un objet pas encore en base
or $is_id_objet_temporaire
// ...ou bien l'objet existe et on a le droit de le modifier
or autoriser('modifier', $objet, $id_objet, $qui)
)
// ...et l'album n'est pas inséré dans le texte
and tester_autorisation_album('non_vu', $args)
);
return $autoriser;
}
/**
* Autorisation à dissocier *tous* les albums d'un objet donné.
*
* Il faut plusieurs albums liés, et pouvoir modifier l'objet ou être admin complet.
*
* @example
* ````
* #AUTORISER{dissocieralbums,#OBJET,#ID_OBJET}
* ````
*
* @uses tester_autorisation_album()
*
* @param string $faire Action demandée
* @param string $type Type d'objet sur lequel appliquer l'action
* @param int $id Identifiant de l'objet
* @param array $qui Description de l'auteur demandant l'autorisation
* @param array $options Options de cette autorisation
* @return bool true s'il a le droit, false sinon
*/
function autoriser_dissocieralbums_dist($faire, $type, $id, $qui, $options) {
$args = func_get_args();
$autoriser = (
// Il y a plusieurs albums liés
tester_autorisation_album('plusieurs_lies', $args)
and (
// ...et on est admin
tester_autorisation_album('est_admin', $args)
// ...ou bien on a le droit de modifier l'objet
or autoriser('modifier', $type, $id, $qui, $options)
)
);
return $autoriser;
}
/**
* Auto-association d'albums à du contenu éditorial qui le référence.
*
* Par défaut true pour tous les objets.
*
* @param string $faire Action demandée
* @param string $type Type d'objet sur lequel appliquer l'action
* @param int $id Identifiant de l'objet
* @param array $qui Description de l'auteur demandant l'autorisation
* @param array $options Options de cette autorisation
* @return bool true s'il a le droit, false sinon
*/
function autoriser_autoassocieralbum_dist($faire, $type, $id, $qui, $options) {
return true;
}
/**
* Autorisation de vider un album
*
* Il faut qu'il y ait des documents, et être admin complet
*
* @uses tester_autorisation_album()
*
* @param string $faire Action demandée
* @param string $type Type d'objet sur lequel appliquer l'action
* @param int $id Identifiant de l'objet
* @param array $qui Description de l'auteur demandant l'autorisation
* @param array $options Options de cette autorisation
* @return bool true s'il a le droit, false sinon
**/
function autoriser_album_vider_dist($faire, $type, $id, $qui, $options) {
$args = func_get_args();
$autoriser = (
// L'album est rempli
!tester_autorisation_album('est_vide', $args)
// ...et on a le droit de le modifier
and autoriser('modifier', $type, $id, $qui, $options)
);
return $autoriser;
}
/**
* Différents tests utiles aux autorisations des albums
*
*
* @param string $test
* @param array $args
* @return bool
*/
function tester_autorisation_album(string $test, array $args): bool {
$ok = false;
[$faire, $type, $id, $qui, $options] = $args;
// Perf : une statique car ces tests sont mutualisés entre les autorisations,
// donc appelés potentiellement plusieurs fois dans le même hit.
static $tests;
$hash = "$test-" . ($qui['id_auteur'] ?? '') . "-$id";
if (isset($tests[$hash])) {
return $tests[$hash];
}
switch ($test) {
// On est connecté⋅e
case 'connecte':
$ok = ($qui['id_auteur'] > 0);
break;
// On est admin simple ou rédacteur
case 'admin_redac':
$ok = (in_array($qui['statut'], ['0minirezo', '1comite']));
break;
// On est admin simple
case 'admin':
$ok = ($qui['statut'] === '0minirezo');
break;
// On est admin complet
case 'admin_complet':
$ok = ($qui['statut'] === '0minirezo' and !$qui['restreint']);
break;
// On est un⋅e des auteur⋅ices de l'album
case 'auteur_album':
$ids_auteurs = sql_allfetsel('id_auteur', 'spip_auteurs_liens', ['objet=' . sql_quote('album'), 'id_objet=' . intval($id)]);
$ids_auteurs = array_column($ids_auteurs, 'id_auteur');
$ids_auteurs = (is_array($ids_auteurs) ? array_values($ids_auteurs) : []);
$ok = in_array($qui['id_auteur'], $ids_auteurs);
break;
// On peut modifier tous les objets liés
case 'objets_lies_modifiables':
$ok = true; // les liaisons sont optionnelles
if ($liens = sql_allfetsel('objet,id_objet', 'spip_albums_liens', 'id_album=' . intval($id))) {
foreach ($liens as $lien) {
if (!autoriser('modifier', $lien['objet'], $lien['id_objet'], $qui, $options)) {
$ok = false;
break;
}
}
}
break;
// C'est un des objets configurés pour les albums
case 'objet_config':
include_spip('inc/config');
$config = lire_config('albums/objets', []);
$ok = in_array(table_objet_sql($type), array_filter($config));
break;
// On a le droit de modifier l'objet (existant ou en cours de création)
case 'modifier_objet':
// c'est un objet existant
if ($id > 0) {
$ok = autoriser('modifier', $type, $id, $qui, $options);
// c'est un nouvel objet
} elseif ($id < 0 and (abs($id) == $qui['id_auteur'])) {
$ok = autoriser('ecrire', $type, $id, $qui, $options);
}
break;
// L'album est à la poubelle
case 'poubelle':
$ok = (sql_getfetsel('statut', 'spip_albums', 'id_album=' . intval($id)) === 'poubelle');
break;
// L'album est vide
case 'vide':
$ok = !sql_countsel('spip_documents_liens', ['objet=' . sql_quote($type), 'id_objet=' . intval($id)]);
break;
// L'album est orphelin
case 'orphelin':
$ok = !sql_countsel('spip_albums_liens', 'id_album=' . intval($id));
break;
// L'album n'est pas inséré dans le texte de l'objet lié (passé dans les options)
case 'non_vu':
$ok = !sql_countsel(
'spip_albums_liens',
[
'id_album=' . intval($id),
'objet=' . sql_quote($options['objet']),
'id_objet=' . intval($options['id_objet']),
'vu=' . sql_quote('oui'),
]
);
break;
// Il y a plusieurs albums liés à l'objet
case 'plusieurs_lies':
$ok = (sql_countsel('spip_albums_liens', ['objet=' . sql_quote($type), 'id_objet=' . intval($id)]) > 1);
break;
// L'album est dans un secteur wiki (plugin autorité)
case 'wiki':
$ok = tester_album_wiki($id, $qui);
break;
}
// Garder pour les passages suivants
$tests[$hash] = $ok;
return $ok;
}
/**
* Teste si un album se trouve dans un secteur wiki auquel on a accès (plugin autorité)
*
* @note
* Il faudrait une fonction générique dans autorité.
*
* @param integer $id_album
* @param array $qui
* @return boolean
*/
function tester_album_wiki($id_album, $qui) {
include_spip('inc/utils');
$acces_album_wiki = false;
if (test_plugin_actif('autorite')) {
include_spip('action/editer_liens');
$liens = objet_trouver_liens(['album' => $id_album], '*');
// Parcourir les objets liés : ils doivent tous être dans un secteur wiki
if (is_array($liens)) {
include_spip('inc/autorite');
foreach ($liens as $lien) {
$objet = $lien['objet'];
$id_objet = $lien['id_objet'];
$cle_objet = id_table_objet($objet);
$table_objet = table_objet_sql($objet);
// On cherche le secteur
$desc = lister_tables_objets_sql(table_objet_sql($objet));
if (isset($desc['field']['id_secteur'])) {
$id_secteur = sql_getfetsel('id_secteur', $table_objet, $cle_objet . '=' . intval($id_objet));
} elseif (isset($desc['field']['id_rubrique'])) {
$id_rubrique = sql_getfetsel('id_rubrique', $table_objet, $cle_objet . '=' . intval($id_objet));
$id_secteur = sql_getfetsel('id_secteur', 'spip_rubriques', 'id_rubrique=' . intval($id_rubrique));
}
// Si on a le secteur, on teste
// obligé de recopier une partie du code d'autorité, faute de fonction séparée
if (
$id_secteur
and isset($GLOBALS['autorite']['espace_wiki'])
and autorisation_wiki_visiteur($qui, $id_secteur)
and (
isset($GLOBALS['autorite']['espace_wiki_rubrique_anonyme'])
or $qui['statut']
)
) {
$acces_album_wiki = true;
} else {
return; // Niet dès que le moindre objet lié n'est pas ok
}
}
}
}
return $acces_album_wiki;
}