jskos-server 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.dockerignore +20 -0
- package/.editorconfig +9 -0
- package/.github/workflows/docker.yml +59 -0
- package/.github/workflows/gh-pages.yml +23 -0
- package/.github/workflows/gh-release.yml +19 -0
- package/.github/workflows/test.yml +39 -0
- package/.husky/pre-commit +1 -0
- package/CHANGELOG.md +18 -0
- package/LICENSE +21 -0
- package/README.md +2710 -0
- package/bin/extra.js +81 -0
- package/bin/import.js +438 -0
- package/bin/mongodb.js +21 -0
- package/bin/reset.js +257 -0
- package/bin/upgrade.js +34 -0
- package/config/config.default.json +88 -0
- package/config/config.schema.json +877 -0
- package/config/config.test.json +107 -0
- package/config/index.js +77 -0
- package/config/setup.js +212 -0
- package/depdendencies.png +0 -0
- package/docker/.env +1 -0
- package/docker/Dockerfile +20 -0
- package/docker/README.md +175 -0
- package/docker/docker-compose.yml +29 -0
- package/docker/docker-entrypoint.sh +8 -0
- package/docker/mongo-initdb.d/mongo_setup.sh +22 -0
- package/ecosystem.example.json +7 -0
- package/errors/index.js +94 -0
- package/eslint.config.js +17 -0
- package/index.js +10 -0
- package/models/annotations.js +13 -0
- package/models/concepts.js +12 -0
- package/models/concordances.js +12 -0
- package/models/index.js +33 -0
- package/models/mappings.js +20 -0
- package/models/meta.js +21 -0
- package/models/registries.js +12 -0
- package/models/schemes.js +12 -0
- package/package.json +91 -0
- package/routes/annotations.js +83 -0
- package/routes/common.js +86 -0
- package/routes/concepts.js +64 -0
- package/routes/concordances.js +86 -0
- package/routes/data.js +19 -0
- package/routes/mappings.js +108 -0
- package/routes/registries.js +24 -0
- package/routes/schemes.js +72 -0
- package/routes/validate.js +37 -0
- package/server.js +190 -0
- package/services/abstract.js +328 -0
- package/services/annotations.js +237 -0
- package/services/concepts.js +459 -0
- package/services/concordances.js +264 -0
- package/services/data.js +30 -0
- package/services/index.js +34 -0
- package/services/mappings.js +978 -0
- package/services/registries.js +319 -0
- package/services/schemes.js +318 -0
- package/services/validate.js +39 -0
- package/status.schema.json +145 -0
- package/test/abstract-service.js +36 -0
- package/test/annotations/annotation.json +13 -0
- package/test/api.js +2481 -0
- package/test/chai.js +14 -0
- package/test/changes.js +179 -0
- package/test/concepts/conceptNoFileEnding +4 -0
- package/test/concepts/concepts-ddc-6-60-61-62.json +123 -0
- package/test/concordances/concordances.ndjson +2 -0
- package/test/config.js +26 -0
- package/test/configs/complex-config.json +90 -0
- package/test/configs/empty-object.json +1 -0
- package/test/configs/fail-array.json +1 -0
- package/test/configs/fail-empty.json +0 -0
- package/test/configs/fail-mapping-only-props1.json +5 -0
- package/test/configs/fail-mapping-only-props2.json +5 -0
- package/test/configs/fail-mapping-only-props3.json +5 -0
- package/test/configs/fail-mapping-only-props4.json +5 -0
- package/test/configs/fail-nonexisting-prop.json +3 -0
- package/test/configs/fail-port-string.json +3 -0
- package/test/configs/fail-registry-types.json +16 -0
- package/test/configs/registry-types.json +16 -0
- package/test/data-write.js +784 -0
- package/test/eslint.js +22 -0
- package/test/import-reset.js +287 -0
- package/test/infer-mappings.js +340 -0
- package/test/ipcheck.js +287 -0
- package/test/mappings/README.md +1 -0
- package/test/mappings/ddc-gnd-1.mapping.json +33 -0
- package/test/mappings/ddc-gnd-2.mapping.json +67 -0
- package/test/mappings/mapping-ddc-gnd-noScheme.json +145 -0
- package/test/mappings/mapping-ddc-gnd.json +175 -0
- package/test/mappings/mappings-ddc.json +214 -0
- package/test/registries/registries.ndjson +2 -0
- package/test/services.js +557 -0
- package/test/terminologies/terminologies.json +94 -0
- package/test/test-utils.js +182 -0
- package/test/utils.js +425 -0
- package/test/validate.js +226 -0
- package/utils/adjust.js +206 -0
- package/utils/auth.js +154 -0
- package/utils/changes.js +88 -0
- package/utils/db.js +106 -0
- package/utils/ipcheck.js +76 -0
- package/utils/middleware.js +636 -0
- package/utils/searchHelper.js +153 -0
- package/utils/status.js +77 -0
- package/utils/users.js +7 -0
- package/utils/utils.js +114 -0
- package/utils/uuid.js +6 -0
- package/utils/version.js +324 -0
- package/views/base.ejs +172 -0
package/test/chai.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// Setup chai and plugins
|
|
2
|
+
|
|
3
|
+
import * as chaiModule from "chai"
|
|
4
|
+
|
|
5
|
+
import chaiAsPromised from "chai-as-promised"
|
|
6
|
+
chaiModule.use(chaiAsPromised)
|
|
7
|
+
|
|
8
|
+
import chaiHttp from "chai-http"
|
|
9
|
+
const chai = chaiModule.use(chaiHttp)
|
|
10
|
+
|
|
11
|
+
// eslint-disable-next-line no-unused-vars
|
|
12
|
+
const should = chai.should()
|
|
13
|
+
|
|
14
|
+
export default chai
|
package/test/changes.js
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { assertMongoDB, dropDatabaseBeforeAndAfter, setupInMemoryMongo, teardownInMemoryMongo, createCollectionsAndIndexes } from "./test-utils.js"
|
|
2
|
+
import WebSocket from "ws"
|
|
3
|
+
import assert from "assert"
|
|
4
|
+
import config from "../config/index.js"
|
|
5
|
+
import { app } from "../server.js"
|
|
6
|
+
import { setupChangesApi } from "../utils/changes.js"
|
|
7
|
+
import { objectTypes } from "jskos-tools"
|
|
8
|
+
import mongoose from "mongoose"
|
|
9
|
+
|
|
10
|
+
// Map each route to its collection name and expected JSKOS type
|
|
11
|
+
const routes = {
|
|
12
|
+
voc: { coll: "terminologies", type: "ConceptScheme" },
|
|
13
|
+
concepts: { coll: "concepts", type: "Concept" },
|
|
14
|
+
mappings: { coll: "mappings", type: "ConceptMapping" },
|
|
15
|
+
concordances: { coll: "concordances", type: "Concordance" },
|
|
16
|
+
annotations: { coll: "annotations", type: "Annotation" },
|
|
17
|
+
registries: { coll: "registries", type: "Registry" },
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
describe("Change‐Streams API setup", () => {
|
|
21
|
+
// Capture console.log output
|
|
22
|
+
let loggedMessages = []
|
|
23
|
+
const originalLog = console.log
|
|
24
|
+
|
|
25
|
+
before(async () => {
|
|
26
|
+
console.log = (msg) => loggedMessages.push(msg)
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
after(async () => {
|
|
30
|
+
console.log = originalLog
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
it("should skip registering when changes is false", async () => {
|
|
34
|
+
// ensure flag is off
|
|
35
|
+
config.changes = false
|
|
36
|
+
|
|
37
|
+
// call the exported setup function
|
|
38
|
+
await setupChangesApi(app, config)
|
|
39
|
+
|
|
40
|
+
// assert our early‐return message was logged
|
|
41
|
+
loggedMessages.includes("Change API is disabled by configuration.")
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
describe("WebSocket Change‐Streams (integration)", function () {
|
|
47
|
+
|
|
48
|
+
before(async () => {
|
|
49
|
+
await setupInMemoryMongo({ replSet: true })
|
|
50
|
+
config.changes = true
|
|
51
|
+
await setupChangesApi(app, config)
|
|
52
|
+
await createCollectionsAndIndexes()
|
|
53
|
+
// optionally spin up your HTTP+WS server here
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
after(async () => {
|
|
57
|
+
// close server if you started one
|
|
58
|
+
await teardownInMemoryMongo()
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
// 🗑 Drop DB before *and* after every single `it()` in this file
|
|
62
|
+
dropDatabaseBeforeAndAfter()
|
|
63
|
+
|
|
64
|
+
// 🔌 Sanity‐check that mongoose really is connected
|
|
65
|
+
assertMongoDB()
|
|
66
|
+
|
|
67
|
+
// generate tests for each route
|
|
68
|
+
for (const [route, info] of Object.entries(routes)) {
|
|
69
|
+
lifecycleTests(route, info)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
function lifecycleTests(route, { coll, type }) {
|
|
75
|
+
const uriBase = `urn:test:${route}`
|
|
76
|
+
const typeUri = objectTypes[type].type?.[0]
|
|
77
|
+
|
|
78
|
+
describe(`${route}/changes`, () => {
|
|
79
|
+
it("emits create", done => {
|
|
80
|
+
const ws = new WebSocket(`ws://localhost:${config.port}/${route}/changes`)
|
|
81
|
+
ws.on("open", async () => {
|
|
82
|
+
await mongoose.connection.db.collection(coll).insertOne({
|
|
83
|
+
uri: `${uriBase}:1`,
|
|
84
|
+
type: typeUri,
|
|
85
|
+
prefLabel: { en: ["A"] },
|
|
86
|
+
})
|
|
87
|
+
})
|
|
88
|
+
ws.on("message", raw => {
|
|
89
|
+
const evt = JSON.parse(raw)
|
|
90
|
+
if (evt.type !== "create") {
|
|
91
|
+
return
|
|
92
|
+
}
|
|
93
|
+
try {
|
|
94
|
+
assert.strictEqual(evt.type, "create")
|
|
95
|
+
assert.strictEqual(evt.objectType, type)
|
|
96
|
+
assert.deepStrictEqual(evt.document.prefLabel.en, ["A"])
|
|
97
|
+
assertOptionalIsoTimestamp(evt.timestamp)
|
|
98
|
+
ws.close()
|
|
99
|
+
done()
|
|
100
|
+
} catch (err) {
|
|
101
|
+
done(err)
|
|
102
|
+
}
|
|
103
|
+
})
|
|
104
|
+
ws.on("error", err => done(err))
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
it("emits update", done => {
|
|
108
|
+
const ws = new WebSocket(`ws://localhost:${config.port}/${route}/changes`)
|
|
109
|
+
ws.on("open", async () => {
|
|
110
|
+
const { insertedId } = await mongoose.connection.db.collection(coll).insertOne({
|
|
111
|
+
uri: `${uriBase}:2`,
|
|
112
|
+
type: typeUri,
|
|
113
|
+
prefLabel: { en: ["B"] },
|
|
114
|
+
})
|
|
115
|
+
await mongoose.connection.db.collection(coll).updateOne(
|
|
116
|
+
{ _id: insertedId },
|
|
117
|
+
{ $set: { prefLabel: { en: ["BB"] } } },
|
|
118
|
+
)
|
|
119
|
+
})
|
|
120
|
+
ws.on("message", raw => {
|
|
121
|
+
const evt = JSON.parse(raw)
|
|
122
|
+
if (evt.type !== "update") {
|
|
123
|
+
return
|
|
124
|
+
}
|
|
125
|
+
try {
|
|
126
|
+
assert.strictEqual(evt.objectType, type)
|
|
127
|
+
assert.deepStrictEqual(evt.document.prefLabel.en, ["BB"])
|
|
128
|
+
assertOptionalIsoTimestamp(evt.timestamp)
|
|
129
|
+
ws.close()
|
|
130
|
+
done()
|
|
131
|
+
} catch (err) {
|
|
132
|
+
done(err)
|
|
133
|
+
}
|
|
134
|
+
})
|
|
135
|
+
ws.on("error", err => done(err))
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
it("emits delete", done => {
|
|
139
|
+
const ws = new WebSocket(`ws://localhost:${config.port}/${route}/changes`)
|
|
140
|
+
ws.on("open", async () => {
|
|
141
|
+
const { insertedId } = await mongoose.connection.db.collection(coll).insertOne({
|
|
142
|
+
uri: `${uriBase}:3`,
|
|
143
|
+
type: typeUri,
|
|
144
|
+
prefLabel: { en: ["C"] },
|
|
145
|
+
})
|
|
146
|
+
await mongoose.connection.db.collection(coll).deleteOne({ _id: insertedId })
|
|
147
|
+
})
|
|
148
|
+
ws.on("message", raw => {
|
|
149
|
+
const evt = JSON.parse(raw)
|
|
150
|
+
if (evt.type !== "delete") {
|
|
151
|
+
return
|
|
152
|
+
}
|
|
153
|
+
try {
|
|
154
|
+
// on delete fullDocument is omitted
|
|
155
|
+
assert.strictEqual(evt.document, undefined)
|
|
156
|
+
ws.close()
|
|
157
|
+
done()
|
|
158
|
+
} catch (err) {
|
|
159
|
+
done(err)
|
|
160
|
+
}
|
|
161
|
+
})
|
|
162
|
+
ws.on("error", err => done(err))
|
|
163
|
+
})
|
|
164
|
+
})
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Validates that the provided timestamp, if present, is a string matching the strict ISO 8601 format `YYYY-MM-DDTHH:mm:ss.SSSZ`.
|
|
169
|
+
*
|
|
170
|
+
* @param {?string} ts - The timestamp to validate.
|
|
171
|
+
* @throws {AssertionError} If the timestamp is not a string or does not match the ISO 8601 format.
|
|
172
|
+
*/
|
|
173
|
+
function assertOptionalIsoTimestamp(ts) {
|
|
174
|
+
if (ts == null) {
|
|
175
|
+
return
|
|
176
|
+
}
|
|
177
|
+
assert.strictEqual(typeof ts, "string")
|
|
178
|
+
assert.match(ts, /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/)
|
|
179
|
+
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"@context": "https://gbv.github.io/jskos/context.json",
|
|
4
|
+
"created": "2000-02-02",
|
|
5
|
+
"identifier": [
|
|
6
|
+
"856c92e9-8b1f-3131-bfbe-f2d2266527d3"
|
|
7
|
+
],
|
|
8
|
+
"modified": "2005-11-02",
|
|
9
|
+
"notation": [
|
|
10
|
+
"6"
|
|
11
|
+
],
|
|
12
|
+
"prefLabel": {
|
|
13
|
+
"de": "Technik, Medizin, angewandte Wissenschaften"
|
|
14
|
+
},
|
|
15
|
+
"topConceptOf": [
|
|
16
|
+
{
|
|
17
|
+
"uri": "http://dewey.info/scheme/edition/e23/"
|
|
18
|
+
}
|
|
19
|
+
],
|
|
20
|
+
"type": [
|
|
21
|
+
"http://www.w3.org/2004/02/skos/core#Concept"
|
|
22
|
+
],
|
|
23
|
+
"uri": "http://dewey.info/class/6/e23/",
|
|
24
|
+
"narrower": [
|
|
25
|
+
null
|
|
26
|
+
]
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"@context": "https://gbv.github.io/jskos/context.json",
|
|
30
|
+
"broader": [
|
|
31
|
+
{
|
|
32
|
+
"uri": "http://dewey.info/class/6/e23/"
|
|
33
|
+
}
|
|
34
|
+
],
|
|
35
|
+
"created": "2000-02-02",
|
|
36
|
+
"identifier": [
|
|
37
|
+
"028d7bfc-77bf-3062-a6a8-857f66153fb9"
|
|
38
|
+
],
|
|
39
|
+
"inScheme": [
|
|
40
|
+
{
|
|
41
|
+
"uri": "http://dewey.info/scheme/edition/e23/"
|
|
42
|
+
}
|
|
43
|
+
],
|
|
44
|
+
"modified": "2005-11-02",
|
|
45
|
+
"notation": [
|
|
46
|
+
"60"
|
|
47
|
+
],
|
|
48
|
+
"prefLabel": {
|
|
49
|
+
"de": "Technik",
|
|
50
|
+
"en": "Technology"
|
|
51
|
+
},
|
|
52
|
+
"type": [
|
|
53
|
+
"http://www.w3.org/2004/02/skos/core#Concept"
|
|
54
|
+
],
|
|
55
|
+
"uri": "http://dewey.info/class/60/e23/",
|
|
56
|
+
"narrower": [
|
|
57
|
+
null
|
|
58
|
+
]
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
"@context": "https://gbv.github.io/jskos/context.json",
|
|
62
|
+
"broader": [
|
|
63
|
+
{
|
|
64
|
+
"uri": "http://dewey.info/class/6/e23/"
|
|
65
|
+
}
|
|
66
|
+
],
|
|
67
|
+
"created": "2000-02-02",
|
|
68
|
+
"identifier": [
|
|
69
|
+
"c14b599b-42cc-327e-abe2-fc1bb609e99e"
|
|
70
|
+
],
|
|
71
|
+
"inScheme": [
|
|
72
|
+
{
|
|
73
|
+
"uri": "http://dewey.info/scheme/edition/e23/"
|
|
74
|
+
}
|
|
75
|
+
],
|
|
76
|
+
"modified": "2005-11-02",
|
|
77
|
+
"notation": [
|
|
78
|
+
"61"
|
|
79
|
+
],
|
|
80
|
+
"prefLabel": {
|
|
81
|
+
"de": "Medizin & Gesundheit"
|
|
82
|
+
},
|
|
83
|
+
"type": [
|
|
84
|
+
"http://www.w3.org/2004/02/skos/core#Concept"
|
|
85
|
+
],
|
|
86
|
+
"uri": "http://dewey.info/class/61/e23/",
|
|
87
|
+
"narrower": [
|
|
88
|
+
null
|
|
89
|
+
]
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
"@context": "https://gbv.github.io/jskos/context.json",
|
|
93
|
+
"broader": [
|
|
94
|
+
{
|
|
95
|
+
"uri": "http://dewey.info/class/6/e23/"
|
|
96
|
+
}
|
|
97
|
+
],
|
|
98
|
+
"created": "2000-02-02",
|
|
99
|
+
"identifier": [
|
|
100
|
+
"ac872f11-eb09-3f7d-a307-613f3042791e"
|
|
101
|
+
],
|
|
102
|
+
"inScheme": [
|
|
103
|
+
{
|
|
104
|
+
"uri": "http://dewey.info/scheme/edition/e23/"
|
|
105
|
+
}
|
|
106
|
+
],
|
|
107
|
+
"modified": "2005-11-02",
|
|
108
|
+
"notation": [
|
|
109
|
+
"62"
|
|
110
|
+
],
|
|
111
|
+
"prefLabel": {
|
|
112
|
+
"de": "Ingenieurwissenschaften"
|
|
113
|
+
},
|
|
114
|
+
"type": [
|
|
115
|
+
"http://www.w3.org/2004/02/skos/core#Concept"
|
|
116
|
+
],
|
|
117
|
+
"uri": "http://dewey.info/class/62/e23/",
|
|
118
|
+
"narrower": [
|
|
119
|
+
null
|
|
120
|
+
]
|
|
121
|
+
}
|
|
122
|
+
]
|
|
123
|
+
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
{"@context":"https://gbv.github.io/jskos/context.json","creator":[{"prefLabel":{"de":"VZG"}}],"extent":"2267","fromScheme":{"notation":["DDC"],"uri":"http://bartoc.org/en/node/241"},"notation":["ddc_rvk_recht"],"scopeNote":{"de":["Recht"]},"toScheme":{"notation":["RVK"],"uri":"http://bartoc.org/en/node/533"},"type":["http://rdfs.org/ns/void#Linkset"],"uri":"http://coli-conc.gbv.de/concordances/ddc_rvk_recht"}
|
|
2
|
+
{"@context":"https://gbv.github.io/jskos/context.json","creator":[{"prefLabel":{"de":"VZG"}}],"extent":"2813","fromScheme":{"notation":["DDC"],"uri":"http://bartoc.org/en/node/241"},"notation":["ddc_rvk_medizin"],"scopeNote":{"de":["Medizin und Gesundheit"]},"toScheme":{"notation":["RVK"],"uri":"http://bartoc.org/en/node/533"},"type":["http://rdfs.org/ns/void#Linkset"],"uri":"http://coli-conc.gbv.de/concordances/ddc_rvk_medizin"}
|
package/test/config.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import fs from "node:fs"
|
|
2
|
+
import assert from "node:assert"
|
|
3
|
+
import { validateConfig, setupConfig } from "../config/setup.js"
|
|
4
|
+
|
|
5
|
+
describe("Configuration", () => {
|
|
6
|
+
for (let file of [
|
|
7
|
+
"config/config.default.json",
|
|
8
|
+
"config/config.test.json",
|
|
9
|
+
].concat(fs.readdirSync("./test/configs").map(f => `test/configs/${f}`))) {
|
|
10
|
+
const shouldFail = file.includes("fail-")
|
|
11
|
+
it(`should ${shouldFail ? "not validate" : "validate and setup"} ${file}`, () => {
|
|
12
|
+
let config
|
|
13
|
+
try {
|
|
14
|
+
config = JSON.parse(fs.readFileSync(file))
|
|
15
|
+
} catch { /* ignore */ }
|
|
16
|
+
if (shouldFail) {
|
|
17
|
+
assert.throws(() => validateConfig(config))
|
|
18
|
+
} else {
|
|
19
|
+
validateConfig(config)
|
|
20
|
+
setupConfig(config)
|
|
21
|
+
assert.ok(config)
|
|
22
|
+
assert.ok(config.log)
|
|
23
|
+
}
|
|
24
|
+
})
|
|
25
|
+
}
|
|
26
|
+
})
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
{
|
|
2
|
+
"verbosity": "log",
|
|
3
|
+
"baseUrl": "https://example.com/",
|
|
4
|
+
"title": "JSKOS Server Complex Example Config",
|
|
5
|
+
"port": 12345,
|
|
6
|
+
"proxies": [
|
|
7
|
+
"127.0.0.1/8"
|
|
8
|
+
],
|
|
9
|
+
"mongo": {
|
|
10
|
+
"user": "a",
|
|
11
|
+
"pass": "b",
|
|
12
|
+
"host": "127.0.0.1",
|
|
13
|
+
"port": 27018,
|
|
14
|
+
"db": "jskos-server-db"
|
|
15
|
+
},
|
|
16
|
+
"auth": {
|
|
17
|
+
"algorithm": "RS256",
|
|
18
|
+
"key": "public key here"
|
|
19
|
+
},
|
|
20
|
+
"schemes": true,
|
|
21
|
+
"concepts": {
|
|
22
|
+
"read": {
|
|
23
|
+
"auth": false
|
|
24
|
+
},
|
|
25
|
+
"create": {
|
|
26
|
+
"auth": true,
|
|
27
|
+
"ips": [
|
|
28
|
+
"5.6.7.8"
|
|
29
|
+
]
|
|
30
|
+
},
|
|
31
|
+
"update": {
|
|
32
|
+
"identityProviders": [
|
|
33
|
+
"github"
|
|
34
|
+
]
|
|
35
|
+
},
|
|
36
|
+
"delete": {
|
|
37
|
+
"auth": false,
|
|
38
|
+
"identities": [
|
|
39
|
+
"http://some.uri"
|
|
40
|
+
]
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
"mappings": {
|
|
44
|
+
"read": {
|
|
45
|
+
"auth": false
|
|
46
|
+
},
|
|
47
|
+
"create": {
|
|
48
|
+
"auth": true
|
|
49
|
+
},
|
|
50
|
+
"update": {
|
|
51
|
+
"auth": true,
|
|
52
|
+
"crossUser": true
|
|
53
|
+
},
|
|
54
|
+
"delete": {
|
|
55
|
+
"auth": true,
|
|
56
|
+
"crossUser": false
|
|
57
|
+
},
|
|
58
|
+
"fromSchemeWhitelist": [
|
|
59
|
+
{
|
|
60
|
+
"uri": "some:scheme"
|
|
61
|
+
}
|
|
62
|
+
],
|
|
63
|
+
"anonymous": true,
|
|
64
|
+
"cardinality": "1-to-1"
|
|
65
|
+
},
|
|
66
|
+
"concordances": false,
|
|
67
|
+
"annotations": {
|
|
68
|
+
"read": {
|
|
69
|
+
"auth": false
|
|
70
|
+
},
|
|
71
|
+
"create": {
|
|
72
|
+
"auth": true,
|
|
73
|
+
"identities": [
|
|
74
|
+
"http://some.uri"
|
|
75
|
+
]
|
|
76
|
+
},
|
|
77
|
+
"update": {
|
|
78
|
+
"auth": true,
|
|
79
|
+
"crossUser": false
|
|
80
|
+
},
|
|
81
|
+
"delete": {
|
|
82
|
+
"auth": true,
|
|
83
|
+
"crossUser": false,
|
|
84
|
+
"ips": [
|
|
85
|
+
"134.5.6.7/24"
|
|
86
|
+
]
|
|
87
|
+
},
|
|
88
|
+
"moderatingIdentities": []
|
|
89
|
+
}
|
|
90
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
[]
|
|
File without changes
|