@evanp/activitypub-bot 0.12.1 → 0.13.1

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.
Files changed (46) hide show
  1. package/lib/app.js +19 -1
  2. package/lib/index.js +2 -0
  3. package/lib/routes/collection.js +83 -67
  4. package/lib/routes/inbox.js +8 -0
  5. package/lib/routes/object.js +25 -5
  6. package/package.json +3 -3
  7. package/.github/dependabot.yml +0 -11
  8. package/.github/workflows/main.yml +0 -34
  9. package/.github/workflows/tag.yml +0 -106
  10. package/.nvmrc +0 -1
  11. package/Dockerfile +0 -17
  12. package/docs/activitypub.bot.drawio +0 -110
  13. package/tests/activitydistributor.test.js +0 -606
  14. package/tests/activityhandler.test.js +0 -2276
  15. package/tests/activitypubclient.test.js +0 -210
  16. package/tests/actorstorage.test.js +0 -283
  17. package/tests/app.test.js +0 -17
  18. package/tests/authorizer.test.js +0 -301
  19. package/tests/bot.donothing.test.js +0 -30
  20. package/tests/bot.ok.test.js +0 -101
  21. package/tests/botcontext.test.js +0 -720
  22. package/tests/botdatastorage.test.js +0 -88
  23. package/tests/botfactory.provincebotfactory.test.js +0 -430
  24. package/tests/digester.test.js +0 -56
  25. package/tests/fixtures/bots.js +0 -27
  26. package/tests/fixtures/eventloggingbot.js +0 -57
  27. package/tests/fixtures/provincebotfactory.js +0 -53
  28. package/tests/httpsignature.test.js +0 -199
  29. package/tests/httpsignatureauthenticator.test.js +0 -463
  30. package/tests/index.test.js +0 -10
  31. package/tests/keystorage.test.js +0 -124
  32. package/tests/microsyntax.test.js +0 -123
  33. package/tests/objectcache.test.js +0 -133
  34. package/tests/objectstorage.test.js +0 -149
  35. package/tests/remotekeystorage.test.js +0 -78
  36. package/tests/routes.actor.test.js +0 -214
  37. package/tests/routes.collection.test.js +0 -433
  38. package/tests/routes.health.test.js +0 -41
  39. package/tests/routes.inbox.test.js +0 -136
  40. package/tests/routes.object.test.js +0 -525
  41. package/tests/routes.server.test.js +0 -69
  42. package/tests/routes.sharedinbox.test.js +0 -473
  43. package/tests/routes.webfinger.test.js +0 -68
  44. package/tests/urlformatter.test.js +0 -164
  45. package/tests/utils/digest.js +0 -7
  46. package/tests/utils/nock.js +0 -499
