From 25a1f4f85b0df5683c1f690ced2bd173914adf2e Mon Sep 17 00:00:00 2001 From: Martin Geno Date: Mon, 17 Oct 2016 19:21:17 +0200 Subject: [PATCH] [host] add modify and delete of database and domain --- build.sh | 0 cmd/warehost/main.go | 2 +- modul/host/api.go | 6 +++ modul/host/apidatabase.go | 70 +++++++++++++++++++++++++++++++ modul/host/apidatabase_test.go | 55 ++++++++++++++++++++++++ modul/host/apidomain.go | 76 ++++++++++++++++++++++++++++++++++ modul/host/apidomain_test.go | 71 ++++++++++++++++++++++++++++++- modul/host/models.go | 2 +- 8 files changed, 279 insertions(+), 3 deletions(-) mode change 100644 => 100755 build.sh diff --git a/build.sh b/build.sh old mode 100644 new mode 100755 diff --git a/cmd/warehost/main.go b/cmd/warehost/main.go index e362622..9ca257a 100644 --- a/cmd/warehost/main.go +++ b/cmd/warehost/main.go @@ -91,7 +91,7 @@ func main() { c := cors.New(cors.Options{ AllowedOrigins: []string{config.Data.API.AllowedOrigins}, AllowCredentials: true, - AllowedMethods: []string{"GET", "POST", "PUT", "DELETE"}, + AllowedMethods: []string{"GET", "POST", "PATCH", "DELETE"}, }) handler := c.Handler(router) // Start server diff --git a/modul/host/api.go b/modul/host/api.go index cba9169..bac79dc 100644 --- a/modul/host/api.go +++ b/modul/host/api.go @@ -29,10 +29,16 @@ func BindAPI(db *gorm.DB, router *goji.Mux, prefix string) { router.HandleFuncC(pat.Get(prefix+"/signup"), libapi.SessionHandler(system.LoginHandler(checkSignup))) router.HandleFuncC(pat.Delete(prefix+"/delete"), libapi.SessionHandler(system.LoginHandler(ProfilHandler(delete)))) router.HandleFuncC(pat.Get(prefix+"/profil"), libapi.SessionHandler(system.LoginHandler(ProfilHandler(profil)))) + router.HandleFuncC(pat.Get(prefix+"/domain"), libapi.SessionHandler(system.LoginHandler(ProfilHandler(domainList)))) router.HandleFuncC(pat.Post(prefix+"/domain"), libapi.SessionHandler(system.LoginHandler(ProfilHandler(domainAdd)))) + router.HandleFuncC(pat.Patch(prefix+"/domain/:domainid"), libapi.SessionHandler(system.LoginHandler(ProfilHandler(domainEdit)))) + router.HandleFuncC(pat.Delete(prefix+"/domain/:domainid"), libapi.SessionHandler(system.LoginHandler(ProfilHandler(domainDelete)))) + router.HandleFuncC(pat.Get(prefix+"/database"), libapi.SessionHandler(system.LoginHandler(ProfilHandler(databaseList)))) router.HandleFuncC(pat.Post(prefix+"/database"), libapi.SessionHandler(system.LoginHandler(ProfilHandler(databaseAdd)))) + router.HandleFuncC(pat.Patch(prefix+"/database/:databaseid"), libapi.SessionHandler(system.LoginHandler(ProfilHandler(databaseEdit)))) + router.HandleFuncC(pat.Delete(prefix+"/database/:databaseid"), libapi.SessionHandler(system.LoginHandler(ProfilHandler(databaseDelete)))) } func checkSignup(ctx context.Context, w http.ResponseWriter, r *http.Request) (returndata interface{}, returnerr *libapi.ErrorResult) { diff --git a/modul/host/apidatabase.go b/modul/host/apidatabase.go index 6681986..8dd1ee8 100644 --- a/modul/host/apidatabase.go +++ b/modul/host/apidatabase.go @@ -2,12 +2,31 @@ package host import ( "net/http" + "strconv" + "goji.io/pat" "golang.org/x/net/context" libapi "dev.sum7.eu/sum7/warehost/lib/api" ) +func getDatabase(ctx context.Context, w http.ResponseWriter) (database Database, returnerr *libapi.ErrorResult) { + profil := ctx.Value("profil").(*Profil) + id, err := strconv.ParseInt(pat.Param(ctx, "databaseid"), 10, 64) + if err != nil { + returnerr = &libapi.ErrorResult{ + Message: "Internal Request Error", + } + w.WriteHeader(http.StatusBadRequest) + return + } + dbconnection.Where(map[string]int64{"id": id, "profil": profil.ID}).Find(&database) + if database.ID <= 0 { + returnerr = &libapi.ErrorResult{Fields: []string{"database"}, Message: "not found"} + } + return +} + func databaseList(ctx context.Context, w http.ResponseWriter, r *http.Request) (returndata interface{}, returnerr *libapi.ErrorResult) { profil := ctx.Value("profil").(*Profil) returndata = false @@ -46,3 +65,54 @@ func databaseAdd(ctx context.Context, w http.ResponseWriter, r *http.Request) (r logger.Info("done") return } + +func databaseEdit(ctx context.Context, w http.ResponseWriter, r *http.Request) (returndata interface{}, returnerr *libapi.ErrorResult) { + returndata = false + logger := log.GetLog(r, "databaseedit") + + database, returnerr := getDatabase(ctx, w) + if returnerr != nil { + logger.Info("not found") + return + } + + var databaseRequest Database + returnerr = libapi.JSONDecoder(r.Body, &databaseRequest, w, logger) + if returnerr != nil { + return + } + + database.Password = databaseRequest.Password + database.Comment = databaseRequest.Comment + + if err := dbconnection.Save(database).Error; err != nil { + logger.Error("database: during modify host database: ", err) + w.WriteHeader(http.StatusInternalServerError) + returnerr = &libapi.ErrorResult{Message: "Internal Database Error with Database"} + return + } + returndata = true + logger.Info("done") + return +} + +func databaseDelete(ctx context.Context, w http.ResponseWriter, r *http.Request) (returndata interface{}, returnerr *libapi.ErrorResult) { + returndata = false + logger := log.GetLog(r, "databasedelete") + + databaseRequest, returnerr := getDatabase(ctx, w) + if returnerr != nil { + logger.Info("not found") + return + } + + if err := dbconnection.Unscoped().Delete(databaseRequest).Error; err != nil { + logger.Error("database: during create host database: ", err) + w.WriteHeader(http.StatusInternalServerError) + returnerr = &libapi.ErrorResult{Message: "Internal Database Error with Database"} + return + } + returndata = true + logger.Info("done") + return +} diff --git a/modul/host/apidatabase_test.go b/modul/host/apidatabase_test.go index 7c51d7f..8086b1f 100644 --- a/modul/host/apidatabase_test.go +++ b/modul/host/apidatabase_test.go @@ -2,6 +2,7 @@ package host import ( "net/http" + "strconv" "testing" "dev.sum7.eu/sum7/warehost/system" @@ -56,4 +57,58 @@ func TestAPIDatabase(t *testing.T) { }) assertion.Equal(w.StatusCode, http.StatusOK) assertion.NotEqual(result.Data, false) + + /* + * TEST databaseEdit + */ + result, w = session.JSONRequest("GET", "/host/database", nil) + assertion.Equal(w.StatusCode, http.StatusOK) + assertion.NotEqual(result.Data, false) + var database int + for _, obj := range result.Data.([]interface{}) { + item := obj.(map[string]interface{}) + if item["password"] == "example.de" { + database = int(item["ID"].(float64)) + break + } + } + session.Clean() + + result, w = session.JSONRequest("PATCH", "/host/database/"+strconv.Itoa(database), Database{ + Comment: "test-bug", + }) + assertion.Equal(w.StatusCode, http.StatusUnauthorized) + assertion.Equal(result.Data, false) + + loginTest(session, assertion) + + result, w = session.JSONRequest("PATCH", "/host/database/"+strconv.Itoa(database), Database{ + Comment: "test2", + }) + assertion.Equal(w.StatusCode, http.StatusOK) + assertion.Equal(result.Data, true) + + result, w = session.JSONRequest("PATCH", "/host/database/"+strconv.Itoa(database), []byte{2, 3}) + assertion.Equal(w.StatusCode, http.StatusBadRequest) + assertion.Equal(result.Data, false) + + /* + * TEST databaseDelete + */ + session.Clean() + + result, w = session.JSONRequest("DELETE", "/host/database/"+strconv.Itoa(database), nil) + assertion.Equal(w.StatusCode, http.StatusUnauthorized) + assertion.Equal(result.Data, false) + + loginTest(session, assertion) + + result, w = session.JSONRequest("DELETE", "/host/database/"+strconv.Itoa(database), nil) + assertion.Equal(w.StatusCode, http.StatusOK) + assertion.Equal(result.Data, true) + + result, w = session.JSONRequest("DELETE", "/host/database/"+strconv.Itoa(database), nil) + assertion.Equal(w.StatusCode, http.StatusOK) + assertion.Equal(result.Data, false) + } diff --git a/modul/host/apidomain.go b/modul/host/apidomain.go index 139235b..1ea3161 100644 --- a/modul/host/apidomain.go +++ b/modul/host/apidomain.go @@ -2,12 +2,32 @@ package host import ( "net/http" + "strconv" + "strings" + "goji.io/pat" "golang.org/x/net/context" libapi "dev.sum7.eu/sum7/warehost/lib/api" ) +func getDomain(ctx context.Context, w http.ResponseWriter) (domain Domain, returnerr *libapi.ErrorResult) { + profil := ctx.Value("profil").(*Profil) + id, err := strconv.ParseInt(pat.Param(ctx, "domainid"), 10, 64) + if err != nil { + returnerr = &libapi.ErrorResult{ + Message: "Internal Request Error", + } + w.WriteHeader(http.StatusBadRequest) + return + } + dbconnection.Where(map[string]int64{"id": id, "profil": profil.ID}).Find(&domain) + if domain.ID <= 0 { + returnerr = &libapi.ErrorResult{Fields: []string{"domain"}, Message: "not found"} + } + return +} + func domainList(ctx context.Context, w http.ResponseWriter, r *http.Request) (returndata interface{}, returnerr *libapi.ErrorResult) { profil := ctx.Value("profil").(*Profil) returndata = false @@ -38,6 +58,62 @@ func domainAdd(ctx context.Context, w http.ResponseWriter, r *http.Request) (ret } if err := dbconnection.Create(domain).Error; err != nil { + if strings.Contains(err.Error(), "duplicate key") { + logger.Warning("exists already") + return + } + logger.Error("database: during create host domain: ", err) + w.WriteHeader(http.StatusInternalServerError) + returnerr = &libapi.ErrorResult{Message: "Internal Database Error with Database"} + return + } + returndata = true + logger.Info("done") + return +} + +func domainEdit(ctx context.Context, w http.ResponseWriter, r *http.Request) (returndata interface{}, returnerr *libapi.ErrorResult) { + returndata = false + logger := log.GetLog(r, "domainedit") + + domain, returnerr := getDomain(ctx, w) + if returnerr != nil { + logger.Info("not found") + return + } + + var domainRequest Domain + returnerr = libapi.JSONDecoder(r.Body, &domainRequest, w, logger) + if returnerr != nil { + return + } + + domain.FQDN = domainRequest.FQDN + domain.Mail = domainRequest.Mail + domain.Web = domainRequest.Web + + if err := dbconnection.Save(domain).Error; err != nil { + logger.Error("database: during modify host domain: ", err) + w.WriteHeader(http.StatusInternalServerError) + returnerr = &libapi.ErrorResult{Message: "Internal Database Error with Database"} + return + } + returndata = true + logger.Info("done") + return +} + +func domainDelete(ctx context.Context, w http.ResponseWriter, r *http.Request) (returndata interface{}, returnerr *libapi.ErrorResult) { + returndata = false + logger := log.GetLog(r, "domaindelete") + + domainRequest, returnerr := getDomain(ctx, w) + if returnerr != nil { + logger.Info("not found") + return + } + + if err := dbconnection.Unscoped().Delete(domainRequest).Error; err != nil { logger.Error("database: during create host domain: ", err) w.WriteHeader(http.StatusInternalServerError) returnerr = &libapi.ErrorResult{Message: "Internal Database Error with Database"} diff --git a/modul/host/apidomain_test.go b/modul/host/apidomain_test.go index c7a6c80..d3434b6 100644 --- a/modul/host/apidomain_test.go +++ b/modul/host/apidomain_test.go @@ -2,6 +2,7 @@ package host import ( "net/http" + "strconv" "testing" "dev.sum7.eu/sum7/warehost/system" @@ -50,13 +51,81 @@ func TestAPIDomain(t *testing.T) { /* * TEST domainAdd */ + session.Clean() + result, w = session.JSONRequest("POST", "/host/domain", Domain{ + FQDN: "example.de", + }) + assertion.Equal(w.StatusCode, http.StatusUnauthorized) + assertion.Equal(result.Data, false) + + loginTest(session, assertion) + + result, w = session.JSONRequest("POST", "/host/domain", []byte{2, 3}) + assertion.Equal(w.StatusCode, http.StatusBadRequest) + assertion.Equal(result.Data, false) + result, w = session.JSONRequest("POST", "/host/domain", Domain{ FQDN: "example.de", }) assertion.Equal(w.StatusCode, http.StatusOK) assertion.NotEqual(result.Data, false) - result, w = session.JSONRequest("POST", "/host/domain", []byte{2, 3}) + result, w = session.JSONRequest("POST", "/host/domain", Domain{ + FQDN: "example.de", + }) + assertion.Equal(w.StatusCode, http.StatusOK) + assertion.Equal(result.Data, false) + + /* + * TEST domainEdit + */ + result, w = session.JSONRequest("GET", "/host/domain", nil) + assertion.Equal(w.StatusCode, http.StatusOK) + assertion.NotEqual(result.Data, false) + var domain int + for _, obj := range result.Data.([]interface{}) { + item := obj.(map[string]interface{}) + if item["fqdn"] == "example.de" { + domain = int(item["ID"].(float64)) + break + } + } + session.Clean() + + result, w = session.JSONRequest("PATCH", "/host/domain/"+strconv.Itoa(domain), Domain{ + Mail: true, + }) + assertion.Equal(w.StatusCode, http.StatusUnauthorized) + assertion.Equal(result.Data, false) + + loginTest(session, assertion) + + result, w = session.JSONRequest("PATCH", "/host/domain/"+strconv.Itoa(domain), Domain{ + Mail: true, + }) + assertion.Equal(w.StatusCode, http.StatusOK) + assertion.Equal(result.Data, true) + + result, w = session.JSONRequest("PATCH", "/host/domain/"+strconv.Itoa(domain), []byte{2, 3}) assertion.Equal(w.StatusCode, http.StatusBadRequest) assertion.Equal(result.Data, false) + + /* + * TEST domainDelete + */ + session.Clean() + + result, w = session.JSONRequest("DELETE", "/host/domain/"+strconv.Itoa(domain), nil) + assertion.Equal(w.StatusCode, http.StatusUnauthorized) + assertion.Equal(result.Data, false) + + loginTest(session, assertion) + + result, w = session.JSONRequest("DELETE", "/host/domain/"+strconv.Itoa(domain), nil) + assertion.Equal(w.StatusCode, http.StatusOK) + assertion.Equal(result.Data, true) + + result, w = session.JSONRequest("DELETE", "/host/domain/"+strconv.Itoa(domain), nil) + assertion.Equal(w.StatusCode, http.StatusOK) + assertion.Equal(result.Data, false) } diff --git a/modul/host/models.go b/modul/host/models.go index 988c1b0..de38698 100644 --- a/modul/host/models.go +++ b/modul/host/models.go @@ -18,7 +18,7 @@ func (Profil) TableName() string { return "host_profil" } type Domain struct { ID int64 ProfilID int64 `sql:"type:bigint NOT NULL REFERENCES host_profil(id) ON UPDATE CASCADE ON DELETE CASCADE;column:profil" json:"profil"` - FQDN string `sql:"type:varchar(255);column:fqdn" json:"fqdn"` + FQDN string `sql:"type:varchar(255) NOT NULL UNIQUE;column:fqdn" json:"fqdn"` Code string `sql:"type:varchar(255);column:code" json:"-"` Active bool `sql:"default:false;column:active" json:"active"` Mail bool `sql:"default:false;column:mail" json:"mail"`