forked from Deuxfleurs/guichet
Inclusive + Fix checks + Fix SSHA
This commit is contained in:
parent
216e175eaf
commit
3c846b6a59
10 changed files with 70 additions and 69 deletions
|
@ -4,9 +4,9 @@
|
|||
|
||||
"base_dn": "dc=example,dc=com",
|
||||
"user_base_dn": "ou=users,dc=example,dc=com",
|
||||
"user_name_attr": "uid",
|
||||
"user_name_attr": "cn",
|
||||
"group_base_dn": "ou=groups,dc=example,dc=com",
|
||||
"group_name_attr": "gid",
|
||||
"group_name_attr": "cn",
|
||||
|
||||
"invitation_base_dn": "ou=invitations,dc=example,dc=com",
|
||||
"invitation_name_attr": "cn",
|
||||
|
@ -21,7 +21,7 @@
|
|||
"smtp_username": "guichet",
|
||||
"smtp_password": "",
|
||||
|
||||
"admin_account": "uid=admin,dc=example,dc=com",
|
||||
"admin_account": "cn=admin,dc=example,dc=com",
|
||||
"group_can_admin": "gid=admin,ou=groups,dc=example,dc=com",
|
||||
"group_can_invite": "",
|
||||
|
||||
|
|
6
go.mod
6
go.mod
|
@ -5,14 +5,12 @@ go 1.13
|
|||
require (
|
||||
github.com/emersion/go-sasl v0.0.0-20191210011802-430746ea8b9b
|
||||
github.com/emersion/go-smtp v0.12.1
|
||||
github.com/go-ldap/ldap v3.0.3+incompatible
|
||||
github.com/go-ldap/ldap/v3 v3.1.6
|
||||
github.com/google/uuid v1.1.1
|
||||
github.com/gorilla/mux v1.7.3
|
||||
github.com/gorilla/sessions v1.2.0
|
||||
github.com/jsimonetti/pwscheme v0.0.0-20220125093853-4d9895f5db73
|
||||
github.com/minio/minio-go/v7 v7.0.0
|
||||
github.com/sirupsen/logrus v1.6.0
|
||||
github.com/stretchr/objx v0.1.1 // indirect
|
||||
golang.org/x/crypto v0.0.0-20200214034016-1d94cc7ab1c6
|
||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646
|
||||
golang.org/x/crypto v0.0.0-20200214034016-1d94cc7ab1c6
|
||||
)
|
||||
|
|
19
go.sum
19
go.sum
|
@ -1,4 +1,5 @@
|
|||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/emersion/go-sasl v0.0.0-20190817083125-240c8404624e/go.mod h1:G/dpzLu16WtQpBfQ/z3LYiYJn3ZhKSGWn83fyoyQe/k=
|
||||
|
@ -8,13 +9,12 @@ github.com/emersion/go-smtp v0.12.1 h1:1R8BDqrR2HhlGwgFYcOi+BVTvK1bMjAB65QcVpJ5s
|
|||
github.com/emersion/go-smtp v0.12.1/go.mod h1:SD9V/xa4ndMw77lR3Mf7htkp8RBNYuPh9UeuBs9tpUQ=
|
||||
github.com/go-asn1-ber/asn1-ber v1.3.1 h1:gvPdv/Hr++TRFCl0UbPFHC54P9N9jgsRPnmnr419Uck=
|
||||
github.com/go-asn1-ber/asn1-ber v1.3.1/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
|
||||
github.com/go-ldap/ldap v3.0.3+incompatible h1:HTeSZO8hWMS1Rgb2Ziku6b8a7qRIZZMHjsvuZyatzwk=
|
||||
github.com/go-ldap/ldap v3.0.3+incompatible/go.mod h1:qfd9rJvER9Q0/D/Sqn1DfHRoBp40uXYvFoEVrNEPqRc=
|
||||
github.com/go-ldap/ldap/v3 v3.1.6 h1:VTihvB7egSAvU6KOagaiA/EvgJMR2jsjRAVIho2ydBo=
|
||||
github.com/go-ldap/ldap/v3 v3.1.6/go.mod h1:5Zun81jBTabRaI8lzN7E1JjyEl1g6zI6u9pd8luAK4Q=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
|
||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw=
|
||||
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
|
@ -22,14 +22,14 @@ github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyC
|
|||
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
|
||||
github.com/gorilla/sessions v1.2.0 h1:S7P+1Hm5V/AT9cjEcUD5uDaQSX0OE577aCXgoaKpYbQ=
|
||||
github.com/gorilla/sessions v1.2.0/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
|
||||
github.com/jsimonetti/pwscheme v0.0.0-20220125093853-4d9895f5db73 h1:ZhC4QngptYaGx53+ph1RjxcH8fkCozBaY+935TNX4i8=
|
||||
github.com/jsimonetti/pwscheme v0.0.0-20220125093853-4d9895f5db73/go.mod h1:t0Q9JvoMTfTYdAWIk2MF69iz+Qpdk9D+PgVu6fVmaDI=
|
||||
github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68=
|
||||
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/klauspost/cpuid v1.2.3 h1:CCtW0xUnWGVINKvE/WWOYKdsPV6mawAtvQuSl8guwQs=
|
||||
github.com/klauspost/cpuid v1.2.3/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/minio/md5-simd v1.1.0 h1:QPfiOqlZH+Cj9teu0t9b1nTBfPbyTl16Of5MeuShdK4=
|
||||
github.com/minio/md5-simd v1.1.0/go.mod h1:XpBqgZULrMYD3R+M28PcmP0CkI7PEMzB3U77ZrKZ0Gw=
|
||||
|
@ -45,16 +45,16 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLD
|
|||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
|
||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I=
|
||||
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a h1:pa8hGb/2YqsZKovtsgrwcDH1RZhVbTKCjLp47XpqCDs=
|
||||
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
|
@ -66,7 +66,6 @@ golang.org/x/net v0.0.0-20190522155817-f3200d17e092 h1:4QSRKanuywn15aTZvI/mIDEgP
|
|||
golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc=
|
||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae h1:/WDfKMnPU+m5M4xB+6x4kaepxRw6jWvR5iDRdvjHgy8=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
|
|
33
invite.go
33
invite.go
|
@ -133,9 +133,12 @@ func handleNewAccount(w http.ResponseWriter, r *http.Request, l *ldap.Conn, invi
|
|||
}
|
||||
|
||||
func tryCreateAccount(l *ldap.Conn, data *NewAccountData, pass1 string, pass2 string, invitedBy string) {
|
||||
checkFailed := false
|
||||
|
||||
// Check if username is correct
|
||||
if match, err := regexp.MatchString("^[a-zA-Z0-9._-]+$", data.Username); !(err == nil && match) {
|
||||
if match, err := regexp.MatchString("^[a-z0-9._-]+$", data.Username); !(err == nil && match) {
|
||||
data.ErrorInvalidUsername = true
|
||||
checkFailed = true
|
||||
}
|
||||
|
||||
// Check if user exists
|
||||
|
@ -150,30 +153,39 @@ func tryCreateAccount(l *ldap.Conn, data *NewAccountData, pass1 string, pass2 st
|
|||
sr, err := l.Search(searchRq)
|
||||
if err != nil {
|
||||
data.ErrorMessage = err.Error()
|
||||
return
|
||||
checkFailed = true
|
||||
}
|
||||
|
||||
if len(sr.Entries) > 0 {
|
||||
data.ErrorUsernameTaken = true
|
||||
return
|
||||
checkFailed = true
|
||||
}
|
||||
|
||||
// Check that password is long enough
|
||||
if len(pass1) < 8 {
|
||||
data.ErrorPasswordTooShort = true
|
||||
return
|
||||
checkFailed = true
|
||||
}
|
||||
|
||||
if pass1 != pass2 {
|
||||
data.ErrorPasswordMismatch = true
|
||||
return
|
||||
checkFailed = true
|
||||
}
|
||||
|
||||
if checkFailed {
|
||||
return
|
||||
}
|
||||
|
||||
// Actually create user
|
||||
req := ldap.NewAddRequest(userDn, nil)
|
||||
req.Attribute("objectclass", []string{"inetOrgPerson", "organizationalPerson", "person", "top"})
|
||||
req.Attribute("structuralobjectclass", []string{"inetOrgPerson"})
|
||||
req.Attribute("userpassword", []string{SSHAEncode([]byte(pass1))})
|
||||
pw, err := SSHAEncode(pass1)
|
||||
if err != nil {
|
||||
data.ErrorMessage = err.Error()
|
||||
return
|
||||
}
|
||||
req.Attribute("userpassword", []string{pw})
|
||||
req.Attribute("invitedby", []string{invitedBy})
|
||||
if len(data.DisplayName) > 0 {
|
||||
req.Attribute("displayname", []string{data.DisplayName})
|
||||
|
@ -259,10 +271,15 @@ func trySendCode(login *LoginStatus, choice string, sendto string, data *SendCod
|
|||
// Create invitation object in database
|
||||
inviteDn := config.InvitationNameAttr + "=" + code_id + "," + config.InvitationBaseDN
|
||||
req := ldap.NewAddRequest(inviteDn, nil)
|
||||
req.Attribute("userpassword", []string{SSHAEncode([]byte(code_pw))})
|
||||
pw, err := SSHAEncode(code_pw)
|
||||
if err != nil {
|
||||
data.ErrorMessage = err.Error()
|
||||
return
|
||||
}
|
||||
req.Attribute("userpassword", []string{pw})
|
||||
req.Attribute("objectclass", []string{"top", "invitationCode"})
|
||||
|
||||
err := login.conn.Add(req)
|
||||
err = login.conn.Add(req)
|
||||
if err != nil {
|
||||
data.ErrorMessage = err.Error()
|
||||
return
|
||||
|
|
15
profile.go
15
profile.go
|
@ -122,12 +122,17 @@ func handlePasswd(w http.ResponseWriter, r *http.Request) {
|
|||
data.NoMatchError = true
|
||||
} else {
|
||||
modify_request := ldap.NewModifyRequest(login.Info.DN, nil)
|
||||
modify_request.Replace("userpassword", []string{SSHAEncode([]byte(password))})
|
||||
err := login.conn.Modify(modify_request)
|
||||
if err != nil {
|
||||
data.ErrorMessage = err.Error()
|
||||
pw, err := SSHAEncode(password);
|
||||
if err == nil {
|
||||
modify_request.Replace("userpassword", []string{pw})
|
||||
err := login.conn.Modify(modify_request)
|
||||
if err != nil {
|
||||
data.ErrorMessage = err.Error()
|
||||
} else {
|
||||
data.Success = true
|
||||
}
|
||||
} else {
|
||||
data.Success = true
|
||||
data.ErrorMessage = err.Error()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
33
ssha.go
33
ssha.go
|
@ -1,37 +1,10 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"crypto/sha1"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/jsimonetti/pwscheme/ssha512"
|
||||
)
|
||||
|
||||
// Encode encodes the []byte of raw password
|
||||
func SSHAEncode(rawPassPhrase []byte) string {
|
||||
hash := makeSSHAHash(rawPassPhrase, makeSalt())
|
||||
b64 := base64.StdEncoding.EncodeToString(hash)
|
||||
return fmt.Sprintf("{ssha}%s", b64)
|
||||
}
|
||||
|
||||
// makeSalt make a 32 byte array containing random bytes.
|
||||
func makeSalt() []byte {
|
||||
sbytes := make([]byte, 32)
|
||||
_, err := rand.Read(sbytes)
|
||||
if err != nil {
|
||||
log.Panicf("Could not read random bytes: %s", err)
|
||||
}
|
||||
return sbytes
|
||||
}
|
||||
|
||||
// makeSSHAHash make hasing using SHA-1 with salt. This is not the final output though. You need to append {SSHA} string with base64 of this hash.
|
||||
func makeSSHAHash(passphrase, salt []byte) []byte {
|
||||
sha := sha1.New()
|
||||
sha.Write(passphrase)
|
||||
sha.Write(salt)
|
||||
|
||||
h := sha.Sum(nil)
|
||||
return append(h, salt...)
|
||||
func SSHAEncode(rawPassPhrase string) (string, error) {
|
||||
return ssha512.Generate(rawPassPhrase, 16)
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
Administration
|
||||
</div>
|
||||
<div class="list-group list-group-flush">
|
||||
<a class="list-group-item list-group-item-action" href="/admin/users">Utilisateurs</a>
|
||||
<a class="list-group-item list-group-item-action" href="/admin/users">Utilisateur·ices</a>
|
||||
<a class="list-group-item list-group-item-action" href="/admin/groups">Groupes</a>
|
||||
<a class="list-group-item list-group-item-action" href="/admin/ldap/{{.BaseDN}}">Explorateur LDAP</a>
|
||||
</div>
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
</div>
|
||||
{{end}}
|
||||
{{if .WarningMessage}}
|
||||
<div class="alert alert-danger mt-4">Des erreurs se sont produtes, le compte pourrait ne pas être totalement fonctionnel.
|
||||
<div class="alert alert-danger mt-4">Des erreurs se sont produites, le compte pourrait ne pas être totalement fonctionnel.
|
||||
<div style="font-size: 0.8em">{{ .WarningMessage }}</div>
|
||||
</div>
|
||||
{{end}}
|
||||
|
@ -25,12 +25,15 @@
|
|||
<form method="POST" class="mt-4">
|
||||
<h5>Renseignements obligatoires</h5>
|
||||
<div class="form-group">
|
||||
<label for="username">Nom d'utilisateur souhaité :</label>
|
||||
<label for="username">Identifiant souhaité :</label>
|
||||
<input type="text" id="username" name="username" class="form-control" value="{{ .Username }}" />
|
||||
<small class="form-text text-muted">
|
||||
Votre identifiant doit être en minuscule.
|
||||
</small>
|
||||
</div>
|
||||
{{if .ErrorInvalidUsername}}
|
||||
<div class="alert alert-warning">
|
||||
Nom d'utilisateur invalide. Ne peut contenir que les caractères suivants : chiffres, lettres, point, tiret bas (_) et tiret du milieu (-).
|
||||
Nom d'utilisateur invalide. Ne peut contenir que les caractères suivants : chiffres, lettres minuscules, point, tiret bas (_) et tiret du milieu (-).
|
||||
</div>
|
||||
{{end}}
|
||||
{{if .ErrorUsernameTaken}}
|
||||
|
@ -41,6 +44,9 @@
|
|||
<div class="form-group">
|
||||
<label for="password">Mot de passe :</label>
|
||||
<input type="password" id="password" name="password" class="form-control" />
|
||||
<small class="form-text text-muted">
|
||||
La seule contrainte est que votre mot de passe doit faire au moins 8 caractères. Utilisez chiffres, majuscules, et caractères spéciaux sans modération !
|
||||
</small>
|
||||
</div>
|
||||
{{if .ErrorPasswordTooShort}}
|
||||
<div class="alert alert-warning">
|
||||
|
@ -58,6 +64,9 @@
|
|||
{{end}}
|
||||
|
||||
<h5>Renseignements optionnels</h5>
|
||||
<small class="form-text text-muted">
|
||||
Ces informations sont utilisées exclusivement pour "pré-configurer" les services que vous utiliserez, elles n'ont pas besoin de correspondre à votre état civil.
|
||||
</small>
|
||||
<div class="form-group">
|
||||
<label for="displayname">Nom complet :</label>
|
||||
<input type="text" id="displayname" name="displayname" class="form-control" value="{{ .DisplayName }}" />
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
<form method="POST">
|
||||
{{if .WrongUser}}
|
||||
<div class="alert alert-danger">Nom d'utilisateur invalide.</div>
|
||||
<div class="alert alert-danger">Identifiant invalide.</div>
|
||||
{{end}}
|
||||
{{if .WrongPass}}
|
||||
<div class="alert alert-danger">Mot de passe invalide.</div>
|
||||
|
@ -16,11 +16,11 @@
|
|||
</div>
|
||||
{{end}}
|
||||
<div class="form-group">
|
||||
<label for="username">Nom d'utilisateur:</label>
|
||||
<label for="username">Identifiant :</label>
|
||||
<input type="text" name="username" id="username" class="form-control" value="{{ .Username }}" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="password">Mot de passe:</label>
|
||||
<label for="password">Mot de passe :</label>
|
||||
<input type="password" name="password" id="password" class="form-control" />
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary">Se connecter</button>
|
||||
|
@ -30,6 +30,6 @@
|
|||
|
||||
<p><strong>Mot de passe oublié ?</strong>
|
||||
Écrivez à <samp>coucou</samp><img src="static/image/at_sign.svg" style="height: 1em" alt="arobase" /><samp>deuxfleurs.fr</samp>
|
||||
ou contactez directement votre administrateur favori.</p>
|
||||
ou contactez directement votre opérateur·ice préféré·e.</p>
|
||||
|
||||
{{end}}
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
<form method="POST" class="mt-4" enctype="multipart/form-data">
|
||||
<div class="form-row">
|
||||
<div class="form-group col-md-6">
|
||||
<label>Nom d'utilisateur:</label>
|
||||
<label>Identifiant:</label>
|
||||
<input type="text" disabled="true" class="form-control" value="{{ .Status.Info.Username }}" />
|
||||
</div>
|
||||
<div class="form-group col-md-6">
|
||||
|
|
Loading…
Reference in a new issue