package main import ( "crypto/sha256" "encoding/json" "fmt" "io" "log" "net/http" "strings" ) type Group struct { GroupId int64 Name string Password string `db:"-"` PasswordHash string `json:"-"` } type GroupList struct { Groups *[]*Group `json:"groups"` } type GroupExistsError struct{} func (gee GroupExistsError) Error() string { return "Group exists" } func (g *Group) Write(w http.ResponseWriter) error { enc := json.NewEncoder(w) return enc.Encode(g) } func (g *Group) Read(json_str string) error { dec := json.NewDecoder(strings.NewReader(json_str)) return dec.Decode(g) } func (gl *GroupList) Write(w http.ResponseWriter) error { enc := json.NewEncoder(w) return enc.Encode(gl) } func (g *Group) HashPassword() { password_hasher := sha256.New() io.WriteString(password_hasher, g.Password) g.PasswordHash = fmt.Sprintf("%x", password_hasher.Sum(nil)) g.Password = "" } func GetGroup(groupid int64) (*Group, error) { var g Group err := DB.SelectOne(&g, "SELECT * from groups where GroupId=?", groupid) if err != nil { return nil, err } return &g, nil } func ValidGroup(groupid int64, password string) (bool, error) { var test Group test.Password = password test.HashPassword() group, err := GetGroup(groupid) if err != nil { return false, err } else { return group.PasswordHash == test.PasswordHash, nil } } func GetGroups() (*[]*Group, error) { var groups []*Group _, err := DB.Select(&groups, "SELECT * from groups") if err != nil { return nil, err } return &groups, nil } func GetGroupByName(groupname string) (*Group, error) { var g Group err := DB.SelectOne(&g, "SELECT * from groups where Name=?", groupname) if err != nil { return nil, err } return &g, nil } func InsertGroup(g *Group) error { transaction, err := DB.Begin() if err != nil { return err } existing, err := transaction.SelectInt("SELECT count(*) from groups where Name=?", g.Name) if err != nil { transaction.Rollback() return err } if existing > 0 { transaction.Rollback() return GroupExistsError{} } err = transaction.Insert(g) if err != nil { transaction.Rollback() return err } err = transaction.Commit() if err != nil { transaction.Rollback() return err } return nil } func GroupHandler(w http.ResponseWriter, r *http.Request) { if r.Method == "POST" { group_json := r.PostFormValue("group") if group_json == "" { WriteError(w, 3 /*Invalid Request*/) return } var group Group err := group.Read(group_json) if err != nil { WriteError(w, 3 /*Invalid Request*/) return } group.GroupId = -1 group.HashPassword() err = InsertGroup(&group) if err != nil { if _, ok := err.(GroupExistsError); ok { WriteError(w, 9 /*Group Exists*/) } else { WriteError(w, 999 /*Internal Error*/) log.Print(err) } return } w.WriteHeader(201 /*Created*/) err = group.Write(w) if err != nil { WriteError(w, 999 /*Internal Error*/) log.Print(err) return } } else if r.Method == "GET" { var gl GroupList groups, err := GetGroups() if err != nil { WriteError(w, 999 /*Internal Error*/) log.Print(err) return } gl.Groups = groups err = (&gl).Write(w) if err != nil { WriteError(w, 999 /*Internal Error*/) log.Print(err) return } } else if r.Method == "PUT" { user, err := GetUserFromSession(r) if err != nil { WriteError(w, 1 /*Not Signed In*/) return } groupid, err := GetURLID(r.URL.Path) if err != nil { WriteError(w, 3 /*Invalid Request*/) return } if groupid != user.GroupId { WriteError(w, 2 /*Unauthorized Access*/) return } group_json := r.PostFormValue("group") if group_json == "" { WriteError(w, 3 /*Invalid Request*/) return } group, err := GetGroup(groupid) if err != nil { WriteError(w, 999 /*Internal Error*/) log.Print(err) return } // Save old PWHash in case the new password is bogus old_pwhash := group.PasswordHash err = group.Read(group_json) if err != nil || group.GroupId != groupid { WriteError(w, 3 /*Invalid Request*/) return } // If the user didn't create a new password for the group, keep the old one if group.Password != BogusPassword { group.HashPassword() } else { group.Password = "" group.PasswordHash = old_pwhash } count, err := DB.Update(group) if count != 1 || err != nil { WriteError(w, 999 /*Internal Error*/) log.Print(err) return } err = group.Write(w) if err != nil { WriteError(w, 999 /*Internal Error*/) log.Print(err) return } } else { /* DELETE not implemented*/ WriteError(w, 3 /*Invalid Request*/) return } }