/
rc02.go
115 lines (103 loc) · 3.46 KB
/
rc02.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package dcs
import (
"bytes"
"html/template"
"io"
"net/http"
"strings"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/options"
"github.com/santhosh-tekuri/jsonschema/v5"
_ "github.com/santhosh-tekuri/jsonschema/v5/httploader" // Loader for Schema via HTTP
)
var rc02Schema *jsonschema.Schema
// GetRC02Schema returns the schema for RC v0.2
func GetRC02Schema(reload bool) (*jsonschema.Schema, error) {
githubPrefix := "https://raw.githubusercontent.com/unfoldingWord/rc-schema/master/"
if rc02Schema == nil || reload {
jsonschema.Loaders["https"] = func(url string) (io.ReadCloser, error) {
res, err := http.Get(url)
if err == nil && res != nil && res.StatusCode == 200 {
return res.Body, nil
}
log.Warn("GetRC02Schema: not able to get the schema file remotely [%q]: %v", url, err)
uriPath := strings.TrimPrefix(url, githubPrefix)
fileBuf, err := options.AssetFS().ReadFile("schema", "rc02", uriPath)
if err != nil {
log.Error("GetRC02Schema: local schema file not found: [options/schema/rc02/%s]: %v", uriPath, err)
return nil, err
}
return io.NopCloser(bytes.NewReader(fileBuf)), nil
}
var err error
rc02Schema, err = jsonschema.Compile(githubPrefix + "rc.schema.json")
if err != nil {
return nil, err
}
}
return rc02Schema, nil
}
// ValidateManifestFileAsHTML validates a manifest file and returns the results as template.HTML
func ValidateManifestFileAsHTML(entry *git.TreeEntry) template.HTML {
var result *jsonschema.ValidationError
if r, err := ValidateManifestTreeEntry(entry); err != nil {
log.Warn("ValidateManifestTreeEntry: %v\n", err)
} else {
result = r
}
return template.HTML(ConvertValidationErrorToHTML(result))
}
// ValidateManifestTreeEntry validates a tree entry that is a manifest file and returns the results
func ValidateManifestTreeEntry(entry *git.TreeEntry) (*jsonschema.ValidationError, error) {
if entry == nil {
return nil, nil
}
manifest, err := ReadYAMLFromBlob(entry.Blob())
if err != nil {
return nil, err
}
return ValidateMapByRC02Schema(manifest)
}
// ValidateMetadataFileAsHTML validates a metadata file and returns the results as template.HTML
func ValidateMetadataFileAsHTML(entry *git.TreeEntry) template.HTML {
var result *jsonschema.ValidationError
if r, err := ValidateMetadataTreeEntry(entry); err != nil {
log.Warn("ValidateManifestTreeEntry: %v\n", err)
} else {
result = r
}
return template.HTML(ConvertValidationErrorToHTML(result))
}
// ValidateMetadataTreeEntry validates a tree entry that is a metadata file and returns the results
func ValidateMetadataTreeEntry(entry *git.TreeEntry) (*jsonschema.ValidationError, error) {
if entry == nil {
return nil, nil
}
metadata, err := ReadJSONFromBlob(entry.Blob())
if err != nil {
return nil, err
}
return ValidateMapBySB100Schema(metadata)
}
// ValidateMapByRC02Schema Validates a map structure by the RC v0.2.0 schema and returns the result
func ValidateMapByRC02Schema(data map[string]interface{}) (*jsonschema.ValidationError, error) {
if data == nil {
return &jsonschema.ValidationError{Message: "file cannot be empty"}, nil
}
schema, err := GetRC02Schema(false)
if err != nil {
return nil, err
}
if err = schema.Validate(data); err != nil {
switch e := err.(type) {
case *jsonschema.ValidationError:
return e, nil
default:
return nil, e
}
}
return nil, nil
}