From 065161f994137d7fde47b1c2910969b01665a87f Mon Sep 17 00:00:00 2001 From: Chris Mann Date: Wed, 26 Jul 2023 08:31:25 +0200 Subject: [PATCH] Refactoring --- Makefile | 5 +- admin.go | 1021 ------------------------- config.go | 53 -- controller.go | 33 +- garage.go | 8 +- gpas.go | 169 ---- home.go | 40 - http-utils.go | 40 - invite.go | 555 -------------- login.go | 128 ---- model-user.go | 9 - profile.go | 219 ------ ssha.go | 10 - templates/admin_activate.html | 39 - templates/admin_create.html | 96 --- templates/admin_groups.html | 40 - templates/admin_ldap.html | 239 ------ templates/admin_mailing.html | 35 - templates/admin_mailing_list.html | 117 --- templates/admin_users.html | 43 -- templates/directory_results.html | 23 - templates/garage_key.html | 237 ------ templates/garage_website_inspect.html | 61 -- templates/garage_website_list.html | 41 - templates/garage_website_new.html | 66 -- templates/home.html | 16 +- templates/invite_invalid_code.html | 4 - templates/invite_mail.txt | 13 - templates/invite_new_account.html | 131 ---- templates/invite_send_code.html | 66 -- templates/layout.html | 16 +- templates/login.html | 4 +- templates/lost_password_email.txt | 13 - templates/password_lost.html | 40 - templates/profile.html | 86 --- 35 files changed, 45 insertions(+), 3671 deletions(-) delete mode 100644 admin.go delete mode 100644 config.go delete mode 100644 gpas.go delete mode 100644 home.go delete mode 100644 http-utils.go delete mode 100644 invite.go delete mode 100644 login.go delete mode 100644 profile.go delete mode 100644 ssha.go delete mode 100644 templates/admin_activate.html delete mode 100644 templates/admin_create.html delete mode 100644 templates/admin_groups.html delete mode 100644 templates/admin_ldap.html delete mode 100644 templates/admin_mailing.html delete mode 100644 templates/admin_mailing_list.html delete mode 100644 templates/admin_users.html delete mode 100644 templates/directory_results.html delete mode 100644 templates/garage_key.html delete mode 100644 templates/garage_website_inspect.html delete mode 100644 templates/garage_website_list.html delete mode 100644 templates/garage_website_new.html delete mode 100644 templates/invite_invalid_code.html delete mode 100644 templates/invite_mail.txt delete mode 100644 templates/invite_new_account.html delete mode 100644 templates/invite_send_code.html delete mode 100644 templates/lost_password_email.txt delete mode 100644 templates/password_lost.html delete mode 100644 templates/profile.html diff --git a/Makefile b/Makefile index c8eeba0..9e74b42 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,8 @@ BIN=guichet -SRC=main.go ssha.go profile.go admin.go invite.go directory.go utils.go picture.go login.go config.go http-utils.go home.go model-user.go gpas.go session.go model.go view.go controller.go +SRC=main.go model.go view.go controller.go utils.go model-user.go view-admin.go view-home.go view-invite.go view-login.go view-passwd.go view.profile.go utils-http.go utils-ldap.go utils-config.go directory.go garage.go picture.go session.go utils-ssha.go + +# ssha.go profile.go admin.go invite.go directory.go utils.go picture.go login.go config.go http-utils.go home.go model-user.go gpas.go session.go model.go view.go controller.go utils-ldap.go + DOCKER=lxpz/guichet_amd64 all: $(BIN) diff --git a/admin.go b/admin.go deleted file mode 100644 index 83a9346..0000000 --- a/admin.go +++ /dev/null @@ -1,1021 +0,0 @@ -package main - -import ( - "fmt" - "net/http" - "regexp" - "sort" - "strings" - - "github.com/go-ldap/ldap/v3" - "github.com/gorilla/mux" -) - -func checkAdminLogin(w http.ResponseWriter, r *http.Request) *LoginStatus { - login := checkLogin(w, r) - if login == nil { - return nil - } - - if !login.Common.CanAdmin { - http.Error(w, "Not authorized to perform administrative operations.", http.StatusUnauthorized) - return nil - } - return login -} - -func (d EntryList) Len() int { - return len(d) -} - -func (d EntryList) Swap(i, j int) { - d[i], d[j] = d[j], d[i] -} - -func (d EntryList) Less(i, j int) bool { - return d[i].DN < d[j].DN -} - -func handleAdminActivateUsers(w http.ResponseWriter, r *http.Request) { - templateAdminActivateUsers := getTemplate("admin_activate.html") - login := checkAdminLogin(w, r) - if login == nil { - return - } - - searchRequest := ldap.NewSearchRequest( - config.InvitationBaseDN, - ldap.ScopeSingleLevel, - ldap.NeverDerefAliases, - 0, - 0, - false, - fmt.Sprintf("(&(objectClass=organizationalPerson))"), - []string{"cn", "displayName", "givenName", "sn", "mail", "uid"}, - nil) - - sr, err := login.conn.Search(searchRequest) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - - data := &AdminUsersTplData{ - Login: NestedLoginTplData{ - Login: login, - }, - UserNameAttr: config.UserNameAttr, - UserBaseDN: config.UserBaseDN, - Users: EntryList(sr.Entries), - Common: NestedCommonTplData{ - CanAdmin: true, - LoggedIn: true, - }, - } - templateAdminActivateUsers.Execute(w, data) - -} - -func handleAdminActivateUser(w http.ResponseWriter, r *http.Request) { - cn := mux.Vars(r)["cn"] - login := checkAdminLogin(w, r) - if login == nil { - return - } - modifyRequest := *ldap.NewModifyDNRequest("cn="+cn+","+config.InvitationBaseDN, "cn="+cn, true, config.UserBaseDN) - err := login.conn.ModifyDN(&modifyRequest) - if err != nil { - return - } - http.Redirect(w, r, "/admin/activate", http.StatusFound) -} - -func handleAdminUnactivateUser(w http.ResponseWriter, r *http.Request) { - cn := mux.Vars(r)["cn"] - login := checkAdminLogin(w, r) - if login == nil { - return - } - modifyRequest := *ldap.NewModifyDNRequest("cn="+cn+","+config.UserBaseDN, "cn="+cn, true, config.InvitationBaseDN) - err := login.conn.ModifyDN(&modifyRequest) - if err != nil { - return - } - http.Redirect(w, r, "/admin/users", http.StatusFound) -} - -func handleAdminUsers(w http.ResponseWriter, r *http.Request) { - templateAdminUsers := getTemplate("admin_users.html") - - login := checkAdminLogin(w, r) - if login == nil { - return - } - - searchRequest := ldap.NewSearchRequest( - config.UserBaseDN, - ldap.ScopeSingleLevel, ldap.NeverDerefAliases, 0, 0, false, - fmt.Sprintf("(&(objectClass=organizationalPerson))"), - []string{config.UserNameAttr, "dn", "displayName", "givenName", "sn", "mail", "uid", "cn"}, - nil) - - sr, err := login.conn.Search(searchRequest) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - - data := &AdminUsersTplData{ - Login: NestedLoginTplData{Login: login}, - UserNameAttr: config.UserNameAttr, - UserBaseDN: config.UserBaseDN, - Users: EntryList(sr.Entries), - Common: NestedCommonTplData{ - CanAdmin: login.Common.CanAdmin, - LoggedIn: false}, - } - sort.Sort(data.Users) - - // addNewUser(NewUser{ - // DN: "cn=newuser@lesgv.com,ou=newusers,dc=resdigita,dc=org", - // CN: "newuser@lesgv.com", - // GivenName: "New", - // SN: "User", - // DisplayName: "New User", - // Mail: "newuser@lesgv.com", - // }, config, login) - - templateAdminUsers.Execute(w, data) -} - -func handleAdminGroups(w http.ResponseWriter, r *http.Request) { - templateAdminGroups := getTemplate("admin_groups.html") - - login := checkAdminLogin(w, r) - if login == nil { - return - } - - searchRequest := ldap.NewSearchRequest( - config.GroupBaseDN, - ldap.ScopeSingleLevel, ldap.NeverDerefAliases, 0, 0, false, - fmt.Sprintf("(&(objectClass=groupOfNames))"), - []string{config.GroupNameAttr, "dn", "description"}, - nil) - - sr, err := login.conn.Search(searchRequest) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - - data := &AdminGroupsTplData{ - Login: NestedLoginTplData{ - Login: login}, - GroupNameAttr: config.GroupNameAttr, - GroupBaseDN: config.GroupBaseDN, - Groups: EntryList(sr.Entries), - Common: NestedCommonTplData{ - CanAdmin: login.Common.CanAdmin, - LoggedIn: false}, - } - sort.Sort(data.Groups) - - templateAdminGroups.Execute(w, data) -} - -func handleAdminMailing(w http.ResponseWriter, r *http.Request) { - templateAdminMailing := getTemplate("admin_mailing.html") - - login := checkAdminLogin(w, r) - if login == nil { - return - } - - searchRequest := ldap.NewSearchRequest( - config.MailingBaseDN, - ldap.ScopeSingleLevel, ldap.NeverDerefAliases, 0, 0, false, - fmt.Sprintf("(&(objectClass=groupOfNames))"), - []string{config.MailingNameAttr, "dn", "description"}, - nil) - - sr, err := login.conn.Search(searchRequest) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - - data := &AdminMailingTplData{ - Login: NestedLoginTplData{ - Login: login}, - MailingNameAttr: config.MailingNameAttr, - MailingBaseDN: config.MailingBaseDN, - MailingLists: EntryList(sr.Entries), - Common: NestedCommonTplData{ - CanAdmin: login.Common.CanAdmin, - LoggedIn: false}, - } - sort.Sort(data.MailingLists) - - templateAdminMailing.Execute(w, data) -} - -func handleAdminMailingList(w http.ResponseWriter, r *http.Request) { - templateAdminMailingList := getTemplate("admin_mailing_list.html") - - login := checkAdminLogin(w, r) - if login == nil { - return - } - - id := mux.Vars(r)["id"] - dn := fmt.Sprintf("%s=%s,%s", config.MailingNameAttr, id, config.MailingBaseDN) - - // handle modifications - dError := "" - dSuccess := false - - if r.Method == "POST" { - r.ParseForm() - action := strings.Join(r.Form["action"], "") - if action == "add-member" { - member := strings.Join(r.Form["member"], "") - modify_request := ldap.NewModifyRequest(dn, nil) - modify_request.Add("member", []string{member}) - - err := login.conn.Modify(modify_request) - // log.Printf(fmt.Sprintf("198: %v",modify_request)) - if err != nil { - dError = err.Error() - } else { - dSuccess = true - } - } else if action == "add-external" { - mail := strings.Join(r.Form["mail"], "") - sn := strings.Join(r.Form["sn"], "") - givenname := strings.Join(r.Form["givenname"], "") - member := strings.Join(r.Form["member"], "") - displayname := strings.Join(r.Form["displayname"], "") - - searchRequest := ldap.NewSearchRequest( - config.UserBaseDN, - ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false, - fmt.Sprintf("(&(objectClass=organizationalPerson)(mail=%s))", mail), - []string{"dn", "displayname", "mail"}, - nil) - sr, err := login.conn.Search(searchRequest) - if err != nil { - dError = err.Error() - } else { - if len(sr.Entries) == 0 { - if config.MailingGuestsBaseDN != "" { - guestDn := fmt.Sprintf("%s=%s,%s", config.UserNameAttr, mail, config.MailingGuestsBaseDN) - req := ldap.NewAddRequest(guestDn, nil) - //req.Attribute("objectclass", []string{"inetOrgPerson", "organizationalPerson", "person", "top"}) - req.Attribute("objectclass", []string{"inetOrgPerson"}) - req.Attribute("mail", []string{fmt.Sprintf("%s", mail)}) - if givenname != "" { - req.Attribute("givenname", []string{givenname}) - } - if member != "" { - req.Attribute("member", []string{member}) - } - if displayname != "" { - req.Attribute("displayname", []string{displayname}) - } - if sn != "" { - req.Attribute("sn", []string{sn}) - } - // log.Printf(fmt.Sprintf("226: %v",req)) - err := login.conn.Add(req) - if err != nil { - dError = err.Error() - } else { - modify_request := ldap.NewModifyRequest(dn, nil) - modify_request.Add("member", []string{guestDn}) - - err := login.conn.Modify(modify_request) - // log.Printf(fmt.Sprintf("249: %v",modify_request)) - if err != nil { - dError = err.Error() - } else { - dSuccess = true - } - } - } else { - dError = "Adding guest users not supported, the user must already have an LDAP account." - } - } else if len(sr.Entries) == 1 { - modify_request := ldap.NewModifyRequest(dn, nil) - modify_request.Add("member", []string{sr.Entries[0].DN}) - - err := login.conn.Modify(modify_request) - // log.Printf(fmt.Sprintf("264: %v",modify_request)) - if err != nil { - dError = err.Error() - } else { - dSuccess = true - } - } else { - dError = fmt.Sprintf("Multiple users exist with email address %s", mail) - } - } - } else if action == "delete-member" { - member := strings.Join(r.Form["member"], "") - modify_request := ldap.NewModifyRequest(dn, nil) - modify_request.Delete("member", []string{member}) - - err := login.conn.Modify(modify_request) - // log.Printf(fmt.Sprintf("280: %v",modify_request)) - if err != nil { - dError = err.Error() - } else { - dSuccess = true - } - } - } - - // Retrieve mailing list - searchRequest := ldap.NewSearchRequest( - dn, - ldap.ScopeBaseObject, ldap.NeverDerefAliases, 0, 0, false, - fmt.Sprintf("(objectclass=groupOfNames)"), - []string{"dn", config.MailingNameAttr, "member", "description"}, - nil) - - sr, err := login.conn.Search(searchRequest) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - - if len(sr.Entries) != 1 { - http.Error(w, fmt.Sprintf("Object not found: %s", dn), http.StatusNotFound) - return - } - - ml := sr.Entries[0] - - memberDns := make(map[string]bool) - for _, attr := range ml.Attributes { - if attr.Name == "member" { - for _, v := range attr.Values { - memberDns[v] = true - } - } - } - - // Retrieve list of current and possible new members - members := []*ldap.Entry{} - possibleNewMembers := []*ldap.Entry{} - - searchRequest = ldap.NewSearchRequest( - config.UserBaseDN, - ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false, - fmt.Sprintf("(objectClass=organizationalPerson)"), - []string{"dn", "displayname", "mail"}, - nil) - sr, err = login.conn.Search(searchRequest) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - - for _, ent := range sr.Entries { - if _, ok := memberDns[ent.DN]; ok { - members = append(members, ent) - } else { - possibleNewMembers = append(possibleNewMembers, ent) - } - } - - data := &AdminMailingListTplData{ - Login: NestedLoginTplData{ - Login: login, - }, - MailingNameAttr: config.MailingNameAttr, - MailingBaseDN: config.MailingBaseDN, - - MailingList: ml, - Members: members, - PossibleNewMembers: possibleNewMembers, - AllowGuest: config.MailingGuestsBaseDN != "", - Common: NestedCommonTplData{ - CanAdmin: true, - Error: dError, - Success: dSuccess, - LoggedIn: true}, - } - sort.Sort(data.Members) - sort.Sort(data.PossibleNewMembers) - - templateAdminMailingList.Execute(w, data) -} - -// =================================================== -// LDAP EXPLORER -// =================================================== - -func handleAdminLDAP(w http.ResponseWriter, r *http.Request) { - templateAdminLDAP := getTemplate("admin_ldap.html") - - login := checkAdminLogin(w, r) - if login == nil { - return - } - - dn := mux.Vars(r)["dn"] - - dError := "" - dSuccess := false - - // Build path - path := []PathItem{ - PathItem{ - DN: config.BaseDN, - Identifier: config.BaseDN, - Active: dn == config.BaseDN, - }, - } - // log.Printf(fmt.Sprintf("434: %v",path)) - - len_base_dn := len(strings.Split(config.BaseDN, ",")) - dn_split := strings.Split(dn, ",") - dn_last_attr := strings.Split(dn_split[0], "=")[0] - for i := len_base_dn + 1; i <= len(dn_split); i++ { - path = append(path, PathItem{ - DN: strings.Join(dn_split[len(dn_split)-i:len(dn_split)], ","), - Identifier: dn_split[len(dn_split)-i], - Active: i == len(dn_split), - }) - } - // log.Printf(fmt.Sprintf("446: %v",path)) - - // Handle modification operation - if r.Method == "POST" { - r.ParseForm() - action := strings.Join(r.Form["action"], "") - if action == "modify" { - attr := strings.Join(r.Form["attr"], "") - values := strings.Split(strings.Join(r.Form["values"], ""), "\n") - values_filtered := []string{} - for _, v := range values { - v2 := strings.TrimSpace(v) - if v2 != "" { - values_filtered = append(values_filtered, v2) - } - } - - if len(values_filtered) == 0 { - dError = "Refusing to delete attribute." - } else { - modify_request := ldap.NewModifyRequest(dn, nil) - modify_request.Replace(attr, values_filtered) - - err := login.conn.Modify(modify_request) - // log.Printf(fmt.Sprintf("468: %v",modify_request)) - if err != nil { - dError = err.Error() - } else { - dSuccess = true - } - } - } else if action == "add" { - attr := strings.Join(r.Form["attr"], "") - values := strings.Split(strings.Join(r.Form["values"], ""), "\n") - values_filtered := []string{} - for _, v := range values { - v2 := strings.TrimSpace(v) - if v2 != "" { - values_filtered = append(values_filtered, v2) - } - } - - modify_request := ldap.NewModifyRequest(dn, nil) - modify_request.Add(attr, values_filtered) - - err := login.conn.Modify(modify_request) - // log.Printf(fmt.Sprintf("490: %v",modify_request)) - if err != nil { - dError = err.Error() - } else { - dSuccess = true - } - } else if action == "delete" { - attr := strings.Join(r.Form["attr"], "") - - modify_request := ldap.NewModifyRequest(dn, nil) - modify_request.Replace(attr, []string{}) - - err := login.conn.Modify(modify_request) - // log.Printf(fmt.Sprintf("503: %v",modify_request)) - if err != nil { - dError = err.Error() - } else { - dSuccess = true - } - } else if action == "delete-from-group" { - group := strings.Join(r.Form["group"], "") - modify_request := ldap.NewModifyRequest(group, nil) - modify_request.Delete("member", []string{dn}) - - err := login.conn.Modify(modify_request) - // log.Printf(fmt.Sprintf("515: %v",modify_request)) - if err != nil { - dError = err.Error() - } else { - dSuccess = true - } - } else if action == "add-to-group" { - group := strings.Join(r.Form["group"], "") - modify_request := ldap.NewModifyRequest(group, nil) - modify_request.Add("member", []string{dn}) - - err := login.conn.Modify(modify_request) - // log.Printf(fmt.Sprintf("527: %v",modify_request)) - if err != nil { - dError = err.Error() - } else { - dSuccess = true - } - } else if action == "delete-member" { - member := strings.Join(r.Form["member"], "") - modify_request := ldap.NewModifyRequest(dn, nil) - modify_request.Delete("member", []string{member}) - - err := login.conn.Modify(modify_request) - // log.Printf(fmt.Sprintf("539: %v",modify_request)) - if err != nil { - dError = err.Error() - } else { - dSuccess = true - } - } else if action == "delete-object" { - del_request := ldap.NewDelRequest(dn, nil) - err := login.conn.Del(del_request) - if err != nil { - dError = err.Error() - } else { - http.Redirect(w, r, "/admin/ldap/"+strings.Join(dn_split[1:], ","), http.StatusFound) - return - } - } - } - - // Get object and parse it - searchRequest := ldap.NewSearchRequest( - dn, - ldap.ScopeBaseObject, ldap.NeverDerefAliases, 0, 0, false, - fmt.Sprintf("(objectclass=*)"), - []string{}, - nil) - - sr, err := login.conn.Search(searchRequest) - // log.Printf(fmt.Sprintf("569: %v",searchRequest)) - - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - - if len(sr.Entries) != 1 { - http.Error(w, fmt.Sprintf("Object not found: %s", dn), http.StatusNotFound) - return - } - - object := sr.Entries[0] - - // Read object properties and prepare appropriate form fields - props := make(map[string]*PropValues) - for _, attr := range object.Attributes { - name_lower := strings.ToLower(attr.Name) - if name_lower != dn_last_attr { - if existing, ok := props[name_lower]; ok { - existing.Values = append(existing.Values, attr.Values...) - } else { - editable := true - for _, restricted := range []string{ - "creatorsname", "modifiersname", "createtimestamp", - "modifytimestamp", "entryuuid", - } { - if strings.EqualFold(attr.Name, restricted) { - editable = false - break - } - } - deletable := true - for _, restricted := range []string{"objectclass", "structuralobjectclass"} { - if strings.EqualFold(attr.Name, restricted) { - deletable = false - break - } - } - props[name_lower] = &PropValues{ - Name: attr.Name, - Values: attr.Values, - Editable: editable, - Deletable: deletable, - } - } - } - } - - // Check objectclass to determine object type - objectClass := []string{} - if val, ok := props["objectclass"]; ok { - objectClass = val.Values - } - hasMembers, hasGroups, isOrganization := false, false, false - for _, oc := range objectClass { - if strings.EqualFold(oc, "organizationalPerson") || strings.EqualFold(oc, "person") || strings.EqualFold(oc, "inetOrgPerson") { - hasGroups = true - } - if strings.EqualFold(oc, "groupOfNames") { - hasMembers = true - } - if strings.EqualFold(oc, "organization") { - isOrganization = true - } - } - - // Parse member list and prepare form section - members_dn := []string{} - if mp, ok := props["member"]; ok { - members_dn = mp.Values - delete(props, "member") - } - - members := []EntryName{} - possibleNewMembers := []EntryName{} - if len(members_dn) > 0 || hasMembers { - // Lookup all existing users in the server - // to know the DN -> display name correspondance - searchRequest = ldap.NewSearchRequest( - config.UserBaseDN, - ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false, - fmt.Sprintf("(objectClass=organizationalPerson)"), - []string{"dn", "displayname", "description"}, - nil) - sr, err = login.conn.Search(searchRequest) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - - userMap := make(map[string]string) - for _, ent := range sr.Entries { - userMap[ent.DN] = ent.GetAttributeValue("displayname") - if userMap[ent.DN] == "" { - userMap[ent.DN] = ent.GetAttributeValue("description") - } - } - - // Select members with their name and remove them from map - for _, memdn := range members_dn { - members = append(members, EntryName{ - DN: memdn, - Name: userMap[memdn], - }) - delete(userMap, memdn) - } - - // Create list of members that can be added - for dn, name := range userMap { - entry := EntryName{ - DN: dn, - Name: name, - } - if entry.Name == "" { - entry.Name = entry.DN - } - possibleNewMembers = append(possibleNewMembers, entry) - } - } - - // // Parse group list and prepare form section - // groups_dn := []string{} - // if gp, ok := props["memberof"]; ok { - // groups_dn = gp.Values - // delete(props, "memberof") - // } - - groups := []EntryName{} - possibleNewGroups := []EntryName{} - searchRequest = ldap.NewSearchRequest( - config.GroupBaseDN, - ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false, - fmt.Sprintf("(&(objectClass=groupOfNames)(member=%s))", dn), - []string{"dn", "displayName", "cn", "description"}, - nil) - // log.Printf(fmt.Sprintf("708: %v",searchRequest)) - sr, err = login.conn.Search(searchRequest) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - // log.Printf(fmt.Sprintf("714: %v",sr.Entries)) - for _, ent := range sr.Entries { - groups = append(groups, EntryName{ - DN: ent.DN, - Name: ent.GetAttributeValue("cn"), - }) - } - searchRequest = ldap.NewSearchRequest( - config.GroupBaseDN, - ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false, - fmt.Sprintf("(&(objectClass=groupOfNames)(!(member=%s)))", dn), - []string{"dn", "displayName", "cn", "description"}, - nil) - // log.Printf(fmt.Sprintf("724: %v",searchRequest)) - sr, err = login.conn.Search(searchRequest) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - // log.Printf(fmt.Sprintf("714: %v",sr.Entries)) - for _, ent := range sr.Entries { - possibleNewGroups = append(possibleNewGroups, EntryName{ - DN: ent.DN, - Name: ent.GetAttributeValue("cn"), - }) - } - - // possibleNewGroup.DN = ent.GetAttributeValue("dn") - // possibleNewGroup.Name = ent.GetAttributeValue("cn") - // // log.Printf(fmt.Sprintf("725: %v %v",dn, ent.GetAttributeValue("member"))) - // for _, member := range ent .GetAttributeValue("member") { - // // // log.Printf(fmt.Sprintf("725: %v %v",dn, member)) - // if ent.GetAttributeValue("member") == dn { - // groups = append(groups,possibleNewGroup,) - // possibleNewGroup.DN = "" - // possibleNewGroup.Name = "" - // } - // // } - // if possibleNewGroup.DN != "" { - // possibleNewGroups = append(possibleNewGroups,possibleNewGroup,) - // possibleNewGroup = EntryName{} - // } - - // groupMap[.DN] = ent.GetAttributeValue("displayName") - // if groupMap[.DN] == "" { - // groupMap[.DN] = ent.GetAttributeValue("cn") - // } - // if groupMap[.DN] == "" { - // groupMap[.DN] = ent.GetAttributeValue("description") - // } - // } - - // // Calculate list of current groups - // // log.Printf(fmt.Sprintf("%v",groups_dn)) - // for _, grpdn := range groups_dn { - // // log.Printf(fmt.Sprintf("%v",grpdn)) - // groups = append(groups, EntryName{ - // DN: grpdn, - // Name: groupMap[grpdn], - // }) - // delete(groupMap, grpdn) - // } - - // // Calculate list of possible new groups - // for dn, name := range groupMap { - // entry := EntryName{ - // DN: dn, - // Name: name, - // } - // if entry.Name == "" { - // entry.Name = entry.DN - // } - // possibleNewGroups = append(possibleNewGroups, entry) - // } - // } - - // Get children - searchRequest = ldap.NewSearchRequest( - dn, - ldap.ScopeSingleLevel, ldap.NeverDerefAliases, 0, 0, false, - fmt.Sprintf("(objectclass=*)"), - []string{"dn", "displayname", "description"}, - nil) - - sr, err = login.conn.Search(searchRequest) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - - sort.Sort(EntryList(sr.Entries)) - - childrenOU := []Child{} - childrenOther := []Child{} - for _, item := range sr.Entries { - name := item.GetAttributeValue("displayname") - if name == "" { - name = item.GetAttributeValue("description") - } - child := Child{ - DN: item.DN, - Identifier: strings.Split(item.DN, ",")[0], - Name: name, - } - if strings.HasPrefix(item.DN, "ou=") { - childrenOU = append(childrenOU, child) - } else { - childrenOther = append(childrenOther, child) - } - } - - // Run template, finally! - templateAdminLDAP.Execute(w, &AdminLDAPTplData{ - DN: dn, - - Path: path, - ChildrenOU: childrenOU, - ChildrenOther: childrenOther, - Props: props, - CanAddChild: dn_last_attr == "ou" || isOrganization, - CanDelete: dn != config.BaseDN && len(childrenOU) == 0 && len(childrenOther) == 0, - - HasMembers: len(members) > 0 || hasMembers, - Members: members, - PossibleNewMembers: possibleNewMembers, - HasGroups: len(groups) > 0 || hasGroups, - Groups: groups, - PossibleNewGroups: possibleNewGroups, - - Common: NestedCommonTplData{ - CanAdmin: true, - LoggedIn: true, - Error: dError, - Success: dSuccess, - }, - }) -} - -func handleAdminCreate(w http.ResponseWriter, r *http.Request) { - templateAdminCreate := getTemplate("admin_create.html") - - login := checkAdminLogin(w, r) - if login == nil { - return - } - - template := mux.Vars(r)["template"] - super_dn := mux.Vars(r)["super_dn"] - - // Check that base DN exists - searchRequest := ldap.NewSearchRequest( - super_dn, - ldap.ScopeBaseObject, ldap.NeverDerefAliases, 0, 0, false, - fmt.Sprintf("(objectclass=*)"), - []string{}, - nil) - - sr, err := login.conn.Search(searchRequest) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - - if len(sr.Entries) != 1 { - http.Error(w, fmt.Sprintf("Parent object %s does not exist", super_dn), http.StatusNotFound) - return - } - - // Build path - path := []PathItem{ - PathItem{ - DN: config.BaseDN, - Identifier: config.BaseDN, - }, - } - - len_base_dn := len(strings.Split(config.BaseDN, ",")) - dn_split := strings.Split(super_dn, ",") - for i := len_base_dn + 1; i <= len(dn_split); i++ { - path = append(path, PathItem{ - DN: strings.Join(dn_split[len(dn_split)-i:len(dn_split)], ","), - Identifier: dn_split[len(dn_split)-i], - }) - } - - // Handle data - data := &CreateData{ - SuperDN: super_dn, - Path: path, - } - data.Template = template - if template == "user" { - data.IdType = config.UserNameAttr - data.StructuralObjectClass = "inetOrgPerson" - data.ObjectClass = "inetOrgPerson\norganizationalPerson\nperson\ntop" - } else if template == "group" || template == "ml" { - data.IdType = config.UserNameAttr - data.StructuralObjectClass = "groupOfNames" - data.ObjectClass = "groupOfNames\ntop" - data.Member = "cn=sogo@resdigita.org,ou=users,dc=resdigita,dc=org" - } else if template == "ou" { - data.IdType = "ou" - data.StructuralObjectClass = "organizationalUnit" - data.ObjectClass = "organizationalUnit\ntop" - } else { - data.IdType = "cn" - data.ObjectClass = "top" - data.Template = "" - } - - if r.Method == "POST" { - r.ParseForm() - if data.Template == "" { - data.IdType = strings.TrimSpace(strings.Join(r.Form["idtype"], "")) - data.StructuralObjectClass = strings.TrimSpace(strings.Join(r.Form["soc"], "")) - data.ObjectClass = strings.Join(r.Form["oc"], "") - } - data.IdValue = strings.TrimSpace(strings.Join(r.Form["idvalue"], "")) - data.DisplayName = strings.TrimSpace(strings.Join(r.Form["displayname"], "")) - data.GivenName = strings.TrimSpace(strings.Join(r.Form["givenname"], "")) - data.Mail = strings.TrimSpace(strings.Join(r.Form["mail"], "")) - data.Member = strings.TrimSpace(strings.Join(r.Form["member"], "")) - data.Description = strings.TrimSpace(strings.Join(r.Form["description"], "")) - data.SN = strings.TrimSpace(strings.Join(r.Form["sn"], "")) - - object_class := []string{} - for _, oc := range strings.Split(data.ObjectClass, "\n") { - x := strings.TrimSpace(oc) - if x != "" { - object_class = append(object_class, x) - } - } - - if len(object_class) == 0 { - data.Common.Error = "No object class specified" - } else if match, err := regexp.MatchString("^[a-z]+$", data.IdType); err != nil || !match { - data.Common.Error = "Invalid identifier type" - } else if len(data.IdValue) == 0 { - data.Common.Error = "No identifier specified" - } else { - newUser := User{ - DN: data.IdType + "=" + data.IdValue + "," + super_dn, - } - // dn := data.IdType + "=" + data.IdValue + "," + super_dn - // req := ldap.NewAddRequest(dn, nil) - // req.Attribute("objectclass", object_class) - // req.Attribute("mail", []string{data.IdValue}) - /* - if data.StructuralObjectClass != "" { - req.Attribute("structuralobjectclass", []string{data.StructuralObjectClass}) - } - */ - if data.Mail != "" { - newUser.Mail = data.Mail - // req.Attribute("mail", []string{data.Mail}) - } - if data.IdType == "cn" { - newUser.CN = data.IdValue - } else if data.IdType == "mail" { - newUser.Mail = data.IdValue - } else if data.IdType == "uid" { - newUser.UID = data.IdValue - } - - if data.DisplayName != "" { - newUser.DisplayName = data.DisplayName - // req.Attribute("displayname", []string{data.DisplayName}) - } - if data.GivenName != "" { - newUser.GivenName = data.GivenName - // req.Attribute("givenname", []string{data.GivenName}) - } - - // if data.Member != "" { - // req.Attribute("member", []string{data.Member}) - // } - if data.SN != "" { - newUser.SN = data.SN - // req.Attribute("sn", []string{data.SN}) - } - if data.Description != "" { - newUser.Description = data.Description - // req.Attribute("description", []string{data.Description}) - } - - add(newUser, config, login.conn) - - // err := login.conn.Add(req) - // // log.Printf(fmt.Sprintf("899: %v",err)) - // // log.Printf(fmt.Sprintf("899: %v",req)) - // // log.Printf(fmt.Sprintf("899: %v",data)) - // if err != nil { - // data.Common.Error = err.Error() - // } else { - if template == "ml" { - http.Redirect(w, r, "/admin/mailing/"+data.IdValue, http.StatusFound) - } else { - http.Redirect(w, r, "/admin/ldap/"+newUser.DN, http.StatusFound) - } - // } - } - } - data.Common.CanAdmin = true - - templateAdminCreate.Execute(w, data) -} diff --git a/config.go b/config.go deleted file mode 100644 index ebbde9d..0000000 --- a/config.go +++ /dev/null @@ -1,53 +0,0 @@ -/* -config handles reading the config.json file at the root and processing the settings -*/ -package main - -import ( - "encoding/json" - "flag" - "io/ioutil" - "log" - "os" -) - -var configFlag = flag.String("config", "./config.json", "Configuration file path") - -var config *ConfigFile - -func readConfig() ConfigFile { - // Default configuration values for certain fields - config_file := ConfigFile{ - HttpBindAddr: ":9991", - LdapServerAddr: "ldap://127.0.0.1:389", - - UserNameAttr: "uid", - GroupNameAttr: "gid", - - InvitationNameAttr: "cn", - InvitedAutoGroups: []string{}, - - Org: "ResDigita", - } - - _, err := os.Stat(*configFlag) - if os.IsNotExist(err) { - log.Fatalf("Could not find Guichet configuration file at %s. Please create this file, for exemple starting with config.json.exemple and customizing it for your deployment.", *configFlag) - } - - if err != nil { - log.Fatal(err) - } - - bytes, err := ioutil.ReadFile(*configFlag) - if err != nil { - log.Fatal(err) - } - - err = json.Unmarshal(bytes, &config_file) - if err != nil { - log.Fatal(err) - } - - return config_file -} diff --git a/controller.go b/controller.go index 49d3151..2ddee28 100644 --- a/controller.go +++ b/controller.go @@ -62,15 +62,26 @@ Create the different routes func makeGVRouter() (*mux.Router, error) { r := mux.NewRouter() r.HandleFunc("/", handleHome) - r.HandleFunc("/logout", handleLogout) - r.HandleFunc("/profile", handleProfile) - r.HandleFunc("/passwd", handlePasswd) + r.HandleFunc("/session/logout", handleLogout) + + r.HandleFunc("/user", handleProfile) + r.HandleFunc("/user/new", handleInviteNewAccount) + r.HandleFunc("/picture/{name}", handleDownloadPicture) - r.HandleFunc("/admin-activate", handleAdminActivateUsers) - r.HandleFunc("/admin-unactivate/{cn}", handleAdminUnactivateUser) - r.HandleFunc("/admin-activate/{cn}", handleAdminActivateUser) + r.HandleFunc("/passwd", handlePasswd) + r.HandleFunc("/passwd/lost", handleLostPassword) + r.HandleFunc("/passwd/lost/{code}", handleFoundPassword) + + r.HandleFunc("/admin", handleHome) + r.HandleFunc("/admin/activate", handleAdminActivateUsers) + r.HandleFunc("/admin/unactivate/{cn}", handleAdminUnactivateUser) + r.HandleFunc("/admin/activate/{cn}", handleAdminActivateUser) + r.HandleFunc("/admin/users", handleAdminUsers) + r.HandleFunc("/admin/groups", handleAdminGroups) + r.HandleFunc("/admin/ldap/{dn}", handleAdminLDAP) + r.HandleFunc("/admin/create/{template}/{super_dn}", handleAdminCreate) // r.HandleFunc("/directory/search", handleDirectorySearch) // r.HandleFunc("/directory", handleDirectory) @@ -79,18 +90,12 @@ func makeGVRouter() (*mux.Router, error) { // r.HandleFunc("/garage/website/new", handleGarageWebsiteNew) // r.HandleFunc("/garage/website/b/{bucket}", handleGarageWebsiteInspect) - r.HandleFunc("/inscription", handleInviteNewAccount) - // r.HandleFunc("/invite/send_code", handleInviteSendCode) - r.HandleFunc("/gpassword/{code}", handleFoundPassword) - r.HandleFunc("/gpas", handleLostPassword) + // r.HandleFunc("/user/send_code", handleInviteSendCode) + // r.HandleFunc("/invitation/{code}", handleInvitationCode) - r.HandleFunc("/admin-users", handleAdminUsers) - r.HandleFunc("/admin-groups", handleAdminGroups) // r.HandleFunc("/admin-mailing", handleAdminMailing) // r.HandleFunc("/admin/mailing/{id}", handleAdminMailingList) - r.HandleFunc("/admin-ldap/{dn}", handleAdminLDAP) - r.HandleFunc("/admin-create/{template}/{super_dn}", handleAdminCreate) staticFiles := http.FileServer(http.Dir(staticPath)) r.Handle("/static/{file:.*}", http.StripPrefix("/static/", staticFiles)) diff --git a/garage.go b/garage.go index c72f118..a2cf521 100644 --- a/garage.go +++ b/garage.go @@ -150,7 +150,7 @@ func handleGarageKey(w http.ResponseWriter, r *http.Request) { } view := keyView{Status: login, Key: s3key} - tKey := getTemplate("garage_key.html") + tKey := getTemplate("garage/key.html") tKey.Execute(w, &view) } @@ -167,7 +167,7 @@ func handleGarageWebsiteList(w http.ResponseWriter, r *http.Request) { } view := webListView{Status: login, Key: s3key} - tWebsiteList := getTemplate("garage_website_list.html") + tWebsiteList := getTemplate("garage/website/list.html") tWebsiteList.Execute(w, &view) } @@ -178,7 +178,7 @@ func handleGarageWebsiteNew(w http.ResponseWriter, r *http.Request) { return } - tWebsiteNew := getTemplate("garage_website_new.html") + tWebsiteNew := getTemplate("garage/website/new.html") if r.Method == "POST" { r.ParseForm() log.Println(r.Form) @@ -247,6 +247,6 @@ func handleGarageWebsiteInspect(w http.ResponseWriter, r *http.Request) { MaxSize: (&q).GetMaxSize(), } - tWebsiteInspect := getTemplate("garage_website_inspect.html") + tWebsiteInspect := getTemplate("garage/website/inspect.html") tWebsiteInspect.Execute(w, &view) } diff --git a/gpas.go b/gpas.go deleted file mode 100644 index 415ddab..0000000 --- a/gpas.go +++ /dev/null @@ -1,169 +0,0 @@ -/* -gpas is GVoisin password reset -*/ - -package main - -import ( - "bytes" - "errors" - "fmt" - "html/template" - "log" - - // "github.com/emersion/go-sasl" - // "github.com/emersion/go-smtp" - "net/smtp" - - "github.com/go-ldap/ldap/v3" - // "strings" - b64 "encoding/base64" -) - -// type InvitationAccount struct { -// UID string -// Password string -// BaseDN string -// } - -// var EMAIL_REGEXP := regexp.MustCompile("^[a-zA-Z0-9.!#$%&'*+\\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$") - -func passwordLost(user User, config *ConfigFile, ldapConn *ldap.Conn) error { - if user.CN == "" && user.Mail == "" && user.OtherMailbox == "" { - return errors.New("Il n'y a pas de quoi identifier l'utilisateur") - } - searchFilter := "(|" - if user.CN != "" { - searchFilter += "(cn=" + user.UID + ")" - } - if user.Mail != "" { - searchFilter += "(mail=" + user.Mail + ")" - } - if user.OtherMailbox != "" { - searchFilter += "(carLicense=" + user.OtherMailbox + ")" - } - searchFilter += ")" - searchReq := ldap.NewSearchRequest(config.UserBaseDN, ldap.ScopeSingleLevel, ldap.NeverDerefAliases, 0, 0, false, searchFilter, []string{"cn", "uid", "mail", "carLicense", "sn", "displayName", "givenName"}, nil) - searchRes, err := ldapConn.Search(searchReq) - if err != nil { - log.Printf(fmt.Sprintf("passwordLost 49 : %v %v", err, ldapConn)) - log.Printf(fmt.Sprintf("passwordLost 50 : %v", searchReq)) - log.Printf(fmt.Sprintf("passwordLost 51: %v", user)) - return err - } - if len(searchRes.Entries) == 0 { - log.Printf("Il n'y a pas d'utilisateur qui correspond %v", searchReq) - return errors.New("Il n'y a pas d'utilisateur qui correspond") - } - // log.Printf(fmt.Sprintf("passwordLost 58 : %v", user)) - // log.Printf(fmt.Sprintf("passwordLost 59 : %v", searchRes.Entries[0])) - // log.Printf(fmt.Sprintf("passwordLost 60 : %v", searchRes.Entries[0].GetAttributeValue("cn"))) - // log.Printf(fmt.Sprintf("passwordLost 61 : %v", searchRes.Entries[0].GetAttributeValue("uid"))) - // log.Printf(fmt.Sprintf("passwordLost 62 : %v", searchRes.Entries[0].GetAttributeValue("mail"))) - // log.Printf(fmt.Sprintf("passwordLost 63 : %v", searchRes.Entries[0].GetAttributeValue("carLicense"))) - // Préparation du courriel à envoyer - user.Password = suggestPassword() - code := b64.URLEncoding.EncodeToString([]byte(user.UID + ";" + user.Password)) - user.DN = "uid=" + searchRes.Entries[0].GetAttributeValue("cn") + ",ou=invitations,dc=resdigita,dc=org" - user.UID = searchRes.Entries[0].GetAttributeValue("cn") - user.CN = searchRes.Entries[0].GetAttributeValue("cn") - user.Mail = searchRes.Entries[0].GetAttributeValue("mail") - user.OtherMailbox = searchRes.Entries[0].GetAttributeValue("carLicense") - /* Check for outstanding invitation */ - searchReq = ldap.NewSearchRequest(config.InvitationBaseDN, ldap.ScopeBaseObject, - ldap.NeverDerefAliases, 0, 0, false, "(uid="+user.UID+")", []string{"seeAlso"}, nil) - searchRes, err = ldapConn.Search(searchReq) - if err != nil { - log.Printf(fmt.Sprintf("passwordLost (Check existing invitation) : %v", err)) - log.Printf(fmt.Sprintf("passwordLost (Check existing invitation) : %v", user)) - return err - } - if len(searchRes.Entries) == 0 { - /* Add the invitation */ - addReq := ldap.NewAddRequest( - user.DN, - nil) - addReq.Attribute("objectClass", []string{"top", "account", "simpleSecurityObject"}) - addReq.Attribute("uid", []string{user.UID}) - addReq.Attribute("userPassword", []string{"absdefghi"}) - addReq.Attribute("seeAlso", []string{config.UserNameAttr + "=" + user.UID + "," + config.UserBaseDN}) - err = ldapConn.Add(addReq) - if err != nil { - log.Printf(fmt.Sprintf("passwordLost 83 : %v", err)) - log.Printf(fmt.Sprintf("passwordLost 84 : %v", user)) - // log.Printf(fmt.Sprintf("passwordLost 85 : %v", searchRes.Entries[0])) - // For some reason I get here even if the entry exists already - return err - } - } - err = passwd(user, config, ldapConn) - if err != nil { - log.Printf(fmt.Sprintf("passwordLost 90 : %v", err)) - log.Printf(fmt.Sprintf("passwordLost 91 : %v", user)) - log.Printf(fmt.Sprintf("passwordLost 92 : %v", searchRes.Entries[0])) - return err - } - templateMail := template.Must(template.ParseFiles(templatePath + "/lost_password_email.txt")) - buf := bytes.NewBuffer([]byte{}) - templateMail.Execute(buf, &CodeMailFields{ - To: user.OtherMailbox, - From: config.MailFrom, - InviteFrom: user.UID, - Code: code, - WebBaseAddress: config.WebAddress, - }) - // message := []byte("Hi " + user.OtherMailbox) - log.Printf("Sending mail to: %s", user.OtherMailbox) - // var auth sasl.Client = nil - // if config.SMTPUsername != "" { - // auth = sasl.NewPlainClient("", config.SMTPUsername, config.SMTPPassword) - // } - message := buf.Bytes() - auth := smtp.PlainAuth("", config.SMTPUsername, config.SMTPPassword, config.SMTPServer) - log.Printf("auth: %v", auth) - err = smtp.SendMail(config.SMTPServer+":587", auth, config.SMTPUsername, []string{user.OtherMailbox}, message) - if err != nil { - log.Printf("email send error %v", err) - return err - } - log.Printf("Mail sent.") - return nil -} - -func passwordFound(user User, config *ConfigFile, ldapConn *ldap.Conn) (string, error) { - l, err := openLdap(config) - if err != nil { - log.Printf("passwordFound %v", err) - log.Printf("passwordFound Config : %v", config) - return "", err - } - if user.DN == "" && user.UID != "" { - user.DN = "uid=" + user.UID + ",ou=invitations,dc=resdigita,dc=org" - } - err = l.Bind(user.DN, user.Password) - if err != nil { - log.Printf("passwordFound %v", err) - log.Printf("passwordFound %v", user.DN) - log.Printf("passwordFound %v", user.UID) - return "", err - } - searchReq := ldap.NewSearchRequest(user.DN, ldap.ScopeBaseObject, - ldap.NeverDerefAliases, 0, 0, false, "(uid="+user.UID+")", []string{"seeAlso"}, nil) - var searchRes *ldap.SearchResult - searchRes, err = ldapConn.Search(searchReq) - if err != nil { - log.Printf("passwordFound %v", err) - log.Printf("passwordFound %v", searchReq) - log.Printf("passwordFound %v", ldapConn) - log.Printf("passwordFound %v", searchRes) - return "", err - } - if len(searchRes.Entries) == 0 { - log.Printf("passwordFound %v", err) - log.Printf("passwordFound %v", searchReq) - log.Printf("passwordFound %v", ldapConn) - log.Printf("passwordFound %v", searchRes) - return "", err - } - return searchRes.Entries[0].GetAttributeValue("seeAlso"), err -} diff --git a/home.go b/home.go deleted file mode 100644 index d895793..0000000 --- a/home.go +++ /dev/null @@ -1,40 +0,0 @@ -/* -home show the home page -*/ - -package main - -import "net/http" - -func handleHome(w http.ResponseWriter, r *http.Request) { - templateHome := getTemplate("home.html") - - login := checkLogin(w, r) - if login == nil { - status := handleLogin(w, r) - if status == nil { - return - } - login = checkLogin(w, r) - } - - can_admin := false - if login != nil { - can_admin = login.Common.CanAdmin - } - - data := HomePageData{ - Login: NestedLoginTplData{ - Login: login, - }, - BaseDN: config.BaseDN, - Org: config.Org, - Common: NestedCommonTplData{ - CanAdmin: can_admin, - CanInvite: true, - LoggedIn: true, - }, - } - templateHome.Execute(w, data) - -} diff --git a/http-utils.go b/http-utils.go deleted file mode 100644 index 6cae84e..0000000 --- a/http-utils.go +++ /dev/null @@ -1,40 +0,0 @@ -/* -http-utils provide utility functions that interact with http -*/ - -package main - -import ( - "crypto/tls" - "net" - "net/http" - - "github.com/go-ldap/ldap/v3" -) - -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) - handler.ServeHTTP(w, r) - }) -} - -func ldapOpen(w http.ResponseWriter) (*ldap.Conn, error) { - if config.LdapTLS { - tlsConf := &tls.Config{ - ServerName: config.LdapServerAddr, - InsecureSkipVerify: true, - } - return ldap.DialTLS("tcp", net.JoinHostPort(config.LdapServerAddr, "636"), tlsConf) - } else { - return ldap.DialURL("ldap://" + config.LdapServerAddr) - } - - // if err != nil { - // http.Error(w, err.Error(), http.StatusInternalServerError) - // log.Printf(fmt.Sprintf("27: %v %v", err, l)) - // return nil - // } - - // return l -} diff --git a/invite.go b/invite.go deleted file mode 100644 index e8890a5..0000000 --- a/invite.go +++ /dev/null @@ -1,555 +0,0 @@ -package main - -import ( - "bytes" - "crypto/rand" - "encoding/binary" - "encoding/hex" - "fmt" - "html/template" - "log" - "net/http" - "regexp" - "strings" - - // "github.com/emersion/go-sasl" - // "github.com/emersion/go-smtp" - "github.com/go-ldap/ldap/v3" - "github.com/gorilla/mux" - "golang.org/x/crypto/argon2" -) - -var EMAIL_REGEXP = regexp.MustCompile("^[a-zA-Z0-9.!#$%&'*+\\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$") - -func checkInviterLogin(w http.ResponseWriter, r *http.Request) *LoginStatus { - - login := checkLogin(w, r) - if login == nil { - return nil - } - - // if !login.CanInvite { - // http.Error(w, "Not authorized to invite new users.", http.StatusUnauthorized) - // return nil - // } - - return login -} - -// New account creation directly from interface - -func openNewUserLdap(config *ConfigFile) (*ldap.Conn, error) { - l, err := openLdap(config) - if err != nil { - log.Printf(fmt.Sprintf("openNewUserLdap 1 : %v %v", err, l)) - log.Printf(fmt.Sprintf("openNewUserLdap 1 : %v", config)) - // data.Common.ErrorMessage = err.Error() - } - err = l.Bind(config.NewUserDN, config.NewUserPassword) - if err != nil { - log.Printf(fmt.Sprintf("openNewUserLdap 2 : %v", err)) - log.Printf(fmt.Sprintf("openNewUserLdap 2 : %v", config.NewUserDN)) - log.Printf(fmt.Sprintf("openNewUserLdap 2 : %v", config.NewUserPassword)) - log.Printf(fmt.Sprintf("openNewUserLdap 2 : %v", config)) - // data.Common.ErrorMessage = err.Error() - } - return l, err -} - -func handleLostPassword(w http.ResponseWriter, r *http.Request) { - templateLostPasswordPage := getTemplate("password_lost.html") - if checkLogin(w, r) != nil { - http.Redirect(w, r, "/", http.StatusTemporaryRedirect) - } - - data := PasswordLostData{ - Common: NestedCommonTplData{ - CanAdmin: false, - LoggedIn: false}, - } - - if r.Method == "POST" { - r.ParseForm() - data.Username = strings.TrimSpace(strings.Join(r.Form["username"], "")) - data.Mail = strings.TrimSpace(strings.Join(r.Form["mail"], "")) - data.OtherMailbox = strings.TrimSpace(strings.Join(r.Form["othermailbox"], "")) - user := User{ - CN: strings.TrimSpace(strings.Join(r.Form["username"], "")), - UID: strings.TrimSpace(strings.Join(r.Form["username"], "")), - Mail: strings.TrimSpace(strings.Join(r.Form["mail"], "")), - OtherMailbox: strings.TrimSpace(strings.Join(r.Form["othermailbox"], "")), - } - ldapConn, err := openNewUserLdap(config) - if err != nil { - log.Printf(fmt.Sprintf("handleLostPassword 99 : %v %v", err, ldapConn)) - data.Common.ErrorMessage = err.Error() - } - err = passwordLost(user, config, ldapConn) - if err != nil { - log.Printf(fmt.Sprintf("handleLostPassword 104 : %v %v", err, ldapConn)) - data.Common.ErrorMessage = err.Error() - } else { - err = ldapConn.Bind(config.NewUserDN, config.NewUserPassword) - if err != nil { - log.Printf(fmt.Sprintf("handleLostPassword 109 : %v %v", err, ldapConn)) - data.Common.ErrorMessage = err.Error() - } else { - data.Common.Success = true - } - } - } - data.Common.CanAdmin = false - templateLostPasswordPage.Execute(w, data) -} - -func handleInviteNewAccount(w http.ResponseWriter, r *http.Request) { - l, err := ldapOpen(w) - if err != nil { - log.Printf(fmt.Sprintf("58: %v %v", err, l)) - } - // l.Bind(config.NewUserDN, config.NewUserPassword) - - // login := checkInviterLogin(w, r) - // if login == nil { - // return - // } - // l, _ := ldap.DialURL(config.LdapServerAddr) - // l.Bind(config.NewUserDN, config.NewUserPassword) - - // loginInfo, err := doLogin(w, r, "testuser", config.NewUserDN, config.NewUserPassword) - - // if err != nil { - // log.Printf(fmt.Sprintf("58: %v %v", err, l)) - // } - - // l := ldapOpen(w) - if l == nil { - return - } - - err = l.Bind(config.NewUserDN, config.NewUserPassword) - if err != nil { - log.Printf(fmt.Sprintf("58: %v %v", err, l)) - } - handleNewAccount(w, r, l, config.NewUserDN) -} - -// New account creation using code - -func handleInvitationCode(w http.ResponseWriter, r *http.Request) { - code := mux.Vars(r)["code"] - code_id, code_pw := readCode(code) - - // log.Printf(code_pw) - - login := checkLogin(w, r) - - // l := ldapOpen(w) - // if l == nil { - // return - // } - - inviteDn := config.InvitationNameAttr + "=" + code_id + "," + config.InvitationBaseDN - err := login.conn.Bind(inviteDn, code_pw) - if err != nil { - templateInviteInvalidCode := getTemplate("invite_invalid_code.html") - templateInviteInvalidCode.Execute(w, nil) - return - } - - sReq := ldap.NewSearchRequest( - inviteDn, - ldap.ScopeBaseObject, ldap.NeverDerefAliases, 0, 0, false, - fmt.Sprintf("(objectclass=*)"), - []string{"dn", "creatorsname"}, - nil) - sr, err := login.conn.Search(sReq) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - if len(sr.Entries) != 1 { - http.Error(w, fmt.Sprintf("Expected 1 entry, got %d", len(sr.Entries)), http.StatusInternalServerError) - return - } - - invitedBy := sr.Entries[0].GetAttributeValue("creatorsname") - - if handleNewAccount(w, r, login.conn, invitedBy) { - del_req := ldap.NewDelRequest(inviteDn, nil) - err = login.conn.Del(del_req) - if err != nil { - log.Printf("Could not delete invitation %s: %s", inviteDn, err) - } - } -} - -// Common functions for new account - -func handleNewAccount(w http.ResponseWriter, r *http.Request, l *ldap.Conn, invitedBy string) bool { - templateInviteNewAccount := getTemplate("invite_new_account.html") - - data := &NewAccountData{} - - if r.Method == "POST" { - r.ParseForm() - - newUser := User{} - // login := checkLogin(w, r) - - // newUser.Mail = fmt.Sprintf("%s@%s", strings.TrimSpace(strings.Join(r.Form["username"], "")), "lesgv.com") - newUser.DisplayName = strings.TrimSpace(strings.Join(r.Form["displayname"], "")) - newUser.GivenName = strings.TrimSpace(strings.Join(r.Form["givenname"], "")) - newUser.SN = strings.TrimSpace(strings.Join(r.Form["surname"], "")) - newUser.Mail = strings.TrimSpace(strings.Join(r.Form["mail"], "")) - newUser.UID = strings.TrimSpace(strings.Join(r.Form["otheremail"], "")) - newUser.CN = strings.TrimSpace(strings.Join(r.Form["username"], "")) - newUser.DN = "cn=" + strings.TrimSpace(strings.Join(r.Form["username"], "")) + "," + config.InvitationBaseDN - - password1 := strings.Join(r.Form["password"], "") - password2 := strings.Join(r.Form["password2"], "") - - if password1 != password2 { - data.Common.Success = false - data.ErrorPasswordMismatch = true - } else { - newUser.Password = password2 - l.Bind(config.NewUserDN, config.NewUserPassword) - err := add(newUser, config, l) - if err != nil { - data.Common.Success = false - data.Common.ErrorMessage = err.Error() - } - http.Redirect(w, r, "/admin/activate", http.StatusFound) - } - - // tryCreateAccount(l, data, password1, password2, invitedBy) - - } else { - data.SuggestPW = fmt.Sprintf("%s", suggestPassword()) - } - data.Common.CanAdmin = false - data.Common.LoggedIn = false - - templateInviteNewAccount.Execute(w, data) - return data.Common.Success -} - -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-z0-9._-]+$", data.Username); !(err == nil && match) { - data.ErrorInvalidUsername = true - checkFailed = true - } - - // Check if user exists - userDn := config.UserNameAttr + "=" + data.Username + "," + config.UserBaseDN - searchRq := ldap.NewSearchRequest( - userDn, - ldap.ScopeBaseObject, ldap.NeverDerefAliases, 0, 0, false, - "(objectclass=*)", - []string{"dn"}, - nil) - - sr, err := l.Search(searchRq) - if err != nil { - data.Common.ErrorMessage = err.Error() - checkFailed = true - } - - if len(sr.Entries) > 0 { - data.ErrorUsernameTaken = true - checkFailed = true - } - - // Check that password is long enough - if len(pass1) < 8 { - data.ErrorPasswordTooShort = true - checkFailed = true - } - - if pass1 != pass2 { - data.ErrorPasswordMismatch = true - 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"}) - pw, err := SSHAEncode(pass1) - if err != nil { - data.Common.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}) - } - if len(data.GivenName) > 0 { - req.Attribute("givenname", []string{data.GivenName}) - } - if len(data.Surname) > 0 { - req.Attribute("sn", []string{data.Surname}) - } - if len(config.InvitedMailFormat) > 0 { - email := strings.ReplaceAll(config.InvitedMailFormat, "{}", data.Username) - req.Attribute("mail", []string{email}) - } - - err = l.Add(req) - if err != nil { - data.Common.ErrorMessage = err.Error() - return - } - - for _, group := range config.InvitedAutoGroups { - req := ldap.NewModifyRequest(group, nil) - req.Add("member", []string{userDn}) - err = l.Modify(req) - if err != nil { - data.Common.WarningMessage += fmt.Sprintf("Cannot add to %s: %s\n", group, err.Error()) - } - } - - data.Common.Success = true -} - -// ---- Code generation ---- - -func handleInviteSendCode(w http.ResponseWriter, r *http.Request) { - templateInviteSendCode := getTemplate("invite_send_code.html") - - login := checkInviterLogin(w, r) - if login == nil { - return - } - - // carLicense - - if r.Method == "POST" { - r.ParseForm() - data := &SendCodeData{ - WebBaseAddress: config.WebAddress, - } - - // modify_request := ldap.NewModifyRequest(login.UserEntry.DN, nil) - // // choice := strings.Join(r.Form["choice"], "") - // // sendto := strings.Join(r.Form["sendto"], "") - code, code_id, code_pw := genCode() - log.Printf(fmt.Sprintf("272: %v %v %v", code, code_id, code_pw)) - // // Create invitation object in database - // modify_request.Add("carLicense", []string{fmt.Sprintf("%s,%s,%s",code, code_id, code_pw)}) - // err := login.conn.Modify(modify_request) - // if err != nil { - // data.Common.ErrorMessage = err.Error() - // // return - // } else { - // data.Common.Success = true - // data.CodeDisplay = code - // } - log.Printf(fmt.Sprintf("279: %v %v %v", code, code_id, code_pw)) - addReq := ldap.NewAddRequest("documentIdentifier="+code_id+","+config.InvitationBaseDN, nil) - addReq.Attribute("objectClass", []string{"top", "document", "simpleSecurityObject"}) - addReq.Attribute("cn", []string{code}) - addReq.Attribute("userPassword", []string{code_pw}) - addReq.Attribute("documentIdentifier", []string{code_id}) - log.Printf(fmt.Sprintf("285: %v %v %v", code, code_id, code_pw)) - log.Printf(fmt.Sprintf("286: %v", addReq)) - err := login.conn.Add(addReq) - if err != nil { - data.Common.ErrorMessage = err.Error() - // return - } else { - data.Common.Success = true - data.CodeDisplay = code - } - data.Common.CanAdmin = login.Common.CanAdmin - - templateInviteSendCode.Execute(w, data) - - // if choice == "display" || choice == "send" { - // log.Printf(fmt.Sprintf("260: %v %v %v %v", login, choice, sendto, data)) - // trySendCode(login, choice, sendto, data) - // } - } - -} - -func trySendCode(login *LoginStatus, choice string, sendto string, data *SendCodeData) { - log.Printf(fmt.Sprintf("269: %v %v %v %v", login, choice, sendto, data)) - // Generate code - code, code_id, code_pw := genCode() - log.Printf(fmt.Sprintf("272: %v %v %v", code, code_id, code_pw)) - // Create invitation object in database - - // len_base_dn := len(strings.Split(config.BaseDN, ",")) - // dn_split := strings.Split(super_dn, ",") - // for i := len_base_dn + 1; i <= len(dn_split); i++ { - // path = append(path, PathItem{ - // DN: strings.Join(dn_split[len(dn_split)-i:len(dn_split)], ","), - // Identifier: dn_split[len(dn_split)-i], - // }) - // } - // data := &SendCodeData{ - // WebBaseAddress: config.WebAddress, - // } - // // Handle data - // data := &CreateData{ - // SuperDN: super_dn, - // Path: path, - // } - // data.IdType = config.UserNameAttr - // data.StructuralObjectClass = "inetOrgPerson" - // data.ObjectClass = "inetOrgPerson\norganizationalPerson\nperson\ntop" - // data.IdValue = strings.TrimSpace(strings.Join(r.Form["idvalue"], "")) - // data.DisplayName = strings.TrimSpace(strings.Join(r.Form["displayname"], "")) - // data.GivenName = strings.TrimSpace(strings.Join(r.Form["givenname"], "")) - // data.Mail = strings.TrimSpace(strings.Join(r.Form["mail"], "")) - // data.Member = strings.TrimSpace(strings.Join(r.Form["member"], "")) - // data.Description = strings.TrimSpace(strings.Join(r.Form["description"], "")) - // data.SN = strings.TrimSpace(strings.Join(r.Form["sn"], "")) - // object_class := []string{} - // for _, oc := range strings.Split(data.ObjectClass, "\n") { - // x := strings.TrimSpace(oc) - // if x != "" { - // object_class = append(object_class, x) - // } - // } - // dn := data.IdType + "=" + data.IdValue + "," + super_dn - // req := ldap.NewAddRequest(dn, nil) - // req.Attribute("objectclass", object_class) - // // req.Attribute("mail", []string{data.IdValue}) - // /* - // if data.StructuralObjectClass != "" { - // req.Attribute("structuralobjectclass", []string{data.StructuralObjectClass}) - // } - // */ - // if data.DisplayName != "" { - // req.Attribute("displayname", []string{data.DisplayName}) - // } - // if data.GivenName != "" { - // req.Attribute("givenname", []string{data.GivenName}) - // } - // if data.Mail != "" { - // req.Attribute("mail", []string{data.Mail}) - // } - // if data.Member != "" { - // req.Attribute("member", []string{data.Member}) - // } - // if data.SN != "" { - // req.Attribute("sn", []string{data.SN}) - // } - // if data.Description != "" { - // req.Attribute("description", []string{data.Description}) - // } - // err := login.conn.Add(req) - // // log.Printf(fmt.Sprintf("899: %v",err)) - // // log.Printf(fmt.Sprintf("899: %v",req)) - // // log.Printf(fmt.Sprintf("899: %v",data)) - // if err != nil { - // data.Common.Error = err.Error() - // } else { - // if template == "ml" { - // http.Redirect(w, r, "/admin/mailing/"+data.IdValue, http.StatusFound) - // } else { - // http.Redirect(w, r, "/admin/ldap/"+dn, http.StatusFound) - // } - // } - - // inviteDn := config.InvitationNameAttr + "=" + code_id + "," + config.InvitationBaseDN - // req := ldap.NewAddRequest(inviteDn, nil) - // pw, err := SSHAEncode(code_pw) - // if err != nil { - // data.Common.ErrorMessage = err.Error() - // return - // } - // req.Attribute("employeeNumber", []string{pw}) - // req.Attribute("objectclass", []string{"top", "invitationCode"}) - - // err = login.conn.Add(req) - // if err != nil { - // log.Printf(fmt.Sprintf("286: %v", req)) - // data.Common.ErrorMessage = err.Error() - // return - // } - - // If we want to display it, do so - if choice == "display" { - data.Common.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: login.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.Common.ErrorMessage = err.Error() - // return - // } - // log.Printf("Mail sent.") - - data.Common.Success = true - data.CodeSentTo = sendto -} - -func genCode() (code string, code_id string, code_pw string) { - random := make([]byte, 32) - n, err := rand.Read(random) - if err != nil || n != 32 { - log.Fatalf("Could not generate random bytes: %s", err) - } - - a := binary.BigEndian.Uint32(random[0:4]) - b := binary.BigEndian.Uint32(random[4:8]) - c := binary.BigEndian.Uint32(random[8:12]) - - code = fmt.Sprintf("%03d-%03d-%03d", a%1000, b%1000, c%1000) - code_id, code_pw = readCode(code) - log.Printf(fmt.Sprintf("342: %v %v %v", code, code_id, code_pw)) - return code, code_id, code_pw -} - -func readCode(code string) (code_id string, code_pw string) { - // Strip everything that is not a digit - code_digits := "" - for _, c := range code { - if c >= '0' && c <= '9' { - code_digits = code_digits + string(c) - } - } - - id_hash := argon2.IDKey([]byte(code_digits), []byte("Guichet ID"), 2, 64*1024, 4, 32) - pw_hash := argon2.IDKey([]byte(code_digits), []byte("Guichet PW"), 2, 64*1024, 4, 32) - - code_id = hex.EncodeToString(id_hash[:8]) - code_pw = hex.EncodeToString(pw_hash[:16]) - return code_id, code_pw -} diff --git a/login.go b/login.go deleted file mode 100644 index f53b294..0000000 --- a/login.go +++ /dev/null @@ -1,128 +0,0 @@ -/* -login handles login and current-user verification -*/ - -package main - -import ( - "fmt" - "log" - "net/http" - "strings" - - "github.com/go-ldap/ldap/v3" -) - -func (login *LoginStatus) WelcomeName() string { - ret := login.UserEntry.GetAttributeValue("givenName") - if ret == "" { - ret = login.UserEntry.GetAttributeValue("displayName") - } - if ret == "" { - ret = login.Info.Username - } - return ret -} - -func handleLogout(w http.ResponseWriter, r *http.Request) { - - err := logout(w, r) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - - http.Redirect(w, r, "/", http.StatusFound) -} - -func handleLogin(w http.ResponseWriter, r *http.Request) *LoginInfo { - templateLogin := getTemplate("login.html") - - if r.Method == "POST" { - // log.Printf("%v", "Parsing Form handleLogin") - r.ParseForm() - - username := strings.Join(r.Form["username"], "") - password := strings.Join(r.Form["password"], "") - user_dn := fmt.Sprintf("%s=%s,%s", config.UserNameAttr, username, config.UserBaseDN) - - // log.Printf("%v", user_dn) - // log.Printf("%v", username) - - if strings.EqualFold(username, config.AdminAccount) { - user_dn = username - } - loginInfo, err := doLogin(w, r, username, user_dn, password) - // log.Printf("%v", loginInfo) - if err != nil { - data := &LoginFormData{ - Username: username, - Common: NestedCommonTplData{ - CanAdmin: false, - CanInvite: true, - LoggedIn: false, - }, - } - if ldap.IsErrorWithCode(err, ldap.LDAPResultInvalidCredentials) { - data.WrongPass = true - } else if ldap.IsErrorWithCode(err, ldap.LDAPResultNoSuchObject) { - data.WrongUser = true - } else { - log.Printf("%v", err) - log.Printf("%v", user_dn) - log.Printf("%v", username) - data.Common.ErrorMessage = err.Error() - } - templateLogin.Execute(w, data) - } - http.Redirect(w, r, "/", http.StatusTemporaryRedirect) - return loginInfo - - } else if r.Method == "GET" { - templateLogin.Execute(w, LoginFormData{ - Common: NestedCommonTplData{ - CanAdmin: false, - CanInvite: true, - LoggedIn: false}}) - return nil - } else { - http.Error(w, "Unsupported method", http.StatusBadRequest) - return nil - } -} - -func doLogin(w http.ResponseWriter, r *http.Request, username string, user_dn string, password string) (*LoginInfo, error) { - l, _ := ldapOpen(w) - - err := l.Bind(user_dn, password) - if err != nil { - log.Printf("doLogin : %v", err) - log.Printf("doLogin : %v", user_dn) - return nil, err - } - - // Successfully logged in, save it to session - session, err := store.Get(r, SESSION_NAME) - if err != nil { - session, _ = store.New(r, SESSION_NAME) - } - - session.Values["login_username"] = username - session.Values["login_password"] = password - session.Values["login_dn"] = user_dn - - err = session.Save(r, w) - if err != nil { - log.Printf("doLogin Session Save: %v", err) - http.Error(w, err.Error(), http.StatusInternalServerError) - return nil, err - } - - LoginInfo := LoginInfo{ - DN: user_dn, - Username: username, - Password: password, - } - - return &LoginInfo, nil -} diff --git a/model-user.go b/model-user.go index 34f5a91..99e2c2a 100644 --- a/model-user.go +++ b/model-user.go @@ -148,15 +148,6 @@ func bind(user User, config *ConfigFile, ldapConn *ldap.Conn) error { return ldapConn.Bind(user.DN, user.Password) } -func replaceIfContent(modifReq *ldap.ModifyRequest, key string, value string, previousValue string) error { - if value != "" { - modifReq.Replace(key, []string{value}) - } else if previousValue != "" { - modifReq.Delete(key, []string{previousValue}) - } - return nil -} - // func encodePassword(inPassword string) (string, error) { // utf16 := unicode.UTF16(unicode.LittleEndian, unicode.IgnoreBOM) // return utf16.NewEncoder().String("\"" + inPassword + "\"") diff --git a/profile.go b/profile.go deleted file mode 100644 index 67c9145..0000000 --- a/profile.go +++ /dev/null @@ -1,219 +0,0 @@ -package main - -import ( - b64 "encoding/base64" - "fmt" - "log" - "net/http" - "strings" - - "github.com/gorilla/mux" -) - -func handleProfile(w http.ResponseWriter, r *http.Request) { - templateProfile := getTemplate("profile.html") - - login := checkLogin(w, r) - if login == nil { - templatePasswd := getTemplate("passwd.html") - templatePasswd.Execute(w, PasswdTplData{ - - Common: NestedCommonTplData{ - CanAdmin: false, - LoggedIn: false}, - }) - return - } - - data := &ProfileTplData{ - Login: NestedLoginTplData{ - Status: login, - Login: login, - }, - Common: NestedCommonTplData{ - CanAdmin: login.Common.CanAdmin, - LoggedIn: true, - ErrorMessage: "", - Success: false, - }, - } - - data.Mail = login.UserEntry.GetAttributeValue("mail") - data.DisplayName = login.UserEntry.GetAttributeValue("displayName") - data.GivenName = login.UserEntry.GetAttributeValue("givenName") - data.Surname = login.UserEntry.GetAttributeValue("sn") - // data.Visibility = login.UserEntry.GetAttributeValue(FIELD_NAME_DIRECTORY_VISIBILITY) - data.Description = login.UserEntry.GetAttributeValue("description") - //data.ProfilePicture = login.UserEntry.GetAttributeValue(FIELD_NAME_PROFILE_PICTURE) - - if r.Method == "POST" { - //5MB maximum size files - r.ParseMultipartForm(5 << 20) - user := User{ - DN: login.Info.DN, - // CN: , - GivenName: strings.TrimSpace(strings.Join(r.Form["given_name"], "")), - DisplayName: strings.TrimSpace(strings.Join(r.Form["display_name"], "")), - Mail: strings.TrimSpace(strings.Join(r.Form["mail"], "")), - SN: strings.TrimSpace(strings.Join(r.Form["surname"], "")), - //UID: , - Description: strings.TrimSpace(strings.Join(r.Form["description"], "")), - // Password: , - } - - if user.DisplayName != "" { - err := modify(user, config, login.conn) - if err != nil { - data.Common.ErrorMessage = "handleProfile : " + err.Error() - } else { - data.Common.Success = true - } - } - findUser, err := get(user, config, login.conn) - if err != nil { - data.Common.ErrorMessage = "handleProfile : " + err.Error() - } - data.DisplayName = findUser.DisplayName - data.GivenName = findUser.GivenName - data.Surname = findUser.SN - data.Description = findUser.Description - data.Mail = findUser.Mail - data.Common.LoggedIn = false - - /* - visible := strings.TrimSpace(strings.Join(r.Form["visibility"], "")) - if visible != "" { - visible = "on" - } else { - visible = "off" - } - data.Visibility = visible - */ - /* - profilePicture, err := uploadProfilePicture(w, r, login) - if err != nil { - data.Common.ErrorMessage = err.Error() - } - if profilePicture != "" { - data.ProfilePicture = profilePicture - } - */ - - //modify_request.Replace(FIELD_NAME_DIRECTORY_VISIBILITY, []string{data.Visibility}) - //modify_request.Replace(FIELD_NAME_DIRECTORY_VISIBILITY, []string{"on"}) - //if data.ProfilePicture != "" { - // modify_request.Replace(FIELD_NAME_PROFILE_PICTURE, []string{data.ProfilePicture}) - // } - - // err := login.conn.Modify(modify_request) - // log.Printf(fmt.Sprintf("Profile:079: %v",modify_request)) - // log.Printf(fmt.Sprintf("Profile:079: %v",err)) - // log.Printf(fmt.Sprintf("Profile:079: %v",data)) - // if err != nil { - // data.Common.ErrorMessage = err.Error() - // } else { - // data.Common.Success = true - // } - - } - - templateProfile.Execute(w, data) -} - -func handleFoundPassword(w http.ResponseWriter, r *http.Request) { - templateFoundPasswordPage := getTemplate("passwd.html") - data := PasswdTplData{ - Common: NestedCommonTplData{ - CanAdmin: false, - LoggedIn: false}, - } - code := mux.Vars(r)["code"] - // code = strings.TrimSpace(strings.Join([]string{code}, "")) - newCode, _ := b64.URLEncoding.DecodeString(code) - ldapConn, err := openNewUserLdap(config) - if err != nil { - log.Printf(fmt.Sprint("handleFoundPassword / openNewUserLdap / %v", err)) - data.Common.ErrorMessage = err.Error() - } - codeArray := strings.Split(string(newCode), ";") - user := User{ - UID: codeArray[0], - Password: codeArray[1], - DN: "uid=" + codeArray[0] + ",ou=invitations,dc=resdigita,dc=org", - } - user.SeeAlso, err = passwordFound(user, config, ldapConn) - if err != nil { - log.Printf("handleFoundPassword / passwordFound %v", err) - log.Printf("handleFoundPassword / passwordFound %v", err) - data.Common.ErrorMessage = err.Error() - } - if r.Method == "POST" { - r.ParseForm() - - password := strings.Join(r.Form["password"], "") - password2 := strings.Join(r.Form["password2"], "") - - if len(password) < 8 { - data.TooShortError = true - } else if password2 != password { - data.NoMatchError = true - } else { - err := passwd(User{ - DN: user.SeeAlso, - Password: password, - }, config, ldapConn) - if err != nil { - data.Common.ErrorMessage = err.Error() - } else { - data.Common.Success = true - } - } - } - data.Common.CanAdmin = false - templateFoundPasswordPage.Execute(w, data) -} - -func handlePasswd(w http.ResponseWriter, r *http.Request) { - templatePasswd := getTemplate("passwd.html") - data := &PasswdTplData{ - Common: NestedCommonTplData{ - CanAdmin: false, - LoggedIn: true, - ErrorMessage: "", - Success: false, - }, - } - - login := checkLogin(w, r) - if login == nil { - templatePasswd.Execute(w, data) - return - } - data.Login.Status = login - data.Common.CanAdmin = login.Common.CanAdmin - - if r.Method == "POST" { - r.ParseForm() - - password := strings.Join(r.Form["password"], "") - password2 := strings.Join(r.Form["password2"], "") - - if len(password) < 8 { - data.TooShortError = true - } else if password2 != password { - data.NoMatchError = true - } else { - err := passwd(User{ - DN: login.Info.DN, - Password: password, - }, config, login.conn) - if err != nil { - data.Common.ErrorMessage = err.Error() - } else { - data.Common.Success = true - } - } - } - data.Common.CanAdmin = false - templatePasswd.Execute(w, data) -} diff --git a/ssha.go b/ssha.go deleted file mode 100644 index a198d27..0000000 --- a/ssha.go +++ /dev/null @@ -1,10 +0,0 @@ -package main - -import ( - "github.com/jsimonetti/pwscheme/ssha512" -) - -// Encode encodes the []byte of raw password -func SSHAEncode(rawPassPhrase string) (string, error) { - return ssha512.Generate(rawPassPhrase, 16) -} diff --git a/templates/admin_activate.html b/templates/admin_activate.html deleted file mode 100644 index 15a945c..0000000 --- a/templates/admin_activate.html +++ /dev/null @@ -1,39 +0,0 @@ -{{define "title"}}Activer des utilisateurs |{{end}} - -{{define "admenu"}} -{{end}} - -{{define "body"}} - - - - - - - - - - - - {{with $root := .}} - {{range $user := $root.Users}} - - - - - - - - - - {{end}} - {{end}} - -
LoginEmailNom d'ffichagePrénomNom de familledescription
- - Activer - - - {{$user.GetAttributeValue "cn"}} - {{$user.GetAttributeValue "mail"}}{{$user.GetAttributeValue "displayName"}}{{$user.GetAttributeValue "givenName"}}{{$user.GetAttributeValue "sn"}}{{$user.GetAttributeValue "description"}}
-{{end}} \ No newline at end of file diff --git a/templates/admin_create.html b/templates/admin_create.html deleted file mode 100644 index 392847a..0000000 --- a/templates/admin_create.html +++ /dev/null @@ -1,96 +0,0 @@ -{{define "title"}}Nouvel objet |{{end}} - -{{define "admenu"}} -{{end}} - - -{{define "body"}} -
-

