Merge remote-tracking branch 'origin/main' into signer-middleware

This commit is contained in:
Alex Gleason 2024-05-14 14:16:38 -05:00
commit e5392f4d9e
No known key found for this signature in database
GPG Key ID: 7211D1F99744FBB7
8 changed files with 120 additions and 67 deletions

BIN
..env.swp

Binary file not shown.

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
.env .env
*.cpuprofile *.cpuprofile
*.swp
deno-test.xml deno-test.xml

View File

@ -9,9 +9,7 @@ The Ditto server publishes kind `30361` events to represent users. These events
User events have the following tags: User events have the following tags:
- `d` - pubkey of the user. - `d` - pubkey of the user.
- `name` - NIP-05 username granted to the user, without the domain.
- `role` - one of `admin` or `user`. - `role` - one of `admin` or `user`.
- `origin` - the origin of the user's NIP-05, at the time the event was published.
Example: Example:
@ -25,7 +23,6 @@ Example:
"tags": [ "tags": [
["d", "79c2cae114ea28a981e7559b4fe7854a473521a8d22a66bbab9fa248eb820ff6"], ["d", "79c2cae114ea28a981e7559b4fe7854a473521a8d22a66bbab9fa248eb820ff6"],
["role", "user"], ["role", "user"],
["origin", "https://ditto.ngrok.app"],
["alt", "User's account was updated by the admins of ditto.ngrok.app"] ["alt", "User's account was updated by the admins of ditto.ngrok.app"]
], ],
"sig": "fc12db77b1c8f8aa86c73b617f0cd4af1e6ba244239eaf3164a292de6d39363f32d6b817ffff796ace7a103d75e1d8e6a0fb7f618819b32d81a953b4a75d7507" "sig": "fc12db77b1c8f8aa86c73b617f0cd4af1e6ba244239eaf3164a292de6d39363f32d6b817ffff796ace7a103d75e1d8e6a0fb7f618819b32d81a953b4a75d7507"
@ -40,4 +37,4 @@ The sections below describe the `content` field. Some are encrypted and some are
### `pub.ditto.pleroma.config` ### `pub.ditto.pleroma.config`
NIP-04 encrypted JSON array of Pleroma ConfigDB objects. Pleroma admin API endpoints set this config, and Ditto reads from it. NIP-04 encrypted JSON array of Pleroma ConfigDB objects. Pleroma admin API endpoints set this config, and Ditto reads from it.

View File

@ -0,0 +1,9 @@
{
"id": "2238893aee54bbe9188498a5aa124d62870d5757894bf52cdb362d1a0874ed18",
"pubkey": "c9f5508526e213c3bc5468161f1b738a86063a2ece540730f9412e7becd5f0b2",
"created_at": 1715517440,
"kind": 0,
"tags": [],
"content": "{\"name\":\"dictator\",\"about\":\"\",\"nip05\":\"\"}",
"sig": "a630ba158833eea10289fe077087ccad22c71ddfbe475153958cfc158ae94fb0a5f7b7626e62da6a3ef8bfbe67321e8f993517ed7f1578a45aff11bc2bec484c"
}

View File

@ -0,0 +1,9 @@
{
"id": "da4e1e727c6456cee2b0341a1d7a2356e4263523374a2570a7dd318ab5d73f93",
"pubkey": "e4d96e951739787e62ada74ee06a9a185af22791a899a6166ec23aab58c5d700",
"created_at": 1715517565,
"kind": 0,
"tags": [],
"content": "{\"name\":\"george orwell\",\"about\":\"\",\"nip05\":\"\"}",
"sig": "cd375e2065cf452d3bfefa9951b04ab63018ab7c253803256cca1d89d03b38e454c71ed36fdd3c28a8ff2723cc19b21371ce0f9bbd39a92b1d1aa946137237bd"
}

View File

@ -0,0 +1,9 @@
{
"id": "44f19148f5af60b0f43ed8c737fbda31b165e05bb55562003c45d9a9f02e8228",
"pubkey": "e4d96e951739787e62ada74ee06a9a185af22791a899a6166ec23aab58c5d700",
"created_at": 1715636249,
"kind": 1,
"tags": [],
"content": "I like free speech",
"sig": "6b50db9c1c02bd8b0e64512e71d53a0058569f44e8dcff65ad17fce544d6ae79f8f79fa0f9a615446fa8cbc2375709bf835751843b0cd10e62ae5d505fe106d4"
}

View File

