move stuff
This commit is contained in:
parent
d7cb1c38f3
commit
6a1cedd718
6 changed files with 222 additions and 173 deletions
|
|
@ -5,7 +5,7 @@ import * as Types from '../proto/autogenerated/ts/types.js'
|
||||||
import NewNostrTransport, { NostrRequest } from '../proto/autogenerated/ts/nostr_transport.js';
|
import NewNostrTransport, { NostrRequest } from '../proto/autogenerated/ts/nostr_transport.js';
|
||||||
import { ERROR, getLogger } from "./services/helpers/logger.js";
|
import { ERROR, getLogger } from "./services/helpers/logger.js";
|
||||||
import { NdebitData, NofferData } from "@shocknet/clink-sdk";
|
import { NdebitData, NofferData } from "@shocknet/clink-sdk";
|
||||||
import { ManagementManager } from "./services/managementManager.js";
|
import { ManagementManager } from "./services/main/managementManager.js";
|
||||||
|
|
||||||
export default (serverMethods: Types.ServerMethods, mainHandler: Main, nostrSettings: NostrSettings, onClientEvent: (e: { requestId: string }, fromPub: string) => void): { Stop: () => void, Send: NostrSend, Ping: () => Promise<void> } => {
|
export default (serverMethods: Types.ServerMethods, mainHandler: Main, nostrSettings: NostrSettings, onClientEvent: (e: { requestId: string }, fromPub: string) => void): { Stop: () => void, Send: NostrSend, Ping: () => Promise<void> } => {
|
||||||
const log = getLogger({})
|
const log = getLogger({})
|
||||||
|
|
@ -40,7 +40,8 @@ export default (serverMethods: Types.ServerMethods, mainHandler: Main, nostrSett
|
||||||
})
|
})
|
||||||
|
|
||||||
let nostr: Nostr;
|
let nostr: Nostr;
|
||||||
const managementManager = new ManagementManager((...args) => nostr.Send(...args), nostrSettings);
|
const managementManager = new ManagementManager((...args: Parameters<NostrSend>) => nostr.Send(...args), nostrSettings, mainHandler.storage.managementStorage);
|
||||||
|
mainHandler.managementManager = managementManager;
|
||||||
|
|
||||||
nostr = new Nostr(nostrSettings, mainHandler.utils, event => {
|
nostr = new Nostr(nostrSettings, mainHandler.utils, event => {
|
||||||
let j: NostrRequest
|
let j: NostrRequest
|
||||||
|
|
@ -76,7 +77,7 @@ export default (serverMethods: Types.ServerMethods, mainHandler: Main, nostrSett
|
||||||
}, event.startAtNano, event.startAtMs)
|
}, event.startAtNano, event.startAtMs)
|
||||||
})
|
})
|
||||||
|
|
||||||
return { Stop: () => nostr.Stop, Send: (...args) => nostr.Send(...args), Ping: () => nostr.Ping() }
|
return { Stop: () => nostr.Stop, Send: (...args: Parameters<NostrSend>) => nostr.Send(...args), Ping: () => nostr.Ping() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ import { defaultInvoiceExpiry } from "../storage/paymentStorage.js"
|
||||||
import { DebitManager } from "./debitManager.js"
|
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"
|
||||||
|
|
||||||
type UserOperationsSub = {
|
type UserOperationsSub = {
|
||||||
id: string
|
id: string
|
||||||
|
|
@ -51,17 +52,16 @@ export default class {
|
||||||
liquidityProvider: LiquidityProvider
|
liquidityProvider: LiquidityProvider
|
||||||
debitManager: DebitManager
|
debitManager: DebitManager
|
||||||
offerManager: OfferManager
|
offerManager: OfferManager
|
||||||
|
managementManager?: ManagementManager
|
||||||
utils: Utils
|
utils: Utils
|
||||||
rugPullTracker: RugPullTracker
|
rugPullTracker: RugPullTracker
|
||||||
unlocker: Unlocker
|
unlocker: Unlocker
|
||||||
//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, storage: Storage, adminManager: AdminManager, utils: Utils, unlocker: Unlocker) {
|
constructor(settings: MainSettings, utils: Utils, unlocker: Unlocker) {
|
||||||
this.settings = settings
|
this.settings = settings
|
||||||
this.storage = storage
|
|
||||||
this.utils = utils
|
this.utils = utils
|
||||||
this.adminManager = adminManager
|
|
||||||
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)
|
||||||
this.liquidityProvider = new LiquidityProvider(settings.liquiditySettings.liquidityProviderPub, this.utils, this.invoicePaidCb, updateProviderBalance)
|
this.liquidityProvider = new LiquidityProvider(settings.liquiditySettings.liquidityProviderPub, this.utils, this.invoicePaidCb, updateProviderBalance)
|
||||||
|
|
@ -340,6 +340,10 @@ export default class {
|
||||||
log({ unsigned: event })
|
log({ unsigned: event })
|
||||||
this.nostrSend({ type: 'app', appId: invoice.linkedApplication.app_id }, { type: 'event', event }, zapInfo.relays || undefined)
|
this.nostrSend({ type: 'app', appId: invoice.linkedApplication.app_id }, { type: 'event', event }, zapInfo.relays || undefined)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async Start() {
|
||||||
|
// ... existing code ...
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
195
src/services/main/managementManager.ts
Normal file
195
src/services/main/managementManager.ts
Normal file
|
|
@ -0,0 +1,195 @@
|
||||||
|
import { getRepository } from "typeorm";
|
||||||
|
import { User } from "../storage/entity/User.js";
|
||||||
|
import { UserOffer } from "../storage/entity/UserOffer.js";
|
||||||
|
import { ManagementGrant } from "../storage/entity/ManagementGrant.js";
|
||||||
|
import { NostrEvent, NostrSend, NostrSettings } from "../nostr/handler.js";
|
||||||
|
import { ManagementStorage } from "../storage/managementStorage.js";
|
||||||
|
|
||||||
|
export class ManagementManager {
|
||||||
|
private nostrSend: NostrSend;
|
||||||
|
private settings: NostrSettings;
|
||||||
|
private storage: ManagementStorage;
|
||||||
|
|
||||||
|
constructor(nostrSend: NostrSend, settings: NostrSettings, storage: ManagementStorage) {
|
||||||
|
this.nostrSend = nostrSend;
|
||||||
|
this.settings = settings;
|
||||||
|
this.storage = storage;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles an incoming CLINK Manage request
|
||||||
|
* @param event The raw Nostr event
|
||||||
|
*/
|
||||||
|
public async handleRequest(event: NostrEvent) {
|
||||||
|
const app = this.settings.apps.find((a: any) => a.appId === event.appId);
|
||||||
|
if (!app) {
|
||||||
|
console.error(`App with id ${event.appId} not found in settings`);
|
||||||
|
return; // Cannot proceed
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this._validateRequest(event)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const grant = await this._checkGrant(event, app.publicKey);
|
||||||
|
if (!grant) {
|
||||||
|
this.sendErrorResponse(event.pubkey, "Permission denied.", app);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await this._performAction(event, app);
|
||||||
|
}
|
||||||
|
|
||||||
|
private _validateRequest(event: NostrEvent): boolean {
|
||||||
|
// TODO: NIP-44 validation or similar
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async _checkGrant(event: NostrEvent, appPubkey: string): Promise<ManagementGrant | null> {
|
||||||
|
const userIdTag = event.tags.find((t: string[]) => t[0] === 'p');
|
||||||
|
if (!userIdTag) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const userId = userIdTag[1];
|
||||||
|
|
||||||
|
const grant = await this.storage.getGrant(userId, appPubkey);
|
||||||
|
|
||||||
|
if (!grant || (grant.expires_at && grant.expires_at.getTime() < Date.now())) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return grant;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async _performAction(event: NostrEvent, app: {publicKey: string, appId: string}) {
|
||||||
|
const actionTag = event.tags.find((t: string[]) => t[0] === 'a');
|
||||||
|
if (!actionTag) {
|
||||||
|
console.error("No action specified in event");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const action = actionTag[1];
|
||||||
|
|
||||||
|
switch (action) {
|
||||||
|
case "create":
|
||||||
|
await this._createOffer(event, app);
|
||||||
|
break;
|
||||||
|
case "update":
|
||||||
|
await this._updateOffer(event, app);
|
||||||
|
break;
|
||||||
|
case "delete":
|
||||||
|
await this._deleteOffer(event, app);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
console.error(`Unknown action: ${action}`);
|
||||||
|
this.sendErrorResponse(event.pubkey, `Unknown action: ${action}`, app);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async _createOffer(event: NostrEvent, app: {publicKey: string, appId: string}) {
|
||||||
|
const createDetailsTag = event.tags.find((t: string[]) => t[0] === 'd');
|
||||||
|
if (!createDetailsTag || !createDetailsTag[1]) {
|
||||||
|
console.error("No details provided for create action");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const userId = event.tags.find((t: string[]) => t[0] === 'p')![1];
|
||||||
|
|
||||||
|
try {
|
||||||
|
const offerData = JSON.parse(createDetailsTag[1]);
|
||||||
|
const offerRepo = getRepository(UserOffer);
|
||||||
|
const newOffer = offerRepo.create({
|
||||||
|
...offerData,
|
||||||
|
user_id: userId,
|
||||||
|
managing_app_pubkey: app.publicKey
|
||||||
|
});
|
||||||
|
await offerRepo.save(newOffer);
|
||||||
|
this.sendSuccessResponse(event.pubkey, "Offer created successfully", app);
|
||||||
|
} catch (e) {
|
||||||
|
console.error("Failed to parse or save offer data", e);
|
||||||
|
this.sendErrorResponse(event.pubkey, "Failed to create offer", app);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async _updateOffer(event: NostrEvent, app: {publicKey: string, appId: string}) {
|
||||||
|
const updateTags = event.tags.filter((t: string[]) => t[0] === 'd');
|
||||||
|
if (updateTags.length < 2) {
|
||||||
|
console.error("Insufficient details for update action");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const offerIdToUpdate = updateTags[0][1];
|
||||||
|
const updateData = JSON.parse(updateTags[1][1]);
|
||||||
|
const offerRepo = getRepository(UserOffer);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const existingOffer = await offerRepo.findOne({where: { offer_id: offerIdToUpdate }});
|
||||||
|
if (!existingOffer) {
|
||||||
|
console.error(`Offer ${offerIdToUpdate} not found`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (existingOffer.managing_app_pubkey !== app.publicKey) {
|
||||||
|
console.error(`App ${app.publicKey} not authorized to update offer ${offerIdToUpdate}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
offerRepo.merge(existingOffer, updateData);
|
||||||
|
await offerRepo.save(existingOffer);
|
||||||
|
this.sendSuccessResponse(event.pubkey, "Offer updated successfully", app);
|
||||||
|
} catch (e) {
|
||||||
|
console.error("Failed to update offer data", e);
|
||||||
|
this.sendErrorResponse(event.pubkey, "Failed to update offer", app);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async _deleteOffer(event: NostrEvent, app: {publicKey: string, appId: string}) {
|
||||||
|
const deleteDetailsTag = event.tags.find((t: string[]) => t[0] === 'd');
|
||||||
|
if (!deleteDetailsTag || !deleteDetailsTag[1]) {
|
||||||
|
console.error("No details provided for delete action");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const offerIdToDelete = deleteDetailsTag[1];
|
||||||
|
const offerRepo = getRepository(UserOffer);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const offerToDelete = await offerRepo.findOne({where: { offer_id: offerIdToDelete }});
|
||||||
|
if (!offerToDelete) {
|
||||||
|
console.error(`Offer ${offerIdToDelete} not found`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offerToDelete.managing_app_pubkey !== app.publicKey) {
|
||||||
|
console.error(`App ${app.publicKey} not authorized to delete offer ${offerIdToDelete}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await offerRepo.remove(offerToDelete);
|
||||||
|
this.sendSuccessResponse(event.pubkey, "Offer deleted successfully", app);
|
||||||
|
} catch (e) {
|
||||||
|
console.error("Failed to delete offer", e);
|
||||||
|
this.sendErrorResponse(event.pubkey, "Failed to delete offer", app);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private sendSuccessResponse(recipient: string, message: string, app: {publicKey: string, appId: string}) {
|
||||||
|
const responseEvent = {
|
||||||
|
kind: 21003,
|
||||||
|
pubkey: app.publicKey,
|
||||||
|
created_at: Math.floor(Date.now() / 1000),
|
||||||
|
content: JSON.stringify({ status: "success", message }),
|
||||||
|
tags: [['p', recipient]],
|
||||||
|
};
|
||||||
|
this.nostrSend({ type: 'app', appId: app.appId }, { type: 'event', event: responseEvent, encrypt: { toPub: recipient } });
|
||||||
|
}
|
||||||
|
|
||||||
|
private sendErrorResponse(recipient: string, message: string, app: {publicKey: string, appId: string}) {
|
||||||
|
const responseEvent = {
|
||||||
|
kind: 21003,
|
||||||
|
pubkey: app.publicKey,
|
||||||
|
created_at: Math.floor(Date.now() / 1000),
|
||||||
|
content: JSON.stringify({ status: "error", message }),
|
||||||
|
tags: [['p', recipient]],
|
||||||
|
};
|
||||||
|
this.nostrSend({ type: 'app', appId: app.appId }, { type: 'event', event: responseEvent, encrypt: { toPub: recipient } });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,167 +0,0 @@
|
||||||
import { getRepository } from "typeorm";
|
|
||||||
import { User } from "./storage/entity/User";
|
|
||||||
import { UserOffer } from "./storage/entity/UserOffer";
|
|
||||||
import { ManagementGrant } from "./storage/entity/ManagementGrant";
|
|
||||||
import { NostrEvent, NostrSend, NostrSettings } from "./nostr/handler.js";
|
|
||||||
|
|
||||||
export class ManagementManager {
|
|
||||||
private nostrSend: NostrSend;
|
|
||||||
private settings: NostrSettings;
|
|
||||||
|
|
||||||
constructor(nostrSend: NostrSend, settings: NostrSettings) {
|
|
||||||
this.nostrSend = nostrSend;
|
|
||||||
this.settings = settings;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles an incoming CLINK Manage request
|
|
||||||
* @param event The raw Nostr event
|
|
||||||
*/
|
|
||||||
public async handleRequest(event: NostrEvent) {
|
|
||||||
const app = this.settings.apps.find(a => a.appId === event.appId);
|
|
||||||
if (!app) {
|
|
||||||
console.error(`App with id ${event.appId} not found in settings`);
|
|
||||||
return; // Cannot proceed
|
|
||||||
}
|
|
||||||
const appPubkey = app.publicKey;
|
|
||||||
|
|
||||||
// Check grant
|
|
||||||
const userIdTag = event.tags.find((t: string[]) => t[0] === 'p');
|
|
||||||
if (!userIdTag) {
|
|
||||||
console.error("No user specified in event");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const userId = userIdTag[1];
|
|
||||||
const requestingPubkey = event.pubkey;
|
|
||||||
|
|
||||||
const grantRepo = getRepository(ManagementGrant);
|
|
||||||
const grant = await grantRepo.findOne({ where: { user_id: userId, app_pubkey: appPubkey } });
|
|
||||||
|
|
||||||
if (!grant) {
|
|
||||||
console.error(`No management grant found for app ${appPubkey} and user ${userId}`);
|
|
||||||
this.sendErrorResponse(requestingPubkey, `No management grant found for app`, app);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (grant.expires_at && grant.expires_at.getTime() < Date.now()) {
|
|
||||||
console.error(`Management grant for app ${appPubkey} and user ${userId} has expired`);
|
|
||||||
this.sendErrorResponse(requestingPubkey, `Management grant has expired`, app);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Perform action
|
|
||||||
const actionTag = event.tags.find((t: string[]) => t[0] === 'a');
|
|
||||||
if (!actionTag) {
|
|
||||||
console.error("No action specified in event");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const action = actionTag[1];
|
|
||||||
const offerRepo = getRepository(UserOffer);
|
|
||||||
|
|
||||||
switch (action) {
|
|
||||||
case "create":
|
|
||||||
const createDetailsTag = event.tags.find((t: string[]) => t[0] === 'd');
|
|
||||||
if (!createDetailsTag || !createDetailsTag[1]) {
|
|
||||||
console.error("No details provided for create action");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
const offerData = JSON.parse(createDetailsTag[1]);
|
|
||||||
const newOffer = offerRepo.create({
|
|
||||||
...offerData,
|
|
||||||
user_id: userId,
|
|
||||||
managing_app_pubkey: appPubkey
|
|
||||||
});
|
|
||||||
await offerRepo.save(newOffer);
|
|
||||||
this.sendSuccessResponse(requestingPubkey, "Offer created successfully", app);
|
|
||||||
} catch (e) {
|
|
||||||
console.error("Failed to parse or save offer data", e);
|
|
||||||
this.sendErrorResponse(requestingPubkey, "Failed to create offer", app);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "update":
|
|
||||||
const updateTags = event.tags.filter((t: string[]) => t[0] === 'd');
|
|
||||||
if (updateTags.length < 2) {
|
|
||||||
console.error("Insufficient details for update action");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const offerIdToUpdate = updateTags[0][1];
|
|
||||||
const updateData = JSON.parse(updateTags[1][1]);
|
|
||||||
|
|
||||||
try {
|
|
||||||
const existingOffer = await offerRepo.findOne({where: { offer_id: offerIdToUpdate }});
|
|
||||||
if (!existingOffer) {
|
|
||||||
console.error(`Offer ${offerIdToUpdate} not found`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (existingOffer.managing_app_pubkey !== appPubkey) {
|
|
||||||
console.error(`App ${appPubkey} not authorized to update offer ${offerIdToUpdate}`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
offerRepo.merge(existingOffer, updateData);
|
|
||||||
await offerRepo.save(existingOffer);
|
|
||||||
this.sendSuccessResponse(requestingPubkey, "Offer updated successfully", app);
|
|
||||||
} catch (e) {
|
|
||||||
console.error("Failed to update offer data", e);
|
|
||||||
this.sendErrorResponse(requestingPubkey, "Failed to update offer", app);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "delete":
|
|
||||||
const deleteDetailsTag = event.tags.find((t: string[]) => t[0] === 'd');
|
|
||||||
if (!deleteDetailsTag || !deleteDetailsTag[1]) {
|
|
||||||
console.error("No details provided for delete action");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const offerIdToDelete = deleteDetailsTag[1];
|
|
||||||
|
|
||||||
try {
|
|
||||||
const offerToDelete = await offerRepo.findOne({where: { offer_id: offerIdToDelete }});
|
|
||||||
if (!offerToDelete) {
|
|
||||||
console.error(`Offer ${offerIdToDelete} not found`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (offerToDelete.managing_app_pubkey !== appPubkey) {
|
|
||||||
console.error(`App ${appPubkey} not authorized to delete offer ${offerIdToDelete}`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await offerRepo.remove(offerToDelete);
|
|
||||||
this.sendSuccessResponse(requestingPubkey, "Offer deleted successfully", app);
|
|
||||||
} catch (e) {
|
|
||||||
console.error("Failed to delete offer", e);
|
|
||||||
this.sendErrorResponse(requestingPubkey, "Failed to delete offer", app);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
console.error(`Unknown action: ${action}`);
|
|
||||||
this.sendErrorResponse(requestingPubkey, `Unknown action: ${action}`, app);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private sendSuccessResponse(recipient: string, message: string, app: {publicKey: string, appId: string}) {
|
|
||||||
const responseEvent = {
|
|
||||||
kind: 21003,
|
|
||||||
pubkey: app.publicKey,
|
|
||||||
created_at: Math.floor(Date.now() / 1000),
|
|
||||||
content: JSON.stringify({ status: "success", message }),
|
|
||||||
tags: [['p', recipient]],
|
|
||||||
};
|
|
||||||
this.nostrSend({ type: 'app', appId: app.appId }, { type: 'event', event: responseEvent, encrypt: { toPub: recipient } });
|
|
||||||
}
|
|
||||||
|
|
||||||
private sendErrorResponse(recipient: string, message: string, app: {publicKey: string, appId: string}) {
|
|
||||||
const responseEvent = {
|
|
||||||
kind: 21003,
|
|
||||||
pubkey: app.publicKey,
|
|
||||||
created_at: Math.floor(Date.now() / 1000),
|
|
||||||
content: JSON.stringify({ status: "error", message }),
|
|
||||||
tags: [['p', recipient]],
|
|
||||||
};
|
|
||||||
this.nostrSend({ type: 'app', appId: app.appId }, { type: 'event', event: responseEvent, encrypt: { toPub: recipient } });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -10,6 +10,7 @@ import EventsLogManager from "./eventsLog.js";
|
||||||
import { LiquidityStorage } from "./liquidityStorage.js";
|
import { LiquidityStorage } from "./liquidityStorage.js";
|
||||||
import DebitStorage from "./debitStorage.js"
|
import DebitStorage from "./debitStorage.js"
|
||||||
import OfferStorage from "./offerStorage.js"
|
import OfferStorage from "./offerStorage.js"
|
||||||
|
import { ManagementStorage } from "./managementStorage.js";
|
||||||
import { StorageInterface, TX } from "./db/storageInterface.js";
|
import { StorageInterface, TX } from "./db/storageInterface.js";
|
||||||
import { PubLogger } from "../helpers/logger.js"
|
import { PubLogger } from "../helpers/logger.js"
|
||||||
import { TlvStorageFactory } from './tlv/tlvFilesStorageFactory.js';
|
import { TlvStorageFactory } from './tlv/tlvFilesStorageFactory.js';
|
||||||
|
|
@ -36,6 +37,7 @@ export default class {
|
||||||
liquidityStorage: LiquidityStorage
|
liquidityStorage: LiquidityStorage
|
||||||
debitStorage: DebitStorage
|
debitStorage: DebitStorage
|
||||||
offerStorage: OfferStorage
|
offerStorage: OfferStorage
|
||||||
|
managementStorage: ManagementStorage
|
||||||
eventsLog: EventsLogManager
|
eventsLog: EventsLogManager
|
||||||
utils: Utils
|
utils: Utils
|
||||||
constructor(settings: StorageSettings, utils: Utils) {
|
constructor(settings: StorageSettings, utils: Utils) {
|
||||||
|
|
@ -58,6 +60,7 @@ export default class {
|
||||||
this.liquidityStorage = new LiquidityStorage(this.dbs)
|
this.liquidityStorage = new LiquidityStorage(this.dbs)
|
||||||
this.debitStorage = new DebitStorage(this.dbs)
|
this.debitStorage = new DebitStorage(this.dbs)
|
||||||
this.offerStorage = new OfferStorage(this.dbs)
|
this.offerStorage = new OfferStorage(this.dbs)
|
||||||
|
this.managementStorage = new ManagementStorage(this.dbs);
|
||||||
try { if (this.settings.dataDir) fs.mkdirSync(this.settings.dataDir) } catch (e) { }
|
try { if (this.settings.dataDir) fs.mkdirSync(this.settings.dataDir) } catch (e) { }
|
||||||
/* const executedMetricsMigrations = */ await this.metricsStorage.Connect()
|
/* const executedMetricsMigrations = */ await this.metricsStorage.Connect()
|
||||||
/* if (executedMigrations.length > 0) {
|
/* if (executedMigrations.length > 0) {
|
||||||
|
|
|
||||||
13
src/services/storage/managementStorage.ts
Normal file
13
src/services/storage/managementStorage.ts
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
import { StorageInterface } from "./db/storageInterface.js";
|
||||||
|
import { ManagementGrant } from "./entity/ManagementGrant.js";
|
||||||
|
|
||||||
|
export class ManagementStorage {
|
||||||
|
private dbs: StorageInterface;
|
||||||
|
constructor(dbs: StorageInterface) {
|
||||||
|
this.dbs = dbs;
|
||||||
|
}
|
||||||
|
|
||||||
|
getGrant(user_id: string, app_pubkey: string) {
|
||||||
|
return this.dbs.FindOne<ManagementGrant>('ManagementGrant' as any, { where: { user_id, app_pubkey } });
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue