Skip to content

Commit ae1292e

Browse files
committed
Update allowed users API and add personal mode
- Fix TypeScript error in allowedUsers.api.ts with proper type casting - Update API endpoints to use unified /api/settings endpoint - Update response parsing for new nested settings.allowed_users structure - Update request format to send data in settings.allowed_users structure - Add new 'personal' mode for single-user private relays - Update mode labels for better clarity: * free -> 'Free - Public Relay' * paid -> 'Paid - Subscription Tiers' * exclusive -> 'Free - Invite Only' * personal -> 'Free - Only Me' (NEW) - Add personal mode configuration with unlimited access and NPUB management - Update API logic to handle personal mode like free mode for tier filtering
1 parent 45e6adf commit ae1292e

3 files changed

Lines changed: 76 additions & 32 deletions

File tree

src/api/allowedUsers.api.ts

Lines changed: 54 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,14 @@ import {
66
AllowedUsersNpubsResponse,
77
BulkImportRequest,
88
AllowedUsersNpub,
9+
AllowedUsersMode,
910
DEFAULT_TIERS
1011
} from '@app/types/allowedUsers.types';
1112

1213
// Settings Management
1314
export const getAllowedUsersSettings = async (): Promise<AllowedUsersSettings> => {
1415
const token = readToken();
15-
const response = await fetch(`${config.baseURL}/api/settings/allowed_users`, {
16+
const response = await fetch(`${config.baseURL}/api/settings`, {
1617
headers: {
1718
'Authorization': `Bearer ${token}`,
1819
},
@@ -22,25 +23,47 @@ export const getAllowedUsersSettings = async (): Promise<AllowedUsersSettings> =
2223

2324
const text = await response.text();
2425
try {
25-
const data: AllowedUsersApiResponse = JSON.parse(text);
26+
const data = JSON.parse(text);
27+
28+
// Extract allowed_users from the new nested structure
29+
const allowedUsersData = data.settings?.allowed_users;
30+
if (!allowedUsersData) {
31+
throw new Error('No allowed_users data found in response');
32+
}
2633

2734
// 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-
}));
35+
let transformedTiers = [];
36+
37+
// Check if tiers exist in response, otherwise use defaults
38+
if (allowedUsersData.tiers && Array.isArray(allowedUsersData.tiers)) {
39+
transformedTiers = allowedUsersData.tiers.map((tier: any) => ({
40+
data_limit: tier.datalimit || tier.data_limit || '',
41+
price: tier.price || '0'
42+
}));
43+
} else {
44+
// Use default tiers for the mode if none provided
45+
const mode = allowedUsersData.mode as AllowedUsersMode;
46+
transformedTiers = DEFAULT_TIERS[mode] || DEFAULT_TIERS.free;
47+
}
3248

3349
// For free mode, reconstruct full UI options with active tier marked
34-
if (data.allowed_users.mode === 'free' && transformedTiers.length === 1) {
50+
if (allowedUsersData.mode === 'free' && transformedTiers.length === 1) {
3551
const activeTierDataLimit = transformedTiers[0].data_limit;
3652
transformedTiers = DEFAULT_TIERS.free.map(defaultTier => ({
3753
...defaultTier,
3854
active: defaultTier.data_limit === activeTierDataLimit
3955
}));
4056
}
4157

58+
// For personal mode, reconstruct with single unlimited tier
59+
if (allowedUsersData.mode === 'personal' && transformedTiers.length === 1) {
60+
transformedTiers = DEFAULT_TIERS.personal;
61+
}
62+
4263
const transformedSettings = {
43-
...data.allowed_users,
64+
mode: allowedUsersData.mode || 'free',
65+
read_access: allowedUsersData.read_access || { enabled: true, scope: 'all_users' },
66+
write_access: allowedUsersData.write_access || { enabled: true, scope: 'all_users' },
4467
tiers: transformedTiers
4568
};
4669

@@ -53,33 +76,35 @@ export const getAllowedUsersSettings = async (): Promise<AllowedUsersSettings> =
5376
export const updateAllowedUsersSettings = async (settings: AllowedUsersSettings): Promise<{ success: boolean, message: string }> => {
5477
const token = readToken();
5578

56-
// Filter tiers based on mode - for free mode, only send active tier
57-
const tiersToSend = settings.mode === 'free'
79+
// Filter tiers based on mode - for free and personal modes, only send active tier
80+
const tiersToSend = (settings.mode === 'free' || settings.mode === 'personal')
5881
? settings.tiers.filter(tier => tier.active)
5982
: settings.tiers;
6083

61-
// Transform to nested format as expected by backend
84+
// Transform to nested format as expected by new unified backend API
6285
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-
}))
86+
"settings": {
87+
"allowed_users": {
88+
"mode": settings.mode,
89+
"read_access": {
90+
"enabled": settings.read_access.enabled,
91+
"scope": settings.read_access.scope
92+
},
93+
"write_access": {
94+
"enabled": settings.write_access.enabled,
95+
"scope": settings.write_access.scope
96+
},
97+
"tiers": tiersToSend.map(tier => ({
98+
"datalimit": tier.data_limit || "1 GB per month", // Backend expects 'datalimit' not 'data_limit', fallback for empty values
99+
"price": tier.price || "0"
100+
}))
101+
}
77102
}
78103
};
79104

80105
console.log('Sending to backend:', JSON.stringify(nestedSettings, null, 2));
81106

82-
const response = await fetch(`${config.baseURL}/api/settings/allowed_users`, {
107+
const response = await fetch(`${config.baseURL}/api/settings`, {
83108
method: 'POST',
84109
headers: {
85110
'Content-Type': 'application/json',
@@ -97,9 +122,10 @@ export const updateAllowedUsersSettings = async (settings: AllowedUsersSettings)
97122
}
98123

99124
try {
100-
return JSON.parse(text);
125+
return JSON.parse(text) || { success: true, message: 'Settings updated successfully' };
101126
} catch (jsonError) {
102-
throw new Error(`Invalid JSON response: ${text}`);
127+
// If response is not JSON, assume success if status was OK
128+
return { success: true, message: 'Settings updated successfully' };
103129
}
104130
};
105131

src/components/allowed-users/components/ModeSelector/ModeSelector.tsx

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,24 @@ interface ModeSelectorProps {
1111

1212
const MODE_INFO = {
1313
free: {
14-
label: 'Free Mode',
14+
label: 'Free - Public Relay',
1515
description: 'Open access with optional free tiers',
1616
color: '#1890ff'
1717
},
1818
paid: {
19-
label: 'Paid Mode',
19+
label: 'Paid - Subscription Tiers',
2020
description: 'Subscription-based access control',
2121
color: '#52c41a'
2222
},
2323
exclusive: {
24-
label: 'Exclusive Mode',
24+
label: 'Free - Invite Only',
2525
description: 'Invite-only access with manual NPUB management',
2626
color: '#722ed1'
27+
},
28+
personal: {
29+
label: 'Free - Only Me',
30+
description: 'Personal relay for single user with unlimited access',
31+
color: '#fa541c'
2732
}
2833
};
2934

src/types/allowedUsers.types.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
export type AllowedUsersMode = 'free' | 'paid' | 'exclusive';
1+
export type AllowedUsersMode = 'free' | 'paid' | 'exclusive' | 'personal';
22

33
export type AccessScope = 'all_users' | 'paid_users' | 'allowed_users';
44

@@ -91,6 +91,16 @@ export const MODE_CONFIGURATIONS: Record<AllowedUsersMode, ModeOptions> = {
9191
],
9292
allowsFreeTiers: true,
9393
requiresNpubManagement: true
94+
},
95+
personal: {
96+
readOptions: [
97+
{ value: 'allowed_users', label: 'Only Me' }
98+
],
99+
writeOptions: [
100+
{ value: 'allowed_users', label: 'Only Me' }
101+
],
102+
allowsFreeTiers: true,
103+
requiresNpubManagement: true
94104
}
95105
};
96106

@@ -110,5 +120,8 @@ export const DEFAULT_TIERS: Record<AllowedUsersMode, AllowedUsersTier[]> = {
110120
{ data_limit: '5 GB per month', price: '0' },
111121
{ data_limit: '50 GB per month', price: '0' },
112122
{ data_limit: 'unlimited', price: '0' }
123+
],
124+
personal: [
125+
{ data_limit: 'unlimited', price: '0', active: true } // Personal use, unlimited and free
113126
]
114127
};

0 commit comments

Comments
 (0)