Skip to content
Merged
23 changes: 13 additions & 10 deletions api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,22 @@ package api
import (
"net/http"

libcommon "github.com/String-xyz/go-lib/common"
"github.com/String-xyz/go-lib/database"
libmiddleware "github.com/String-xyz/go-lib/middleware"
"github.com/String-xyz/go-lib/validator"
"github.com/String-xyz/string-api/api/handler"
"github.com/String-xyz/string-api/api/middleware"
"github.com/String-xyz/string-api/api/validator"

"github.com/String-xyz/string-api/pkg/service"
"github.com/String-xyz/string-api/pkg/store"
"github.com/jmoiron/sqlx"
"github.com/labstack/echo/v4"
"github.com/rs/zerolog"
)

type APIConfig struct {
DB *sqlx.DB
Redis store.RedisStore
Redis database.RedisStore
Logger *zerolog.Logger
Port string
}
Expand All @@ -40,7 +43,7 @@ func Start(config APIConfig) {
services := NewServices(config, repos)

// initialize routes - A route group only needs access to the services layer. It should'n access the repos layer directly
AuthAPIKey(services, e, handler.IsLocalEnv())
AuthAPIKey(services, e, libcommon.IsLocalEnv())
transactRoute(services, e)
quoteRoute(services, e)
userRoute(services, e)
Expand All @@ -67,12 +70,12 @@ func StartInternal(config APIConfig) {
}

func baseMiddleware(logger *zerolog.Logger, e *echo.Echo) {
e.Use(middleware.Tracer())
e.Use(middleware.CORS())
e.Use(middleware.RequestId())
e.Use(middleware.Recover())
e.Use(middleware.Logger(logger))
e.Use(middleware.LogRequest())
e.Use(libmiddleware.Tracer())
e.Use(libmiddleware.CORS())
e.Use(libmiddleware.RequestId())
e.Use(libmiddleware.Recover())
e.Use(libmiddleware.Logger(logger))
e.Use(libmiddleware.LogRequest())
}

func platformRoute(services service.Services, e *echo.Echo) {
Expand Down
16 changes: 9 additions & 7 deletions api/handler/auth_key.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package handler
import (
"net/http"

libcommon "github.com/String-xyz/go-lib/common"
"github.com/String-xyz/go-lib/httperror"
"github.com/String-xyz/string-api/pkg/service"
"github.com/labstack/echo/v4"
"github.com/rs/zerolog"
Expand All @@ -28,15 +30,15 @@ func NewAuthAPIKey(service service.APIKeyStrategy, internal bool) AuthAPIKey {
func (o authAPIKey) Create(c echo.Context) error {
key, err := o.service.Create()
if err != nil {
LogStringError(c, err, "authKey approve: create")
libcommon.LogStringError(c, err, "authKey approve: create")
return echo.NewHTTPError(http.StatusInternalServerError, "Unable to process request")
}
return c.JSON(http.StatusOK, key)
}

func (o authAPIKey) List(c echo.Context) error {
if !o.isInternal {
return NotAllowedError(c)
return httperror.NotAllowedError(c)
}
body := struct {
Status string `query:"status"`
Expand All @@ -45,33 +47,33 @@ func (o authAPIKey) List(c echo.Context) error {
}{}
err := c.Bind(&body)
if err != nil {
LogStringError(c, err, "authKey list: bind")
libcommon.LogStringError(c, err, "authKey list: bind")
return echo.NewHTTPError(http.StatusBadRequest)
}
list, err := o.service.List(body.Limit, body.Offset, body.Status)
if err != nil {
LogStringError(c, err, "authKey list")
libcommon.LogStringError(c, err, "authKey list")
return echo.NewHTTPError(http.StatusInternalServerError, "ApiKey Service Failed")
}
return c.JSON(http.StatusCreated, list)
}

func (o authAPIKey) Approve(c echo.Context) error {
if !o.isInternal {
return NotAllowedError(c)
return httperror.NotAllowedError(c)
}
params := struct {
Id string `param:"id"`
}{}
err := c.Bind(&params)

if err != nil {
LogStringError(c, err, "authKey approve: bind")
libcommon.LogStringError(c, err, "authKey approve: bind")
return echo.NewHTTPError(http.StatusInternalServerError, "Unable to process request")
}
err = o.service.Approve(params.Id)
if err != nil {
LogStringError(c, err, "authKey approve: approve")
libcommon.LogStringError(c, err, "authKey approve: approve")
return echo.NewHTTPError(http.StatusInternalServerError, "Unable to process request")
}
return c.JSON(http.StatusOK, ResultMessage{Status: "Success"})
Expand Down
57 changes: 8 additions & 49 deletions api/handler/common.go
Original file line number Diff line number Diff line change
@@ -1,64 +1,27 @@
package handler

import (
"fmt"
"net/http"
"os"
"regexp"
"strings"
"time"

libcommon "github.com/String-xyz/go-lib/common"
service "github.com/String-xyz/string-api/pkg/service"
"golang.org/x/crypto/sha3"
"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer"

"github.com/labstack/echo/v4"
"github.com/pkg/errors"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
)

func LogError(c echo.Context, err error, handlerMsg string) {
lg := c.Get("logger").(*zerolog.Logger)
sp, _ := tracer.SpanFromContext(c.Request().Context())
lg.Error().Stack().Err(err).Uint64("trace_id", sp.Context().TraceID()).
Uint64("span_id", sp.Context().SpanID()).Msg(handlerMsg)
}

func LogStringError(c echo.Context, err error, handlerMsg string) {
type stackTracer interface {
StackTrace() errors.StackTrace
}

tracer, ok := errors.Cause(err).(stackTracer)
if !ok {
log.Warn().Str("error", err.Error()).Msg("error does not implement stack trace")
return
}

cause := errors.Cause(err)
st := tracer.StackTrace()

if IsLocalEnv() {
st2 := fmt.Sprintf("\nSTACK TRACE:\n%+v: [%+v ]\n\n", cause.Error(), st[0:5])
// delete the string_api docker path from the stack trace
st2 = strings.ReplaceAll(st2, "/string_api/", "")
fmt.Print(st2)
return
}

LogError(c, err, handlerMsg)
}

func SetJWTCookie(c echo.Context, jwt service.JWT) error {
cookie := new(http.Cookie)
cookie.Name = "StringJWT"
cookie.Value = jwt.Token
// cookie.HttpOnly = true // due the short expiration time it is not needed to be http only
cookie.Expires = jwt.ExpAt // we want the cookie to expire at the same time as the token
cookie.SameSite = getCookieSameSiteMode()
cookie.Path = "/" // Send cookie in every sub path request
cookie.Secure = !IsLocalEnv() // in production allow https only
cookie.Path = "/" // Send cookie in every sub path request
cookie.Secure = !libcommon.IsLocalEnv() // in production allow https only
c.SetCookie(cookie)

return nil
Expand All @@ -71,8 +34,8 @@ func SetRefreshTokenCookie(c echo.Context, refresh service.RefreshTokenResponse)
cookie.HttpOnly = true
cookie.Expires = refresh.ExpAt // we want the cookie to expire at the same time as the token
cookie.SameSite = getCookieSameSiteMode()
cookie.Path = "/login/" // Send cookie only in /login path request
cookie.Secure = !IsLocalEnv() // in production allow https only
cookie.Path = "/login/" // Send cookie only in /login path request
cookie.Secure = !libcommon.IsLocalEnv() // in production allow https only
c.SetCookie(cookie)

return nil
Expand Down Expand Up @@ -100,7 +63,7 @@ func DeleteAuthCookies(c echo.Context) error {
cookie.Expires = time.Now()
cookie.SameSite = getCookieSameSiteMode()
cookie.Path = "/" // Send cookie in every sub path request
cookie.Secure = !IsLocalEnv()
cookie.Secure = !libcommon.IsLocalEnv()
c.SetCookie(cookie)

cookie = new(http.Cookie)
Expand All @@ -109,24 +72,20 @@ func DeleteAuthCookies(c echo.Context) error {
cookie.Expires = time.Now()
cookie.SameSite = getCookieSameSiteMode()
cookie.Path = "/login/" // Send cookie only in refresh path request
cookie.Secure = !IsLocalEnv()
cookie.Secure = !libcommon.IsLocalEnv()
c.SetCookie(cookie)

return nil
}

func IsLocalEnv() bool {
return os.Getenv("ENV") == "local"
}

func validAddress(addr string) bool {
re := regexp.MustCompile("^0x[0-9a-fA-F]{40}$")
return re.MatchString(addr)
}

func getCookieSameSiteMode() http.SameSite {
sameSiteMode := http.SameSiteNoneMode // allow cors
if IsLocalEnv() {
if libcommon.IsLocalEnv() {
sameSiteMode = http.SameSiteLaxMode // because SameSiteNoneMode is not allowed in localhost we use lax mode
}
return sameSiteMode
Expand Down
99 changes: 0 additions & 99 deletions api/handler/http_error.go

This file was deleted.

Loading