1+ import config from '@app/config/config' ;
2+ import { readToken } from '@app/services/localStorage.service' ;
3+ import {
4+ AllowedUsersSettings ,
5+ AllowedUsersApiResponse ,
6+ AllowedUsersNpubsResponse ,
7+ BulkImportRequest ,
8+ AllowedUsersNpub ,
9+ DEFAULT_TIERS
10+ } from '@app/types/allowedUsers.types' ;
11+
12+ // Settings Management
13+ export const getAllowedUsersSettings = async ( ) : Promise < AllowedUsersSettings > => {
14+ const token = readToken ( ) ;
15+ const response = await fetch ( `${ config . baseURL } /api/settings/allowed_users` , {
16+ headers : {
17+ 'Authorization' : `Bearer ${ token } ` ,
18+ } ,
19+ } ) ;
20+
21+ if ( ! response . ok ) throw new Error ( `HTTP error! status: ${ response . status } ` ) ;
22+
23+ const text = await response . text ( ) ;
24+ try {
25+ const data : AllowedUsersApiResponse = JSON . parse ( text ) ;
26+
27+ // Transform tiers from backend format to frontend format
28+ let transformedTiers = data . allowed_users . tiers . map ( tier => ( {
29+ data_limit : ( tier as any ) . datalimit || tier . data_limit || '' ,
30+ price : tier . price
31+ } ) ) ;
32+
33+ // For free mode, reconstruct full UI options with active tier marked
34+ if ( data . allowed_users . mode === 'free' && transformedTiers . length === 1 ) {
35+ const activeTierDataLimit = transformedTiers [ 0 ] . data_limit ;
36+ transformedTiers = DEFAULT_TIERS . free . map ( defaultTier => ( {
37+ ...defaultTier ,
38+ active : defaultTier . data_limit === activeTierDataLimit
39+ } ) ) ;
40+ }
41+
42+ const transformedSettings = {
43+ ...data . allowed_users ,
44+ tiers : transformedTiers
45+ } ;
46+
47+ return transformedSettings ;
48+ } catch ( jsonError ) {
49+ throw new Error ( `Invalid JSON response: ${ text } ` ) ;
50+ }
51+ } ;
52+
53+ export const updateAllowedUsersSettings = async ( settings : AllowedUsersSettings ) : Promise < { success : boolean , message : string } > => {
54+ const token = readToken ( ) ;
55+
56+ // Filter tiers based on mode - for free mode, only send active tier
57+ const tiersToSend = settings . mode === 'free'
58+ ? settings . tiers . filter ( tier => tier . active )
59+ : settings . tiers ;
60+
61+ // Transform to nested format as expected by backend
62+ const nestedSettings = {
63+ "allowed_users" : {
64+ "mode" : settings . mode ,
65+ "read_access" : {
66+ "enabled" : settings . read_access . enabled ,
67+ "scope" : settings . read_access . scope
68+ } ,
69+ "write_access" : {
70+ "enabled" : settings . write_access . enabled ,
71+ "scope" : settings . write_access . scope
72+ } ,
73+ "tiers" : tiersToSend . map ( tier => ( {
74+ "datalimit" : tier . data_limit || "1 GB per month" , // Backend expects 'datalimit' not 'data_limit', fallback for empty values
75+ "price" : tier . price || "0"
76+ } ) )
77+ }
78+ } ;
79+
80+ console . log ( 'Sending to backend:' , JSON . stringify ( nestedSettings , null , 2 ) ) ;
81+
82+ const response = await fetch ( `${ config . baseURL } /api/settings/allowed_users` , {
83+ method : 'POST' ,
84+ headers : {
85+ 'Content-Type' : 'application/json' ,
86+ 'Authorization' : `Bearer ${ token } ` ,
87+ } ,
88+ body : JSON . stringify ( nestedSettings ) ,
89+ } ) ;
90+
91+ const text = await response . text ( ) ;
92+ console . log ( 'Backend response:' , response . status , text ) ;
93+
94+ if ( ! response . ok ) {
95+ console . error ( 'Backend error:' , response . status , text ) ;
96+ throw new Error ( `HTTP error! status: ${ response . status } , response: ${ text } ` ) ;
97+ }
98+
99+ try {
100+ return JSON . parse ( text ) ;
101+ } catch ( jsonError ) {
102+ throw new Error ( `Invalid JSON response: ${ text } ` ) ;
103+ }
104+ } ;
105+
106+ // Read NPUBs Management
107+ export const getReadNpubs = async ( page = 1 , pageSize = 20 ) : Promise < AllowedUsersNpubsResponse > => {
108+ const token = readToken ( ) ;
109+ const response = await fetch ( `${ config . baseURL } /api/allowed-npubs/read?page=${ page } &pageSize=${ pageSize } ` , {
110+ headers : {
111+ 'Authorization' : `Bearer ${ token } ` ,
112+ } ,
113+ } ) ;
114+
115+ if ( ! response . ok ) throw new Error ( `HTTP error! status: ${ response . status } ` ) ;
116+
117+ const text = await response . text ( ) ;
118+ try {
119+ const data = JSON . parse ( text ) ;
120+ // Transform backend response to expected format
121+ return {
122+ npubs : data . npubs || [ ] ,
123+ total : data . pagination ?. total || 0 ,
124+ page : data . pagination ?. page || page ,
125+ pageSize : data . pagination ?. pageSize || pageSize
126+ } ;
127+ } catch ( jsonError ) {
128+ throw new Error ( `Invalid JSON response: ${ text } ` ) ;
129+ }
130+ } ;
131+
132+ export const addReadNpub = async ( npub : string , tier : string ) : Promise < { success : boolean , message : string } > => {
133+ const token = readToken ( ) ;
134+ const response = await fetch ( `${ config . baseURL } /api/allowed-npubs/read` , {
135+ method : 'POST' ,
136+ headers : {
137+ 'Content-Type' : 'application/json' ,
138+ 'Authorization' : `Bearer ${ token } ` ,
139+ } ,
140+ body : JSON . stringify ( { npub, tier } ) ,
141+ } ) ;
142+
143+ if ( ! response . ok ) throw new Error ( `HTTP error! status: ${ response . status } ` ) ;
144+
145+ const text = await response . text ( ) ;
146+ try {
147+ return JSON . parse ( text ) ;
148+ } catch ( jsonError ) {
149+ throw new Error ( `Invalid JSON response: ${ text } ` ) ;
150+ }
151+ } ;
152+
153+ export const removeReadNpub = async ( npub : string ) : Promise < { success : boolean , message : string } > => {
154+ const token = readToken ( ) ;
155+ const response = await fetch ( `${ config . baseURL } /api/allowed-npubs/read/${ npub } ` , {
156+ method : 'DELETE' ,
157+ headers : {
158+ 'Authorization' : `Bearer ${ token } ` ,
159+ } ,
160+ } ) ;
161+
162+ if ( ! response . ok ) throw new Error ( `HTTP error! status: ${ response . status } ` ) ;
163+
164+ const text = await response . text ( ) ;
165+ try {
166+ return JSON . parse ( text ) ;
167+ } catch ( jsonError ) {
168+ throw new Error ( `Invalid JSON response: ${ text } ` ) ;
169+ }
170+ } ;
171+
172+ // Write NPUBs Management
173+ export const getWriteNpubs = async ( page = 1 , pageSize = 20 ) : Promise < AllowedUsersNpubsResponse > => {
174+ const token = readToken ( ) ;
175+ const response = await fetch ( `${ config . baseURL } /api/allowed-npubs/write?page=${ page } &pageSize=${ pageSize } ` , {
176+ headers : {
177+ 'Authorization' : `Bearer ${ token } ` ,
178+ } ,
179+ } ) ;
180+
181+ if ( ! response . ok ) throw new Error ( `HTTP error! status: ${ response . status } ` ) ;
182+
183+ const text = await response . text ( ) ;
184+ try {
185+ const data = JSON . parse ( text ) ;
186+ // Transform backend response to expected format
187+ return {
188+ npubs : data . npubs || [ ] ,
189+ total : data . pagination ?. total || 0 ,
190+ page : data . pagination ?. page || page ,
191+ pageSize : data . pagination ?. pageSize || pageSize
192+ } ;
193+ } catch ( jsonError ) {
194+ throw new Error ( `Invalid JSON response: ${ text } ` ) ;
195+ }
196+ } ;
197+
198+ export const addWriteNpub = async ( npub : string , tier : string ) : Promise < { success : boolean , message : string } > => {
199+ const token = readToken ( ) ;
200+ const response = await fetch ( `${ config . baseURL } /api/allowed-npubs/write` , {
201+ method : 'POST' ,
202+ headers : {
203+ 'Content-Type' : 'application/json' ,
204+ 'Authorization' : `Bearer ${ token } ` ,
205+ } ,
206+ body : JSON . stringify ( { npub, tier } ) ,
207+ } ) ;
208+
209+ if ( ! response . ok ) throw new Error ( `HTTP error! status: ${ response . status } ` ) ;
210+
211+ const text = await response . text ( ) ;
212+ try {
213+ return JSON . parse ( text ) ;
214+ } catch ( jsonError ) {
215+ throw new Error ( `Invalid JSON response: ${ text } ` ) ;
216+ }
217+ } ;
218+
219+ export const removeWriteNpub = async ( npub : string ) : Promise < { success : boolean , message : string } > => {
220+ const token = readToken ( ) ;
221+ const response = await fetch ( `${ config . baseURL } /api/allowed-npubs/write/${ npub } ` , {
222+ method : 'DELETE' ,
223+ headers : {
224+ 'Authorization' : `Bearer ${ token } ` ,
225+ } ,
226+ } ) ;
227+
228+ if ( ! response . ok ) throw new Error ( `HTTP error! status: ${ response . status } ` ) ;
229+
230+ const text = await response . text ( ) ;
231+ try {
232+ return JSON . parse ( text ) ;
233+ } catch ( jsonError ) {
234+ throw new Error ( `Invalid JSON response: ${ text } ` ) ;
235+ }
236+ } ;
237+
238+ // Bulk Import
239+ export const bulkImportNpubs = async ( importData : BulkImportRequest ) : Promise < { success : boolean , message : string , imported : number , failed : number } > => {
240+ const token = readToken ( ) ;
241+ const response = await fetch ( `${ config . baseURL } /api/allowed-npubs/bulk-import` , {
242+ method : 'POST' ,
243+ headers : {
244+ 'Content-Type' : 'application/json' ,
245+ 'Authorization' : `Bearer ${ token } ` ,
246+ } ,
247+ body : JSON . stringify ( importData ) ,
248+ } ) ;
249+
250+ if ( ! response . ok ) throw new Error ( `HTTP error! status: ${ response . status } ` ) ;
251+
252+ const text = await response . text ( ) ;
253+ try {
254+ return JSON . parse ( text ) ;
255+ } catch ( jsonError ) {
256+ throw new Error ( `Invalid JSON response: ${ text } ` ) ;
257+ }
258+ } ;
0 commit comments