@kkuffour/solid-moderation-plugin 0.2.2 → 0.3.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/.data/.internal/idp/keys/cookie-secret$.json +1 -0
- package/.data/.internal/idp/keys/jwks$.json +1 -0
- package/.data/.internal/setup/current-base-url$.json +1 -0
- package/PLUGIN_DEVELOPER_GUIDE.md +213 -0
- package/README.md +25 -28
- package/components/context.jsonld +6 -245
- package/config/default.json +14 -28
- package/dist/ModerationHandler.d.ts +21 -0
- package/dist/ModerationHandler.d.ts.map +1 -0
- package/dist/ModerationHandler.js +158 -0
- package/dist/ModerationHandler.js.map +1 -0
- package/dist/ModerationHandler.jsonld +126 -0
- package/dist/components/components.jsonld +13 -0
- package/dist/components/context.jsonld +11 -0
- package/dist/index.d.ts +1 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -6
- package/dist/index.js.map +1 -1
- package/dist/providers/SightEngineProvider.jsonld +2 -2
- package/package.json +11 -11
- package/src/ModerationHandler.ts +189 -0
- package/src/index.ts +1 -6
- package/ARCHITECTURE.md +0 -52
- package/CONFIG-GUIDE.md +0 -49
- package/DEVELOPMENT.md +0 -129
- package/ENV-VARIABLES.md +0 -137
- package/INSTALLATION.md +0 -90
- package/MIGRATION.md +0 -81
- package/PRODUCTION.md +0 -186
- package/PUBLISHING.md +0 -104
- package/TESTING.md +0 -93
- package/components/components.jsonld +0 -18
- package/dist/ModerationConfig.d.ts +0 -16
- package/dist/ModerationConfig.d.ts.map +0 -1
- package/dist/ModerationConfig.js +0 -18
- package/dist/ModerationConfig.js.map +0 -1
- package/dist/ModerationConfig.jsonld +0 -66
- package/dist/ModerationMixin.d.ts +0 -13
- package/dist/ModerationMixin.d.ts.map +0 -1
- package/dist/ModerationMixin.js +0 -136
- package/dist/ModerationMixin.js.map +0 -1
- package/dist/ModerationMixin.jsonld +0 -180
- package/dist/ModerationOperationHandler.d.ts +0 -16
- package/dist/ModerationOperationHandler.d.ts.map +0 -1
- package/dist/ModerationOperationHandler.js +0 -45
- package/dist/ModerationOperationHandler.js.map +0 -1
- package/dist/ModerationOperationHandler.jsonld +0 -140
- package/dist/ModerationRecord.d.ts +0 -20
- package/dist/ModerationRecord.d.ts.map +0 -1
- package/dist/ModerationRecord.js +0 -3
- package/dist/ModerationRecord.js.map +0 -1
- package/dist/ModerationRecord.jsonld +0 -59
- package/dist/ModerationResourceStore.d.ts +0 -30
- package/dist/ModerationResourceStore.d.ts.map +0 -1
- package/dist/ModerationResourceStore.js +0 -167
- package/dist/ModerationResourceStore.js.map +0 -1
- package/dist/ModerationResourceStore.jsonld +0 -157
- package/dist/ModerationStore.d.ts +0 -12
- package/dist/ModerationStore.d.ts.map +0 -1
- package/dist/ModerationStore.js +0 -37
- package/dist/ModerationStore.js.map +0 -1
- package/dist/ModerationStore.jsonld +0 -59
- package/dist/util/GuardedStream.d.ts +0 -33
- package/dist/util/GuardedStream.d.ts.map +0 -1
- package/dist/util/GuardedStream.js +0 -89
- package/dist/util/GuardedStream.js.map +0 -1
- package/simple-test.json +0 -7
- package/src/ModerationConfig.ts +0 -29
- package/src/ModerationMixin.ts +0 -153
- package/src/ModerationOperationHandler.ts +0 -64
- package/src/ModerationRecord.ts +0 -19
- package/src/ModerationResourceStore.ts +0 -227
- package/src/ModerationStore.ts +0 -41
- package/src/util/GuardedStream.ts +0 -101
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"key":"idp/keys/cookie-secret","payload":["59d073a4fc66124c74d4d8f2d32f0383ef82d91122b25ee81ad691a46dc785203c2720e6e47d9ab7f19bf8970f460cb672267c6c47064e91f36285542b8d694b"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"key":"idp/keys/jwks","payload":{"keys":[{"kty":"EC","x":"ttiH782m1M7AgKeQtsBJbJ6wx453vyKjJxho6vS7GpQ","y":"38doyGzPtVycO8Su7jVHDiY3n1zDofPNlUqYBut8FSA","crv":"P-256","d":"lVK7R5xL1Oph5Vh7FZPOZNwr24QTRu3HECdC8DLKd9Y","alg":"ES256"}]}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"key":"setup/current-base-url","payload":"http://localhost:3009/"}
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
# Plugin Developer Guide: Using the ExtensionHandler
|
|
2
|
+
|
|
3
|
+
## Quick Start
|
|
4
|
+
|
|
5
|
+
To create a plugin that extends Community Solid Server functionality:
|
|
6
|
+
|
|
7
|
+
### 1. Create Your Handler Class
|
|
8
|
+
|
|
9
|
+
Your handler must extend `OperationHandler` from CSS:
|
|
10
|
+
|
|
11
|
+
```typescript
|
|
12
|
+
import { OperationHandler } from '@solid/community-server';
|
|
13
|
+
import type { OperationHandlerInput, ResponseDescription } from '@solid/community-server';
|
|
14
|
+
import { NotFoundHttpError } from '@solid/community-server';
|
|
15
|
+
|
|
16
|
+
export class MyPluginHandler extends OperationHandler {
|
|
17
|
+
public async handle(input: OperationHandlerInput): Promise<ResponseDescription> {
|
|
18
|
+
const { operation } = input;
|
|
19
|
+
|
|
20
|
+
// Your custom logic here
|
|
21
|
+
// Example: Check if operation should be handled
|
|
22
|
+
if (this.shouldHandle(operation)) {
|
|
23
|
+
// Process the operation
|
|
24
|
+
return this.processOperation(operation);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Pass to next handler in chain
|
|
28
|
+
throw new NotFoundHttpError();
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
private shouldHandle(operation: Operation): boolean {
|
|
32
|
+
// Your logic to determine if this operation should be handled
|
|
33
|
+
return operation.method === 'POST' || operation.method === 'PUT';
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
private async processOperation(operation: Operation): Promise<ResponseDescription> {
|
|
37
|
+
// Your processing logic
|
|
38
|
+
// Return a ResponseDescription or throw an error
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### 2. Create Components.js Configuration
|
|
44
|
+
|
|
45
|
+
Create a config file (e.g., `config/default.json`) in your plugin package:
|
|
46
|
+
|
|
47
|
+
```json
|
|
48
|
+
{
|
|
49
|
+
"@context": "https://linkedsoftwaredependencies.org/bundles/npm/@solid/community-server/^7.0.0/components/context.jsonld",
|
|
50
|
+
"import": ["css:config/file.json"],
|
|
51
|
+
"@graph": [
|
|
52
|
+
{
|
|
53
|
+
"@id": "urn:solid-server:default:ExtensionHandler",
|
|
54
|
+
"@type": "MyPluginHandler",
|
|
55
|
+
"MyPluginHandler:config": { "@id": "urn:my-plugin:config" }
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
"@id": "urn:my-plugin:config",
|
|
59
|
+
"@type": "MyPluginConfig",
|
|
60
|
+
"MyPluginConfig:enabled": true,
|
|
61
|
+
"MyPluginConfig:apiKey": "@ENV:MY_PLUGIN_API_KEY"
|
|
62
|
+
}
|
|
63
|
+
]
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### 3. Package Structure
|
|
68
|
+
|
|
69
|
+
```
|
|
70
|
+
my-solid-plugin/
|
|
71
|
+
├── package.json
|
|
72
|
+
├── src/
|
|
73
|
+
│ ├── MyPluginHandler.ts
|
|
74
|
+
│ └── index.ts
|
|
75
|
+
├── config/
|
|
76
|
+
│ └── default.json
|
|
77
|
+
└── components/
|
|
78
|
+
└── context.jsonld
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### 4. Package.json Setup
|
|
82
|
+
|
|
83
|
+
```json
|
|
84
|
+
{
|
|
85
|
+
"name": "@myorg/solid-plugin",
|
|
86
|
+
"version": "1.0.0",
|
|
87
|
+
"main": "dist/index.js",
|
|
88
|
+
"types": "dist/index.d.ts",
|
|
89
|
+
"lsd:module": true,
|
|
90
|
+
"lsd:components": "components/components.jsonld",
|
|
91
|
+
"lsd:contexts": {
|
|
92
|
+
"https://linkedsoftwaredependencies.org/bundles/npm/@myorg/solid-plugin/^1.0.0/components/context.jsonld": "components/context.jsonld"
|
|
93
|
+
},
|
|
94
|
+
"peerDependencies": {
|
|
95
|
+
"@solid/community-server": "^7.0.0"
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### 5. User Installation
|
|
101
|
+
|
|
102
|
+
Users install both CSS and your plugin:
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
npm install @solid/community-server
|
|
106
|
+
npm install @myorg/solid-plugin
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### 6. User Configuration
|
|
110
|
+
|
|
111
|
+
Users run CSS with your plugin config:
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
npx community-solid-server \
|
|
115
|
+
-c @css:config/file.json \
|
|
116
|
+
-c @myorg/solid-plugin:config/default.json \
|
|
117
|
+
-f data/ -p 3000
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Or create a combined config file:
|
|
121
|
+
|
|
122
|
+
```json
|
|
123
|
+
{
|
|
124
|
+
"@context": "https://linkedsoftwaredependencies.org/bundles/npm/@solid/community-server/^7.0.0/components/context.jsonld",
|
|
125
|
+
"import": [
|
|
126
|
+
"css:config/file.json",
|
|
127
|
+
"@myorg/solid-plugin:config/default.json"
|
|
128
|
+
]
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## Key Points
|
|
133
|
+
|
|
134
|
+
### The Extension Point
|
|
135
|
+
|
|
136
|
+
**URN**: `urn:solid-server:default:ExtensionHandler`
|
|
137
|
+
|
|
138
|
+
**Interface**: `OperationHandler`
|
|
139
|
+
|
|
140
|
+
**Position**: First in the handler chain (runs before GET, POST, PUT, etc.)
|
|
141
|
+
|
|
142
|
+
**Behavior**: Your handler is called for EVERY operation. If you don't handle it, throw `NotFoundHttpError` to pass to the next handler.
|
|
143
|
+
|
|
144
|
+
### Handler Chain Flow
|
|
145
|
+
|
|
146
|
+
```
|
|
147
|
+
Request → ExtensionHandler (your plugin) → GET/POST/PUT/etc handlers → Response
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
If your handler throws `NotFoundHttpError`, the request continues to standard handlers.
|
|
151
|
+
|
|
152
|
+
If your handler returns a `ResponseDescription`, the request is complete.
|
|
153
|
+
|
|
154
|
+
### What You Can Do
|
|
155
|
+
|
|
156
|
+
- **Content moderation**: Scan uploads before they're stored
|
|
157
|
+
- **Rate limiting**: Track and limit requests per user
|
|
158
|
+
- **Virus scanning**: Check files for malware
|
|
159
|
+
- **Custom validation**: Enforce business rules
|
|
160
|
+
- **Analytics**: Log operations for analysis
|
|
161
|
+
- **Webhooks**: Notify external services
|
|
162
|
+
- **Data transformation**: Modify data before storage
|
|
163
|
+
|
|
164
|
+
### What You Cannot Do
|
|
165
|
+
|
|
166
|
+
- Override core CSS components (GET/POST/PUT handlers, ResourceStore, etc.)
|
|
167
|
+
- Change the handler chain order
|
|
168
|
+
- Remove the extension point
|
|
169
|
+
|
|
170
|
+
## Example: Content Moderation Plugin
|
|
171
|
+
|
|
172
|
+
```typescript
|
|
173
|
+
export class ModerationHandler extends OperationHandler {
|
|
174
|
+
private readonly moderationClient: ModerationClient;
|
|
175
|
+
|
|
176
|
+
public constructor(moderationClient: ModerationClient) {
|
|
177
|
+
super();
|
|
178
|
+
this.moderationClient = moderationClient;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
public async handle({ operation }: OperationHandlerInput): Promise<ResponseDescription> {
|
|
182
|
+
// Only moderate POST and PUT operations with content
|
|
183
|
+
if ((operation.method === 'POST' || operation.method === 'PUT') && operation.body) {
|
|
184
|
+
const result = await this.moderationClient.scan(operation.body);
|
|
185
|
+
|
|
186
|
+
if (result.isInappropriate) {
|
|
187
|
+
throw new ForbiddenHttpError(`Content blocked: ${result.reason}`);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// Pass to next handler
|
|
192
|
+
throw new NotFoundHttpError();
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
## Testing Your Plugin
|
|
198
|
+
|
|
199
|
+
1. Install CSS and your plugin locally
|
|
200
|
+
2. Create a test config that uses your plugin
|
|
201
|
+
3. Start the server: `npm start -- -c test-config.json -f data/ -p 3000`
|
|
202
|
+
4. Test operations: `curl -X POST http://localhost:3000/test -d "data"`
|
|
203
|
+
5. Verify your handler is called and behaves correctly
|
|
204
|
+
|
|
205
|
+
## Reference Implementation
|
|
206
|
+
|
|
207
|
+
See `@solid/access-token-verifier` for a complete example of a CSS plugin package.
|
|
208
|
+
|
|
209
|
+
## Support
|
|
210
|
+
|
|
211
|
+
- CSS Documentation: https://communitysolidserver.github.io/CommunitySolidServer/
|
|
212
|
+
- Components.js: https://componentsjs.readthedocs.io/
|
|
213
|
+
- CSS Discussions: https://github.com/CommunitySolidServer/CommunitySolidServer/discussions
|
package/README.md
CHANGED
|
@@ -1,11 +1,16 @@
|
|
|
1
|
-
# @solid
|
|
1
|
+
# @kkuffour/solid-moderation-plugin
|
|
2
2
|
|
|
3
3
|
Content moderation plugin for Community Solid Server using SightEngine API.
|
|
4
4
|
|
|
5
|
+
## Status
|
|
6
|
+
|
|
7
|
+
✅ **Functional** - Uses CSS ExtensionHandler pattern (v0.3.0+)
|
|
8
|
+
|
|
5
9
|
## Installation
|
|
6
10
|
|
|
7
11
|
```bash
|
|
8
|
-
npm install @solid/
|
|
12
|
+
npm install @solid/community-server
|
|
13
|
+
npm install @kkuffour/solid-moderation-plugin
|
|
9
14
|
```
|
|
10
15
|
|
|
11
16
|
## Configuration
|
|
@@ -13,41 +18,33 @@ npm install @solid/moderation-plugin
|
|
|
13
18
|
Set environment variables:
|
|
14
19
|
|
|
15
20
|
```bash
|
|
16
|
-
export SIGHTENGINE_API_USER=your_api_user
|
|
17
|
-
export SIGHTENGINE_API_SECRET=your_api_secret
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
Create a configuration file that imports the plugin:
|
|
21
|
-
|
|
22
|
-
```json
|
|
23
|
-
{
|
|
24
|
-
"@context": "https://linkedsoftwaredependencies.org/bundles/npm/@solid/community-server/^7.0.0/components/context.jsonld",
|
|
25
|
-
"import": [
|
|
26
|
-
"css:config/file.json",
|
|
27
|
-
"@solid/moderation-plugin:config/default.json"
|
|
28
|
-
]
|
|
29
|
-
}
|
|
21
|
+
export SIGHTENGINE_API_USER="your_api_user"
|
|
22
|
+
export SIGHTENGINE_API_SECRET="your_api_secret"
|
|
30
23
|
```
|
|
31
24
|
|
|
32
|
-
|
|
25
|
+
Run CSS with the plugin:
|
|
33
26
|
|
|
34
27
|
```bash
|
|
35
|
-
npx
|
|
28
|
+
npx community-solid-server \
|
|
29
|
+
-c @css:config/file.json \
|
|
30
|
+
-c @kkuffour/solid-moderation-plugin:config/default.json \
|
|
31
|
+
-f data/ -p 3000
|
|
36
32
|
```
|
|
37
33
|
|
|
38
|
-
##
|
|
34
|
+
## How It Works
|
|
35
|
+
|
|
36
|
+
The plugin uses CSS's `ExtensionHandler` pattern to intercept POST/PUT/PATCH operations before they reach storage:
|
|
39
37
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
- Audit logging
|
|
45
|
-
- Fail-open policy (allows content if API fails)
|
|
38
|
+
1. Handler runs first in the operation chain
|
|
39
|
+
2. Moderates image/video/text content using SightEngine API
|
|
40
|
+
3. Blocks inappropriate content with 403 Forbidden
|
|
41
|
+
4. Passes approved content to standard handlers
|
|
46
42
|
|
|
47
|
-
##
|
|
43
|
+
## Components
|
|
48
44
|
|
|
49
|
-
|
|
45
|
+
- `ModerationHandler` - OperationHandler that moderates POST/PUT/PATCH operations
|
|
46
|
+
- `SightEngineProvider` - SightEngine API client
|
|
50
47
|
|
|
51
48
|
## License
|
|
52
49
|
|
|
53
|
-
MIT
|
|
50
|
+
MIT
|
|
@@ -1,250 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"@context": [
|
|
3
|
-
"https://linkedsoftwaredependencies.org/bundles/npm/
|
|
3
|
+
"https://linkedsoftwaredependencies.org/bundles/npm/@solid/community-server/^7.0.0/components/context.jsonld",
|
|
4
4
|
{
|
|
5
|
-
"
|
|
6
|
-
|
|
7
|
-
"
|
|
8
|
-
|
|
9
|
-
"@prefix": true,
|
|
10
|
-
"@context": {
|
|
11
|
-
"enabled": {
|
|
12
|
-
"@id": "ksmp:dist/ModerationOperationHandler.jsonld#ModerationOperationHandler_enabled"
|
|
13
|
-
},
|
|
14
|
-
"auditLoggingEnabled": {
|
|
15
|
-
"@id": "ksmp:dist/ModerationOperationHandler.jsonld#ModerationOperationHandler_auditLoggingEnabled"
|
|
16
|
-
},
|
|
17
|
-
"auditLoggingStorePath": {
|
|
18
|
-
"@id": "ksmp:dist/ModerationOperationHandler.jsonld#ModerationOperationHandler_auditLoggingStorePath"
|
|
19
|
-
},
|
|
20
|
-
"sightEngineApiUser": {
|
|
21
|
-
"@id": "ksmp:dist/ModerationOperationHandler.jsonld#ModerationOperationHandler_sightEngineApiUser"
|
|
22
|
-
},
|
|
23
|
-
"sightEngineApiSecret": {
|
|
24
|
-
"@id": "ksmp:dist/ModerationOperationHandler.jsonld#ModerationOperationHandler_sightEngineApiSecret"
|
|
25
|
-
},
|
|
26
|
-
"imagesEnabled": {
|
|
27
|
-
"@id": "ksmp:dist/ModerationOperationHandler.jsonld#ModerationOperationHandler_imagesEnabled"
|
|
28
|
-
},
|
|
29
|
-
"textEnabled": {
|
|
30
|
-
"@id": "ksmp:dist/ModerationOperationHandler.jsonld#ModerationOperationHandler_textEnabled"
|
|
31
|
-
},
|
|
32
|
-
"videoEnabled": {
|
|
33
|
-
"@id": "ksmp:dist/ModerationOperationHandler.jsonld#ModerationOperationHandler_videoEnabled"
|
|
34
|
-
},
|
|
35
|
-
"imageNudityThreshold": {
|
|
36
|
-
"@id": "ksmp:dist/ModerationOperationHandler.jsonld#ModerationOperationHandler_imageNudityThreshold"
|
|
37
|
-
},
|
|
38
|
-
"textSexualThreshold": {
|
|
39
|
-
"@id": "ksmp:dist/ModerationOperationHandler.jsonld#ModerationOperationHandler_textSexualThreshold"
|
|
40
|
-
},
|
|
41
|
-
"textToxicThreshold": {
|
|
42
|
-
"@id": "ksmp:dist/ModerationOperationHandler.jsonld#ModerationOperationHandler_textToxicThreshold"
|
|
43
|
-
},
|
|
44
|
-
"videoNudityThreshold": {
|
|
45
|
-
"@id": "ksmp:dist/ModerationOperationHandler.jsonld#ModerationOperationHandler_videoNudityThreshold"
|
|
46
|
-
},
|
|
47
|
-
"source": {
|
|
48
|
-
"@id": "ksmp:dist/ModerationOperationHandler.jsonld#ModerationOperationHandler_source"
|
|
49
|
-
},
|
|
50
|
-
"": {
|
|
51
|
-
"@id": "ksmp:dist/ModerationOperationHandler.jsonld#ModerationOperationHandler_enabled"
|
|
52
|
-
},
|
|
53
|
-
"ggingEnabled": {
|
|
54
|
-
"@id": "ksmp:dist/ModerationOperationHandler.jsonld#ModerationOperationHandler_auditLoggingEnabled"
|
|
55
|
-
},
|
|
56
|
-
"ggingStorePath": {
|
|
57
|
-
"@id": "ksmp:dist/ModerationOperationHandler.jsonld#ModerationOperationHandler_auditLoggingStorePath"
|
|
58
|
-
},
|
|
59
|
-
"gineApiUser": {
|
|
60
|
-
"@id": "ksmp:dist/ModerationOperationHandler.jsonld#ModerationOperationHandler_sightEngineApiUser"
|
|
61
|
-
},
|
|
62
|
-
"gineApiSecret": {
|
|
63
|
-
"@id": "ksmp:dist/ModerationOperationHandler.jsonld#ModerationOperationHandler_sightEngineApiSecret"
|
|
64
|
-
},
|
|
65
|
-
"nabled": {
|
|
66
|
-
"@id": "ksmp:dist/ModerationOperationHandler.jsonld#ModerationOperationHandler_imagesEnabled"
|
|
67
|
-
},
|
|
68
|
-
"bled": {
|
|
69
|
-
"@id": "ksmp:dist/ModerationOperationHandler.jsonld#ModerationOperationHandler_textEnabled"
|
|
70
|
-
},
|
|
71
|
-
"abled": {
|
|
72
|
-
"@id": "ksmp:dist/ModerationOperationHandler.jsonld#ModerationOperationHandler_videoEnabled"
|
|
73
|
-
},
|
|
74
|
-
"dityThreshold": {
|
|
75
|
-
"@id": "ksmp:dist/ModerationOperationHandler.jsonld#ModerationOperationHandler_videoNudityThreshold"
|
|
76
|
-
},
|
|
77
|
-
"ualThreshold": {
|
|
78
|
-
"@id": "ksmp:dist/ModerationOperationHandler.jsonld#ModerationOperationHandler_textSexualThreshold"
|
|
79
|
-
},
|
|
80
|
-
"icThreshold": {
|
|
81
|
-
"@id": "ksmp:dist/ModerationOperationHandler.jsonld#ModerationOperationHandler_textToxicThreshold"
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
},
|
|
85
|
-
"ModerationResourceStore": {
|
|
86
|
-
"@id": "ksmp:dist/ModerationResourceStore.jsonld#ModerationResourceStore",
|
|
87
|
-
"@prefix": true,
|
|
88
|
-
"@context": {
|
|
89
|
-
"enabled": {
|
|
90
|
-
"@id": "ksmp:dist/ModerationResourceStore.jsonld#ModerationResourceStore_enabled"
|
|
91
|
-
},
|
|
92
|
-
"imageNudityThreshold": {
|
|
93
|
-
"@id": "ksmp:dist/ModerationResourceStore.jsonld#ModerationResourceStore_imageNudityThreshold"
|
|
94
|
-
},
|
|
95
|
-
"textSexualThreshold": {
|
|
96
|
-
"@id": "ksmp:dist/ModerationResourceStore.jsonld#ModerationResourceStore_textSexualThreshold"
|
|
97
|
-
},
|
|
98
|
-
"textToxicThreshold": {
|
|
99
|
-
"@id": "ksmp:dist/ModerationResourceStore.jsonld#ModerationResourceStore_textToxicThreshold"
|
|
100
|
-
},
|
|
101
|
-
"videoNudityThreshold": {
|
|
102
|
-
"@id": "ksmp:dist/ModerationResourceStore.jsonld#ModerationResourceStore_videoNudityThreshold"
|
|
103
|
-
},
|
|
104
|
-
"client": {
|
|
105
|
-
"@id": "ksmp:dist/ModerationResourceStore.jsonld#ModerationResourceStore_client"
|
|
106
|
-
},
|
|
107
|
-
"source": {
|
|
108
|
-
"@id": "ksmp:dist/ModerationResourceStore.jsonld#ModerationResourceStore_source"
|
|
109
|
-
},
|
|
110
|
-
"": {
|
|
111
|
-
"@id": "ksmp:dist/ModerationResourceStore.jsonld#ModerationResourceStore_enabled"
|
|
112
|
-
},
|
|
113
|
-
"dityThreshold": {
|
|
114
|
-
"@id": "ksmp:dist/ModerationResourceStore.jsonld#ModerationResourceStore_videoNudityThreshold"
|
|
115
|
-
},
|
|
116
|
-
"ualThreshold": {
|
|
117
|
-
"@id": "ksmp:dist/ModerationResourceStore.jsonld#ModerationResourceStore_textSexualThreshold"
|
|
118
|
-
},
|
|
119
|
-
"icThreshold": {
|
|
120
|
-
"@id": "ksmp:dist/ModerationResourceStore.jsonld#ModerationResourceStore_textToxicThreshold"
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
},
|
|
124
|
-
"ModerationConfig": {
|
|
125
|
-
"@id": "ksmp:dist/ModerationConfig.jsonld#ModerationConfig",
|
|
126
|
-
"@prefix": true,
|
|
127
|
-
"@context": {}
|
|
128
|
-
},
|
|
129
|
-
"ModerationStore": {
|
|
130
|
-
"@id": "ksmp:dist/ModerationStore.jsonld#ModerationStore",
|
|
131
|
-
"@prefix": true,
|
|
132
|
-
"@context": {
|
|
133
|
-
"storePath": {
|
|
134
|
-
"@id": "ksmp:dist/ModerationStore.jsonld#ModerationStore_storePath"
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
},
|
|
138
|
-
"ModerationRecord": {
|
|
139
|
-
"@id": "ksmp:dist/ModerationRecord.jsonld#ModerationRecord",
|
|
140
|
-
"@prefix": true,
|
|
141
|
-
"@context": {}
|
|
142
|
-
},
|
|
143
|
-
"ModerationMixin": {
|
|
144
|
-
"@id": "ksmp:dist/ModerationMixin.jsonld#ModerationMixin",
|
|
145
|
-
"@prefix": true,
|
|
146
|
-
"@context": {
|
|
147
|
-
"moderationConfig_enabled": {
|
|
148
|
-
"@id": "ksmp:dist/ModerationMixin.jsonld#ModerationMixin_moderationConfig_enabled"
|
|
149
|
-
},
|
|
150
|
-
"moderationConfig_auditLoggingEnabled": {
|
|
151
|
-
"@id": "ksmp:dist/ModerationMixin.jsonld#ModerationMixin_moderationConfig_auditLoggingEnabled"
|
|
152
|
-
},
|
|
153
|
-
"moderationConfig_auditLoggingStorePath": {
|
|
154
|
-
"@id": "ksmp:dist/ModerationMixin.jsonld#ModerationMixin_moderationConfig_auditLoggingStorePath"
|
|
155
|
-
},
|
|
156
|
-
"moderationConfig_sightEngineApiUser": {
|
|
157
|
-
"@id": "ksmp:dist/ModerationMixin.jsonld#ModerationMixin_moderationConfig_sightEngineApiUser"
|
|
158
|
-
},
|
|
159
|
-
"moderationConfig_sightEngineApiSecret": {
|
|
160
|
-
"@id": "ksmp:dist/ModerationMixin.jsonld#ModerationMixin_moderationConfig_sightEngineApiSecret"
|
|
161
|
-
},
|
|
162
|
-
"moderationConfig_imagesEnabled": {
|
|
163
|
-
"@id": "ksmp:dist/ModerationMixin.jsonld#ModerationMixin_moderationConfig_imagesEnabled"
|
|
164
|
-
},
|
|
165
|
-
"moderationConfig_textEnabled": {
|
|
166
|
-
"@id": "ksmp:dist/ModerationMixin.jsonld#ModerationMixin_moderationConfig_textEnabled"
|
|
167
|
-
},
|
|
168
|
-
"moderationConfig_videoEnabled": {
|
|
169
|
-
"@id": "ksmp:dist/ModerationMixin.jsonld#ModerationMixin_moderationConfig_videoEnabled"
|
|
170
|
-
},
|
|
171
|
-
"moderationConfig_imageNudityThreshold": {
|
|
172
|
-
"@id": "ksmp:dist/ModerationMixin.jsonld#ModerationMixin_moderationConfig_imageNudityThreshold"
|
|
173
|
-
},
|
|
174
|
-
"moderationConfig_textSexualThreshold": {
|
|
175
|
-
"@id": "ksmp:dist/ModerationMixin.jsonld#ModerationMixin_moderationConfig_textSexualThreshold"
|
|
176
|
-
},
|
|
177
|
-
"moderationConfig_textToxicThreshold": {
|
|
178
|
-
"@id": "ksmp:dist/ModerationMixin.jsonld#ModerationMixin_moderationConfig_textToxicThreshold"
|
|
179
|
-
},
|
|
180
|
-
"moderationConfig_videoNudityThreshold": {
|
|
181
|
-
"@id": "ksmp:dist/ModerationMixin.jsonld#ModerationMixin_moderationConfig_videoNudityThreshold"
|
|
182
|
-
},
|
|
183
|
-
"enabled": {
|
|
184
|
-
"@id": "ksmp:dist/ModerationMixin.jsonld#ModerationMixin_moderationConfig_enabled"
|
|
185
|
-
},
|
|
186
|
-
"auditLoggingEnabled": {
|
|
187
|
-
"@id": "ksmp:dist/ModerationMixin.jsonld#ModerationMixin_moderationConfig_auditLoggingEnabled"
|
|
188
|
-
},
|
|
189
|
-
"auditLoggingStorePath": {
|
|
190
|
-
"@id": "ksmp:dist/ModerationMixin.jsonld#ModerationMixin_moderationConfig_auditLoggingStorePath"
|
|
191
|
-
},
|
|
192
|
-
"sightEngineApiUser": {
|
|
193
|
-
"@id": "ksmp:dist/ModerationMixin.jsonld#ModerationMixin_moderationConfig_sightEngineApiUser"
|
|
194
|
-
},
|
|
195
|
-
"sightEngineApiSecret": {
|
|
196
|
-
"@id": "ksmp:dist/ModerationMixin.jsonld#ModerationMixin_moderationConfig_sightEngineApiSecret"
|
|
197
|
-
},
|
|
198
|
-
"imagesEnabled": {
|
|
199
|
-
"@id": "ksmp:dist/ModerationMixin.jsonld#ModerationMixin_moderationConfig_imagesEnabled"
|
|
200
|
-
},
|
|
201
|
-
"textEnabled": {
|
|
202
|
-
"@id": "ksmp:dist/ModerationMixin.jsonld#ModerationMixin_moderationConfig_textEnabled"
|
|
203
|
-
},
|
|
204
|
-
"videoEnabled": {
|
|
205
|
-
"@id": "ksmp:dist/ModerationMixin.jsonld#ModerationMixin_moderationConfig_videoEnabled"
|
|
206
|
-
},
|
|
207
|
-
"imageNudityThreshold": {
|
|
208
|
-
"@id": "ksmp:dist/ModerationMixin.jsonld#ModerationMixin_moderationConfig_imageNudityThreshold"
|
|
209
|
-
},
|
|
210
|
-
"textSexualThreshold": {
|
|
211
|
-
"@id": "ksmp:dist/ModerationMixin.jsonld#ModerationMixin_moderationConfig_textSexualThreshold"
|
|
212
|
-
},
|
|
213
|
-
"textToxicThreshold": {
|
|
214
|
-
"@id": "ksmp:dist/ModerationMixin.jsonld#ModerationMixin_moderationConfig_textToxicThreshold"
|
|
215
|
-
},
|
|
216
|
-
"videoNudityThreshold": {
|
|
217
|
-
"@id": "ksmp:dist/ModerationMixin.jsonld#ModerationMixin_moderationConfig_videoNudityThreshold"
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
},
|
|
221
|
-
"SightEngineProvider": {
|
|
222
|
-
"@id": "ksmp:dist/providers/SightEngineProvider.jsonld#SightEngineProvider",
|
|
223
|
-
"@prefix": true,
|
|
224
|
-
"@context": {
|
|
225
|
-
"apiUser": {
|
|
226
|
-
"@id": "ksmp:dist/providers/SightEngineProvider.jsonld#SightEngineProvider_apiUser"
|
|
227
|
-
},
|
|
228
|
-
"apiSecret": {
|
|
229
|
-
"@id": "ksmp:dist/providers/SightEngineProvider.jsonld#SightEngineProvider_apiSecret"
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
},
|
|
233
|
-
"SightEngineResult": {
|
|
234
|
-
"@id": "ksmp:dist/providers/SightEngineProvider.jsonld#SightEngineResult",
|
|
235
|
-
"@prefix": true,
|
|
236
|
-
"@context": {}
|
|
237
|
-
},
|
|
238
|
-
"SightEngineTextResult": {
|
|
239
|
-
"@id": "ksmp:dist/providers/SightEngineProvider.jsonld#SightEngineTextResult",
|
|
240
|
-
"@prefix": true,
|
|
241
|
-
"@context": {}
|
|
242
|
-
},
|
|
243
|
-
"SightEngineVideoResult": {
|
|
244
|
-
"@id": "ksmp:dist/providers/SightEngineProvider.jsonld#SightEngineVideoResult",
|
|
245
|
-
"@prefix": true,
|
|
246
|
-
"@context": {}
|
|
247
|
-
}
|
|
5
|
+
"ksmp": "https://linkedsoftwaredependencies.org/bundles/npm/@kkuffour/solid-moderation-plugin/",
|
|
6
|
+
|
|
7
|
+
"ModerationHandler": "ksmp:ModerationHandler",
|
|
8
|
+
"SightEngineProvider": "ksmp:SightEngineProvider"
|
|
248
9
|
}
|
|
249
10
|
]
|
|
250
|
-
}
|
|
11
|
+
}
|
package/config/default.json
CHANGED
|
@@ -1,39 +1,25 @@
|
|
|
1
1
|
{
|
|
2
2
|
"@context": [
|
|
3
3
|
"https://linkedsoftwaredependencies.org/bundles/npm/@solid/community-server/^7.0.0/components/context.jsonld",
|
|
4
|
-
"https://linkedsoftwaredependencies.org/bundles/npm/@kkuffour/solid-moderation-plugin/^0.
|
|
5
|
-
],
|
|
6
|
-
"import": [
|
|
7
|
-
"css:config/file.json"
|
|
4
|
+
"https://linkedsoftwaredependencies.org/bundles/npm/@kkuffour/solid-moderation-plugin/^0.3.0/components/context.jsonld"
|
|
8
5
|
],
|
|
9
6
|
"@graph": [
|
|
10
7
|
{
|
|
11
|
-
"
|
|
12
|
-
"@id": "urn:solid-
|
|
13
|
-
"@type": "
|
|
14
|
-
"
|
|
15
|
-
"
|
|
8
|
+
"comment": "TEST: If you see this in logs, config is loaded",
|
|
9
|
+
"@id": "urn:solid-server:default:ExtensionHandler",
|
|
10
|
+
"@type": "ModerationHandler",
|
|
11
|
+
"ModerationHandler:_client": { "@id": "urn:moderation:SightEngineClient" },
|
|
12
|
+
"ModerationHandler:_enabled": true,
|
|
13
|
+
"ModerationHandler:_imageNudityThreshold": 0.1,
|
|
14
|
+
"ModerationHandler:_textSexualThreshold": 0.1,
|
|
15
|
+
"ModerationHandler:_textToxicThreshold": 0.1,
|
|
16
|
+
"ModerationHandler:_videoNudityThreshold": 0.1
|
|
16
17
|
},
|
|
17
18
|
{
|
|
18
|
-
"@
|
|
19
|
-
"@
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
"auxiliaryStrategy": { "@id": "urn:solid-server:default:AuxiliaryStrategy" },
|
|
23
|
-
"accessor": { "@id": "urn:solid-server:default:DataAccessor" },
|
|
24
|
-
"metadataStrategy": { "@id": "urn:solid-server:default:MetadataStrategy" }
|
|
25
|
-
},
|
|
26
|
-
{
|
|
27
|
-
"@comment": "Moderation wrapper for ResourceStore",
|
|
28
|
-
"@id": "urn:solid-server:default:ResourceStore",
|
|
29
|
-
"@type": "ModerationResourceStore",
|
|
30
|
-
"ModerationResourceStore:_source": { "@id": "urn:solid-server:default:ResourceStore_Original" },
|
|
31
|
-
"ModerationResourceStore:_client": { "@id": "urn:solid-moderation:SightEngineProvider" },
|
|
32
|
-
"ModerationResourceStore:_enabled": true,
|
|
33
|
-
"ModerationResourceStore:_imageNudityThreshold": 0.5,
|
|
34
|
-
"ModerationResourceStore:_textSexualThreshold": 0.5,
|
|
35
|
-
"ModerationResourceStore:_textToxicThreshold": 0.5,
|
|
36
|
-
"ModerationResourceStore:_videoNudityThreshold": 0.5
|
|
19
|
+
"@id": "urn:moderation:SightEngineClient",
|
|
20
|
+
"@type": "SightEngineProvider",
|
|
21
|
+
"SightEngineProvider:_apiUser": "@ENV:SIGHTENGINE_API_USER",
|
|
22
|
+
"SightEngineProvider:_apiSecret": "@ENV:SIGHTENGINE_API_SECRET"
|
|
37
23
|
}
|
|
38
24
|
]
|
|
39
25
|
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { OperationHandler } from '@solid/community-server';
|
|
2
|
+
import type { OperationHandlerInput, ResponseDescription } from '@solid/community-server';
|
|
3
|
+
import type { SightEngineProvider } from './providers/SightEngineProvider';
|
|
4
|
+
export declare class ModerationHandler extends OperationHandler {
|
|
5
|
+
private readonly logger;
|
|
6
|
+
private readonly client;
|
|
7
|
+
private readonly enabled;
|
|
8
|
+
private readonly imageNudityThreshold;
|
|
9
|
+
private readonly textSexualThreshold;
|
|
10
|
+
private readonly textToxicThreshold;
|
|
11
|
+
private readonly videoNudityThreshold;
|
|
12
|
+
constructor(client: SightEngineProvider, enabled: boolean, imageNudityThreshold: number, textSexualThreshold: number, textToxicThreshold: number, videoNudityThreshold: number);
|
|
13
|
+
handle({ operation }: OperationHandlerInput): Promise<ResponseDescription>;
|
|
14
|
+
private shouldModerate;
|
|
15
|
+
private isModeratable;
|
|
16
|
+
private moderateImage;
|
|
17
|
+
private moderateVideo;
|
|
18
|
+
private moderateText;
|
|
19
|
+
private getFileExtension;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=ModerationHandler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ModerationHandler.d.ts","sourceRoot":"","sources":["../src/ModerationHandler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAA0E,MAAM,yBAAyB,CAAC;AACnI,OAAO,KAAK,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAE1F,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AAE3E,qBAAa,iBAAkB,SAAQ,gBAAgB;IACrD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAsB;IAC7C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAsB;IAC7C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAU;IAClC,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAS;IAC9C,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAS;IAC7C,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAS;IAC5C,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAS;gBAG5C,MAAM,EAAE,mBAAmB,EAC3B,OAAO,EAAE,OAAO,EAChB,oBAAoB,EAAE,MAAM,EAC5B,mBAAmB,EAAE,MAAM,EAC3B,kBAAkB,EAAE,MAAM,EAC1B,oBAAoB,EAAE,MAAM;IAejB,MAAM,CAAC,EAAE,SAAS,EAAE,EAAE,qBAAqB,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAwDvF,OAAO,CAAC,cAAc;IAKtB,OAAO,CAAC,aAAa;YAMP,aAAa;YAyBb,aAAa;YAyBb,YAAY;IAyB1B,OAAO,CAAC,gBAAgB;CAWzB"}
|