This commit is contained in:
shocknet-justin 2025-06-15 13:47:58 -04:00
parent 6a1cedd718
commit 1950bebd74
4 changed files with 36 additions and 21 deletions

View file

@ -40,7 +40,7 @@ export default (serverMethods: Types.ServerMethods, mainHandler: Main, nostrSett
}) })
let nostr: Nostr; let nostr: Nostr;
const managementManager = new ManagementManager((...args: Parameters<NostrSend>) => nostr.Send(...args), nostrSettings, mainHandler.storage.managementStorage); const managementManager = new ManagementManager((...args: Parameters<NostrSend>) => nostr.Send(...args), mainHandler.storage);
mainHandler.managementManager = managementManager; mainHandler.managementManager = managementManager;
nostr = new Nostr(nostrSettings, mainHandler.utils, event => { nostr = new Nostr(nostrSettings, mainHandler.utils, event => {

View file

@ -26,6 +26,7 @@ import { DebitManager } from "./debitManager.js"
import { OfferManager } from "./offerManager.js" import { OfferManager } from "./offerManager.js"
import webRTC from "../webRTC/index.js" import webRTC from "../webRTC/index.js"
import { ManagementManager } from "./managementManager.js" import { ManagementManager } from "./managementManager.js"
import NostrSubprocess, { LoadNosrtSettingsFromEnv } from "../nostr/index.js"
type UserOperationsSub = { type UserOperationsSub = {
id: string id: string
@ -59,8 +60,10 @@ export default class {
//webRTC: webRTC //webRTC: webRTC
nostrSend: NostrSend = () => { getLogger({})("nostr send not initialized yet") } nostrSend: NostrSend = () => { getLogger({})("nostr send not initialized yet") }
nostrProcessPing: (() => Promise<void>) | null = null nostrProcessPing: (() => Promise<void>) | null = null
constructor(settings: MainSettings, utils: Utils, unlocker: Unlocker) { constructor(settings: MainSettings, storage: Storage, adminManager: AdminManager, utils: Utils, unlocker: Unlocker) {
this.settings = settings this.settings = settings
this.storage = storage
this.adminManager = adminManager
this.utils = utils this.utils = utils
this.unlocker = unlocker this.unlocker = unlocker
const updateProviderBalance = (b: number) => this.storage.liquidityStorage.IncrementTrackedProviderBalance('lnPub', settings.liquiditySettings.liquidityProviderPub, b) const updateProviderBalance = (b: number) => this.storage.liquidityStorage.IncrementTrackedProviderBalance('lnPub', settings.liquiditySettings.liquidityProviderPub, b)
@ -76,6 +79,8 @@ export default class {
this.appUserManager = new AppUserManager(this.storage, this.settings, this.applicationManager) this.appUserManager = new AppUserManager(this.storage, this.settings, this.applicationManager)
this.debitManager = new DebitManager(this.storage, this.lnd, this.applicationManager) this.debitManager = new DebitManager(this.storage, this.lnd, this.applicationManager)
this.offerManager = new OfferManager(this.storage, this.lnd, this.applicationManager, this.productManager, this.liquidityManager) this.offerManager = new OfferManager(this.storage, this.lnd, this.applicationManager, this.productManager, this.liquidityManager)
const nostrSettings = LoadNosrtSettingsFromEnv()
this.managementManager = new ManagementManager(this.nostrSend, this.storage)
//this.webRTC = new webRTC(this.storage, this.utils) //this.webRTC = new webRTC(this.storage, this.utils)
} }

View file

@ -2,17 +2,15 @@ import { getRepository } from "typeorm";
import { User } from "../storage/entity/User.js"; import { User } from "../storage/entity/User.js";
import { UserOffer } from "../storage/entity/UserOffer.js"; import { UserOffer } from "../storage/entity/UserOffer.js";
import { ManagementGrant } from "../storage/entity/ManagementGrant.js"; import { ManagementGrant } from "../storage/entity/ManagementGrant.js";
import { NostrEvent, NostrSend, NostrSettings } from "../nostr/handler.js"; import { NostrEvent, NostrSend } from "../nostr/handler.js";
import { ManagementStorage } from "../storage/managementStorage.js"; import Storage from "../storage/index.js";
export class ManagementManager { export class ManagementManager {
private nostrSend: NostrSend; private nostrSend: NostrSend;
private settings: NostrSettings; private storage: Storage;
private storage: ManagementStorage;
constructor(nostrSend: NostrSend, settings: NostrSettings, storage: ManagementStorage) { constructor(nostrSend: NostrSend, storage: Storage) {
this.nostrSend = nostrSend; this.nostrSend = nostrSend;
this.settings = settings;
this.storage = storage; this.storage = storage;
} }
@ -21,23 +19,31 @@ export class ManagementManager {
* @param event The raw Nostr event * @param event The raw Nostr event
*/ */
public async handleRequest(event: NostrEvent) { public async handleRequest(event: NostrEvent) {
const app = this.settings.apps.find((a: any) => a.appId === event.appId); let app;
if (!app) { try {
console.error(`App with id ${event.appId} not found in settings`); app = await this.storage.applicationStorage.GetApplication(event.appId);
return; // Cannot proceed } catch {
console.error(`App with id ${event.appId} not found`);
return;
} }
if (!this._validateRequest(event)) { if (!this._validateRequest(event)) {
return; return;
} }
const grant = await this._checkGrant(event, app.publicKey); if (!app.nostr_public_key) {
if (!grant) { console.error(`App with id ${event.appId} has no nostr public key configured.`);
this.sendErrorResponse(event.pubkey, "Permission denied.", app);
return; return;
} }
await this._performAction(event, app); const grant = await this._checkGrant(event, app.nostr_public_key);
if (!grant) {
this.sendErrorResponse(event.pubkey, "Permission denied.", { publicKey: app.nostr_public_key, appId: app.app_id });
return;
}
const appInfo = { publicKey: app.nostr_public_key, appId: app.app_id };
await this._performAction(event, appInfo);
} }
private _validateRequest(event: NostrEvent): boolean { private _validateRequest(event: NostrEvent): boolean {
@ -52,7 +58,7 @@ export class ManagementManager {
} }
const userId = userIdTag[1]; const userId = userIdTag[1];
const grant = await this.storage.getGrant(userId, appPubkey); const grant = await this.storage.managementStorage.getGrant(userId, appPubkey);
if (!grant || (grant.expires_at && grant.expires_at.getTime() < Date.now())) { if (!grant || (grant.expires_at && grant.expires_at.getTime() < Date.now())) {
return null; return null;
@ -61,7 +67,7 @@ export class ManagementManager {
return grant; return grant;
} }
private async _performAction(event: NostrEvent, app: {publicKey: string, appId: string}) { private async _performAction(event: NostrEvent, app: { publicKey: string; appId: string }) {
const actionTag = event.tags.find((t: string[]) => t[0] === 'a'); const actionTag = event.tags.find((t: string[]) => t[0] === 'a');
if (!actionTag) { if (!actionTag) {
console.error("No action specified in event"); console.error("No action specified in event");
@ -86,7 +92,7 @@ export class ManagementManager {
} }
} }
private async _createOffer(event: NostrEvent, app: {publicKey: string, appId: string}) { private async _createOffer(event: NostrEvent, app: { publicKey: string; appId: string }) {
const createDetailsTag = event.tags.find((t: string[]) => t[0] === 'd'); const createDetailsTag = event.tags.find((t: string[]) => t[0] === 'd');
if (!createDetailsTag || !createDetailsTag[1]) { if (!createDetailsTag || !createDetailsTag[1]) {
console.error("No details provided for create action"); console.error("No details provided for create action");
@ -111,7 +117,7 @@ export class ManagementManager {
} }
} }
private async _updateOffer(event: NostrEvent, app: {publicKey: string, appId: string}) { private async _updateOffer(event: NostrEvent, app: { publicKey: string; appId: string }) {
const updateTags = event.tags.filter((t: string[]) => t[0] === 'd'); const updateTags = event.tags.filter((t: string[]) => t[0] === 'd');
if (updateTags.length < 2) { if (updateTags.length < 2) {
console.error("Insufficient details for update action"); console.error("Insufficient details for update action");
@ -142,7 +148,7 @@ export class ManagementManager {
} }
} }
private async _deleteOffer(event: NostrEvent, app: {publicKey: string, appId: string}) { private async _deleteOffer(event: NostrEvent, app: { publicKey: string; appId: string }) {
const deleteDetailsTag = event.tags.find((t: string[]) => t[0] === 'd'); const deleteDetailsTag = event.tags.find((t: string[]) => t[0] === 'd');
if (!deleteDetailsTag || !deleteDetailsTag[1]) { if (!deleteDetailsTag || !deleteDetailsTag[1]) {
console.error("No details provided for delete action"); console.error("No details provided for delete action");

View file

@ -10,4 +10,8 @@ export class ManagementStorage {
getGrant(user_id: string, app_pubkey: string) { getGrant(user_id: string, app_pubkey: string) {
return this.dbs.FindOne<ManagementGrant>('ManagementGrant' as any, { where: { user_id, app_pubkey } }); return this.dbs.FindOne<ManagementGrant>('ManagementGrant' as any, { where: { user_id, app_pubkey } });
} }
async addGrant(user_id: string, app_pubkey: string, expires_at?: Date) {
return this.dbs.CreateAndSave<ManagementGrant>('ManagementGrant' as any, { user_id, app_pubkey, expires_at });
}
} }