forked from Deuxfleurs/guichet
Merge pull request 'Quick fixes' (#82) from qdu-fix into main
Reviewed-on: Deuxfleurs/guichet#82
This commit is contained in:
commit
8a939391d5
10 changed files with 59 additions and 90 deletions
19
Makefile
19
Makefile
|
@ -1,19 +0,0 @@
|
||||||
BIN=guichet
|
|
||||||
SRC=main.go ssha.go profile.go admin.go invite.go directory.go picture.go
|
|
||||||
DOCKER=lxpz/guichet_amd64
|
|
||||||
|
|
||||||
all: $(BIN)
|
|
||||||
|
|
||||||
$(BIN): $(SRC)
|
|
||||||
go get -d -v
|
|
||||||
go build -v -o $(BIN)
|
|
||||||
|
|
||||||
$(BIN).static: $(SRC)
|
|
||||||
go get -d -v
|
|
||||||
CGO_ENABLED=0 GOOS=linux go build -a -v -o $(BIN).static
|
|
||||||
|
|
||||||
docker: $(BIN).static
|
|
||||||
docker build -t $(DOCKER):$(TAG) .
|
|
||||||
docker push $(DOCKER):$(TAG)
|
|
||||||
docker tag $(DOCKER):$(TAG) $(DOCKER):latest
|
|
||||||
docker push $(DOCKER):latest
|
|
18
README.md
18
README.md
|
@ -27,9 +27,23 @@ Guichet is licensed under the terms of the GPLv3.
|
||||||
|
|
||||||
Guichet requires go 1.13 or later.
|
Guichet requires go 1.13 or later.
|
||||||
|
|
||||||
To build Guichet, clone this repository outside of your `$GOPATH`.
|
Development build:
|
||||||
Then, run `make` in the root of the repo.
|
|
||||||
|
|
||||||
|
```
|
||||||
|
go build
|
||||||
|
```
|
||||||
|
|
||||||
|
Production build:
|
||||||
|
|
||||||
|
```
|
||||||
|
nix build
|
||||||
|
```
|
||||||
|
|
||||||
|
Production container:
|
||||||
|
|
||||||
|
```
|
||||||
|
docker run .#docker
|
||||||
|
```
|
||||||
|
|
||||||
## Configuration of Guichet
|
## Configuration of Guichet
|
||||||
|
|
||||||
|
|
11
flake.nix
11
flake.nix
|
@ -47,11 +47,20 @@
|
||||||
Entrypoint = "/bin/guichet";
|
Entrypoint = "/bin/guichet";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
docker = pkgs.writeScriptBin "guichet-docker" ''
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -euxo pipefail
|
||||||
|
docker load <$(nix build --print-out-paths .#container)
|
||||||
|
'';
|
||||||
|
|
||||||
in {
|
in {
|
||||||
packages.x86_64-linux.guichet = guichet;
|
packages.x86_64-linux.guichet = guichet;
|
||||||
packages.x86_64-linux.container = container;
|
packages.x86_64-linux.container = container;
|
||||||
|
packages.x86_64-linux.docker = docker;
|
||||||
packages.x86_64-linux.default = guichet;
|
packages.x86_64-linux.default = guichet;
|
||||||
|
|
||||||
devShell.x86_64-linux = pkgs.mkShell { nativeBuildInputs = [ pkgs.go pkgs.gomod2nix ]; };
|
devShell.x86_64-linux = pkgs.mkShell { nativeBuildInputs = [ pkgs.go pkgs.gomod2nix ]; };
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
2
go.sum
2
go.sum
|
@ -31,8 +31,6 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl
|
||||||
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
|
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
|
||||||
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
||||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||||
git.deuxfleurs.fr/garage-sdk/garage-admin-sdk-golang v0.0.0-20230131081355-c965fe7f7dc9 h1:ERg8KCpIKym98EOKa8Gq0NSBxsasD3sqb/R0gg1wOzU=
|
|
||||||
git.deuxfleurs.fr/garage-sdk/garage-admin-sdk-golang v0.0.0-20230131081355-c965fe7f7dc9/go.mod h1:TlSL6QVxozmdRaSgP6Akspi0HCJv4HAkkq3Dldru4GM=
|
|
||||||
git.deuxfleurs.fr/garage-sdk/garage-admin-sdk-golang v0.0.0-20231128153612-8b81fae65e5e h1:h89CAh0qmUcGJykss/utXIw+yRGa3Gr6VyrZ5ZWN0kY=
|
git.deuxfleurs.fr/garage-sdk/garage-admin-sdk-golang v0.0.0-20231128153612-8b81fae65e5e h1:h89CAh0qmUcGJykss/utXIw+yRGa3Gr6VyrZ5ZWN0kY=
|
||||||
git.deuxfleurs.fr/garage-sdk/garage-admin-sdk-golang v0.0.0-20231128153612-8b81fae65e5e/go.mod h1:TlSL6QVxozmdRaSgP6Akspi0HCJv4HAkkq3Dldru4GM=
|
git.deuxfleurs.fr/garage-sdk/garage-admin-sdk-golang v0.0.0-20231128153612-8b81fae65e5e/go.mod h1:TlSL6QVxozmdRaSgP6Akspi0HCJv4HAkkq3Dldru4GM=
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
|
|
|
@ -21,7 +21,7 @@ services:
|
||||||
garage:
|
garage:
|
||||||
# sync with deuxfleurs/nixcfg/cluster/prod/app/garage/deploy/garage.hcl
|
# sync with deuxfleurs/nixcfg/cluster/prod/app/garage/deploy/garage.hcl
|
||||||
# to ensure compatibility with prod
|
# to ensure compatibility with prod
|
||||||
image: superboum/garage:v1.0.0-rc1-hotfix-red-ftr-wquorum
|
image: dxflrs/garage:v1.99.1-internal
|
||||||
ports:
|
ports:
|
||||||
- "3900:3900"
|
- "3900:3900"
|
||||||
- "3902:3902"
|
- "3902:3902"
|
||||||
|
|
56
invite.go
56
invite.go
|
@ -1,19 +1,15 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
"html/template"
|
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/emersion/go-sasl"
|
|
||||||
"github.com/emersion/go-smtp"
|
|
||||||
"github.com/go-ldap/ldap/v3"
|
"github.com/go-ldap/ldap/v3"
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
"golang.org/x/crypto/argon2"
|
"golang.org/x/crypto/argon2"
|
||||||
|
@ -251,21 +247,11 @@ func handleInviteSendCode(w http.ResponseWriter, r *http.Request) {
|
||||||
WebBaseAddress: config.WebAddress,
|
WebBaseAddress: config.WebAddress,
|
||||||
}
|
}
|
||||||
|
|
||||||
if r.Method == "POST" {
|
tryGenerateInvitation(user, data)
|
||||||
r.ParseForm()
|
|
||||||
|
|
||||||
choice := strings.Join(r.Form["choice"], "")
|
|
||||||
sendto := strings.Join(r.Form["sendto"], "")
|
|
||||||
|
|
||||||
if choice == "display" || choice == "send" {
|
|
||||||
trySendCode(user, choice, sendto, data)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
templateInviteSendCode.Execute(w, data)
|
templateInviteSendCode.Execute(w, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
func trySendCode(user *LoggedUser, choice string, sendto string, data *SendCodeData) {
|
func tryGenerateInvitation(user *LoggedUser, data *SendCodeData) {
|
||||||
// Generate code
|
// Generate code
|
||||||
code, code_id, code_pw := genCode()
|
code, code_id, code_pw := genCode()
|
||||||
|
|
||||||
|
@ -286,43 +272,9 @@ func trySendCode(user *LoggedUser, choice string, sendto string, data *SendCodeD
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we want to display it, do so
|
|
||||||
if choice == "display" {
|
|
||||||
data.Success = true
|
|
||||||
data.CodeDisplay = code
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise, we are sending a mail
|
|
||||||
if !EMAIL_REGEXP.MatchString(sendto) {
|
|
||||||
data.ErrorInvalidEmail = true
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
templateMail := template.Must(template.ParseFiles(templatePath + "/invite_mail.txt"))
|
|
||||||
buf := bytes.NewBuffer([]byte{})
|
|
||||||
templateMail.Execute(buf, &CodeMailFields{
|
|
||||||
To: sendto,
|
|
||||||
From: config.MailFrom,
|
|
||||||
InviteFrom: user.WelcomeName(),
|
|
||||||
Code: code,
|
|
||||||
WebBaseAddress: config.WebAddress,
|
|
||||||
})
|
|
||||||
|
|
||||||
log.Printf("Sending mail to: %s", sendto)
|
|
||||||
var auth sasl.Client = nil
|
|
||||||
if config.SMTPUsername != "" {
|
|
||||||
auth = sasl.NewPlainClient("", config.SMTPUsername, config.SMTPPassword)
|
|
||||||
}
|
|
||||||
err = smtp.SendMail(config.SMTPServer, auth, config.MailFrom, []string{sendto}, buf)
|
|
||||||
if err != nil {
|
|
||||||
data.ErrorMessage = err.Error()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
log.Printf("Mail sent.")
|
|
||||||
|
|
||||||
data.Success = true
|
data.Success = true
|
||||||
data.CodeSentTo = sendto
|
data.CodeDisplay = code
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func genCode() (code string, code_id string, code_pw string) {
|
func genCode() (code string, code_id string, code_pw string) {
|
||||||
|
|
|
@ -57,9 +57,9 @@
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<p>Vous devez éditer votre zone DNS, souvent gérée par votre bureau d'enregistrement, comme Gandi, pour la faire pointer vers Deuxfleurs. Si vous utilisez un sous domaine (eg. <code>site.example.com</code>), une entrée <code>CNAME</code> est appropriée :</p>
|
<p>Vous devez éditer votre zone DNS, souvent gérée par votre bureau d'enregistrement, comme Gandi, pour la faire pointer vers Deuxfleurs. Si vous utilisez un sous domaine (eg. <code>site.example.com</code>), une entrée <code>CNAME</code> est appropriée :</p>
|
||||||
<pre>site CNAME 3600 garage.deuxfleurs.fr.</pre>
|
<pre>site CNAME 3600 global.site.deuxfleurs.fr.</pre>
|
||||||
<p>Si vous utilisez la racine de votre nom de domaine (eg. <code>example.com</code>, aussi appelée APEX), la solution dépend de votre fournisseur DNS, il vous faudra au choix une entrée <code>ALIAS</code> ou <code>CNAME</code> en fonction de ce que votre fournisseur supporte :</p>
|
<p>Si vous utilisez la racine de votre nom de domaine (eg. <code>example.com</code>, aussi appelée APEX), la solution dépend de votre fournisseur DNS, il vous faudra au choix une entrée <code>ALIAS</code> ou <code>CNAME</code> en fonction de ce que votre fournisseur supporte :</p>
|
||||||
<pre>@ ALIAS 3600 garage.deuxfleurs.fr.</pre>
|
<pre>@ ALIAS 3600 global.site.deuxfleurs.fr.</pre>
|
||||||
<p>La première fois que vous chargerez votre site web, une erreur de certificat sera renvoyée. C'est normal, il faudra patienter quelques minutes le temps que le certificat se génère.</p>
|
<p>La première fois que vous chargerez votre site web, une erreur de certificat sera renvoyée. C'est normal, il faudra patienter quelques minutes le temps que le certificat se génère.</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-4">
|
<div class="mt-4">
|
||||||
|
|
|
@ -76,7 +76,10 @@
|
||||||
<h5 class="mt-3">Informations de connexion</h5>
|
<h5 class="mt-3">Informations de connexion</h5>
|
||||||
<ul class="nav nav-tabs" id="proto" role="tablist">
|
<ul class="nav nav-tabs" id="proto" role="tablist">
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link active" id="s3-tab" data-toggle="tab" href="#s3" role="tab" aria-controls="s3" aria-selected="true">S3 (recommandé)</a>
|
<a class="nav-link active" id="dxfl-tab" data-toggle="tab" href="#dxfl" role="tab" aria-controls="dxfl" aria-selected="true">dxfl (recommandé)</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" id="s3-tab" data-toggle="tab" href="#s3" role="tab" aria-controls="s3" aria-selected="false">S3</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" id="sftp-tab" data-toggle="tab" href="#sftp" role="tab" aria-controls="sftp" aria-selected="false">SFTP</a>
|
<a class="nav-link" id="sftp-tab" data-toggle="tab" href="#sftp" role="tab" aria-controls="sftp" aria-selected="false">SFTP</a>
|
||||||
|
@ -86,7 +89,20 @@
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<div class="tab-content" id="protocols">
|
<div class="tab-content" id="protocols">
|
||||||
<div class="tab-pane fade show active" id="s3" role="tabpanel" aria-labelledby="s3-tab">
|
<div class="tab-pane fade show active" id="dxfl" role="tabpanel" aria-labelledby="dxfl-tab">
|
||||||
|
<p>Première configuration :</p>
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
sudo npm install -g dxfl
|
||||||
|
dxfl login
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<p>Pour déployer votre site contenu dans le dossier <code>public</code> :</p>
|
||||||
|
<pre>
|
||||||
|
dxfl deploy {{ .View.Name.Pretty }} ./public
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
<div class="tab-pane fade show" id="s3" role="tabpanel" aria-labelledby="s3-tab">
|
||||||
<table class="table mt-4">
|
<table class="table mt-4">
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
|
@ -96,7 +112,7 @@
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">Clé secrète</th>
|
<th scope="row">Clé secrète</th>
|
||||||
<td>
|
<td>
|
||||||
<a href="#" onclick="document.getElementById('secret_key').style.display='inline'; this.style.display='none'">[Afficher la clé secrète]</a><span id="secret_key" style="display: none">{{ .View.SecretAccessKey }}</span>
|
<a href="#secret_key" onclick="document.getElementById('secret_key').style.display='inline'; this.style.display='none'">[Afficher la clé secrète]</a><span id="secret_key" style="display: none">{{ .View.SecretAccessKey }}</span>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
|
@ -137,7 +153,7 @@
|
||||||
<p>Entrez les informations suivantes quand elles vous sont demandées :</p>
|
<p>Entrez les informations suivantes quand elles vous sont demandées :</p>
|
||||||
<dl>
|
<dl>
|
||||||
<dt>AWS Access Key ID [None]:</dt><dd>{{ .View.AccessKeyId }}</dd>
|
<dt>AWS Access Key ID [None]:</dt><dd>{{ .View.AccessKeyId }}</dd>
|
||||||
<dt>AWS Secret Access Key [None]:</dt><dd><a href="#" onclick="document.getElementById('aws_secret_key').style.display='inline'; this.style.display='none'">[Afficher la clé secrète]</a><span id="aws_secret_key" style="display: none">{{ .View.SecretAccessKey }}</span></dd>
|
<dt>AWS Secret Access Key [None]:</dt><dd><a href="#aws_secret_key" onclick="document.getElementById('aws_secret_key').style.display='inline'; this.style.display='none'">[Afficher la clé secrète]</a><span id="aws_secret_key" style="display: none">{{ .View.SecretAccessKey }}</span></dd>
|
||||||
<dt>Default region name [None]:</dt> <dd>garage</dd>
|
<dt>Default region name [None]:</dt> <dd>garage</dd>
|
||||||
<dt>Default output format [None]:</dt> <dd>(laissez vide et appuyez sur entrée)</dd>
|
<dt>Default output format [None]:</dt> <dd>(laissez vide et appuyez sur entrée)</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
@ -171,7 +187,7 @@ mc alias set \
|
||||||
{{ .View.Name.Pretty }} \
|
{{ .View.Name.Pretty }} \
|
||||||
https://garage.deuxfleurs.fr \
|
https://garage.deuxfleurs.fr \
|
||||||
{{ .View.AccessKeyId }} \
|
{{ .View.AccessKeyId }} \
|
||||||
<a href="#" onclick="document.getElementById('minio_secret_key').style.display='inline'; this.style.display='none'">[Afficher la clé secrète]</a><span id="minio_secret_key" style="display: none">{{ .View.SecretAccessKey }}</span> \
|
<a href="#minio_secret_key" onclick="document.getElementById('minio_secret_key').style.display='inline'; this.style.display='none'">[Afficher la clé secrète]</a><span id="minio_secret_key" style="display: none">{{ .View.SecretAccessKey }}</span> \
|
||||||
--api S3v4
|
--api S3v4
|
||||||
</pre>
|
</pre>
|
||||||
<p>Et ensuite copiez votre site web avec la sous-commande mirror de Minio CLI :</p>
|
<p>Et ensuite copiez votre site web avec la sous-commande mirror de Minio CLI :</p>
|
||||||
|
@ -195,12 +211,12 @@ mc mirror --overwrite ./public/ {{ .View.Name.Pretty }}/
|
||||||
<p>Créez un fichier nommé <code>.deployment.secrets</code> (ne commitez pas ce fichier dans votre dépôt !) :</p>
|
<p>Créez un fichier nommé <code>.deployment.secrets</code> (ne commitez pas ce fichier dans votre dépôt !) :</p>
|
||||||
<pre>
|
<pre>
|
||||||
export AWS_ACCESS_KEY_ID={{ .View.AccessKeyId }}
|
export AWS_ACCESS_KEY_ID={{ .View.AccessKeyId }}
|
||||||
export AWS_SECRET_ACCESS_KEY=<a href="#" onclick="document.getElementById('ugo_secret_key').style.display='inline'; this.style.display='none'">[Afficher la clé secrète]</a><span id="hugo_secret_key" style="display: none">{{ .View.SecretAccessKey }}</span>
|
export AWS_SECRET_ACCESS_KEY=<a href="#hugo_secret_key" onclick="document.getElementById('hugo_secret_key').style.display='inline'; this.style.display='none'">[Afficher la clé secrète]</a><span id="hugo_secret_key" style="display: none">{{ .View.SecretAccessKey }}</span>
|
||||||
</pre>
|
</pre>
|
||||||
<p>Dans votre fichier de configuration Hugo <code>config.toml</code> (que vous pouvez commiter), rajoutez :</p>
|
<p>Dans votre fichier de configuration Hugo <code>config.toml</code> (que vous pouvez commiter), rajoutez :</p>
|
||||||
<pre>
|
<pre>
|
||||||
[[deployment.targets]]
|
[[deployment.targets]]
|
||||||
URL = "s3://bucket?endpoint=garage.deuxfleurs.fr&s3ForcePathStyle=true&region=garage"
|
URL = "s3://{{ .View.Name.Pretty }}?endpoint=https://garage.deuxfleurs.fr&awssdk=v2&use_path_style=true&region=garage&disable_https=false
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<p>Pour déployer, sourcez le fichier de configuration et laissez hugo faire : </p>
|
<p>Pour déployer, sourcez le fichier de configuration et laissez hugo faire : </p>
|
||||||
|
|
|
@ -57,9 +57,9 @@
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<p>Vous devez éditer votre zone DNS, souvent gérée par votre bureau d'enregistrement, comme Gandi, pour la faire pointer vers Deuxfleurs. Si vous utilisez un sous domaine (eg. <code>site.example.com</code>), une entrée <code>CNAME</code> est appropriée :</p>
|
<p>Vous devez éditer votre zone DNS, souvent gérée par votre bureau d'enregistrement, comme Gandi, pour la faire pointer vers Deuxfleurs. Si vous utilisez un sous domaine (eg. <code>site.example.com</code>), une entrée <code>CNAME</code> est appropriée :</p>
|
||||||
<pre>site CNAME 3600 garage.deuxfleurs.fr.</pre>
|
<pre>site CNAME 3600 global.site.deuxfleurs.fr.</pre>
|
||||||
<p>Si vous utilisez la racine de votre nom de domaine (eg. <code>example.com</code>, aussi appelée APEX), la solution dépend de votre fournisseur DNS, il vous faudra au choix une entrée <code>ALIAS</code> ou <code>CNAME</code> en fonction de ce que votre fournisseur supporte :</p>
|
<p>Si vous utilisez la racine de votre nom de domaine (eg. <code>example.com</code>, aussi appelée APEX), la solution dépend de votre fournisseur DNS, il vous faudra au choix une entrée <code>ALIAS</code> ou <code>CNAME</code> en fonction de ce que votre fournisseur supporte :</p>
|
||||||
<pre>@ ALIAS 3600 garage.deuxfleurs.fr.</pre>
|
<pre>@ ALIAS 3600 global.site.deuxfleurs.fr.</pre>
|
||||||
<p>La première fois que vous chargerez votre site web, une erreur de certificat sera renvoyée. C'est normal, il faudra patienter quelques minutes le temps que le certificat se génère.</p>
|
<p>La première fois que vous chargerez votre site web, une erreur de certificat sera renvoyée. C'est normal, il faudra patienter quelques minutes le temps que le certificat se génère.</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-4">
|
<div class="mt-4">
|
||||||
|
|
|
@ -38,8 +38,7 @@
|
||||||
Inviter des gens sur Deuxfleurs
|
Inviter des gens sur Deuxfleurs
|
||||||
</div>
|
</div>
|
||||||
<div class="list-group list-group-flush">
|
<div class="list-group list-group-flush">
|
||||||
<a class="list-group-item list-group-item-action" href="/invite/send_code">Envoyer un code d'invitation</a>
|
<a class="list-group-item list-group-item-action" href="/invite/send_code">Générer un code d'invitation</a>
|
||||||
<a class="list-group-item list-group-item-action" href="/invite/new_account">Créer un nouveau compte directement</a>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
Loading…
Add table
Reference in a new issue