Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions migrations/20260410_230000_add_is_vanished_to_users_table.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
exports.up = async function (knex) {
await knex.schema.alterTable('users', (table) => {
table.boolean('is_vanished').notNullable().defaultTo(false)
})

await knex.raw(`
UPDATE users u
SET is_vanished = true
WHERE EXISTS (
SELECT 1 FROM events e
WHERE e.event_pubkey = u.pubkey
AND e.event_kind = 62
AND e.deleted_at IS NULL
)
`)
}

exports.down = function (knex) {
return knex.schema.alterTable('users', (table) => {
table.dropColumn('is_vanished')
})
}
25 changes: 23 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions src/@types/repositories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ export interface IUserRepository {
findByPubkey(pubkey: Pubkey, client?: DatabaseClient): Promise<User | undefined>
upsert(user: Partial<User>, client?: DatabaseClient): Promise<number>
getBalanceByPubkey(pubkey: Pubkey, client?: DatabaseClient): Promise<bigint>
isVanished(pubkey: Pubkey, client?: DatabaseClient): Promise<boolean>
setVanished(pubkey: Pubkey, vanished: boolean, client?: DatabaseClient): Promise<number>
admitUser(pubkey: Pubkey, admittedAt: Date, client?: DatabaseClient): Promise<void>
}

