db + auth routes
This commit is contained in:
parent
d2b2418e21
commit
6df5752d46
17 changed files with 553 additions and 12 deletions
|
|
@ -15,6 +15,7 @@ import { LspOrder } from "./build/src/services/storage/entity/LspOrder.js"
|
|||
import { LndNodeInfo } from "./build/src/services/storage/entity/LndNodeInfo.js"
|
||||
import { TrackedProvider } from "./build/src/services/storage/entity/TrackedProvider.js"
|
||||
import { InviteToken } from "./build/src/services/storage/entity/InviteToken.js"
|
||||
import { DebitAccess } from "./build/src/services/storage/entity/DebitAccess.js"
|
||||
|
||||
import { Initial1703170309875 } from './build/src/services/storage/migrations/1703170309875-initial.js'
|
||||
import { LspOrder1718387847693 } from './build/src/services/storage/migrations/1718387847693-lsp_order.js'
|
||||
|
|
@ -22,13 +23,14 @@ import { LndNodeInfo1720187506189 } from './build/src/services/storage/migration
|
|||
import { LiquidityProvider1719335699480 } from './build/src/services/storage/migrations/1719335699480-liquidity_provider.js'
|
||||
import { CreateInviteTokenTable1721751414878 } from './build/src/services/storage/migrations/1721751414878-create_invite_token_table.js'
|
||||
import { PaymentIndex1721760297610 } from './build/src/services/storage/migrations/1721760297610-payment_index.js'
|
||||
import { DebitAccess1726496225078 } from './build/src/services/storage/migrations/1726496225078-debit_access.js'
|
||||
export default new DataSource({
|
||||
type: "sqlite",
|
||||
database: "db.sqlite",
|
||||
// logging: true,
|
||||
migrations: [Initial1703170309875, LspOrder1718387847693, LiquidityProvider1719335699480, LndNodeInfo1720187506189, CreateInviteTokenTable1721751414878, PaymentIndex1721760297610],
|
||||
migrations: [Initial1703170309875, LspOrder1718387847693, LiquidityProvider1719335699480, LndNodeInfo1720187506189, CreateInviteTokenTable1721751414878, PaymentIndex1721760297610, DebitAccess1726496225078],
|
||||
entities: [User, UserReceivingInvoice, UserReceivingAddress, AddressReceivingTransaction, UserInvoicePayment, UserTransactionPayment,
|
||||
UserBasicAuth, UserEphemeralKey, Product, UserToUserPayment, Application, ApplicationUser, UserToUserPayment, LspOrder, LndNodeInfo, TrackedProvider, InviteToken],
|
||||
UserBasicAuth, UserEphemeralKey, Product, UserToUserPayment, Application, ApplicationUser, UserToUserPayment, LspOrder, LndNodeInfo, TrackedProvider, InviteToken, DebitAccess],
|
||||
// synchronize: true,
|
||||
})
|
||||
//npx typeorm migration:generate ./src/services/storage/migrations/lnd_node_info -d ./datasource.js
|
||||
//npx typeorm migration:generate ./src/services/storage/migrations/debit_access -d ./datasource.js
|
||||
|
|
@ -28,6 +28,11 @@ The nostr server will send back a message response, and inside the body there wi
|
|||
- input: [AuthAppRequest](#AuthAppRequest)
|
||||
- output: [AuthApp](#AuthApp)
|
||||
|
||||
- AuthorizeDebit
|
||||
- auth type: __User__
|
||||
- input: [DebitAuthorization](#DebitAuthorization)
|
||||
- output: [AuthorizedDebit](#AuthorizedDebit)
|
||||
|
||||
- BanUser
|
||||
- auth type: __Admin__
|
||||
- input: [BanUserRequest](#BanUserRequest)
|
||||
|
|
@ -58,6 +63,11 @@ The nostr server will send back a message response, and inside the body there wi
|
|||
- input: [AppsMetricsRequest](#AppsMetricsRequest)
|
||||
- output: [AppsMetrics](#AppsMetrics)
|
||||
|
||||
- GetAuthorizedDebits
|
||||
- auth type: __User__
|
||||
- This methods has an __empty__ __request__ body
|
||||
- output: [AuthorizedDebits](#AuthorizedDebits)
|
||||
|
||||
- GetHttpCreds
|
||||
- auth type: __User__
|
||||
- This methods has an __empty__ __request__ body
|
||||
|
|
@ -170,6 +180,11 @@ The nostr server will send back a message response, and inside the body there wi
|
|||
- input: [PayInvoiceRequest](#PayInvoiceRequest)
|
||||
- output: [PayInvoiceResponse](#PayInvoiceResponse)
|
||||
|
||||
- RemoveAuthorizedDebit
|
||||
- auth type: __User__
|
||||
- input: [RemoveAuthorizedDebitRequest](#RemoveAuthorizedDebitRequest)
|
||||
- This methods has an __empty__ __response__ body
|
||||
|
||||
- UseInviteLink
|
||||
- auth type: __GuestWithPub__
|
||||
- input: [UseInviteLinkRequest](#UseInviteLinkRequest)
|
||||
|
|
@ -256,6 +271,13 @@ The nostr server will send back a message response, and inside the body there wi
|
|||
- input: [AuthAppRequest](#AuthAppRequest)
|
||||
- output: [AuthApp](#AuthApp)
|
||||
|
||||
- AuthorizeDebit
|
||||
- auth type: __User__
|
||||
- http method: __post__
|
||||
- http route: __/api/user/debit/authorize__
|
||||
- input: [DebitAuthorization](#DebitAuthorization)
|
||||
- output: [AuthorizedDebit](#AuthorizedDebit)
|
||||
|
||||
- BanUser
|
||||
- auth type: __Admin__
|
||||
- http method: __post__
|
||||
|
|
@ -326,6 +348,13 @@ The nostr server will send back a message response, and inside the body there wi
|
|||
- input: [AppsMetricsRequest](#AppsMetricsRequest)
|
||||
- output: [AppsMetrics](#AppsMetrics)
|
||||
|
||||
- GetAuthorizedDebits
|
||||
- auth type: __User__
|
||||
- http method: __get__
|
||||
- http route: __/api/user/debit/get__
|
||||
- This methods has an __empty__ __request__ body
|
||||
- output: [AuthorizedDebits](#AuthorizedDebits)
|
||||
|
||||
- GetHttpCreds
|
||||
- auth type: __User__
|
||||
- http method: __post__
|
||||
|
|
@ -545,6 +574,13 @@ The nostr server will send back a message response, and inside the body there wi
|
|||
- input: [PayInvoiceRequest](#PayInvoiceRequest)
|
||||
- output: [PayInvoiceResponse](#PayInvoiceResponse)
|
||||
|
||||
- RemoveAuthorizedDebit
|
||||
- auth type: __User__
|
||||
- http method: __post__
|
||||
- http route: __/api/user/debit/remove__
|
||||
- input: [RemoveAuthorizedDebitRequest](#RemoveAuthorizedDebitRequest)
|
||||
- This methods has an __empty__ __response__ body
|
||||
|
||||
- RequestNPubLinkingToken
|
||||
- auth type: __App__
|
||||
- http method: __post__
|
||||
|
|
@ -675,6 +711,14 @@ The nostr server will send back a message response, and inside the body there wi
|
|||
- __allow_user_creation__: _boolean_ *this field is optional
|
||||
- __name__: _string_
|
||||
|
||||
### AuthorizedDebit
|
||||
- __debit_id__: _string_
|
||||
- __debit_type__: _[AuthorizedDebitType](#AuthorizedDebitType)_
|
||||
- __key__: _string_
|
||||
|
||||
### AuthorizedDebits
|
||||
- __debits__: ARRAY of: _[AuthorizedDebit](#AuthorizedDebit)_
|
||||
|
||||
### BanUserRequest
|
||||
- __user_id__: _string_
|
||||
|
||||
|
|
@ -702,6 +746,9 @@ The nostr server will send back a message response, and inside the body there wi
|
|||
### CreateOneTimeInviteLinkResponse
|
||||
- __invitation_link__: _string_
|
||||
|
||||
### DebitAuthorization
|
||||
- __authorize_npub__: _string_ *this field is optional
|
||||
|
||||
### DecodeInvoiceRequest
|
||||
- __invoice__: _string_
|
||||
|
||||
|
|
@ -903,6 +950,9 @@ The nostr server will send back a message response, and inside the body there wi
|
|||
### RelaysMigration
|
||||
- __relays__: ARRAY of: _string_
|
||||
|
||||
### RemoveAuthorizedDebitRequest
|
||||
- __debit_id__: _string_
|
||||
|
||||
### RequestNPubLinkingTokenRequest
|
||||
- __user_identifier__: _string_
|
||||
|
||||
|
|
@ -1003,6 +1053,10 @@ The nostr server will send back a message response, and inside the body there wi
|
|||
- __TAPROOT_PUBKEY__
|
||||
- __WITNESS_PUBKEY_HASH__
|
||||
|
||||
### AuthorizedDebitType
|
||||
- __KEY__
|
||||
- __NPUB__
|
||||
|
||||
### UserOperationType
|
||||
- __INCOMING_INVOICE__
|
||||
- __INCOMING_TX__
|
||||
|
|
|
|||
|
|
@ -166,6 +166,28 @@ export default (methods: Types.ServerMethods, opts: ServerOptions) => {
|
|||
opts.metricsCallback([{ ...info, ...stats, ...authContext }])
|
||||
} catch (ex) { const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e }
|
||||
})
|
||||
if (!opts.allowNotImplementedMethods && !methods.AuthorizeDebit) throw new Error('method: AuthorizeDebit is not implemented')
|
||||
app.post('/api/user/debit/authorize', async (req, res) => {
|
||||
const info: Types.RequestInfo = { rpcName: 'AuthorizeDebit', batch: false, nostr: false, batchSize: 0}
|
||||
const stats: Types.RequestStats = { startMs:req.startTimeMs || 0, start:req.startTime || 0n, parse: process.hrtime.bigint(), guard: 0n, validate: 0n, handle: 0n }
|
||||
let authCtx: Types.AuthContext = {}
|
||||
try {
|
||||
if (!methods.AuthorizeDebit) throw new Error('method: AuthorizeDebit is not implemented')
|
||||
const authContext = await opts.UserAuthGuard(req.headers['authorization'])
|
||||
authCtx = authContext
|
||||
stats.guard = process.hrtime.bigint()
|
||||
const request = req.body
|
||||
const error = Types.DebitAuthorizationValidate(request)
|
||||
stats.validate = process.hrtime.bigint()
|
||||
if (error !== null) return logErrorAndReturnResponse(error, 'invalid request body', res, logger, { ...info, ...stats, ...authContext }, opts.metricsCallback)
|
||||
const query = req.query
|
||||
const params = req.params
|
||||
const response = await methods.AuthorizeDebit({rpcName:'AuthorizeDebit', ctx:authContext , req: request})
|
||||
stats.handle = process.hrtime.bigint()
|
||||
res.json({status: 'OK', ...response})
|
||||
opts.metricsCallback([{ ...info, ...stats, ...authContext }])
|
||||
} catch (ex) { const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e }
|
||||
})
|
||||
if (!opts.allowNotImplementedMethods && !methods.BanUser) throw new Error('method: BanUser is not implemented')
|
||||
app.post('/api/admin/user/ban', async (req, res) => {
|
||||
const info: Types.RequestInfo = { rpcName: 'BanUser', batch: false, nostr: false, batchSize: 0}
|
||||
|
|
@ -221,6 +243,18 @@ export default (methods: Types.ServerMethods, opts: ServerOptions) => {
|
|||
callsMetrics.push({ ...opInfo, ...opStats, ...ctx })
|
||||
}
|
||||
break
|
||||
case 'AuthorizeDebit':
|
||||
if (!methods.AuthorizeDebit) {
|
||||
throw new Error('method AuthorizeDebit not found' )
|
||||
} else {
|
||||
const error = Types.DebitAuthorizationValidate(operation.req)
|
||||
opStats.validate = process.hrtime.bigint()
|
||||
if (error !== null) throw error
|
||||
const res = await methods.AuthorizeDebit({...operation, ctx}); responses.push({ status: 'OK', ...res })
|
||||
opStats.handle = process.hrtime.bigint()
|
||||
callsMetrics.push({ ...opInfo, ...opStats, ...ctx })
|
||||
}
|
||||
break
|
||||
case 'DecodeInvoice':
|
||||
if (!methods.DecodeInvoice) {
|
||||
throw new Error('method DecodeInvoice not found' )
|
||||
|
|
@ -245,6 +279,16 @@ export default (methods: Types.ServerMethods, opts: ServerOptions) => {
|
|||
callsMetrics.push({ ...opInfo, ...opStats, ...ctx })
|
||||
}
|
||||
break
|
||||
case 'GetAuthorizedDebits':
|
||||
if (!methods.GetAuthorizedDebits) {
|
||||
throw new Error('method GetAuthorizedDebits not found' )
|
||||
} else {
|
||||
opStats.validate = opStats.guard
|
||||
const res = await methods.GetAuthorizedDebits({...operation, ctx}); responses.push({ status: 'OK', ...res })
|
||||
opStats.handle = process.hrtime.bigint()
|
||||
callsMetrics.push({ ...opInfo, ...opStats, ...ctx })
|
||||
}
|
||||
break
|
||||
case 'GetLNURLChannelLink':
|
||||
if (!methods.GetLNURLChannelLink) {
|
||||
throw new Error('method GetLNURLChannelLink not found' )
|
||||
|
|
@ -379,6 +423,18 @@ export default (methods: Types.ServerMethods, opts: ServerOptions) => {
|
|||
callsMetrics.push({ ...opInfo, ...opStats, ...ctx })
|
||||
}
|
||||
break
|
||||
case 'RemoveAuthorizedDebit':
|
||||
if (!methods.RemoveAuthorizedDebit) {
|
||||
throw new Error('method RemoveAuthorizedDebit not found' )
|
||||
} else {
|
||||
const error = Types.RemoveAuthorizedDebitRequestValidate(operation.req)
|
||||
opStats.validate = process.hrtime.bigint()
|
||||
if (error !== null) throw error
|
||||
await methods.RemoveAuthorizedDebit({...operation, ctx}); responses.push({ status: 'OK' })
|
||||
opStats.handle = process.hrtime.bigint()
|
||||
callsMetrics.push({ ...opInfo, ...opStats, ...ctx })
|
||||
}
|
||||
break
|
||||
case 'UserHealth':
|
||||
if (!methods.UserHealth) {
|
||||
throw new Error('method UserHealth not found' )
|
||||
|
|
@ -572,6 +628,25 @@ export default (methods: Types.ServerMethods, opts: ServerOptions) => {
|
|||
opts.metricsCallback([{ ...info, ...stats, ...authContext }])
|
||||
} catch (ex) { const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e }
|
||||
})
|
||||
if (!opts.allowNotImplementedMethods && !methods.GetAuthorizedDebits) throw new Error('method: GetAuthorizedDebits is not implemented')
|
||||
app.get('/api/user/debit/get', async (req, res) => {
|
||||
const info: Types.RequestInfo = { rpcName: 'GetAuthorizedDebits', batch: false, nostr: false, batchSize: 0}
|
||||
const stats: Types.RequestStats = { startMs:req.startTimeMs || 0, start:req.startTime || 0n, parse: process.hrtime.bigint(), guard: 0n, validate: 0n, handle: 0n }
|
||||
let authCtx: Types.AuthContext = {}
|
||||
try {
|
||||
if (!methods.GetAuthorizedDebits) throw new Error('method: GetAuthorizedDebits is not implemented')
|
||||
const authContext = await opts.UserAuthGuard(req.headers['authorization'])
|
||||
authCtx = authContext
|
||||
stats.guard = process.hrtime.bigint()
|
||||
stats.validate = stats.guard
|
||||
const query = req.query
|
||||
const params = req.params
|
||||
const response = await methods.GetAuthorizedDebits({rpcName:'GetAuthorizedDebits', ctx:authContext })
|
||||
stats.handle = process.hrtime.bigint()
|
||||
res.json({status: 'OK', ...response})
|
||||
opts.metricsCallback([{ ...info, ...stats, ...authContext }])
|
||||
} catch (ex) { const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e }
|
||||
})
|
||||
if (!opts.allowNotImplementedMethods && !methods.GetInviteLinkState) throw new Error('method: GetInviteLinkState is not implemented')
|
||||
app.post('/api/admin/app/invite/get', async (req, res) => {
|
||||
const info: Types.RequestInfo = { rpcName: 'GetInviteLinkState', batch: false, nostr: false, batchSize: 0}
|
||||
|
|
@ -1102,6 +1177,28 @@ export default (methods: Types.ServerMethods, opts: ServerOptions) => {
|
|||
opts.metricsCallback([{ ...info, ...stats, ...authContext }])
|
||||
} catch (ex) { const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e }
|
||||
})
|
||||
if (!opts.allowNotImplementedMethods && !methods.RemoveAuthorizedDebit) throw new Error('method: RemoveAuthorizedDebit is not implemented')
|
||||
app.post('/api/user/debit/remove', async (req, res) => {
|
||||
const info: Types.RequestInfo = { rpcName: 'RemoveAuthorizedDebit', batch: false, nostr: false, batchSize: 0}
|
||||
const stats: Types.RequestStats = { startMs:req.startTimeMs || 0, start:req.startTime || 0n, parse: process.hrtime.bigint(), guard: 0n, validate: 0n, handle: 0n }
|
||||
let authCtx: Types.AuthContext = {}
|
||||
try {
|
||||
if (!methods.RemoveAuthorizedDebit) throw new Error('method: RemoveAuthorizedDebit is not implemented')
|
||||
const authContext = await opts.UserAuthGuard(req.headers['authorization'])
|
||||
authCtx = authContext
|
||||
stats.guard = process.hrtime.bigint()
|
||||
const request = req.body
|
||||
const error = Types.RemoveAuthorizedDebitRequestValidate(request)
|
||||
stats.validate = process.hrtime.bigint()
|
||||
if (error !== null) return logErrorAndReturnResponse(error, 'invalid request body', res, logger, { ...info, ...stats, ...authContext }, opts.metricsCallback)
|
||||
const query = req.query
|
||||
const params = req.params
|
||||
await methods.RemoveAuthorizedDebit({rpcName:'RemoveAuthorizedDebit', ctx:authContext , req: request})
|
||||
stats.handle = process.hrtime.bigint()
|
||||
res.json({status: 'OK'})
|
||||
opts.metricsCallback([{ ...info, ...stats, ...authContext }])
|
||||
} catch (ex) { const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e }
|
||||
})
|
||||
if (!opts.allowNotImplementedMethods && !methods.RequestNPubLinkingToken) throw new Error('method: RequestNPubLinkingToken is not implemented')
|
||||
app.post('/api/app/user/npub/token', async (req, res) => {
|
||||
const info: Types.RequestInfo = { rpcName: 'RequestNPubLinkingToken', batch: false, nostr: false, batchSize: 0}
|
||||
|
|
|
|||
|
|
@ -101,6 +101,20 @@ export default (params: ClientParams) => ({
|
|||
}
|
||||
return { status: 'ERROR', reason: 'invalid response' }
|
||||
},
|
||||
AuthorizeDebit: async (request: Types.DebitAuthorization): Promise<ResultError | ({ status: 'OK' }& Types.AuthorizedDebit)> => {
|
||||
const auth = await params.retrieveUserAuth()
|
||||
if (auth === null) throw new Error('retrieveUserAuth() returned null')
|
||||
let finalRoute = '/api/user/debit/authorize'
|
||||
const { data } = await axios.post(params.baseUrl + finalRoute, request, { headers: { 'authorization': auth } })
|
||||
if (data.status === 'ERROR' && typeof data.reason === 'string') return data
|
||||
if (data.status === 'OK') {
|
||||
const result = data
|
||||
if(!params.checkResult) return { status: 'OK', ...result }
|
||||
const error = Types.AuthorizedDebitValidate(result)
|
||||
if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message }
|
||||
}
|
||||
return { status: 'ERROR', reason: 'invalid response' }
|
||||
},
|
||||
BanUser: async (request: Types.BanUserRequest): Promise<ResultError | ({ status: 'OK' }& Types.BanUserResponse)> => {
|
||||
const auth = await params.retrieveAdminAuth()
|
||||
if (auth === null) throw new Error('retrieveAdminAuth() returned null')
|
||||
|
|
@ -232,6 +246,20 @@ export default (params: ClientParams) => ({
|
|||
}
|
||||
return { status: 'ERROR', reason: 'invalid response' }
|
||||
},
|
||||
GetAuthorizedDebits: async (): Promise<ResultError | ({ status: 'OK' }& Types.AuthorizedDebits)> => {
|
||||
const auth = await params.retrieveUserAuth()
|
||||
if (auth === null) throw new Error('retrieveUserAuth() returned null')
|
||||
let finalRoute = '/api/user/debit/get'
|
||||
const { data } = await axios.get(params.baseUrl + finalRoute, { headers: { 'authorization': auth } })
|
||||
if (data.status === 'ERROR' && typeof data.reason === 'string') return data
|
||||
if (data.status === 'OK') {
|
||||
const result = data
|
||||
if(!params.checkResult) return { status: 'OK', ...result }
|
||||
const error = Types.AuthorizedDebitsValidate(result)
|
||||
if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message }
|
||||
}
|
||||
return { status: 'ERROR', reason: 'invalid response' }
|
||||
},
|
||||
GetHttpCreds: async (cb: (v:ResultError | ({ status: 'OK' }& Types.HttpCreds)) => void): Promise<void> => { throw new Error('http streams are not supported')},
|
||||
GetInviteLinkState: async (request: Types.GetInviteTokenStateRequest): Promise<ResultError | ({ status: 'OK' }& Types.GetInviteTokenStateResponse)> => {
|
||||
const auth = await params.retrieveAdminAuth()
|
||||
|
|
@ -601,6 +629,17 @@ export default (params: ClientParams) => ({
|
|||
}
|
||||
return { status: 'ERROR', reason: 'invalid response' }
|
||||
},
|
||||
RemoveAuthorizedDebit: async (request: Types.RemoveAuthorizedDebitRequest): Promise<ResultError | ({ status: 'OK' })> => {
|
||||
const auth = await params.retrieveUserAuth()
|
||||
if (auth === null) throw new Error('retrieveUserAuth() returned null')
|
||||
let finalRoute = '/api/user/debit/remove'
|
||||
const { data } = await axios.post(params.baseUrl + finalRoute, request, { headers: { 'authorization': auth } })
|
||||
if (data.status === 'ERROR' && typeof data.reason === 'string') return data
|
||||
if (data.status === 'OK') {
|
||||
return data
|
||||
}
|
||||
return { status: 'ERROR', reason: 'invalid response' }
|
||||
},
|
||||
RequestNPubLinkingToken: async (request: Types.RequestNPubLinkingTokenRequest): Promise<ResultError | ({ status: 'OK' }& Types.RequestNPubLinkingTokenResponse)> => {
|
||||
const auth = await params.retrieveAppAuth()
|
||||
if (auth === null) throw new Error('retrieveAppAuth() returned null')
|
||||
|
|
|
|||
|
|
@ -57,6 +57,21 @@ export default (params: NostrClientParams, send: (to:string, message: NostrRequ
|
|||
}
|
||||
return { status: 'ERROR', reason: 'invalid response' }
|
||||
},
|
||||
AuthorizeDebit: async (request: Types.DebitAuthorization): Promise<ResultError | ({ status: 'OK' }& Types.AuthorizedDebit)> => {
|
||||
const auth = await params.retrieveNostrUserAuth()
|
||||
if (auth === null) throw new Error('retrieveNostrUserAuth() returned null')
|
||||
const nostrRequest: NostrRequest = {}
|
||||
nostrRequest.body = request
|
||||
const data = await send(params.pubDestination, {rpcName:'AuthorizeDebit',authIdentifier:auth, ...nostrRequest })
|
||||
if (data.status === 'ERROR' && typeof data.reason === 'string') return data
|
||||
if (data.status === 'OK') {
|
||||
const result = data
|
||||
if(!params.checkResult) return { status: 'OK', ...result }
|
||||
const error = Types.AuthorizedDebitValidate(result)
|
||||
if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message }
|
||||
}
|
||||
return { status: 'ERROR', reason: 'invalid response' }
|
||||
},
|
||||
BanUser: async (request: Types.BanUserRequest): Promise<ResultError | ({ status: 'OK' }& Types.BanUserResponse)> => {
|
||||
const auth = await params.retrieveNostrAdminAuth()
|
||||
if (auth === null) throw new Error('retrieveNostrAdminAuth() returned null')
|
||||
|
|
@ -140,6 +155,20 @@ export default (params: NostrClientParams, send: (to:string, message: NostrRequ
|
|||
}
|
||||
return { status: 'ERROR', reason: 'invalid response' }
|
||||
},
|
||||
GetAuthorizedDebits: async (): Promise<ResultError | ({ status: 'OK' }& Types.AuthorizedDebits)> => {
|
||||
const auth = await params.retrieveNostrUserAuth()
|
||||
if (auth === null) throw new Error('retrieveNostrUserAuth() returned null')
|
||||
const nostrRequest: NostrRequest = {}
|
||||
const data = await send(params.pubDestination, {rpcName:'GetAuthorizedDebits',authIdentifier:auth, ...nostrRequest })
|
||||
if (data.status === 'ERROR' && typeof data.reason === 'string') return data
|
||||
if (data.status === 'OK') {
|
||||
const result = data
|
||||
if(!params.checkResult) return { status: 'OK', ...result }
|
||||
const error = Types.AuthorizedDebitsValidate(result)
|
||||
if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message }
|
||||
}
|
||||
return { status: 'ERROR', reason: 'invalid response' }
|
||||
},
|
||||
GetHttpCreds: async (cb: (res:ResultError | ({ status: 'OK' }& Types.HttpCreds)) => void): Promise<void> => {
|
||||
const auth = await params.retrieveNostrUserAuth()
|
||||
if (auth === null) throw new Error('retrieveNostrUserAuth() returned null')
|
||||
|
|
@ -460,6 +489,18 @@ export default (params: NostrClientParams, send: (to:string, message: NostrRequ
|
|||
}
|
||||
return { status: 'ERROR', reason: 'invalid response' }
|
||||
},
|
||||
RemoveAuthorizedDebit: async (request: Types.RemoveAuthorizedDebitRequest): Promise<ResultError | ({ status: 'OK' })> => {
|
||||
const auth = await params.retrieveNostrUserAuth()
|
||||
if (auth === null) throw new Error('retrieveNostrUserAuth() returned null')
|
||||
const nostrRequest: NostrRequest = {}
|
||||
nostrRequest.body = request
|
||||
const data = await send(params.pubDestination, {rpcName:'RemoveAuthorizedDebit',authIdentifier:auth, ...nostrRequest })
|
||||
if (data.status === 'ERROR' && typeof data.reason === 'string') return data
|
||||
if (data.status === 'OK') {
|
||||
return data
|
||||
}
|
||||
return { status: 'ERROR', reason: 'invalid response' }
|
||||
},
|
||||
UseInviteLink: async (request: Types.UseInviteLinkRequest): Promise<ResultError | ({ status: 'OK' })> => {
|
||||
const auth = await params.retrieveNostrGuestWithPubAuth()
|
||||
if (auth === null) throw new Error('retrieveNostrGuestWithPubAuth() returned null')
|
||||
|
|
|
|||
|
|
@ -80,6 +80,22 @@ export default (methods: Types.ServerMethods, opts: NostrOptions) => {
|
|||
opts.metricsCallback([{ ...info, ...stats, ...authContext }])
|
||||
}catch(ex){ const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e }
|
||||
break
|
||||
case 'AuthorizeDebit':
|
||||
try {
|
||||
if (!methods.AuthorizeDebit) throw new Error('method: AuthorizeDebit is not implemented')
|
||||
const authContext = await opts.NostrUserAuthGuard(req.appId, req.authIdentifier)
|
||||
stats.guard = process.hrtime.bigint()
|
||||
authCtx = authContext
|
||||
const request = req.body
|
||||
const error = Types.DebitAuthorizationValidate(request)
|
||||
stats.validate = process.hrtime.bigint()
|
||||
if (error !== null) return logErrorAndReturnResponse(error, 'invalid request body', res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback)
|
||||
const response = await methods.AuthorizeDebit({rpcName:'AuthorizeDebit', ctx:authContext , req: request})
|
||||
stats.handle = process.hrtime.bigint()
|
||||
res({status: 'OK', ...response})
|
||||
opts.metricsCallback([{ ...info, ...stats, ...authContext }])
|
||||
}catch(ex){ const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e }
|
||||
break
|
||||
case 'BanUser':
|
||||
try {
|
||||
if (!methods.BanUser) throw new Error('method: BanUser is not implemented')
|
||||
|
|
@ -127,6 +143,18 @@ export default (methods: Types.ServerMethods, opts: NostrOptions) => {
|
|||
callsMetrics.push({ ...opInfo, ...opStats, ...ctx })
|
||||
}
|
||||
break
|
||||
case 'AuthorizeDebit':
|
||||
if (!methods.AuthorizeDebit) {
|
||||
throw new Error('method not defined: AuthorizeDebit')
|
||||
} else {
|
||||
const error = Types.DebitAuthorizationValidate(operation.req)
|
||||
opStats.validate = process.hrtime.bigint()
|
||||
if (error !== null) throw error
|
||||
const res = await methods.AuthorizeDebit({...operation, ctx}); responses.push({ status: 'OK', ...res })
|
||||
opStats.handle = process.hrtime.bigint()
|
||||
callsMetrics.push({ ...opInfo, ...opStats, ...ctx })
|
||||
}
|
||||
break
|
||||
case 'DecodeInvoice':
|
||||
if (!methods.DecodeInvoice) {
|
||||
throw new Error('method not defined: DecodeInvoice')
|
||||
|
|
@ -151,6 +179,16 @@ export default (methods: Types.ServerMethods, opts: NostrOptions) => {
|
|||
callsMetrics.push({ ...opInfo, ...opStats, ...ctx })
|
||||
}
|
||||
break
|
||||
case 'GetAuthorizedDebits':
|
||||
if (!methods.GetAuthorizedDebits) {
|
||||
throw new Error('method not defined: GetAuthorizedDebits')
|
||||
} else {
|
||||
opStats.validate = opStats.guard
|
||||
const res = await methods.GetAuthorizedDebits({...operation, ctx}); responses.push({ status: 'OK', ...res })
|
||||
opStats.handle = process.hrtime.bigint()
|
||||
callsMetrics.push({ ...opInfo, ...opStats, ...ctx })
|
||||
}
|
||||
break
|
||||
case 'GetLNURLChannelLink':
|
||||
if (!methods.GetLNURLChannelLink) {
|
||||
throw new Error('method not defined: GetLNURLChannelLink')
|
||||
|
|
@ -285,6 +323,18 @@ export default (methods: Types.ServerMethods, opts: NostrOptions) => {
|
|||
callsMetrics.push({ ...opInfo, ...opStats, ...ctx })
|
||||
}
|
||||
break
|
||||
case 'RemoveAuthorizedDebit':
|
||||
if (!methods.RemoveAuthorizedDebit) {
|
||||
throw new Error('method not defined: RemoveAuthorizedDebit')
|
||||
} else {
|
||||
const error = Types.RemoveAuthorizedDebitRequestValidate(operation.req)
|
||||
opStats.validate = process.hrtime.bigint()
|
||||
if (error !== null) throw error
|
||||
await methods.RemoveAuthorizedDebit({...operation, ctx}); responses.push({ status: 'OK' })
|
||||
opStats.handle = process.hrtime.bigint()
|
||||
callsMetrics.push({ ...opInfo, ...opStats, ...ctx })
|
||||
}
|
||||
break
|
||||
case 'UserHealth':
|
||||
if (!methods.UserHealth) {
|
||||
throw new Error('method not defined: UserHealth')
|
||||
|
|
@ -369,6 +419,19 @@ export default (methods: Types.ServerMethods, opts: NostrOptions) => {
|
|||
opts.metricsCallback([{ ...info, ...stats, ...authContext }])
|
||||
}catch(ex){ const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e }
|
||||
break
|
||||
case 'GetAuthorizedDebits':
|
||||
try {
|
||||
if (!methods.GetAuthorizedDebits) throw new Error('method: GetAuthorizedDebits is not implemented')
|
||||
const authContext = await opts.NostrUserAuthGuard(req.appId, req.authIdentifier)
|
||||
stats.guard = process.hrtime.bigint()
|
||||
authCtx = authContext
|
||||
stats.validate = stats.guard
|
||||
const response = await methods.GetAuthorizedDebits({rpcName:'GetAuthorizedDebits', ctx:authContext })
|
||||
stats.handle = process.hrtime.bigint()
|
||||
res({status: 'OK', ...response})
|
||||
opts.metricsCallback([{ ...info, ...stats, ...authContext }])
|
||||
}catch(ex){ const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e }
|
||||
break
|
||||
case 'GetHttpCreds':
|
||||
try {
|
||||
if (!methods.GetHttpCreds) throw new Error('method: GetHttpCreds is not implemented')
|
||||
|
|
@ -688,6 +751,22 @@ export default (methods: Types.ServerMethods, opts: NostrOptions) => {
|
|||
opts.metricsCallback([{ ...info, ...stats, ...authContext }])
|
||||
}catch(ex){ const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e }
|
||||
break
|
||||
case 'RemoveAuthorizedDebit':
|
||||
try {
|
||||
if (!methods.RemoveAuthorizedDebit) throw new Error('method: RemoveAuthorizedDebit is not implemented')
|
||||
const authContext = await opts.NostrUserAuthGuard(req.appId, req.authIdentifier)
|
||||
stats.guard = process.hrtime.bigint()
|
||||
authCtx = authContext
|
||||
const request = req.body
|
||||
const error = Types.RemoveAuthorizedDebitRequestValidate(request)
|
||||
stats.validate = process.hrtime.bigint()
|
||||
if (error !== null) return logErrorAndReturnResponse(error, 'invalid request body', res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback)
|
||||
await methods.RemoveAuthorizedDebit({rpcName:'RemoveAuthorizedDebit', ctx:authContext , req: request})
|
||||
stats.handle = process.hrtime.bigint()
|
||||
res({status: 'OK'})
|
||||
opts.metricsCallback([{ ...info, ...stats, ...authContext }])
|
||||
}catch(ex){ const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e }
|
||||
break
|
||||
case 'UseInviteLink':
|
||||
try {
|
||||
if (!methods.UseInviteLink) throw new Error('method: UseInviteLink is not implemented')
|
||||
|
|
|
|||
|
|
@ -34,8 +34,8 @@ export type UserContext = {
|
|||
app_user_id: string
|
||||
user_id: string
|
||||
}
|
||||
export type UserMethodInputs = AddProduct_Input | DecodeInvoice_Input | EnrollAdminToken_Input | GetLNURLChannelLink_Input | GetLnurlPayLink_Input | GetLnurlWithdrawLink_Input | GetPaymentState_Input | GetUserInfo_Input | GetUserOperations_Input | NewAddress_Input | NewInvoice_Input | NewProductInvoice_Input | OpenChannel_Input | PayAddress_Input | PayInvoice_Input | UserHealth_Input
|
||||
export type UserMethodOutputs = AddProduct_Output | DecodeInvoice_Output | EnrollAdminToken_Output | GetLNURLChannelLink_Output | GetLnurlPayLink_Output | GetLnurlWithdrawLink_Output | GetPaymentState_Output | GetUserInfo_Output | GetUserOperations_Output | NewAddress_Output | NewInvoice_Output | NewProductInvoice_Output | OpenChannel_Output | PayAddress_Output | PayInvoice_Output | UserHealth_Output
|
||||
export type UserMethodInputs = AddProduct_Input | AuthorizeDebit_Input | DecodeInvoice_Input | EnrollAdminToken_Input | GetAuthorizedDebits_Input | GetLNURLChannelLink_Input | GetLnurlPayLink_Input | GetLnurlWithdrawLink_Input | GetPaymentState_Input | GetUserInfo_Input | GetUserOperations_Input | NewAddress_Input | NewInvoice_Input | NewProductInvoice_Input | OpenChannel_Input | PayAddress_Input | PayInvoice_Input | RemoveAuthorizedDebit_Input | UserHealth_Input
|
||||
export type UserMethodOutputs = AddProduct_Output | AuthorizeDebit_Output | DecodeInvoice_Output | EnrollAdminToken_Output | GetAuthorizedDebits_Output | GetLNURLChannelLink_Output | GetLnurlPayLink_Output | GetLnurlWithdrawLink_Output | GetPaymentState_Output | GetUserInfo_Output | GetUserOperations_Output | NewAddress_Output | NewInvoice_Output | NewProductInvoice_Output | OpenChannel_Output | PayAddress_Output | PayInvoice_Output | RemoveAuthorizedDebit_Output | UserHealth_Output
|
||||
export type AuthContext = AdminContext | AppContext | GuestContext | GuestWithPubContext | MetricsContext | UserContext
|
||||
|
||||
export type AddApp_Input = {rpcName:'AddApp', req: AddAppRequest}
|
||||
|
|
@ -56,6 +56,9 @@ export type AddProduct_Output = ResultError | ({ status: 'OK' } & Product)
|
|||
export type AuthApp_Input = {rpcName:'AuthApp', req: AuthAppRequest}
|
||||
export type AuthApp_Output = ResultError | ({ status: 'OK' } & AuthApp)
|
||||
|
||||
export type AuthorizeDebit_Input = {rpcName:'AuthorizeDebit', req: DebitAuthorization}
|
||||
export type AuthorizeDebit_Output = ResultError | ({ status: 'OK' } & AuthorizedDebit)
|
||||
|
||||
export type BanUser_Input = {rpcName:'BanUser', req: BanUserRequest}
|
||||
export type BanUser_Output = ResultError | ({ status: 'OK' } & BanUserResponse)
|
||||
|
||||
|
|
@ -86,6 +89,9 @@ export type GetAppUserLNURLInfo_Output = ResultError | ({ status: 'OK' } & Lnurl
|
|||
export type GetAppsMetrics_Input = {rpcName:'GetAppsMetrics', req: AppsMetricsRequest}
|
||||
export type GetAppsMetrics_Output = ResultError | ({ status: 'OK' } & AppsMetrics)
|
||||
|
||||
export type GetAuthorizedDebits_Input = {rpcName:'GetAuthorizedDebits'}
|
||||
export type GetAuthorizedDebits_Output = ResultError | ({ status: 'OK' } & AuthorizedDebits)
|
||||
|
||||
export type GetHttpCreds_Input = {rpcName:'GetHttpCreds', cb:(res: HttpCreds, err:Error|null)=> void}
|
||||
export type GetHttpCreds_Output = ResultError | { status: 'OK' }
|
||||
|
||||
|
|
@ -195,6 +201,9 @@ export type PayAppUserInvoice_Output = ResultError | ({ status: 'OK' } & PayInvo
|
|||
export type PayInvoice_Input = {rpcName:'PayInvoice', req: PayInvoiceRequest}
|
||||
export type PayInvoice_Output = ResultError | ({ status: 'OK' } & PayInvoiceResponse)
|
||||
|
||||
export type RemoveAuthorizedDebit_Input = {rpcName:'RemoveAuthorizedDebit', req: RemoveAuthorizedDebitRequest}
|
||||
export type RemoveAuthorizedDebit_Output = ResultError | { status: 'OK' }
|
||||
|
||||
export type RequestNPubLinkingToken_Input = {rpcName:'RequestNPubLinkingToken', req: RequestNPubLinkingTokenRequest}
|
||||
export type RequestNPubLinkingToken_Output = ResultError | ({ status: 'OK' } & RequestNPubLinkingTokenResponse)
|
||||
|
||||
|
|
@ -229,6 +238,7 @@ export type ServerMethods = {
|
|||
AddAppUserInvoice?: (req: AddAppUserInvoice_Input & {ctx: AppContext }) => Promise<NewInvoiceResponse>
|
||||
AddProduct?: (req: AddProduct_Input & {ctx: UserContext }) => Promise<Product>
|
||||
AuthApp?: (req: AuthApp_Input & {ctx: AdminContext }) => Promise<AuthApp>
|
||||
AuthorizeDebit?: (req: AuthorizeDebit_Input & {ctx: UserContext }) => Promise<AuthorizedDebit>
|
||||
BanUser?: (req: BanUser_Input & {ctx: AdminContext }) => Promise<BanUserResponse>
|
||||
CreateOneTimeInviteLink?: (req: CreateOneTimeInviteLink_Input & {ctx: AdminContext }) => Promise<CreateOneTimeInviteLinkResponse>
|
||||
DecodeInvoice?: (req: DecodeInvoice_Input & {ctx: UserContext }) => Promise<DecodeInvoiceResponse>
|
||||
|
|
@ -238,6 +248,7 @@ export type ServerMethods = {
|
|||
GetAppUser?: (req: GetAppUser_Input & {ctx: AppContext }) => Promise<AppUser>
|
||||
GetAppUserLNURLInfo?: (req: GetAppUserLNURLInfo_Input & {ctx: AppContext }) => Promise<LnurlPayInfoResponse>
|
||||
GetAppsMetrics?: (req: GetAppsMetrics_Input & {ctx: MetricsContext }) => Promise<AppsMetrics>
|
||||
GetAuthorizedDebits?: (req: GetAuthorizedDebits_Input & {ctx: UserContext }) => Promise<AuthorizedDebits>
|
||||
GetHttpCreds?: (req: GetHttpCreds_Input & {ctx: UserContext }) => Promise<void>
|
||||
GetInviteLinkState?: (req: GetInviteLinkState_Input & {ctx: AdminContext }) => Promise<GetInviteTokenStateResponse>
|
||||
GetLNURLChannelLink?: (req: GetLNURLChannelLink_Input & {ctx: UserContext }) => Promise<LnurlLinkResponse>
|
||||
|
|
@ -267,6 +278,7 @@ export type ServerMethods = {
|
|||
PayAddress?: (req: PayAddress_Input & {ctx: UserContext }) => Promise<PayAddressResponse>
|
||||
PayAppUserInvoice?: (req: PayAppUserInvoice_Input & {ctx: AppContext }) => Promise<PayInvoiceResponse>
|
||||
PayInvoice?: (req: PayInvoice_Input & {ctx: UserContext }) => Promise<PayInvoiceResponse>
|
||||
RemoveAuthorizedDebit?: (req: RemoveAuthorizedDebit_Input & {ctx: UserContext }) => Promise<void>
|
||||
RequestNPubLinkingToken?: (req: RequestNPubLinkingToken_Input & {ctx: AppContext }) => Promise<RequestNPubLinkingTokenResponse>
|
||||
ResetNPubLinkingToken?: (req: ResetNPubLinkingToken_Input & {ctx: AppContext }) => Promise<RequestNPubLinkingTokenResponse>
|
||||
SendAppUserToAppPayment?: (req: SendAppUserToAppPayment_Input & {ctx: AppContext }) => Promise<void>
|
||||
|
|
@ -287,6 +299,14 @@ export const enumCheckAddressType = (e?: AddressType): boolean => {
|
|||
for (const v in AddressType) if (e === v) return true
|
||||
return false
|
||||
}
|
||||
export enum AuthorizedDebitType {
|
||||
KEY = 'KEY',
|
||||
NPUB = 'NPUB',
|
||||
}
|
||||
export const enumCheckAuthorizedDebitType = (e?: AuthorizedDebitType): boolean => {
|
||||
for (const v in AuthorizedDebitType) if (e === v) return true
|
||||
return false
|
||||
}
|
||||
export enum UserOperationType {
|
||||
INCOMING_INVOICE = 'INCOMING_INVOICE',
|
||||
INCOMING_TX = 'INCOMING_TX',
|
||||
|
|
@ -668,6 +688,57 @@ export const AuthAppRequestValidate = (o?: AuthAppRequest, opts: AuthAppRequestO
|
|||
return null
|
||||
}
|
||||
|
||||
export type AuthorizedDebit = {
|
||||
debit_id: string
|
||||
debit_type: AuthorizedDebitType
|
||||
key: string
|
||||
}
|
||||
export const AuthorizedDebitOptionalFields: [] = []
|
||||
export type AuthorizedDebitOptions = OptionsBaseMessage & {
|
||||
checkOptionalsAreSet?: []
|
||||
debit_id_CustomCheck?: (v: string) => boolean
|
||||
debit_type_CustomCheck?: (v: AuthorizedDebitType) => boolean
|
||||
key_CustomCheck?: (v: string) => boolean
|
||||
}
|
||||
export const AuthorizedDebitValidate = (o?: AuthorizedDebit, opts: AuthorizedDebitOptions = {}, path: string = 'AuthorizedDebit::root.'): Error | null => {
|
||||
if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message')
|
||||
if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null')
|
||||
|
||||
if (typeof o.debit_id !== 'string') return new Error(`${path}.debit_id: is not a string`)
|
||||
if (opts.debit_id_CustomCheck && !opts.debit_id_CustomCheck(o.debit_id)) return new Error(`${path}.debit_id: custom check failed`)
|
||||
|
||||
if (!enumCheckAuthorizedDebitType(o.debit_type)) return new Error(`${path}.debit_type: is not a valid AuthorizedDebitType`)
|
||||
if (opts.debit_type_CustomCheck && !opts.debit_type_CustomCheck(o.debit_type)) return new Error(`${path}.debit_type: custom check failed`)
|
||||
|
||||
if (typeof o.key !== 'string') return new Error(`${path}.key: is not a string`)
|
||||
if (opts.key_CustomCheck && !opts.key_CustomCheck(o.key)) return new Error(`${path}.key: custom check failed`)
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
export type AuthorizedDebits = {
|
||||
debits: AuthorizedDebit[]
|
||||
}
|
||||
export const AuthorizedDebitsOptionalFields: [] = []
|
||||
export type AuthorizedDebitsOptions = OptionsBaseMessage & {
|
||||
checkOptionalsAreSet?: []
|
||||
debits_ItemOptions?: AuthorizedDebitOptions
|
||||
debits_CustomCheck?: (v: AuthorizedDebit[]) => boolean
|
||||
}
|
||||
export const AuthorizedDebitsValidate = (o?: AuthorizedDebits, opts: AuthorizedDebitsOptions = {}, path: string = 'AuthorizedDebits::root.'): Error | null => {
|
||||
if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message')
|
||||
if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null')
|
||||
|
||||
if (!Array.isArray(o.debits)) return new Error(`${path}.debits: is not an array`)
|
||||
for (let index = 0; index < o.debits.length; index++) {
|
||||
const debitsErr = AuthorizedDebitValidate(o.debits[index], opts.debits_ItemOptions, `${path}.debits[${index}]`)
|
||||
if (debitsErr !== null) return debitsErr
|
||||
}
|
||||
if (opts.debits_CustomCheck && !opts.debits_CustomCheck(o.debits)) return new Error(`${path}.debits: custom check failed`)
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
export type BanUserRequest = {
|
||||
user_id: string
|
||||
}
|
||||
|
|
@ -830,6 +901,25 @@ export const CreateOneTimeInviteLinkResponseValidate = (o?: CreateOneTimeInviteL
|
|||
return null
|
||||
}
|
||||
|
||||
export type DebitAuthorization = {
|
||||
authorize_npub?: string
|
||||
}
|
||||
export type DebitAuthorizationOptionalField = 'authorize_npub'
|
||||
export const DebitAuthorizationOptionalFields: DebitAuthorizationOptionalField[] = ['authorize_npub']
|
||||
export type DebitAuthorizationOptions = OptionsBaseMessage & {
|
||||
checkOptionalsAreSet?: DebitAuthorizationOptionalField[]
|
||||
authorize_npub_CustomCheck?: (v?: string) => boolean
|
||||
}
|
||||
export const DebitAuthorizationValidate = (o?: DebitAuthorization, opts: DebitAuthorizationOptions = {}, path: string = 'DebitAuthorization::root.'): Error | null => {
|
||||
if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message')
|
||||
if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null')
|
||||
|
||||
if ((o.authorize_npub || opts.allOptionalsAreSet || opts.checkOptionalsAreSet?.includes('authorize_npub')) && typeof o.authorize_npub !== 'string') return new Error(`${path}.authorize_npub: is not a string`)
|
||||
if (opts.authorize_npub_CustomCheck && !opts.authorize_npub_CustomCheck(o.authorize_npub)) return new Error(`${path}.authorize_npub: custom check failed`)
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
export type DecodeInvoiceRequest = {
|
||||
invoice: string
|
||||
}
|
||||
|
|
@ -2028,6 +2118,24 @@ export const RelaysMigrationValidate = (o?: RelaysMigration, opts: RelaysMigrati
|
|||
return null
|
||||
}
|
||||
|
||||
export type RemoveAuthorizedDebitRequest = {
|
||||
debit_id: string
|
||||
}
|
||||
export const RemoveAuthorizedDebitRequestOptionalFields: [] = []
|
||||
export type RemoveAuthorizedDebitRequestOptions = OptionsBaseMessage & {
|
||||
checkOptionalsAreSet?: []
|
||||
debit_id_CustomCheck?: (v: string) => boolean
|
||||
}
|
||||
export const RemoveAuthorizedDebitRequestValidate = (o?: RemoveAuthorizedDebitRequest, opts: RemoveAuthorizedDebitRequestOptions = {}, path: string = 'RemoveAuthorizedDebitRequest::root.'): Error | null => {
|
||||
if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message')
|
||||
if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null')
|
||||
|
||||
if (typeof o.debit_id !== 'string') return new Error(`${path}.debit_id: is not a string`)
|
||||
if (opts.debit_id_CustomCheck && !opts.debit_id_CustomCheck(o.debit_id)) return new Error(`${path}.debit_id: custom check failed`)
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
export type RequestNPubLinkingTokenRequest = {
|
||||
user_identifier: string
|
||||
}
|
||||
|
|
|
|||
|
|
@ -430,11 +430,29 @@ service LightningPub {
|
|||
}
|
||||
|
||||
rpc GetLNURLChannelLink(structs.Empty) returns (structs.LnurlLinkResponse){
|
||||
option (auth_type) = "User";
|
||||
option (auth_type) = "User";
|
||||
option (http_method) = "post";
|
||||
option (http_route) = "/api/user/lnurl_channel/url";
|
||||
option (nostr) = true;
|
||||
}
|
||||
rpc GetAuthorizedDebits(structs.Empty) returns (structs.AuthorizedDebits){
|
||||
option (auth_type) = "User";
|
||||
option (http_method) = "get";
|
||||
option (http_route) = "/api/user/debit/get";
|
||||
option (nostr) = true;
|
||||
}
|
||||
rpc RemoveAuthorizedDebit(structs.RemoveAuthorizedDebitRequest) returns (structs.Empty){
|
||||
option (auth_type) = "User";
|
||||
option (http_method) = "post";
|
||||
option (http_route) = "/api/user/debit/remove";
|
||||
option (nostr) = true;
|
||||
}
|
||||
rpc AuthorizeDebit(structs.DebitAuthorization) returns (structs.AuthorizedDebit){
|
||||
option (auth_type) = "User";
|
||||
option (http_method) = "post";
|
||||
option (http_route) = "/api/user/debit/authorize";
|
||||
option (nostr) = true;
|
||||
}
|
||||
rpc GetLiveUserOperations(structs.Empty) returns (stream structs.LiveUserOperation){
|
||||
option (auth_type) = "User";
|
||||
option (http_method) = "post";
|
||||
|
|
|
|||
|
|
@ -476,4 +476,29 @@ message GetInviteTokenStateRequest {
|
|||
|
||||
message GetInviteTokenStateResponse {
|
||||
bool used = 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
message DebitAuthorization {
|
||||
optional string authorize_npub =1;
|
||||
}
|
||||
|
||||
enum AuthorizedDebitType {
|
||||
NPUB = 0;
|
||||
KEY = 1;
|
||||
}
|
||||
|
||||
message AuthorizedDebit {
|
||||
string debit_id = 1;
|
||||
AuthorizedDebitType debit_type = 2;
|
||||
string key = 3;
|
||||
}
|
||||
|
||||
message AuthorizedDebits {
|
||||
repeated AuthorizedDebit debits = 1;
|
||||
}
|
||||
|
||||
message RemoveAuthorizedDebitRequest {
|
||||
string debit_id = 1;
|
||||
}
|
||||
|
|
@ -7,6 +7,7 @@ import { ERROR, getLogger } from "./services/helpers/logger.js";
|
|||
import { UnsignedEvent } from "./services/nostr/tools/event.js";
|
||||
import { defaultInvoiceExpiry } from "./services/storage/paymentStorage.js";
|
||||
import { Application } from "./services/storage/entity/Application.js";
|
||||
import { NdebitData } from "./services/main/debitManager.js";
|
||||
|
||||
export default (serverMethods: Types.ServerMethods, mainHandler: Main, nostrSettings: NostrSettings, onClientEvent: (e: { requestId: string }, fromPub: string) => void): { Stop: () => void, Send: NostrSend } => {
|
||||
const log = getLogger({})
|
||||
|
|
@ -52,6 +53,10 @@ export default (serverMethods: Types.ServerMethods, mainHandler: Main, nostrSett
|
|||
const offerReq = j as NofferData
|
||||
mainHandler.handleNip69Noffer(offerReq, event)
|
||||
return
|
||||
} else if (event.kind === 21002) {
|
||||
const debitReq = j as NdebitData
|
||||
mainHandler.handleNip68Debit(debitReq, event)
|
||||
return
|
||||
}
|
||||
if (!j.rpcName) {
|
||||
onClientEvent(j as { requestId: string }, event.pub)
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import crypto from 'crypto';
|
||||
import * as Types from "../../../proto/autogenerated/ts/types.js";
|
||||
import ApplicationManager from "./applicationManager.js";
|
||||
import { DebitKeyType } from "../storage/entity/DebitAccess.js";
|
||||
|
|
@ -18,6 +19,9 @@ const nip68errs = {
|
|||
export type NdebitResponse = NdebitSuccess | NdebitFailure
|
||||
type HandleNdebitRes = { ok: false, debitRes: NdebitFailure } | { ok: true, op: Types.UserOperation, appUserId: string, debitRes: NdebitSuccess }
|
||||
export class DebitManager {
|
||||
|
||||
|
||||
|
||||
applicationManager: ApplicationManager
|
||||
storage: Storage
|
||||
lnd: LND
|
||||
|
|
@ -26,6 +30,37 @@ export class DebitManager {
|
|||
this.storage = storage
|
||||
}
|
||||
|
||||
AuthorizeDebit = async (ctx: Types.UserContext, req: Types.DebitAuthorization): Promise<Types.AuthorizedDebit> => {
|
||||
const debitType = this.getDebitType(req.authorize_npub)
|
||||
const access = await this.storage.debitStorage.AddDebitAccess(ctx.app_user_id, debitType.key, debitType.keyType)
|
||||
return {
|
||||
debit_id: access.serial_id.toString(),
|
||||
debit_type: debitType.debitType,
|
||||
key: debitType.key,
|
||||
}
|
||||
}
|
||||
|
||||
getDebitType = (authorizeNpub?: string): { keyType: DebitKeyType, key: string, debitType: Types.AuthorizedDebitType } => {
|
||||
if (authorizeNpub) {
|
||||
return { keyType: 'pubKey', key: authorizeNpub, debitType: Types.AuthorizedDebitType.NPUB }
|
||||
}
|
||||
return { keyType: 'simpleId', key: crypto.randomBytes(32).toString('hex'), debitType: Types.AuthorizedDebitType.KEY }
|
||||
}
|
||||
|
||||
GetAuthorizedDebits = async (ctx: Types.UserContext): Promise<Types.AuthorizedDebits> => {
|
||||
const allDebitsAccesses = await this.storage.debitStorage.GetAllUserDebitAccess(ctx.app_user_id)
|
||||
const debits: Types.AuthorizedDebit[] = allDebitsAccesses.map(access => ({
|
||||
debit_id: access.serial_id.toString(),
|
||||
debit_type: access.key_type === 'pubKey' ? Types.AuthorizedDebitType.NPUB : Types.AuthorizedDebitType.KEY,
|
||||
key: access.key
|
||||
}))
|
||||
return { debits }
|
||||
}
|
||||
|
||||
RemoveAuthorizedDebit = async (ctx: Types.UserContext, req: Types.RemoveAuthorizedDebitRequest): Promise<void> => {
|
||||
await this.storage.debitStorage.RemoveDebitAccess(ctx.app_user_id, +req.debit_id)
|
||||
}
|
||||
|
||||
payNdebitInvoice = async (appId: string, requestorPub: string, pointerdata: NdebitData): Promise<HandleNdebitRes> => {
|
||||
try {
|
||||
return await this.doNdebit(appId, requestorPub, pointerdata)
|
||||
|
|
@ -90,5 +125,7 @@ export class DebitManager {
|
|||
internal: payment.network_fee === 0
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -261,7 +261,20 @@ export default (mainHandler: Main): Types.ServerMethods => {
|
|||
})
|
||||
if (err != null) throw new Error(err.message)
|
||||
return mainHandler.adminManager.GetInviteTokenState(ctx, req);
|
||||
}
|
||||
},
|
||||
AuthorizeDebit: async ({ ctx, req }) => {
|
||||
return mainHandler.debitManager.AuthorizeDebit(ctx, req)
|
||||
},
|
||||
GetAuthorizedDebits: async ({ ctx }) => {
|
||||
return mainHandler.debitManager.GetAuthorizedDebits(ctx)
|
||||
},
|
||||
RemoveAuthorizedDebit: async ({ ctx, req }) => {
|
||||
const err = Types.RemoveAuthorizedDebitRequestValidate(req, {
|
||||
debit_id_CustomCheck: id => id !== '',
|
||||
})
|
||||
if (err != null) throw new Error(err.message)
|
||||
return mainHandler.debitManager.RemoveAuthorizedDebit(ctx, req)
|
||||
},
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -21,6 +21,7 @@ import { Product } from "./entity/Product.js"
|
|||
import { LndNodeInfo } from "./entity/LndNodeInfo.js"
|
||||
import { TrackedProvider } from "./entity/TrackedProvider.js"
|
||||
import { InviteToken } from "./entity/InviteToken.js"
|
||||
import { DebitAccess } from "./entity/DebitAccess.js"
|
||||
|
||||
|
||||
export type DbSettings = {
|
||||
|
|
@ -61,7 +62,7 @@ export default async (settings: DbSettings, migrations: Function[]): Promise<{ s
|
|||
// logging: true,
|
||||
entities: [User, UserReceivingInvoice, UserReceivingAddress, AddressReceivingTransaction, UserInvoicePayment, UserTransactionPayment,
|
||||
UserBasicAuth, UserEphemeralKey, Product, UserToUserPayment, Application, ApplicationUser, UserToUserPayment, LspOrder, LndNodeInfo, TrackedProvider,
|
||||
InviteToken
|
||||
InviteToken, DebitAccess
|
||||
],
|
||||
//synchronize: true,
|
||||
migrations
|
||||
|
|
|
|||
|
|
@ -20,6 +20,10 @@ export default class {
|
|||
return this.txQueue.PushToQueue<DebitAccess>({ exec: async db => db.getRepository(DebitAccess).save(entry), dbTx: false })
|
||||
}
|
||||
|
||||
async GetAllUserDebitAccess(appUserId: string) {
|
||||
return this.DB.getRepository(DebitAccess).find({ where: { app_user_id: appUserId } })
|
||||
}
|
||||
|
||||
async GetDebitAccess(appUserId: string, key: string, keyType: DebitKeyType) {
|
||||
return this.DB.getRepository(DebitAccess).findOne({ where: { app_user_id: appUserId, key, key_type: keyType } })
|
||||
}
|
||||
|
|
@ -27,4 +31,8 @@ export default class {
|
|||
async IncrementDebitAccess(appUserId: string, key: string, keyType: DebitKeyType, amount: number) {
|
||||
return this.DB.getRepository(DebitAccess).increment({ app_user_id: appUserId, key, key_type: keyType }, 'total_debits', amount)
|
||||
}
|
||||
|
||||
async RemoveDebitAccess(appUserId: string, serialId: number) {
|
||||
return this.DB.getRepository(DebitAccess).delete({ app_user_id: appUserId, serial_id: serialId })
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,4 @@
|
|||
import { Entity, PrimaryGeneratedColumn, Column, Index, Check, ManyToOne, JoinColumn, CreateDateColumn, UpdateDateColumn } from "typeorm"
|
||||
import { User } from "./User.js"
|
||||
import { Application } from "./Application.js"
|
||||
import { ApplicationUser } from "./ApplicationUser.js"
|
||||
export type DebitKeyType = 'simpleId' | 'pubKey'
|
||||
@Entity()
|
||||
@Index("unique_debit_access", ["app_user_id", "key", "key_type"], { unique: true })
|
||||
|
|
|
|||
|
|
@ -0,0 +1,16 @@
|
|||
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||
|
||||
export class DebitAccess1726496225078 implements MigrationInterface {
|
||||
name = 'DebitAccess1726496225078'
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`CREATE TABLE "debit_access" ("serial_id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "app_user_id" varchar NOT NULL, "key" varchar NOT NULL, "key_type" varchar NOT NULL, "total_debits" integer NOT NULL DEFAULT (0), "created_at" datetime NOT NULL DEFAULT (datetime('now')), "updated_at" datetime NOT NULL DEFAULT (datetime('now')))`);
|
||||
await queryRunner.query(`CREATE UNIQUE INDEX "unique_debit_access" ON "debit_access" ("app_user_id", "key", "key_type") `);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`DROP INDEX "unique_debit_access"`);
|
||||
await queryRunner.query(`DROP TABLE "debit_access"`);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -12,7 +12,8 @@ import { CreateInviteTokenTable1721751414878 } from "./1721751414878-create_invi
|
|||
import { PaymentIndex1721760297610 } from './1721760297610-payment_index.js'
|
||||
import { HtlcCount1724266887195 } from './1724266887195-htlc_count.js'
|
||||
import { BalanceEvents1724860966825 } from './1724860966825-balance_events.js'
|
||||
const allMigrations = [Initial1703170309875, LspOrder1718387847693, LiquidityProvider1719335699480, LndNodeInfo1720187506189, TrackedProvider1720814323679, CreateInviteTokenTable1721751414878, PaymentIndex1721760297610]
|
||||
import { DebitAccess1726496225078 } from './1726496225078-debit_access.js'
|
||||
const allMigrations = [Initial1703170309875, LspOrder1718387847693, LiquidityProvider1719335699480, LndNodeInfo1720187506189, TrackedProvider1720814323679, CreateInviteTokenTable1721751414878, PaymentIndex1721760297610, DebitAccess1726496225078]
|
||||
const allMetricsMigrations = [LndMetrics1703170330183, ChannelRouting1709316653538, HtlcCount1724266887195, BalanceEvents1724860966825]
|
||||
export const TypeOrmMigrationRunner = async (log: PubLogger, storageManager: Storage, settings: DbSettings, arg: string | undefined): Promise<boolean> => {
|
||||
if (arg === 'fake_initial_migration') {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue