forked from Deuxfleurs/guichet
Profile modify
This commit is contained in:
parent
ebb7553cc8
commit
6297981c3b
3 changed files with 181 additions and 11 deletions
120
main.go
120
main.go
|
@ -1,6 +1,7 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"crypto/rand"
|
||||
"crypto/tls"
|
||||
"encoding/base64"
|
||||
|
@ -92,6 +93,7 @@ func main() {
|
|||
|
||||
http.HandleFunc("/", handleHome)
|
||||
http.HandleFunc("/logout", handleLogout)
|
||||
http.HandleFunc("/profile", handleProfile)
|
||||
|
||||
staticfiles := http.FileServer(http.Dir("static"))
|
||||
http.Handle("/static/", http.StripPrefix("/static/", staticfiles))
|
||||
|
@ -108,6 +110,12 @@ type LoginInfo struct {
|
|||
Password string
|
||||
}
|
||||
|
||||
type LoginStatus struct {
|
||||
Info *LoginInfo
|
||||
conn *ldap.Conn
|
||||
UserEntry *ldap.Entry
|
||||
}
|
||||
|
||||
func logRequest(handler http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
log.Printf("%s %s %s\n", r.RemoteAddr, r.Method, r.URL)
|
||||
|
@ -115,7 +123,7 @@ func logRequest(handler http.Handler) http.Handler {
|
|||
})
|
||||
}
|
||||
|
||||
func checkLogin(w http.ResponseWriter, r *http.Request) *LoginInfo {
|
||||
func checkLogin(w http.ResponseWriter, r *http.Request) *LoginStatus {
|
||||
session, err := store.Get(r, SESSION_NAME)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
|
@ -125,15 +133,63 @@ func checkLogin(w http.ResponseWriter, r *http.Request) *LoginInfo {
|
|||
username, ok := session.Values["login_username"]
|
||||
password, ok2 := session.Values["login_password"]
|
||||
user_dn, ok3 := session.Values["login_dn"]
|
||||
if !(ok && ok2 && ok3) {
|
||||
return handleLogin(w, r)
|
||||
}
|
||||
|
||||
return &LoginInfo{
|
||||
var login_info *LoginInfo
|
||||
if !(ok && ok2 && ok3) {
|
||||
login_info = handleLogin(w, r)
|
||||
if login_info == nil {
|
||||
return nil
|
||||
}
|
||||
} else {
|
||||
login_info = &LoginInfo{
|
||||
DN: user_dn.(string),
|
||||
Username: username.(string),
|
||||
Password: password.(string),
|
||||
}
|
||||
}
|
||||
|
||||
l := ldapOpen(w)
|
||||
if l == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
err = l.Bind(login_info.DN, login_info.Password)
|
||||
if err != nil {
|
||||
delete(session.Values, "login_username")
|
||||
delete(session.Values, "login_password")
|
||||
delete(session.Values, "login_dn")
|
||||
|
||||
err = session.Save(r, w)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return nil
|
||||
}
|
||||
return checkLogin(w, r)
|
||||
}
|
||||
|
||||
searchRequest := ldap.NewSearchRequest(
|
||||
login_info.DN,
|
||||
ldap.ScopeBaseObject, ldap.NeverDerefAliases, 0, 0, false,
|
||||
fmt.Sprintf("(&(objectClass=organizationalPerson))"),
|
||||
[]string{"dn", "displayname", "givenname", "sn", "mail"},
|
||||
nil)
|
||||
|
||||
sr, err := l.Search(searchRequest)
|
||||
if err!= nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return nil
|
||||
}
|
||||
|
||||
if len(sr.Entries) != 1 {
|
||||
http.Error(w, fmt.Sprintf("Multiple entries: %#v", sr.Entries), http.StatusInternalServerError)
|
||||
return nil
|
||||
}
|
||||
|
||||
return &LoginStatus{
|
||||
Info: login_info,
|
||||
conn: l,
|
||||
UserEntry: sr.Entries[0],
|
||||
}
|
||||
}
|
||||
|
||||
func ldapOpen(w http.ResponseWriter) *ldap.Conn {
|
||||
|
@ -248,3 +304,57 @@ func handleLogin(w http.ResponseWriter, r *http.Request) *LoginInfo {
|
|||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
type ProfileTplData struct {
|
||||
Status *LoginStatus
|
||||
ErrorMessage string
|
||||
Success bool
|
||||
Mail string
|
||||
DisplayName string
|
||||
GivenName string
|
||||
Surname string
|
||||
}
|
||||
|
||||
func handleProfile(w http.ResponseWriter, r *http.Request) {
|
||||
templateProfile := template.Must(template.ParseFiles("templates/layout.html", "templates/profile.html"))
|
||||
|
||||
login := checkLogin(w, r)
|
||||
if login == nil {
|
||||
return
|
||||
}
|
||||
|
||||
data := &ProfileTplData{
|
||||
Status: login,
|
||||
ErrorMessage: "",
|
||||
Success: false,
|
||||
}
|
||||
|
||||
if r.Method == "POST" {
|
||||
r.ParseForm()
|
||||
|
||||
data.Mail = strings.Join(r.Form["mail"], "")
|
||||
data.DisplayName = strings.Join(r.Form["display_name"], "")
|
||||
data.GivenName = strings.Join(r.Form["given_name"], "")
|
||||
data.Surname = strings.Join(r.Form["surname"], "")
|
||||
|
||||
modify_request := ldap.NewModifyRequest(login.Info.DN, nil)
|
||||
modify_request.Replace("mail", []string{data.Mail})
|
||||
modify_request.Replace("displayname", []string{data.DisplayName})
|
||||
modify_request.Replace("givenname", []string{data.GivenName})
|
||||
modify_request.Replace("sn", []string{data.Surname})
|
||||
|
||||
err := login.conn.Modify(modify_request)
|
||||
if err != nil {
|
||||
data.ErrorMessage = err.Error()
|
||||
} else {
|
||||
data.Success = true
|
||||
}
|
||||
} else {
|
||||
data.Mail = login.UserEntry.GetAttributeValue("mail")
|
||||
data.DisplayName = login.UserEntry.GetAttributeValue("displayname")
|
||||
data.GivenName = login.UserEntry.GetAttributeValue("givenname")
|
||||
data.Surname = login.UserEntry.GetAttributeValue("sn")
|
||||
}
|
||||
|
||||
templateProfile.Execute(w, data)
|
||||
}
|
||||
|
|
|
@ -1,17 +1,32 @@
|
|||
{{define "title"}}Guichet{{end}}
|
||||
{{define "title"}}{{end}}
|
||||
|
||||
{{define "body"}}
|
||||
<div class="alert alert-success">
|
||||
Bienvenue, <strong>{{ .Username }}</strong> !
|
||||
<div class="d-flex">
|
||||
<span>Bienvenue, <strong>{{ .UserEntry.GetAttributeValue "givenname" }}</strong> !</span>
|
||||
<a class="ml-auto btn btn-sm btn-dark" href="/logout">Se déconnecter</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
Gérer mon compte
|
||||
Mon compte
|
||||
</div>
|
||||
<div class="list-group list-group-flush">
|
||||
<a class="list-group-item list-group-item-action" href="/">Test</a>
|
||||
<a class="list-group-item list-group-item-action" href="/logout">Se déconnecter</a>
|
||||
<a class="list-group-item list-group-item-action" href="/profile">Modifier mon profil</a>
|
||||
<a class="list-group-item list-group-item-action" href="/passwd">Modifier mon mot de passe</a>
|
||||
<a class="list-group-item list-group-item-action" href="/invite">Inviter quelqu'un</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card mt-3">
|
||||
<div class="card-header">
|
||||
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/groups">Groupes</a>
|
||||
<a class="list-group-item list-group-item-action" href="/admin/ldap">Explorateur LDAP</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
45
templates/profile.html
Normal file
45
templates/profile.html
Normal file
|
@ -0,0 +1,45 @@
|
|||
{{define "title"}}Profile |{{end}}
|
||||
|
||||
{{define "body"}}
|
||||
<h4>Modifier mon profil</h4>
|
||||
|
||||
<form method="POST">
|
||||
{{if .ErrorMessage}}
|
||||
<div class="alert alert-danger">Impossible de se connecter.
|
||||
<div style="font-size: 0.8em">{{ .ErrorMessage }}</div>
|
||||
</div>
|
||||
{{end}}
|
||||
{{if .Success}}
|
||||
<div class="alert alert-success">
|
||||
<div class="d-flex">
|
||||
<span>Profil enregistré.</span>
|
||||
<a class="ml-auto btn btn-sm btn-info" href="/">Retour</a>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
<div class="form-group">
|
||||
<label>Nom d'utilisateur:</label>
|
||||
<input type="text" disabled="true" class="form-control" value="{{ .Status.Info.Username }}" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="mail">Adresse e-mail:</label>
|
||||
<input type="text" id="mail" name="mail" class="form-control" value="{{ .Mail }}" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="display_name">Nom complet:</label>
|
||||
<input type="text" id="display_name" name="display_name" class="form-control" value="{{ .DisplayName }}" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="given_name">Prénom:</label>
|
||||
<input type="text" id="given_name" name="given_name" class="form-control" value="{{ .GivenName }}" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="surname">Nom de famille:</label>
|
||||
<input type="text" id="surname" name="surname" class="form-control" value="{{ .Surname }}" />
|
||||
</div>
|
||||
<div class="d-flex">
|
||||
<button type="submit" class="btn btn-primary">Enregistrer les modifications</button>
|
||||
<a class="ml-auto btn btn-danger" href="/">Annuler</a>
|
||||
</div>
|
||||
</form>
|
||||
{{end}}
|
Loading…
Reference in a new issue