verify nodeinfo response by schema (#22137)
... using [github.com/xeipuuv/gojsonschema](https://github.com/xeipuuv/gojsonschema) Co-authored-by: techknowlogick <techknowlogick@gitea.io>
This commit is contained in:
parent
c4c4151f7d
commit
f3370eeaee
3
go.mod
3
go.mod
|
@ -88,6 +88,7 @@ require (
|
||||||
github.com/unrolled/render v1.5.0
|
github.com/unrolled/render v1.5.0
|
||||||
github.com/urfave/cli v1.22.10
|
github.com/urfave/cli v1.22.10
|
||||||
github.com/xanzy/go-gitlab v0.73.1
|
github.com/xanzy/go-gitlab v0.73.1
|
||||||
|
github.com/xeipuuv/gojsonschema v1.2.0
|
||||||
github.com/yohcop/openid-go v1.0.0
|
github.com/yohcop/openid-go v1.0.0
|
||||||
github.com/yuin/goldmark v1.5.2
|
github.com/yuin/goldmark v1.5.2
|
||||||
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20220924101305-151362477c87
|
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20220924101305-151362477c87
|
||||||
|
@ -266,6 +267,8 @@ require (
|
||||||
github.com/valyala/fastjson v1.6.3 // indirect
|
github.com/valyala/fastjson v1.6.3 // indirect
|
||||||
github.com/x448/float16 v0.8.4 // indirect
|
github.com/x448/float16 v0.8.4 // indirect
|
||||||
github.com/xanzy/ssh-agent v0.3.2 // indirect
|
github.com/xanzy/ssh-agent v0.3.2 // indirect
|
||||||
|
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect
|
||||||
|
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
|
||||||
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect
|
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect
|
||||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 // indirect
|
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 // indirect
|
||||||
go.etcd.io/bbolt v1.3.6 // indirect
|
go.etcd.io/bbolt v1.3.6 // indirect
|
||||||
|
|
6
go.sum
6
go.sum
|
@ -1468,6 +1468,12 @@ github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+
|
||||||
github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g=
|
github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g=
|
||||||
github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM=
|
github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM=
|
||||||
github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8=
|
github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8=
|
||||||
|
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c=
|
||||||
|
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
|
||||||
|
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0=
|
||||||
|
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
|
||||||
|
github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74=
|
||||||
|
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
|
||||||
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo=
|
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo=
|
||||||
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos=
|
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos=
|
||||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8=
|
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8=
|
||||||
|
|
|
@ -27,6 +27,8 @@ func TestNodeinfo(t *testing.T) {
|
||||||
onGiteaRun(t, func(*testing.T, *url.URL) {
|
onGiteaRun(t, func(*testing.T, *url.URL) {
|
||||||
req := NewRequestf(t, "GET", "/api/v1/nodeinfo")
|
req := NewRequestf(t, "GET", "/api/v1/nodeinfo")
|
||||||
resp := MakeRequest(t, req, http.StatusOK)
|
resp := MakeRequest(t, req, http.StatusOK)
|
||||||
|
VerifyJSONSchema(t, resp, "nodeinfo_2.1.json")
|
||||||
|
|
||||||
var nodeinfo api.NodeInfo
|
var nodeinfo api.NodeInfo
|
||||||
DecodeJSON(t, resp, &nodeinfo)
|
DecodeJSON(t, resp, &nodeinfo)
|
||||||
assert.True(t, nodeinfo.OpenRegistrations)
|
assert.True(t, nodeinfo.OpenRegistrations)
|
||||||
|
|
|
@ -33,6 +33,7 @@ import (
|
||||||
|
|
||||||
"github.com/PuerkitoBio/goquery"
|
"github.com/PuerkitoBio/goquery"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/xeipuuv/gojsonschema"
|
||||||
)
|
)
|
||||||
|
|
||||||
var c *web.Route
|
var c *web.Route
|
||||||
|
@ -398,6 +399,25 @@ func DecodeJSON(t testing.TB, resp *httptest.ResponseRecorder, v interface{}) {
|
||||||
assert.NoError(t, decoder.Decode(v))
|
assert.NoError(t, decoder.Decode(v))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func VerifyJSONSchema(t testing.TB, resp *httptest.ResponseRecorder, schemaFile string) {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
schemaFilePath := filepath.Join(filepath.Dir(setting.AppPath), "tests", "integration", "schemas", schemaFile)
|
||||||
|
_, schemaFileErr := os.Stat(schemaFilePath)
|
||||||
|
assert.Nil(t, schemaFileErr)
|
||||||
|
|
||||||
|
schema, schemaFileReadErr := os.ReadFile(schemaFilePath)
|
||||||
|
assert.Nil(t, schemaFileReadErr)
|
||||||
|
assert.True(t, len(schema) > 0)
|
||||||
|
|
||||||
|
nodeinfoSchema := gojsonschema.NewStringLoader(string(schema))
|
||||||
|
nodeinfoString := gojsonschema.NewStringLoader(resp.Body.String())
|
||||||
|
result, schemaValidationErr := gojsonschema.Validate(nodeinfoSchema, nodeinfoString)
|
||||||
|
assert.Nil(t, schemaValidationErr)
|
||||||
|
assert.Empty(t, result.Errors())
|
||||||
|
assert.True(t, result.Valid())
|
||||||
|
}
|
||||||
|
|
||||||
func GetCSRF(t testing.TB, session *TestSession, urlStr string) string {
|
func GetCSRF(t testing.TB, session *TestSession, urlStr string) string {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
req := NewRequest(t, "GET", urlStr)
|
req := NewRequest(t, "GET", urlStr)
|
||||||
|
|
|
@ -0,0 +1,188 @@
|
||||||
|
{
|
||||||
|
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||||
|
"id": "http://nodeinfo.diaspora.software/ns/schema/2.1#",
|
||||||
|
"description": "NodeInfo schema version 2.1.",
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"version",
|
||||||
|
"software",
|
||||||
|
"protocols",
|
||||||
|
"services",
|
||||||
|
"openRegistrations",
|
||||||
|
"usage",
|
||||||
|
"metadata"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"version": {
|
||||||
|
"description": "The schema version, must be 2.1.",
|
||||||
|
"enum": [
|
||||||
|
"2.1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"software": {
|
||||||
|
"description": "Metadata about server software in use.",
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"name",
|
||||||
|
"version"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"description": "The canonical name of this server software.",
|
||||||
|
"type": "string",
|
||||||
|
"pattern": "^[a-z0-9-]+$"
|
||||||
|
},
|
||||||
|
"version": {
|
||||||
|
"description": "The version of this server software.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"description": "The url of the source code repository of this server software.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"homepage": {
|
||||||
|
"description": "The url of the homepage of this server software.",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"protocols": {
|
||||||
|
"description": "The protocols supported on this server.",
|
||||||
|
"type": "array",
|
||||||
|
"minItems": 1,
|
||||||
|
"items": {
|
||||||
|
"enum": [
|
||||||
|
"activitypub",
|
||||||
|
"buddycloud",
|
||||||
|
"dfrn",
|
||||||
|
"diaspora",
|
||||||
|
"libertree",
|
||||||
|
"ostatus",
|
||||||
|
"pumpio",
|
||||||
|
"tent",
|
||||||
|
"xmpp",
|
||||||
|
"zot"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"services": {
|
||||||
|
"description": "The third party sites this server can connect to via their application API.",
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"inbound",
|
||||||
|
"outbound"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"inbound": {
|
||||||
|
"description": "The third party sites this server can retrieve messages from for combined display with regular traffic.",
|
||||||
|
"type": "array",
|
||||||
|
"minItems": 0,
|
||||||
|
"items": {
|
||||||
|
"enum": [
|
||||||
|
"atom1.0",
|
||||||
|
"gnusocial",
|
||||||
|
"imap",
|
||||||
|
"pnut",
|
||||||
|
"pop3",
|
||||||
|
"pumpio",
|
||||||
|
"rss2.0",
|
||||||
|
"twitter"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"outbound": {
|
||||||
|
"description": "The third party sites this server can publish messages to on the behalf of a user.",
|
||||||
|
"type": "array",
|
||||||
|
"minItems": 0,
|
||||||
|
"items": {
|
||||||
|
"enum": [
|
||||||
|
"atom1.0",
|
||||||
|
"blogger",
|
||||||
|
"buddycloud",
|
||||||
|
"diaspora",
|
||||||
|
"dreamwidth",
|
||||||
|
"drupal",
|
||||||
|
"facebook",
|
||||||
|
"friendica",
|
||||||
|
"gnusocial",
|
||||||
|
"google",
|
||||||
|
"insanejournal",
|
||||||
|
"libertree",
|
||||||
|
"linkedin",
|
||||||
|
"livejournal",
|
||||||
|
"mediagoblin",
|
||||||
|
"myspace",
|
||||||
|
"pinterest",
|
||||||
|
"pnut",
|
||||||
|
"posterous",
|
||||||
|
"pumpio",
|
||||||
|
"redmatrix",
|
||||||
|
"rss2.0",
|
||||||
|
"smtp",
|
||||||
|
"tent",
|
||||||
|
"tumblr",
|
||||||
|
"twitter",
|
||||||
|
"wordpress",
|
||||||
|
"xmpp"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"openRegistrations": {
|
||||||
|
"description": "Whether this server allows open self-registration.",
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"usage": {
|
||||||
|
"description": "Usage statistics for this server.",
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"users"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"users": {
|
||||||
|
"description": "statistics about the users of this server.",
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": {
|
||||||
|
"total": {
|
||||||
|
"description": "The total amount of on this server registered users.",
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 0
|
||||||
|
},
|
||||||
|
"activeHalfyear": {
|
||||||
|
"description": "The amount of users that signed in at least once in the last 180 days.",
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 0
|
||||||
|
},
|
||||||
|
"activeMonth": {
|
||||||
|
"description": "The amount of users that signed in at least once in the last 30 days.",
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"localPosts": {
|
||||||
|
"description": "The amount of posts that were made by users that are registered on this server.",
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 0
|
||||||
|
},
|
||||||
|
"localComments": {
|
||||||
|
"description": "The amount of comments that were made by users that are registered on this server.",
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"metadata": {
|
||||||
|
"description": "Free form key value pairs for software specific values. Clients should not rely on any specific key present.",
|
||||||
|
"type": "object",
|
||||||
|
"minProperties": 0,
|
||||||
|
"additionalProperties": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue