179 lines
4.2 KiB
Go
179 lines
4.2 KiB
Go
package server
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"html/template"
|
|
"net/http"
|
|
"path"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/angelbeltran/templater"
|
|
"github.com/gin-gonic/gin"
|
|
|
|
"ruben/inventory2/internal/domains/accounts"
|
|
"ruben/inventory2/internal/domains/authentication"
|
|
etsy_platform "ruben/inventory2/internal/domains/platforms/etsy"
|
|
"ruben/inventory2/internal/domains/raw_events"
|
|
"ruben/inventory2/internal/logging"
|
|
accounts_api "ruben/inventory2/internal/server/api/accounts"
|
|
auth_api "ruben/inventory2/internal/server/api/auth"
|
|
templates_api "ruben/inventory2/internal/server/api/templates"
|
|
"ruben/inventory2/internal/server/api/webhooks"
|
|
etsy_webhooks "ruben/inventory2/internal/server/api/webhooks/etsy"
|
|
"ruben/inventory2/internal/server/middleware"
|
|
)
|
|
|
|
// r gin.IRouter, // TODO: use this everywhere
|
|
|
|
func Router(
|
|
ctx context.Context,
|
|
logger *logging.Logger,
|
|
contentDir string,
|
|
rawEvents *raw_events.Store,
|
|
accts *accounts.Store,
|
|
etsy *etsy_platform.Platform,
|
|
auth *authentication.Authenticator,
|
|
) *gin.Engine {
|
|
r := gin.Default()
|
|
|
|
// TODO: shouldn't this ACTUALLY be a middleware?
|
|
// - only try to make this an actual middleware AFTER all the routers are broken out, so that way how the middleware is supposed to work can be known
|
|
authMiddleware := middleware.NewAuth(
|
|
logger.WithGroup("auth-middleware"),
|
|
auth,
|
|
auth_api.NewLoginURL,
|
|
accts,
|
|
)
|
|
|
|
// webpage content
|
|
|
|
// non-html content: scripts, styles, images, etc
|
|
|
|
r.Use(fileServer("/scripts", contentDir+"/scripts", func(c *gin.Context) {
|
|
w := c.Writer
|
|
w.Header().Set("Content-Type", "text/javascript")
|
|
if path.Ext(c.Request.URL.Path) == ".gz" {
|
|
w.Header().Set("Content-Encoding", "gzip")
|
|
}
|
|
}))
|
|
r.Static("/styles", "./styles")
|
|
r.Static("/favicon", "./favicon")
|
|
|
|
// html (must be before the api endpoints, because the webpage middleware has to be installed beforehand
|
|
|
|
r.GET("/", func(c *gin.Context) {
|
|
c.Redirect(http.StatusMovedPermanently, "/ui")
|
|
})
|
|
|
|
// kind of a dumb way to capture routes for webpages
|
|
templates_api.SetupRoutes(
|
|
logger.WithGroup("templates"),
|
|
r.Group("/ui"),
|
|
contentDir,
|
|
templater.NewTemplater(
|
|
contentDir+"/templates",
|
|
func() template.FuncMap {
|
|
return template.FuncMap{
|
|
// params
|
|
"addPathParam": func(k string, v any, args map[string]any) (map[string]any, error) {
|
|
pathParams, ok := args["PathParams"].(map[string]string)
|
|
if !ok {
|
|
return nil, fmt.Errorf("PathParams no set are args: %v", args)
|
|
}
|
|
|
|
pathParams[k] = fmt.Sprint(v)
|
|
|
|
return args, nil
|
|
},
|
|
|
|
// parsing
|
|
"parseInt": func(s string) (int, error) {
|
|
return strconv.Atoi(s)
|
|
},
|
|
"parseInt64": func(s string) (int64, error) {
|
|
return strconv.ParseInt(s, 10, 64)
|
|
},
|
|
"parsePlatform": func(s string) (accounts.Platform, error) {
|
|
return accounts.NewPlatform(s)
|
|
},
|
|
|
|
// arithmetic
|
|
"addInt": func(a, b int) int {
|
|
return a + b
|
|
},
|
|
"subInt": func(a, b int) int {
|
|
return a - b
|
|
},
|
|
"multInt": func(a, b int) int {
|
|
return a * b
|
|
},
|
|
|
|
// json
|
|
"prettyPrintJSON": func(j json.RawMessage) string {
|
|
b, err := json.MarshalIndent(j, " ", "")
|
|
if err != nil {
|
|
return string(j)
|
|
}
|
|
return string(b)
|
|
},
|
|
}
|
|
},
|
|
),
|
|
rawEvents,
|
|
accts,
|
|
etsy,
|
|
authMiddleware,
|
|
)
|
|
|
|
// api endpoints
|
|
|
|
api := r.Group("/api")
|
|
|
|
auth_api.Routes(
|
|
api.Group("/auth"),
|
|
logger.WithGroup("/auth"),
|
|
auth,
|
|
)
|
|
accounts_api.Routes(
|
|
api.Group("/accounts"),
|
|
logger.WithGroup("/accounts"),
|
|
accts,
|
|
authMiddleware,
|
|
)
|
|
|
|
// api webhooks (TODO: make a router for these)
|
|
|
|
webhooks.Webhooks(
|
|
api.Group("/webhooks"),
|
|
logger.WithGroup("webhooks"),
|
|
rawEvents,
|
|
etsy,
|
|
webhooks.Config{
|
|
Etsy: etsy_webhooks.Config{
|
|
OAuthRedirectURIWithAcctIDParam: "/oauth/account/{acctID}/auth_code",
|
|
},
|
|
},
|
|
)
|
|
|
|
return r
|
|
}
|
|
|
|
func fileServer(urlPrefix, dir string, beforeServe func(c *gin.Context)) gin.HandlerFunc {
|
|
scfs := http.StripPrefix(urlPrefix, http.FileServer(http.Dir(dir)))
|
|
return func(c *gin.Context) {
|
|
r := c.Request
|
|
if r.URL.Path == urlPrefix || strings.HasPrefix(r.URL.Path, path.Join(urlPrefix, "/")) {
|
|
if beforeServe != nil {
|
|
beforeServe(c)
|
|
}
|
|
scfs.ServeHTTP(c.Writer, r)
|
|
c.Abort()
|
|
}
|
|
|
|
// TODO: need a c.Next()?
|
|
}
|
|
}
|