@ -0,0 +1,24 @@
{
"id": "129b2749330a7f1189d3e74c6764a955851f1e4017a818dfd51ab8e24192b0f3",
"pubkey": "c9f5508526e213c3bc5468161f1b738a86063a2ece540730f9412e7becd5f0b2",
"created_at": 1715636348,
"kind": 1984,
"tags": [
[
"p",
"e4d96e951739787e62ada74ee06a9a185af22791a899a6166ec23aab58c5d700",
"other"
],
[
"P",
"e724b1c1b90eab9cc0f5976b380b80dda050de1820dc143e62d9e4f27a9a0b2c"
],
[
"e",
"44f19148f5af60b0f43ed8c737fbda31b165e05bb55562003c45d9a9f02e8228",
"other"
]
],
"content": "freedom of speech not freedom of reach",
"sig": "cd05a14749cdf0c7664d056e2c02518740000387732218dacd0c71de5b96c0c3c99a0b927b0cd0778f25a211525fa03b4ed4f4f537bb1221c73467780d4ee1bc"
}

View File

@ -5,127 +5,131 @@ import { MockRelay } from '@nostrify/nostrify/test';
import { DittoEvent } from '@/interfaces/DittoEvent.ts'; import { DittoEvent } from '@/interfaces/DittoEvent.ts';
import { eventFixture } from '@/test.ts'; import { eventFixture } from '@/test.ts';
import event0madePost from '~/fixtures/events/event-0-the-one-who-post-and-users-repost.json' with { type: 'json' };
import event0madeRepost from '~/fixtures/events/event-0-the-one-who-repost.json' with { type: 'json' };
import event0madeQuoteRepost from '~/fixtures/events/event-0-the-one-who-quote-repost.json' with { type: 'json' };
import event1 from '~/fixtures/events/event-1.json' with { type: 'json' };
import event1quoteRepost from '~/fixtures/events/event-1-quote-repost.json' with { type: 'json' };
import event1futureIsMine from '~/fixtures/events/event-1-will-be-reposted-with-quote-repost.json' with {
type: 'json',
};
import event1quoteRepostLatin from '~/fixtures/events/event-1-quote-repost-will-be-reposted.json' with { type: 'json' };
import event1willBeQuoteReposted from '~/fixtures/events/event-1-that-will-be-quote-reposted.json' with {
type: 'json',
};
import event1reposted from '~/fixtures/events/event-1-reposted.json' with { type: 'json' };
import event6 from '~/fixtures/events/event-6.json' with { type: 'json' };
import event6ofQuoteRepost from '~/fixtures/events/event-6-of-quote-repost.json' with { type: 'json' };
Deno.test('hydrateEvents(): author --- WITHOUT stats', async () => { Deno.test('hydrateEvents(): author --- WITHOUT stats', async () => {
const db = new MockRelay(); const db = new MockRelay();
const event0 = await eventFixture('event-0'); const event0 = await eventFixture('event-0');
const event1copy = structuredClone(event1); const event1 = await eventFixture('event-1');
// Save events to database // Save events to database
await db.event(event0); await db.event(event0);
await db.event(event1copy); await db.event(event1);
assertEquals((event1copy as DittoEvent).author, undefined, "Event hasn't been hydrated yet");
await hydrateEvents({ await hydrateEvents({
events: [event1copy], events: [event1],
storage: db, storage: db,
}); });
const expectedEvent = { ...event1copy, author: event0 }; const expectedEvent = { ...event1, author: event0 };
assertEquals(event1copy, expectedEvent); assertEquals(event1, expectedEvent);
}); });
Deno.test('hydrateEvents(): repost --- WITHOUT stats', async () => { Deno.test('hydrateEvents(): repost --- WITHOUT stats', async () => {
const db = new MockRelay(); const db = new MockRelay();
const event0madePostCopy = structuredClone(event0madePost); const event0madePost = await eventFixture('event-0-the-one-who-post-and-users-repost');
const event0madeRepostCopy = structuredClone(event0madeRepost); const event0madeRepost = await eventFixture('event-0-the-one-who-repost');
const event1repostedCopy = structuredClone(event1reposted); const event1reposted = await eventFixture('event-1-reposted');
const event6copy = structuredClone(event6); const event6 = await eventFixture('event-6');
// Save events to database // Save events to database
await db.event(event0madePostCopy); await db.event(event0madePost);
await db.event(event0madeRepostCopy); await db.event(event0madeRepost);
await db.event(event1repostedCopy); await db.event(event1reposted);
await db.event(event6copy); await db.event(event6);
assertEquals((event6copy as DittoEvent).author, undefined, "Event hasn't hydrated author yet");
assertEquals((event6copy as DittoEvent).repost, undefined, "Event hasn't hydrated repost yet");
await hydrateEvents({ await hydrateEvents({
events: [event6copy], events: [event6],
storage: db, storage: db,
}); });
const expectedEvent6 = { const expectedEvent6 = {
...event6copy, ...event6,
author: event0madeRepostCopy, author: event0madeRepost,
repost: { ...event1repostedCopy, author: event0madePostCopy }, repost: { ...event1reposted, author: event0madePost },
}; };
assertEquals(event6copy, expectedEvent6); assertEquals(event6, expectedEvent6);
}); });
Deno.test('hydrateEvents(): quote repost --- WITHOUT stats', async () => { Deno.test('hydrateEvents(): quote repost --- WITHOUT stats', async () => {
const db = new MockRelay(); const db = new MockRelay();
const event0madeQuoteRepostCopy = structuredClone(event0madeQuoteRepost); const event0madeQuoteRepost = await eventFixture('event-0-the-one-who-quote-repost');
const event0 = await eventFixture('event-0'); const event0 = await eventFixture('event-0');
const event1quoteRepostCopy = structuredClone(event1quoteRepost); const event1quoteRepost = await eventFixture('event-1-quote-repost');
const event1willBeQuoteRepostedCopy = structuredClone(event1willBeQuoteReposted); const event1willBeQuoteReposted = await eventFixture('event-1-that-will-be-quote-reposted');
// Save events to database // Save events to database
await db.event(event0madeQuoteRepostCopy); await db.event(event0madeQuoteRepost);
await db.event(event0); await db.event(event0);
await db.event(event1quoteRepostCopy); await db.event(event1quoteRepost);
await db.event(event1willBeQuoteRepostedCopy); await db.event(event1willBeQuoteReposted);
await hydrateEvents({ await hydrateEvents({
events: [event1quoteRepostCopy], events: [event1quoteRepost],
storage: db, storage: db,
}); });
const expectedEvent1quoteRepost = { const expectedEvent1quoteRepost = {
...event1quoteRepostCopy, ...event1quoteRepost,
author: event0madeQuoteRepostCopy, author: event0madeQuoteRepost,
quote: { ...event1willBeQuoteRepostedCopy, author: event0 }, quote: { ...event1willBeQuoteReposted, author: event0 },
}; };
assertEquals(event1quoteRepostCopy, expectedEvent1quoteRepost); assertEquals(event1quoteRepost, expectedEvent1quoteRepost);
}); });
Deno.test('hydrateEvents(): repost of quote repost --- WITHOUT stats', async () => { Deno.test('hydrateEvents(): repost of quote repost --- WITHOUT stats', async () => {
const db = new MockRelay(); const db = new MockRelay();
const author = await eventFixture('event-0-makes-repost-with-quote-repost'); const author = await eventFixture('event-0-makes-repost-with-quote-repost');
const event1copy = structuredClone(event1futureIsMine); const event1 = await eventFixture('event-1-will-be-reposted-with-quote-repost');
const event1quoteCopy = structuredClone(event1quoteRepostLatin); const event6 = await eventFixture('event-6-of-quote-repost');
const event6copy = structuredClone(event6ofQuoteRepost); const event1quote = await eventFixture('event-1-quote-repost-will-be-reposted');
// Save events to database // Save events to database
await db.event(author); await db.event(author);
await db.event(event1copy); await db.event(event1);
await db.event(event1quoteCopy); await db.event(event1quote);
await db.event(event6copy); await db.event(event6);
assertEquals((event6copy as DittoEvent).author, undefined, "Event hasn't hydrated author yet");
assertEquals((event6copy as DittoEvent).repost, undefined, "Event hasn't hydrated repost yet");
await hydrateEvents({ await hydrateEvents({
events: [event6copy], events: [event6],
storage: db, storage: db,
}); });
const expectedEvent6 = { const expectedEvent6 = {
...event6copy, ...event6,
author, author,
repost: { ...event1quoteCopy, author, quote: { author, ...event1copy } }, repost: { ...event1quote, author, quote: { author, ...event1 } },
}; };
assertEquals(event6copy, expectedEvent6); assertEquals(event6, expectedEvent6);
});
Deno.test('hydrateEvents(): report pubkey and post // kind 1984 --- WITHOUT stats', async () => {
const db = new MockRelay();
const authorDictator = await eventFixture('kind-0-dictator');
const authorVictim = await eventFixture('kind-0-george-orwell');
const reportEvent = await eventFixture('kind-1984-dictator-reports-george-orwell');
const event1 = await eventFixture('kind-1-author-george-orwell');
// Save events to database
await db.event(authorDictator);
await db.event(authorVictim);
await db.event(reportEvent);
await db.event(event1);
await hydrateEvents({
events: [reportEvent],
storage: db,
});
const expectedEvent: DittoEvent = {
...reportEvent,
author: authorDictator,
reported_notes: [event1],
reported_profile: authorVictim,
};
assertEquals(reportEvent, expectedEvent);
}); });