Créer un objet

-
- -
- -
- -{{if .Common.Error}} -
Impossible de créer l'objet. -
{{ .Common.Error }}
-
-{{end}} - -
- - {{if eq .Template "ml"}} -
- - -
- {{else}} -
- - -
- {{end}} -
- - -
- {{ if eq .Template "user" }} -
- - -
-
- - -
- -
- - -
- -
- - -
- - {{ else }} -
- - -
- -
- - -
- - {{ end }} - -
- - -
- -
- -{{end}} diff --git a/templates/admin_groups.html b/templates/admin_groups.html deleted file mode 100644 index b74c424..0000000 --- a/templates/admin_groups.html +++ /dev/null @@ -1,40 +0,0 @@ -{{define "title"}}Liste des groupes |{{end}} - -{{define "admenu"}} -{{end}} - - -{{define "body"}} - -
-

Liste des groupes

- Nouveau groupe -
- -
- Les groupes servent uniquement à contrôler l'accès à différentes fonctionalités de Deuxfleurs. - Ce ne sont pas des mailing lists. -
- - - - - - - - {{with $root := .}} - {{range $group := $root.Groups}} - - - - - {{end}} - {{end}} - -
IdentifiantNom complet
- - {{$group.GetAttributeValue $root.GroupNameAttr}} - - {{$group.GetAttributeValue "description"}}
- -{{end}} diff --git a/templates/admin_ldap.html b/templates/admin_ldap.html deleted file mode 100644 index a8a9301..0000000 --- a/templates/admin_ldap.html +++ /dev/null @@ -1,239 +0,0 @@ -{{define "title"}}Explorateur LDAP |{{end}} - -{{define "admenu"}} -{{end}} - - -{{define "body"}} - -
-

Explorateur LDAP

-
- -
- -
- - - - {{range .ChildrenOU}} - - - - - {{end}} - {{range .ChildrenOther}} - - - - - {{end}} - -
- - 🗀 {{.Identifier}} - - {{.Name}}
- - {{.Identifier}} - - {{.Name}}
- -{{if .CanAddChild}} -
- +utilisateur - +groupe - +ou - +objet -
-
-{{end}} - -{{if .Common.Success}} -
Modification enregistrée.
-{{end}} -{{if .Common.Error}} -
- Impossible d'effectuer la modification. -
{{.Error}}
-
-{{end}} - -
Attributs
-
- {{range $key, $value := .Props}} - {{if $value.Editable}} -
-
{{$value.Name}}
- -
-
-
- - - -
- -
-
-
-
- -
- {{if $value.Deletable}} -
- - - -
- {{end}} -
-
- {{end}} - {{end}} - {{range $key, $value := .Props}} - {{if not $value.Editable}} -
-
{{$key}}
-
- {{range $value.Values}} - {{if eq $key "creatorsname" "modifiersname" }} -
{{.}}
- {{else}} -
{{.}}
- {{end}} - {{end}} -
-
- {{end}} - {{end}} -
-
-
- - -
-
-
- -
- -
-
-
-
-
-
- -{{if .HasMembers}} -
-
Membres
-
- {{range .Members}} -
-
- {{.Name}} -
-
- {{.DN}} -
-
-
- - - -
-
-
- {{end}} -
- - -
-
Ajouter au groupe : -
-
- - - {{range .PossibleNewMembers}} - - {{end}} - -
-
- -
- -
-{{end}} - -{{if .HasGroups}} -
-
Membre de
-
- {{range .Groups}} -
-
- {{.Name}} -
-
- {{.DN}} -
-
-
- - - -
-
-
- {{end}} -
- -
-
Nouveau groupe : -
-
- - - {{range .PossibleNewGroups}} - - {{end}} - -
-
- -
- -
-{{end}} - -{{if .CanDelete}} -
-
Supprimer l'objet
-
- Attention, cette opération est irrévocable ! -
-
-
- -
- -
-
-
-{{end}} - -
- -{{end}} diff --git a/templates/admin_mailing.html b/templates/admin_mailing.html deleted file mode 100644 index edb05f2..0000000 --- a/templates/admin_mailing.html +++ /dev/null @@ -1,35 +0,0 @@ -{{define "title"}}Mailing lists |{{end}} - -{{define "admenu"}} -{{end}} - -{{define "body"}} - -
-

Mailing lists

- Nouvelle mailing list - Menu principal -
- - - - - - - - {{with $root := .}} - {{range $ml := $root.MailingLists}} - - - - - {{end}} - {{end}} - -
AdresseDescription
- - {{$ml.GetAttributeValue $root.MailingNameAttr}} - - {{$ml.GetAttributeValue "description"}}
- -{{end}} diff --git a/templates/admin_mailing_list.html b/templates/admin_mailing_list.html deleted file mode 100644 index 895ddbc..0000000 --- a/templates/admin_mailing_list.html +++ /dev/null @@ -1,117 +0,0 @@ -{{define "title"}}ML {{.MailingList.GetAttributeValue .MailingNameAttr}} |{{end}} -{{define "admenu"}} -{{end}} -{{define "body"}} - -
-

ML {{.MailingList.GetAttributeValue .MailingNameAttr}} - Vue avancée -

- Liste des ML -
- -{{if .Common.Success}} -
Modification enregistrée.
-{{end}} -{{if .Common.Error}} -
- Impossible d'effectuer la modification. -
{{.Error}}
-
-{{end}} - -{{with $desc := .MailingList.GetAttributeValue "description"}}{{if $desc}} -

{{$desc}}

-{{end}}{{end}} - - - - - - - - - {{with $root := .}} - {{range $member := $root.Members}} - - - - - - {{end}} - {{end}} - {{if not .Members}} - - {{end}} - -
AdresseNom
- - {{$member.GetAttributeValue "mail"}} - - {{$member.GetAttributeValue "displayname"}} -
- - - -
-
(aucun abonné)
- -
-
Ajouter un destinataire
- -
-
- -
-
Utilisateur existant :
-
- - - {{range .PossibleNewMembers}} - {{if .GetAttributeValue "mail"}} - - {{end}} - {{end}} - -
-
- -
-
-
- - {{if .AllowGuest}} -
-
OU
-
- -
- -
-
E-mail :
-
- -
-
-
-
-
-
Nom (optionnel) :
-
- -
-
- -
-
-
- - Si un utilisateur existe déjà avec l'email spécifiée, celui-ci sera ajouté à la liste. - Sinon, un utilisateur invité sera créé. - -
-
- {{end}} -
- -{{end}} diff --git a/templates/admin_users.html b/templates/admin_users.html deleted file mode 100644 index 84f5edb..0000000 --- a/templates/admin_users.html +++ /dev/null @@ -1,43 +0,0 @@ -{{define "title"}}Liste des utilisateurs |{{end}} - -{{define "admenu"}} -{{end}} - - -{{define "body"}} - -
-

