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"}} -
- | Login | -Nom d'ffichage | -Prénom | -Nom de famille | -description | - - - {{with $root := .}} - {{range $user := $root.Users}} -|
---|---|---|---|---|---|---|
- - Activer - - | -- {{$user.GetAttributeValue "cn"}} - | -{{$user.GetAttributeValue "mail"}} | -{{$user.GetAttributeValue "displayName"}} | -{{$user.GetAttributeValue "givenName"}} | -{{$user.GetAttributeValue "sn"}} | -{{$user.GetAttributeValue "description"}} | -
Identifiant | -Nom complet | - - - {{with $root := .}} - {{range $group := $root.Groups}} -
---|---|
- - {{$group.GetAttributeValue $root.GroupNameAttr}} - - | -{{$group.GetAttributeValue "description"}} | -
- - 🗀 {{.Identifier}} - - | -{{.Name}} | -
- - {{.Identifier}} - - | -{{.Name}} | -
Utiliser ce mot de passe : {{ .SuggestPW }}
-{{ .CodeSentTo }}
.
- {{end}}
- {{if .CodeDisplay}}
- Lien d'invitation :
-
-
- {{end}}
- Refaire son mot de passe
- -{{if .Common.ErrorMessage}} -Merci de renseigner au moins un des champs ci-dessous.
- -