Destroy everything

This commit is contained in:
Alex Gleason 2024-05-14 11:40:20 -05:00
parent ee7864da8c
commit 5a2b1b7de7
No known key found for this signature in database
GPG Key ID: 7211D1F99744FBB7
4 changed files with 37 additions and 126 deletions

View File

@ -81,7 +81,7 @@ import { hostMetaController } from '@/controllers/well-known/host-meta.ts';
import { nodeInfoController, nodeInfoSchemaController } from '@/controllers/well-known/nodeinfo.ts';
import { nostrController } from '@/controllers/well-known/nostr.ts';
import { webfingerController } from '@/controllers/well-known/webfinger.ts';
import { auth19, requirePubkey } from '@/middleware/auth19.ts';
import { requirePubkey } from '@/middleware/auth19.ts';
import { auth98, requireProof, requireRole } from '@/middleware/auth98.ts';
import { cache } from '@/middleware/cache.ts';
import { csp } from '@/middleware/csp.ts';
@ -94,10 +94,6 @@ interface AppEnv extends HonoEnv {
Variables: {
/** Signer to get the logged-in user's pubkey, relays, and to sign events, or `undefined` if the user isn't logged in. */
signer?: NostrSigner;
/** Hex pubkey for the current user. If provided, the user is considered "logged in." */
pubkey?: string;
/** Hex secret key for the current user. Optional, but easiest way to use legacy Mastodon apps. */
seckey?: Uint8Array;
/** NIP-98 signed event proving the pubkey is owned by the user. */
proof?: NostrEvent;
/** User associated with the pubkey, if any. */
@ -130,7 +126,6 @@ app.use(
'*',
csp(),
cors({ origin: '*', exposeHeaders: ['link'] }),
auth19,
auth98(),
storeMiddleware,
signerMiddleware,

View File

@ -1,49 +0,0 @@
import { HTTPException } from 'hono';
import { getPublicKey, nip19 } from 'nostr-tools';
import { type AppMiddleware } from '@/app.ts';
/** We only accept "Bearer" type. */
const BEARER_REGEX = new RegExp(`^Bearer (${nip19.BECH32_REGEX.source})$`);
/** NIP-19 auth middleware. */
const auth19: AppMiddleware = async (c, next) => {
const authHeader = c.req.header('authorization');
const match = authHeader?.match(BEARER_REGEX);
if (match) {
const [_, bech32] = match;
try {
const decoded = nip19.decode(bech32!);
switch (decoded.type) {
case 'npub':
c.set('pubkey', decoded.data);
break;
case 'nprofile':
c.set('pubkey', decoded.data.pubkey);
break;
case 'nsec':
c.set('pubkey', getPublicKey(decoded.data));
c.set('seckey', decoded.data);
break;
}
} catch (_e) {
//
}
}
await next();
};
/** Throw a 401 if the pubkey isn't set. */
const requirePubkey: AppMiddleware = async (c, next) => {
if (!c.get('pubkey')) {
throw new HTTPException(401, { message: 'No pubkey provided' });
}
await next();
};
export { auth19, requirePubkey };

View File

@ -1,12 +1,43 @@
import { NConnectSigner, NSecSigner } from '@nostrify/nostrify';
import { nip19 } from 'nostr-tools';
import { AppMiddleware } from '@/app.ts';
import { APISigner } from '@/signers/APISigner.ts';
import { AdminSigner } from '@/signers/AdminSigner.ts';
import { Storages } from '@/storages.ts';
/** We only accept "Bearer" type. */
const BEARER_REGEX = new RegExp(`^Bearer (${nip19.BECH32_REGEX.source})$`);
/** Make a `signer` object available to all controllers, or unset if the user isn't logged in. */
export const signerMiddleware: AppMiddleware = async (c, next) => {
try {
c.set('signer', new APISigner(c));
} catch {
// do nothing
const header = c.req.header('authorization');
const match = header?.match(BEARER_REGEX);
if (match) {
const [_, bech32] = match;
try {
const decoded = nip19.decode(bech32!);
switch (decoded.type) {
case 'npub':
c.set(
'signer',
new NConnectSigner({
pubkey: decoded.data,
relay: Storages.pubsub,
signer: new AdminSigner(),
timeout: 60000,
}),
);
break;
case 'nsec':
c.set('signer', new NSecSigner(decoded.data));
break;
}
} catch {
// the user is not logged in
}
}
await next();

View File

@ -1,66 +0,0 @@
// deno-lint-ignore-file require-await
import { NConnectSigner, NostrEvent, NostrSigner, NSecSigner } from '@nostrify/nostrify';
import { HTTPException } from 'hono';
import { type AppContext } from '@/app.ts';
import { AdminSigner } from '@/signers/AdminSigner.ts';
import { Storages } from '@/storages.ts';
/**
* Sign Nostr event using the app context.
*
* - If a secret key is provided, it will be used to sign the event.
* - Otherwise, it will use NIP-46 to sign the event.
*/
export class APISigner implements NostrSigner {
private signer: NostrSigner;
constructor(c: AppContext) {
const seckey = c.get('seckey');
const pubkey = c.get('pubkey');
if (!pubkey) {
throw new HTTPException(401, { message: 'Missing pubkey' });
}
if (seckey) {
this.signer = new NSecSigner(seckey);
} else {
this.signer = new NConnectSigner({
pubkey,
relay: Storages.pubsub,
signer: new AdminSigner(),
timeout: 60000,
});
}
}
async getPublicKey(): Promise<string> {
return this.signer.getPublicKey();
}
async signEvent(event: Omit<NostrEvent, 'id' | 'pubkey' | 'sig'>): Promise<NostrEvent> {
return this.signer.signEvent(event);
}
readonly nip04 = {
encrypt: async (pubkey: string, plaintext: string): Promise<string> => {
return this.signer.nip04!.encrypt(pubkey, plaintext);
},
decrypt: async (pubkey: string, ciphertext: string): Promise<string> => {
return this.signer.nip04!.decrypt(pubkey, ciphertext);
},
};
readonly nip44 = {
encrypt: async (pubkey: string, plaintext: string): Promise<string> => {
return this.signer.nip44!.encrypt(pubkey, plaintext);
},
decrypt: async (pubkey: string, ciphertext: string): Promise<string> => {
return this.signer.nip44!.decrypt(pubkey, ciphertext);
},
};
}