mirror of
https://github.com/Permissionless-Software-Foundation/bch-dex.git
synced 2026-09-21 16:52:00 -07:00
feat(nostr): Added new route for deleteChat and deletePost models
This commit is contained in:
@@ -9,6 +9,8 @@ import Order from './models/order.js'
|
|||||||
import Offer from './models/offer.js'
|
import Offer from './models/offer.js'
|
||||||
import Usage from './models/usage.js'
|
import Usage from './models/usage.js'
|
||||||
import SmAccount from './models/smAccount.js'
|
import SmAccount from './models/smAccount.js'
|
||||||
|
import DeletedChat from './models/deletedChat.js'
|
||||||
|
import DeletedPost from './models/deletedPost.js'
|
||||||
|
|
||||||
class LocalDB {
|
class LocalDB {
|
||||||
constructor () {
|
constructor () {
|
||||||
@@ -19,6 +21,8 @@ class LocalDB {
|
|||||||
this.Offer = Offer
|
this.Offer = Offer
|
||||||
this.Usage = Usage
|
this.Usage = Usage
|
||||||
this.SmAccount = SmAccount
|
this.SmAccount = SmAccount
|
||||||
|
this.DeletedChat = DeletedChat
|
||||||
|
this.DeletedPost = DeletedPost
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import OrderRouter from './order/index.js'
|
|||||||
import P2WDBRouter from './p2wdb/index.js'
|
import P2WDBRouter from './p2wdb/index.js'
|
||||||
import UsageRESTController from './usage/index.js'
|
import UsageRESTController from './usage/index.js'
|
||||||
import SmAccountRouter from './smAccount/index.js'
|
import SmAccountRouter from './smAccount/index.js'
|
||||||
|
import NostrRouter from './nostr/index.js'
|
||||||
|
|
||||||
class RESTControllers {
|
class RESTControllers {
|
||||||
constructor (localConfig = {}) {
|
constructor (localConfig = {}) {
|
||||||
@@ -90,6 +91,10 @@ class RESTControllers {
|
|||||||
|
|
||||||
const smAccountRouter = new SmAccountRouter(dependencies)
|
const smAccountRouter = new SmAccountRouter(dependencies)
|
||||||
smAccountRouter.attach(app)
|
smAccountRouter.attach(app)
|
||||||
|
|
||||||
|
// Attach the REST API Controllers associated with the /nostr route
|
||||||
|
const nostrRouter = new NostrRouter(dependencies)
|
||||||
|
nostrRouter.attach(app)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,219 @@
|
|||||||
|
/*
|
||||||
|
REST API Controller library for the /nostr route
|
||||||
|
*/
|
||||||
|
import wlogger from '../../../adapters/wlogger.js'
|
||||||
|
|
||||||
|
class NostrRESTControllerLib {
|
||||||
|
constructor (localConfig = {}) {
|
||||||
|
// Dependency Injection.
|
||||||
|
this.adapters = localConfig.adapters
|
||||||
|
if (!this.adapters) {
|
||||||
|
throw new Error(
|
||||||
|
'Instance of Adapters library required when instantiating /nostr REST Controller.'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
this.useCases = localConfig.useCases
|
||||||
|
if (!this.useCases) {
|
||||||
|
throw new Error(
|
||||||
|
'Instance of Use Cases library required when instantiating /nostr REST Controller.'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.createDeletedChat = this.createDeletedChat.bind(this)
|
||||||
|
this.getDeletedChats = this.getDeletedChats.bind(this)
|
||||||
|
this.createDeletedPost = this.createDeletedPost.bind(this)
|
||||||
|
this.getDeletedPosts = this.getDeletedPosts.bind(this)
|
||||||
|
this.handleError = this.handleError.bind(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @api {post} /nostr/deletedChat Create Deleted Chat.
|
||||||
|
* @apiPermission admin
|
||||||
|
* @apiName CreateDeletedChat
|
||||||
|
* @apiGroup REST Nostr
|
||||||
|
*
|
||||||
|
* @apiExample Example usage:
|
||||||
|
* curl -H "Content-Type: application/json" -H "Authorization: Bearer <token>" -X POST -d '{"eventId": "note19e93faw4ffqepsqsrwrnstd3ee00nmzakwwuyfjm43dankgummfqms4p6q" , "npub" : "npub1d4ed5x49d7p24xn63flj4985dc4gpfngdhtqcxpth0ywhm6czxcscfpcq8" , "bchAddr" : "bitcoincash:qpm2qsznhks23z7629mms6s4cwef74vcwvy22gdx6a", "pubkey":"6d72da1aa56f82aa9a7a8a7f2a94f46e2a80a6686dd60c182bbbc8ebef5811b1"}' localhost:5700/nostr/deletedChat
|
||||||
|
*
|
||||||
|
* @apiSuccess {String} _id DB Model id
|
||||||
|
* @apiSuccess {String} eventId Event id
|
||||||
|
* @apiSuccess {String} bchAddr BCH Address
|
||||||
|
* @apiSuccess {String} npub Nostr Npub
|
||||||
|
* @apiSuccess {String} pubkey Nostr pubkey
|
||||||
|
* @apiSuccess {Date} createdAt Created at date.
|
||||||
|
* @apiSuccess {Date} updatedAt Updated at date.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @apiSuccessExample {json} Success-Response:
|
||||||
|
* HTTP/1.1 200 OK
|
||||||
|
* {
|
||||||
|
* "_id": "6900f87f9cafee38028ea27e",
|
||||||
|
* "npub": "npub1d4ed5x49d7p24xn63flj4985dc4gpfngdhtqcxpth0ywhm6czxcscfpcq8",
|
||||||
|
* "bchAddr" : "bitcoincash:qpm2qsznhks23z7629mms6s4cwef74vcwvy22gdx6a",
|
||||||
|
* "pubKey": "6d72da1aa56f82aa9a7a8a7f2a94f46e2a80a6686dd60c182bbbc8ebef5811b1",
|
||||||
|
* "createdAt":"2025-10-28T17:08:15.409Z",
|
||||||
|
* "updatedAt": "2025-10-28T17:08:15.409Z"
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* @apiUse TokenError
|
||||||
|
*/
|
||||||
|
async createDeletedChat (ctx) {
|
||||||
|
try {
|
||||||
|
const chat = ctx.request.body
|
||||||
|
|
||||||
|
const result = await this.useCases.nostr.createDeletedChat(chat)
|
||||||
|
|
||||||
|
ctx.body = {
|
||||||
|
deletedChat: result
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
wlogger.error('Error in createDeletedChat() REST API handler.')
|
||||||
|
this.handleError(ctx, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @api {get} /nostr/deletedChat Get Deleted Chats.
|
||||||
|
* @apiPermission public
|
||||||
|
* @apiName GetDeletedChats
|
||||||
|
* @apiGroup REST Nostr
|
||||||
|
*
|
||||||
|
* @apiExample Example usage:
|
||||||
|
* curl -H "Content-Type: application/json" -X GET localhost:5700/nostr/deletedChat
|
||||||
|
*
|
||||||
|
* @apiSuccess {String} _id DB Model id
|
||||||
|
* @apiSuccess {String} eventId Event id
|
||||||
|
* @apiSuccess {String} bchAddr BCH Address
|
||||||
|
* @apiSuccess {String} npub Nostr Npub
|
||||||
|
* @apiSuccess {String} pubkey Nostr pubkey
|
||||||
|
* @apiSuccess {Date} createdAt Created at date.
|
||||||
|
* @apiSuccess {Date} updatedAt Updated at date.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @apiSuccessExample {json} Success-Response:
|
||||||
|
* HTTP/1.1 200 OK
|
||||||
|
* [{
|
||||||
|
* "_id": "6900f87f9cafee38028ea27e",
|
||||||
|
* "npub": "npub1d4ed5x49d7p24xn63flj4985dc4gpfngdhtqcxpth0ywhm6czxcscfpcq8",
|
||||||
|
* "bchAddr" : "bitcoincash:qpm2qsznhks23z7629mms6s4cwef74vcwvy22gdx6a",
|
||||||
|
* "pubKey": "6d72da1aa56f82aa9a7a8a7f2a94f46e2a80a6686dd60c182bbbc8ebef5811b1",
|
||||||
|
* "createdAt":"2025-10-28T17:08:15.409Z",
|
||||||
|
* "updatedAt": "2025-10-28T17:08:15.409Z"
|
||||||
|
* }]
|
||||||
|
*
|
||||||
|
* */
|
||||||
|
async getDeletedChats (ctx) {
|
||||||
|
try {
|
||||||
|
const deletedChats = await this.useCases.nostr.getDeletedChats()
|
||||||
|
|
||||||
|
ctx.body = { deletedChats }
|
||||||
|
} catch (err) {
|
||||||
|
wlogger.error('Error in getDeletedChats() REST API handler.')
|
||||||
|
this.handleError(ctx, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @api {post} /nostr/deletedPost Create Deleted Post.
|
||||||
|
* @apiPermission admin
|
||||||
|
* @apiName CreateDeletedPost
|
||||||
|
* @apiGroup REST Nostr
|
||||||
|
*
|
||||||
|
* @apiExample Example usage:
|
||||||
|
* curl -H "Content-Type: application/json" -H "Authorization: Bearer <token>" -X POST -d '{"eventId": "note19e93faw4ffqepsqsrwrnstd3ee00nmzakwwuyfjm43dankgummfqms4p6q" , "npub" : "npub1d4ed5x49d7p24xn63flj4985dc4gpfngdhtqcxpth0ywhm6czxcscfpcq8" , "bchAddr" : "bitcoincash:qpm2qsznhks23z7629mms6s4cwef74vcwvy22gdx6a", "pubkey":"6d72da1aa56f82aa9a7a8a7f2a94f46e2a80a6686dd60c182bbbc8ebef5811b1"}' localhost:5700/nostr/deletedPost
|
||||||
|
*
|
||||||
|
* @apiSuccess {String} _id DB Model id
|
||||||
|
* @apiSuccess {String} eventId Event id
|
||||||
|
* @apiSuccess {String} bchAddr BCH Address
|
||||||
|
* @apiSuccess {String} npub Nostr Npub
|
||||||
|
* @apiSuccess {String} pubkey Nostr pubkey
|
||||||
|
* @apiSuccess {Date} createdAt Created at date.
|
||||||
|
* @apiSuccess {Date} updatedAt Updated at date.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @apiSuccessExample {json} Success-Response:
|
||||||
|
* HTTP/1.1 200 OK
|
||||||
|
* {
|
||||||
|
* "_id": "6900f87f9cafee38028ea27e",
|
||||||
|
* "npub": "npub1d4ed5x49d7p24xn63flj4985dc4gpfngdhtqcxpth0ywhm6czxcscfpcq8",
|
||||||
|
* "bchAddr" : "bitcoincash:qpm2qsznhks23z7629mms6s4cwef74vcwvy22gdx6a",
|
||||||
|
* "pubKey": "6d72da1aa56f82aa9a7a8a7f2a94f46e2a80a6686dd60c182bbbc8ebef5811b1",
|
||||||
|
* "createdAt":"2025-10-28T17:08:15.409Z",
|
||||||
|
* "updatedAt": "2025-10-28T17:08:15.409Z"
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* @apiUse TokenError
|
||||||
|
*/
|
||||||
|
async createDeletedPost (ctx) {
|
||||||
|
try {
|
||||||
|
const post = ctx.request.body
|
||||||
|
|
||||||
|
const result = await this.useCases.nostr.createDeletedPost(post)
|
||||||
|
|
||||||
|
ctx.body = {
|
||||||
|
deletedPost: result
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
wlogger.error('Error in createDeletedPost() REST API handler.')
|
||||||
|
this.handleError(ctx, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @api {get} /nostr/deletedPost Get Deleted Posts.
|
||||||
|
* @apiPermission public
|
||||||
|
* @apiName GetDeletedPosts
|
||||||
|
* @apiGroup REST Nostr
|
||||||
|
*
|
||||||
|
* @apiExample Example usage:
|
||||||
|
* curl -H "Content-Type: application/json" -X GET localhost:5700/nostr/deletedPost
|
||||||
|
*
|
||||||
|
* @apiSuccess {String} _id DB Model id
|
||||||
|
* @apiSuccess {String} eventId Event id
|
||||||
|
* @apiSuccess {String} bchAddr BCH Address
|
||||||
|
* @apiSuccess {String} npub Nostr Npub
|
||||||
|
* @apiSuccess {String} pubkey Nostr pubkey
|
||||||
|
* @apiSuccess {Date} createdAt Created at date.
|
||||||
|
* @apiSuccess {Date} updatedAt Updated at date.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @apiSuccessExample {json} Success-Response:
|
||||||
|
* HTTP/1.1 200 OK
|
||||||
|
* [{
|
||||||
|
* "_id": "6900f87f9cafee38028ea27e",
|
||||||
|
* "npub": "npub1d4ed5x49d7p24xn63flj4985dc4gpfngdhtqcxpth0ywhm6czxcscfpcq8",
|
||||||
|
* "bchAddr" : "bitcoincash:qpm2qsznhks23z7629mms6s4cwef74vcwvy22gdx6a",
|
||||||
|
* "pubKey": "6d72da1aa56f82aa9a7a8a7f2a94f46e2a80a6686dd60c182bbbc8ebef5811b1",
|
||||||
|
* "createdAt":"2025-10-28T17:08:15.409Z",
|
||||||
|
* "updatedAt": "2025-10-28T17:08:15.409Z"
|
||||||
|
* }]
|
||||||
|
*
|
||||||
|
* */
|
||||||
|
async getDeletedPosts (ctx) {
|
||||||
|
try {
|
||||||
|
const deletedPosts = await this.useCases.nostr.getDeletedPosts()
|
||||||
|
|
||||||
|
ctx.body = { deletedPosts }
|
||||||
|
} catch (err) {
|
||||||
|
wlogger.error('Error in getDeletedPosts() REST API handler.')
|
||||||
|
this.handleError(ctx, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DRY error handler
|
||||||
|
handleError (ctx, err) {
|
||||||
|
// If an HTTP status is specified by the buisiness logic, use that.
|
||||||
|
if (err.status) {
|
||||||
|
if (err.message) {
|
||||||
|
ctx.throw(err.status, err.message)
|
||||||
|
} else {
|
||||||
|
ctx.throw(err.status)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// By default use a 422 error if the HTTP status is not specified.
|
||||||
|
ctx.throw(422, err.message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default NostrRESTControllerLib
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
/*
|
||||||
|
REST API library for /nostr route.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Public npm libraries.
|
||||||
|
import Router from 'koa-router'
|
||||||
|
|
||||||
|
// Local libraries.
|
||||||
|
import NostrRESTControllerLib from './controller.js'
|
||||||
|
|
||||||
|
import Validators from '../middleware/validators.js'
|
||||||
|
|
||||||
|
import config from '../../../../config/index.js'
|
||||||
|
|
||||||
|
class NostrRouter {
|
||||||
|
constructor (localConfig = {}) {
|
||||||
|
// Dependency Injection.
|
||||||
|
this.adapters = localConfig.adapters
|
||||||
|
if (!this.adapters) {
|
||||||
|
throw new Error(
|
||||||
|
'Instance of Adapters library required when instantiating NostrRouter REST Controller.'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
this.useCases = localConfig.useCases
|
||||||
|
if (!this.useCases) {
|
||||||
|
throw new Error(
|
||||||
|
'Instance of Use Cases library required when instantiating NostrRouter REST Controller.'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const dependencies = {
|
||||||
|
adapters: this.adapters,
|
||||||
|
useCases: this.useCases
|
||||||
|
}
|
||||||
|
|
||||||
|
// Encapsulate dependencies.
|
||||||
|
this.config = config
|
||||||
|
this.nostrRESTController = new NostrRESTControllerLib(dependencies)
|
||||||
|
this.validators = new Validators()
|
||||||
|
|
||||||
|
// Instantiate the router and set the base route.
|
||||||
|
const baseUrl = '/nostr'
|
||||||
|
this.router = new Router({ prefix: baseUrl })
|
||||||
|
|
||||||
|
this.attach = this.attach.bind(this)
|
||||||
|
this.createDeletedChat = this.createDeletedChat.bind(this)
|
||||||
|
this.createDeletedPost = this.createDeletedPost.bind(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
attach (app) {
|
||||||
|
if (!app) {
|
||||||
|
throw new Error(
|
||||||
|
'Must pass app object when attaching REST API controllers.'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Define the routes and attach the controller.
|
||||||
|
this.router.post('/deletedChat', this.createDeletedChat)
|
||||||
|
this.router.get('/deletedChat', this.nostrRESTController.getDeletedChats)
|
||||||
|
this.router.post('/deletedPost', this.createDeletedPost)
|
||||||
|
this.router.get('/deletedPost', this.nostrRESTController.getDeletedPosts)
|
||||||
|
|
||||||
|
// Attach the Controller routes to the Koa app.
|
||||||
|
app.use(this.router.routes())
|
||||||
|
app.use(this.router.allowedMethods())
|
||||||
|
}
|
||||||
|
|
||||||
|
async createDeletedChat (ctx, next) {
|
||||||
|
await this.validators.ensureAdmin(ctx, next)
|
||||||
|
await this.nostrRESTController.createDeletedChat(ctx, next)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
async createDeletedPost (ctx, next) {
|
||||||
|
await this.validators.ensureAdmin(ctx, next)
|
||||||
|
await this.nostrRESTController.createDeletedPost(ctx, next)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default NostrRouter
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
/*
|
||||||
|
DeletedChat Entity
|
||||||
|
*/
|
||||||
|
|
||||||
|
class DeletedChat {
|
||||||
|
validate (data = {}) {
|
||||||
|
const { eventId } = data
|
||||||
|
// Input Validation
|
||||||
|
if (!eventId || typeof eventId !== 'string') {
|
||||||
|
throw new Error("Property 'eventId' must be a string!")
|
||||||
|
}
|
||||||
|
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default DeletedChat
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
/*
|
||||||
|
DeletedPost Entity
|
||||||
|
*/
|
||||||
|
|
||||||
|
class DeletedPost {
|
||||||
|
validate (data = {}) {
|
||||||
|
const { eventId } = data
|
||||||
|
// Input Validation
|
||||||
|
if (!eventId || typeof eventId !== 'string') {
|
||||||
|
throw new Error("Property 'eventId' must be a string!")
|
||||||
|
}
|
||||||
|
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default DeletedPost
|
||||||
@@ -11,6 +11,7 @@ import OfferUseCases from './offer/index.js'
|
|||||||
import OrderUseCases from './order.js'
|
import OrderUseCases from './order.js'
|
||||||
import { UsageUseCases } from './usage-use-cases.js'
|
import { UsageUseCases } from './usage-use-cases.js'
|
||||||
import SmAccountUseCases from './smAccount-use-cases.js'
|
import SmAccountUseCases from './smAccount-use-cases.js'
|
||||||
|
import NostrUseCases from './nostr-use-cases.js'
|
||||||
|
|
||||||
class UseCases {
|
class UseCases {
|
||||||
constructor (localConfig = {}) {
|
constructor (localConfig = {}) {
|
||||||
@@ -29,6 +30,7 @@ class UseCases {
|
|||||||
this.offer = new OfferUseCases(localConfig)
|
this.offer = new OfferUseCases(localConfig)
|
||||||
this.usage = new UsageUseCases(localConfig)
|
this.usage = new UsageUseCases(localConfig)
|
||||||
this.smAccount = new SmAccountUseCases(localConfig)
|
this.smAccount = new SmAccountUseCases(localConfig)
|
||||||
|
this.nostr = new NostrUseCases(localConfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run any startup Use Cases at the start of the app.
|
// Run any startup Use Cases at the start of the app.
|
||||||
|
|||||||
@@ -0,0 +1,92 @@
|
|||||||
|
/*
|
||||||
|
This library contains business-logic for dealing with deleted chats. Most of these
|
||||||
|
functions are called by the /nostr REST API endpoints.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import wlogger from '../adapters/wlogger.js'
|
||||||
|
import DeletedChatEntity from '../entities/deletedChat.js'
|
||||||
|
import DeletedPostEntity from '../entities/deletedPost.js'
|
||||||
|
|
||||||
|
class NostrUseCases {
|
||||||
|
constructor (localConfig = {}) {
|
||||||
|
this.adapters = localConfig.adapters
|
||||||
|
if (!this.adapters) {
|
||||||
|
throw new Error(
|
||||||
|
'Instance of adapters must be passed in when instantiating Nostr Use Cases library.'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
// Encapsulate dependencies
|
||||||
|
this.DeletedChatEntity = new DeletedChatEntity()
|
||||||
|
this.DeletedPostEntity = new DeletedPostEntity()
|
||||||
|
this.DeletedChatModel = this.adapters.localdb.DeletedChat
|
||||||
|
this.DeletedPostModel = this.adapters.localdb.DeletedPost
|
||||||
|
|
||||||
|
this.createDeletedChat = this.createDeletedChat.bind(this)
|
||||||
|
this.getDeletedChats = this.getDeletedChats.bind(this)
|
||||||
|
this.createDeletedPost = this.createDeletedPost.bind(this)
|
||||||
|
this.getDeletedPosts = this.getDeletedPosts.bind(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new deleted chat model and add it to the Mongo database.
|
||||||
|
async createDeletedChat (deletedChatObj) {
|
||||||
|
try {
|
||||||
|
// Input Validation
|
||||||
|
|
||||||
|
const deletedChatEntity = this.DeletedChatEntity.validate(deletedChatObj)
|
||||||
|
const deletedChat = new this.DeletedChatModel(deletedChatEntity)
|
||||||
|
|
||||||
|
// Save the new model to the database.
|
||||||
|
await deletedChat.save()
|
||||||
|
return deletedChat
|
||||||
|
} catch (err) {
|
||||||
|
// console.log('createDeletedChat() error: ', err)
|
||||||
|
wlogger.error('Error in lib/nostr.js/createDeletedChat()')
|
||||||
|
throw err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns an array of all deleted chats models in the Mongo database.
|
||||||
|
async getDeletedChats () {
|
||||||
|
try {
|
||||||
|
// Get deleted chats models.
|
||||||
|
const deletedChats = await this.DeletedChatModel.find({})
|
||||||
|
|
||||||
|
return deletedChats
|
||||||
|
} catch (err) {
|
||||||
|
wlogger.error('Error in lib/users.js/getAllDeletedChat()')
|
||||||
|
throw err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new deleted post model and add it to the Mongo database.
|
||||||
|
async createDeletedPost (deletedPostObj) {
|
||||||
|
try {
|
||||||
|
// Input Validation
|
||||||
|
|
||||||
|
const deletedPostEntity = this.DeletedPostEntity.validate(deletedPostObj)
|
||||||
|
const deletedPost = new this.DeletedPostModel(deletedPostEntity)
|
||||||
|
|
||||||
|
// Save the new model to the database.
|
||||||
|
await deletedPost.save()
|
||||||
|
return deletedPost
|
||||||
|
} catch (err) {
|
||||||
|
wlogger.error('Error in lib/users.js/createDeletedPost()')
|
||||||
|
throw err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns an array of all deleted posts models in the Mongo database.
|
||||||
|
async getDeletedPosts () {
|
||||||
|
try {
|
||||||
|
// Get deleted posts models.
|
||||||
|
const deletedPosts = await this.DeletedPostModel.find({})
|
||||||
|
|
||||||
|
return deletedPosts
|
||||||
|
} catch (err) {
|
||||||
|
wlogger.error('Error in lib/users.js/getDeletedPosts()')
|
||||||
|
throw err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default NostrUseCases
|
||||||
@@ -0,0 +1,188 @@
|
|||||||
|
import testUtils from '../../utils/test-utils.js'
|
||||||
|
import { assert } from 'chai'
|
||||||
|
import config from '../../../config/index.js'
|
||||||
|
import axios from 'axios'
|
||||||
|
import sinon from 'sinon'
|
||||||
|
import util from 'util'
|
||||||
|
|
||||||
|
util.inspect.defaultOptions = { depth: 1 }
|
||||||
|
|
||||||
|
const LOCALHOST = `http://localhost:${config.port}`
|
||||||
|
|
||||||
|
const context = {}
|
||||||
|
let sandbox
|
||||||
|
|
||||||
|
// const mockContext = require('../../unit/mocks/ctx-mock').context
|
||||||
|
|
||||||
|
if (!config.noMongo) {
|
||||||
|
describe('Nostr', () => {
|
||||||
|
before(async () => {
|
||||||
|
// console.log(`config: ${JSON.stringify(config, null, 2)}`)
|
||||||
|
|
||||||
|
// Create a second test user.
|
||||||
|
const userObj = {
|
||||||
|
email: 'test2@test.com',
|
||||||
|
password: 'pass2',
|
||||||
|
name: 'test2'
|
||||||
|
}
|
||||||
|
const testUser = await testUtils.createUser(userObj)
|
||||||
|
// console.log(`testUser2: ${JSON.stringify(testUser, null, 2)}`)
|
||||||
|
|
||||||
|
context.user2 = testUser.user
|
||||||
|
context.token2 = testUser.token
|
||||||
|
context.id2 = testUser.user._id
|
||||||
|
|
||||||
|
// Get the JWT used to log in as the admin 'system' user.
|
||||||
|
const adminJWT = await testUtils.getAdminJWT()
|
||||||
|
console.log(`adminJWT: ${adminJWT}`)
|
||||||
|
context.adminJWT = adminJWT
|
||||||
|
|
||||||
|
// const admin = await testUtils.loginAdminUser()
|
||||||
|
// context.adminJWT = admin.token
|
||||||
|
|
||||||
|
// const admin = await adminLib.loginAdmin()
|
||||||
|
// console.log(`admin: ${JSON.stringify(admin, null, 2)}`)
|
||||||
|
})
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
// const useCases = new UseCases({ adapters })
|
||||||
|
// uut = new UserController({ adapters, useCases })
|
||||||
|
|
||||||
|
sandbox = sinon.createSandbox()
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(() => sandbox.restore())
|
||||||
|
|
||||||
|
describe('POST /nostr/deletedChat - Create Deleted Chat', () => {
|
||||||
|
it('should not create deleted chat if the authorization header is missing', async () => {
|
||||||
|
try {
|
||||||
|
const options = {
|
||||||
|
method: 'POST',
|
||||||
|
url: `${LOCALHOST}/nostr/deletedChat`
|
||||||
|
}
|
||||||
|
await axios(options)
|
||||||
|
|
||||||
|
assert.equal(true, false, 'Unexpected behavior')
|
||||||
|
} catch (err) {
|
||||||
|
assert.equal(err.response.status, 401)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
it('should not create deleted chat if the authorization header is invalid scheme', async () => {
|
||||||
|
try {
|
||||||
|
const options = {
|
||||||
|
method: 'POST',
|
||||||
|
url: `${LOCALHOST}/nostr/deletedChat`,
|
||||||
|
headers: {
|
||||||
|
Authorization: 'Bearer invalid'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await axios(options)
|
||||||
|
|
||||||
|
assert.equal(true, false, 'Unexpected behavior')
|
||||||
|
} catch (err) {
|
||||||
|
assert.equal(err.response.status, 401)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
it('should not create deleted chat if the authorization header is invalid token', async () => {
|
||||||
|
try {
|
||||||
|
const options = {
|
||||||
|
method: 'POST',
|
||||||
|
url: `${LOCALHOST}/nostr/deletedChat`,
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${context.token}`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await axios(options)
|
||||||
|
|
||||||
|
assert.equal(true, false, 'Unexpected behavior')
|
||||||
|
} catch (err) {
|
||||||
|
assert.equal(err.response.status, 401)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
it('should not create deleted chat if token is not admin', async () => {
|
||||||
|
try {
|
||||||
|
const options = {
|
||||||
|
method: 'POST',
|
||||||
|
url: `${LOCALHOST}/nostr/deletedChat`,
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${context.token}`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await axios(options)
|
||||||
|
|
||||||
|
assert.equal(true, false, 'Unexpected behavior')
|
||||||
|
} catch (err) {
|
||||||
|
assert.equal(err.response.status, 401)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('POST /nostr/deletedPost - Create Deleted Post', () => {
|
||||||
|
it('should not create deleted post if the authorization header is missing', async () => {
|
||||||
|
try {
|
||||||
|
const options = {
|
||||||
|
method: 'POST',
|
||||||
|
url: `${LOCALHOST}/nostr/deletedPost`
|
||||||
|
}
|
||||||
|
await axios(options)
|
||||||
|
|
||||||
|
assert.equal(true, false, 'Unexpected behavior')
|
||||||
|
} catch (err) {
|
||||||
|
assert.equal(err.response.status, 401)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should not create deleted post if the authorization header is invalid scheme', async () => {
|
||||||
|
try {
|
||||||
|
const options = {
|
||||||
|
method: 'POST',
|
||||||
|
url: `${LOCALHOST}/nostr/deletedPost`,
|
||||||
|
headers: {
|
||||||
|
Authorization: 'Bearer invalid'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await axios(options)
|
||||||
|
|
||||||
|
assert.equal(true, false, 'Unexpected behavior')
|
||||||
|
} catch (err) {
|
||||||
|
assert.equal(err.response.status, 401)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
it('should not create deleted post if the authorization header is invalid token', async () => {
|
||||||
|
try {
|
||||||
|
const options = {
|
||||||
|
method: 'POST',
|
||||||
|
url: `${LOCALHOST}/nostr/deletedPost`,
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${context.token}`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await axios(options)
|
||||||
|
|
||||||
|
assert.equal(true, false, 'Unexpected behavior')
|
||||||
|
} catch (err) {
|
||||||
|
assert.equal(err.response.status, 401)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
it('should not create deleted post if token is not admin', async () => {
|
||||||
|
try {
|
||||||
|
const options = {
|
||||||
|
method: 'POST',
|
||||||
|
url: `${LOCALHOST}/nostr/deletedPost`,
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${context.token}`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await axios(options)
|
||||||
|
|
||||||
|
assert.equal(true, false, 'Unexpected behavior')
|
||||||
|
} catch (err) {
|
||||||
|
assert.equal(err.response.status, 401)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1,201 @@
|
|||||||
|
/*
|
||||||
|
Unit tests for the REST API handler for the /nostr endpoints.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Public npm libraries
|
||||||
|
import { assert } from 'chai'
|
||||||
|
import sinon from 'sinon'
|
||||||
|
|
||||||
|
// Local support libraries
|
||||||
|
import adapters from '../../../mocks/adapters/index.js'
|
||||||
|
import UseCasesMock from '../../../mocks/use-cases/index.js'
|
||||||
|
import NostrController from '../../../../../src/controllers/rest-api/nostr/controller.js'
|
||||||
|
|
||||||
|
import { context as mockContext } from '../../../../unit/mocks/ctx-mock.js'
|
||||||
|
let uut
|
||||||
|
let sandbox
|
||||||
|
let ctx
|
||||||
|
|
||||||
|
describe('#Nostr-REST-Controller', () => {
|
||||||
|
// const testUser = {}
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
const useCases = new UseCasesMock()
|
||||||
|
uut = new NostrController({ adapters, useCases })
|
||||||
|
|
||||||
|
sandbox = sinon.createSandbox()
|
||||||
|
|
||||||
|
// Mock the context object.
|
||||||
|
ctx = mockContext()
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(() => sandbox.restore())
|
||||||
|
|
||||||
|
describe('#constructor', () => {
|
||||||
|
it('should throw an error if adapters are not passed in', () => {
|
||||||
|
try {
|
||||||
|
uut = new NostrController()
|
||||||
|
|
||||||
|
assert.fail('Unexpected code path')
|
||||||
|
} catch (err) {
|
||||||
|
assert.include(
|
||||||
|
err.message,
|
||||||
|
'Instance of Adapters library required when instantiating /nostr REST Controller.'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should throw an error if useCases are not passed in', () => {
|
||||||
|
try {
|
||||||
|
uut = new NostrController({ adapters })
|
||||||
|
|
||||||
|
assert.fail('Unexpected code path')
|
||||||
|
} catch (err) {
|
||||||
|
assert.include(
|
||||||
|
err.message,
|
||||||
|
'Instance of Use Cases library required when instantiating /nostr REST Controller.'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('#POST /nostr/deletedChat', () => {
|
||||||
|
it('should return 422 status on biz logic error', async () => {
|
||||||
|
try {
|
||||||
|
sandbox.stub(uut.useCases.nostr, 'createDeletedChat').rejects(new Error('test error'))
|
||||||
|
await uut.createDeletedChat(ctx)
|
||||||
|
|
||||||
|
assert.fail('Unexpected result')
|
||||||
|
} catch (err) {
|
||||||
|
// console.log(err)
|
||||||
|
assert.equal(err.status, 422)
|
||||||
|
assert.include(err.message, 'test error')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should return 200 status on success', async () => {
|
||||||
|
ctx.request.body = {
|
||||||
|
eventId: 'note19e93faw4ffqepsqsrwrnstd3ee00nmzakwwuyfjm43dankgummfqms4p6q',
|
||||||
|
npub: 'npub1d4ed5x49d7p24xn63flj4985dc4gpfngdhtqcxpth0ywhm6czxcscfpcq8',
|
||||||
|
bchAddr: 'bitcoincash:qpm2qsznhks23z7629mms6s4cwef74vcwvy22gdx6a',
|
||||||
|
pubkey: '6d72da1aa56f82aa9a7a8a7f2a94f46e2a80a6686dd60c182bbbc8ebef5811b1'
|
||||||
|
}
|
||||||
|
|
||||||
|
await uut.createDeletedChat(ctx)
|
||||||
|
|
||||||
|
// Assert the expected HTTP response
|
||||||
|
assert.equal(ctx.status, 200)
|
||||||
|
|
||||||
|
assert.isObject(ctx.response.body)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('#GET /nostr/deletedChat', () => {
|
||||||
|
it('should return 422 status on arbitrary biz logic error', async () => {
|
||||||
|
try {
|
||||||
|
// Force an error
|
||||||
|
sandbox
|
||||||
|
.stub(uut.useCases.nostr, 'getDeletedChats')
|
||||||
|
.rejects(new Error('test error'))
|
||||||
|
|
||||||
|
await uut.getDeletedChats(ctx)
|
||||||
|
|
||||||
|
assert.fail('Unexpected result')
|
||||||
|
} catch (err) {
|
||||||
|
assert.equal(err.status, 422)
|
||||||
|
assert.include(err.message, 'test error')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should return 200 status on success', async () => {
|
||||||
|
await uut.getDeletedChats(ctx)
|
||||||
|
|
||||||
|
// Assert the expected HTTP response
|
||||||
|
assert.equal(ctx.status, 200)
|
||||||
|
|
||||||
|
// Assert that expected properties exist in the returned data.
|
||||||
|
assert.isObject(ctx.response.body)
|
||||||
|
assert.property(ctx.response.body, 'deletedChats')
|
||||||
|
assert.isArray(ctx.response.body.deletedChats)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
describe('#POST /nostr/deletedPost', () => {
|
||||||
|
it('should return 422 status on biz logic error', async () => {
|
||||||
|
try {
|
||||||
|
sandbox.stub(uut.useCases.nostr, 'createDeletedPost').rejects(new Error('test error'))
|
||||||
|
await uut.createDeletedPost(ctx)
|
||||||
|
|
||||||
|
assert.fail('Unexpected result')
|
||||||
|
} catch (err) {
|
||||||
|
assert.equal(err.status, 422)
|
||||||
|
assert.include(err.message, 'test error')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
it('should return 200 status on success', async () => {
|
||||||
|
ctx.request.body = {
|
||||||
|
eventId: 'note19e93faw4ffqepsqsrwrnstd3ee00nmzakwwuyfjm43dankgummfqms4p6q',
|
||||||
|
npub: 'npub1d4ed5x49d7p24xn63flj4985dc4gpfngdhtqcxpth0ywhm6czxcscfpcq8',
|
||||||
|
bchAddr: 'bitcoincash:qpm2qsznhks23z7629mms6s4cwef74vcwvy22gdx6a',
|
||||||
|
pubkey: '6d72da1aa56f82aa9a7a8a7f2a94f46e2a80a6686dd60c182bbbc8ebef5811b1'
|
||||||
|
}
|
||||||
|
|
||||||
|
await uut.createDeletedPost(ctx)
|
||||||
|
|
||||||
|
assert.equal(ctx.status, 200)
|
||||||
|
|
||||||
|
assert.isObject(ctx.response.body)
|
||||||
|
assert.property(ctx.response.body, 'deletedPost')
|
||||||
|
assert.isObject(ctx.response.body.deletedPost)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
describe('#GET /nostr/deletedPost', () => {
|
||||||
|
it('should return 422 status on biz logic error', async () => {
|
||||||
|
try {
|
||||||
|
sandbox.stub(uut.useCases.nostr, 'getDeletedPosts').rejects(new Error('test error'))
|
||||||
|
await uut.getDeletedPosts(ctx)
|
||||||
|
|
||||||
|
assert.fail('Unexpected result')
|
||||||
|
} catch (err) {
|
||||||
|
assert.equal(err.status, 422)
|
||||||
|
assert.include(err.message, 'test error')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
it('should return 200 status on success', async () => {
|
||||||
|
await uut.getDeletedPosts(ctx)
|
||||||
|
|
||||||
|
// Assert the expected HTTP response
|
||||||
|
assert.equal(ctx.status, 200)
|
||||||
|
|
||||||
|
assert.isObject(ctx.response.body)
|
||||||
|
assert.property(ctx.response.body, 'deletedPosts')
|
||||||
|
assert.isArray(ctx.response.body.deletedPosts)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('#handleError', () => {
|
||||||
|
it('should still throw error if there is no message', () => {
|
||||||
|
try {
|
||||||
|
const err = {
|
||||||
|
status: 404
|
||||||
|
}
|
||||||
|
|
||||||
|
uut.handleError(ctx, err)
|
||||||
|
} catch (err) {
|
||||||
|
assert.include(err.message, 'Not Found')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should throw error with message', () => {
|
||||||
|
try {
|
||||||
|
const err = {
|
||||||
|
status: 422,
|
||||||
|
message: 'test error'
|
||||||
|
}
|
||||||
|
|
||||||
|
uut.handleError(ctx, err)
|
||||||
|
} catch (err) {
|
||||||
|
assert.include(err.message, 'test error')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -0,0 +1,108 @@
|
|||||||
|
/*
|
||||||
|
Unit tests for the REST API handler for the /nostr endpoints.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Public npm libraries
|
||||||
|
import { assert } from 'chai'
|
||||||
|
|
||||||
|
import sinon from 'sinon'
|
||||||
|
|
||||||
|
// Local support libraries
|
||||||
|
import adapters from '../../../mocks/adapters/index.js'
|
||||||
|
|
||||||
|
import UseCasesMock from '../../../mocks/use-cases/index.js'
|
||||||
|
|
||||||
|
// const app = require('../../../mocks/app-mock')
|
||||||
|
|
||||||
|
import NostrRouter from '../../../../../src/controllers/rest-api/nostr/index.js'
|
||||||
|
|
||||||
|
let uut
|
||||||
|
let sandbox
|
||||||
|
// let ctx
|
||||||
|
|
||||||
|
// const mockContext = require('../../../../unit/mocks/ctx-mock').context
|
||||||
|
|
||||||
|
describe('#Nostr-REST-Router', () => {
|
||||||
|
// const testUser = {}
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
const useCases = new UseCasesMock()
|
||||||
|
uut = new NostrRouter({ adapters, useCases })
|
||||||
|
|
||||||
|
sandbox = sinon.createSandbox()
|
||||||
|
|
||||||
|
// Mock the context object.
|
||||||
|
// ctx = mockContext()
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(() => sandbox.restore())
|
||||||
|
|
||||||
|
describe('#constructor', () => {
|
||||||
|
it('should throw an error if adapters are not passed in', () => {
|
||||||
|
try {
|
||||||
|
uut = new NostrRouter()
|
||||||
|
|
||||||
|
assert.fail('Unexpected code path')
|
||||||
|
} catch (err) {
|
||||||
|
assert.include(
|
||||||
|
err.message,
|
||||||
|
'Instance of Adapters library required when instantiating NostrRouter REST Controller.'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should throw an error if useCases are not passed in', () => {
|
||||||
|
try {
|
||||||
|
uut = new NostrRouter({ adapters })
|
||||||
|
|
||||||
|
assert.fail('Unexpected code path')
|
||||||
|
} catch (err) {
|
||||||
|
assert.include(
|
||||||
|
err.message,
|
||||||
|
'Instance of Use Cases library required when instantiating NostrRouter REST Controller.'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('#attach', () => {
|
||||||
|
it('should throw an error if app is not passed in.', () => {
|
||||||
|
try {
|
||||||
|
uut.attach()
|
||||||
|
|
||||||
|
assert.fail('Unexpected code path')
|
||||||
|
} catch (err) {
|
||||||
|
assert.include(
|
||||||
|
err.message,
|
||||||
|
'Must pass app object when attaching REST API controllers.'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('#createDeletedChat', () => {
|
||||||
|
it('should route to the createDeletedChat function', async () => {
|
||||||
|
// Stub functions
|
||||||
|
const validationSpy = sandbox.stub(uut.validators, 'ensureAdmin').resolves(true)
|
||||||
|
sandbox.stub(uut.nostrRESTController, 'createDeletedChat').resolves(true)
|
||||||
|
|
||||||
|
// Call function
|
||||||
|
const res = await uut.createDeletedChat()
|
||||||
|
assert.isTrue(validationSpy.calledOnce, 'Admin validator should be called')
|
||||||
|
assert.isTrue(res)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('#createDeletedPost', () => {
|
||||||
|
it('should route to the createDeletedPost function', async () => {
|
||||||
|
// Stub functions
|
||||||
|
const validationSpy = sandbox.stub(uut.validators, 'ensureAdmin').resolves(true)
|
||||||
|
sandbox.stub(uut.nostrRESTController, 'createDeletedPost').resolves(true)
|
||||||
|
|
||||||
|
// Call function
|
||||||
|
const res = await uut.createDeletedPost()
|
||||||
|
assert.isTrue(validationSpy.calledOnce, 'Admin validator should be called')
|
||||||
|
assert.isTrue(res)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
Unit tests for the DeletedChat entity library.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { assert } from 'chai'
|
||||||
|
import sinon from 'sinon'
|
||||||
|
|
||||||
|
import DeletedChat from '../../../src/entities/deletedChat.js'
|
||||||
|
|
||||||
|
let sandbox
|
||||||
|
let uut
|
||||||
|
|
||||||
|
describe('#DeletedChat-Entity', () => {
|
||||||
|
before(async () => {})
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
uut = new DeletedChat()
|
||||||
|
|
||||||
|
sandbox = sinon.createSandbox()
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(() => sandbox.restore())
|
||||||
|
|
||||||
|
describe('#validate', () => {
|
||||||
|
it('should throw an error if eventId is not provided', () => {
|
||||||
|
try {
|
||||||
|
uut.validate()
|
||||||
|
} catch (err) {
|
||||||
|
assert.include(err.message, "Property 'eventId' must be a string!")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should return a DeletedChat object', () => {
|
||||||
|
const inputData = {
|
||||||
|
eventId: 'note19e93faw4ffqepsqsrwrnstd3ee00nmzakwwuyfjm43dankgummfqms4p6q',
|
||||||
|
npub: 'npub1d4ed5x49d7p24xn63flj4985dc4gpfngdhtqcxpth0ywhm6czxcscfpcq8',
|
||||||
|
bchAddr: 'bitcoincash:qpm2qsznhks23z7629mms6s4cwef74vcwvy22gdx6a',
|
||||||
|
pubkey: '6d72da1aa56f82aa9a7a8a7f2a94f46e2a80a6686dd60c182bbbc8ebef5811b1'
|
||||||
|
}
|
||||||
|
|
||||||
|
const deletedChat = uut.validate(inputData)
|
||||||
|
// console.log('entry: ', entry)
|
||||||
|
|
||||||
|
assert.property(deletedChat, 'eventId')
|
||||||
|
assert.equal(deletedChat.eventId, inputData.eventId)
|
||||||
|
|
||||||
|
assert.property(deletedChat, 'npub')
|
||||||
|
assert.equal(deletedChat.npub, inputData.npub)
|
||||||
|
|
||||||
|
assert.property(deletedChat, 'bchAddr')
|
||||||
|
assert.equal(deletedChat.bchAddr, inputData.bchAddr)
|
||||||
|
|
||||||
|
assert.property(deletedChat, 'pubkey')
|
||||||
|
assert.equal(deletedChat.pubkey, inputData.pubkey)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
Unit tests for the DeletedPost entity library.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { assert } from 'chai'
|
||||||
|
import sinon from 'sinon'
|
||||||
|
|
||||||
|
import DeletedPost from '../../../src/entities/deletedPost.js'
|
||||||
|
|
||||||
|
let sandbox
|
||||||
|
let uut
|
||||||
|
|
||||||
|
describe('#DeletedPost-Entity', () => {
|
||||||
|
before(async () => { })
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
uut = new DeletedPost()
|
||||||
|
|
||||||
|
sandbox = sinon.createSandbox()
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(() => sandbox.restore())
|
||||||
|
|
||||||
|
describe('#validate', () => {
|
||||||
|
it('should throw an error if eventId is not provided', () => {
|
||||||
|
try {
|
||||||
|
uut.validate()
|
||||||
|
} catch (err) {
|
||||||
|
assert.include(err.message, "Property 'eventId' must be a string!")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should return a DeletedPost object', () => {
|
||||||
|
const inputData = {
|
||||||
|
eventId: 'note19e93faw4ffqepsqsrwrnstd3ee00nmzakwwuyfjm43dankgummfqms4p6q',
|
||||||
|
npub: 'npub1d4ed5x49d7p24xn63flj4985dc4gpfngdhtqcxpth0ywhm6czxcscfpcq8',
|
||||||
|
bchAddr: 'bitcoincash:qpm2qsznhks23z7629mms6s4cwef74vcwvy22gdx6a',
|
||||||
|
pubkey: '6d72da1aa56f82aa9a7a8a7f2a94f46e2a80a6686dd60c182bbbc8ebef5811b1'
|
||||||
|
}
|
||||||
|
|
||||||
|
const deletedPost = uut.validate(inputData)
|
||||||
|
// console.log('entry: ', entry)
|
||||||
|
|
||||||
|
assert.property(deletedPost, 'eventId')
|
||||||
|
assert.equal(deletedPost.eventId, inputData.eventId)
|
||||||
|
|
||||||
|
assert.property(deletedPost, 'npub')
|
||||||
|
assert.equal(deletedPost.npub, inputData.npub)
|
||||||
|
|
||||||
|
assert.property(deletedPost, 'bchAddr')
|
||||||
|
assert.equal(deletedPost.bchAddr, inputData.bchAddr)
|
||||||
|
|
||||||
|
assert.property(deletedPost, 'pubkey')
|
||||||
|
assert.equal(deletedPost.pubkey, inputData.pubkey)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -165,7 +165,31 @@ const localdb = {
|
|||||||
async save () {
|
async save () {
|
||||||
return {}
|
return {}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
DeletedChat: class DeletedChat {
|
||||||
|
constructor (obj) {}
|
||||||
|
|
||||||
|
static findById () {}
|
||||||
|
static find () {}
|
||||||
|
static findOne () {}
|
||||||
|
static updateOne () {}
|
||||||
|
|
||||||
|
async save () {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
DeletedPost: class DeletedPost {
|
||||||
|
constructor (obj) {}
|
||||||
|
|
||||||
|
static findById () {}
|
||||||
|
static find () {}
|
||||||
|
static findOne () {}
|
||||||
|
static updateOne () {}
|
||||||
|
|
||||||
|
async save () {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const bch = {
|
const bch = {
|
||||||
|
|||||||
@@ -135,6 +135,22 @@ class SmAccountUseCaseMock {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class NostrUseCasesMock {
|
||||||
|
async createDeletedChat() {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
async getDeletedChats() {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
async createDeletedPost() {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
async getDeletedPosts() {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
class UseCasesMock {
|
class UseCasesMock {
|
||||||
constuctor(localConfig = {}) {
|
constuctor(localConfig = {}) {
|
||||||
// this.user = new UserUseCaseMock(localConfig)
|
// this.user = new UserUseCaseMock(localConfig)
|
||||||
@@ -146,6 +162,7 @@ class UseCasesMock {
|
|||||||
order = new Order()
|
order = new Order()
|
||||||
usage = new UsageUseCaseMock()
|
usage = new UsageUseCaseMock()
|
||||||
smAccount = new SmAccountUseCaseMock()
|
smAccount = new SmAccountUseCaseMock()
|
||||||
|
nostr = new NostrUseCasesMock()
|
||||||
}
|
}
|
||||||
|
|
||||||
export default UseCasesMock;
|
export default UseCasesMock;
|
||||||
|
|||||||
@@ -0,0 +1,213 @@
|
|||||||
|
/*
|
||||||
|
Unit tests for the Nostr Use Case library.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Public npm libraries
|
||||||
|
import { assert } from 'chai'
|
||||||
|
import sinon from 'sinon'
|
||||||
|
|
||||||
|
// Unit under test (uut)
|
||||||
|
import NostrUseCases from '../../../src/use-cases/nostr-use-cases.js'
|
||||||
|
// Local support libraries
|
||||||
|
import adapters from '../mocks/adapters/index.js'
|
||||||
|
|
||||||
|
describe('#nostr-use-cases', () => {
|
||||||
|
let uut
|
||||||
|
let sandbox
|
||||||
|
|
||||||
|
before(async () => {
|
||||||
|
// Delete all previous users in the database.
|
||||||
|
// await testUtils.deleteAllUsers()
|
||||||
|
})
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
sandbox = sinon.createSandbox()
|
||||||
|
|
||||||
|
uut = new NostrUseCases({ adapters })
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(() => sandbox.restore())
|
||||||
|
|
||||||
|
describe('#constructor', () => {
|
||||||
|
it('should throw an error if adapters are not passed in', () => {
|
||||||
|
try {
|
||||||
|
uut = new NostrUseCases()
|
||||||
|
|
||||||
|
assert.fail('Unexpected code path')
|
||||||
|
console.log(uut) // linter
|
||||||
|
} catch (err) {
|
||||||
|
assert.include(
|
||||||
|
err.message,
|
||||||
|
'Instance of adapters must be passed in when instantiating Nostr Use Cases library.'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('#createDeletedChat', () => {
|
||||||
|
it('should throw an error if no input is given', async () => {
|
||||||
|
try {
|
||||||
|
await uut.createDeletedChat()
|
||||||
|
|
||||||
|
assert.fail('Unexpected code path')
|
||||||
|
} catch (err) {
|
||||||
|
// console.log(err)
|
||||||
|
// assert.equal(err.status, 422)
|
||||||
|
assert.include(err.message, "Property 'eventId' must be a string!")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should throw an error if eventId is not provided', async () => {
|
||||||
|
try {
|
||||||
|
await uut.createDeletedChat({})
|
||||||
|
|
||||||
|
assert.fail('Unexpected code path')
|
||||||
|
} catch (err) {
|
||||||
|
assert.include(err.message, "Property 'eventId' must be a string!")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should catch and throw DB errors', async () => {
|
||||||
|
try {
|
||||||
|
// Force an error with the database.
|
||||||
|
sandbox.stub(uut, 'DeletedChatModel').throws(new Error('test error'))
|
||||||
|
|
||||||
|
const inObj = {
|
||||||
|
eventId: 'note19e93faw4ffqepsqsrwrnstd3ee00nmzakwwuyfjm43dankgummfqms4p6q'
|
||||||
|
}
|
||||||
|
|
||||||
|
await uut.createDeletedChat(inObj)
|
||||||
|
|
||||||
|
assert.fail('Unexpected code path')
|
||||||
|
} catch (err) {
|
||||||
|
assert.include(err.message, 'test error')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should create a new deleted chat model with minimum inputs', async () => {
|
||||||
|
const inObj = {
|
||||||
|
eventId: 'note19e93faw4ffqepsqsrwrnstd3ee00nmzakwwuyfjm43dankgummfqms4p6q'
|
||||||
|
}
|
||||||
|
|
||||||
|
const res = await uut.createDeletedChat(inObj)
|
||||||
|
|
||||||
|
assert.isObject(res)
|
||||||
|
})
|
||||||
|
it('should create a new deleted chat model with maximum inputs', async () => {
|
||||||
|
const inObj = {
|
||||||
|
eventId: 'note19e93faw4ffqepsqsrwrnstd3ee00nmzakwwuyfjm43dankgummfqms4p6q',
|
||||||
|
npub: 'npub1d4ed5x49d7p24xn63flj4985dc4gpfngdhtqcxpth0ywhm6czxcscfpcq8',
|
||||||
|
bchAddr: 'bitcoincash:qpm2qsznhks23z7629mms6s4cwef74vcwvy22gdx6a',
|
||||||
|
pubkey: '6d72da1aa56f82aa9a7a8a7f2a94f46e2a80a6686dd60c182bbbc8ebef5811b1'
|
||||||
|
}
|
||||||
|
|
||||||
|
const res = await uut.createDeletedChat(inObj)
|
||||||
|
|
||||||
|
assert.isObject(res)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('#getDeletedChats', () => {
|
||||||
|
it('should return all deleted chats from the database', async () => {
|
||||||
|
sandbox.stub(uut.DeletedChatModel, 'find').resolves([])
|
||||||
|
const res = await uut.getDeletedChats()
|
||||||
|
|
||||||
|
assert.isArray(res)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should catch and throw an error', async () => {
|
||||||
|
try {
|
||||||
|
// Force an error.
|
||||||
|
sandbox.stub(uut.DeletedChatModel, 'find').rejects(new Error('test error'))
|
||||||
|
|
||||||
|
await uut.getDeletedChats()
|
||||||
|
|
||||||
|
assert.fail('Unexpected code path')
|
||||||
|
} catch (err) {
|
||||||
|
assert.include(err.message, 'test error')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('#createDeletedPost', () => {
|
||||||
|
it('should throw an error if no input is given', async () => {
|
||||||
|
try {
|
||||||
|
await uut.createDeletedPost()
|
||||||
|
|
||||||
|
assert.fail('Unexpected code path')
|
||||||
|
} catch (err) {
|
||||||
|
assert.include(err.message, "Property 'eventId' must be a string!")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should throw an error if eventId is not provided', async () => {
|
||||||
|
try {
|
||||||
|
await uut.createDeletedPost({})
|
||||||
|
|
||||||
|
assert.fail('Unexpected code path')
|
||||||
|
} catch (err) {
|
||||||
|
assert.include(err.message, "Property 'eventId' must be a string!")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should catch and throw DB errors', async () => {
|
||||||
|
try {
|
||||||
|
// Force an error with the database.
|
||||||
|
sandbox.stub(uut, 'DeletedPostModel').throws(new Error('test error'))
|
||||||
|
|
||||||
|
const inObj = {
|
||||||
|
eventId: 'note19e93faw4ffqepsqsrwrnstd3ee00nmzakwwuyfjm43dankgummfqms4p6q'
|
||||||
|
}
|
||||||
|
|
||||||
|
await uut.createDeletedPost(inObj)
|
||||||
|
|
||||||
|
assert.fail('Unexpected code path')
|
||||||
|
} catch (err) {
|
||||||
|
assert.include(err.message, 'test error')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
it('should create a new deleted post model with minimum inputs', async () => {
|
||||||
|
const inObj = {
|
||||||
|
eventId: 'note19e93faw4ffqepsqsrwrnstd3ee00nmzakwwuyfjm43dankgummfqms4p6q'
|
||||||
|
}
|
||||||
|
|
||||||
|
const res = await uut.createDeletedPost(inObj)
|
||||||
|
|
||||||
|
assert.isObject(res)
|
||||||
|
})
|
||||||
|
it('should create a new deleted post model with maximum inputs', async () => {
|
||||||
|
const inObj = {
|
||||||
|
eventId: 'note19e93faw4ffqepsqsrwrnstd3ee00nmzakwwuyfjm43dankgummfqms4p6q',
|
||||||
|
npub: 'npub1d4ed5x49d7p24xn63flj4985dc4gpfngdhtqcxpth0ywhm6czxcscfpcq8',
|
||||||
|
bchAddr: 'bitcoincash:qpm2qsznhks23z7629mms6s4cwef74vcwvy22gdx6a',
|
||||||
|
pubkey: '6d72da1aa56f82aa9a7a8a7f2a94f46e2a80a6686dd60c182bbbc8ebef5811b1'
|
||||||
|
}
|
||||||
|
|
||||||
|
const res = await uut.createDeletedPost(inObj)
|
||||||
|
|
||||||
|
assert.isObject(res)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('#getDeletedPosts', () => {
|
||||||
|
it('should return all deleted posts from the database', async () => {
|
||||||
|
sandbox.stub(uut.DeletedPostModel, 'find').resolves([])
|
||||||
|
const res = await uut.getDeletedPosts()
|
||||||
|
|
||||||
|
assert.isArray(res)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should catch and throw an error', async () => {
|
||||||
|
try {
|
||||||
|
// Force an error.
|
||||||
|
sandbox.stub(uut.DeletedPostModel, 'find').rejects(new Error('test error'))
|
||||||
|
|
||||||
|
await uut.getDeletedPosts()
|
||||||
|
|
||||||
|
assert.fail('Unexpected code path')
|
||||||
|
} catch (err) {
|
||||||
|
assert.include(err.message, 'test error')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user