- Update getCurrentUser method to fetch Nostr keys alongside basic user info, improving user data retrieval. - Implement error handling to ensure basic user info is returned if Nostr key fetching fails, enhancing robustness of the authentication process.
187 lines
No EOL
4.3 KiB
TypeScript
187 lines
No EOL
4.3 KiB
TypeScript
interface LoginCredentials {
|
|
username: string
|
|
password: string
|
|
}
|
|
|
|
interface RegisterData {
|
|
username: string
|
|
email?: string
|
|
password: string
|
|
password_repeat: string
|
|
}
|
|
|
|
interface AuthResponse {
|
|
access_token: string
|
|
user_id: string
|
|
username?: string
|
|
email?: string
|
|
}
|
|
|
|
interface Wallet {
|
|
id: string
|
|
user: string
|
|
name: string
|
|
adminkey: string
|
|
inkey: string
|
|
deleted: boolean
|
|
created_at: string
|
|
updated_at: string
|
|
currency?: string
|
|
balance_msat: number
|
|
extra?: {
|
|
icon: string
|
|
color: string
|
|
pinned: boolean
|
|
}
|
|
}
|
|
|
|
interface User {
|
|
id: string
|
|
username?: string
|
|
email?: string
|
|
pubkey?: string
|
|
prvkey?: string // Nostr private key for user
|
|
external_id?: string
|
|
extensions: string[]
|
|
wallets: Wallet[]
|
|
admin: boolean
|
|
super_user: boolean
|
|
fiat_providers: string[]
|
|
has_password: boolean
|
|
created_at: string
|
|
updated_at: string
|
|
extra?: {
|
|
email_verified?: boolean
|
|
first_name?: string
|
|
last_name?: string
|
|
display_name?: string
|
|
picture?: string
|
|
provider?: string
|
|
visible_wallet_count?: number
|
|
}
|
|
}
|
|
|
|
import { getApiUrl, getAuthToken, setAuthToken, removeAuthToken } from '@/lib/config/lnbits'
|
|
|
|
class LnbitsAPI {
|
|
private accessToken: string | null = null
|
|
|
|
constructor() {
|
|
// Try to load token from localStorage
|
|
this.accessToken = getAuthToken()
|
|
}
|
|
|
|
private async request<T>(
|
|
endpoint: string,
|
|
options: RequestInit = {}
|
|
): Promise<T> {
|
|
const url = getApiUrl(endpoint)
|
|
console.log('🔧 LNBits API request:', { endpoint, fullUrl: url })
|
|
|
|
const headers: HeadersInit = {
|
|
'Content-Type': 'application/json',
|
|
...options.headers,
|
|
}
|
|
|
|
if (this.accessToken) {
|
|
(headers as Record<string, string>)['Authorization'] = `Bearer ${this.accessToken}`
|
|
}
|
|
|
|
const response = await fetch(url, {
|
|
...options,
|
|
headers,
|
|
})
|
|
|
|
if (!response.ok) {
|
|
const errorText = await response.text()
|
|
console.error('LNBits API Error:', {
|
|
status: response.status,
|
|
statusText: response.statusText,
|
|
errorText
|
|
})
|
|
throw new Error(`API request failed: ${response.status} ${response.statusText}`)
|
|
}
|
|
|
|
const data = await response.json()
|
|
return data
|
|
}
|
|
|
|
async login(credentials: LoginCredentials): Promise<AuthResponse> {
|
|
const response = await this.request<AuthResponse>('/auth', {
|
|
method: 'POST',
|
|
body: JSON.stringify(credentials),
|
|
})
|
|
|
|
this.accessToken = response.access_token
|
|
setAuthToken(response.access_token)
|
|
|
|
return response
|
|
}
|
|
|
|
async register(data: RegisterData): Promise<AuthResponse> {
|
|
const response = await this.request<AuthResponse>('/auth/register', {
|
|
method: 'POST',
|
|
body: JSON.stringify(data),
|
|
})
|
|
|
|
this.accessToken = response.access_token
|
|
setAuthToken(response.access_token)
|
|
|
|
return response
|
|
}
|
|
|
|
async logout(): Promise<void> {
|
|
// Just clear local state - no API call needed for logout
|
|
this.accessToken = null
|
|
removeAuthToken()
|
|
}
|
|
|
|
async getCurrentUser(): Promise<User> {
|
|
// First get basic user info from /auth
|
|
const basicUser = await this.request<User>('/auth')
|
|
|
|
// Then get Nostr keys from /auth/nostr/me (this was working in main branch)
|
|
try {
|
|
const nostrUser = await this.request<User>('/auth/nostr/me')
|
|
|
|
// Merge the data - basic user info + Nostr keys
|
|
return {
|
|
...basicUser,
|
|
pubkey: nostrUser.pubkey,
|
|
prvkey: nostrUser.prvkey
|
|
}
|
|
} catch (error) {
|
|
console.warn('Failed to fetch Nostr keys, returning basic user info:', error)
|
|
// Return basic user info without Nostr keys if the endpoint fails
|
|
return basicUser
|
|
}
|
|
}
|
|
|
|
async updatePassword(currentPassword: string, newPassword: string): Promise<User> {
|
|
return this.request<User>('/auth/password', {
|
|
method: 'PUT',
|
|
body: JSON.stringify({
|
|
current_password: currentPassword,
|
|
new_password: newPassword,
|
|
}),
|
|
})
|
|
}
|
|
|
|
async updateProfile(data: Partial<User>): Promise<User> {
|
|
return this.request<User>('/auth/update', {
|
|
method: 'PUT',
|
|
body: JSON.stringify(data),
|
|
})
|
|
}
|
|
|
|
isAuthenticated(): boolean {
|
|
return !!this.accessToken
|
|
}
|
|
|
|
getAccessToken(): string | null {
|
|
return this.accessToken
|
|
}
|
|
}
|
|
|
|
export const lnbitsAPI = new LnbitsAPI()
|
|
export type { LoginCredentials, RegisterData, AuthResponse, User }
|