fix(user): disabled multiple npubs #31

Merged
y merged 1 commits from payload-validation into staging 2025-04-02 12:12:01 +00:00
11 changed files with 24 additions and 48 deletions

@ -7,6 +7,6 @@ export class NostrEvent {
public kind: number, // event type, e.g., review, article, comment public kind: number, // event type, e.g., review, article, comment
public tags: string[][], // array of keywords or hashtags public tags: string[][], // array of keywords or hashtags
public content: string, // text content of the event public content: string, // text content of the event
public id?: ObjectId public id?: ObjectId // database object id
) {} ) {}
} }

@ -3,9 +3,9 @@ import { UserRole } from '../types'
export class User { export class User {
constructor( constructor(
public name: string, public name: string, // name
public npub: string | string[], public npub: string, // npub
public role: UserRole, public role: UserRole, // user role (user, reviewer, producer)
public id?: ObjectId public id?: ObjectId // database object id
) {} ) {}
} }

@ -22,8 +22,8 @@ export class Wine {
public viticulture: Viticulture, // two-letter country codes public viticulture: Viticulture, // two-letter country codes
public sulfites: number, // parts per million public sulfites: number, // parts per million
public filtered: boolean, // is wine filtered (fined (egg or fish)) public filtered: boolean, // is wine filtered (fined (egg or fish))
public vegan: boolean, public vegan: boolean, // if wine is vegan
public kosher: boolean, public kosher: boolean, // if wine is kosher
public closure: BottleClosure, // cork, crown-seal, screwcap public closure: BottleClosure, // cork, crown-seal, screwcap
public RRPamount: number, // 20 public RRPamount: number, // 20
public RRPcurrency: CurrencyCode, // USD public RRPcurrency: CurrencyCode, // USD

@ -2,7 +2,6 @@ import express, { Request, Response } from 'express'
import { collections } from '../services/database.service' import { collections } from '../services/database.service'
import { Coffee } from '../models' import { Coffee } from '../models'
// Global Config
export const coffeeRouter = express.Router() export const coffeeRouter = express.Router()
coffeeRouter.use(express.json()) coffeeRouter.use(express.json())

@ -1,4 +1,3 @@
// External Dependencies
import express, { Request, Response } from 'express' import express, { Request, Response } from 'express'
import { collections } from '../services/database.service' import { collections } from '../services/database.service'
import { NostrEvent } from '../models' import { NostrEvent } from '../models'
@ -10,7 +9,6 @@ import {
import { Event } from 'nostr-tools' import { Event } from 'nostr-tools'
import Joi from 'joi' import Joi from 'joi'
// Global Config
export const nostrRouter = express.Router() export const nostrRouter = express.Router()
nostrRouter.use(express.json()) nostrRouter.use(express.json())

@ -4,7 +4,6 @@ import { Review } from '../models'
import { reviewValidation, handleReqError, handleReqSuccess } from '../utils' import { reviewValidation, handleReqError, handleReqSuccess } from '../utils'
import Joi from 'joi' import Joi from 'joi'
// Global Config
export const reviewsRouter = express.Router() export const reviewsRouter = express.Router()
reviewsRouter.use(express.json()) reviewsRouter.use(express.json())

@ -2,7 +2,6 @@ import express, { Request, Response } from 'express'
import { collections } from '../services/database.service' import { collections } from '../services/database.service'
import { Sake } from '../models' import { Sake } from '../models'
// Global Config
export const sakeRouter = express.Router() export const sakeRouter = express.Router()
sakeRouter.use(express.json()) sakeRouter.use(express.json())

@ -2,7 +2,6 @@ import express, { Request, Response } from 'express'
import { collections } from '../services/database.service' import { collections } from '../services/database.service'
import { Spirit } from '../models' import { Spirit } from '../models'
// Global Config
export const spiritsRouter = express.Router() export const spiritsRouter = express.Router()
spiritsRouter.use(express.json()) spiritsRouter.use(express.json())

@ -1,11 +1,9 @@
// External Dependencies
import express, { Request, Response } from 'express' import express, { Request, Response } from 'express'
import { collections } from '../services/database.service' import { collections } from '../services/database.service'
import { User } from '../models' import { User } from '../models'
import { userValidation, handleReqError, handleReqSuccess } from '../utils' import { userValidation, handleReqError, handleReqSuccess } from '../utils'
import Joi from 'joi' import Joi from 'joi'
// Global Config
export const usersRouter = express.Router() export const usersRouter = express.Router()
usersRouter.use(express.json()) usersRouter.use(express.json())
@ -39,22 +37,12 @@ usersRouter.post('/', async (req: Request, res: Response) => {
throw error.details[0].message throw error.details[0].message
} }
if (typeof newUser.npub === 'string') { const existingUser = await collections.users?.findOne({
const existingUser = await collections.users?.findOne({ npub: newUser.npub
npub: newUser.npub })
})
if (existingUser) { if (existingUser) {
throw new Error('user with provided "npub" exists') throw new Error('user with provided "npub" exists')
}
} else {
for (const npub of newUser.npub) {
const existingUser = await collections.users?.findOne({ npub })
if (existingUser) {
throw new Error('user with provided "npub" exists')
}
}
} }
const result = await collections.users?.insertOne(newUser) const result = await collections.users?.insertOne(newUser)

@ -2,7 +2,6 @@ import express, { Request, Response } from 'express'
import { collections } from '../services/database.service' import { collections } from '../services/database.service'
import { Wine } from '../models' import { Wine } from '../models'
// Global Config
export const winesRouter = express.Router() export const winesRouter = express.Router()
winesRouter.use(express.json()) winesRouter.use(express.json())

@ -2,26 +2,21 @@ import Joi from 'joi'
import { UserRole } from '../../types' import { UserRole } from '../../types'
import { npubToHex, validateHex } from '../nostr' import { npubToHex, validateHex } from '../nostr'
const npubValidation = (value: unknown, helper: Joi.CustomHelpers<unknown>) => {
const hex = npubToHex(value as string)
if (!hex || !validateHex(hex)) {
return helper.message({
custom: Joi.expression('"npub" contains an invalid value')
})
}
return hex
}
export const userValidation = (data: unknown): Joi.ValidationResult => export const userValidation = (data: unknown): Joi.ValidationResult =>
Joi.object({ Joi.object({
name: Joi.string().required(), name: Joi.string().required(),
npub: Joi.alternatives() npub: Joi.string()
.try( .custom((value, helper) => {
Joi.array().items(Joi.string().custom(npubValidation)), const hex = npubToHex(value as string)
Joi.string().custom(npubValidation)
) if (!hex || !validateHex(hex)) {
return helper.message({
custom: Joi.expression('"npub" contains an invalid value')
})
}
return hex
})
.required(), .required(),
role: Joi.string() role: Joi.string()
.valid(...Object.values(UserRole)) .valid(...Object.values(UserRole))