Merge remote-tracking branch 'origin/main' into signer-middleware
This commit is contained in:
commit
e5392f4d9e
|
@ -1,3 +1,4 @@
|
||||||
.env
|
.env
|
||||||
*.cpuprofile
|
*.cpuprofile
|
||||||
|
*.swp
|
||||||
deno-test.xml
|
deno-test.xml
|
|
@ -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.
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"id": "2238893aee54bbe9188498a5aa124d62870d5757894bf52cdb362d1a0874ed18",
|
||||||
|
"pubkey": "c9f5508526e213c3bc5468161f1b738a86063a2ece540730f9412e7becd5f0b2",
|
||||||
|
"created_at": 1715517440,
|
||||||
|
"kind": 0,
|
||||||
|
"tags": [],
|
||||||
|
"content": "{\"name\":\"dictator\",\"about\":\"\",\"nip05\":\"\"}",
|
||||||
|
"sig": "a630ba158833eea10289fe077087ccad22c71ddfbe475153958cfc158ae94fb0a5f7b7626e62da6a3ef8bfbe67321e8f993517ed7f1578a45aff11bc2bec484c"
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"id": "da4e1e727c6456cee2b0341a1d7a2356e4263523374a2570a7dd318ab5d73f93",
|
||||||
|
"pubkey": "e4d96e951739787e62ada74ee06a9a185af22791a899a6166ec23aab58c5d700",
|
||||||
|
"created_at": 1715517565,
|
||||||
|
"kind": 0,
|
||||||
|
"tags": [],
|
||||||
|
"content": "{\"name\":\"george orwell\",\"about\":\"\",\"nip05\":\"\"}",
|
||||||
|
"sig": "cd375e2065cf452d3bfefa9951b04ab63018ab7c253803256cca1d89d03b38e454c71ed36fdd3c28a8ff2723cc19b21371ce0f9bbd39a92b1d1aa946137237bd"
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"id": "44f19148f5af60b0f43ed8c737fbda31b165e05bb55562003c45d9a9f02e8228",
|
||||||
|
"pubkey": "e4d96e951739787e62ada74ee06a9a185af22791a899a6166ec23aab58c5d700",
|
||||||
|
"created_at": 1715636249,
|
||||||
|
"kind": 1,
|
||||||
|
"tags": [],
|
||||||
|
"content": "I like free speech",
|
||||||
|
"sig": "6b50db9c1c02bd8b0e64512e71d53a0058569f44e8dcff65ad17fce544d6ae79f8f79fa0f9a615446fa8cbc2375709bf835751843b0cd10e62ae5d505fe106d4"
|
||||||
|
}
|
|
@ -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"
|
||||||
|
}
|
|
@ -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);
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue