From 2fa63db3227ac0bb260380b9017175b5610ba5a0 Mon Sep 17 00:00:00 2001 From: tavo Date: Mon, 16 Sep 2024 13:52:26 -0600 Subject: [PATCH] isolate db var --- Makefile | 3 +- server/db.go | 10 +- server/init.go | 57 -------- server/main.go | 349 ++++++++++++++++++++++++++++--------------------- 4 files changed, 206 insertions(+), 213 deletions(-) delete mode 100644 server/init.go diff --git a/Makefile b/Makefile index 264eab8..c11f8f9 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,6 @@ BIN = builder SRCDIR = server -SRC = ${SRCDIR}/init.go \ - ${SRCDIR}/main.go \ +SRC = ${SRCDIR}/main.go \ ${SRCDIR}/paypal.go \ ${SRCDIR}/db.go \ ${SRCDIR}/auth.go \ diff --git a/server/db.go b/server/db.go index aff85ed..8070a90 100644 --- a/server/db.go +++ b/server/db.go @@ -18,7 +18,7 @@ const ( errDBUpdateSiteAuth = "db.go (sites): Auth" ) -func AvailableSite(folder string) error { +func AvailableSite(db *sql.DB, folder string) error { if len(folder) <= 3 { return fmt.Errorf("folder name must be longer than 3 characters") } @@ -37,7 +37,7 @@ func AvailableSite(folder string) error { return nil } -func RegisterSitePayment( +func RegisterSitePayment(db *sql.DB, capture Capture, directory string, editorData json.RawMessage, ) error { var ( @@ -109,7 +109,7 @@ func RegisterSitePayment( return nil } -func UpdateSite(pkey int, editorData json.RawMessage) error { +func UpdateSite(db *sql.DB, pkey int, editorData json.RawMessage) error { if _, err := db.Exec(` UPDATE sites SET raw = $1 WHERE id = $2 `, editorData, pkey); err != nil { @@ -119,7 +119,7 @@ func UpdateSite(pkey int, editorData json.RawMessage) error { return nil } -func UpdateSiteAuth(folder string, code string) (string, error) { +func UpdateSiteAuth(db *sql.DB, folder string, code string) (string, error) { valid := time.Now().Add(5 * time.Minute) var email string @@ -135,7 +135,7 @@ func UpdateSiteAuth(folder string, code string) (string, error) { return email, nil } -func ValidateSiteAuth(folder string, code string) (int, error) { +func ValidateSiteAuth(db *sql.DB, folder string, code string) (int, error) { var dbCode string var validTime time.Time diff --git a/server/init.go b/server/init.go deleted file mode 100644 index bf35430..0000000 --- a/server/init.go +++ /dev/null @@ -1,57 +0,0 @@ -package main - -import ( - "database/sql" - "os" - - "github.com/joho/godotenv" - _ "github.com/lib/pq" -) - -const ( - msgClosingDBConn = "Msg: init.go: Closing database connection" - msgDBConn = "Msg: init.go: Established database connection" - errDBConn = "Fatal: init.go: Connect to database" - errDBPing = "Fatal: init.go: Ping database" - errClosingDBConn = "Fatal: init.go: Closing database connection" - errMissingCredentials = "Fatal: init.go: Credentials" -) - -var db *sql.DB - -func initialize() { - godotenv.Load() - if os.Getenv("BASE_URL") == "" || - os.Getenv("CLIENT_ID") == "" || - os.Getenv("CLIENT_SECRET") == "" || - os.Getenv("RETURN_URL") == "" || - os.Getenv("CANCEL_URL") == "" || - os.Getenv("PORT") == "" { - fatal(nil, errMissingCredentials) - } - - var err error - db, err = sql.Open("postgres", "host="+os.Getenv("DB_HOST")+ - " port="+os.Getenv("DB_PORT")+ - " user="+os.Getenv("DB_USER")+ - " password="+os.Getenv("DB_PASS")+ - " dbname="+os.Getenv("DB_NAME")) - if err != nil { - fatal(err, errDBConn) - } - - if err := db.Ping(); err != nil { - fatal(err, errDBPing) - } - - msg(msgDBConn) -} - -func shutdown() { - if db != nil { - msg(msgClosingDBConn) - if err := db.Close(); err != nil { - fatal(err, errClosingDBConn) - } - } -} diff --git a/server/main.go b/server/main.go index cfadd69..b6186b9 100644 --- a/server/main.go +++ b/server/main.go @@ -1,6 +1,7 @@ package main import ( + "database/sql" "encoding/json" "log" "net/http" @@ -8,33 +9,68 @@ import ( "os/signal" "strings" "syscall" + + "github.com/joho/godotenv" + _ "github.com/lib/pq" ) const ( - msgServerStart = "Msg: main.go: Starting server" - msgServerShutdown = "Msg: main.go: Server shutdown gracefully" - errServerStart = "Fatal: main.go: Start server" - errReadBody = "Error: main.go: Read request body" - errParseBody = "Error: main.go: Parse request body" - errGetOrderID = "Error: main.go: Get orderID from client URL" - errCaptureOrder = "Error: main.go: Capture order" - errRegisterSite = "Error: main.go: Register site in database" - errEncodeResponse = "Error: main.go: Encode response" - errCreateOrder = "Error: main.go: Obtain orderID" - errAuthGen = "Error: main.go: Gen and register auth" - errAuthEmail = "Error: main.go: Send auth email" - errAuthValidate = "Error: main.go: Validate changes" - errUpdateSite = "Error: main.go: Updating site data" + msgClosingDBConn = "Msg: init.go: Closing database connection" + msgDBConn = "Msg: init.go: Established database connection" + errDBConn = "Fatal: init.go: Connect to database" + errDBPing = "Fatal: init.go: Ping database" + errClosingDBConn = "Fatal: init.go: Closing database connection" + errMissingCredentials = "Fatal: init.go: Credentials" + msgServerStart = "Msg: main.go: Starting server" + msgServerShutdown = "Msg: main.go: Server shutdown gracefully" + errServerStart = "Fatal: main.go: Start server" + errReadBody = "Error: main.go: Read request body" + errParseBody = "Error: main.go: Parse request body" + errGetOrderID = "Error: main.go: Get orderID from client URL" + errCaptureOrder = "Error: main.go: Capture order" + errRegisterSite = "Error: main.go: Register site in database" + errEncodeResponse = "Error: main.go: Encode response" + errCreateOrder = "Error: main.go: Obtain orderID" + errAuthGen = "Error: main.go: Gen and register auth" + errAuthEmail = "Error: main.go: Send auth email" + errAuthValidate = "Error: main.go: Validate changes" + errUpdateSite = "Error: main.go: Updating site data" ) func main() { - initialize() + var db *sql.DB - http.HandleFunc("/api/orders", CreateOrderHandler) - http.HandleFunc("/api/orders/", CaptureOrderHandler) - http.HandleFunc("/api/update", UpdateSiteHandler) - http.HandleFunc("/api/confirm", ConfirmChangesHandler) - http.HandleFunc("/api/directory/", VerifyDirectoryHandler) + godotenv.Load() + if os.Getenv("BASE_URL") == "" || + os.Getenv("CLIENT_ID") == "" || + os.Getenv("CLIENT_SECRET") == "" || + os.Getenv("RETURN_URL") == "" || + os.Getenv("CANCEL_URL") == "" || + os.Getenv("PORT") == "" { + fatal(nil, errMissingCredentials) + } + + var err error + db, err = sql.Open("postgres", "host="+os.Getenv("DB_HOST")+ + " port="+os.Getenv("DB_PORT")+ + " user="+os.Getenv("DB_USER")+ + " password="+os.Getenv("DB_PASS")+ + " dbname="+os.Getenv("DB_NAME")) + if err != nil { + fatal(err, errDBConn) + } + + if err := db.Ping(); err != nil { + fatal(err, errDBPing) + } + + msg(msgDBConn) + + http.HandleFunc("/api/orders", CreateOrderHandler(db)) + http.HandleFunc("/api/orders/", CaptureOrderHandler(db)) + http.HandleFunc("/api/update", UpdateSiteHandler(db)) + http.HandleFunc("/api/confirm", ConfirmChangesHandler(db)) + http.HandleFunc("/api/directory/", VerifyDirectoryHandler(db)) http.Handle("/", http.FileServer(http.Dir("./public"))) stop := make(chan os.Signal, 1) @@ -50,7 +86,12 @@ func main() { <-stop - shutdown() + if db != nil { + msg(msgClosingDBConn) + if err := db.Close(); err != nil { + fatal(err, errClosingDBConn) + } + } msg(msgServerShutdown) } @@ -66,157 +107,167 @@ func httpErrorAndLog(w http.ResponseWriter, } func fatal(err error, notice string) { - shutdown() log.Fatalf("%s: %v", notice, err) } -func CreateOrderHandler(w http.ResponseWriter, r *http.Request) { - var cart struct { - Directory string `json:"directory"` - } - if err := json.NewDecoder(r.Body).Decode(&cart); err != nil { - httpErrorAndLog(w, err, errReadBody, "Error decoding response") +func CreateOrderHandler(db *sql.DB) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var cart struct { + Directory string `json:"directory"` + } + if err := json.NewDecoder(r.Body).Decode(&cart); err != nil { + httpErrorAndLog(w, err, errReadBody, "Error decoding response") + return + } + if err := AvailableSite(db, cart.Directory); err != nil { + http.Error(w, "Site already exists", http.StatusConflict) + log.Printf("%s: %v", "Site already exists", err) + return + } + + orderID, err := CreateOrder() + if err != nil { + httpErrorAndLog(w, err, errCreateOrder, "Error creating order") + return + } + + var response struct { + ID string `json:"id"` + } + response.ID = orderID + + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(response) return } - if err := AvailableSite(cart.Directory) ; err != nil { - http.Error(w, "Site already exists", http.StatusConflict) - log.Printf("%s: %v", "Site already exists", err) - return - } - - orderID, err := CreateOrder() - if err != nil { - httpErrorAndLog(w, err, errCreateOrder, "Error creating order") - return - } - - var response struct { - ID string `json:"id"` - } - response.ID = orderID - - w.Header().Set("Content-Type", "application/json") - json.NewEncoder(w).Encode(response) - return } -func CaptureOrderHandler(w http.ResponseWriter, r *http.Request) { - errClientNotice := "Error capturing order" +func CaptureOrderHandler(db *sql.DB) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + errClientNotice := "Error capturing order" + + var cart struct { + Directory string `json:"directory"` + EditorData json.RawMessage `json:"editor_data"` + } + if err := json.NewDecoder(r.Body).Decode(&cart); err != nil { + httpErrorAndLog(w, err, errReadBody, errClientNotice) + return + } + + path := strings.TrimPrefix(r.URL.Path, "/api/orders/") + parts := strings.Split(path, "/") + orderID := parts[0] + if orderID == "" { + httpErrorAndLog(w, nil, errGetOrderID, errClientNotice) + return + } + + capture, receipt, err := CaptureOrder(orderID) + if err != nil { + httpErrorAndLog(w, err, errCaptureOrder, errClientNotice) + return + } + + if err := RegisterSitePayment(db, capture, cart.Directory, + cart.EditorData); err != nil { + httpErrorAndLog(w, err, errRegisterSite+": "+cart.Directory, errClientNotice) + return + } + + w.Header().Set("Content-Type", "application/json") + if err := json.NewEncoder(w).Encode(receipt); err != nil { + httpErrorAndLog(w, err, errEncodeResponse, errClientNotice) + return + } - var cart struct { - Directory string `json:"directory"` - EditorData json.RawMessage `json:"editor_data"` - } - if err := json.NewDecoder(r.Body).Decode(&cart); err != nil { - httpErrorAndLog(w, err, errReadBody, errClientNotice) return } - - path := strings.TrimPrefix(r.URL.Path, "/api/orders/") - parts := strings.Split(path, "/") - orderID := parts[0] - if orderID == "" { - httpErrorAndLog(w, nil, errGetOrderID, errClientNotice) - return - } - - capture, receipt, err := CaptureOrder(orderID) - if err != nil { - httpErrorAndLog(w, err, errCaptureOrder, errClientNotice) - return - } - - if err := RegisterSitePayment(capture, cart.Directory, cart.EditorData); err != nil { - httpErrorAndLog(w, err, errRegisterSite+": "+cart.Directory, errClientNotice) - return - } - - w.Header().Set("Content-Type", "application/json") - if err := json.NewEncoder(w).Encode(receipt); err != nil { - httpErrorAndLog(w, err, errEncodeResponse, errClientNotice) - return - } - - return } -func UpdateSiteHandler(w http.ResponseWriter, r *http.Request) { - errClientNotice := "Error handling update request" +func UpdateSiteHandler(db *sql.DB) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + errClientNotice := "Error handling update request" + + var cart struct { + Directory string `json:"directory"` + } + if err := json.NewDecoder(r.Body).Decode(&cart); err != nil { + httpErrorAndLog(w, err, errReadBody, errClientNotice) + return + } + + code := GenerateCode() + + email, err := UpdateSiteAuth(db, cart.Directory, code) + if err != nil { + httpErrorAndLog(w, err, errAuthGen, errClientNotice) + return + } + + if err := SendAuthEmail(email, code); err != nil { + httpErrorAndLog(w, err, errAuthEmail, errClientNotice) + return + } - var cart struct { - Directory string `json:"directory"` - } - if err := json.NewDecoder(r.Body).Decode(&cart); err != nil { - httpErrorAndLog(w, err, errReadBody, errClientNotice) return } - - code := GenerateCode() - - email, err := UpdateSiteAuth(cart.Directory, code) - if err != nil { - httpErrorAndLog(w, err, errAuthGen, errClientNotice) - return - } - - if err := SendAuthEmail(email, code); err != nil { - httpErrorAndLog(w, err, errAuthEmail, errClientNotice) - return - } - - return } -func ConfirmChangesHandler(w http.ResponseWriter, r *http.Request) { - errClientNotice := "Error handling confirm changes request" +func ConfirmChangesHandler(db *sql.DB) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + errClientNotice := "Error handling confirm changes request" + + var cart struct { + Directory string `json:"directory"` + Code string `json:"auth_code"` + EditorData json.RawMessage `json:"editor_data"` + } + if err := json.NewDecoder(r.Body).Decode(&cart); err != nil { + httpErrorAndLog(w, err, errReadBody, errClientNotice) + return + } + + pkey, err := ValidateSiteAuth(db, cart.Directory, cart.Code) + if err != nil { + httpErrorAndLog(w, err, errAuthValidate, errClientNotice) + return + } + + if err := UpdateSite(db, pkey, cart.EditorData); err != nil { + httpErrorAndLog(w, err, errUpdateSite, errClientNotice) + return + } - var cart struct { - Directory string `json:"directory"` - Code string `json:"auth_code"` - EditorData json.RawMessage `json:"editor_data"` - } - if err := json.NewDecoder(r.Body).Decode(&cart); err != nil { - httpErrorAndLog(w, err, errReadBody, errClientNotice) return } - - pkey, err := ValidateSiteAuth(cart.Directory, cart.Code) - if err != nil { - httpErrorAndLog(w, err, errAuthValidate, errClientNotice) - return - } - - if err := UpdateSite(pkey, cart.EditorData); err != nil { - httpErrorAndLog(w, err, errUpdateSite, errClientNotice) - return - } - - return } -func VerifyDirectoryHandler(w http.ResponseWriter, r *http.Request) { - errClientNotice := "Error verifying directory against db" +func VerifyDirectoryHandler(db *sql.DB) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + errClientNotice := "Error verifying directory against db" - path := strings.TrimPrefix(r.URL.Path, "/api/directory/") - parts := strings.Split(path, "/") - folder := parts[0] - if folder == "" { - httpErrorAndLog(w, nil, "Error getting directory", errClientNotice) + path := strings.TrimPrefix(r.URL.Path, "/api/directory/") + parts := strings.Split(path, "/") + folder := parts[0] + if folder == "" { + httpErrorAndLog(w, nil, "Error getting directory", errClientNotice) + return + } + + var response struct { + Exists bool `json:"exists"` + } + + err := AvailableSite(db, folder) + if err != nil { + response.Exists = true + } else { + response.Exists = false + } + + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(response) return } - - var response struct { - Exists bool `json:"exists"` - } - - err := AvailableSite(folder) - if err != nil { - response.Exists = true - } else { - response.Exists = false - } - - w.Header().Set("Content-Type", "application/json") - json.NewEncoder(w).Encode(response) - return }