@@ -1,10 +0,0 @@
1
- import assert from 'node:assert'
2
- import { describe, it } from 'node:test'
3
- describe('package exports', () => {
4
- it('exposes Bot, BotFactory, and makeApp', async () => {
5
- const { Bot, BotFactory, makeApp } = await import('../lib/index.js')
6
- assert.equal(typeof Bot, 'function')
7
- assert.equal(typeof BotFactory, 'function')
8
- assert.equal(typeof makeApp, 'function')
9
- })
10
- })
@@ -1,124 +0,0 @@
1
- import { describe, before, after, it } from 'node:test'
2
- import { KeyStorage } from '../lib/keystorage.js'
3
- import assert from 'node:assert'
4
- import { Sequelize } from 'sequelize'
5
- import Logger from 'pino'
6
- import { runMigrations } from '../lib/migrations/index.js'
7
-
8
- describe('KeyStorage', async () => {
9
- let connection = null
10
- let storage = null
11
- let logger = null
12
- let firstPublicKey = null
13
- let firstPrivateKey = null
14
- let secondPublicKey = null
15
- let secondPrivateKey = null
16
- let firstSystemPublicKey = null
17
- let firstSystemPrivateKey = null
18
- let secondSystemPublicKey = null
19
- let secondSystemPrivateKey = null
20
- before(async () => {
21
- connection = new Sequelize({ dialect: 'sqlite', storage: ':memory:', logging: false })
22
- await connection.authenticate()
23
- await runMigrations(connection)
24
- logger = new Logger({
25
- level: 'silent'
26
- })
27
- })
28
- after(async () => {
29
- await connection.close()
30
- connection = null
31
- logger = null
32
- })
33
- it('can initialize', async () => {
34
- storage = new KeyStorage(connection, logger)
35
- })
36
- it('can get a public key', async () => {
37
- firstPublicKey = await storage.getPublicKey('test1')
38
- assert.ok(firstPublicKey)
39
- assert.equal(typeof firstPublicKey, 'string')
40
- assert.match(firstPublicKey, /^-----BEGIN PUBLIC KEY-----\n/)
41
- assert.match(firstPublicKey, /-----END PUBLIC KEY-----\n$/)
42
- })
43
- it('can get a public key again', async () => {
44
- secondPublicKey = await storage.getPublicKey('test1')
45
- assert.ok(secondPublicKey)
46
- assert.equal(typeof secondPublicKey, 'string')
47
- assert.match(secondPublicKey, /^-----BEGIN PUBLIC KEY-----\n/)
48
- assert.match(secondPublicKey, /-----END PUBLIC KEY-----\n$/)
49
- assert.equal(firstPublicKey, secondPublicKey)
50
- })
51
- it('can get a private key after getting a public key', async () => {
52
- const privateKey = await storage.getPrivateKey('test1')
53
- assert.ok(privateKey)
54
- assert.equal(typeof privateKey, 'string')
55
- assert.match(privateKey, /^-----BEGIN PRIVATE KEY-----\n/)
56
- assert.match(privateKey, /-----END PRIVATE KEY-----\n$/)
57
- })
58
- it('can get a private key', async () => {
59
- firstPrivateKey = await storage.getPrivateKey('test2')
60
- assert.ok(firstPrivateKey)
61
- assert.equal(typeof firstPrivateKey, 'string')
62
- assert.match(firstPrivateKey, /^-----BEGIN PRIVATE KEY-----\n/)
63
- assert.match(firstPrivateKey, /-----END PRIVATE KEY-----\n$/)
64
- })
65
- it('can get a private key again', async () => {
66
- secondPrivateKey = await storage.getPrivateKey('test2')
67
- assert.ok(secondPrivateKey)
68
- assert.equal(typeof secondPrivateKey, 'string')
69
- assert.match(secondPrivateKey, /^-----BEGIN PRIVATE KEY-----\n/)
70
- assert.match(secondPrivateKey, /-----END PRIVATE KEY-----\n$/)
71
- assert.equal(firstPrivateKey, secondPrivateKey)
72
- })
73
- it('can get a public key after getting a private key', async () => {
74
- const publicKey = await storage.getPublicKey('test2')
75
- assert.ok(publicKey)
76
- assert.equal(typeof publicKey, 'string')
77
- assert.match(publicKey, /^-----BEGIN PUBLIC KEY-----\n/)
78
- assert.match(publicKey, /-----END PUBLIC KEY-----\n$/)
79
- })
80
- it('can get distinct public keys for distinct bots', async () => {
81
- const publicKey = await storage.getPublicKey('test1')
82
- const publicKey2 = await storage.getPublicKey('test2')
83
- assert.ok(publicKey)
84
- assert.ok(publicKey2)
85
- assert.notEqual(publicKey, publicKey2)
86
- })
87
- it('can get distinct private keys for distinct bots', async () => {
88
- const privateKey = await storage.getPrivateKey('test1')
89
- const privateKey2 = await storage.getPrivateKey('test2')
90
- assert.ok(privateKey)
91
- assert.ok(privateKey2)
92
- assert.notEqual(privateKey, privateKey2)
93
- })
94
- it('can get a system public key', async () => {
95
- firstSystemPublicKey = await storage.getPublicKey(null)
96
- assert.ok(firstSystemPublicKey)
97
- assert.equal(typeof firstSystemPublicKey, 'string')
98
- assert.match(firstSystemPublicKey, /^-----BEGIN PUBLIC KEY-----\n/)
99
- assert.match(firstSystemPublicKey, /-----END PUBLIC KEY-----\n$/)
100
- })
101
- it('can get a system public key again', async () => {
102
- secondSystemPublicKey = await storage.getPublicKey(null)
103
- assert.ok(secondSystemPublicKey)
104
- assert.equal(typeof secondSystemPublicKey, 'string')
105
- assert.match(secondSystemPublicKey, /^-----BEGIN PUBLIC KEY-----\n/)
106
- assert.match(secondSystemPublicKey, /-----END PUBLIC KEY-----\n$/)
107
- assert.equal(firstSystemPublicKey, secondSystemPublicKey)
108
- })
109
- it('can get a system private key', async () => {
110
- firstSystemPrivateKey = await storage.getPrivateKey(null)
111
- assert.ok(firstSystemPrivateKey)
112
- assert.equal(typeof firstSystemPrivateKey, 'string')
113
- assert.match(firstSystemPrivateKey, /^-----BEGIN PRIVATE KEY-----\n/)
114
- assert.match(firstSystemPrivateKey, /-----END PRIVATE KEY-----\n$/)
115
- })
116
- it('can get a system private key again', async () => {
117
- secondSystemPrivateKey = await storage.getPrivateKey(null)
118
- assert.ok(secondSystemPrivateKey)
119
- assert.equal(typeof secondSystemPrivateKey, 'string')
120
- assert.match(secondSystemPrivateKey, /^-----BEGIN PRIVATE KEY-----\n/)
121
- assert.match(secondSystemPrivateKey, /-----END PRIVATE KEY-----\n$/)
122
- assert.equal(firstSystemPrivateKey, secondSystemPrivateKey)
123
- })
124
- })
@@ -1,123 +0,0 @@
1
- import { describe, it } from 'node:test'
2
- import assert from 'node:assert'
3
- import { Sequelize } from 'sequelize'
4
- import { Transformer } from '../lib/microsyntax.js'
5
- import { UrlFormatter } from '../lib/urlformatter.js'
6
- import { KeyStorage } from '../lib/keystorage.js'
7
- import { ActivityPubClient } from '../lib/activitypubclient.js'
8
- import { nockSetup } from './utils/nock.js'
9
- import { HTTPSignature } from '../lib/httpsignature.js'
10
- import Logger from 'pino'
11
- import { Digester } from '../lib/digester.js'
12
- import { runMigrations } from '../lib/migrations/index.js'
13
-
14
- const AS2 = 'https://www.w3.org/ns/activitystreams#'
15
-
16
- describe('microsyntax', async () => {
17
- const tagNamespace = 'https://tags.example/tag/'
18
- const origin = 'https://activitypubbot.example'
19
-
20
- nockSetup('social.example')
21
-
22
- const logger = Logger({
23
- level: 'silent'
24
- })
25
- const digester = new Digester(logger)
26
- const connection = new Sequelize({ dialect: 'sqlite', storage: ':memory:', logging: false })
27
- await connection.authenticate()
28
- await runMigrations(connection)
29
- const keyStorage = new KeyStorage(connection, logger)
30
- const formatter = new UrlFormatter(origin)
31
- const signer = new HTTPSignature(logger)
32
- const client = new ActivityPubClient(keyStorage, formatter, signer, digester, logger)
33
- const transformer = new Transformer(tagNamespace, client)
34
-
35
- it('has transformer', () => {
36
- assert.ok(transformer)
37
- })
38
-
39
- describe('transform tagless text', async () => {
40
- const text = 'Hello, world!'
41
- const { html } = await transformer.transform(text)
42
- it('has output', () => {
43
- assert.ok(html)
44
- })
45
- it('is the same as input', () => {
46
- assert.equal(html, `<p>${text}</p>`)
47
- })
48
- })
49
-
50
- describe('transform hashtag', async () => {
51
- const text = 'Hello, World! #greeting'
52
- const { html, tag } = await transformer.transform(text)
53
- it('has html output', () => {
54
- assert.ok(html)
55
- })
56
- it('has tag', () => {
57
- assert.ok(tag)
58
- })
59
- it('has correct html', () => {
60
- assert.equal(html, '<p>Hello, World! <a href="https://tags.example/tag/greeting">#greeting</a></p>')
61
- })
62
- it('has correct tag', () => {
63
- assert.equal(tag.length, 1)
64
- assert.equal(tag[0].type, AS2 + 'Hashtag')
65
- assert.equal(tag[0].name, '#greeting')
66
- assert.equal(tag[0].href, 'https://tags.example/tag/greeting')
67
- })
68
- })
69
-
70
- describe('transform url', async () => {
71
- const text = 'Please visit https://example.com for more information.'
72
- const { html, tag } = await transformer.transform(text)
73
- it('has html output', () => {
74
- assert.ok(html)
75
- })
76
- it('has tag', () => {
77
- assert.ok(tag)
78
- })
79
- it('has correct html', () => {
80
- assert.equal(html, '<p>Please visit <a href="https://example.com">https://example.com</a> for more information.</p>')
81
- })
82
- it('has correct tag', () => {
83
- assert.equal(tag.length, 0)
84
- })
85
- })
86
-
87
- describe('transform url with fragment', async () => {
88
- const text = 'Please visit https://example.com#fragment for more information.'
89
- const { html, tag } = await transformer.transform(text)
90
- it('has html output', () => {
91
- assert.ok(html)
92
- })
93
- it('has tag', () => {
94
- assert.ok(tag)
95
- })
96
- it('has correct html', () => {
97
- assert.equal(html, '<p>Please visit <a href="https://example.com#fragment">https://example.com#fragment</a> for more information.</p>')
98
- })
99
- it('has correct tag', () => {
100
- assert.equal(tag.length, 0)
101
- })
102
- })
103
-
104
- describe('transform full mention', async () => {
105
- const text = 'Hello, @world@social.example !'
106
- const { html, tag } = await transformer.transform(text)
107
- it('has html output', () => {
108
- assert.ok(html)
109
- })
110
- it('has tag', () => {
111
- assert.ok(tag)
112
- })
113
- it('has correct html', () => {
114
- assert.equal(html, '<p>Hello, <a href="https://social.example/profile/world">@world@social.example</a> !</p>')
115
- })
116
- it('has correct tag', () => {
117
- assert.equal(tag.length, 1)
118
- assert.equal(tag[0].type, 'Mention')
119
- assert.equal(tag[0].name, '@world@social.example')
120
- assert.equal(tag[0].href, 'https://social.example/profile/world')
121
- })
122
- })
123
- })
@@ -1,133 +0,0 @@
1
- import { describe, it } from 'node:test'
2
- import { ObjectCache } from '../lib/objectcache.js'
3
- import assert from 'node:assert/strict'
4
- import as2 from '../lib/activitystreams.js'
5
-
6
- describe('ObjectCache', async () => {
7
- let cache = null
8
- const longTTL = 3600 * 1000
9
- const shortTTL = 300 * 1000
10
- const maxItems = 1000
11
- const makeObject = (num) =>
12
- as2.import({
13
- id: `https://example.com/${num}`,
14
- name: `Object ${num}`,
15
- type: 'Object',
16
- attributedTo: `https://example.com/user${num}`,
17
- to: 'https://www.w3.org/ns/activitystreams#Public'
18
- })
19
- const makeCollection = (num) =>
20
- as2.import({
21
- id: `https://example.com/collection${num}`,
22
- type: 'Collection',
23
- name: `Collection ${num}`,
24
- totalItems: 1
25
- })
26
-
27
- const object1 = await makeObject(1)
28
- const object2 = await makeObject(2)
29
- const object3 = await makeObject(3)
30
- const object4 = await makeObject(4)
31
- const object5 = await makeObject(5)
32
- const badid = 'https://example.com/badid'
33
- const badcoll = 'https://example.com/badcoll'
34
- const collection1 = await makeCollection(1)
35
- const collection2 = await makeCollection(2)
36
- const collection3 = await makeCollection(3)
37
-
38
- it('should be a class', async () => {
39
- assert.strictEqual(typeof ObjectCache, 'function')
40
- })
41
-
42
- it('can be instantiated', async () => {
43
- cache = new ObjectCache({ longTTL, shortTTL, maxItems })
44
- assert.strictEqual(typeof cache, 'object')
45
- })
46
-
47
- it('can be initialized', async () => {
48
- try {
49
- await cache.initialize()
50
- assert.ok(true)
51
- } catch (error) {
52
- assert.fail(error)
53
- }
54
- })
55
-
56
- it('returns undefined if not found', async () => {
57
- try {
58
- const value = await cache.get(badid)
59
- assert.strictEqual(value, undefined)
60
- } catch (error) {
61
- assert.fail(error)
62
- }
63
- })
64
-
65
- it('can save', async () => {
66
- try {
67
- await cache.save(object1)
68
- const dupe = await cache.get(object1.id)
69
- assert.strictEqual(dupe.id, object1.id)
70
- } catch (error) {
71
- assert.fail(error)
72
- }
73
- })
74
-
75
- it('can saveReceived', async () => {
76
- try {
77
- await cache.saveReceived(object2)
78
- const dupe = await cache.get(object2.id)
79
- assert.strictEqual(dupe.id, object2.id)
80
- } catch (error) {
81
- assert.fail(error)
82
- }
83
- })
84
-
85
- it('can clear', async () => {
86
- try {
87
- await cache.save(object3)
88
- await cache.clear(object3)
89
- const dupe = await cache.get(object3.id)
90
- assert.strictEqual(dupe, undefined)
91
- } catch (error) {
92
- assert.fail(error)
93
- }
94
- })
95
-
96
- it('fails membership for unknown collection', async () => {
97
- try {
98
- const flag = await cache.isMember(collection3, badid)
99
- assert.strictEqual(flag, undefined)
100
- } catch (error) {
101
- assert.fail(error)
102
- }
103
- })
104
-
105
- it('fails membership for unknown object', async () => {
106
- try {
107
- const flag = await cache.isMember(badcoll, object4)
108
- assert.strictEqual(flag, undefined)
109
- } catch (error) {
110
- assert.fail(error)
111
- }
112
- })
113
-
114
- it('can saveMembership', async () => {
115
- try {
116
- await cache.saveMembership(collection1, object4)
117
- const flag = await cache.isMember(collection1, object4)
118
- assert.ok(flag)
119
- } catch (error) {
120
- assert.fail(error)
121
- }
122
- })
123
-
124
- it('can saveMembershipReceived', async () => {
125
- try {
126
- await cache.saveMembershipReceived(collection2, object5)
127
- const flag = await cache.isMember(collection2, object5)
128
- assert.ok(flag)
129
- } catch (error) {
130
- assert.fail(error)
131
- }
132
- })
133
- })
@@ -1,149 +0,0 @@
1
- import { describe, it, before, after } from 'node:test'
2
- import as2 from '../lib/activitystreams.js'
3
- import assert from 'node:assert'
4
- import { ObjectStorage, NoSuchObjectError } from '../lib/objectstorage.js'
5
- import { Sequelize } from 'sequelize'
6
- import { runMigrations } from '../lib/migrations/index.js'
7
-
8
- describe('ObjectStorage', async () => {
9
- let doc = null
10
- let doc2 = null
11
- let doc3 = null
12
- let connection = null
13
- let storage = null
14
- before(async () => {
15
- doc = await as2.import({
16
- '@context': 'https://www.w3.org/ns/activitystreams',
17
- id: 'https://social.example/users/test/note/1',
18
- type: 'Note',
19
- name: 'test',
20
- content: 'test'
21
- })
22
- doc2 = await as2.import({
23
- '@context': 'https://www.w3.org/ns/activitystreams',
24
- id: 'https://social.example/users/test/note/2',
25
- type: 'Note',
26
- name: 'test',
27
- content: 'test',
28
- inReplyTo: doc.id
29
- })
30
- doc3 = await as2.import({
31
- '@context': 'https://www.w3.org/ns/activitystreams',
32
- id: 'https://social.example/users/test/note/3',
33
- type: 'Note',
34
- name: 'test',
35
- content: 'test'
36
- })
37
- connection = new Sequelize({ dialect: 'sqlite', storage: ':memory:', logging: false })
38
- await connection.authenticate()
39
- await runMigrations(connection)
40
- })
41
- after(async () => {
42
- await connection.close()
43
- })
44
- it('can initialize', async () => {
45
- storage = new ObjectStorage(connection)
46
- })
47
- it('can create a new object', async () => {
48
- await storage.create(doc)
49
- })
50
- it('can read a created object', async () => {
51
- await storage.read(doc.id)
52
- })
53
- it('can update a created object', async () => {
54
- const doc2 = await as2.import({
55
- '@context': 'https://www.w3.org/ns/activitystreams',
56
- id: 'https://social.example/users/test/note/1',
57
- type: 'Note',
58
- name: 'test2',
59
- content: 'test2'
60
- })
61
- await storage.update(doc2)
62
- const read = await storage.read(doc2.id)
63
- assert.equal(read.name.get(), 'test2')
64
- })
65
- it('can delete a created object', async () => {
66
- await storage.delete(doc)
67
- try {
68
- await storage.read(doc.id)
69
- assert.fail('should not be able to read deleted object')
70
- } catch (err) {
71
- assert.ok(err instanceof NoSuchObjectError)
72
- }
73
- })
74
- it('can get a collection', async () => {
75
- const collection = await storage.getCollection(doc.id, 'replies')
76
- assert.equal(typeof (collection), 'object')
77
- assert.equal(typeof (collection.id), 'string')
78
- assert.equal(collection.id, `${doc.id}/replies`)
79
- assert.equal(collection.type, 'https://www.w3.org/ns/activitystreams#OrderedCollection')
80
- assert.equal(collection.totalItems, 0)
81
- assert.equal(collection.first.id, `${doc.id}/replies/1`)
82
- assert.equal(collection.last.id, `${doc.id}/replies/1`)
83
- })
84
- it('can get a collection page', async () => {
85
- const page = await storage.getCollectionPage(doc.id, 'replies', 1)
86
- assert.equal(typeof page, 'object')
87
- assert.equal(page.id, `${doc.id}/replies/1`)
88
- assert.equal(page.type, 'https://www.w3.org/ns/activitystreams#OrderedCollectionPage')
89
- assert.equal(page.partOf.id, `${doc.id}/replies`)
90
- assert.ok(!page.next)
91
- assert.ok(!page.prev)
92
- assert.ok(!page.items)
93
- })
94
- it('can add to a collection', async () => {
95
- await storage.addToCollection(doc.id, 'replies', doc2)
96
- const page = await storage.getCollectionPage(doc.id, 'replies', 1)
97
- assert.ok(Array.from(page.items).find(item => item.id === doc2.id))
98
- })
99
- it('can check collection membership', async () => {
100
- assert.strictEqual(true, await storage.isInCollection(doc.id, 'replies', doc2))
101
- assert.strictEqual(false, await storage.isInCollection(doc.id, 'replies', doc3))
102
- })
103
- it('can remove from a collection', async () => {
104
- await storage.removeFromCollection(doc.id, 'replies', doc2)
105
- const page = await storage.getCollectionPage(doc.id, 'replies', 1)
106
- assert.ok(!page.items)
107
- })
108
- it('can add many items to a collection', async () => {
109
- for (let i = 3; i < 103; i++) {
110
- const reply = await as2.import({
111
- '@context': 'https://www.w3.org/ns/activitystreams',
112
- id: `https://social.example/users/test/note/${i}`,
113
- type: 'Note',
114
- name: 'test',
115
- content: 'test',
116
- inReplyTo: doc.id
117
- })
118
- await storage.addToCollection(doc.id, 'replies', reply)
119
- }
120
- const collection = await storage.getCollection(doc.id, 'replies')
121
- assert.equal(collection.totalItems, 100)
122
- assert.equal(collection.first.id, `${doc.id}/replies/5`)
123
- assert.equal(collection.last.id, `${doc.id}/replies/1`)
124
- const page = await storage.getCollectionPage(doc.id, 'replies', 3)
125
- assert.ok(page.next)
126
- // assert.ok(page.prev)
127
- assert.ok(page.items)
128
- const items = Array.from(page.items)
129
- assert.equal(items.length, 20)
130
- for (let i = 0; i < items.length; i++) {
131
- assert.ok(items[i])
132
- for (let j = i + 1; j < items.length; j++) {
133
- assert.ok(items[j])
134
- assert.ok(
135
- items[i].id > items[j].id,
136
- `item ${i} (${items[i].id}) <= item ${j} (${items[j].id})`
137
- )
138
- }
139
- }
140
- })
141
- it('can iterate over a collection', async () => {
142
- const seen = new Set()
143
- for await (const item of storage.items(doc.id, 'replies')) {
144
- assert.ok(!(item.id in seen))
145
- seen.add(item.id)
146
- }
147
- assert.strictEqual(seen.size, 100)
148
- })
149
- })
@@ -1,78 +0,0 @@
1
- import { describe, before, after, it } from 'node:test'
2
- import { RemoteKeyStorage } from '../lib/remotekeystorage.js'
3
- import assert from 'node:assert'
4
- import { Sequelize } from 'sequelize'
5
- import { KeyStorage } from '../lib/keystorage.js'
6
- import { UrlFormatter } from '../lib/urlformatter.js'
7
- import { ActivityPubClient } from '../lib/activitypubclient.js'
8
- import { nockSetup, nockFormat, getPublicKey, nockKeyRotate } from './utils/nock.js'
9
- import { HTTPSignature } from '../lib/httpsignature.js'
10
- import Logger from 'pino'
11
- import { Digester } from '../lib/digester.js'
12
- import { runMigrations } from '../lib/migrations/index.js'
13
-
14
- describe('RemoteKeyStorage', async () => {
15
- const host = 'activitypubbot.example'
16
- const remoteHost = 'social.example'
17
- const origin = `https://${host}`
18
- let connection = null
19
- let remoteKeyStorage = null
20
- let client = null
21
- let logger = null
22
- before(async () => {
23
- logger = Logger({
24
- level: 'silent'
25
- })
26
- connection = new Sequelize({ dialect: 'sqlite', storage: ':memory:', logging: false })
27
- await connection.authenticate()
28
- await runMigrations(connection)
29
- const keyStorage = new KeyStorage(connection, logger)
30
- const formatter = new UrlFormatter(origin)
31
- const digester = new Digester(logger)
32
- const signer = new HTTPSignature(logger)
33
- client = new ActivityPubClient(keyStorage, formatter, signer, digester, logger)
34
- nockSetup(remoteHost)
35
- })
36
-
37
- after(async () => {
38
- await connection.close()
39
- logger = null
40
- })
41
-
42
- it('can initialize', async () => {
43
- remoteKeyStorage = new RemoteKeyStorage(client, connection, logger)
44
- assert.ok(remoteKeyStorage)
45
- assert.ok(true)
46
- })
47
-
48
- it('can get a remote public key', async () => {
49
- const username = 'test'
50
- const domain = remoteHost
51
- const id = nockFormat({ username, key: true, domain })
52
- const publicKey = await getPublicKey(username, domain)
53
- const remote = await remoteKeyStorage.getPublicKey(id)
54
- assert.equal(remote.publicKeyPem, publicKey)
55
- })
56
-
57
- it('can get the same remote public key twice', async () => {
58
- const username = 'test'
59
- const domain = remoteHost
60
- const id = nockFormat({ username, key: true, domain })
61
- const publicKey = await getPublicKey(username, domain)
62
- const remote = await remoteKeyStorage.getPublicKey(id)
63
- assert.equal(remote.publicKeyPem, publicKey)
64
- })
65
-
66
- it('can get the right public key after key rotation', async () => {
67
- const username = 'test'
68
- const domain = remoteHost
69
- const id = nockFormat({ username, key: true, domain })
70
- const publicKey = await getPublicKey(username, domain)
71
- const remote = await remoteKeyStorage.getPublicKey(id)
72
- assert.equal(remote.publicKeyPem, publicKey)
73
- await nockKeyRotate(username)
74
- const publicKey2 = await getPublicKey(username, domain)
75
- const remote2 = await remoteKeyStorage.getPublicKey(id, false)
76
- assert.equal(remote2.publicKeyPem, publicKey2)
77
- })
78
- })