Skip to content

Commit 67086c2

Browse files
committed
Added script to populate DB with 5k followers
1 parent df358ab commit 67086c2

File tree

4 files changed

+178
-0
lines changed

4 files changed

+178
-0
lines changed

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,12 @@ This has only been tested on MacOS using [Docker for Mac](https://docs.docker.co
6565
- Run `yarn test` to execute tests within a Docker Compose stack.
6666

6767

68+
## Populating the DB
69+
70+
The below command will populate the DB with ~5000 followers for the `activitypub` host
71+
72+
- Run `docker compose run scripts populate-activitypub-db`
73+
6874
 
6975

7076
![Leaderboard](https://github.com/TryGhost/ActivityPub/assets/115641230/371e8f36-8293-43d2-912a-772e56517e1d)

docker-compose.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@ services:
1818
mysql:
1919
condition: service_healthy
2020

21+
scripts:
22+
build: scripts
23+
depends_on:
24+
- activitypub
25+
- fake-mastodon
26+
2127
nginx:
2228
build: nginx
2329
ports:

scripts/Dockerfile

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
FROM debian:latest
2+
3+
RUN apt-get update -y
4+
RUN apt-get install -y curl openssl jq
5+
6+
COPY bin /usr/local/bin

scripts/bin/populate-activitypub-db

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
#!/usr/bin/env bash
2+
3+
activitypub_url="http://activitypub:8080"
4+
user_count=5000
5+
wiremock_only=false
6+
7+
while getopts "u:n:w" opt; do
8+
case ${opt} in
9+
u )
10+
activitypub_url=$OPTARG
11+
;;
12+
n )
13+
user_count=$OPTARG
14+
;;
15+
w )
16+
wiremock_only=true
17+
;;
18+
\? )
19+
echo "Usage: cmd [-u activitypub_url] [-n user_count] [-w]"
20+
exit 1
21+
;;
22+
esac
23+
done
24+
25+
curl -X DELETE http://fake-mastodon:8080/__admin/mappings
26+
27+
curl "${activitypub_url}/.ghost/activitypub/users/index"
28+
29+
if [ ! -f "private.pem" ] || [ ! -f "public.pem" ]; then
30+
openssl genpkey -algorithm RSA -out private.pem -pkeyopt rsa_keygen_bits:2048
31+
openssl rsa -pubout -in private.pem -out public.pem
32+
openssl pkcs8 -topk8 -inform PEM -outform PEM -in private.pem -out private-pkcs8.pem -nocrypt
33+
fi
34+
35+
PUBLIC_PEM=$(cat public.pem)
36+
37+
PUBLIC_PEM_JSON=$(printf '%s' "$PUBLIC_PEM" | jq -aRs .)
38+
39+
curl -X POST http://fake-mastodon:8080/__admin/mappings \
40+
-H "Content-Type: application/json" \
41+
-d '{
42+
"request": {
43+
"method": "POST",
44+
"urlPattern": "/inbox/.*"
45+
},
46+
"response": {
47+
"status": 200
48+
}
49+
}'
50+
51+
curl -X POST http://fake-mastodon:8080/__admin/mappings \
52+
-H "Content-Type: application/json" \
53+
-d '{
54+
"request": {
55+
"method": "GET",
56+
"urlPattern": "/user/.*"
57+
},
58+
"response": {
59+
"status": 200,
60+
"jsonBody": {
61+
"@context": [
62+
"https://www.w3.org/ns/activitystreams",
63+
"https://w3id.org/security/v1",
64+
"https://w3id.org/security/data-integrity/v1",
65+
"https://www.w3.org/ns/did/v1",
66+
"https://w3id.org/security/multikey/v1",
67+
{
68+
"manuallyApprovesFollowers": "as:manuallyApprovesFollowers",
69+
"toot": "http://joinmastodon.org/ns#",
70+
"featured": {
71+
"@id": "toot:featured",
72+
"@type": "@id"
73+
},
74+
"featuredTags": {
75+
"@id": "toot:featuredTags",
76+
"@type": "@id"
77+
},
78+
"discoverable": "toot:discoverable",
79+
"suspended": "toot:suspended",
80+
"memorial": "toot:memorial",
81+
"indexable": "toot:indexable",
82+
"schema": "http://schema.org#",
83+
"PropertyValue": "schema:PropertyValue",
84+
"value": "schema:value"
85+
}
86+
],
87+
"id": "http://fake-mastodon:8080/user/{{request.pathSegments.[1]}}",
88+
"type": "Person",
89+
"inbox": "http://fake-mastodon:8080/inbox/{{request.pathSegments.[1]}}",
90+
"publicKey": {
91+
"id": "http://fake-mastodon:8080/user/{{request.pathSegments.[1]}}#main-key",
92+
"type": "CryptographicKey",
93+
"owner": "http://fake-mastodon:8080/user/{{request.pathSegments.[1]}}",
94+
"publicKeyPem": '"$PUBLIC_PEM_JSON"'
95+
},
96+
"followers": "http://fake-mastodon:8080/followers/{{request.pathSegments.[1]}}",
97+
"following": "http://fake-mastodon:8080/following/{{request.pathSegments.[1]}}",
98+
"icon": {
99+
"type": "Image",
100+
"url": "https://ghost.org/favicon.ico"
101+
},
102+
"liked": "http://fake-mastodon:8080/liked/{{request.pathSegments.[1]}}",
103+
"name": "User {{request.pathSegments.[1]}}",
104+
"outbox": "http://fake-mastodon:8080/outbox/{{request.pathSegments.[1]}}",
105+
"preferredUsername": "{{request.pathSegments.[1]}}",
106+
"summary": "This is a dynamically generated summary for {{request.pathSegments.[1]}}",
107+
"url": "http://fake-mastodon:8080/user/{{request.pathSegments.[1]}}"
108+
},
109+
"headers": {
110+
"Content-Type": "application/activity+json"
111+
}
112+
}
113+
}'
114+
115+
if [ "$wiremock_only" = true ]; then
116+
echo "Wiremock setup only, skipping user creation."
117+
exit 0
118+
fi
119+
120+
# Define variables
121+
PRIVATE_KEY="private.pem"
122+
123+
for i in $(seq 1 $user_count); do
124+
NAME="user$i"
125+
echo "Processing user: $NAME"
126+
127+
KEY_ID="http://fake-mastodon:8080/user/$NAME#main-key"
128+
129+
BODY=$(jq -n --arg name "$NAME" --arg randomId "$RANDOM" '{
130+
"@context": "https://www.w3.org/ns/activitystreams",
131+
"id": "http://fake-mastodon:8080/activity/\($randomId)",
132+
"type": "Follow",
133+
"actor": "http://fake-mastodon:8080/user/\($name)",
134+
"object": "'"${activitypub_url}/.ghost/activitypub/users/index"'",
135+
"to": ["'"${activitypub_url}/.ghost/activitypub/users/index"'"],
136+
"cc": ["http://fake-mastodon:8080/user/\($name)/following"]
137+
}')
138+
139+
DIGEST=$(echo -n "$BODY" | openssl dgst -sha256 -binary | openssl base64)
140+
REQUEST_TARGET="post /.ghost/activitypub/inbox/index"
141+
HOST=$(echo "$activitypub_url" | awk -F/ '{print $3}')
142+
DATE=$(date -R)
143+
SIGN_STRING="(request-target): $REQUEST_TARGET\nhost: $HOST\ndate: $DATE\ndigest: SHA-256=$DIGEST"
144+
145+
SIGNATURE=$(echo -n "$SIGN_STRING" | openssl dgst -sha256 -sign "$PRIVATE_KEY" | openssl base64 -A)
146+
147+
AUTH_HEADER="keyId=\"$KEY_ID\",algorithm=\"rsa-sha256\",headers=\"(request-target) host date digest\",signature=\"$SIGNATURE\""
148+
149+
curl -v -X POST "${activitypub_url}/.ghost/activitypub/inbox/index" \
150+
-H "Host: $HOST" \
151+
-H "Date: $DATE" \
152+
-H "Digest: SHA-256=$DIGEST" \
153+
-H "Signature: $AUTH_HEADER" \
154+
-d "$BODY"
155+
156+
echo "Request sent for user: $NAME"
157+
echo "---------------------------------------------"
158+
done
159+
160+
exit 0

0 commit comments

Comments
 (0)