@musakui/fedi
Advanced tools
Comparing version 0.0.5 to 0.0.6
export const CONTENT_TYPE = `application/activity+json` | ||
export * from './core.js' |
export const CONTEXT = 'https://www.w3.org/ns/activitystreams' | ||
export * from './core.js' |
@@ -1,76 +0,44 @@ | ||
/** @link https://www.w3.org/ns/activitystreams#Object */ | ||
import { | ||
ACTOR_TYPES, | ||
OBJECT_TYPES, | ||
ACTIVTY_TYPES, | ||
INTRANSITIVE_ACTIVTY_TYPES, | ||
} from './core' | ||
/** @see https://www.w3.org/ns/activitystreams#Object */ | ||
export interface BaseObject<T = string> { | ||
type: T | ||
id?: string | ||
id?: string | null | ||
name?: string | ||
summary?: string | ||
published?: Date | ||
published?: Date | string | ||
attachment?: ObjectReference[] | ||
to?: ObjectReference | ObjectReference[] | ||
cc?: ObjectReference | ObjectReference[] | ||
} | ||
export interface BaseCollection<T = BaseObject> extends BaseObject { | ||
totalItems: number | ||
items: T[] | ||
export type ObjectReference<T = BaseObject> = T | string | ||
export interface BaseCollection<T = ObjectReference> extends BaseObject { | ||
items?: T[] | ||
totalItems?: number | ||
} | ||
/** @link https://www.w3.org/ns/activitystreams#Collection */ | ||
export interface Collection extends BaseCollection { | ||
/** @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-collection */ | ||
export interface Collection<T = ObjectReference> extends BaseCollection<T> { | ||
type: 'Collection' | ||
} | ||
/** @link https://www.w3.org/ns/activitystreams#OrderedCollection */ | ||
export interface OrderedCollection extends BaseCollection { | ||
/** @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-orderedcollection */ | ||
export interface OrderedCollection<T = ObjectReference> extends BaseCollection<T> { | ||
type: 'OrderedCollection' | ||
} | ||
export type ActorTypes = 'Application' | 'Group' | 'Organization' | 'Person' | 'Service' | ||
export type ActorTypes = typeof ACTOR_TYPES[number] | ||
export type ObjectTypes = typeof OBJECT_TYPES[number] | ||
export interface Actor extends BaseObject<ActorTypes> { | ||
} | ||
/** @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-activity */ | ||
export type ActivtyTypes = typeof ACTIVTY_TYPES[number] | ||
export type ActivtyTypes = 'Accept' | ||
| 'Add' | ||
| 'Announce' | ||
| 'Block' | ||
| 'Create' | ||
| 'Delete' | ||
| 'Dislike' | ||
| 'Flag' | ||
| 'Follow' | ||
| 'Ignore' | ||
| 'Join' | ||
| 'Leave' | ||
| 'Like' | ||
| 'Reject' | ||
| 'Remove' | ||
| 'Undo' | ||
| 'Update' | ||
/** @link https://www.w3.org/ns/activitystreams#Activity */ | ||
export interface Activity<O = BaseObject, T = BaseObject> extends BaseObject<ActivtyTypes> { | ||
object: O | ||
target: T | ||
} | ||
export type IntransitiveActivtyTypes = 'Arrive' | 'Question' | 'Travel' | ||
/** @link https://www.w3.org/ns/activitystreams#IntransitiveActivity */ | ||
export interface IntransitiveActivity<T = BaseObject> extends BaseObject<IntransitiveActivityTypes> { | ||
actor: Actor | ||
target: T | ||
} | ||
export type ObjectTypes = 'Article' | ||
| 'Audio' | ||
| 'Document' | ||
| 'Event' | ||
| 'Image' | ||
| 'Note' | ||
| 'Page' | ||
| 'Place' | ||
| 'Profile' | ||
| 'Relationship' | ||
| 'Tombstone' | ||
| 'Video' | ||
export interface ActivityStreamsObject extends BaseObject<ObjectTypes> { | ||
} | ||
/** @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-intransitiveactivity */ | ||
export type IntransitiveActivtyTypes = typeof INTRANSITIVE_ACTIVTY_TYPES[number] |
@@ -0,1 +1,7 @@ | ||
import { | ||
HTTPSignaturesError, | ||
INVALID_HEADER, | ||
INVALID_FIELD, | ||
} from './errors.js' | ||
const HS2019 = 'hs2019' | ||
@@ -85,4 +91,4 @@ const CREATED = '(created)' | ||
export const parse = (req) => { | ||
if (!req.headers) throw new Error('no headers on request') | ||
if (!req.headers.signature) throw new Error('missing signature header') | ||
if (!req.headers) throw new HTTPSignaturesError(INVALID_HEADER, 'no headers on request') | ||
if (!req.headers.signature) throw new HTTPSignaturesError(INVALID_HEADER, 'missing signature header') | ||
@@ -93,5 +99,5 @@ const now = new Date() | ||
const hd = new Date(req.headers.date) | ||
if (isNaN(hd)) throw new Error(`invalid date header: ${req.headers.date}`) | ||
if (isNaN(hd)) throw new HTTPSignaturesError(INVALID_HEADER, `invalid date header: ${req.headers.date}`) | ||
const dt = Math.abs(now - hd) | ||
if (dt > 1e5) throw new Error(`date too far: ${dt}`) | ||
if (dt > 1e5) throw new HTTPSignaturesError(INVALID_HEADER, `date too far: ${dt}`) | ||
} | ||
@@ -106,11 +112,11 @@ | ||
if (!sig.keyId || !sig.signature) { | ||
throw new Error(`invalid signature header: ${req.headers.signature}`) | ||
throw new HTTPSignaturesError(INVALID_FIELD, `invalid signature header: ${req.headers.signature}`) | ||
} | ||
if (sig.headers === '') throw new Error('empty headers field') | ||
if (sig.headers === '') throw new HTTPSignaturesError(INVALID_FIELD, 'empty headers field') | ||
if (sig.created) { | ||
const created = new Date(sig.created * 1000) | ||
if (isNaN(created)) throw new Error(`invalid created: ${sig.created}`) | ||
if (created > now) throw new Error(`created in future: ${created}`) | ||
if (isNaN(created)) throw new HTTPSignaturesError(INVALID_FIELD, `invalid created: ${sig.created}`) | ||
if (created > now) throw new HTTPSignaturesError(INVALID_FIELD, `created in future: ${created}`) | ||
} | ||
@@ -120,4 +126,4 @@ | ||
const expires = new Date(sig.expires * 1000) | ||
if (isNaN(expires)) throw new Error(`invalid expires: ${sig.expires}`) | ||
if (expires < now) throw new Error(`signature expired: ${expires}`) | ||
if (isNaN(expires)) throw new HTTPSignaturesError(INVALID_FIELD, `invalid expires: ${sig.expires}`) | ||
if (expires < now) throw new HTTPSignaturesError(INVALID_FIELD, `signature expired: ${expires}`) | ||
} | ||
@@ -142,3 +148,3 @@ | ||
} | ||
throw new Error(`invalid field: ${h}`) | ||
throw new HTTPSignaturesError(INVALID_FIELD, `invalid field: ${h}`) | ||
} | ||
@@ -145,0 +151,0 @@ |
import { createSign, createVerify, createHash } from 'crypto' | ||
import * as core from './core.js' | ||
import { | ||
HTTPSignaturesError, | ||
INVALID_FIELD, | ||
INVALID_HEADER, | ||
VERIFICATION_FAILED, | ||
KEY_RETRIEVAL_FAILED, | ||
} from './errors.js' | ||
@@ -93,3 +100,3 @@ /** @type {(d: string) => string} */ | ||
const ha = dg.split('=')[0] | ||
if (dg !== getDigest(req.body, ha)) throw new Error(`invalid digest: ${dg}`) | ||
if (dg !== getDigest(req.body, ha)) throw new HTTPSignaturesError(INVALID_HEADER, `invalid digest: ${dg}`) | ||
} | ||
@@ -101,7 +108,7 @@ | ||
if (!pk || !pk.publicKeyPem) { | ||
throw new Error(`failed to get key: ${sig.keyId}`) | ||
throw new HTTPSignaturesError(KEY_RETRIEVAL_FAILED, `failed to get key: ${sig.keyId}`) | ||
} | ||
if (pk.id && pk.id !== sig.keyId) { | ||
throw new Error(`invalid keyId: ${sig.keyId} != ${pk.id}`) | ||
throw new HTTPSignaturesError(INVALID_FIELD, `invalid keyId: ${sig.keyId} != ${pk.id}`) | ||
} | ||
@@ -112,3 +119,3 @@ | ||
throw new Error('verification failed') | ||
throw new HTTPSignaturesError(VERIFICATION_FAILED, 'verification failed') | ||
} | ||
@@ -115,0 +122,0 @@ |
@@ -7,2 +7,3 @@ export * as Keys from './keys' | ||
export * from './well-known/types' | ||
export * from './activitypub/types' | ||
export * from './activitystreams/types' |
@@ -10,3 +10,3 @@ { | ||
"repository": "github:musakui/fedi", | ||
"version": "0.0.5", | ||
"version": "0.0.6", | ||
"type": "module", | ||
@@ -13,0 +13,0 @@ "files": [ |
17454
21
581