feat(extensions): add NIP-05 identity extension #4

Open
padreug wants to merge 5 commits from feature/nip05 into dev
2 changed files with 20 additions and 7 deletions
Showing only changes of commit f59073e589 - Show all commits

View file

@ -27,7 +27,9 @@ const DEFAULT_CONFIG: Required<Nip05Config> = {
min_username_length: 1, min_username_length: 1,
reserved_usernames: ['admin', 'root', 'system', 'support', 'help', 'info', 'contact', 'abuse', 'postmaster', 'webmaster', 'hostmaster', 'noreply', 'no-reply', 'null', 'undefined', 'api', 'www', 'mail', 'ftp', 'ssh', 'test', 'demo'], reserved_usernames: ['admin', 'root', 'system', 'support', 'help', 'info', 'contact', 'abuse', 'postmaster', 'webmaster', 'hostmaster', 'noreply', 'no-reply', 'null', 'undefined', 'api', 'www', 'mail', 'ftp', 'ssh', 'test', 'demo'],
include_relays: true, include_relays: true,
default_relays: [] default_relays: [],
max_relays_per_user: 10,
max_identities_listing: 100
} }
/** /**
@ -99,11 +101,15 @@ function validateUsername(username: string, config: Required<Nip05Config>): User
/** /**
* Validate relay URLs * Validate relay URLs
*/ */
function validateRelays(relays: string[]): UsernameValidation { function validateRelays(relays: string[], maxRelays?: number): UsernameValidation {
if (!Array.isArray(relays)) { if (!Array.isArray(relays)) {
return { valid: false, error: 'Relays must be an array' } return { valid: false, error: 'Relays must be an array' }
} }
if (maxRelays && relays.length > maxRelays) {
return { valid: false, error: `Too many relays (max ${maxRelays})` }
}
for (const relay of relays) { for (const relay of relays) {
if (typeof relay !== 'string') { if (typeof relay !== 'string') {
return { valid: false, error: 'Each relay must be a string' } return { valid: false, error: 'Each relay must be a string' }
@ -166,7 +172,7 @@ export class Nip05Manager {
// Validate relays if provided // Validate relays if provided
const relays = request.relays || this.config.default_relays const relays = request.relays || this.config.default_relays
if (relays.length > 0) { if (relays.length > 0) {
const relayValidation = validateRelays(relays) const relayValidation = validateRelays(relays, this.config.max_relays_per_user)
if (!relayValidation.valid) { if (!relayValidation.valid) {
throw new Error(relayValidation.error) throw new Error(relayValidation.error)
} }
@ -241,7 +247,7 @@ export class Nip05Manager {
request: UpdateRelaysRequest request: UpdateRelaysRequest
): Promise<Nip05Identity> { ): Promise<Nip05Identity> {
// Validate relays // Validate relays
const validation = validateRelays(request.relays) const validation = validateRelays(request.relays, this.config.max_relays_per_user)
if (!validation.valid) { if (!validation.valid) {
throw new Error(validation.error) throw new Error(validation.error)
} }
@ -361,10 +367,11 @@ export class Nip05Manager {
} }
} }
} else { } else {
// Return all active identities (with reasonable limit) // Return all active identities (with configurable limit)
const limit = this.config.max_identities_listing
const rows = await this.db.query<Nip05IdentityRow>( const rows = await this.db.query<Nip05IdentityRow>(
`SELECT * FROM identities WHERE application_id = ? AND is_active = 1 LIMIT 1000`, `SELECT * FROM identities WHERE application_id = ? AND is_active = 1 LIMIT ?`,
[applicationId] [applicationId, limit]
) )
for (const row of rows) { for (const row of rows) {

View file

@ -119,6 +119,12 @@ export interface Nip05Config {
/** Default relays to suggest for new users */ /** Default relays to suggest for new users */
default_relays?: string[] default_relays?: string[]
/** Maximum number of relays per user (default: 10) */
max_relays_per_user?: number
/** Maximum number of identities returned when no name query param is provided (default: 100) */
max_identities_listing?: number
} }
/** /**