Liste des utilisateurs

- Nouvel utilisateur -
- - - - - - - - - - {{with $root := .}} - {{range $user := $root.Users}} - - - - - - - {{end}} - {{end}} - -
IdentifiantNom completEmail
- - Dèsactiver - - - - {{$user.GetAttributeValue $root.UserNameAttr}} - - {{$user.GetAttributeValue "displayName"}}{{$user.GetAttributeValue "mail"}}
- -{{end}} diff --git a/templates/directory_results.html b/templates/directory_results.html deleted file mode 100644 index c7dd715..0000000 --- a/templates/directory_results.html +++ /dev/null @@ -1,23 +0,0 @@ -{{if .Results}} - {{range .Results}} -
-
-
- {{if .ProfilePicture}} - - - - {{else}} - {{end}} -
-
- {{.DisplayName}} - {{.Id}}@ -
-

{{.Description}}

-
-
- {{end}} -{{else}} - Aucun résultat. -{{end}} diff --git a/templates/garage_key.html b/templates/garage_key.html deleted file mode 100644 index b322ab3..0000000 --- a/templates/garage_key.html +++ /dev/null @@ -1,237 +0,0 @@ -{{define "title"}}Profile |{{end}} - -{{define "admenu"}} -{{end}} - -{{define "body"}} -
-

