Skip to content

Commit

Permalink
Test sendActivity()
Browse files Browse the repository at this point in the history
  • Loading branch information
dahlia committed Mar 5, 2024
1 parent a0ec9bf commit e50a58b
Show file tree
Hide file tree
Showing 4 changed files with 207 additions and 103 deletions.
110 changes: 106 additions & 4 deletions federation/send.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,24 @@
import { assertEquals } from "jsr:@std/assert@^0.218.2";
import { Service } from "../mod.ts";
import * as mf from "https://deno.land/x/[email protected]/mod.ts";
import {
assertEquals,
assertNotEquals,
assertRejects,
assertStrictEquals,
} from "jsr:@std/assert@^0.218.2";
import { doesActorOwnKey, verify } from "../httpsig/mod.ts";
import { mockDocumentLoader } from "../testing/docloader.ts";
import { privateKey2, publicKey2 } from "../testing/keys.ts";
import { Actor } from "../vocab/actor.ts";
import { Application, Endpoints, Group, Person } from "../vocab/vocab.ts";
import { extractInboxes } from "./send.ts";
import {
Activity,
Application,
Create,
Endpoints,
Group,
Person,
Service,
} from "../vocab/vocab.ts";
import { extractInboxes, sendActivity } from "./send.ts";

Deno.test("extractInboxes()", () => {
const recipients: Actor[] = [
Expand Down Expand Up @@ -52,3 +68,89 @@ Deno.test("extractInboxes()", () => {
]),
);
});

