Skip to content

Commit

Permalink
Merge pull request #15 from ashbeelghouri/0.5
Browse files Browse the repository at this point in the history
0.4
  • Loading branch information
ashbeelghouri committed Jul 1, 2024
2 parents 30eae26 + afcf322 commit ece319c
Show file tree
Hide file tree
Showing 25 changed files with 1,586 additions and 824 deletions.
141 changes: 9 additions & 132 deletions Basic_test.go
Original file line number Diff line number Diff line change
@@ -1,149 +1,26 @@
package jsonschematics

import (
"encoding/json"
v2 "github.com/ashbeelghouri/jsonschematics/data/v2"
"github.com/ashbeelghouri/jsonschematics/utils"
"log"
"os"
"testing"
"time"
)

func TestForObjData(t *testing.T) {
fnTimeStart := time.Now()
var schema Schematics
err := schema.LoadSchemaFromFile("json/schema.json")
schema.Logging.PrintErrorLogs = true
schema.Logging.PrintDebugLogs = true
func TestV2Validate(t *testing.T) {
schematics, err := v2.LoadJsonSchemaFile("test-data/schema/direct/v2/example-1.json")
if err != nil {
t.Error(err)
}
data, err := GetJson("json/data.json")
content, err := os.ReadFile("test-data/data/direct/v2/example-2.json")
if err != nil {
t.Error(err)
}
start := time.Now()
errs := schema.Validate(data)
log.Printf("[SINGLE OBJ] Validation Time: %v", time.Since(start))
log.Print("[SINGLE OBJ] have single errors: ", errs.HaveSingleError("", ""))
errorsFromValidate, err := json.Marshal(errs)
if err != nil {
log.Fatalf("err: %v", err)
}
log.Println("[SINGLE OBJ] errorsFromValidate: ", string(errorsFromValidate))
start = time.Now()
newData := schema.Operate(data)
log.Printf("[SINGLE OBJ] Operaions Time: %v", time.Since(start))
log.Printf("[SINGLE OBJ] Updated DATA: %v", newData)

log.Printf("[SINGLE OBJ] total time taken: %v", time.Since(fnTimeStart))
log.Println("-------------------------------------------")
}

func TestForArrayData(t *testing.T) {
fnTimeStart := time.Now()
var schema1 Schematics
schema1.Logging.PrintErrorLogs = true
schema1.Logging.PrintDebugLogs = true
err := schema1.LoadSchemaFromFile("json/schema.json")
schema1.ArrayIdKey = "user.id"
if err != nil {
t.Error(err)
}
data, err := GetJson("json/arr-data.json")
if err != nil {
t.Error(err)
}
start := time.Now()
errs := schema1.Validate(data)
log.Printf("[ARRAY OF OBJ] Validation Time: %v", time.Since(start))
if errs != nil {
obj, err := json.Marshal(errs)
if err != nil {
log.Fatalf("err: %v", err)
}
log.Printf("array validations >>>> %v", string(obj))
} else {
start = time.Now()
newData := schema1.Operate(data)
log.Printf("[ARRAY OF OBJ] Operation Time: %v", time.Since(start))
log.Printf("[ARRAY OF OBJ] Updated Data: %v", newData)
}
log.Printf("[ARRAY OF OBJ] total time taken: %v", time.Since(fnTimeStart))
log.Println("-------------------------------------------")
}

func TestNestedArrays(t *testing.T) {
fnTimeStart := time.Now()
var schema Schematics
schema.Logging.PrintErrorLogs = true
schema.Logging.PrintDebugLogs = true
err := schema.LoadSchemaFromFile("json/arr-inside-obj-schema.json")
jsonData, err := utils.BytesToMap(content)
if err != nil {
t.Error(err)
}
data, err := GetJson("json/arr-inside-obj-data.json")
if err != nil {
t.Error(err)
}
start := time.Now()
errs := schema.Validate(data)
log.Printf("[TestNestedArrays] Validation Time: %v", time.Since(start))
if errs != nil {
jsonErrors, err := json.Marshal(errs)
if err != nil {
log.Fatalf("[TestNestedArrays] err: %v", err)
}
log.Println("[TestNestedArrays] json errors:", string(jsonErrors))
}

start = time.Now()
newData := schema.Operate(data)
log.Printf("[TestNestedArrays] Operation Time: %v", time.Since(start))
log.Println("[TestNestedArrays] after operations:", newData)
log.Println("[TestNestedArrays] total time taken:", time.Since(fnTimeStart))
}

func TestDeepValidationInArray(t *testing.T) {
fnTimeStart := time.Now()
var schema Schematics
schema.Logging.PrintErrorLogs = true
schema.Logging.PrintDebugLogs = true
err := schema.LoadSchemaFromFile("json/arr-inside-obj-schema.json")
if err != nil {
log.Println("[TestDeepValidationInArray] unable to load the schema from json file: ", err)
t.Error(err)
}
data, err := GetJson("json/arr-inside-arr-obj-data.json")
if err != nil {
log.Println("[TestDeepValidationInArray] unable to load the data from json file: ", err)
t.Error(err)
}
start := time.Now()
errs := schema.Validate(data)
log.Printf("[TestDeepValidationInArray] Validation Time: %v", time.Since(start))

if errs != nil {
jsonErrors, err := json.Marshal(errs)
if err != nil {
log.Fatalf("[TestDeepValidationInArray] err: %v", err)
}
log.Println("[TestDeepValidationInArray] json errors:", string(jsonErrors))
}
start = time.Now()
newData := schema.Operate(data)
log.Printf("[TestDeepValidationInArray] Operation Time: %v", time.Since(start))
log.Println("[TestDeepValidationInArray] after operations:", newData)
log.Println("[TestDeepValidationInArray] total time taken:", time.Since(fnTimeStart))
}

func TestSchemaVersioning(t *testing.T) {
fnTimeStart := time.Now()
var schema Schematics
err := schema.LoadSchemaFromFile("json/schema-v1.1.json")
if err != nil {
log.Println("[TestSchemaVersioning] unable to load the schema from json file: ", err)
t.Error(err)
}
log.Println("Schema Version 1.1", schema)

log.Println("[TestSchemaVersioning] total time taken:", time.Since(fnTimeStart))
errs := schematics.Validate(jsonData)
log.Println(errs.GetStrings("en", "%data\n"))
}
47 changes: 47 additions & 0 deletions api/parsers/request.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package parsers

import (
"encoding/json"
"github.com/ashbeelghouri/jsonschematics"
"io"
"net/http"
"strings"
)

func ParseRequest(r *http.Request) (map[string]interface{}, error) {
var headers map[string]string
for key, values := range r.Header {
headers[key] = values[0]
}
var body map[string]interface{}
if r.Body != nil {
bodyBytes, err := io.ReadAll(r.Body)
if err != nil {
return nil, err
}
err = json.Unmarshal(bodyBytes, &body)
if err != nil {
return nil, err
}
}
body = jsonschematics.DeflateMap(body, ".")
splitPath := strings.Split(r.RequestURI, "?")
// get query parameters
query := map[string]interface{}{}
if splitPath[1] != "" {
for _, param := range strings.Split(splitPath[1], "&") {
kv := strings.Split(param, "=")
if len(kv) == 2 {
query[kv[0]] = kv[1]
}
}
}
// already in the FLAT mode
return map[string]interface{}{
"headers": headers,
"body": body,
"path": splitPath[0],
"method": r.Method,
"query": query,
}, nil
}
176 changes: 176 additions & 0 deletions api/v0/schema.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
package v0

import (
"github.com/ashbeelghouri/jsonschematics/api/parsers"
jsonschematics "github.com/ashbeelghouri/jsonschematics/data/v0"
"github.com/ashbeelghouri/jsonschematics/errorHandler"
"github.com/ashbeelghouri/jsonschematics/utils"
"net/http"
"regexp"
"strings"
)

type TargetKey string
type EndpointKey string
type Name string

type Field struct {
DependsOn []string
Name string
Type string
Required bool
Validators map[TargetKey]Constant
Operators map[TargetKey]Constant
L10n map[string]interface{}
}

type Constant struct {
Attributes map[string]interface{} `json:"attributes"`
ErrMsg string `json:"error"`
L10n map[string]interface{} `json:"l10n"`
}

type Global struct {
Headers map[TargetKey]Field
}

type Endpoint struct {
Type string
Body map[TargetKey]Field
Headers map[TargetKey]Field
Query map[TargetKey]Field
}

type Schema struct {
Version string
Global Global
Locale string
Logger utils.Logger
Endpoints map[EndpointKey]Endpoint
}

func (s *Schema) GetSchematics(fieldType string, fields *map[TargetKey]Field) (*jsonschematics.Schematics, error) {
var schematics jsonschematics.Schematics
FieldKeys := jsonschematics.Field{
DependsOn: []string{},
Type: fieldType,
Validators: map[string]jsonschematics.Constant{},
Operators: map[string]jsonschematics.Constant{},
}

schema := jsonschematics.Schema{
Version: s.Version,
Fields: make(map[jsonschematics.TargetKey]jsonschematics.Field),
}

for target, f := range *fields {
var allValidators map[string]jsonschematics.Constant

for key, validator := range f.Validators {
allValidators[string(key)] = jsonschematics.Constant{
Attributes: validator.Attributes,
Error: validator.ErrMsg,
L10n: validator.L10n,
}
}
var allOperations map[string]jsonschematics.Constant
for key, operator := range f.Operators {
allOperations[string(key)] = jsonschematics.Constant{
Attributes: operator.Attributes,
Error: operator.ErrMsg,
L10n: operator.L10n,
}
}
FieldKeys.Type = f.Type
FieldKeys.Validators = allValidators
FieldKeys.Operators = allOperations
FieldKeys.L10n = s.Global.Headers[target].L10n
schema.Fields[jsonschematics.TargetKey(target)] = FieldKeys
}

schematics.Schema = schema
return &schematics, nil
}

func (s *Schema) ValidateRequest(r *http.Request) *errorHandler.Errors {
internalErrors := "internal-errors"

var errorMessages errorHandler.Errors
var errMsg errorHandler.Error
errMsg.Validator = "request"
errMsg.Value = "all"
transformedRequest, err := parsers.ParseRequest(r)
if err != nil {
s.Logger.ERROR(err.Error())
errMsg.AddMessage("en", "unable to transform request")
errorMessages.AddError(internalErrors, errMsg)
return &errorMessages
}

globalHeadersSchematics, err := s.GetSchematics("Global Headers", &s.Global.Headers)
if err != nil {
s.Logger.ERROR(err.Error())
errMsg.AddMessage("en", "schema conversion error")
errorMessages.AddError(internalErrors, errMsg)
return &errorMessages
}
errs := globalHeadersSchematics.Validate(transformedRequest["headers"])
if errs.HasErrors() {
s.Logger.ERROR("all errors", err.Error())
return errs
}

for path, endpoint := range s.Endpoints {
regex := utils.GetPathRegex(string(path))
matched, err := regexp.MatchString(regex, transformedRequest["path"].(string))
if err != nil {
errMsg.AddMessage("en", "path not matched - regex not matched")
errorMessages.AddError(internalErrors, errMsg)
return &errorMessages
}
if matched {
s.Logger.DEBUG("url not matched")
return nil
}

if strings.ToLower(endpoint.Type) == strings.ToLower(transformedRequest["method"].(string)) {
headerSchematics, err := s.GetSchematics("Headers", &endpoint.Headers)
if err != nil {
s.Logger.ERROR(err.Error())
errMsg.AddMessage("en", err.Error())
errorMessages.AddError(internalErrors, errMsg)
return &errorMessages
}
errs := headerSchematics.Validate(transformedRequest["headers"])
if errs.HasErrors() {
s.Logger.ERROR("validation errors on headers:", errs.GetStrings("en", "%validator: %message"))
return errs
}
bodySchematics, err := s.GetSchematics("Body", &endpoint.Body)
if err != nil {
s.Logger.ERROR(err.Error())
errMsg.AddMessage("en", err.Error())
errorMessages.AddError(internalErrors, errMsg)
return &errorMessages
}
errs = bodySchematics.Validate(transformedRequest["body"])
if errs.HasErrors() {
s.Logger.ERROR("validation errors on body:", errs.GetStrings("en", "%validator: %message"))
return errs
}
querySchematics, err := s.GetSchematics("Query", &endpoint.Query)
if err != nil {
s.Logger.ERROR(err.Error())
errMsg.AddMessage("en", err.Error())
errorMessages.AddError(internalErrors, errMsg)
return &errorMessages
}
errs = querySchematics.Validate(transformedRequest["query"])
if errs.HasErrors() {
s.Logger.ERROR("validation errors on query:", errs.GetStrings("en", "%validator: %message"))
return errs
}
}
}
return nil
}
Loading

0 comments on commit ece319c

Please sign in to comment.