Mes identifiants

- Mes sites webs - Menu principal -
- - - -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - -
Identifiant de clé{{ .Key.AccessKeyId }}
Clé secrète{{ .Key.SecretAccessKey }}
Régiongarage
Endpoint URLhttps://garage.resdigita.org
Type d'URLDNS et chemin (préférer chemin)
SignatureVersion 4
- -

Configurer votre logiciel :

- -
-
-
-

- -

-
-
-
-

Créez un fichier nommé ~/.awsrc :

-
-export AWS_ACCESS_KEY_ID={{ .Key.AccessKeyId }}
-export AWS_SECRET_ACCESS_KEY={{ .Key.SecretAccessKey }}
-export AWS_DEFAULT_REGION='garage'
-
-function aws { command aws --endpoint-url https://garage.resdigita.org $@ ; }
-aws --version
-                        
-

Ensuite vous pouvez utiliser awscli :

-
-source ~/.awsrc
-aws s3 ls
-aws s3 ls s3://my-bucket
-aws s3 cp /tmp/a.txt s3://my-bucket
-...
-                        
-
-
-
- -
-
-

- -

-
- -
-
-

Vous pouvez configurer Minio CLI avec cette commande :

-
-mc alias set \
-  garage \
-  https://garage.resdigita.org \
-  {{ .Key.AccessKeyId }} \
-  {{ .Key.SecretAccessKey }} \
-  --api S3v4
-                        
-

Et ensuite pour utiliser Minio CLI avec :

-
-mc ls garage/
-mc cp /tmp/a.txt garage/my-bucket/a.txt
-...
-                        
-
-
-
- -
-
-

- -

-
- -
-
- Reportez vous au guide -
-
-
- -
-
-

- -

-
-
-
-

Dans votre fichier config.toml, rajoutez :

-
-[[deployment.targets]]
- URL = "s3://bucket?endpoint=garage.resdigita.org&s3ForcePathStyle=true&region=garage"
-                        
-

Assurez-vous d'avoir un fichier dans lequel les variables AWS_ACCESS_KEY_ID et AWS_SECRET_ACCESS_KEY sont définies, - ici on suppose que vous avez suivi les instructions de l'outil awscli (ci-dessus) et que vous avez un fichier ~/.awsrc qui défini ces variables. - Ensuite :

-
-source ~/.awsrc
-hugo deploy
-                        
-
-
-
- -
-
-

- -

-
-
-
- Bientôt... -
-
-
-
-
- - -
- - - - - - - - - - - - - - - - - - - -
Nom d'utilisateur-ice{{ .Login.Status.Info.Username }}
Mot de passe(votre mot de passe guichet)
Hôtesftp://bagage.resdigita.org
Port2222
-

Configurer votre logiciel :

- -
-
-
-

- -

-
-
-
-

Un exemple avec SCP :

-
-scp -oHostKeyAlgorithms=+ssh-rsa -P2222 -r ./public {{ .Login.Status.Info.Username }}@bagage.resdigita.org:mon_bucket/
-                        
-
-
-
-
-
-

- -

-
-
-
- Bientôt -
-
-
-
- -
-
- -{{end}} diff --git a/templates/garage_website_inspect.html b/templates/garage_website_inspect.html deleted file mode 100644 index 3b5c8b5..0000000 --- a/templates/garage_website_inspect.html +++ /dev/null @@ -1,61 +0,0 @@ -{{define "title"}}Inspecter le site web |{{end}} - -{{define "admenu"}} -{{end}} - -{{define "body"}} -
-

Inspecter le site web

- Mes identifiants - Nouveau site web - Mes sites webs -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ID{{ .Bucket.Id }}
URLs - {{ range $alias := .Bucket.GlobalAliases }} - {{ if contains $alias "." }} - https://{{ $alias }} - {{ else }} - https://{{ $alias }}.web.resdigita.org - {{ end }} - {{ end }} -
Document d'index {{ .IndexDoc }}
Document d'erreur{{ .Common.ErrorDoc }}
Nombre de fichiers{{ .Bucket.Objects }} / {{ .MaxObjects }}
Espace utilisé{{ .Bucket.Bytes }} / {{ .MaxSize }} octets
- -

Configurer le nom de domaine

- -{{ range $alias := .Bucket.GlobalAliases }} -{{ if contains $alias "." }} -

Le nom de domaine {{ $alias }} n'est pas géré par Deuxfleurs, il vous revient donc de configurer la zone DNS. Vous devez ajouter une entrée CNAME garage.resdigita.org ou ALIAS garage.resdigita.org auprès de votre hébergeur DNS, qui est souvent aussi le bureau d'enregistrement (eg. Gandi, GoDaddy, BookMyName, etc.).

-{{ else }} -

Le nom de domaine https://{{ $alias }}.web.resdigita.org est fourni par Deuxfleurs, il n'y a pas de configuration à faire.

-{{ end }} -{{ end }} - -{{end}} diff --git a/templates/garage_website_list.html b/templates/garage_website_list.html deleted file mode 100644 index eb36afa..0000000 --- a/templates/garage_website_list.html +++ /dev/null @@ -1,41 +0,0 @@ -{{define "title"}}Sites webs |{{end}} - -{{define "admenu"}} -{{end}} - -{{define "body"}} - - - - - - - - - - {{ range $buck := .Key.Buckets }} - {{ if $buck.GlobalAliases }} - - - - - {{ end }} - {{ end }} - -
IDURLs
- {{$buck.Id}} - - {{ range $alias := $buck.GlobalAliases }} - {{ if contains $alias "." }} - https://{{ $alias }} - {{ else }} - https://{{ $alias }}.web.resdigita.org - {{ end }} - {{ end }} -
-{{end}} diff --git a/templates/garage_website_new.html b/templates/garage_website_new.html deleted file mode 100644 index 06b87c8..0000000 --- a/templates/garage_website_new.html +++ /dev/null @@ -1,66 +0,0 @@ -{{define "title"}}Créer un site web |{{end}} - -{{define "admenu"}} -{{end}} - -{{define "body"}} -
-

Créer un site web

- Mes identifiants - Mes sites webs -
- - - -
-
-
-
-
- - -
-
- - -
-
-
-

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.

-
- -
-
-
-
-
-
- - -
-
- - -
-
-
-

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. site.exemple.com), une entrée CNAME est appropriée :

