first commit

This commit is contained in:
julien committed 2026-10-22 01:07:27 +02:00
commit 82f8b28353
28 files changed
+1210

No files matched your search

+2
View File
@@ -0,0 +1,2 @@
.ruby-lsp/
.env
+15
View File
@@ -0,0 +1,15 @@
# frozen_string_literal: true
source "https://rubygems.org"
group :development do
gem "irb"
gem "dotenv"
end
gem "roda"
gem "rackup"
gem "puma"
gem "tilt"
gem "erubi"
gem "mail"
+102
View File
@@ -0,0 +1,102 @@
GEM
remote: https://rubygems.org/
specs:
date (3.6.0)
dotenv (3.2.0)
erb (6.0.7)
erubi (1.13.1)
io-console (0.9.4)
irb (1.18.0)
pp (>= 0.6.0)
prism (>= 1.3.0)
rdoc (>= 4.0.0)
reline (>= 0.4.2)
logger (1.7.0)
mail (2.9.1)
logger
mini_mime (>= 0.1.1)
net-imap
net-pop
net-smtp
mini_mime (1.1.5)
net-imap (0.6.8)
date
net-protocol
net-pop (0.1.2)
net-protocol
net-protocol (0.4.0)
timeout
net-smtp (0.5.2)
net-protocol
nio4r (2.7.5)
pp (0.6.4)
prettyprint
prettyprint (0.2.1)
prism (1.9.0)
puma (8.0.2)
nio4r (~> 2.0)
rack (3.2.7)
rackup (2.3.1)
rack (>= 3)
rbs (4.2.0)
logger
prism (>= 1.6.0)
tsort
rdoc (8.1.0)
erb
prism (>= 1.6.0)
rbs (>= 4.0.0)
tsort
reline (0.7.0)
io-console (~> 0.5)
roda (3.109.0)
rack
tilt (2.9.0)
timeout (0.6.1)
tsort (0.2.0)
PLATFORMS
ruby
x86_64-linux
DEPENDENCIES
dotenv
erubi
irb
mail
puma
rackup
roda
tilt
CHECKSUMS
date (3.6.0) sha256=18ac945c4e24ebd93534f8eab8c2fd8c5604b3e977105b3798d62a1e8d27b580
dotenv (3.2.0) sha256=e375b83121ea7ca4ce20f214740076129ab8514cd81378161f11c03853fe619d
erb (6.0.7) sha256=c5ca6dc25b0ef974a44dc8f59fe847577122483b1968a38dec305c60bf91ee92
erubi (1.13.1) sha256=a082103b0885dbc5ecf1172fede897f9ebdb745a4b97a5e8dc63953db1ee4ad9
io-console (0.9.4) sha256=a403304f32928ee85e56d457b4612ca43f2703b561a3258844992bd24085fbb1
irb (1.18.0) sha256=de9454a0703a54704b9811a5ef31a60c86949fbf4013fcf244fabc7c775248e3
logger (1.7.0) sha256=196edec7cc44b66cfb40f9755ce11b392f21f7967696af15d274dde7edff0203
mail (2.9.1) sha256=06574eca475253d6c18145dd70af80d0eb970182d55053497c5f4d797ea160e8
mini_mime (1.1.5) sha256=8681b7e2e4215f2a159f9400b5816d85e9d8c6c6b491e96a12797e798f8bccef
net-imap (0.6.8) sha256=eb30bb62227b64a3af6b518b04b2375113d69f68f15de59b0193b07d98acf6d9
net-pop (0.1.2) sha256=848b4e982013c15b2f0382792268763b748cce91c9e91e36b0f27ed26420dff3
net-protocol (0.4.0) sha256=f9f90c8c6f64794a45160bf422177a336db12809de3beeeaa26b88fcd2e8c853
net-smtp (0.5.2) sha256=35103cc04d6b2d94632f9928ede07483c24b70b9c0db1f231fea43909b678f3c
nio4r (2.7.5) sha256=6c90168e48fb5f8e768419c93abb94ba2b892a1d0602cb06eef16d8b7df1dca1
pp (0.6.4) sha256=dfcb0fce700c41456265922884f9fe195d7fbb0674a3578e6c0f69588e82b570
prettyprint (0.2.1) sha256=d555d57ea6d7cf001d4774b693546a6bd88bec1e778ddffb5c60b68ceec4b7d4
prism (1.9.0) sha256=7b530c6a9f92c24300014919c9dcbc055bf4cdf51ec30aed099b06cd6674ef85
puma (8.0.2) sha256=c8ed871dfbbe66448ea9ffd46692342d9804d4071522b52b5331b7b6e7b686fb
rack (3.2.7) sha256=93e13e1c24f93556671d85d2d79fa228c3485815c50d7e2f265b5330c6528fb7
rackup (2.3.1) sha256=6c79c26753778e90983761d677a48937ee3192b3ffef6bc963c0950f94688868
rbs (4.2.0) sha256=51f7b886dcc05bc09e10b901daa6a81829f6adc03101d6ca9ea4aac6103e0674
rdoc (8.1.0) sha256=befc37880a5cfd36dcb176c748b5fd5ee39dd3536a75e81824e4972ce230f60a
reline (0.7.0) sha256=5b012d8e55dbf9d450f12bde2cf7d15ff546ae80b3f8f3b30e570d431815583d
roda (3.109.0) sha256=470f60355043a7732edb08ece2d12eb2e6912866ac87106c92ded5f6f8a5a8dc
tilt (2.9.0) sha256=da5735d0280bba96e9a91041bb14aee435ccad5c17b0fa519249ae543d9aa3a5
timeout (0.6.1) sha256=78f57368a7e7bbadec56971f78a3f5ecbcfb59b7fcbb0a3ed6ddc08a5094accb
tsort (0.2.0) sha256=9650a793f6859a43b6641671278f79cfead60ac714148aabe4e3f0060480089f
BUNDLED WITH
4.0.20
+34
View File
@@ -0,0 +1,34 @@
# netig.net
## Développement
Installer les dépendances :
```sh
bundle install
```
Créer un fichier `.env` à la racine du projet :
```dotenv
SESSION_SECRET=...
SMTP_PASSWORD=...
```
Générer `SESSION_SECRET` avec `openssl rand -hex 64` et conserver la valeur dans `.env`.
Démarrer le serveur de développement :
```sh
bundle exec rackup
```
Ou ouvrir un shell interactif :
```sh
bundle exec irb -r dotenv/load -r ./netig.rb
```
## Production
Docker Compose fournit les variables avec `env_file` et définit `RACK_ENV=production`.
+4
View File
@@ -0,0 +1,4 @@
require "dotenv/load" if ENV.fetch("RACK_ENV", "development") == "development"
require_relative "netig"
run Netig.freeze.app
+13
View File
@@ -0,0 +1,13 @@
require "mail"
Mail.defaults do
delivery_method :smtp, {
:address => "mail.netig.net",
:port => 587,
:domain => "netig.net",
:user_name => "noreply@netig.net",
:password => ENV.fetch("SMTP_PASSWORD"),
:authentication => "plain",
:enable_starttls => :always
}
end
+36
View File
@@ -0,0 +1,36 @@
class ContactForm
LIMITS = {
"email" => 254,
"name" => 128,
"subject" => 200,
"message" => 5000
}.freeze
def initialize(params)
@params = params
end
def spam?
!@params["website"].to_s.empty?
end
def valid?
fields_valid = LIMITS.all? do |key, max|
value = @params[key]
value.is_a?(String) &&
value.valid_encoding? &&
!value.strip.empty? &&
value.strip.length <= max
end
return false unless fields_valid
email_valid = @params["email"].strip.match?(/\A[^\s@]+@[^\s@]+\.[^\s@]+\z/)
headers_valid = %w[name subject].none? do |key|
@params[key].match?(/[\r\n]/)
end
email_valid && headers_valid
end
end
+27
View File
@@ -0,0 +1,27 @@
require "mail"
class ContactMailer
def initialize(params)
@params = params
end
def build
email = @params["email"]
name = @params["name"]
subject = @params["subject"]
message = @params["message"]
Mail.new do
from "noreply@netig.net"
to "contact@netig.net"
reply_to email
content_type "text/plain; charset=UTF-8"
subject subject
body "Nom : #{name}\n\n#{message}"
end
end
def deliver
build.deliver
end
end
+35
View File
@@ -0,0 +1,35 @@
require "roda"
require_relative "config/mail"
require_relative "lib/contact_form"
require_relative "lib/contact_mailer"
class Netig < Roda
plugin :render, escape: true
plugin :public
plugin :default_headers, "Content-Type" => "text/html; charset=utf-8"
plugin :sessions, secret: ENV.fetch("SESSION_SECRET")
plugin :route_csrf
plugin :hash_branches
plugin :flash
require_relative "routes/contact"
route do |r|
r.public
r.hash_branches
r.root do
@canonical_url = "https://netig.net/"
view "index"
end
r.get "legal" do
@page_title = "Mentions légales — NETig"
@page_description = "Mentions légales de l'association NETig."
@canonical_url = "https://netig.net/legal"
view "legal"
end
end
end
+551
View File
@@ -0,0 +1,551 @@
/* Polices
------------------------------------------------------------------------ */
@font-face {
font-family: "TitilliumWeb";
src: url("/fonts/TitilliumWeb-Regular.woff2") format("woff2");
font-weight: 400;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: "TitilliumWeb";
src: url("/fonts/TitilliumWeb-Bold.woff2") format("woff2");
font-weight: 700;
font-style: normal;
font-display: swap;
}
/* Couleurs
------------------------------------------------------------------------ */
:root {
/* Fonds */
--color-background: #2f3e46;
--color-surface: #354f52;
--color-surface-dark: #243138;
/* Texte et accents */
--color-text: #cad2c5;
--color-link: #a9cecf;
--color-accent: #a8c9a5;
--color-highlight: #ebdbb2;
--color-heading-soft: #c7d9c9;
/* Messages */
--color-flash-notice-background: #294e43;
--color-flash-error-background: #2c4647;
--color-flash-error-border: #e6afa2;
/* Ombres */
--color-shadow-light: rgb(202 210 197 / 20%);
--color-shadow-dark: rgb(0 0 0 / 8%);
}
/* Structure et mise en page
------------------------------------------------------------------------ */
*,
*::before,
*::after {
box-sizing: border-box;
}
html {
scroll-behavior: smooth;
}
body {
display: flex;
flex-direction: column;
min-height: 100vh;
min-height: 100dvh;
margin: 0;
background: var(--color-background);
color: var(--color-text);
font-family: "TitilliumWeb", sans-serif;
font-size: 1.4rem;
}
main {
display: flex;
flex: 1;
min-width: 0;
flex-direction: column;
}
/* Image sur les sections alternées de l'accueil et les pages intérieures. */
main > section {
background-color: var(--color-background);
}
main > section:nth-of-type(odd):not(:only-of-type),
.page-section {
background-color: var(--color-surface);
background-image:
linear-gradient(rgb(15 40 55 / 74%), rgb(15 40 55 / 74%)),
url("/images/background.webp");
background-position: center;
background-size: cover;
background-repeat: no-repeat;
}
.content {
width: 100%;
max-width: 1200px;
margin-inline: auto;
padding: 20px;
}
.prose {
max-width: 72ch;
line-height: 1.6;
}
/* Une seule feuille de lecture sur les pages intérieures. */
.page-section {
flex: 1;
padding: clamp(24px, 5vw, 72px) 20px;
}
.page-panel {
max-width: 1000px;
padding: clamp(24px, 4vw, 48px);
border-radius: 16px;
background: var(--color-background);
}
.page-panel.prose {
max-width: 72ch;
}
.section-services,
.section-hosting {
padding-bottom: 100px;
}
/* Typographie et liens
------------------------------------------------------------------------ */
h1,
h2,
h3,
h4 {
color: var(--color-text);
font-weight: 700;
text-align: left;
}
h1 {
margin-block: 0.67em;
font-size: 2.8rem;
line-height: 1.1;
}
h2 {
padding-left: 14px;
border-left: 4px solid var(--color-highlight);
color: var(--color-highlight);
font-size: 2.6rem;
line-height: 1.15;
}
h3 {
width: fit-content;
padding-bottom: 0.25rem;
border-bottom: 2px solid var(--color-accent);
color: var(--color-highlight);
font-size: 1.9rem;
line-height: 1.2;
}
h4 {
color: var(--color-heading-soft);
font-size: 1.4rem;
line-height: 1.25;
}
a {
color: var(--color-link);
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
a:focus-visible,
button:focus-visible,
input:focus-visible,
textarea:focus-visible,
select:focus-visible,
summary:focus-visible {
outline: 3px solid var(--color-accent);
outline-offset: 3px;
}
.skip-link {
position: fixed;
top: 10px;
left: 10px;
z-index: 100;
padding: 8px 12px;
background: var(--color-text);
color: var(--color-background);
transform: translateY(-200%);
}
.skip-link:focus {
transform: translateY(0);
}
/* En-tête et navigation
------------------------------------------------------------------------ */
.topbar {
display: flex;
min-height: 70px;
flex-wrap: wrap;
align-items: center;
text-align: left;
background: var(--color-surface);
border-bottom: 1px solid rgb(202 210 197 / 18%);
}
.topbar a {
padding-left: 20px;
}
.topbar a:hover {
color: var(--color-text);
}
.topbar a.topbar__account {
margin-left: auto;
margin-right: 20px;
padding: 8px 14px;
border: 1px solid var(--color-accent);
color: var(--color-accent);
}
.topbar a.topbar__account:hover {
background: var(--color-accent);
color: var(--color-background);
text-decoration: none;
}
.topbar img {
display: block;
width: 48px;
height: 48px;
}
.logo {
display: flex;
align-items: center;
justify-content: center;
}
.logo img {
display: block;
width: 100%;
max-width: 340px;
height: auto;
}
.hero p {
font-size: 1.6rem;
}
.hero h1 {
font-size: clamp(2.8rem, 6vw, 4rem);
}
.hero__lead {
margin-bottom: 0;
}
.hero__actions {
display: flex;
flex-wrap: wrap;
gap: 12px;
margin-top: 28px;
}
/* Boutons et cartes
------------------------------------------------------------------------ */
.button {
display: inline-block;
padding: 10px 16px;
border: 2px solid var(--color-accent);
background: var(--color-accent);
color: var(--color-background);
font-weight: 700;
transition: filter 0.2s ease;
}
.button:hover {
filter: brightness(1.12);
text-decoration: none;
}
.button--secondary {
display: inline-flex;
align-items: center;
gap: 8px;
border-color: var(--color-link);
background: transparent;
color: var(--color-link);
}
.box {
display: flex;
min-width: 0;
flex-direction: column;
justify-content: space-between;
margin-top: 80px;
padding: 20px 20px 40px;
border: 2px solid var(--color-text);
box-shadow: 0 0 5px var(--color-shadow-light), 0 4px 4px var(--color-shadow-dark);
}
.box img {
display: block;
max-width: 96px;
margin-inline: auto;
}
.box__title {
margin-block: 0;
padding: 10px;
border-bottom: 0;
background: var(--color-background);
color: var(--color-text);
translate: 0 -55px;
}
/* Bordure supérieure interrompue autour des titres, sans masquer la photo. */
.section-hosting .box {
border-top: 0;
background: rgb(15 40 55 / 30%);
}
.section-hosting .box__title {
display: flex;
align-items: center;
gap: 8px;
width: auto;
margin-inline: -22px;
padding: 10px 0;
background: transparent;
translate: 0 calc(-50% - 20px);
}
.section-hosting .box__title::before,
.section-hosting .box__title::after {
content: "";
flex: 1;
border-top: 2px solid var(--color-text);
}
.section-hosting .box__title::before {
flex: 0 0 20px;
}
.box__link {
padding: 20px;
color: var(--color-text);
text-align: center;
transition: transform 0.2s ease, border-color 0.2s ease;
}
.box__link:hover {
text-decoration: none;
}
.service-icon {
margin-top: -20px;
margin-bottom: 10px;
}
/* Couleur des cartes selon leur position. */
.section-services .box:nth-child(3n + 1) {
--service-accent: var(--color-link);
}
.section-services .box:nth-child(3n + 2) {
--service-accent: var(--color-accent);
}
.section-services .box:nth-child(3n + 3) {
--service-accent: var(--color-highlight);
}
.section-services .box__title {
color: var(--service-accent);
}
.section-services .box__link:focus-visible {
border-color: var(--service-accent);
}
/* Formulaires et messages
------------------------------------------------------------------------ */
.contact-form {
display: grid;
gap: 10px;
font-size: 1rem;
font-weight: 700;
}
.contact-form input,
.contact-form textarea {
width: 100%;
margin: 0;
padding: 10px;
border: 0;
font-family: inherit;
font-size: 1rem;
}
/* Ne pas appliquer le fond clair au bouton d'envoi. */
.contact-form input:not([type="submit"]),
.contact-form textarea {
background: var(--color-text);
color: var(--color-background);
}
.contact-form textarea {
min-height: 150px;
resize: vertical;
box-shadow: 0 0 10px var(--color-surface-dark);
}
.contact-form input:not([type="submit"]):focus-visible,
.contact-form textarea:focus-visible {
outline-color: var(--color-surface);
}
.submit {
width: 100%;
background: var(--color-accent);
color: var(--color-background);
font-weight: 700;
cursor: pointer;
}
.honeypot {
position: absolute;
left: -10000px;
width: 1px;
height: 1px;
overflow: hidden;
}
.flash {
margin: 0 0 1rem;
padding: 0.75rem 1rem;
border-left: 3px solid;
}
.flash--notice {
background-color: var(--color-flash-notice-background);
border-color: var(--color-accent);
color: var(--color-text);
}
.flash--error {
background-color: var(--color-flash-error-background);
border-color: var(--color-flash-error-border);
color: var(--color-text);
}
/* Pied de page
------------------------------------------------------------------------ */
footer {
padding: 40px 20px;
background: var(--color-surface-dark);
box-shadow: 0 0 20px var(--color-surface-dark);
}
.botbar {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
font-size: 1rem;
text-align: center;
}
.botbar p {
margin-inline: auto;
}
/* Adaptations et accessibilité
------------------------------------------------------------------------ */
@media screen and (min-width: 1080px) {
.col--1-1,
.col--1-2,
.col--1-1-1 {
display: grid;
gap: 40px;
}
.col--1-1 {
grid-template-columns: repeat(2, 1fr);
}
.col--1-2 {
grid-template-columns: 1fr 2fr;
}
.col--1-1-1 {
grid-template-columns: repeat(3, 1fr);
}
}
/* Effets au survol sur les écrans et périphériques adaptés. */
@media (hover: hover) and (min-width: 1080px) {
.box__link:hover {
transform: scale(1.04);
}
.section-services .box__link:hover {
border-color: var(--service-accent);
}
}
@media screen and (max-width: 600px) {
.box {
margin-top: 60px;
padding: 20px;
}
.section-services,
.section-hosting {
padding-bottom: 60px;
}
footer {
padding: 24px 20px;
}
}
@media (prefers-reduced-motion: reduce) {
html {
scroll-behavior: auto;
}
.box__link,
.button {
transition: none;
}
.box__link:hover {
transform: none;
}
}
Binary file not shown.
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 625 KiB

+4
View File
@@ -0,0 +1,4 @@
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" fill="none" stroke="#a9cecf" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<rect x="3" y="3" width="18" height="18" rx="2"/>
<path d="M6 7h2 M11 7h7 M6 12h2 M11 12h7 M6 17h2 M11 17h7"/>
</svg>

After

Width:  |  Height:  |  Size: 276 B

+3
View File
@@ -0,0 +1,3 @@
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" fill="none" stroke="#cad2c5" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M3 13.6493C3 16.6044 5.41766 19 8.4 19L16.5 19C18.9853 19 21 16.9839 21 14.4969C21 12.6503 19.8893 10.9449 18.3 10.25C18.1317 7.32251 15.684 5 12.6893 5C10.3514 5 8.34694 6.48637 7.5 8.5C4.8 8.9375 3 11.2001 3 13.6493Z"/>
</svg>

After

Width:  |  Height:  |  Size: 394 B

+3
View File
@@ -0,0 +1,3 @@
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" fill="none" stroke="#ebdbb2" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M12 21V11M12 11L9 14M12 11L15 14M7 16.8184C4.69636 16.2074 3 14.1246 3 11.6493C3 9.20008 4.8 6.9375 7.5 6.5C8.34694 4.48637 10.3514 3 12.6893 3C15.684 3 18.1317 5.32251 18.3 8.25C19.8893 8.94488 21 10.6503 21 12.4969C21 14.8148 19.25 16.7236 17 16.9725"/>
</svg>

After

Width:  |  Height:  |  Size: 428 B

+37
View File
@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
version="1.1"
id="svg2"
width="2094.5647"
height="1495.7888"
viewBox="0 0 2094.5647 1495.7888"
sodipodi:docname="logo_dark.png"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs6" />
<sodipodi:namedview
id="namedview4"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
showgrid="false" />
<g
inkscape:groupmode="layer"
inkscape:label="Image"
id="g8"
transform="translate(-308.12363,-531.00464)">
<path
style="fill:#cad2c5;stroke-width:1.33333"
d="m 1406.0532,2025.5807 c -74.9825,-8.6243 -146.7942,-38.3188 -206,-85.1823 -16.4809,-13.0452 -52.9941,-49.2609 -65.9309,-65.3937 -11.7067,-14.5989 -31.7085,-44.8465 -41.3224,-62.4897 -24.54,-45.0352 -38.8941,-88.4986 -48.7165,-147.5103 -8.0876,-48.5895 -20.8866,-86.9065 -40.974,-122.6667 -54.45849,-96.9482 -145.00236,-159.3456 -251.63203,-173.4093 -19.50421,-2.5724 -58.86989,-2.478 -79.63514,0.1912 -67.68994,8.7007 -132.9166,41.3512 -178.22074,89.2119 -40.29541,42.5693 -64.62434,91.5909 -74.44665,150.0062 -3.19459,18.999 -3.19116,57.918 0.007,77.3334 9.62184,58.4153 37.1521,110.0962 77.53824,145.5578 32.4415,28.4856 65.41481,44.8746 108.66666,54.0111 17.12019,3.6165 59.97007,3.318 77.33334,-0.5387 47.69634,-10.5941 86.59273,-34.7861 113.51018,-70.5989 46.41784,-61.7573 44.48291,-143.4735 -4.64754,-196.2741 -6.81191,-7.3208 -23.99176,-19.5356 -34.47438,-24.5114 -27.65698,-13.1277 -63.54624,-13.8964 -87.28005,-1.8696 -36.86617,18.6815 -52.62061,59.4991 -33.62267,87.1116 5.63298,8.1874 14.56206,13.0743 23.82914,13.0422 8.67582,-0.031 12.868,-2.386 17.97337,-10.1008 8.06559,-12.1879 26.96733,-11.9592 37.41123,0.4526 25.60878,30.4344 3.17233,80.2267 -42.69928,94.761 -7.91499,2.5078 -12.37264,2.9572 -29.33334,2.9572 -17.33817,0 -21.24218,-0.4112 -29.33333,-3.0895 -46.28136,-15.32 -78.4158,-54.2183 -86.76373,-105.0264 -5.64287,-34.3443 1.60986,-72.4279 19.7839,-103.8841 25.95592,-44.9254 70.8461,-76.2739 126.34508,-88.2318 17.79047,-3.833 61.15974,-3.489 79.96808,0.6343 19.66531,4.3113 32.9486,8.8095 50.61192,17.1388 70.05614,33.0359 119.58232,102.1564 131.3354,183.2964 2.7155,18.7471 2.67887,54.1851 -0.0752,72.7885 -17.25493,116.5543 -106.17216,209.8236 -225.20542,236.2284 -93.19772,20.6739 -192.44179,-2.7918 -269.73448,-63.777 -16.43848,-12.9703 -41.22532,-37.3099 -53.6262,-52.6587 -22.79115,-28.2091 -47.3443,-72.3513 -58.63694,-105.4189 -9.33166,-27.3254 -16.14933,-57.725 -18.64601,-83.1414 -1.71719,-17.4809 -1.71428,-58.3008 0.005,-74.8586 7.74724,-74.5975 37.7685,-146.0334 86.01208,-204.6667 12.5498,-15.2525 38.9568,-41.7071 54.62623,-54.7245 43.09312,-35.7998 99.92209,-64.4729 157.09939,-79.2642 41.02978,-10.6141 73.79994,-14.1591 118.90061,-12.8623 51.74559,1.4878 96.43257,10.9062 150.42723,31.7047 96.01306,36.9839 197.05175,33.3345 284.76295,-10.2855 65.3627,-32.5056 114.4587,-80.8821 146.7187,-144.5683 36.5119,-72.0803 42.9397,-153.37261 18.0967,-228.86812 -10.2929,-31.27921 -28.2874,-64.21108 -48.7031,-89.13185 -10.2717,-12.5384 -32.8619,-34.25199 -45.9971,-44.21208 -65.9866,-50.03641 -152.5652,-65.36784 -227.5006,-40.28603 -57.18814,19.14156 -104.29813,59.99487 -129.00161,111.86884 -25.63992,53.8404 -26.42022,110.73946 -2.22269,162.07744 38.19356,81.0323 132.0996,115.1711 202.6812,73.6833 13.7313,-8.0713 31.909,-26.9386 38.9858,-40.4648 8.7623,-16.748 11.4702,-28.5956 10.7869,-47.19602 -0.6566,-17.87794 -3.1871,-25.97886 -12.2625,-39.25754 -14.2127,-20.79518 -39.4174,-29.6907 -57.7657,-20.38727 -11.6547,5.90951 -17.1223,17.325 -12.9493,27.03604 5.4376,12.65368 5.0509,19.24024 -1.5929,27.13596 -5.7873,6.8778 -13.0392,9.78196 -24.4639,9.79701 -8.4784,0.0107 -11.3308,-0.62354 -18.74665,-4.17138 -22.71699,-10.86819 -37.59176,-39.15787 -35.3529,-67.23611 4.34406,-54.48001 54.34085,-96.08481 115.43285,-96.05752 73.5528,0.0329 135.9644,55.8974 151.5703,135.67016 3.6332,18.57212 3.0606,51.36797 -1.2454,71.33327 -18.4323,85.4623 -87.6684,149.7119 -178.9915,166.1 -10.0215,1.7984 -20.1226,2.3861 -40.6667,2.366 -24.4878,-0.024 -29.20335,-0.4075 -45.29673,-3.6856 -23.85795,-4.8596 -42.35299,-11.1284 -63.3699,-21.4789 -20.93524,-10.3102 -33.00458,-17.9879 -50.76522,-32.2933 -48.14744,-38.7806 -83.21423,-97.1946 -95.85523,-159.6748 -4.45787,-22.03376 -5.28895,-31.62064 -5.25911,-60.66667 0.026,-25.34852 0.49451,-32.48079 3.02134,-46 6.85533,-36.67784 13.254,-56.34989 28.1898,-86.66667 17.43309,-35.3858 35.0991,-59.62754 64.20665,-88.10598 52.80832,-51.66698 124.97245,-85.19306 199.0267,-92.46398 18.679,-1.83397 57.1585,-1.83809 73.8209,-0.008 113.491,12.46587 216.1056,78.34559 276.141,177.28571 37.0675,61.08833 54.6369,121.09476 58.1555,198.62548 0.9826,21.64771 3.0079,33.44571 8.9266,52.00001 16.8862,52.9362 55.7344,98.8275 101.5962,120.0157 54.187,25.0344 112.8288,18.1774 165.4615,-19.3475 12.8653,-9.1725 40.6667,-34.5278 40.6667,-37.0887 0,-0.8526 -9.5826,-11.1567 -21.2946,-22.8982 l -21.2945,-21.3479 9.388,-14.3333 c 5.1635,-7.8834 9.8023,-14.3334 10.3084,-14.3334 0.5063,0 11.7036,10.7956 24.8829,23.9903 l 23.9626,23.9902 9.0236,-8.9545 c 4.9629,-4.9249 9.0236,-9.5765 9.0236,-10.3367 0,-0.7602 -11.4,-12.7704 -25.3334,-26.6893 -13.9333,-13.9188 -25.3333,-25.7679 -25.3333,-26.3312 0,-1.5604 17.6084,-27.66874 18.6608,-27.66874 0.5064,0 13.1381,12.3 28.0707,27.33334 14.9325,15.0333 27.878,27.3333 28.7678,27.3333 0.8898,0 5.5852,-4.0264 10.4343,-8.9476 l 8.8165,-8.9475 -30.0417,-30.06308 c -16.5229,-16.5347 -30.0417,-30.63007 -30.0417,-31.32306 0,-1.95165 17.8774,-28.70746 18.9492,-28.35989 0.5221,0.16931 15.Line truncated
id="path170" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 12 KiB

+3
View File
@@ -0,0 +1,3 @@
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M13.4142 3.82843C12.6332 3.04738 11.3668 3.04738 10.5858 3.82843L9.91421 4.5L11.482 6.06774C11.6472 6.02356 11.8208 6 12 6C13.1046 6 14 6.89543 14 8C14 8.17916 13.9764 8.35282 13.9323 8.51804L15.982 10.5677C16.1472 10.5236 16.3208 10.5 16.5 10.5C17.6046 10.5 18.5 11.3954 18.5 12.5C18.5 13.6046 17.6046 14.5 16.5 14.5C15.3954 14.5 14.5 13.6046 14.5 12.5C14.5 12.3208 14.5236 12.1472 14.5677 11.982L13 10.4142V15.2676C13.5978 15.6134 14 16.2597 14 17C14 18.1046 13.1046 19 12 19C10.8954 19 10 18.1046 10 17C10 16.2597 10.4022 15.6134 11 15.2676V9.73244C10.4022 9.38663 10 8.74028 10 8C10 7.82084 10.0236 7.64718 10.0677 7.48196L8.5 5.91421L3.82843 10.5858C3.04738 11.3668 3.04738 12.6332 3.82843 13.4142L10.5858 20.1716C11.3668 20.9526 12.6332 20.9526 13.4142 20.1716L20.1716 13.4142C20.9526 12.6332 20.9526 11.3668 20.1716 10.5858L13.4142 3.82843ZM9.17157 2.41421C10.7337 0.852115 13.2663 0.852119 14.8284 2.41422L21.5858 9.17157C23.1479 10.7337 23.1479 13.2663 21.5858 14.8284L14.8284 21.5858C13.2663 23.1479 10.7337 23.1479 9.17157 21.5858L2.41421 14.8284C0.852115 13.2663 0.852119 10.7337 2.41422 9.17157L9.17157 2.41421Z" fill="#cad2c5"/>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

+8
View File
@@ -0,0 +1,8 @@
<svg viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg" fill="none" stroke="#cad2c5" stroke-width="2.667" stroke-linecap="round" stroke-linejoin="round">
<g>
<polyline points="2,16 12,22 22,16 "/>
<path d="M18,11H6c-2.2,0-4,1.8-4,4v10c0,2.2,1.8,4,4,4h12c2.2,0,4-1.8,4-4V15C22,12.8,20.2,11,18,11z"/>
<line x1="21.5" y1="13.1" x2="30" y2="8"/>
<path d="M22,21h4c2.2,0,4-1.8,4-4V7c0-2.2-1.8-4-4-4H14c-2.2,0-4,1.8-4,4v4"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 455 B

+3
View File
@@ -0,0 +1,3 @@
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" fill="none" stroke="#cad2c5" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M21 8L17.4392 9.97822C15.454 11.0811 14.4614 11.6326 13.4102 11.8488C12.4798 12.0401 11.5202 12.0401 10.5898 11.8488C9.53864 11.6326 8.54603 11.0811 6.5608 9.97822L3 8M6.2 19H17.8C18.9201 19 19.4802 19 19.908 18.782C20.2843 18.5903 20.5903 18.2843 20.782 17.908C21 17.4802 21 16.9201 21 15.8V8.2C21 7.0799 21 6.51984 20.782 6.09202C20.5903 5.71569 20.2843 5.40973 19.908 5.21799C19.4802 5 18.9201 5 17.8 5H6.2C5.0799 5 4.51984 5 4.09202 5.21799C3.71569 5.40973 3.40973 5.71569 3.21799 6.09202C3 6.51984 3 7.07989 3 8.2V15.8C3 16.9201 3 17.4802 3.21799 17.908C3.40973 18.2843 3.71569 18.5903 4.09202 18.782C4.51984 19 5.07989 19 6.2 19Z"/>
</svg>

After

Width:  |  Height:  |  Size: 811 B

+4
View File
@@ -0,0 +1,4 @@
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" fill="none" stroke="#cad2c5" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M8.5 8.5a3.5 3.5 0 0 1 7 0c0 2.3-3.5 2.7-3.5 6"/>
<circle cx="12" cy="19" r="1.25" fill="#cad2c5" stroke="none"/>
</svg>

After

Width:  |  Height:  |  Size: 288 B

+3
View File
@@ -0,0 +1,3 @@
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" fill="none" stroke="#a8c9a5" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M4 3H20 M4 6H20 M4 9H20 M4 12H20 M4 15H20 M4 18H20 M4 21H20"/>
</svg>

After

Width:  |  Height:  |  Size: 235 B

+4
View File
@@ -0,0 +1,4 @@
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" fill="none" stroke="#e6afa2" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="m19.5 13.572-7.5 7.428-2.896-2.868m-6.117-8.104a5 5 0 0 1 9.013-3.022 5 5 0 1 1 7.5 6.572"/>
<path d="m3 13h2l2 3 2-6 1 3h3"/>
</svg>

After

Width:  |  Height:  |  Size: 301 B

+37
View File
@@ -0,0 +1,37 @@
class Netig
hash_branch "contact" do |r|
r.is do
r.get do
@page_title = "Contact — NETig"
@page_description = "Contacter NETig pour toute question concernant ses services."
@canonical_url = "https://netig.net/contact"
view "contact"
end
end
r.post "send" do
check_csrf!
form = ContactForm.new(r.params)
if form.spam?
flash["notice"] = "Votre message a été reçu."
r.redirect "/contact"
elsif form.valid?
begin
ContactMailer.new(r.params).deliver
flash["notice"] = "Votre message a été envoyé."
rescue Net::SMTPError, SocketError, SystemCallError, IOError, Timeout::Error, OpenSSL::SSL::SSLError => error
warn "Échec SMTP : #{error.class}"
flash["error"] = "L'envoi a échoué. Veuillez réessayer plus tard."
end
r.redirect "/contact"
else
response.status = 422
flash.now["error"] = "Veuillez vérifier les champs du formulaire."
view "contact"
end
end
end
end
+42
View File
@@ -0,0 +1,42 @@
<section class="page-section">
<div class="content page-panel">
<h1>Contact</h1>
<div class="col--1-1">
<div>
<p>Vous avez un projet en tête ? Un service vous intéresse ? Ou simplement une question ? Ce formulaire est là pour ça !</p>
</div>
<div>
<% if notice = flash["notice"] %>
<p class="flash flash--notice" role="status"><%= notice %></p>
<% end %>
<% if error = flash["error"] %>
<p class="flash flash--error" role="alert"><%= error %></p>
<% end %>
<form action="/contact/send" method="post" class="contact-form" accept-charset="UTF-8">
<%== csrf_tag("/contact/send") %>
<div class="honeypot" aria-hidden="true">
<label for="website">Site web</label>
<input id="website" type="text" name="website" tabindex="-1" autocomplete="off">
</div>
<label for="email">Email</label>
<input id="email" type="email" name="email" maxlength="254" autocomplete="email" required>
<label for="name">Nom</label>
<input id="name" type="text" name="name" maxlength="128" autocomplete="name" required>
<label for="subject">Objet</label>
<input id="subject" type="text" name="subject" maxlength="200" required>
<label for="message">Message</label>
<textarea id="message" name="message" cols="40" rows="10" maxlength="5000" required></textarea>
<input type="submit" value="Envoyer" class="submit">
</form>
</div>
</div>
</div>
</section>
+119
View File
@@ -0,0 +1,119 @@
<section class="hero-section">
<div class="content col--1-2 hero">
<div class="logo">
<img src="/images/favicon.svg" alt="Logo NETig">
</div>
<div>
<h1>NETig</h1>
<p class="hero__lead">Fournisseur associatif de <strong>services numériques libres, simples et indépendants</strong>, respectueux de la vie privée, à destination des particuliers, des associations et des petites entreprises.</p>
<div class="hero__actions">
<a class="button" href="/#association">Découvrir l'association ➜</a>
<a class="button button--secondary" href="https://status.netig.net/status/services" target="_blank" rel="noopener noreferrer">
<img src="/images/status.svg" alt="" width="32" height="32">
État des services ↗
</a>
</div>
</div>
</div>
</section>
<section id="services" class="section-services">
<div class="content">
<h2>Services en libre accès</h2>
<div class="col--1-1-1">
<a class="box box__link" href="https://calc.netig.net" target="_blank" rel="noopener noreferrer">
<h3 class="box__title">NETcalc ↗</h3>
<img class="service-icon" src="/images/calc.svg" alt="">
<p>Tableur collaboratif, alternative à Google Sheets.</p>
</a>
<a class="box box__link" href="https://pad.netig.net" target="_blank" rel="noopener noreferrer">
<h3 class="box__title">NETpad ↗</h3>
<img class="service-icon" src="/images/pad.svg" alt="">
<p>Écriture collaborative, alternative à Google Docs.</p>
</a>
<a class="box box__link" href="https://drop.netig.net" target="_blank" rel="noopener noreferrer">
<h3 class="box__title">NETdrop ↗</h3>
<img class="service-icon" src="/images/drop.svg" alt="">
<p>Partage de fichiers, alternative à Google Drive.</p>
</a>
</div>
</div>
</section>
<section id="hosting" class="section-hosting">
<div class="content">
<h2>Services réservés aux adhérents</h2>
<p><strong>L'adhésion à NETig est gratuite !</strong> <a href="/url/provisoire">Créez votre compte</a> pour demander à rejoindre l'association et profiter de ses services.</p>
<div class="col--1-1">
<div class="box">
<h3 class="box__title">NETmail — Adresse mail</h3>
<div class="col--1-2">
<div>
<img src="/images/mail.svg" alt="">
</div>
<div>
<p>Obtenez une adresse e-mail @netig.net ou utilisez votre propre nom de domaine. Consultez vos messages depuis un navigateur ou votre logiciel de messagerie habituel.</p>
</div>
</div>
</div>
<div class="box">
<h3 class="box__title">NETcloud — Fichiers en ligne</h3>
<div class="col--1-2">
<div>
<img src="/images/cloud.svg" alt="">
</div>
<div>
<p>Conservez vos fichiers, photos et agendas en ligne et retrouvez-les depuis vos différents appareils. Une suite bureautique est également disponible.</p>
</div>
</div>
</div>
</div>
<div class="box">
<h3 class="box__title">NETlist — Listes de diffusion</h3>
<div class="col--1-2">
<div>
<img src="/images/list.svg" alt="">
</div>
<div>
<p>Créez des listes pour envoyer des actualités, des annonces ou des lettres d'information à vos abonnés. Proposez des formulaires d'inscription et des archives publiques, et utilisez une adresse @netig.net ou votre propre domaine pour vos envois.</p>
</div>
</div>
</div>
<div class="col--1-1">
<div class="box">
<h3 class="box__title">NETgit — Hébergement de code</h3>
<div class="col--1-2">
<div>
<img src="/images/git.svg" alt="">
</div>
<div>
<p>Un espace pour conserver, partager et gérer vos projets.</p>
</div>
</div>
</div>
<div class="box">
<h3 class="box__title">Autre</h3>
<div class="col--1-2">
<div>
<img src="/images/other.svg" alt="">
</div>
<div>
<p>Vous recherchez un service qui n'est pas présenté ici ? <a href="/contact">Contactez-nous</a> pour en discuter !</p>
</div>
</div>
</div>
</div>
<p>
Les services NETig reposent sur des logiciels libres.
<a href="/documentation/logiciels">Découvrez les logiciels utilisés ➜</a>
</p>
</div>
</section>
<section id="association" class="section-association">
<div class="content">
<h2>Aidez-nous à continuer !</h2>
<p>L'adhésion est gratuite et les services sont financés grâce aux dons. Votre soutien nous aide à couvrir les frais d'hébergement et à maintenir les services accessibles.</p>
<a class="button" href="/#association">Faire un don ➜</a>
</div>
</section>
+62
View File
@@ -0,0 +1,62 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<% title = @page_title || "NETig" %>
<% description = @page_description || "Services numériques libres, simples et indépendants, pour particuliers, associations et petites structures." %>
<title><%= title %></title>
<meta name="description" content="<%= description %>">
<meta name="theme-color" content="#1c1c1c">
<meta property="og:title" content="<%= title %>">
<meta property="og:description" content="<%= description %>">
<meta property="og:type" content="website">
<% if @canonical_url %>
<meta property="og:url" content="<%= @canonical_url %>">
<link rel="canonical" href="<%= @canonical_url %>">
<% end %>
<link rel="icon" type="image/svg+xml" href="/images/favicon.svg">
<link rel="stylesheet" href="/css/style.css">
</head>
<body>
<a class="skip-link" href="#main-content">Aller au contenu</a>
<header>
<nav class="topbar" aria-label="Accès aux services">
<% unless request.path == "/" %>
<a href="/">
<img src="/images/favicon.svg" alt="Accueil NETig">
</a>
<% end %>
<a href="https://webmail.netig.net" target="_blank" rel="noopener noreferrer">NETmail ↗</a>
<a href="https://cloud.netig.net" target="_blank" rel="noopener noreferrer">NETcloud ↗</a>
<a href="https://git.netig.net" target="_blank" rel="noopener noreferrer">NETgit ↗</a>
<a class="topbar__account" href="/login">Mon espace ➜</a>
</nav>
</header>
<main id="main-content">
<%== yield %>
</main>
<footer>
<div class="botbar">
<p>Contenu du site par Julien Debrousse — <a href="https://creativecommons.org/licenses/by/4.0/" target="_blank" rel="license noopener noreferrer">CC BY 4.0</a></p>
<p><a href="/legal">Mentions légales</a></p>
<p>Fait avec ❤️ et <a href="https://roda.jeremyevans.net/" target="_blank" rel="noopener noreferrer">Roda</a> !</p>
</div>
</footer>
</body>
</html>
+59
View File
@@ -0,0 +1,59 @@
<section class="page-section">
<div class="content prose page-panel">
<h1>Mentions légales</h1>
<p>
NETig — Association loi 1901<br>
Membres fondateurs : Julien Debrousse et John Doe<br>
Siège social : [adresse]<br>
RNA : [numéro]<br>
Directeur de la publication : [nom]
</p>
<h2 id="contact">Contact</h2>
<p>Il est possible de prendre contact par courriel à : <a href="mailto:contact@netig.net">contact@netig.net</a>.</p>
<h2 id="hebergement-des-donnees">Hébergement des données</h2>
<p>Les services sont hébergés sur des infrastructures administrées bénévolement par l'association chez <a href="https://www.hetzner.com/" target="_blank" rel="noopener noreferrer">Hetzner</a>. Le VPS principal fonctionne sous Debian. Des sauvegardes quotidiennes sont conservées sur une Storage Box Hetzner située en Finlande.</p>
<p>Hébergeur : Hetzner Online GmbH — [adresse et téléphone à compléter].</p>
<h2 id="conditions-generales-d-utilisation">Conditions générales d'utilisation</h2>
<h3 id="disponibilite">Disponibilité</h3>
<p>Malgré les efforts faits pour assurer la meilleure disponibilité possible, un accès permanent aux services n'est pas garanti. Vous pouvez consulter l'état des services en temps réel depuis un <a href="https://status.netig.net/status/services" target="_blank" rel="noopener noreferrer">outil de surveillance</a> mis à disposition. Vous pouvez aussi vous inscrire à la <a href="https://list.netig.net/subscription/form" target="_blank" rel="noopener noreferrer">liste de diffusion de maintenance</a>, afin d'être informé des interruptions de service.</p>
<h3 id="responsabilite">Responsabilité</h3>
<p>Vous êtes responsable des contenus diffusés et êtes tenu de respecter la législation en vigueur. Le non-respect des conditions d'utilisation ou des lois en vigueur peut entraîner une suspension des services ou une suppression des données et comptes concernés.</p>
<h3 id="donnees-personnelles">Données personnelles</h3>
<h4 id="confidentialite">Confidentialité</h4>
<p>Les données ne sont ni vendues ni utilisées à des fins publicitaires. Elles sont traitées uniquement pour gérer les adhésions, fournir, administrer et sécuriser les services, sous réserve des obligations légales applicables.</p>
<h4 id="conservation">Conservation</h4>
<p>Les données personnelles sont conservées pendant la durée nécessaire à la gestion des adhésions et à la mise à disposition des services, sous réserve des obligations légales de conservation. Elles peuvent persister pendant la durée de rétention des sauvegardes après la clôture des services.</p>
<h4 id="recuperation">Récupération</h4>
<p>Vous pouvez à tout moment récupérer vos données personnelles, soit à l'aide d'une fonctionnalité intégrée à un service, soit sur demande.</p>
<h4 id="suppression">Suppression</h4>
<p>Vous pouvez demander la suppression de vos données personnelles, soit à l'aide d'une fonctionnalité intégrée à un service, soit sur demande écrite, sous réserve des obligations légales de conservation.</p>
<h4 id="droits">Vos droits</h4>
<p>Vous pouvez exercer vos droits d'accès, de rectification, d'effacement et les autres droits prévus par la réglementation applicable en écrivant à <a href="mailto:contact@netig.net">contact@netig.net</a>. Vous pouvez également introduire une réclamation auprès de la CNIL.</p>
<h3 id="services-en-libre-acces">Services en libre accès</h3>
<p>Ces services sont accessibles à tous afin de proposer une alternative aux produits des GAFAM ou « Géants du web », respectueuse des données de chacun. Les ressources matérielles ne sont pas sans limites : utilisez-les avec bon sens. En cas d'abus et après un premier avertissement lorsque cela est possible, votre adresse IP pourra être bannie.</p>
<h3 id="services-adherents">Services réservés aux adhérents</h3>
<h4 id="adhesion">Adhésion</h4>
<p>L'adhésion à l'association est gratuite et soumise à validation conformément à ses statuts. Elle permet de demander l'accès aux services réservés aux adhérents, dans la limite des ressources disponibles. L'adhésion ne garantit pas l'attribution automatique d'un service.</p>
<h4 id="dons">Dons</h4>
<p>L'association est financée par des dons libres et volontaires destinés à couvrir ses frais de fonctionnement. Aucun don n'est obligatoire pour adhérer ou bénéficier des services. Les dons ne donnent droit à aucun accès ou avantage supplémentaire.</p>
<h4 id="suspension-et-resiliation">Suspension et résiliation</h4>
<p>Le non-respect des conditions d'utilisation peut entraîner une suspension ou une suppression des services concernés, notamment en cas d'abus. Vous pouvez à tout moment demander la désactivation d'un service et la suppression des données associées, sous réserve des obligations légales de conservation.</p>
</div>
</section>