Merge pull request 'feat(nostr): added nostrEvent validation' (#29) from payload-validation into staging
Reviewed-on: #29
This commit is contained in:
commit
063f945cf0
src
models
routes
utils
@ -1,10 +1,12 @@
|
||||
import { ObjectId } from 'mongodb'
|
||||
export class NostrEvent {
|
||||
constructor(
|
||||
public nostrId: string, // nostr unique identifier
|
||||
public pubkey: string, // public key of the event creator
|
||||
public created_at: number, // timestamp
|
||||
public kind: number, // event type, e.g., review, article, comment
|
||||
public tags: [string][], // array of keywords or hashtags
|
||||
public content: string // text content of the event
|
||||
public tags: string[][], // array of keywords or hashtags
|
||||
public content: string, // text content of the event
|
||||
public id?: ObjectId
|
||||
) {}
|
||||
}
|
||||
|
@ -2,6 +2,13 @@
|
||||
import express, { Request, Response } from 'express'
|
||||
import { collections } from '../services/database.service'
|
||||
import { NostrEvent } from '../models'
|
||||
import {
|
||||
nostrEventValidation,
|
||||
handleReqError,
|
||||
handleReqSuccess
|
||||
} from '../utils'
|
||||
import { Event } from 'nostr-tools'
|
||||
import Joi from 'joi'
|
||||
|
||||
// Global Config
|
||||
export const nostrRouter = express.Router()
|
||||
@ -26,23 +33,39 @@ nostrRouter.get('/', async (_req: Request, res: Response) => {
|
||||
// POST
|
||||
nostrRouter.post('/', async (req: Request, res: Response) => {
|
||||
try {
|
||||
const nostrEvent = req.body as NostrEvent
|
||||
const {
|
||||
error,
|
||||
value: event
|
||||
}: { error: Joi.ValidationError | undefined; value: Event } =
|
||||
nostrEventValidation(req.body)
|
||||
|
||||
if (error) {
|
||||
throw error.details[0].message
|
||||
}
|
||||
|
||||
const { id, pubkey, created_at, kind, tags, content } = event
|
||||
|
||||
const events = await collections.nostrEvents
|
||||
?.find({ nostrId: id })
|
||||
.toArray()
|
||||
|
||||
if (events?.length) {
|
||||
throw new Error('nostr event with provided "id" exists')
|
||||
}
|
||||
|
||||
const nostrEvent: NostrEvent = {
|
||||
nostrId: id,
|
||||
pubkey,
|
||||
created_at,
|
||||
kind,
|
||||
tags,
|
||||
content
|
||||
}
|
||||
|
||||
const result = await collections.nostrEvents?.insertOne(nostrEvent)
|
||||
|
||||
if (result) {
|
||||
res
|
||||
.status(201)
|
||||
.send(
|
||||
`Successfully created a new nostrEvent with id ${result.insertedId}`
|
||||
)
|
||||
} else {
|
||||
res.status(500).send('Failed to create a new nostrEvent.')
|
||||
}
|
||||
handleReqSuccess(res, result, 'nostrEvent')
|
||||
} catch (error: unknown) {
|
||||
console.error(error)
|
||||
|
||||
if (error instanceof Error) {
|
||||
res.status(400).send(error.message)
|
||||
}
|
||||
handleReqError(res, error)
|
||||
}
|
||||
})
|
||||
|
@ -2,7 +2,7 @@
|
||||
import express, { Request, Response } from 'express'
|
||||
import { collections } from '../services/database.service'
|
||||
import { User } from '../models'
|
||||
import { userValidation } from '../utils'
|
||||
import { userValidation, handleReqError, handleReqSuccess } from '../utils'
|
||||
import Joi from 'joi'
|
||||
|
||||
// Global Config
|
||||
@ -59,20 +59,8 @@ usersRouter.post('/', async (req: Request, res: Response) => {
|
||||
|
||||
const result = await collections.users?.insertOne(newUser)
|
||||
|
||||
if (result) {
|
||||
res
|
||||
.status(201)
|
||||
.send(`Successfully created a new user with id ${result.insertedId}`)
|
||||
} else {
|
||||
res.status(500).send('Failed to create a new user.')
|
||||
}
|
||||
handleReqSuccess(res, result, 'user')
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
|
||||
if (error instanceof Error) {
|
||||
res.status(400).send(error.message)
|
||||
} else if (typeof error === 'string') {
|
||||
res.status(400).send(error)
|
||||
}
|
||||
handleReqError(res, error)
|
||||
}
|
||||
})
|
||||
|
@ -1,2 +1,3 @@
|
||||
export * from './validation'
|
||||
export * from './nostr'
|
||||
export * from './route'
|
||||
|
28
src/utils/route.ts
Normal file
28
src/utils/route.ts
Normal file
@ -0,0 +1,28 @@
|
||||
import { Response } from 'express'
|
||||
import { InsertOneResult } from 'mongodb'
|
||||
|
||||
export const handleReqError = (res: Response, error: unknown) => {
|
||||
console.error(error)
|
||||
|
||||
if (error instanceof Error) {
|
||||
res.status(400).send(error.message)
|
||||
} else if (typeof error === 'string') {
|
||||
res.status(400).send(error)
|
||||
}
|
||||
}
|
||||
|
||||
export const handleReqSuccess = (
|
||||
res: Response,
|
||||
result: InsertOneResult<Document> | undefined,
|
||||
itemName: string
|
||||
) => {
|
||||
if (result) {
|
||||
res
|
||||
.status(201)
|
||||
.send(
|
||||
`Successfully created a new ${itemName} with id ${result.insertedId}`
|
||||
)
|
||||
} else {
|
||||
res.status(500).send(`Failed to create a new ${itemName}.`)
|
||||
}
|
||||
}
|
@ -1 +1,2 @@
|
||||
export * from './user'
|
||||
export * from './nostr'
|
||||
|
24
src/utils/validation/nostr.ts
Normal file
24
src/utils/validation/nostr.ts
Normal file
@ -0,0 +1,24 @@
|
||||
import Joi from 'joi'
|
||||
import { npubToHex, validateHex } from '../nostr'
|
||||
|
||||
export const nostrEventValidation = (data: unknown): Joi.ValidationResult =>
|
||||
Joi.object({
|
||||
id: Joi.string().required(),
|
||||
kind: Joi.number().required(),
|
||||
content: Joi.string().required(),
|
||||
tags: Joi.array().items(Joi.array().items(Joi.string())),
|
||||
created_at: Joi.number().required(),
|
||||
pubkey: Joi.string()
|
||||
.custom((value, helper) => {
|
||||
const hex = npubToHex(value as string)
|
||||
|
||||
if (!hex || !validateHex(hex)) {
|
||||
return helper.message({
|
||||
custom: Joi.expression('"pubkey" contains an invalid value')
|
||||
})
|
||||
}
|
||||
|
||||
return value
|
||||
})
|
||||
.required()
|
||||
}).validate(data)
|
@ -16,11 +16,11 @@ const npubValidation = (value: unknown, helper: Joi.CustomHelpers<unknown>) => {
|
||||
|
||||
export const userValidation = (data: unknown): Joi.ValidationResult =>
|
||||
Joi.object({
|
||||
name: Joi.string().not('').required(),
|
||||
name: Joi.string().required(),
|
||||
npub: Joi.alternatives()
|
||||
.try(
|
||||
Joi.array().items(Joi.string().custom(npubValidation)),
|
||||
Joi.string().not('').custom(npubValidation)
|
||||
Joi.string().custom(npubValidation)
|
||||
)
|
||||
.required(),
|
||||
role: Joi.string()
|
||||
|
Loading…
x
Reference in New Issue
Block a user