-
site   CNAME    3600    garage.resdigita.org.
-

Si vous utilisez la racine de votre nom de domaine (eg. exemple.com, aussi appelée APEX), la solution dépend de votre fournisseur DNS, il vous faudra au choix une entrée ALIAS ou CNAME en fonction de ce que votre fournisseur supporte :

-
@      ALIAS    3600    garage.resdigita.org.
-

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.

-
-
- - - -
-
-{{end}} diff --git a/templates/home.html b/templates/home.html index 0688518..3130f02 100644 --- a/templates/home.html +++ b/templates/home.html @@ -14,7 +14,7 @@ Mon compte
@@ -56,11 +56,11 @@ Administration
{{end}} diff --git a/templates/invite_invalid_code.html b/templates/invite_invalid_code.html deleted file mode 100644 index fdb60de..0000000 --- a/templates/invite_invalid_code.html +++ /dev/null @@ -1,4 +0,0 @@ -{{define "title"}}Créer un compte |{{end}} - -{{define "admenu"}} -{{end}} diff --git a/templates/invite_mail.txt b/templates/invite_mail.txt deleted file mode 100644 index 6058937..0000000 --- a/templates/invite_mail.txt +++ /dev/null @@ -1,13 +0,0 @@ -From: {{.From}} -To: {{.To}} -Subject: Code d'invitation GVoisin.com -Content-type: text/plain; charset=utf-8 - -Vous avez été invité à créer un compte sur GVoisin.com par {{.InviteFrom}} :) - -Pour créer votre compte, rendez-vous à l'addresse suivante: - -{{.WebBaseAddress}}/invitation/{{.Code}} - -À bientôt sur GVoisin.com ! - diff --git a/templates/invite_new_account.html b/templates/invite_new_account.html deleted file mode 100644 index 69c7f6f..0000000 --- a/templates/invite_new_account.html +++ /dev/null @@ -1,131 +0,0 @@ -{{define "title"}}Créer un compte{{end}} - -{{define "admenu"}} -{{end}} - -{{define "body"}} -
-