Expand Down
2 changes: 2 additions & 0 deletions src/@types/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Pubkey } from './base'
export interface User {
pubkey: Pubkey
isAdmitted: boolean
isVanished: boolean
balance: bigint
tosAcceptedAt?: Date | null
createdAt: Date
Expand All @@ -12,6 +13,7 @@ export interface User {
export interface DBUser {
pubkey: Buffer
is_admitted: boolean
is_vanished: boolean
balance: bigint
created_at: Date
updated_at: Date
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import { getMasterDbClient, getReadReplicaDbClient } from '../../database/client'
import { createSettings } from '../settings-factory'
import { getMasterDbClient } from '../../database/client'
import { EventRepository } from '../../repositories/event-repository'
import { GetSubmissionCheckController } from '../../controllers/admission/get-admission-check-controller'
import { slidingWindowRateLimiterFactory } from '../rate-limiter-factory'
import { UserRepository } from '../../repositories/user-repository'

export const createGetAdmissionCheckController = () => {
const dbClient = getMasterDbClient()
const userRepository = new UserRepository(dbClient)
const readReplicaDbClient = getReadReplicaDbClient()
const eventRepository = new EventRepository(dbClient, readReplicaDbClient)
const userRepository = new UserRepository(dbClient, eventRepository)

return new GetSubmissionCheckController(
userRepository,
Expand Down
7 changes: 5 additions & 2 deletions src/factories/controllers/post-invoice-controller-factory.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
import { getMasterDbClient, getReadReplicaDbClient } from '../../database/client'
import { createPaymentsService } from '../payments-service-factory'
import { createSettings } from '../settings-factory'
import { getMasterDbClient } from '../../database/client'
import { EventRepository } from '../../repositories/event-repository'
import { IController } from '../../@types/controllers'
import { PostInvoiceController } from '../../controllers/invoices/post-invoice-controller'
import { slidingWindowRateLimiterFactory } from '../rate-limiter-factory'
import { UserRepository } from '../../repositories/user-repository'

export const createPostInvoiceController = (): IController => {
const dbClient = getMasterDbClient()
const userRepository = new UserRepository(dbClient)
const readReplicaDbClient = getReadReplicaDbClient()
const eventRepository = new EventRepository(dbClient, readReplicaDbClient)
const userRepository = new UserRepository(dbClient, eventRepository)
const paymentsService = createPaymentsService()

return new PostInvoiceController(
Expand Down
5 changes: 3 additions & 2 deletions src/factories/event-strategy-factory.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { IEventRepository, IUserRepository } from '../@types/repositories'
import { isDeleteEvent, isEphemeralEvent, isGiftWrapEvent, isParameterizedReplaceableEvent, isReplaceableEvent, isRequestToVanishEvent } from '../utils/event'
import { DefaultEventStrategy } from '../handlers/event-strategies/default-event-strategy'
import { DeleteEventStrategy } from '../handlers/event-strategies/delete-event-strategy'
import { EphemeralEventStrategy } from '../handlers/event-strategies/ephemeral-event-strategy'
import { Event } from '../@types/event'
import { Factory } from '../@types/base'
import { GiftWrapEventStrategy } from '../handlers/event-strategies/gift-wrap-event-strategy'
import { IEventRepository } from '../@types/repositories'
import { IEventStrategy } from '../@types/message-handlers'
import { IWebSocketAdapter } from '../@types/adapters'
import { ParameterizedReplaceableEventStrategy } from '../handlers/event-strategies/parameterized-replaceable-event-strategy'
Expand All @@ -14,10 +14,11 @@ import { VanishEventStrategy } from '../handlers/event-strategies/vanish-event-s

export const eventStrategyFactory = (
eventRepository: IEventRepository,
userRepository: IUserRepository,
): Factory<IEventStrategy<Event, Promise<void>>, [Event, IWebSocketAdapter]> =>
([event, adapter]: [Event, IWebSocketAdapter]) => {
if (isRequestToVanishEvent(event)) {
return new VanishEventStrategy(adapter, eventRepository)
return new VanishEventStrategy(adapter, eventRepository, userRepository)
} else if (isGiftWrapEvent(event)) {
return new GiftWrapEventStrategy(adapter, eventRepository)
} else if (isReplaceableEvent(event)) {
Expand Down
2 changes: 1 addition & 1 deletion src/factories/message-handler-factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export const messageHandlerFactory = (
{
return new EventMessageHandler(
adapter,
eventStrategyFactory(eventRepository),
eventStrategyFactory(eventRepository, userRepository),
eventRepository,
userRepository,
createSettings,
Expand Down
4 changes: 2 additions & 2 deletions src/factories/payments-service-factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ export const createPaymentsService = () => {
const dbClient = getMasterDbClient()
const rrDbClient = getReadReplicaDbClient()
const invoiceRepository = new InvoiceRepository(dbClient)
const userRepository = new UserRepository(dbClient)
const paymentsProcessor = createPaymentsProcessor()
const eventRepository = new EventRepository(dbClient, rrDbClient)
const userRepository = new UserRepository(dbClient, eventRepository)
const paymentsProcessor = createPaymentsProcessor()

return new PaymentsService(
dbClient,
Expand Down
2 changes: 1 addition & 1 deletion src/factories/static-mirroring.worker-factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export const staticMirroringWorkerFactory = () => {
const dbClient = getMasterDbClient()
const readReplicaDbClient = getReadReplicaDbClient()
const eventRepository = new EventRepository(dbClient, readReplicaDbClient)
const userRepository = new UserRepository(dbClient)
const userRepository = new UserRepository(dbClient, eventRepository)

return new StaticMirroringWorker(
eventRepository,
Expand Down
2 changes: 1 addition & 1 deletion src/factories/worker-factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export const workerFactory = (): AppWorker => {
const dbClient = getMasterDbClient()
const readReplicaDbClient = getReadReplicaDbClient()
const eventRepository = new EventRepository(dbClient, readReplicaDbClient)
const userRepository = new UserRepository(dbClient)
const userRepository = new UserRepository(dbClient, eventRepository)
const nip05VerificationRepository = new Nip05VerificationRepository(dbClient)

const settings = createSettings()
Expand Down
4 changes: 2 additions & 2 deletions src/handlers/event-message-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -252,8 +252,8 @@ export class EventMessageHandler implements IMessageHandler {
return
}

const existingVanishRequest = await this.eventRepository.hasActiveRequestToVanish(event.pubkey)
if (existingVanishRequest) {
const isVanished = await this.userRepository.isVanished(event.pubkey)
if (isVanished) {
return 'blocked: request to vanish active for pubkey'
}
}
Expand Down
5 changes: 4 additions & 1 deletion src/handlers/event-strategies/vanish-event-strategy.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { IEventRepository, IUserRepository } from '../../@types/repositories'
import { createCommandResult } from '../../utils/messages'
import { createLogger } from '../../factories/logger-factory'
import { Event } from '../../@types/event'
import { EventKinds } from '../../constants/base'
import { IEventRepository } from '../../@types/repositories'
import { IEventStrategy } from '../../@types/message-handlers'
import { IWebSocketAdapter } from '../../@types/adapters'
import { WebSocketAdapterEvent } from '../../constants/adapter'
Expand All @@ -13,6 +13,7 @@ export class VanishEventStrategy implements IEventStrategy<Event, Promise<void>>
public constructor(
private readonly webSocket: IWebSocketAdapter,
private readonly eventRepository: IEventRepository,
private readonly userRepository: IUserRepository,
) {}

public async execute(event: Event): Promise<void> {
Expand All @@ -25,6 +26,8 @@ export class VanishEventStrategy implements IEventStrategy<Event, Promise<void>>

const count = await this.eventRepository.create(event)

await this.userRepository.setVanished(event.pubkey, true)

this.webSocket.emit(
WebSocketAdapterEvent.Message,
createCommandResult(event.id, true, count ? '' : 'duplicate:')
Expand Down
Loading
Loading