Adding group creation support.
This commit is contained in:
parent
b0e9e7c35c
commit
cc509ec22a
177
wwwshop/controller/groupcontroller/groupcontroller.go
Normal file
177
wwwshop/controller/groupcontroller/groupcontroller.go
Normal file
@ -0,0 +1,177 @@
|
||||
package groupcontroller
|
||||
|
||||
import (
|
||||
d "WWWShop/wwwshop/dao/database"
|
||||
u "WWWShop/wwwshop/dao/groupmanager"
|
||||
"WWWShop/wwwshop/model/group"
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"errors"
|
||||
)
|
||||
|
||||
type GroupController struct{}
|
||||
|
||||
func New() GroupController {
|
||||
return GroupController{}
|
||||
}
|
||||
|
||||
func (self GroupController) DELETE(w http.ResponseWriter, r *http.Request) {
|
||||
ids, groupnames, _, err := self.SetupInputForFilter(w, r)
|
||||
group_manager := u.New(d.DB())
|
||||
|
||||
if err != nil {
|
||||
if err != nil {
|
||||
json_response,_ := EncodeJSONResponse(NewResponseError(err.Error()))
|
||||
fmt.Fprintf(w, json_response)
|
||||
return
|
||||
}
|
||||
}
|
||||
deleted_groups, err := group_manager.Delete(ids, groupnames)
|
||||
if err != nil {
|
||||
json_response, _ := EncodeJSONResponse(NewResponseError(err.Error()))
|
||||
fmt.Fprintf(w, json_response)
|
||||
return
|
||||
}
|
||||
deleted_groups_json, _ := EncodeJSONResponse(deleted_groups)
|
||||
fmt.Fprintf(w, deleted_groups_json)
|
||||
}
|
||||
|
||||
func (self GroupController) SetupInputForFilter(w http.ResponseWriter, r *http.Request) ([]int64, []string, *int64, error) {
|
||||
query := r.URL.Query()
|
||||
groupnames, _ := query["groupname"]
|
||||
ids, _ := query["id"]
|
||||
pages, _ := query["page"]
|
||||
var page int64
|
||||
if len(pages) == 0 {
|
||||
page = 0
|
||||
} else {
|
||||
var err error
|
||||
page, err = strconv.ParseInt(pages[0], 0, 64)
|
||||
if err != nil {
|
||||
return nil, nil, nil, errors.New("Unable to parse int page.")
|
||||
}
|
||||
}
|
||||
ids_int := make([]int64, 0)
|
||||
for _, id := range ids {
|
||||
id_int, err := strconv.ParseInt(id, 0, 64)
|
||||
if err != nil {
|
||||
return nil, nil, nil, errors.New("Unable to parse int id.")
|
||||
}
|
||||
ids_int = append(ids_int, id_int)
|
||||
}
|
||||
return ids_int, groupnames, &page, nil
|
||||
}
|
||||
|
||||
func (self GroupController) PUT(w http.ResponseWriter, r *http.Request) {
|
||||
var decoded_group_struct group.Group
|
||||
decoder := json.NewDecoder(r.Body)
|
||||
err := decoder.Decode(&decoded_group_struct)
|
||||
if err != nil {
|
||||
http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
|
||||
json_response, _ := EncodeJSONResponse(NewResponseError("Failed to decode json group on update."))
|
||||
fmt.Fprintf(w, json_response)
|
||||
return
|
||||
}
|
||||
if decoded_group_struct.Id == nil && decoded_group_struct.Groupname == nil {
|
||||
http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
|
||||
json_response, _ := EncodeJSONResponse(NewResponseError("Failed to get groupname or id needed to update groups."))
|
||||
fmt.Fprintf(w, json_response)
|
||||
return
|
||||
}
|
||||
if decoded_group_struct.Permissions == nil {
|
||||
decoded_group_struct.Permissions = make(map[string]string)
|
||||
}
|
||||
group_manager := u.New(d.DB())
|
||||
group, err := group_manager.Update(decoded_group_struct)
|
||||
if err != nil {
|
||||
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
||||
json_response, _ := EncodeJSONResponse(NewResponseError(strings.Join([]string{"Failed to update group with the given data, may be our fault: ", err.Error()}, "")))
|
||||
fmt.Fprintf(w, json_response)
|
||||
return
|
||||
}
|
||||
json_response, _ := EncodeJSONResponse(group)
|
||||
fmt.Fprintf(w, json_response)
|
||||
}
|
||||
|
||||
func (self GroupController) GET(w http.ResponseWriter, r *http.Request) {
|
||||
group_manager := u.New(d.DB())
|
||||
ids, groupnames, page, err := self.SetupInputForFilter(w, r)
|
||||
if err != nil {
|
||||
http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
|
||||
json_response, _ := EncodeJSONResponse(NewResponseError(err.Error()))
|
||||
fmt.Fprintf(w, json_response)
|
||||
return
|
||||
}
|
||||
groups, err := group_manager.Retrieve(*page, ids, groupnames)
|
||||
if err != nil {
|
||||
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
||||
json_response, _ := EncodeJSONResponse(NewResponseError(strings.Join([]string{"Unable to retrieve groups ", err.Error()}, "")))
|
||||
fmt.Fprintf(w, json_response)
|
||||
return
|
||||
}
|
||||
json_response, _ := EncodeJSONResponse(groups)
|
||||
fmt.Fprintf(w, json_response)
|
||||
}
|
||||
|
||||
func (self GroupController) POST(w http.ResponseWriter, r *http.Request) {
|
||||
var decoded_group_struct POSTGroup
|
||||
decoder := json.NewDecoder(r.Body)
|
||||
err := decoder.Decode(&decoded_group_struct)
|
||||
if err != nil {
|
||||
json_response, _ := EncodeJSONResponse(NewResponseError("Unable to decode json"))
|
||||
fmt.Fprintf(w, json_response)
|
||||
return
|
||||
}
|
||||
if decoded_group_struct.Groupname == "" {
|
||||
http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
|
||||
json_response, _ := EncodeJSONResponse(NewResponseError("Unable to get groupname"))
|
||||
fmt.Fprintf(w, json_response)
|
||||
return
|
||||
}
|
||||
if decoded_group_struct.Permissions == nil {
|
||||
decoded_group_struct.Permissions = make(map[string]string)
|
||||
}
|
||||
group_manager := u.New(d.DB())
|
||||
group, err := group_manager.Add(decoded_group_struct.Groupname, decoded_group_struct.Permissions)
|
||||
if err != nil {
|
||||
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
||||
json_response, _ := EncodeJSONResponse(NewResponseError(strings.Join(
|
||||
[]string{"Unable to create group ", err.Error()},
|
||||
"")))
|
||||
fmt.Fprintf(w, json_response)
|
||||
return
|
||||
}
|
||||
json_response, err := EncodeJSONResponse(group)
|
||||
fmt.Fprintf(w, json_response)
|
||||
}
|
||||
|
||||
type Response interface{}
|
||||
|
||||
type ResponseError struct {
|
||||
Error string `json:"error"`
|
||||
}
|
||||
|
||||
func NewResponseError(error_str string) ResponseError {
|
||||
return ResponseError{
|
||||
Error: error_str,
|
||||
}
|
||||
}
|
||||
|
||||
type POSTGroup struct {
|
||||
Groupname string `json:"groupname"`
|
||||
Permissions map[string]string `json:"permissions"`
|
||||
}
|
||||
|
||||
func EncodeJSONResponse(response Response) (string, error) {
|
||||
var buffer bytes.Buffer
|
||||
encoder := json.NewEncoder(&buffer)
|
||||
err := encoder.Encode(response)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return buffer.String(), nil
|
||||
}
|
217
wwwshop/dao/groupmanager/groupmanager.go
Normal file
217
wwwshop/dao/groupmanager/groupmanager.go
Normal file
@ -0,0 +1,217 @@
|
||||
package groupmanager
|
||||
|
||||
import (
|
||||
"WWWShop/wwwshop/model/group"
|
||||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/lib/pq/hstore"
|
||||
"log"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type GroupManager struct {
|
||||
db *sql.DB
|
||||
}
|
||||
|
||||
func New(db *sql.DB) GroupManager {
|
||||
return GroupManager{db}
|
||||
}
|
||||
|
||||
func (self GroupManager) Add(groupname string, permissions map[string]string) (*group.Group, error) {
|
||||
var id int64
|
||||
if permissions == nil {
|
||||
permissions = make(map[string]string)
|
||||
}
|
||||
permissions_null := hstore.Hstore{
|
||||
Map: make(map[string]sql.NullString),
|
||||
}
|
||||
for key, value := range permissions {
|
||||
permissions_null.Map[key] = sql.NullString{
|
||||
String: value,
|
||||
Valid: true,
|
||||
}
|
||||
}
|
||||
result := self.db.QueryRow("INSERT INTO groups(groupname, permissions) VALUES ($1, $2) RETURNING id", groupname, permissions_null)
|
||||
err := result.Scan(&id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
group := group.New(id, groupname, permissions)
|
||||
return &group, nil
|
||||
}
|
||||
|
||||
type QueryParameter interface{}
|
||||
|
||||
func (self GroupManager) GenerateWhere(cur_key *int64, ids []int64, groupnames []string) string {
|
||||
where_string := "WHERE false "
|
||||
if groupnames != nil && len(groupnames) > 0 {
|
||||
where_string = strings.Join([]string{where_string, "OR ( false"}, "")
|
||||
for range groupnames {
|
||||
where_string = strings.Join([]string{where_string, fmt.Sprintf(" OR groupname = $%d", *cur_key)}, "")
|
||||
(*cur_key)++
|
||||
}
|
||||
where_string = strings.Join([]string{where_string, " ) "}, "")
|
||||
}
|
||||
if ids != nil && len(ids) > 0 {
|
||||
where_string = strings.Join([]string{where_string, "OR ( false"}, "")
|
||||
for range ids {
|
||||
where_string = strings.Join([]string{where_string, fmt.Sprintf(" OR id = $%d", *cur_key)}, "")
|
||||
(*cur_key)++
|
||||
}
|
||||
where_string = strings.Join([]string{where_string, " ) "}, "")
|
||||
}
|
||||
return where_string
|
||||
}
|
||||
|
||||
func (self GroupManager) Update(group group.Group) (*group.Group, error) {
|
||||
if group.Id == nil && group.Groupname == nil {
|
||||
return nil, errors.New("Both Id and Groupname cannot be null on the same time on UPDATE.")
|
||||
}
|
||||
if group.Permissions == nil {
|
||||
return nil, errors.New("Should be at least a field for update .")
|
||||
}
|
||||
query := "UPDATE groups SET permissions = $1 WHERE true "
|
||||
parameters := make([]interface{}, 0)
|
||||
permissions_null := hstore.Hstore{
|
||||
Map: make(map[string]sql.NullString),
|
||||
}
|
||||
for key, value := range group.Permissions {
|
||||
log.Println(value)
|
||||
permissions_null.Map[key] = sql.NullString{
|
||||
String: value,
|
||||
Valid: true,
|
||||
}
|
||||
}
|
||||
parameters = append(parameters, permissions_null)
|
||||
if group.Id != nil {
|
||||
query = strings.Join([]string{query, "AND id = $2 "}, "")
|
||||
parameters = append(parameters, *(group.Id))
|
||||
} else {
|
||||
query = strings.Join([]string{query, "AND groupname = $2 "}, "")
|
||||
|
||||
parameters = append(parameters, *(group.Groupname))
|
||||
}
|
||||
query = strings.Join([]string{query, " RETURNING id"}, "")
|
||||
var id int64
|
||||
result := self.db.QueryRow(query, parameters...)
|
||||
err := result.Scan(&id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
groups, err := self.Retrieve(0, []int64{id}, nil)
|
||||
group = groups[0]
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &group, nil
|
||||
}
|
||||
|
||||
func (self GroupManager) Delete(ids []int64, groupnames []string) ([]string, error) {
|
||||
var where bool
|
||||
var cur_key int64
|
||||
var where_string string
|
||||
cur_key = 1
|
||||
|
||||
if ids != nil && len(ids) > 0 {
|
||||
where = true
|
||||
}
|
||||
if groupnames != nil && len(groupnames) > 0 {
|
||||
where = true
|
||||
}
|
||||
|
||||
if where {
|
||||
where_string = self.GenerateWhere(&cur_key, ids, groupnames)
|
||||
} else {
|
||||
return nil, errors.New("Cannot delete without a clause")
|
||||
}
|
||||
|
||||
query_parameters := make([]interface{}, 0)
|
||||
for _, groupname := range groupnames {
|
||||
query_parameters = append(query_parameters, groupname)
|
||||
}
|
||||
for _, id := range ids {
|
||||
query_parameters = append(query_parameters, id)
|
||||
}
|
||||
query_string := fmt.Sprintf("DELETE FROM groups %s RETURNING groupname", where_string)
|
||||
result, err := self.db.Query(
|
||||
query_string,
|
||||
query_parameters...,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer result.Close()
|
||||
var deleted_groups []string
|
||||
for result.Next() {
|
||||
var groupname string
|
||||
err := result.Scan(&groupname)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
deleted_groups = append(deleted_groups, groupname)
|
||||
}
|
||||
if deleted_groups == nil {
|
||||
deleted_groups = make([]string, 0)
|
||||
}
|
||||
return deleted_groups, nil
|
||||
}
|
||||
|
||||
func (self GroupManager) Retrieve(page int64, ids []int64, groupnames []string) ([]group.Group, error) {
|
||||
var where bool
|
||||
var cur_key int64
|
||||
|
||||
if ids != nil && len(ids) > 0 {
|
||||
where = true
|
||||
}
|
||||
if groupnames != nil && len(groupnames) > 0 {
|
||||
where = true
|
||||
}
|
||||
cur_key = 1
|
||||
where_string := ""
|
||||
if where {
|
||||
where_string = self.GenerateWhere(&cur_key, ids, groupnames)
|
||||
}
|
||||
page = (10 * page)
|
||||
page_string := fmt.Sprintf("LIMIT 10 OFFSET %d", page)
|
||||
query_parameters := make([]interface{}, 0)
|
||||
for _, groupname := range groupnames {
|
||||
query_parameters = append(query_parameters, groupname)
|
||||
}
|
||||
for _, id := range ids {
|
||||
query_parameters = append(query_parameters, id)
|
||||
}
|
||||
query_string := fmt.Sprintf("SELECT id, groupname, permissions from groups %s %s;", where_string, page_string)
|
||||
result, err := self.db.Query(
|
||||
query_string,
|
||||
query_parameters...,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer result.Close()
|
||||
var groups []group.Group
|
||||
for result.Next() {
|
||||
var (
|
||||
id_group int64
|
||||
groupname_group string
|
||||
permissions_group_null hstore.Hstore
|
||||
)
|
||||
err := result.Scan(&id_group, &groupname_group, &permissions_group_null)
|
||||
permissions_group := make(map[string]string)
|
||||
for key, permission_null := range permissions_group_null.Map {
|
||||
if permission_null.Valid {
|
||||
permissions_group[key] = permission_null.String
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
u := group.New(id_group, groupname_group, permissions_group)
|
||||
groups = append(groups, u)
|
||||
}
|
||||
if groups == nil {
|
||||
groups = make([]group.Group, 0)
|
||||
}
|
||||
return groups, nil
|
||||
}
|
33
wwwshop/model/group/group.go
Normal file
33
wwwshop/model/group/group.go
Normal file
@ -0,0 +1,33 @@
|
||||
package group
|
||||
|
||||
import (
|
||||
"log"
|
||||
)
|
||||
|
||||
type Group struct {
|
||||
Id *int64 `json:"id"`
|
||||
Groupname *string `json:"groupname"`
|
||||
Permissions map[string]string `json:"permissions"`
|
||||
}
|
||||
|
||||
func New(id int64, groupname string, permissions map[string]string) Group {
|
||||
return Group{
|
||||
Id: &id,
|
||||
Groupname: &groupname,
|
||||
Permissions: permissions,
|
||||
}
|
||||
}
|
||||
|
||||
func (self Group) HasPermission(permission string) string {
|
||||
perm_value, ok := self.Permissions[permission]
|
||||
if ok {
|
||||
if perm_value == "yes" {
|
||||
return "yes"
|
||||
}
|
||||
if perm_value == "no" {
|
||||
return "no"
|
||||
}
|
||||
log.Printf("Invalid permission value for %s in group %s.\n", permission, self.Groupname)
|
||||
}
|
||||
return ""
|
||||
}
|
@ -4,6 +4,7 @@ import (
|
||||
"net/http"
|
||||
c "WWWShop/wwwshop/controller"
|
||||
u "WWWShop/wwwshop/controller/usercontroller"
|
||||
g "WWWShop/wwwshop/controller/groupcontroller"
|
||||
d "WWWShop/wwwshop/dao/database"
|
||||
)
|
||||
|
||||
@ -18,7 +19,8 @@ func New() WWWShop {
|
||||
func (self WWWShop) Init() {
|
||||
d.Migrate(d.DB())
|
||||
user_controller := c.GenerateController(u.New())
|
||||
group_controller := c.GenerateController(g.New())
|
||||
http.Handle("/group", group_controller)
|
||||
http.Handle("/user", user_controller)
|
||||
http.Handle("/user/", user_controller)
|
||||
http.ListenAndServe(":8080", nil)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user