This commit is contained in:
Philippe Pittoli 2025-05-06 20:28:34 +02:00
parent 3edb7b94cc
commit dcb0379858
6 changed files with 132 additions and 133 deletions

View file

@ -206,16 +206,12 @@ render { current_tab, authenticationForm, passwordRecoveryForm, newPasswordForm,
auth_form = [ Web.h3 "Authentication", render_auth_form ]
passrecovery_form =
[ Web.h3 "You forgot your password (or your login)"
, Web.div_content []
[ Web.p "Enter either your login or email and you'll receive a recovery token."
]
, Web.quote [ Web.p "Enter either your login or email and you'll receive a recovery token." ]
, render_password_recovery_form
]
newpass_form =
[ Web.h3 "You got the password recovery mail"
, Web.div_content []
[ Web.p "Nice! You get to choose your new password."
]
, Web.quote [ Web.p "Nice! You get to choose your new password." ]
, render_new_password_form
]

View file

@ -67,9 +67,9 @@ render _ = HH.div_
where
url_linuxfr = "https://linuxfr.org/news/netlibre-un-service-libre-et-un-nom-de-domaine-gratuit"
title = Web.h3
expl content = Web.div_content [] [ Web.explanation content ]
expl content = Web.quote [ Web.explanation content ]
p = Web.p
b x = Web.column_ [ Web.box [ Web.div_content [] x ] ]
b x = Web.column_ [ Web.box [ Web.quote x ] ]
render_description = Web.columns_ [ render_basics, render_no_expert, render_no_housing ]
render_update_why_and_contact = Web.columns_ [ render_updates, render_why, render_contact ]

View file

@ -88,7 +88,7 @@ render { mailValidationForm }
b e = Web.column_ [ Web.box e ]
mail_validation_form
= [ Web.h3 "Verify your account"
, Web.div_content [] [Web.explanation [Web.p "Email addresses must be validated within 30 minutes."]]
, Web.quote [Web.p "Email addresses must be validated within 30 minutes."]
, render_register_form
]

View file

@ -117,17 +117,17 @@ current_rr_modal selected_domain form rr_modal
render_introduction_text :: AcceptedRRTypes -> HH.HTML w i
render_introduction_text = case _ of
A -> Web.div_content [] [Web.explanation Explanations.a_introduction]
AAAA -> Web.div_content [] [Web.explanation Explanations.aaaa_introduction]
TXT -> Web.div_content [] [Web.explanation Explanations.txt_introduction]
CNAME -> Web.div_content [] [Web.explanation Explanations.cname_introduction]
NS -> Web.div_content [] [Web.explanation Explanations.ns_introduction]
A -> Web.quote Explanations.a_introduction
AAAA -> Web.quote Explanations.aaaa_introduction
TXT -> Web.quote Explanations.txt_introduction
CNAME -> Web.quote Explanations.cname_introduction
NS -> Web.quote Explanations.ns_introduction
_ -> HH.p_ []
modal_content_mx :: Array (HH.HTML w i)
modal_content_mx =
[ render_errors
, Web.div_content [] [Web.explanation Explanations.mx_introduction]
, Web.quote Explanations.mx_introduction
, side_text_for_name_input "domainMX"
, Web.input_with_side_text "domainMX" "" "www"
(action_update_form <<< Field.Domain)
@ -147,7 +147,7 @@ current_rr_modal selected_domain form rr_modal
modal_content_caa :: Array (HH.HTML w i)
modal_content_caa =
[ render_errors
, Web.div_content [] [Web.explanation Explanations.caa_introduction]
, Web.quote Explanations.caa_introduction
, side_text_for_name_input "domainCAA"
, Web.input_with_side_text "domainCAA" "" "www"
(action_update_form <<< Field.Domain)
@ -172,7 +172,7 @@ current_rr_modal selected_domain form rr_modal
modal_content_srv :: Array (HH.HTML w i)
modal_content_srv =
[ Web.div_content [] [Web.explanation Explanations.srv_introduction]
[ Web.quote Explanations.srv_introduction
, render_errors
, Web.box_input ("ttlSRV") "TTL" "1800"
(action_update_form <<< Field.TTL)
@ -188,12 +188,12 @@ current_rr_modal selected_domain form rr_modal
, Web.box_input ("portSRV") "Port of the service" "5061"
(action_update_form <<< Field.Port)
(maybe "" show form._rr.port)
, Web.div_content [] [Web.explanation [Web.p "The priority field is a numeric value that indicates the preference of the server (lower values indicate higher priority)."]]
, Web.quote [Web.p "The priority field is a numeric value that indicates the preference of the server (lower values indicate higher priority)."]
, Web.box_input ("prioritySRV") "Priority" "10"
(action_update_form <<< Field.Priority)
(maybe "" show form._rr.priority)
-- Web.div_content [] [Web.explanation Explanations.spf_introduction], Web.p "Modifiers provide additional instructions, such as explanations for SPF failures or redirecting SPF checks to another domain."
, Web.div_content [] [Web.explanation [Web.p "The weight field is a relative weight used when multiple servers have the same priority, determining how often they should be used."]]
-- Web.quote Explanations.spf_introduction, Web.p "Modifiers provide additional instructions, such as explanations for SPF failures or redirecting SPF checks to another domain."
, Web.quote [Web.p "The weight field is a relative weight used when multiple servers have the same priority, determining how often they should be used."]
, Web.box_input ("weightSRV") "Weight" "100"
(action_update_form <<< Field.Weight)
(maybe "" show form._rr.weight)
@ -201,7 +201,7 @@ current_rr_modal selected_domain form rr_modal
modal_content_spf :: Array (HH.HTML w i)
modal_content_spf =
[ Web.div_content [] [Web.explanation Explanations.spf_introduction]
[ Web.quote Explanations.spf_introduction
, render_errors
, side_text_for_name_input "domainSPF"
, Web.input_with_side_text "domainSPF" "" "Let this alone."
@ -216,7 +216,7 @@ current_rr_modal selected_domain form rr_modal
-- Just v -> Web.box_input "vSPF" "Version" "spf1" (action_update_form <<< Field.SPF_v) v
, Web.hr
, Web.box_with_tag [C.has_background_info_light] tag_mechanisms
[ Web.div_content [] [Web.explanation [Web.p "Mechanisms specify which mail servers are allowed to send mail for the domain and how to evaluate the sending mail servers IP address."] ]
[ Web.quote [Web.p "Mechanisms specify which mail servers are allowed to send mail for the domain and how to evaluate the sending mail servers IP address."]
, maybe (Web.p "You don't have any mechanism.") (Table.display_mechanisms (action_update_rr <<< SPF_remove_mechanism)) form._rr.mechanisms
, Web.hr
, Web.h4 "New mechanism"
@ -229,7 +229,7 @@ current_rr_modal selected_domain form rr_modal
]
, Web.hr
, Web.box_with_tag [C.has_background_success_light] tag_modifiers
[ Web.div_content [] [Web.explanation [Web.p "Modifiers provide additional instructions, such as explanations for SPF failures or redirecting SPF checks to another domain."] ]
[ Web.quote [Web.p "Modifiers provide additional instructions, such as explanations for SPF failures or redirecting SPF checks to another domain."]
, maybe (Web.p "You don't have any modifier.") (Table.display_modifiers (action_update_rr <<< SPF_remove_modifier)) form._rr.modifiers
, Web.hr
, Web.h4 "New modifier"
@ -242,7 +242,7 @@ current_rr_modal selected_domain form rr_modal
, Web.hr
, Web.box
[ Web.h3 "Default behavior"
, Web.div_content [] [Web.explanation Explanations.spf_default_behavior]
, Web.quote Explanations.spf_default_behavior
, Web.selection (action_update_rr <<< SPF_Qualifier) qualifier_types (maybe default_qualifier_str show_qualifier form._rr.q)
]
]
@ -255,7 +255,7 @@ current_rr_modal selected_domain form rr_modal
modal_content_dkim :: Array (HH.HTML w i)
modal_content_dkim =
[ Web.div_content [] [Web.explanation Explanations.dkim_introduction]
[ Web.quote Explanations.dkim_introduction
, render_errors
, side_text_for_name_input "domainDKIM"
, Web.input_with_side_text "domainDKIM" "" "default._domainkey"
@ -266,7 +266,7 @@ current_rr_modal selected_domain form rr_modal
(action_update_form <<< Field.TTL)
(show form._rr.ttl)
, Web.hr
, Web.div_content [] [Web.explanation Explanations.dkim_default_algorithms]
, Web.quote Explanations.dkim_default_algorithms
, Web.selection_field "idDKIMSignature" "Signature algo"
(action_update_rr <<< DKIM_sign_algo)
(map show DKIM.sign_algos)
@ -281,7 +281,7 @@ current_rr_modal selected_domain form rr_modal
modal_content_dmarc :: Array (HH.HTML w i)
modal_content_dmarc =
[ Web.div_content [] [Web.explanation Explanations.dmarc_introduction]
[ Web.quote Explanations.dmarc_introduction
, render_errors
, side_text_for_name_input "domainDMARC"
, Web.input_with_side_text "domainDMARC" "" "_dmarc"
@ -291,27 +291,27 @@ current_rr_modal selected_domain form rr_modal
, Web.box_input "ttlDMARC" "TTL" "1800" (action_update_form <<< Field.TTL) (show form._rr.ttl)
, Web.hr
, Web.div_content [] [Web.explanation Explanations.dmarc_policy]
, Web.quote Explanations.dmarc_policy
, Web.selection_field' "idDMARCPolicy" "Policy" (action_update_rr <<< DMARC_policy)
(A.zip DMARC.policies_txt DMARC.policies_raw)
(show form.tmp.dmarc.p)
, Web.div_content [] [Web.explanation Explanations.dmarc_sp_policy]
, Web.quote Explanations.dmarc_sp_policy
, Web.selection_field' "idDMARCPolicy_sp" "Policy for subdomains" (action_update_rr <<< DMARC_sp_policy)
(zip_nullable DMARC.policies_txt_with_null DMARC.policies_raw)
(maybe "-" show form.tmp.dmarc.sp)
, Web.hr
, Web.div_content [] [Web.explanation Explanations.dmarc_adkim]
, Web.quote Explanations.dmarc_adkim
, Web.selection_field' "idDMARCadkim" "Consistency Policy for DKIM" (action_update_rr <<< DMARC_adkim)
(zip_nullable DMARC.consistency_policies_txt DMARC.consistency_policies_raw)
(maybe "-" show form.tmp.dmarc.adkim)
, Web.div_content [] [Web.explanation Explanations.dmarc_aspf]
, Web.quote Explanations.dmarc_aspf
, Web.selection_field' "idDMARCaspf" "Consistency Policy for SPF" (action_update_rr <<< DMARC_aspf)
(zip_nullable DMARC.consistency_policies_txt DMARC.consistency_policies_raw)
(maybe "-" show form.tmp.dmarc.aspf)
, Web.hr
, Web.div_content [] [Web.explanation Explanations.dmarc_pct]
, Web.quote Explanations.dmarc_pct
, Web.box_input "idDMARCpct" "Sample rate (between 0 and 100)" "100" (action_update_rr <<< DMARC_pct) (maybe "100" show form.tmp.dmarc.pct)
, Web.hr
@ -320,7 +320,7 @@ current_rr_modal selected_domain form rr_modal
(maybe "-" show form.tmp.dmarc.fo)
, Web.hr
, Web.div_content [] [Web.explanation Explanations.dmarc_contact]
, Web.quote Explanations.dmarc_contact
, Web.box_with_tag [C.has_background_info_light] tag_aggregated_reports
[ maybe (Web.p "There is no address to send aggregated reports to.")
(Table.display_dmarc_mail_addresses (action_update_rr <<< DMARC_remove_rua))
@ -341,7 +341,7 @@ current_rr_modal selected_domain form rr_modal
] []
, Web.hr
, Web.div_content [] [Web.explanation Explanations.dmarc_ri]
, Web.quote Explanations.dmarc_ri
, Web.box_input "idDMARCri" "Report interval (in seconds)" "86400" (action_update_rr <<< DMARC_ri) (maybe "0" show form.tmp.dmarc.ri)
]

View file

@ -4,10 +4,8 @@ import Halogen.HTML.Properties as HP
import Web as Web
import CSSClasses as C
expl' :: forall w i. String -> HH.HTML w i
expl' text = expl [Web.p text]
expl :: forall w i. Array (HH.HTML w i) -> HH.HTML w i
expl content = Web.div_content [] [ Web.explanation content ]
expl :: forall w i. String -> HH.HTML w i
expl text = Web.quote [Web.p text]
expl_txt :: forall w i. String -> HH.HTML w i
expl_txt content = Web.explanation [ Web.p content ]
@ -17,30 +15,31 @@ col arr = Web.column_ [ Web.box arr ]
tokens :: forall w i. HH.HTML w i
tokens = HH.div_
[ Web.h3 "What are tokens?"
, expl' """
Tokens are a simple way to update a resource record (A or AAAA) with your current IP address.
"""
, expl """
Tokens are a simple way to update a resource record (A or AAAA) with your current IP address.
"""
, HH.p_ [ HH.text "Let's take an example: you have an A record (IPv4) pointing to your web server at home, "
, HH.text "but your ISP changes your IP address from time to time. "
, HH.text "You can ask for a token (which looks like "
, HH.u_ [HH.text "53be0c45-61c4-4d29-8ae9-c2cc8767603d"]
, HH.text ") for this specific entry, then make your server regularly visit the following website."
]
, expl [ HH.p_ [ HH.text "https://www.netlib.re/token-update/"
, HH.u_ [HH.text "<your-token>"]
]
]
, Web.quote
[ HH.p_ [ HH.text "https://www.netlib.re/token-update/"
, HH.u_ [HH.text "<your-token>"]
]
]
, Web.p "For example: https://www.netlib.re/token-update/53be0c45-61c4-4d29-8ae9-c2cc8767603d"
, Web.hr
, Web.h3 "How to automate the update of my IP address?"
, Web.p "On Linux, you can make your computer access the update link with the following command."
, expl [ Web.strong "wget https://www.netlib.re/token-update/<your-token>" ]
, Web.quote [ Web.strong "wget https://www.netlib.re/token-update/<your-token>" ]
, Web.p """
No need for a more complex program. This works just fine.
And you can run this command every hour.
For example, in your crontab (Linux and Unix related):
"""
, expl [ Web.strong "0 * * * * wget <url>" ]
, Web.quote [ Web.strong "0 * * * * wget <url>" ]
, Web.p """
Commands for other operating systems may differ, but you get the idea.
"""
@ -50,11 +49,12 @@ tokens = HH.div_
Make sure to access the website using the related IP address.
To update an IPv6 address (AAAA), force your application to access the URL using an IPv6 address.
"""
, expl [ HH.p_ [ Web.strong "wget -6 <url>" ]
, HH.p_ [ HH.text "To force the use of an IPv6 address." ]
, HH.p_ [ Web.strong "wget -4 <url>" ]
, HH.p_ [ HH.text "To force the use of an IPv4 address." ]
]
, Web.quote
[ HH.p_ [ Web.strong "wget -6 <url>" ]
, HH.p_ [ HH.text "To force the use of an IPv6 address." ]
, HH.p_ [ Web.strong "wget -4 <url>" ]
, HH.p_ [ HH.text "To force the use of an IPv4 address." ]
]
]
basics :: forall w i. HH.HTML w i
@ -69,7 +69,7 @@ basics = HH.div_
, Web.hr
, Web.h3 "I have something to host (A and AAAA records)."
, expl' "Let's assume you have a web server and you host your website somewhere."
, expl "Let's assume you have a web server and you host your website somewhere."
, Web.p """
You want an A (IPv4) or AAAA (IPv6) record pointing to your server, named "enigma" for example.
"""
@ -94,10 +94,10 @@ basics = HH.div_
, Web.hr
, Web.h3 "I want an email server."
, expl' """
Hosting a mail server is quite complex.
This section will focus on the main parts regarding the DNS.
"""
, expl """
Hosting a mail server is quite complex.
This section will focus on the main parts regarding the DNS.
"""
, Web.notification_danger' """
The actual configuration of your mail server is complex and depends on your choice of software.
This won't be covered here.
@ -111,17 +111,17 @@ basics = HH.div_
"""
, Web.columns_
[ col
[ expl' """
Spam mitigation 1: tell what are the right mail servers for your domain with Sender Policy Framework (SPF).
"""
[ expl """
Spam mitigation 1: tell what are the right mail servers for your domain with Sender Policy Framework (SPF).
"""
, expl_txt """
You need a SPF record to tell other mail servers what are the acceptable mail servers for your domain.
"""
]
, col
[ expl' """
Spam mitigation 2: prove that the mails come from your mail server with DomainKeys Identified Mail (DKIM).
"""
[ expl """
Spam mitigation 2: prove that the mails come from your mail server with DomainKeys Identified Mail (DKIM).
"""
, expl_txt """
You will have to configure your mail server to sign the emails you send.
This involves creating a pair of keys (public and private).
@ -131,10 +131,10 @@ basics = HH.div_
"""
]
, col
[ expl' """
Spam mitigation 3: mitigate fraud (impersonators) with Domain-based Message Authentication Reporting and Conformance (DMARC).
Tell other mail servers to only accept emails from your domain which actually are coming from your domain (SPF) and sent by your mail server (DKIM).
"""
[ expl """
Spam mitigation 3: mitigate fraud (impersonators) with Domain-based Message Authentication Reporting and Conformance (DMARC).
Tell other mail servers to only accept emails from your domain which actually are coming from your domain (SPF) and sent by your mail server (DKIM).
"""
, expl_txt """
Last but not least, DMARC.
"""
@ -490,67 +490,69 @@ legal_notice = HH.div_
[ Web.h3 "Legal Notice"
, Web.strong "Website Publisher"
, expl [ HH.p_ [ HH.text "You can contact this website's owner and publisher at: "
, Web.strong website_owner_address
]
, HH.p_ [ HH.text "For legal matter: "
, Web.strong website_abuse_address
]
]
, Web.quote
[ HH.p_ [ HH.text "You can contact this website's owner and publisher at: "
, Web.strong website_owner_address
]
, HH.p_ [ HH.text "For legal matter: "
, Web.strong website_abuse_address
]
]
, Web.strong "Website Hosting"
, expl [ HH.p_ [ HH.text "This website is hosted by "
, Web.strong "Alsace Réseau Neutre"
, HH.text "."
, HH.br_
, HH.text "Website: "
, Web.outside_link [] "https://arn-fai.net" "arn-fai.net"
, HH.br_
, HH.text "Address & contact: "
, Web.outside_link [] "https://arn-fai.net/fr/mentions" "Legal Notice of ARN"
]
]
, Web.quote
[ HH.p_ [ HH.text "This website is hosted by "
, Web.strong "Alsace Réseau Neutre"
, HH.text "."
, HH.br_
, HH.text "Website: "
, Web.outside_link [] "https://arn-fai.net" "arn-fai.net"
, HH.br_
, HH.text "Address & contact: "
, Web.outside_link [] "https://arn-fai.net/fr/mentions" "Legal Notice of ARN"
]
]
, Web.strong "Intellectual Property"
, expl' """
The code of this website is released under the ISC License. You
are free to copy, modify, and distribute the code, provided
that you comply with the terms of the ISC License.
"""
, expl """
The code of this website is released under the ISC License. You
are free to copy, modify, and distribute the code, provided
that you comply with the terms of the ISC License.
"""
, Web.strong "Personal Data Collection"
, expl' """
This website collects only the personal data necessary for its proper functioning.
This includes data such as: a login (arbitrary set of
characters), a password (that is stored encrypted), an email
to contact the owner of the domain, domain names and zone data.
"""
, expl """
This website collects only the personal data necessary for its proper functioning.
This includes data such as: a login (arbitrary set of
characters), a password (that is stored encrypted), an email
to contact the owner of the domain, domain names and zone data.
"""
, Web.strong "Data Sharing"
, expl' """
None of the collected data will be shared to third parties.
"""
, expl """
None of the collected data will be shared to third parties.
"""
, Web.strong "Data Retention"
, expl' """
The personal data collected on this website will be retained
for as long as necessary to fulfill the purposes for which it
was collected, including the management of user accounts.
, expl """
The personal data collected on this website will be retained
for as long as necessary to fulfill the purposes for which it
was collected, including the management of user accounts.
However, please note that even after the deletion of your
account, your data may be retained for up to 6 months due
to technical constraints, such as backups made for disaster
recovery purposes in the event of a hardware failure.
However, please note that even after the deletion of your
account, your data may be retained for up to 6 months due
to technical constraints, such as backups made for disaster
recovery purposes in the event of a hardware failure.
This retention period is necessary to ensure the security and
integrity of our system and to allow for the restoration of
data in case of any unforeseen issues.
This retention period is necessary to ensure the security and
integrity of our system and to allow for the restoration of
data in case of any unforeseen issues.
After this period, all data will be securely deleted.
"""
After this period, all data will be securely deleted.
"""
, Web.strong "Liability"
, expl
, Web.quote
[ Web.p
"""
The publisher of this website makes every effort to ensure that
@ -586,12 +588,13 @@ legal_notice = HH.div_
]
, Web.strong "GDPR compliance"
, expl [ HH.p_ [ HH.text """
You have the right to access, correct and delete your personal
data at any time via this website or by contacting us at the
following email address:
"""
, Web.strong website_owner_address
]
]
, Web.quote
[ HH.p_ [ HH.text """
You have the right to access, correct and delete your personal
data at any time via this website or by contacting us at the
following email address:
"""
, Web.strong website_owner_address
]
]
]

View file

@ -22,13 +22,13 @@ p_ :: forall w i. Array HH.ClassName -> String -> HH.HTML w i
p_ classes str = HH.p [HP.classes classes] [ HH.text str ]
ul :: forall w i. Array (HH.HTML w i) -> HH.HTML w i
ul content = HH.ul_ content
ul body = HH.ul_ body
li :: forall w i. String -> HH.HTML w i
li content = li_ [] content
li body = li_ [] body
li_ :: forall w i. Array HH.ClassName -> String -> HH.HTML w i
li_ classes content = HH.li [HP.classes classes] [ HH.text content ]
li_ classes body = HH.li [HP.classes classes] [ HH.text body ]
strong :: forall w i. String -> HH.HTML w i
strong str = HH.strong_ [ HH.text str ]
@ -37,25 +37,25 @@ hr :: forall w i. HH.HTML w i
hr = HH.hr_
div :: forall w i. Array (HH.HTML w i) -> HH.HTML w i
div content = HH.div_ content
div body = HH.div_ body
div_ :: forall w i. HH.Node DHI.HTMLdiv w i
div_ = HH.div
div_large_content :: forall w i. Array (HH.HTML w i) -> HH.HTML w i
div_large_content content = HH.div [HP.classes [C.is_large, C.content]] content
content :: forall w i. Array (HH.HTML w i) -> HH.HTML w i
content body = HH.div [HP.classes [C.content]] body
div_content :: forall w i. Array HH.ClassName -> Array (HH.HTML w i) -> HH.HTML w i
div_content classes content = HH.div [HP.classes ([C.content] <> classes)] content
content_ :: forall w i. Array HH.ClassName -> Array (HH.HTML w i) -> HH.HTML w i
content_ classes body = HH.div [HP.classes ([C.content] <> classes)] body
explanation :: forall w i. Array (HH.HTML w i) -> HH.HTML w i
explanation content = HH.blockquote [HP.classes [HH.ClassName "justified"]] content
explanation body = HH.blockquote [HP.classes [HH.ClassName "justified"]] body
quote :: forall w i. Array (HH.HTML w i) -> HH.HTML w i
quote content = div_content [] [ explanation content ]
quote body = content [ explanation body ]
simple_quote :: forall w i. String -> HH.HTML w i
simple_quote content = quote [ p content ]
simple_quote string = quote [ p string ]
article_ :: forall w i. Array HH.ClassName -> HH.HTML w i -> HH.HTML w i -> HH.HTML w i
article_ classes head body = HH.article [HP.classes $ [C.message] <> classes]
@ -67,7 +67,7 @@ article :: forall w i. HH.HTML w i -> HH.HTML w i -> HH.HTML w i
article head body = article_ [] head body
container :: forall w i. Array (HH.HTML w i) -> HH.HTML w i
container = HH.div [HP.classes [C.container, C.is_info]]
container body = HH.div [HP.classes [C.container, C.is_info]] body
hdiv :: forall (w :: Type) (a :: Type). Array (HH.HTML w a) -> HH.HTML w a
hdiv = HH.div [ HP.classes [HH.ClassName "mt-5"] ]