Collectif Objets est un site web permettant aux communes françaises de recenser leur patrimoine mobilier monument historiques et aux conservateurs d'examiner ces recensements.
💡 Toute la documentation est contenue dans ce long README pour être facilement découvrable
Avec Gitpod (environnement de développement en ligne configuré automatiquement) : Ouvrir sur Gitpod ↗️
Avec Docker: docker compose up && docker compose run web rails db:setup
Sous Mac / Linux:
Installer Homebrew : https://brew.sh/
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
Installer rbenv : brew install rbenv ruby-build : https://github.com/rbenv/rbenv
brew install rbenv ruby-build
rbenv init
Installer Ruby avec rbenv
rbenv install `cat .ruby-version`
Installer Bundler avec la version précisée dans le Gemfile.lock :
gem install bundler:2.4.13
Installer NodeJS, idéalement la même version qu'en production : https://github.com/nvm-sh/nvm#installing-and-updating
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
nvm install 18
Installer Rails et les dépendances
make install
Lancer le serveur
make dev
Installer le CLI de Scalingo :
curl -O https://cli-dl.scalingo.com/install && bash install
Ajouter sa clé SSH dans son compte Scalingo en suivant ces instructions : https://doc.scalingo.com/platform/getting-started/setup-ssh-linux
Utilisation d'asdf
Il est possible d'utiliser asdf pour installer la bonne version de Ruby et NodeJS. Cela évite d'avoir 2 outils différents (rbenv et nvm ou autres).
Cependant le Makefile n'est pas adapté à son utilisation, il faudrait donc lancer les commandes une à une et préfixer celles avec npm par asdf exec
optionnel: pour une utilisation de rubocop plus rapide en local, voir le mode serveur
Outils de débogage
Dans VSCode, installer l'extension RDBG qui permet de déboguer pas à pas directement dans l'IDE.
Il faut d'abord lancer le serveur depuis le terminal dans VSCode (View > Terminal) avec cette commande :
rdbg -n -c --open=vscode -- bin/rails s
Puis attacher le débogeur via le menu Run and Debug dans la sidebar. Pour ce faire, éditer le fichier .vscode/launch.json
pour qu'il ait la configuration suivante :
{
"version": "0.2.0",
"configurations": [
{
"type": "rdbg",
"name": "Attach with rdbg",
"request": "attach"
}
]
}
Vous pourrez ainsi placer des breakpoints depuis VSCode, voir le contenu des variables en les survolant etc.
Le site expose trois interfaces pour trois types d'usagers différents, toutes accessibles depuis un site commun unique : https://collectif-objets.beta.gouv.fr
permet aux agents municipaux des communes de réaliser les recensements d'objets ;
permet aux conservateurs d'examiner les recensements réalisés ;
permet Ă l'Ă©quipe technique de faire le support
Découverte de l’interface administrateurs
admin@collectif.local
mot de passe 123456
Découverte de l’interface communes
Découverte de l’interface conservateurs
conservateur@collectif.local
mot de passe 123456789 123456789 123456789
Les 3 interfaces sont servies par une seule et unique application Ruby On Rails 7.
Les gems principales dont dépend cette application Rails sont :
devise
: Authentification des usagers. Il y a trois modèles Devise User
(Communes), Conservateur
et Admin
.pundit
: droits et règles d'accès selon les profilsgood_job
: Gestion des tâches asynchronesvite_rails
: Compilation des assets JS et imagesturbo_rails
: Interactions JS simplifiéesmjml-rails
: Templates de mails en MJMLAASM
: Machines à états finis pour les statuts des modèleshaml-rails
, kramdown
et view_component
pour les modèles de vuesransack
: recherches et filtres dans l'admin principalementCôté Javascript les principaux packages utilisés sont :
@gouvfr/dsfr
: Design Système de l'État Français@rails/activestorage
: Gestion des uploads de photos@hotwired/stimulus
: Simplifie le lien entre HTML et JSmaplibre-gl
: permet d'afficher une carte des communes du département d'un conservateurChart.js
: diagrammesflowchart TB
subgraph ext[Services Externes]
dashlord
updown.io
Mattermost
Sentry[Sentry Incubateur]
s3[Scaleway S3 Buckets]
brevo[Brevo - ex Send In Blue]
datasette[collectif-objets-datasette.fly.dev]
end
subgraph scalingo[Scalingo]
subgraph rails[Rails App]
direction TB
web[Web dynos]
worker[GoodJob worker dynos]
cron[Cron tasks]
end
rails <--> postgres[(Postgres)]
postgres -- read-only --> metabase[Metabase]
end
subgraph github[GitHub Actions]
ci[CI\nLint et Tests]
codeql[CodeQL\nStatic Analysis]
dependabot[Dependabot]
end
rails <--> github
rails <--> ext
3 environnements :
Outils & services externes
classDiagram
direction RL
class User
User : email
class Commune
Commune : code_insee
class Edifice
Edifice : nom
Edifice : merimee_REF
class Objet
Objet : palissy_REF
class Recensement
Recensement : etat_sanitaire
Recensement : photos
class Dossier
Dossier : status
class Departement
Departement : code
class Campaign
Campaign : date_lancement
Campaign : date_fin
class Conservateur
Conservateur : email
Commune "*" --> "1" Departement
User "*" --> "1" Commune
Edifice "*" --> "1" Commune
Objet "*" --> "1" Edifice
Recensement "*" --> "1" Objet
Recensement "*" --> "0..1" Dossier
Dossier "*" --> "1" Commune
Dossier "*" --> "1" Conservateur : est examiné par
Campaign "*" --> "1" Departement
Commune "*" --> "*" Campaign
User
sont les comptes usagers des communes. C'est un modèle Devise. Un User
a accès à une et une seule
commune.Conservateurs
sont les comptes usagers des conservateurs. C'est aussi un modèle Devise.
Un Conservateur a accès à un ou plusieurs départements et toutes les communes inclues.Édifices
sont les lieux abritant les objets. Une partie sont des monuments historiques avec des références
vers la base Mérimée.Objets
sont les objets monuments historiques. Leurs infos proviennent de Palissy.
Leur identifiant unique provient de POP et s'appelle dans notre base palissy_REF
, il ressemble Ă PM00023944
.Recensement
contient les observations sur l'Ă©tat d'un Objet
et les photos associées à la visite du User
.Dossier
est un ensemble de Recensements
pour une commune.
Il doit être finalisé par la commune pour être analysable par les conservateurs.Campagne
contient les dates et les communes à démarcher pour une campagne mail avec plusieurs relances.
Elle est gérée et visible uniquement par les administrateurs.AdminUser
est un compte permettant l'accès à l'interface d'admin
Pour créer un nouveau compte, utiliser cette commande dans une console Rails :
AdminUser.create(email: "email@de.ladmin", first_name: "Prénom de l'admin", last_name: "Nom de l'admin", password: "mot_de_passe_de_ladmin")
La version complète du diagramme d'entités de la base de données est visible ici doc/entity-relationship-diagram.svg
Le recensement des objets d'une commune se fait en plusieurs étapes que l'on peut voir sur ce schéma
Dans le code, chaque Ă©tape modifie l'Ă©tat de la Commune
, du Dossier
ou du Recensement
.
Il existe aussi la notion de statut global
sur la commune, qui est affiché en tant que badge pour le conservateur ou dans l'admin. Il est déduit en fonction du statut de la commune, de son dossier et de ses recensements.
Communes | Recensements | Dossiers | Campaigns |
---|---|---|---|
bundle exec rake diagrams:generate[nom_du_model]
permet de mettre Ă jour ces diagrammes
Ci-dessous les étapes avec le détail des différents statuts en base de données
Étape | statut global | commune | recensement(s) | dossier |
---|---|---|---|---|
1 | Non recensé | inactive |
aucun recensement ou tous draft |
aucun dossier |
2 | En cours de recensement | started |
au moins un completed |
construction |
3 | À examiner en priorité | completed |
tous completed |
submitted |
4 | À examiner | completed |
tous completed |
submitted et replied_automatically_at présent |
5 | En cours d'examen | completed |
au moins un completed et examiné |
submitted |
6 | Examiné | completed |
tous completed et tous examinés |
accepted |
7 | Non recensé | inactive |
aucun recensement | ancien dossier archived |
Le statut global est récupéré à la volée dans une requête SQL plutôt qu'avec un champ dédié. Ce choix a été fait pour déployer les fonctionnalités plus vite, en évitant au maximum de changer l'existant.
Cependant, il serait judicieux de réduire le nombre de statuts, qui sont d'ailleurs souvent redondants. Nous avions imaginé de supprimer le status
de la Commune
et remplacer le status
du Dossier
par le statut_global
. Cela simplifierait grandement le code et améliorerait les performances. En effet, le calcul du statut_global
peut être lent comparé à lecture d'un champ en base.
Aussi, le mot analysed vient de l'ancien terme "Analysé" et devrait être remplacé par "Examiné". De plus, on pourrait avoir un statut analysed
ou examined
sur le recensement, pour que ce soit cohérent avec les statuts draft
et completed
.
Tout ce qui est décrit ci-dessous est évidemment discutable et peut évoluer librement.
Les objectifs principaux de ce code sont :
Les commentaires dans le code sont à limiter au minimum, on préfère refactorer le code pour qu’il soit plus clair.
Les contrôleurs sont légers. Les modèles contiennent la logique métier. Il y a des modèles ActiveRecord et d’autres PORO. On utilise les concerns pour isoler des comportements de modèles. cf doctrine 37signals. Cela peut évidemment évoluer.
La couverture des tests est modérée. Il y a des tests E2E pour les chemins les plus importants, principalement pour les cas de succès. Il y a des tests unitaires pour les modèles quand cela semble nécessaire ou que ça aide l’écriture du code. Il n’y a pas de tests de contrôleurs, on favorisera les tests E2E ou pas de tests. Il n’y a pas de tests pour les fonctionnalités natives de Rails ni ActiveRecord. Les appels ActiveRecord ne sont pas mockés, ils font partie de ce qui est couvert par les tests.
L’ajout de dépendances se fait avec parcimonie, les dépendances transitives sont étudiées à chaque fois. Cela vaut pour les services tiers, les gems, et les packages JS.
L’introduction de comportements JS custom hors DSFR et Turbo est faite avec parcimonie. Le site peut en grande partie fonctionner sans JS. De nombreux usagers sont peu à l’aise avec le numérique, le site doit être aussi standard et sans surprise que possible. Le site n’est pour l’instant pas tout à fait responsive, c’est une erreur à corriger.
Les règles rubocop basées uniquement sur la longueur des méthodes ou des classes sont volontairement désactivées. En général il ne faut pas hésiter à désactiver les règles rubocop si on juge qu’elles n’aident pas.
Avec le recul, certains choix méritent d’être revus :
# Dans un terminal à part, lancer un tunnel SSH pour avoir accès à la base de données.
# Il faut avoir préalablement configuré une clé SSH dans Scalingo
scalingo --app collectif-objets-staging db-tunnel SCALINGO_POSTGRESQL_URL
# Dans un second terminal, lancer le dump en remplaçant collectif_o_9999 et XXXXX par les données
# de prod ou staging que vous trouverez dans la variable d'environnement SCALINGO_POSTGRESQL_URL.
# Pour récupérer les données de recensement, utiliser plutôt le scritp pg_dump_data_full.sh
./scripts/pg_dump_data_anonymous.sh postgres://collectif_o_9999:XXXXX@localhost:10000/collectif_o_9999 tmp/dump.pgsql
# Le dump peut alors être importé en local
rails db:drop db:create db:schema:load
rails runner scripts/create_postgres_sequences_memoire_photos_numbers.rb
pg_restore --data-only --no-owner --no-privileges --no-comments --dbname=collectif_objets_dev tmp/dump.pgsql
Pour mettre Ă jour le fichier seeds.pgsql
pour les review apps :
rails runner scripts/reset_recensements_dossiers_communes.rb
./scripts/pg_dump_data_anonymous.sh collectif_objets_dev tmp/seeds.pgsql
tmp/seeds.pgsql
sur le bucket S3 collectif-objets-public
, par exemple avec Cyberducken local rails db:reset
: détruit puis recréé les bases locales, charge le schéma puis les seeds qui se téléchargent
depuis le bucket S3 collectif-objets-public
.
Les review apps ne sont pas activées automatiquement pour toutes les PRs car elles sont coûteuses en ressources et pas utiles
# Création :
scalingo integration-link-manual-review-app --app collectif-objets-staging 701
# Déploiement d’une nouvelle version de la branche
# git push origin feature/etapes-recensement
scalingo integration-link-manual-deploy --app collectif-objets-staging-pr701 feature/etapes-recensement && \
scalingo --app collectif-objets-staging-pr701 deployment-follow
# Réinitialisation de la base de données
# on n’a pas les droits pour dropper la db ni l’app
scalingo --app collectif-objets-staging-pr701 run bash
rails runner scripts/truncate_all_tables.rb
rails runner scripts/create_postgres_sequences_memoire_photos_numbers.rb
rails db:seed
Note: Pour faire fonctionner le direct-upload pour les photos sur une review vous devrez rajouter l’hôte de la review dans la liste des hosts autorisés en CORS sur le bucket S3 de staging, voir plus bas.
Voici une liste à suivre pour préparer une astreinte sereine :
~projet-collectif_objets
et ~projet-collectif_objets-dev
dans l'espace AtNumCultureconfig/master.key
Optionnel :
flowchart TB
api_service_public[api-lannuaire.service-public.fr]
api_data_culture_gouv[data.culture.gouv.fr]
pop[pop.culture.gouv.fr]
fly[collectif-objets-datasette.fly.dev]
subgraph scraper[pop-scraper - python]
scraper_run>poetry run scrapy crawl pop_api]
end
subgraph datasette[collectif-objets-datasette - python]
datasette_run_sqlite>make prepare_sqlite]
datasette_run_deploy>make deploy]
csvs[[data_scrapped/*.csv]]
sqlite[(app/data.sqlite)]
end
subgraph rails[collectif-objets - rails module Synchronizer]
rails_run_edifices>Edifices::SynchronizeAllJob]
rails_run_objets>Objets::SynchronizeAllJob]
rails_run_communes>Communes::SynchronizeAllJob]
rails_run_photos>Photos::SynchronizeAllJob]
postgres[(Postgres DB)]
end
pop --> scraper_run
scraper_run --> csvs
csvs --> datasette_run_sqlite
datasette_run_sqlite --> sqlite
sqlite --> datasette_run_deploy
datasette_run_deploy --> fly
api_data_culture_gouv --> rails_run_objets
rails_run_objets --> postgres
api_service_public --> rails_run_communes
rails_run_communes --> postgres
api_data_culture_gouv --> rails_run_edifices
rails_run_edifices --> postgres
fly --> rails_run_photos
rails_run_photos --> postgres
style pop fill:#6666cc
style fly fill:#6666cc
style api_service_public fill:#6666cc
style api_data_culture_gouv fill:#6666cc
style datasette_run_sqlite fill:#888833
style datasette_run_deploy fill:#888833
style rails_run_objets fill:#888833
style rails_run_communes fill:#888833
style rails_run_edifices fill:#888833
style rails_run_photos fill:#888833
style scraper_run fill:#888833
Les données sur les communes et les emails des mairies proviennent de l’API de service-public.fr
Les données des objets monuments historiques sont récupérées depuis les bases nationales Palissy (objets), Mérimée (édifices) et Mémoire (photos). Plus d'info sur le processus de synchronisation des données dans doc/synchronisation.md
La plupart des données stockées sur Collectif Objets sont publiques. Les exceptions sont :
Voici un schéma approximatif de l'organisation d’un modules de synchronisation (par exemple Synchronizer::Objets
) :
graph TD
SynchronizeAllJob -- instancie des batchs<br> de 1000L --> Batch::Base
Logger --o SynchronizeAllJob
Logger --> log>tmp/synchronize.log]
ApiClient -- itère le CSV --o SynchronizeAllJob
data[[data.culture.gouv.fr]] -- télécharge CSV --> ApiClient
Parser -- parse une ligne CSV <br> en attributs AR --o Batch::Base
EagerLoadStore -- pré-charge les <br> records AR --o Batch::Base
Batch::Base -- filtre les lignes <br> dans le périmètre de CO --> Row#in_scope?
Batch::Base -- instancie à partir des attributs <br> parsés et des records préchargés --> Revision#synchronize
Revision#synchronize -- créé, met à  jour, supprime --> db[(DB)]
[!NOTE] On détaille ici des aspects techniques du code de ces modules de synchronisation. Pour des détails plus haut niveau sur la logique et le périmètre voir doc/synchronisation.md
Les méthodes Revision#synchronize
s’appuient autant que possible sur ActiveModel.
On veut faire un appel canonique objet.save
et que la logique se passe à  l’intérieur.
On passe par exemple des nested attributes plutĂ´t que de faire new_edifice.save! && objet.update(edifice: new_edifice)
.
La classe Row
est un PORO qui représente une ligne du CSV parsée et sur laquelle on applique des règles de filtrage dans la méthode #in_scope?
.
Par exemple pour les objets il s’agit de vérifier que la notice Palissy rentre dans le périmètre de Collectif Objets.
On s’appuie ici sur les validations ActiveModel pour avoir une structure commune et des messages d’erreurs compréhensifs.
Il y a un petit point peu agréable dans cette modélisation : Row
fait un parsing très proche de celui fait dans Parser
mais légèrement différent.
Par exemple pour les objets on va filtrer sur le champ palissy_STAT
qu’on ne stocke pas dans les modèles Objet
.
Il faut donc le parser dans Row
mais pas dans Parser
.
Cette modélisation peut être améliorée pour éviter cette redondance.
Le EagerLoadStore
permet d’éviter les requêtes SQL N+1 en les regroupant au niveau du Batch
.
C’est un module d’optimisation des performances, il serait plus simple de réécrire le code sans ce préchargement mais cela serait nettement plus long, voire trop long. Il faut bien répercuter les modifications faites par Revision#synchronize
dans le EagerLoadStore
.
Exemple :
Store
pour que la ligne 101 ne tente pas de recréer cet édifice mais retrouve l’édifice créé par la ligne 100Les métadonnées des photos venant de Mémoire sont stockées dans le champ objets.palissy_photos
dans un champ JSON, par exemple :
[
{
"url" : "https://s3.eu-west-3.amazonaws.com/pop-phototeque/memoire/AP01W00056/sap83_01w00056_p.jpg",
"name" : "vue de la nef",
"credit" : "© Ministère de la Culture (France), Médiathèque du patrimoine et de la photographie (objets mobiliers), tous droits réservés"
}
]
Les métadonnées des photos mises en ligne par les communes ou les conservateurs lors du recensement sont stockées dans ActiveStorage::Attachment
et ActiveStorage::Blob
, liés à l'objet Recensement
. Les fichiers sont sur un bucket S3.
Les fichiers .rb
des composants View Components sont dans /app/components
.
Pour chaque composant, tous les fichiers liés (JS, CSS, preview) sont dans un dossier du même nom dans
/app/components
.
Par exemple un composant GalerieComponent pourra être composé des fichiers suivants :
/app/components/galerie_component.rb
/app/components/galerie_component/galerie_component.css
/app/components/galerie_component/lightbox_component_controller.js
/app/components/galerie_component/galerie_component_preview.rb
Le format du nom du fichier lightbox_component_controller.js
est important : il ne sera importé que s'il respecte ce format.
Ce fichier doit exporter un controlleur Stimulus et est responsable d'importer le fichier CSS.
La classe de preview doit malheureusement être préfixée par le nom du composant, ici GalerieComponent::GalerieComponentPreview
.
Cette configuration s'inspire partiellement de view_component-contrib.
Des controlleurs Stimulus non liés à des composants existent dans :
/app/frontend/stimulus_controllers
: importés par défaut dans l'entrypoint application.js
/app/frontend/stimulus_controllers_standalone
: doivent être importés dans des entrypoints spécifiquesL'intégration du DSFR est faite par des liens symboliques définis dans /public
qui pointent vers les assets
précompilés du package node :
/public/dsfr/dsfr.min.css -> /node_modules/@gouvfr/dsfr/dist/dsfr.min.css
/public/dsfr/fonts -> /node_modules/@gouvfr/dsfr/dist/fonts/
/public/dsfr/icons -> /node_modules/@gouvfr/dsfr/dist/icons/
/public/dsfr/utility/utility.min.css -> /../node_modules/@gouvfr/dsfr/dist/utility/utility.min.css
Cela permet :
En revanche ce n'est vraiment pas standard et risque de poser des soucis de maintenance.
C'est discuté ici : https://mattermost.incubateur.net/betagouv/pl/ehsuormqztnr3fz6ncuqt9f5ac
La messagerie permet des échanges entre les usagers, les conservateurs et l'équipe support de Collectif Objets. Les messages apparaissent dans l'interface de Collectif Objets et sont envoyés par email aux destinataires. Les conservateurs et usagers peuvent répondre aux emails et les réponses apparaissent dans l'interface de Collectif Objets.
Pour récupérer ces emails, nous utilisons la fonctionnalité
Inbound Parsing Webhooks de Brevo.
Le script scripts/create_brevo_webhooks.sh
permet de gérer les webhooks actifs sur Brevo.
Il y a 3 webhooks actifs pour les 3 environnements (production, staging, local) :
[{
"description": "[STAGING] inbound emails webhook",
"url": "https://staging.collectifobjets.org/api/v1/inbound_emails",
"events": ["inboundEmailProcessed"],
"domain": "reponse-staging.collectifobjets.org"
}, {
"description": "[PROD] inbound emails webhook",
"url": "https://collectif-objets.beta.gouv.fr/api/v1/inbound_emails",
"events": ["inboundEmailProcessed"],
"domain": "reponse.collectifobjets.org"
}, {
"description": "Debug inbound email webhook tunneled to localhost",
"url": "https://collectifobjets-mail-inbound.loophole.site",
"events": ["inboundEmailProcessed"],
"domain": "reponse-loophole.collectifobjets.org"
}]
Chacun des sous domaines reponse(-[a-z]+)
de collectifobjets.org
hébergé sur Gandi est configuré pour rediriger les emails entrants vers Brevo.
Les emails entrants sont reçus sur des adresses signées (qui sont les reply-to des mails de notifications de nouveau message) qui permettent d'authentifier l'auteur du message :
mairie-30001-a1b2c3d4h5@reponse.collectifobjets.org
: réponse de l'usager de la commune 30001 dont le
inbound_email_token
secret est a1b2c3d4h5
.mairie-30001-conservateur-a1b2c3d4h5@reponse.collectifobjets.org
: réponse du conservateur pour la même communeVoir la partie sur les tunnels plus bas pour itérer en local sur ces webhooks.
La démarche d'accessibilité est de réaliser une couverture quasi exhaustive des pages de l'application par des tests automatisés, puis de faire réaliser des tests manuels dans un second temps. Actuellement (février 2023) nous sommes à environ 70% de couverture des pages par des tests automatisés.
Les tests automatisés sont réalisés avec aXe. Plus d’infos sur https://collectif-objets.beta.gouv.fr/declaration_accessibilite
Netlify CMS est un headless CMS (c'est à dire un backend dissocié de l'application principale) qui permet de modifier des contenus facilement par des personnes sans modifier le code directement.
Les particularités de ce CMS sont :
Il n'y a donc pas de base de données supplémentaire à gérer ou de serveur d'API de contenu à maintenir, tous les contenus restent présents dans le dépôt Git.
Nous utilisons ce CMS pour permettre Ă l'Ă©quipe d'Ă©diter les articles de presse, les fiches de conseil et les pages de documentation.
Le CMS est hébergé sur Netlify et est accessible à l'adresse collectif-objets-cms.netlify.app.
Le projet Netlify est configuré pour déployer le répertoire /cms
à la racine de ce dépôt Git courant.
Le fichier /cms/config.yml
configure Netlify CMS pour notre cas.
Nous utilisons Netlify Identity pour authentifier les accès au CMS, et un user github robot pour réaliser les commits
et les PRs Ă©manant de Netlify CMS.
Cette configuration est décrite sur ce pad.
⚠️ Après modification de /cms/config.yml
il faut réactiver les builds sur Netlify.
Ils sont désactivés en temps normal puisque ce fichier est très rarement modifié.
Si l’erreur Git Gateway Error: Please ask your site administrator to reissue the Git Gateway token
apparaît, il faut
repo
uniquementTélécharger la vidéo au format MP4. Pour les vidéos Loom il faut avoir un compte, mais pas nécessairement celui du créateur de la vidéo.
Prendre une capture d’écran d’un moment clé de la vidéo à utiliser comme poster.
La convertir en WEBP avec convert titre.png titre.webm
ou bien la compresser avec imageoptim.
Renommer les fichiers MP4 et PNG/WEBM au format suivant 2023_05_titre_video.mp4
.
Puis convertir en local la vidéo au format WEBM (bien conserver le fichier MP4) :
ffmpeg -i 2023_05_titre_video.mp4 -c:v libvpx-vp9 -crf 30 -b:v 0 -b:a 128k -c:a libopus 2023_05_titre_video.webm
Compresser le fichier MP4 lui-même s’il est trop lourd :
ffmpeg -i 2023_05_titre_video.mp4 -vcodec libx265 -crf 30 2023_05_titre_video.mp4
đź’ˇCe gist contient des scripts pour des raccourcis de conversion dans Mac Os Finder
Uploader les fichiers MP4 et WEBM sur le bucket S3 collectif-objets-public
.
Donner les permissions ACL en lecture pour tous les visiteurs pour les fichiers uploadés.
Enfin insérer et adapter l’un des deux snippets suivants en HAML ou HTML :
%video.co-cursor-pointer{controls:"", width:"100%", preload:"none", poster:vite_asset_path("images/2023_05_titre_video.webp"), href:"#"}
/ the href is a fix for a bad rule in DSFR
%source(src="https://s3.fr-par.scw.cloud/collectif-objets-public/2023_05_titre_video.webm" type="video/webm")
%source(src="https://s3.fr-par.scw.cloud/collectif-objets-public/2023_05_titre_video.mp4" type="video/mp4")
%a(href="https://s3.fr-par.scw.cloud/collectif-objets-public/2023_05_titre_video.mp4")
Télécharger la vidéo au format MP4
<video class="co-cursor-pointer" controls="" width="100%" preload="none" poster="https://s3.fr-par.scw.cloud/collectif-objets-public/2023_05_titre_video.png" href="#">
<source src="https://s3.fr-par.scw.cloud/collectif-objets-public/2023_05_titre_video.webm" type="video/webm">
<source src="https://s3.fr-par.scw.cloud/collectif-objets-public/2023_05_titre_video.mp4" type="video/mp4">
<a href="https://s3.fr-par.scw.cloud/collectif-objets-public/2023_05_titre_video.mp4">
Télécharger la vidéo au format MP4
</a>
</video>
Le tunneling consiste Ă exposer votre environnement local sur une URL publiquement accessible.
ngrok
est l’outil de tunneling le plus répandu mais nous avons configuré loophole
sur ce projet car le plan gratuit est plus généreux.
Les instructions d’installation sont sur le site public de loophole.
Une fois installé vous pouvez utiliser :
make tunnel
tunnel général du port 3000 accessible sur https://collectifobjets.loophole.site. Cela permet par exemple de tester le rendu sur un mobile.make tunnel_webhooks
expose uniquement l’URL racine https://collectifobjets-mail-inbound.loophole.site qui est configurée sur un webhook inbound parsing sur Brevo.Un objet dit prioritaire est un objet en péril ou disparu. Dans les autres cas, on parle d'objet vert.
Historique
Le fait d'examiner le recensement d'une commune par un conservateur s'appelait précédemment l'analyse. De même, on appelait rapport la page de synthèse de l'examen.
On retrouve ces termes encore dans le code, il faudrait idéalement les renommer. Attention à bien migrer les champs en base de données contenant le mot "analyse" sur la table recensements, comme par exemple analyse_etat_sanitaire ou analysed_at.
La configuration des domaines en .beta.gouv.fr
est gérée par l'équipe transverse de beta.gouv.fr,
idem pour les domaines en .incubateur.net
L'adresse contact@collectif-objets.beta.gouv.fr
est une liste de diffusion beta.gouv.fr, elle se gère depuis le mattermost
de beta cf https://doc.incubateur.net/communaute/travailler-a-beta-gouv/jutilise-les-outils-de-la-communaute/outils/liste-de-diffusion-et-adresses-de-contact#la-commande-mattermost-emails
L'adresse support@collectif-objets.beta.gouv.fr
est gérée en délégation de service par l'incubateur du ministère de
la Culture (référent : Ned Baldessin). Idem pour tout le sous-domaine collectif-objets.beta.gouv.fr
Le domaine collectifobjets.org
, le sous domaine de redirection des emails de réponse, et les adresses mails associées
de l'équipe sont gérées par Adrien et son compte Gandi.
Les buckets suivants sont sur Scaleway dans le projet nommé "Collectif objets" :
collectif-objets-development2
: photos de recensement et les bordereaux de récolement en PDF ;collectif-objets-staging2
: photos de recensement et les bordereaux de récolement en PDF ;collectif-objets-public
: contenus Ă©ditoriaux visibles sur le site (documentation par exemple) et fichier seeds.pgsql ;collectif-objets-private
: pour du stockage en interneLe bucket le plus important est dans le projet nommé "default" car il y a été créé et ne peut pas être migré facilement :
collectif-objets-production
: photos de recensement et les bordereaux de récolement en PDFLes buckets de photos et bordereaux doivent être configurés pour le CORS
cf https://www.scaleway.com/en/docs/storage/object/api-cli/setting-cors-rules/
aws s3api put-bucket-cors --bucket collectif-objets-development2 --cors-configuration file://scripts/s3buckets/cors-development.json
aws s3api put-bucket-cors --bucket collectif-objets-staging2 --cors-configuration file://scripts/s3buckets/cors-staging.json
aws s3api put-bucket-cors --bucket collectif-objets-production --cors-configuration file://scripts/s3buckets/cors-production.json
Pour configurer l'accès du bucket collectif-objets-public
utilisez la commande suivante :
aws s3api put-bucket-policy --bucket collectif-objets-public --policy file://bucket-policy-public.json
Avec le fichier suivant
{
"Version": "2022-09-21",
"Id": "collectifobjets",
"Statement": [
{
"Sid": "Allow public access on all files",
"Effect": "Allow",
"Principal": {
"SCW": "project_id:xxxx-xxxx-xxxx"
},
"Action": [
"s3:GetObject"
],
"Resource": [
"collectif-objets-public"
]
}
]
}
Toute la configuration se trouve dans config/initializers/content_security_policy.rb
.
Actuellement les règles ne sont pas appliquées, elles sont encore en "report-only" c’est à dire qu’en cas d’infraction, les navigateurs ne vont pas empêcher la ressource de se charger, mais simplement envoyer l’information à Sentry.
Les ressources problématiques peuvent être filtrées sur Sentry avec event.type:csp
.
Lorsque de nouvelles apparaissent il convient de s’assurer qu’elles proviennent bien de notre code :
source_file
de l’évènement n’indique pas quelque chose de suspect comme une extension navigateurSentry est déjà  configuré pour ignorer les problèmes dont le source_file est moz_extension
ou sandbox eval code
, cf config Sentry.
Pour débugger les CSPs en local, il peut être utile de désactiver vite dev dans le Procfile.dev et les exceptions spécifiques à l’environnement de dev en haut de config/initializers/content_security_policy.rb
.
💡 La règle d’or est de tout faire pour ne jamais avoir à rajouter de règle unsafe inline
pour le style ou pour les scripts.
L’intérêt est en effet que les CSP protègent les usagers d’injections de code.