installed gin
This commit is contained in:
@@ -9,44 +9,41 @@ import (
|
||||
"ruben/inventory2/internal/logging"
|
||||
"ruben/inventory2/internal/server/middleware"
|
||||
"ruben/inventory2/internal/server/response"
|
||||
"ruben/inventory2/internal/server/router"
|
||||
"strconv"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type accountSubrouter struct {
|
||||
log *logging.Logger
|
||||
*router.SubMux
|
||||
log *logging.Logger
|
||||
accts *accounts.Store
|
||||
}
|
||||
|
||||
func NewAccountSubrouter(
|
||||
func Routes(
|
||||
r *gin.RouterGroup,
|
||||
logger *logging.Logger,
|
||||
accts *accounts.Store,
|
||||
authMiddleware *middleware.Auth,
|
||||
) *accountSubrouter {
|
||||
mux := router.NewSubMux(logger)
|
||||
|
||||
) {
|
||||
as := &accountSubrouter{
|
||||
log: logger,
|
||||
SubMux: mux,
|
||||
accts: accts,
|
||||
log: logger,
|
||||
accts: accts,
|
||||
}
|
||||
|
||||
withAuth := func(fn response.HandlerFunc) response.HandlerFunc {
|
||||
return authMiddleware.AuthenticateAndAddIdentity(fn)
|
||||
withAuth := func(fn response.HandlerFunc) gin.HandlerFunc {
|
||||
return response.Handler(authMiddleware.AuthenticateAndAddIdentity(fn))
|
||||
}
|
||||
|
||||
mux.Handle("POST /{acctID}/inventory/sync-groups/draft/listings", withAuth(as.createSyncGroupListingDraft))
|
||||
mux.Handle("PUT /{acctID}/inventory/sync-groups/draft/listings/{orderIndex}/shop", withAuth(as.setShopInSyncGroupListingDraft))
|
||||
mux.Handle("PUT /{acctID}/inventory/sync-groups/draft/listings/{orderIndex}/listing", withAuth(as.setListingInSyncGroupListingDraft))
|
||||
mux.Handle("DELETE /{acctID}/inventory/sync-groups/draft/listings/{orderIndex}", withAuth(as.deleteSyncGroupListingDraft))
|
||||
mux.Handle("POST /{acctID}/inventory/sync-groups", withAuth(as.saveNewSyncGroup))
|
||||
|
||||
return as
|
||||
r.POST("/:acctID/inventory/sync-groups/draft/listings", withAuth(as.createSyncGroupListingDraft))
|
||||
r.PUT("/:acctID/inventory/sync-groups/draft/listings/:orderIndex/shop", withAuth(as.setShopInSyncGroupListingDraft))
|
||||
r.PUT("/:acctID/inventory/sync-groups/draft/listings/:orderIndex/listing", withAuth(as.setListingInSyncGroupListingDraft))
|
||||
r.DELETE("/:acctID/inventory/sync-groups/draft/listings/:orderIndex", withAuth(as.deleteSyncGroupListingDraft))
|
||||
r.POST("/:acctID/inventory/sync-groups", withAuth(as.saveNewSyncGroup))
|
||||
}
|
||||
|
||||
// POST /accounts
|
||||
func (s *accountSubrouter) createAccount(r *http.Request) (response.Response, error) {
|
||||
// POST /api/accounts
|
||||
func (s *accountSubrouter) createAccount(c *gin.Context) (response.Response, error) {
|
||||
r := c.Request
|
||||
ctx := r.Context()
|
||||
email := r.FormValue("email")
|
||||
if email == "" {
|
||||
@@ -64,11 +61,12 @@ func (s *accountSubrouter) createAccount(r *http.Request) (response.Response, er
|
||||
return nil, response.Errorf("failed to create account: %w", err)
|
||||
}
|
||||
|
||||
return response.SeeOther(fmt.Sprintf("/accounts/%d", acct.AccountID)), nil
|
||||
return response.SeeOther(fmt.Sprintf("/api/accounts/%d", acct.AccountID)), nil
|
||||
}
|
||||
|
||||
// POST /accounts/{acctID}/inventory/sync-groups/draft/listings
|
||||
func (s *accountSubrouter) createSyncGroupListingDraft(r *http.Request) (response.Response, error) {
|
||||
// POST /api/accounts/{acctID}/inventory/sync-groups/draft/listings
|
||||
func (s *accountSubrouter) createSyncGroupListingDraft(c *gin.Context) (response.Response, error) {
|
||||
r := c.Request
|
||||
ctx := r.Context()
|
||||
acctID := middleware.GetIdentity(ctx).Account.AccountID
|
||||
|
||||
@@ -79,18 +77,19 @@ func (s *accountSubrouter) createSyncGroupListingDraft(r *http.Request) (respons
|
||||
|
||||
return response.Redirect(
|
||||
http.StatusSeeOther,
|
||||
fmt.Sprintf("/accounts/%d/inventory/sync-groups/draft/listings/%d", acctID, orderIndex),
|
||||
fmt.Sprintf("/ui/accounts/%d/inventory/sync-groups/draft/listings/%d", acctID, orderIndex),
|
||||
), nil
|
||||
}
|
||||
|
||||
// PUT /accounts/{acctID}/inventory/sync-groups/draft/listings/{orderIndex}/shop
|
||||
// PUT /api/accounts/{acctID}/inventory/sync-groups/draft/listings/{orderIndex}/shop
|
||||
// @platform string
|
||||
// @shopID string
|
||||
func (s *accountSubrouter) setShopInSyncGroupListingDraft(r *http.Request) (response.Response, error) {
|
||||
func (s *accountSubrouter) setShopInSyncGroupListingDraft(c *gin.Context) (response.Response, error) {
|
||||
r := c.Request
|
||||
ctx := r.Context()
|
||||
acctID := middleware.GetIdentity(ctx).Account.AccountID
|
||||
|
||||
orderIndex, err := getOrderIndexForSyncGroupListingDraftFromPath(r)
|
||||
orderIndex, err := getOrderIndexForSyncGroupListingDraftFromPath(c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -114,16 +113,17 @@ func (s *accountSubrouter) setShopInSyncGroupListingDraft(r *http.Request) (resp
|
||||
|
||||
return response.Redirect(
|
||||
http.StatusSeeOther,
|
||||
fmt.Sprintf("/accounts/%d/inventory/sync-groups/draft/listings/%d", acctID, orderIndex),
|
||||
fmt.Sprintf("/ui/accounts/%d/inventory/sync-groups/draft/listings/%d", acctID, orderIndex),
|
||||
), nil
|
||||
}
|
||||
|
||||
// PUT /accounts/{acctID}/inventory/sync-groups/draft/listings/{orderIndex}/listing
|
||||
func (s *accountSubrouter) setListingInSyncGroupListingDraft(r *http.Request) (response.Response, error) {
|
||||
// PUT /api/accounts/{acctID}/inventory/sync-groups/draft/listings/{orderIndex}/listing
|
||||
func (s *accountSubrouter) setListingInSyncGroupListingDraft(c *gin.Context) (response.Response, error) {
|
||||
r := c.Request
|
||||
ctx := r.Context()
|
||||
acctID := middleware.GetIdentity(ctx).Account.AccountID
|
||||
|
||||
orderIndex, err := getOrderIndexForSyncGroupListingDraftFromPath(r)
|
||||
orderIndex, err := getOrderIndexForSyncGroupListingDraftFromPath(c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -140,16 +140,17 @@ func (s *accountSubrouter) setListingInSyncGroupListingDraft(r *http.Request) (r
|
||||
|
||||
return response.Redirect(
|
||||
http.StatusSeeOther,
|
||||
fmt.Sprintf("/accounts/%d/inventory/sync-groups/draft/listings/%d", acctID, orderIndex),
|
||||
fmt.Sprintf("/ui/accounts/%d/inventory/sync-groups/draft/listings/%d", acctID, orderIndex),
|
||||
), nil
|
||||
}
|
||||
|
||||
// DELETE /accounts/{acctID}/inventory/sync-groups/draft/listings/{orderIndex}
|
||||
func (s *accountSubrouter) deleteSyncGroupListingDraft(r *http.Request) (response.Response, error) {
|
||||
// DELETE /api/accounts/{acctID}/inventory/sync-groups/draft/listings/{orderIndex}
|
||||
func (s *accountSubrouter) deleteSyncGroupListingDraft(c *gin.Context) (response.Response, error) {
|
||||
r := c.Request
|
||||
ctx := r.Context()
|
||||
acctID := middleware.GetIdentity(ctx).Account.AccountID
|
||||
|
||||
orderIndex, err := getOrderIndexForSyncGroupListingDraftFromPath(r)
|
||||
orderIndex, err := getOrderIndexForSyncGroupListingDraftFromPath(c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -161,8 +162,9 @@ func (s *accountSubrouter) deleteSyncGroupListingDraft(r *http.Request) (respons
|
||||
return response.Status(200), nil
|
||||
}
|
||||
|
||||
// POST /accounts/{acctID}/inventory/sync-groups
|
||||
func (s *accountSubrouter) saveNewSyncGroup(r *http.Request) (response.Response, error) {
|
||||
// POST /api/accounts/{acctID}/inventory/sync-groups
|
||||
func (s *accountSubrouter) saveNewSyncGroup(c *gin.Context) (response.Response, error) {
|
||||
r := c.Request
|
||||
ctx := r.Context()
|
||||
acctID := middleware.GetIdentity(ctx).Account.AccountID
|
||||
|
||||
@@ -174,12 +176,12 @@ func (s *accountSubrouter) saveNewSyncGroup(r *http.Request) (response.Response,
|
||||
return response.Redirect(
|
||||
http.StatusSeeOther,
|
||||
// TODO: template not implemented
|
||||
fmt.Sprintf("/accounts/%d/inventory/sync-groups/%d", acctID, grp.SyncGroupID),
|
||||
fmt.Sprintf("/ui/accounts/%d/inventory/sync-groups/%d", acctID, grp.SyncGroupID),
|
||||
), nil
|
||||
}
|
||||
|
||||
func getOrderIndexForSyncGroupListingDraftFromPath(r *http.Request) (int, error) {
|
||||
orderIndexStr := r.PathValue("orderIndex")
|
||||
func getOrderIndexForSyncGroupListingDraftFromPath(c *gin.Context) (int, error) {
|
||||
orderIndexStr := c.Param("orderIndex")
|
||||
if orderIndexStr == "" {
|
||||
return 0, response.NotFound().
|
||||
Msg("no orderIndex found")
|
||||
|
||||
@@ -3,53 +3,36 @@ package auth
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"ruben/inventory2/internal/domains/authentication"
|
||||
"ruben/inventory2/internal/logging"
|
||||
"ruben/inventory2/internal/server/cookies"
|
||||
"ruben/inventory2/internal/server/response"
|
||||
"ruben/inventory2/internal/server/router"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type loginSubrouter struct {
|
||||
log *logging.Logger
|
||||
auth *authentication.Authenticator
|
||||
router.Subrouter
|
||||
}
|
||||
|
||||
func NewLoginSubrouter(logger *logging.Logger, auth *authentication.Authenticator) *loginSubrouter {
|
||||
mux := router.NewSubMux(logger)
|
||||
|
||||
func Routes(
|
||||
r *gin.RouterGroup,
|
||||
logger *logging.Logger,
|
||||
auth *authentication.Authenticator,
|
||||
) {
|
||||
ls := &loginSubrouter{
|
||||
log: logger,
|
||||
auth: auth,
|
||||
Subrouter: mux,
|
||||
log: logger,
|
||||
auth: auth,
|
||||
}
|
||||
|
||||
mux.Handle("GET /login", ls.loginPage)
|
||||
mux.Handle("GET /login/callback", ls.loginCallback)
|
||||
mux.Handle("GET /logout", ls.logoutPage)
|
||||
|
||||
return ls
|
||||
r.GET("/login", response.Handler(ls.loginPage))
|
||||
r.GET("/login/callback", response.Handler(ls.loginCallback))
|
||||
r.GET("/logout", response.Handler(ls.logoutPage))
|
||||
}
|
||||
|
||||
func (s *loginSubrouter) newLoginSubrouter(logger *logging.Logger) router.Subrouter {
|
||||
mux := router.NewSubMux(logger)
|
||||
|
||||
ls := &loginSubrouter{
|
||||
log: s.log,
|
||||
auth: s.auth,
|
||||
Subrouter: mux,
|
||||
}
|
||||
|
||||
mux.Handle("GET /login", ls.loginPage)
|
||||
mux.Handle("GET /login/callback", ls.loginCallback)
|
||||
mux.Handle("GET /logout", ls.logoutPage)
|
||||
|
||||
return ls
|
||||
}
|
||||
|
||||
func (s *loginSubrouter) loginPage(r *http.Request) (response.Response, error) {
|
||||
func (s *loginSubrouter) loginPage(c *gin.Context) (response.Response, error) {
|
||||
r := c.Request
|
||||
ctx := r.Context()
|
||||
|
||||
u, err := NewLoginURL(ctx, s.auth, "/")
|
||||
@@ -71,7 +54,8 @@ func NewLoginURL(ctx context.Context, auth *authentication.Authenticator, target
|
||||
return auth.AuthCodeURL(base64EncodedState), nil
|
||||
}
|
||||
|
||||
func (s *loginSubrouter) loginCallback(r *http.Request) (response.Response, error) {
|
||||
func (s *loginSubrouter) loginCallback(c *gin.Context) (response.Response, error) {
|
||||
r := c.Request
|
||||
ctx := r.Context()
|
||||
q := r.URL.Query()
|
||||
|
||||
@@ -90,7 +74,9 @@ func (s *loginSubrouter) loginCallback(r *http.Request) (response.Response, erro
|
||||
Cookie(cookies.AccessToken(accessToken, expiration)), nil
|
||||
}
|
||||
|
||||
func (s *loginSubrouter) logoutPage(r *http.Request) (response.Response, error) {
|
||||
func (s *loginSubrouter) logoutPage(c *gin.Context) (response.Response, error) {
|
||||
r := c.Request
|
||||
|
||||
host := r.Header.Get("X-Forwarded-Host")
|
||||
if host == "" {
|
||||
host = r.Host
|
||||
|
||||
@@ -17,55 +17,74 @@ import (
|
||||
"ruben/inventory2/internal/logging"
|
||||
"ruben/inventory2/internal/server/middleware"
|
||||
"ruben/inventory2/internal/server/response"
|
||||
"ruben/inventory2/internal/server/router"
|
||||
|
||||
"github.com/angelbeltran/templater"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type webpageRouter struct {
|
||||
log *logging.Logger
|
||||
contentDir string
|
||||
templater *templater.Templater
|
||||
rawEvents *raw_events.Store
|
||||
accts *accounts.Store
|
||||
etsy *etsy_platform.Platform
|
||||
router.Subrouter
|
||||
}
|
||||
type (
|
||||
webpageRouter struct {
|
||||
log *logging.Logger
|
||||
contentDir string
|
||||
templater *templater.Templater
|
||||
rawEvents *raw_events.Store
|
||||
accts *accounts.Store
|
||||
etsy *etsy_platform.Platform
|
||||
authMiddleware *middleware.Auth
|
||||
}
|
||||
|
||||
func NewWebpageRouter(
|
||||
// ErrTemplateNotFound is returned if the reason the template failed to compile
|
||||
// is due to the template not being found.
|
||||
ErrTemplateNotFound struct {
|
||||
err error
|
||||
}
|
||||
)
|
||||
|
||||
func SetupRoutes(
|
||||
logger *logging.Logger,
|
||||
r gin.IRouter,
|
||||
contentDir string,
|
||||
tmpl *templater.Templater,
|
||||
rawEvents *raw_events.Store,
|
||||
accts *accounts.Store,
|
||||
etsy *etsy_platform.Platform,
|
||||
authMiddleware *middleware.Auth,
|
||||
) *webpageRouter {
|
||||
mux := router.NewSubMux(logger)
|
||||
|
||||
wr := &webpageRouter{
|
||||
log: logger,
|
||||
contentDir: contentDir,
|
||||
templater: tmpl,
|
||||
rawEvents: rawEvents,
|
||||
accts: accts,
|
||||
etsy: etsy,
|
||||
Subrouter: mux,
|
||||
) {
|
||||
s := &webpageRouter{
|
||||
log: logger,
|
||||
contentDir: contentDir,
|
||||
templater: tmpl,
|
||||
rawEvents: rawEvents,
|
||||
accts: accts,
|
||||
etsy: etsy,
|
||||
authMiddleware: authMiddleware,
|
||||
}
|
||||
|
||||
// non-authenticated
|
||||
mux.Handle("GET /{$}", authMiddleware.AddIdentity(wr.serveTemplates))
|
||||
fn2 := s.authMiddleware.AuthenticateAndAddIdentity(s.serveTemplates)
|
||||
|
||||
// authenticated
|
||||
mux.Handle("GET /", authMiddleware.AuthenticateAndAddIdentity(wr.serveTemplates))
|
||||
r.GET("/*rest", response.Handler(func(c *gin.Context) (response.Response, error) {
|
||||
c.Request.URL.Path = c.Request.URL.Path[3:]
|
||||
defer func() {
|
||||
c.Request.URL.Path = "/ui" + c.Request.URL.Path
|
||||
}()
|
||||
|
||||
return wr
|
||||
p := c.Request.URL.Path
|
||||
if p == "/" || p == "" {
|
||||
c, err := s.authMiddleware.AddIdentityToRequest(c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return s.serveTemplates(c)
|
||||
}
|
||||
return fn2(c)
|
||||
}))
|
||||
}
|
||||
|
||||
// GET /
|
||||
// compiles the page template or component template matching the url
|
||||
// func (s *Server) serveTemplates(r *http.Request) (response.Response, error) {
|
||||
func (s *webpageRouter) serveTemplates(r *http.Request) (response.Response, error) {
|
||||
func (s *webpageRouter) serveTemplates(c *gin.Context) (response.Response, error) {
|
||||
r := c.Request
|
||||
name, args := s.getTemplateNameAndArgs(r, s.contentDir+"/templates/component_bodies")
|
||||
|
||||
b, err := s.templater.ExecuteComponentBody(name, args...)
|
||||
@@ -190,7 +209,9 @@ func getMatchingGlobPatternsCapturingFilepathIncludingParametrizedFilepaths(file
|
||||
func (s *webpageRouter) handleTemplateError(err error, templateArgs ...any) (response.Response, error) {
|
||||
if isFileNotFoundError(err) {
|
||||
return nil, response.NotFound().
|
||||
Wrap(err).
|
||||
Wrap(ErrTemplateNotFound{
|
||||
err: err,
|
||||
}).
|
||||
Msg("resource not found")
|
||||
}
|
||||
|
||||
@@ -280,3 +301,14 @@ func authorizeByMatchingAccountID(r *http.Request, acctIDPathPosition int) error
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e ErrTemplateNotFound) Error() string {
|
||||
if e.err != nil {
|
||||
return fmt.Sprintf("template not found: %v", e.err)
|
||||
}
|
||||
return fmt.Sprintf("template not found")
|
||||
}
|
||||
|
||||
func (e ErrTemplateNotFound) Unwrap() error {
|
||||
return e.err
|
||||
}
|
||||
|
||||
@@ -3,58 +3,60 @@ package etsy
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"ruben/inventory2/internal/domains/platforms/etsy"
|
||||
"ruben/inventory2/internal/domains/raw_events"
|
||||
"ruben/inventory2/internal/logging"
|
||||
"ruben/inventory2/internal/server/response"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type (
|
||||
Webhooks struct {
|
||||
log *logging.Logger
|
||||
cfg Config
|
||||
db *raw_events.Store
|
||||
etsy *etsy.Platform
|
||||
}
|
||||
|
||||
Config struct {
|
||||
OAuthRedirectURIWithAcctIDParam string
|
||||
}
|
||||
)
|
||||
|
||||
func NewWebhookHandler(
|
||||
func Webhooks(
|
||||
r *gin.RouterGroup,
|
||||
logger *logging.Logger,
|
||||
db *raw_events.Store,
|
||||
platform *etsy.Platform,
|
||||
cfg Config,
|
||||
) http.Handler {
|
||||
h := Webhooks{
|
||||
) {
|
||||
h := webhooks{
|
||||
log: logger,
|
||||
cfg: cfg,
|
||||
db: db,
|
||||
etsy: platform,
|
||||
}
|
||||
|
||||
mux := http.NewServeMux()
|
||||
r.POST("/test", response.Handler(h.test))
|
||||
|
||||
mux.HandleFunc("POST /test", h.test)
|
||||
r.GET(h.cfg.OAuthRedirectURIWithAcctIDParam, response.Handler(h.redirectURI))
|
||||
|
||||
mux.HandleFunc("GET "+h.cfg.OAuthRedirectURIWithAcctIDParam, h.redirectURI)
|
||||
|
||||
mux.HandleFunc("GET /{acctID}/new-account-link", h.newAccountLink)
|
||||
|
||||
return mux
|
||||
r.GET("/{acctID}/new-account-link", response.Handler(h.newAccountLink))
|
||||
}
|
||||
|
||||
type (
|
||||
webhooks struct {
|
||||
log *logging.Logger
|
||||
cfg Config
|
||||
db *raw_events.Store
|
||||
etsy *etsy.Platform
|
||||
}
|
||||
)
|
||||
|
||||
// POST /test
|
||||
func (h Webhooks) test(w http.ResponseWriter, r *http.Request) {
|
||||
func (h webhooks) test(c *gin.Context) (response.Response, error) {
|
||||
r := c.Request
|
||||
|
||||
var body json.RawMessage
|
||||
if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
|
||||
http.Error(w, "Failed to decode body as json: "+err.Error(), 500)
|
||||
return
|
||||
return nil, response.Errorf("failed to decode body as json: %w", err)
|
||||
}
|
||||
|
||||
ts := time.Now().UTC()
|
||||
@@ -75,21 +77,21 @@ func (h Webhooks) test(w http.ResponseWriter, r *http.Request) {
|
||||
Payload: body,
|
||||
})
|
||||
if err != nil {
|
||||
http.Error(w, "Error occurred saving the body as the event payload: "+err.Error(), 500)
|
||||
return
|
||||
return nil, response.Errorf("error occurred saving the body as the event payload: %w", err)
|
||||
}
|
||||
|
||||
w.WriteHeader(201)
|
||||
return response.Status(201), nil
|
||||
}
|
||||
|
||||
// GET h.cfg.OAuthRedirectURIWithAcctIDParam
|
||||
func (h Webhooks) redirectURI(w http.ResponseWriter, r *http.Request) {
|
||||
func (h webhooks) redirectURI(c *gin.Context) (response.Response, error) {
|
||||
r := c.Request
|
||||
|
||||
// get account id for the request
|
||||
|
||||
acctID, err := strconv.ParseInt(r.PathValue("acctID"), 10, 64)
|
||||
acctID, err := strconv.ParseInt(c.Param("acctID"), 10, 64)
|
||||
if err != nil || acctID <= 0 {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
return
|
||||
return nil, response.NotFound()
|
||||
}
|
||||
|
||||
ctx := r.Context()
|
||||
@@ -113,41 +115,38 @@ func (h Webhooks) redirectURI(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
h.etsy.InvalidateState(ctx, state)
|
||||
|
||||
return
|
||||
return response.Status(200), nil
|
||||
}
|
||||
|
||||
// validate the state to prevent CSRF attacks
|
||||
|
||||
ok, err := h.etsy.HandleNewAuthCode(ctx, acctID, state, q.Get("code"))
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusForbidden)
|
||||
h.log.Error("failed to handle new auth code", "error", err)
|
||||
return
|
||||
return nil, response.Forbidden()
|
||||
}
|
||||
if !ok {
|
||||
w.WriteHeader(http.StatusForbidden)
|
||||
return
|
||||
return nil, response.Forbidden()
|
||||
}
|
||||
|
||||
// redirect to the user's account page
|
||||
|
||||
http.Redirect(w, r, fmt.Sprintf("/accounts/%d", acctID), http.StatusSeeOther)
|
||||
return response.SeeOther(fmt.Sprintf("/accounts/%d", acctID)), nil
|
||||
}
|
||||
|
||||
// GET /{acctID}/new-account-link
|
||||
func (h Webhooks) newAccountLink(w http.ResponseWriter, r *http.Request) {
|
||||
acctIDStr := r.PathValue("acctID")
|
||||
func (h webhooks) newAccountLink(c *gin.Context) (response.Response, error) {
|
||||
r := c.Request
|
||||
acctIDStr := c.Param("acctID")
|
||||
acctID, err := strconv.ParseInt(acctIDStr, 10, 64)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("account %s not found", acctIDStr), http.StatusNotFound)
|
||||
return
|
||||
return nil, response.NotFound().Msgf("account %s not found", acctIDStr)
|
||||
}
|
||||
|
||||
u, err := h.etsy.GenerateConnectionURLForNewAccount(r.Context(), acctID)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("failed to generate url for account %d: %v", acctID, err), http.StatusInternalServerError)
|
||||
return
|
||||
return nil, fmt.Errorf("failed to generate url for account %d: %w", acctID, err)
|
||||
}
|
||||
|
||||
http.Redirect(w, r, u.String(), http.StatusTemporaryRedirect)
|
||||
return response.TemporaryRedirect(u.String()), nil
|
||||
}
|
||||
|
||||
@@ -3,21 +3,26 @@ package tiktok
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"ruben/inventory2/internal/domains/raw_events"
|
||||
"ruben/inventory2/internal/logging"
|
||||
"ruben/inventory2/internal/server/response"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func NewWebhookHandler(logger *logging.Logger, db *raw_events.Store) http.Handler {
|
||||
mux := http.NewServeMux()
|
||||
func Webhooks(
|
||||
r *gin.RouterGroup,
|
||||
logger *logging.Logger,
|
||||
db *raw_events.Store,
|
||||
) {
|
||||
r.POST("/test", response.Handler(func(c *gin.Context) (response.Response, error) {
|
||||
r := c.Request
|
||||
|
||||
mux.HandleFunc("POST /test", func(w http.ResponseWriter, r *http.Request) {
|
||||
var body json.RawMessage
|
||||
if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
|
||||
http.Error(w, "Failed to decode body as json: "+err.Error(), 500)
|
||||
return
|
||||
return nil, fmt.Errorf("failed to decode body as json: %w", err)
|
||||
}
|
||||
|
||||
ts := time.Now().UTC()
|
||||
@@ -30,12 +35,9 @@ func NewWebhookHandler(logger *logging.Logger, db *raw_events.Store) http.Handle
|
||||
Payload: body,
|
||||
})
|
||||
if err != nil {
|
||||
http.Error(w, "Error occurred saving the body as the event payload: "+err.Error(), 500)
|
||||
return
|
||||
return nil, fmt.Errorf("error occurred saving the body as the event payload: %w", err)
|
||||
}
|
||||
|
||||
w.WriteHeader(201)
|
||||
})
|
||||
|
||||
return mux
|
||||
return response.Status(201), nil
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -1,47 +1,42 @@
|
||||
package webhooks
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
etsy_platform "ruben/inventory2/internal/domains/platforms/etsy"
|
||||
"ruben/inventory2/internal/domains/raw_events"
|
||||
"ruben/inventory2/internal/logging"
|
||||
"ruben/inventory2/internal/server/api/webhooks/etsy"
|
||||
"ruben/inventory2/internal/server/api/webhooks/tiktok"
|
||||
"ruben/inventory2/internal/server/api/webhooks/wix"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
Etsy etsy.Config
|
||||
}
|
||||
|
||||
// TODO: just move over to the 'site' package, and then consider renaming the site package to something else?
|
||||
func New(logger *logging.Logger, eventsDB *raw_events.Store, etsyPlatform *etsy_platform.Platform, cfg Config) http.Handler {
|
||||
wh := http.NewServeMux()
|
||||
|
||||
wh.Handle(
|
||||
"/etsy/",
|
||||
http.StripPrefix("/etsy", etsy.NewWebhookHandler(
|
||||
logger.WithGroup("etsy"),
|
||||
eventsDB,
|
||||
etsyPlatform,
|
||||
cfg.Etsy,
|
||||
)),
|
||||
func Webhooks(
|
||||
r *gin.RouterGroup,
|
||||
logger *logging.Logger,
|
||||
eventsDB *raw_events.Store,
|
||||
etsyPlatform *etsy_platform.Platform,
|
||||
cfg Config,
|
||||
) {
|
||||
etsy.Webhooks(
|
||||
r.Group("/etsy"),
|
||||
logger.WithGroup("etsy"),
|
||||
eventsDB,
|
||||
etsyPlatform,
|
||||
cfg.Etsy,
|
||||
)
|
||||
wh.Handle(
|
||||
"/tiktok/",
|
||||
http.StripPrefix("/tiktok", tiktok.NewWebhookHandler(
|
||||
logger.WithGroup("tiktok"),
|
||||
eventsDB,
|
||||
)),
|
||||
tiktok.Webhooks(
|
||||
r.Group("/tiktok"),
|
||||
logger.WithGroup("tiktok"),
|
||||
eventsDB,
|
||||
)
|
||||
wh.Handle(
|
||||
"/wix/",
|
||||
http.StripPrefix("/wix", wix.NewWebhookHandler(
|
||||
logger.WithGroup("wix"),
|
||||
eventsDB,
|
||||
)),
|
||||
wix.Webhooks(
|
||||
r.Group("/wix"),
|
||||
logger.WithGroup("wix"),
|
||||
eventsDB,
|
||||
)
|
||||
|
||||
return wh
|
||||
}
|
||||
|
||||
@@ -3,21 +3,26 @@ package wix
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"ruben/inventory2/internal/domains/raw_events"
|
||||
"ruben/inventory2/internal/logging"
|
||||
"ruben/inventory2/internal/server/response"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func NewWebhookHandler(logger *logging.Logger, db *raw_events.Store) http.Handler {
|
||||
mux := http.NewServeMux()
|
||||
func Webhooks(
|
||||
r *gin.RouterGroup,
|
||||
logger *logging.Logger,
|
||||
db *raw_events.Store,
|
||||
) {
|
||||
r.POST("/test", response.Handler(func(c *gin.Context) (response.Response, error) {
|
||||
r := c.Request
|
||||
|
||||
mux.HandleFunc("POST /test", func(w http.ResponseWriter, r *http.Request) {
|
||||
var body json.RawMessage
|
||||
if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
|
||||
http.Error(w, "Failed to decode body as json: "+err.Error(), 500)
|
||||
return
|
||||
return nil, fmt.Errorf("failed to decode body as json: %w", err)
|
||||
}
|
||||
|
||||
ts := time.Now().UTC()
|
||||
@@ -30,12 +35,9 @@ func NewWebhookHandler(logger *logging.Logger, db *raw_events.Store) http.Handle
|
||||
Payload: body,
|
||||
})
|
||||
if err != nil {
|
||||
http.Error(w, "Error occurred saving the body as the event payload: "+err.Error(), 500)
|
||||
return
|
||||
return nil, fmt.Errorf("error occurred saving the body as the event payload: %w", err)
|
||||
}
|
||||
|
||||
w.WriteHeader(201)
|
||||
})
|
||||
|
||||
return mux
|
||||
return response.Status(201), nil
|
||||
}))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user