Création d'un nouveau compte

-
-{{if .Common.ErrorMessage}} -
Impossible de créer le compte. -
{{ .Common.ErrorMessage }}
-
-{{end}} -{{if .Common.WarningMessage}} -
Des erreurs se sont produites, le compte pourrait ne pas être totalement - fonctionnel. -
{{ .Common.WarningMessage }}
-
-{{end}} -{{if .Common.Success}} -
- Le compe a été créé ! - Rendez-vous sur la page d'accueil pour vous connecter avec ce nouveau compte. -
-{{else}} -
-
- - -
-
- - -
-
- - - - Le courriel de l'utilisateur. - -
-
- - -
-
- - - - Votre identifiant doit être en minuscule. - -
-
-
- {{if .ErrorInvalidUsername}} -
- Nom d'utilisateur invalide. Ne peut contenir que les caractères suivants : chiffres, lettres minuscules, point, - tiret bas (_) et tiret du milieu (-). -
- {{end}} - {{if .ErrorUsernameTaken}} -
- Ce nom d'utilisateur est déjà pris. -
- {{end}} -
- - - - Le courriel et login interne. - -
-

Utiliser ce mot de passe : {{ .SuggestPW }}

-
- - - - 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 ! - -
- {{if .ErrorPasswordTooShort}} -
- Le mot de passe choisi est trop court (minimum 8 caractères). -
- {{end}} -
- - -
- {{if .ErrorPasswordMismatch}} -
- Les deux mots de passe entrés ne correspondent pas. -
- {{end}} - -
- - -{{end}} -{{end}} \ No newline at end of file diff --git a/templates/invite_send_code.html b/templates/invite_send_code.html deleted file mode 100644 index 04d2c8c..0000000 --- a/templates/invite_send_code.html +++ /dev/null @@ -1,66 +0,0 @@ -{{define "title"}}Envoyer un code d'invitation{{end}} -{{define "admenu"}} -{{end}} - -{{define "body"}} -
-

Envoyer un code d'invitation

- Retour -
- - {{if .Common.ErrorMessage}} -
Impossible de génerer ou d'envoyer le code. -
{{ .Common.ErrorMessage }}
-
- {{end}} - {{if .Common.Success}} -
- {{if .CodeSentTo}} - Un code d'invitation a bien été envoyé à {{ .CodeSentTo }}. - {{end}} - {{if .CodeDisplay}} - Lien d'invitation : - -

- {{.WebBaseAddress}}/invitation/{{.CodeDisplay}} -

- {{end}} -
- {{else}} -
- Choisissez une option: - -
-
-
- -
-
- - -
- {{if .Common.ErrorInvalidEmail}} -
- Addresse mail invalide. -
- {{end}} - -
-
-
- -
-
- -
- -
- -
-
- {{end}} -{{end}} diff --git a/templates/layout.html b/templates/layout.html index 523971b..070d5bc 100644 --- a/templates/layout.html +++ b/templates/layout.html @@ -58,24 +58,24 @@ {{if .Common.CanAdmin}}
  • Administration
  • {{end}}
  • Compte
  •  < Jour et nuit
  • diff --git a/templates/login.html b/templates/login.html index 6e5c157..ae9a0fa 100644 --- a/templates/login.html +++ b/templates/login.html @@ -33,8 +33,8 @@ -

    Mot de passe perdu

    +

    Mot de passe perdu

    -

    S'enregistrer

    +

    S'enregistrer

    {{end}} diff --git a/templates/lost_password_email.txt b/templates/lost_password_email.txt deleted file mode 100644 index d99c559..0000000 --- a/templates/lost_password_email.txt +++ /dev/null @@ -1,13 +0,0 @@ -From: {{.From}} -To: {{.To}} -Subject: Code d'invitation GVoisin.com -Content-type: text/plain; charset=utf-8 - -Une refonte de mot de passe avait été demandé sur GVoisin.com - -Pour créer votre compte, rendez-vous à l'adresse suivante: - -{{.WebBaseAddress}}/gpassword/{{.Code}} - -À bientôt sur GVoisin.com ! - diff --git a/templates/password_lost.html b/templates/password_lost.html deleted file mode 100644 index 6efdebe..0000000 --- a/templates/password_lost.html +++ /dev/null @@ -1,40 +0,0 @@ -{{define "title"}}G Pas (Je n'ai pas mon mal de passe){{end}} - -{{define "admenu"}} -{{end}} - -{{define "body"}} -

    G Pas

    - -

    Refaire son mot de passe

    - -{{if .Common.ErrorMessage}} -
    Impossible -
    {{ .Common.ErrorMessage }}
    -
    -{{end}} -{{if .Common.Success}} -
    - Email envoyé au courriel de secours. -
    -{{end}} - -

    Merci de renseigner au moins un des champs ci-dessous.

    - -
    -
    - - -
    -
    - - -
    -
    - - -
    - -
    - -{{end}} \ No newline at end of file diff --git a/templates/profile.html b/templates/profile.html deleted file mode 100644 index b033688..0000000 --- a/templates/profile.html +++ /dev/null @@ -1,86 +0,0 @@ -{{define "title"}}Profile{{end}} - -{{define "admenu"}} -{{end}} - -{{define "body"}} -
    -

    Modifier mon profil

    -
    - - {{if .Common.ErrorMessage}} -
    Impossible d'effectuer la modification. -
    {{ .Common.ErrorMessage }}
    -
    - {{end}} - {{if .Common.Success}} -
    - Profil enregistré. -
    - {{end}} -
    -
    -
    - - -
    -
    - - -
    -
    -
    - - -
    - -{{/* - - - -*/}} -
    -
    - - -
    -
    - - -
    -
    - -
    - - -
    - -
    - -{{end}}