244 lines
4.6 KiB
Go
244 lines
4.6 KiB
Go
|
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
|
||
|
}
|
||
|
}
|