isolate db var

This commit is contained in:
tavo 2024-09-16 13:52:26 -06:00
parent 28b7b1802c
commit 2fa63db322
4 changed files with 206 additions and 213 deletions

View file

@ -1,7 +1,6 @@
BIN = builder BIN = builder
SRCDIR = server SRCDIR = server
SRC = ${SRCDIR}/init.go \ SRC = ${SRCDIR}/main.go \
${SRCDIR}/main.go \
${SRCDIR}/paypal.go \ ${SRCDIR}/paypal.go \
${SRCDIR}/db.go \ ${SRCDIR}/db.go \
${SRCDIR}/auth.go \ ${SRCDIR}/auth.go \

View file

@ -18,7 +18,7 @@ const (
errDBUpdateSiteAuth = "db.go (sites): Auth" errDBUpdateSiteAuth = "db.go (sites): Auth"
) )
func AvailableSite(folder string) error { func AvailableSite(db *sql.DB, folder string) error {
if len(folder) <= 3 { if len(folder) <= 3 {
return fmt.Errorf("folder name must be longer than 3 characters") return fmt.Errorf("folder name must be longer than 3 characters")
} }
@ -37,7 +37,7 @@ func AvailableSite(folder string) error {
return nil return nil
} }
func RegisterSitePayment( func RegisterSitePayment(db *sql.DB,
capture Capture, directory string, editorData json.RawMessage, capture Capture, directory string, editorData json.RawMessage,
) error { ) error {
var ( var (
@ -109,7 +109,7 @@ func RegisterSitePayment(
return nil 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(` if _, err := db.Exec(`
UPDATE sites SET raw = $1 WHERE id = $2 UPDATE sites SET raw = $1 WHERE id = $2
`, editorData, pkey); err != nil { `, editorData, pkey); err != nil {
@ -119,7 +119,7 @@ func UpdateSite(pkey int, editorData json.RawMessage) error {
return nil 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) valid := time.Now().Add(5 * time.Minute)
var email string var email string
@ -135,7 +135,7 @@ func UpdateSiteAuth(folder string, code string) (string, error) {
return email, nil 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 dbCode string
var validTime time.Time var validTime time.Time

View file

@ -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)
}
}
}

View file

@ -1,6 +1,7 @@
package main package main
import ( import (
"database/sql"
"encoding/json" "encoding/json"
"log" "log"
"net/http" "net/http"
@ -8,33 +9,68 @@ import (
"os/signal" "os/signal"
"strings" "strings"
"syscall" "syscall"
"github.com/joho/godotenv"
_ "github.com/lib/pq"
) )
const ( const (
msgServerStart = "Msg: main.go: Starting server" msgClosingDBConn = "Msg: init.go: Closing database connection"
msgServerShutdown = "Msg: main.go: Server shutdown gracefully" msgDBConn = "Msg: init.go: Established database connection"
errServerStart = "Fatal: main.go: Start server" errDBConn = "Fatal: init.go: Connect to database"
errReadBody = "Error: main.go: Read request body" errDBPing = "Fatal: init.go: Ping database"
errParseBody = "Error: main.go: Parse request body" errClosingDBConn = "Fatal: init.go: Closing database connection"
errGetOrderID = "Error: main.go: Get orderID from client URL" errMissingCredentials = "Fatal: init.go: Credentials"
errCaptureOrder = "Error: main.go: Capture order" msgServerStart = "Msg: main.go: Starting server"
errRegisterSite = "Error: main.go: Register site in database" msgServerShutdown = "Msg: main.go: Server shutdown gracefully"
errEncodeResponse = "Error: main.go: Encode response" errServerStart = "Fatal: main.go: Start server"
errCreateOrder = "Error: main.go: Obtain orderID" errReadBody = "Error: main.go: Read request body"
errAuthGen = "Error: main.go: Gen and register auth" errParseBody = "Error: main.go: Parse request body"
errAuthEmail = "Error: main.go: Send auth email" errGetOrderID = "Error: main.go: Get orderID from client URL"
errAuthValidate = "Error: main.go: Validate changes" errCaptureOrder = "Error: main.go: Capture order"
errUpdateSite = "Error: main.go: Updating site data" 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() { func main() {
initialize() var db *sql.DB
http.HandleFunc("/api/orders", CreateOrderHandler) godotenv.Load()
http.HandleFunc("/api/orders/", CaptureOrderHandler) if os.Getenv("BASE_URL") == "" ||
http.HandleFunc("/api/update", UpdateSiteHandler) os.Getenv("CLIENT_ID") == "" ||
http.HandleFunc("/api/confirm", ConfirmChangesHandler) os.Getenv("CLIENT_SECRET") == "" ||
http.HandleFunc("/api/directory/", VerifyDirectoryHandler) 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"))) http.Handle("/", http.FileServer(http.Dir("./public")))
stop := make(chan os.Signal, 1) stop := make(chan os.Signal, 1)
@ -50,7 +86,12 @@ func main() {
<-stop <-stop
shutdown() if db != nil {
msg(msgClosingDBConn)
if err := db.Close(); err != nil {
fatal(err, errClosingDBConn)
}
}
msg(msgServerShutdown) msg(msgServerShutdown)
} }
@ -66,157 +107,167 @@ func httpErrorAndLog(w http.ResponseWriter,
} }
func fatal(err error, notice string) { func fatal(err error, notice string) {
shutdown()
log.Fatalf("%s: %v", notice, err) log.Fatalf("%s: %v", notice, err)
} }
func CreateOrderHandler(w http.ResponseWriter, r *http.Request) { func CreateOrderHandler(db *sql.DB) http.HandlerFunc {
var cart struct { return func(w http.ResponseWriter, r *http.Request) {
Directory string `json:"directory"` var cart struct {
} Directory string `json:"directory"`
if err := json.NewDecoder(r.Body).Decode(&cart); err != nil { }
httpErrorAndLog(w, err, errReadBody, "Error decoding response") 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 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) { func CaptureOrderHandler(db *sql.DB) http.HandlerFunc {
errClientNotice := "Error capturing order" 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 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) { func UpdateSiteHandler(db *sql.DB) http.HandlerFunc {
errClientNotice := "Error handling update request" 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 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) { func ConfirmChangesHandler(db *sql.DB) http.HandlerFunc {
errClientNotice := "Error handling confirm changes request" 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 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) { func VerifyDirectoryHandler(db *sql.DB) http.HandlerFunc {
errClientNotice := "Error verifying directory against db" return func(w http.ResponseWriter, r *http.Request) {
errClientNotice := "Error verifying directory against db"
path := strings.TrimPrefix(r.URL.Path, "/api/directory/") path := strings.TrimPrefix(r.URL.Path, "/api/directory/")
parts := strings.Split(path, "/") parts := strings.Split(path, "/")
folder := parts[0] folder := parts[0]
if folder == "" { if folder == "" {
httpErrorAndLog(w, nil, "Error getting directory", errClientNotice) 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 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
} }