Deno.test("sendActivity()", async (t) => {
mf.install();

let verified: boolean | null = null;
let request: Request | null = null;
mf.mock("POST@/inbox", async (req) => {
request = req;
const key = await verify(req, mockDocumentLoader);
const activity = await Activity.fromJsonLd(await req.json(), {
documentLoader: mockDocumentLoader,
});
if (
key != null && await doesActorOwnKey(activity, key, mockDocumentLoader)
) {
verified = true;
return new Response("", { status: 202 });
}
verified = false;
return new Response("", { status: 401 });
});

await t.step("success", async () => {
const activity = new Create({
actor: new URL("https://example.com/person"),
});
await sendActivity({
activity,
privateKey: privateKey2,
keyId: publicKey2.id!,
inbox: new URL("https://example.com/inbox"),
documentLoader: mockDocumentLoader,
});
assertStrictEquals(verified, true);
assertNotEquals(request, null);
assertEquals(request?.method, "POST");
assertEquals(request?.url, "https://example.com/inbox");
assertEquals(
request?.headers.get("Content-Type"),
"application/activity+json",
);
});

mf.mock("POST@/inbox2", (_req) => {
return new Response("something went wrong", {
status: 500,
statusText: "Internal Server Error",
});
});

await t.step("failure", async () => {
let activity = new Create({
actor: new URL("https://example.com/person"),
});
await assertRejects(
() =>
sendActivity({
activity,
privateKey: privateKey2,
keyId: publicKey2.id!,
inbox: new URL("https://example.com/inbox2"),
documentLoader: mockDocumentLoader,
}),
Error,
"Failed to send activity to https://example.com/inbox2 " +
"(500 Internal Server Error):\n" +
"something went wrong",
);

activity = new Create({});
await assertRejects(
() =>
sendActivity({
activity,
privateKey: privateKey2,
keyId: publicKey2.id!,
inbox: new URL("https://example.com/inbox2"),
documentLoader: mockDocumentLoader,
}),
TypeError,
"The activity to send must have at least one actor property.",
);
});

mf.uninstall();
});
2 changes: 1 addition & 1 deletion federation/send.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ export async function sendActivity(
let request = new Request(inbox, {
method: "POST",
headers: {
"Content-Type": "application/ld+json",
"Content-Type": "application/activity+json",
},
body: JSON.stringify(jsonLd),
});
Expand Down
100 changes: 2 additions & 98 deletions httpsig/mod.test.ts
Original file line number Diff line number Diff line change
@@ -1,106 +1,10 @@
import { assert, assertEquals, assertFalse } from "jsr:@std/assert@^0.218.2";
import { Temporal } from "npm:@js-temporal/polyfill@^0.4.4";
import { CryptographicKey, doesActorOwnKey, sign, verify } from "../mod.ts";
import { doesActorOwnKey, sign, verify } from "../mod.ts";
import { mockDocumentLoader } from "../testing/docloader.ts";
import { privateKey2, publicKey1, publicKey2 } from "../testing/keys.ts";
import { Create } from "../vocab/vocab.ts";

const publicKey1 = new CryptographicKey({
id: new URL("https://example.com/key"),
owner: new URL("https://example.com/person"),
publicKey: await crypto.subtle.importKey(
"jwk",
{
kty: "RSA",
alg: "RS256",
// cSpell: disable
n: "yIB9rotX8G6r6_6toT-x24BUiQ_HaPH1Em9dOt4c94s-OPFoEdH7DY7Iym9A8Ll" +
"H4JaGF8KD38bLHWe1S4x0jV3gHJKhK7veJfGZCKUENcQecBZ-YWUs5HWvUIX1vVB" +
"__0luHrg6BQKGOrSOE-WIAxyr0qsWCFfZzQrvSnUD2yvg1arJX2xhms14uxoRd5K" +
"g9efKSCmmQaNEapicARUmFWrIEpGFa_nUUnqimssAGw1eZFqf3wA4TjhsuARBhGa" +
"Jtv_3KEa016eMZxy3kDlOjZnXZTaTgWkXdodwUvy8563fes3Al6BlcS2iJ9qbtha" +
"8rSm0FHqoUKH73JsLPKQIwQ",
e: "AQAB",
// cSpell: enable
key_ops: ["verify"],
ext: true,
},
{
name: "RSASSA-PKCS1-v1_5",
hash: "SHA-256",
},
true,
["verify"],
),
});

const privateKey2 = await crypto.subtle.importKey(
"jwk",
{
"kty": "RSA",
"alg": "RS256",
// cSpell: disable
n: "oRmBtnxbdFutoRd1GLGwwGTrsqlRRWUe11hHQaoRLGf5LwQ0tIc6I9q-dynliw-2kxY" +
"sLn9SH2je6HcTYOolgW7F_cOWXZQN04b-OiYcU1ConAhLjmn4k1uKawJ614y0ScPNd8P" +
"Q-CljsnlPxbq9ofaCMe2BV3B6y09aCuGFJ0nxn1_ubjmIBIWWFTAznoz1J9BhJDGyt3I" +
"O3ABy3f9zDVlR32L_n5VIkXnxkjUKdzMAOzYb62kuKOp1iznRTPrV71SNtivJMwSh_LV" +
"gBrmZjtIn_oim-KyX_fdLU3tQ7VClyqmJzyAjccOH6Qj6nFTPh-vX07gqN8IlLT2uye4" +
"waw",
e: "AQAB",
d: "f-Pa2L7Sb4YUSa1wlSEC-0li35uQ3DFRkY0QTG2xYnpMFGoXWTV9D1epGrqU8pePzia" +
"s_mCvFiZPx2Y4aRiYm68P2Mu7hCBz9XfWPN1iYTXIFM51BOLVpk3mjdsTICkgOusJI0m" +
"9jDR3ZAjwLj14K6qhYvd0VbECmoItLjQoW64Sc9iDgD3CvGoTqv71oTfW70cy-Ve1xQ9" +
"CThAmMOTKe6rYCUTA8tMZcPszifZ4iOasOjgvRxyel86LqGNtyslY8k86gQlMtFpR3Ve" +
"ZV_8otAWZn0mDc4vVU8HUO-DzYiIFdAcVxfPJh6tx7snCTsdzze_98OEAK4EWYBn7vsG" +
"FeQ",
p: "xuDd7tE_47NWwvDTpB403X13EPA3768MlNpl_v_BGiuP-1uvWUnsOVZB0F3HXSVg1sB" +
"VNtec46v7OU0P693gvYUhouTmSQpayY_VFqMklprWgs7cfneqbeDzv3C4Fw5waY-vjoI" +
"NDsE1jYELUnl5cVjXXyxuGFG-IaLJKmHmHX0",
q: "z17X2t9zO6WcMp6W04gXdKmniJlxekOrOmWnrX9AwaM8NYCLN3y23r59nqNP9aUAWG1" +
"eoGFmav2rYQitWhz_VsEu2pQUsfsYKZYHchu5p_jCYwuM3rIg7aCbhtGv_tBoWAf1NvK" +
"Mhtp2es0ZaHZCzKDGSOkIYDOB-ZDmNigWigc",
dp: "lrXReSkZQXSmSxQ1TimV5kMt96gSu4_r-OGIabVmoG5irhjMyN08Jjc3qK9oZS3uNM-L" +
"xAOg4OdzefjsF9IMfZJl6wuLd85g_l4BHSaEk5zC8l3QugX1IU9XZ7wDxXUrutMoNtZX" +
"DtdbveAMtHNZlIu-qmEBDWzkqJiz2WpW-AE",
dq: "TCLoYcX0ywuNA9DSU6v94KmBh1e_IELEFVbJb5vvLKlAK-ycMK0rfzC1co9Hhkski1Ls" +
"kTnxnoqwZ5oF-7X10eZvy3Te_FHSl0IsTar8ST2-MRtGh2UjTdvP_nnygj4GcXvKfngj" +
"PEfthDzVfVMeR38oDhDxMFD5AaY_v9aMH_U",
qi: "KC6gWhVM_x7iQgl-gEoSh_iM1Jf314ZLJKAAz1DsTHMi5yuCkCMmmY7h6jlkAJVngK3K" +
"If5LPoAeUoGJ26E1kocbRU_nZBftMDVXHCYICz8qMQXR5euN_5SeJnu_VWXH-CY83MKh" +
"PYAorWSZ1-G9gh-C16LlRMzJwoE6h5QNeNo",
// cSpell: enable
"key_ops": ["sign"],
"ext": true,
},
{ name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" },
true,
["sign"],
);

const publicKey2 = new CryptographicKey({
id: new URL("https://example.com/key2"),
publicKey: await crypto.subtle.importKey(
"jwk",
{
kty: "RSA",
alg: "RS256",
// cSpell: disable
n: "oRmBtnxbdFutoRd1GLGwwGTrsqlRRWUe11hHQaoRLGf5LwQ0tIc6I9q-dynliw-" +
"2kxYsLn9SH2je6HcTYOolgW7F_cOWXZQN04b-OiYcU1ConAhLjmn4k1uKawJ614y" +
"0ScPNd8PQ-CljsnlPxbq9ofaCMe2BV3B6y09aCuGFJ0nxn1_ubjmIBIWWFTAznoz" +
"1J9BhJDGyt3IO3ABy3f9zDVlR32L_n5VIkXnxkjUKdzMAOzYb62kuKOp1iznRTPr" +
"V71SNtivJMwSh_LVgBrmZjtIn_oim-KyX_fdLU3tQ7VClyqmJzyAjccOH6Qj6nFT" +
"Ph-vX07gqN8IlLT2uye4waw",
e: "AQAB",
// cSpell: enable
key_ops: ["verify"],
ext: true,
},
{ "name": "RSASSA-PKCS1-v1_5", "hash": "SHA-256" },
true,
["verify"],
),
});

Deno.test("sign()", async () => {
const request = new Request("https://example.com/", {
method: "POST",
Expand Down
98 changes: 98 additions & 0 deletions testing/keys.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import { CryptographicKey } from "../vocab/vocab.ts";

export const publicKey1 = new CryptographicKey({
id: new URL("https://example.com/key"),
owner: new URL("https://example.com/person"),
publicKey: await crypto.subtle.importKey(
"jwk",
{
kty: "RSA",
alg: "RS256",
// cSpell: disable
n: "yIB9rotX8G6r6_6toT-x24BUiQ_HaPH1Em9dOt4c94s-OPFoEdH7DY7Iym9A8Ll" +
"H4JaGF8KD38bLHWe1S4x0jV3gHJKhK7veJfGZCKUENcQecBZ-YWUs5HWvUIX1vVB" +
"__0luHrg6BQKGOrSOE-WIAxyr0qsWCFfZzQrvSnUD2yvg1arJX2xhms14uxoRd5K" +
"g9efKSCmmQaNEapicARUmFWrIEpGFa_nUUnqimssAGw1eZFqf3wA4TjhsuARBhGa" +
"Jtv_3KEa016eMZxy3kDlOjZnXZTaTgWkXdodwUvy8563fes3Al6BlcS2iJ9qbtha" +
"8rSm0FHqoUKH73JsLPKQIwQ",
e: "AQAB",
// cSpell: enable
key_ops: ["verify"],
ext: true,
},
{
name: "RSASSA-PKCS1-v1_5",
hash: "SHA-256",
},
true,
["verify"],
),
});

export const privateKey2 = await crypto.subtle.importKey(
"jwk",
{
"kty": "RSA",
"alg": "RS256",
// cSpell: disable
n: "oRmBtnxbdFutoRd1GLGwwGTrsqlRRWUe11hHQaoRLGf5LwQ0tIc6I9q-dynliw-2kxY" +
"sLn9SH2je6HcTYOolgW7F_cOWXZQN04b-OiYcU1ConAhLjmn4k1uKawJ614y0ScPNd8P" +
"Q-CljsnlPxbq9ofaCMe2BV3B6y09aCuGFJ0nxn1_ubjmIBIWWFTAznoz1J9BhJDGyt3I" +
"O3ABy3f9zDVlR32L_n5VIkXnxkjUKdzMAOzYb62kuKOp1iznRTPrV71SNtivJMwSh_LV" +
"gBrmZjtIn_oim-KyX_fdLU3tQ7VClyqmJzyAjccOH6Qj6nFTPh-vX07gqN8IlLT2uye4" +
"waw",
e: "AQAB",
d: "f-Pa2L7Sb4YUSa1wlSEC-0li35uQ3DFRkY0QTG2xYnpMFGoXWTV9D1epGrqU8pePzia" +
"s_mCvFiZPx2Y4aRiYm68P2Mu7hCBz9XfWPN1iYTXIFM51BOLVpk3mjdsTICkgOusJI0m" +
"9jDR3ZAjwLj14K6qhYvd0VbECmoItLjQoW64Sc9iDgD3CvGoTqv71oTfW70cy-Ve1xQ9" +
"CThAmMOTKe6rYCUTA8tMZcPszifZ4iOasOjgvRxyel86LqGNtyslY8k86gQlMtFpR3Ve" +
"ZV_8otAWZn0mDc4vVU8HUO-DzYiIFdAcVxfPJh6tx7snCTsdzze_98OEAK4EWYBn7vsG" +
"FeQ",
p: "xuDd7tE_47NWwvDTpB403X13EPA3768MlNpl_v_BGiuP-1uvWUnsOVZB0F3HXSVg1sB" +
"VNtec46v7OU0P693gvYUhouTmSQpayY_VFqMklprWgs7cfneqbeDzv3C4Fw5waY-vjoI" +
"NDsE1jYELUnl5cVjXXyxuGFG-IaLJKmHmHX0",
q: "z17X2t9zO6WcMp6W04gXdKmniJlxekOrOmWnrX9AwaM8NYCLN3y23r59nqNP9aUAWG1" +
"eoGFmav2rYQitWhz_VsEu2pQUsfsYKZYHchu5p_jCYwuM3rIg7aCbhtGv_tBoWAf1NvK" +
"Mhtp2es0ZaHZCzKDGSOkIYDOB-ZDmNigWigc",
dp: "lrXReSkZQXSmSxQ1TimV5kMt96gSu4_r-OGIabVmoG5irhjMyN08Jjc3qK9oZS3uNM-L" +
"xAOg4OdzefjsF9IMfZJl6wuLd85g_l4BHSaEk5zC8l3QugX1IU9XZ7wDxXUrutMoNtZX" +
"DtdbveAMtHNZlIu-qmEBDWzkqJiz2WpW-AE",
dq: "TCLoYcX0ywuNA9DSU6v94KmBh1e_IELEFVbJb5vvLKlAK-ycMK0rfzC1co9Hhkski1Ls" +
"kTnxnoqwZ5oF-7X10eZvy3Te_FHSl0IsTar8ST2-MRtGh2UjTdvP_nnygj4GcXvKfngj" +
"PEfthDzVfVMeR38oDhDxMFD5AaY_v9aMH_U",
qi: "KC6gWhVM_x7iQgl-gEoSh_iM1Jf314ZLJKAAz1DsTHMi5yuCkCMmmY7h6jlkAJVngK3K" +
"If5LPoAeUoGJ26E1kocbRU_nZBftMDVXHCYICz8qMQXR5euN_5SeJnu_VWXH-CY83MKh" +
"PYAorWSZ1-G9gh-C16LlRMzJwoE6h5QNeNo",
// cSpell: enable
"key_ops": ["sign"],
"ext": true,
},
{ name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" },
true,
["sign"],
);

export const publicKey2 = new CryptographicKey({
id: new URL("https://example.com/key2"),
publicKey: await crypto.subtle.importKey(
"jwk",
{
kty: "RSA",
alg: "RS256",
// cSpell: disable
n: "oRmBtnxbdFutoRd1GLGwwGTrsqlRRWUe11hHQaoRLGf5LwQ0tIc6I9q-dynliw-" +
"2kxYsLn9SH2je6HcTYOolgW7F_cOWXZQN04b-OiYcU1ConAhLjmn4k1uKawJ614y" +
"0ScPNd8PQ-CljsnlPxbq9ofaCMe2BV3B6y09aCuGFJ0nxn1_ubjmIBIWWFTAznoz" +
"1J9BhJDGyt3IO3ABy3f9zDVlR32L_n5VIkXnxkjUKdzMAOzYb62kuKOp1iznRTPr" +
"V71SNtivJMwSh_LVgBrmZjtIn_oim-KyX_fdLU3tQ7VClyqmJzyAjccOH6Qj6nFT" +
"Ph-vX07gqN8IlLT2uye4waw",
e: "AQAB",
// cSpell: enable
key_ops: ["verify"],
ext: true,
},
{ "name": "RSASSA-PKCS1-v1_5", "hash": "SHA-256" },
true,
["verify"],
),
});

0 comments on commit e50a58b

Please sign in to comment.