chore: init

This commit is contained in:
DevMiner 2024-08-11 03:51:22 +02:00
commit 320715f3e7
174 changed files with 42083 additions and 0 deletions

View file

@ -0,0 +1,90 @@
package val_impls
import (
"errors"
"github.com/lysand-org/versia-go/internal/validators"
"reflect"
"strings"
"github.com/go-logr/logr"
en_locale "github.com/go-playground/locales/en"
universal_translator "github.com/go-playground/universal-translator"
"github.com/go-playground/validator/v10"
en_translations "github.com/go-playground/validator/v10/translations/en"
"github.com/lysand-org/versia-go/ent/schema"
"github.com/lysand-org/versia-go/internal/api_schema"
)
var _ validators.BodyValidator = (*BodyValidatorImpl)(nil)
type BodyValidatorImpl struct {
validator *validator.Validate
translator *universal_translator.UniversalTranslator
enTranslator universal_translator.Translator
log logr.Logger
}
func NewBodyValidator(log logr.Logger) *BodyValidatorImpl {
en := en_locale.New()
translator := universal_translator.New(en, en)
trans, ok := translator.GetTranslator("en")
if !ok {
panic("failed to get \"en\" translator")
}
validate := validator.New(validator.WithRequiredStructEnabled())
if err := en_translations.RegisterDefaultTranslations(validate, trans); err != nil {
panic("failed to register default translations")
}
validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
if name == "-" {
return ""
}
return name
})
if err := validate.RegisterValidation("username_regex", func(fl validator.FieldLevel) bool {
return schema.ValidateUsername(fl.Field().String()) == nil
}); err != nil {
panic("failed to register username_regex validator")
}
if err := validate.RegisterTranslation("username_regex", trans, func(ut universal_translator.Translator) error {
return trans.Add("user_regex", "{0} must match '^[a-z0-9_-]+$'!", true)
}, func(ut universal_translator.Translator, fe validator.FieldError) string {
t, _ := ut.T("user_regex", fe.Field())
return t
}); err != nil {
panic("failed to register user_regex translation")
}
return &BodyValidatorImpl{
validator: validate,
translator: translator,
enTranslator: trans,
}
}
func (i BodyValidatorImpl) Validate(v any) error {
err := i.validator.Struct(v)
if err == nil {
return nil
}
var invalidValidationError *validator.InvalidValidationError
if errors.As(err, &invalidValidationError) {
panic(invalidValidationError)
}
i.log.Error(err, "Failed to validate object")
errs := make([]string, 0)
for _, err := range err.(validator.ValidationErrors) {
errs = append(errs, err.Translate(i.enTranslator))
}
return api_schema.ErrBadRequest(map[string]any{"validation": errs})
}

View file

@ -0,0 +1,109 @@
package val_impls
import (
"bytes"
"context"
"errors"
"git.devminer.xyz/devminer/unitel"
"github.com/go-logr/logr"
"github.com/gofiber/fiber/v2"
"github.com/lysand-org/versia-go/internal/repository"
"github.com/lysand-org/versia-go/internal/validators"
"github.com/lysand-org/versia-go/pkg/lysand"
"github.com/valyala/fasthttp/fasthttpadaptor"
"io"
"net/http"
)
var (
ErrInvalidSignature = errors.New("invalid signature")
_ validators.RequestValidator = (*RequestValidatorImpl)(nil)
)
type RequestValidatorImpl struct {
repositories repository.Manager
telemetry *unitel.Telemetry
log logr.Logger
}
func NewRequestValidator(repositories repository.Manager, telemetry *unitel.Telemetry, log logr.Logger) *RequestValidatorImpl {
return &RequestValidatorImpl{
repositories: repositories,
telemetry: telemetry,
log: log,
}
}
func (i RequestValidatorImpl) Validate(ctx context.Context, r *http.Request) error {
s := i.telemetry.StartSpan(ctx, "function", "validator/val_impls.RequestValidatorImpl.Validate")
defer s.End()
ctx = s.Context()
r = r.WithContext(ctx)
date, sigHeader, err := lysand.ExtractFederationHeaders(r.Header)
if err != nil {
return err
}
// TODO: Fetch user from database instead of using the URI
user, err := i.repositories.Users().Resolve(ctx, lysand.URLFromStd(sigHeader.KeyID))
if err != nil {
return err
}
body, err := copyBody(r)
if err != nil {
return err
}
if !(lysand.Verifier{PublicKey: user.PublicKey}).Verify(r.Method, date, r.Host, r.URL.Path, body, sigHeader) {
i.log.Info("signature verification failed", "user", user.URI, "ur", r.URL.Path)
s.CaptureError(ErrInvalidSignature)
return ErrInvalidSignature
} else {
i.log.V(2).Info("signature verification succeeded", "user", user.URI, "ur", r.URL.Path)
}
return nil
}
func (i RequestValidatorImpl) ValidateFiberCtx(ctx context.Context, c *fiber.Ctx) error {
s := i.telemetry.StartSpan(ctx, "function", "validator/val_impls.RequestValidatorImpl.ValidateFiberCtx")
defer s.End()
ctx = s.Context()
r, err := convertToStdRequest(c)
if err != nil {
return err
}
return i.Validate(ctx, r)
}
func convertToStdRequest(c *fiber.Ctx) (*http.Request, error) {
stdReq := &http.Request{}
if err := fasthttpadaptor.ConvertRequest(c.Context(), stdReq, true); err != nil {
return nil, err
}
return stdReq, nil
}
func copyBody(req *http.Request) ([]byte, error) {
body, err := io.ReadAll(req.Body)
if err != nil {
return nil, err
}
if err := req.Body.Close(); err != nil {
return nil, err
}
req.Body = io.NopCloser(bytes.NewBuffer(body))
return body, nil
}