@oxyhq/core 1.5.0 → 1.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/AuthManager.js +14 -1
- package/dist/cjs/HttpService.js +87 -69
- package/dist/cjs/OxyServices.base.js +5 -4
- package/dist/cjs/crypto/keyManager.js +1 -13
- package/dist/cjs/crypto/signatureService.js +7 -20
- package/dist/cjs/index.js +9 -1
- package/dist/cjs/mixins/OxyServices.analytics.js +2 -2
- package/dist/cjs/mixins/OxyServices.assets.js +14 -14
- package/dist/cjs/mixins/OxyServices.auth.js +19 -19
- package/dist/cjs/mixins/OxyServices.developer.js +6 -6
- package/dist/cjs/mixins/OxyServices.devices.js +7 -7
- package/dist/cjs/mixins/OxyServices.features.js +23 -23
- package/dist/cjs/mixins/OxyServices.fedcm.js +1 -1
- package/dist/cjs/mixins/OxyServices.karma.js +6 -6
- package/dist/cjs/mixins/OxyServices.location.js +2 -2
- package/dist/cjs/mixins/OxyServices.payment.js +6 -6
- package/dist/cjs/mixins/OxyServices.popup.js +1 -1
- package/dist/cjs/mixins/OxyServices.privacy.js +6 -6
- package/dist/cjs/mixins/OxyServices.security.js +3 -3
- package/dist/cjs/mixins/OxyServices.user.js +22 -22
- package/dist/cjs/mixins/OxyServices.utility.js +39 -10
- package/dist/cjs/utils/authHelpers.js +114 -0
- package/dist/cjs/utils/platform.js +14 -0
- package/dist/esm/AuthManager.js +14 -1
- package/dist/esm/HttpService.js +87 -69
- package/dist/esm/OxyServices.base.js +5 -4
- package/dist/esm/crypto/keyManager.js +1 -13
- package/dist/esm/crypto/signatureService.js +2 -15
- package/dist/esm/index.js +2 -0
- package/dist/esm/mixins/OxyServices.analytics.js +2 -2
- package/dist/esm/mixins/OxyServices.assets.js +14 -14
- package/dist/esm/mixins/OxyServices.auth.js +19 -19
- package/dist/esm/mixins/OxyServices.developer.js +6 -6
- package/dist/esm/mixins/OxyServices.devices.js +7 -7
- package/dist/esm/mixins/OxyServices.features.js +23 -23
- package/dist/esm/mixins/OxyServices.fedcm.js +1 -1
- package/dist/esm/mixins/OxyServices.karma.js +6 -6
- package/dist/esm/mixins/OxyServices.location.js +2 -2
- package/dist/esm/mixins/OxyServices.payment.js +6 -6
- package/dist/esm/mixins/OxyServices.popup.js +1 -1
- package/dist/esm/mixins/OxyServices.privacy.js +6 -6
- package/dist/esm/mixins/OxyServices.security.js +3 -3
- package/dist/esm/mixins/OxyServices.user.js +22 -22
- package/dist/esm/mixins/OxyServices.utility.js +39 -10
- package/dist/esm/utils/authHelpers.js +105 -0
- package/dist/esm/utils/platform.js +12 -0
- package/dist/types/HttpService.d.ts +4 -1
- package/dist/types/OxyServices.base.d.ts +1 -1
- package/dist/types/index.d.ts +2 -0
- package/dist/types/mixins/OxyServices.analytics.d.ts +1 -1
- package/dist/types/mixins/OxyServices.assets.d.ts +1 -1
- package/dist/types/mixins/OxyServices.auth.d.ts +1 -1
- package/dist/types/mixins/OxyServices.developer.d.ts +1 -1
- package/dist/types/mixins/OxyServices.devices.d.ts +1 -1
- package/dist/types/mixins/OxyServices.features.d.ts +1 -1
- package/dist/types/mixins/OxyServices.fedcm.d.ts +1 -1
- package/dist/types/mixins/OxyServices.karma.d.ts +1 -1
- package/dist/types/mixins/OxyServices.language.d.ts +1 -1
- package/dist/types/mixins/OxyServices.location.d.ts +1 -1
- package/dist/types/mixins/OxyServices.payment.d.ts +1 -1
- package/dist/types/mixins/OxyServices.popup.d.ts +1 -1
- package/dist/types/mixins/OxyServices.privacy.d.ts +1 -1
- package/dist/types/mixins/OxyServices.redirect.d.ts +1 -1
- package/dist/types/mixins/OxyServices.security.d.ts +1 -1
- package/dist/types/mixins/OxyServices.user.d.ts +1 -1
- package/dist/types/mixins/OxyServices.utility.d.ts +20 -6
- package/dist/types/utils/authHelpers.d.ts +57 -0
- package/dist/types/utils/platform.d.ts +8 -0
- package/package.json +1 -1
- package/src/AuthManager.ts +14 -1
- package/src/HttpService.ts +85 -67
- package/src/OxyServices.base.ts +5 -4
- package/src/crypto/keyManager.ts +1 -15
- package/src/crypto/signatureService.ts +2 -17
- package/src/index.ts +11 -0
- package/src/mixins/OxyServices.analytics.ts +2 -2
- package/src/mixins/OxyServices.assets.ts +14 -14
- package/src/mixins/OxyServices.auth.ts +19 -19
- package/src/mixins/OxyServices.developer.ts +6 -6
- package/src/mixins/OxyServices.devices.ts +7 -7
- package/src/mixins/OxyServices.features.ts +23 -23
- package/src/mixins/OxyServices.fedcm.ts +1 -1
- package/src/mixins/OxyServices.karma.ts +6 -6
- package/src/mixins/OxyServices.location.ts +2 -2
- package/src/mixins/OxyServices.payment.ts +6 -6
- package/src/mixins/OxyServices.popup.ts +1 -1
- package/src/mixins/OxyServices.privacy.ts +6 -6
- package/src/mixins/OxyServices.security.ts +3 -3
- package/src/mixins/OxyServices.user.ts +22 -22
- package/src/mixins/OxyServices.utility.ts +41 -11
- package/src/utils/authHelpers.ts +140 -0
- package/src/utils/platform.ts +14 -0
|
@@ -16,7 +16,7 @@ export function OxyServicesKarmaMixin<T extends typeof OxyServicesBase>(Base: T)
|
|
|
16
16
|
*/
|
|
17
17
|
async getUserKarma(userId: string): Promise<any> {
|
|
18
18
|
try {
|
|
19
|
-
return await this.makeRequest('GET', `/
|
|
19
|
+
return await this.makeRequest('GET', `/karma/${userId}`, undefined, {
|
|
20
20
|
cache: true,
|
|
21
21
|
cacheTTL: 2 * 60 * 1000, // 2 minutes cache
|
|
22
22
|
});
|
|
@@ -30,7 +30,7 @@ export function OxyServicesKarmaMixin<T extends typeof OxyServicesBase>(Base: T)
|
|
|
30
30
|
*/
|
|
31
31
|
async giveKarma(userId: string, amount: number, reason?: string): Promise<any> {
|
|
32
32
|
try {
|
|
33
|
-
return await this.makeRequest('POST', `/
|
|
33
|
+
return await this.makeRequest('POST', `/karma/${userId}/give`, {
|
|
34
34
|
amount,
|
|
35
35
|
reason
|
|
36
36
|
}, { cache: false });
|
|
@@ -46,7 +46,7 @@ export function OxyServicesKarmaMixin<T extends typeof OxyServicesBase>(Base: T)
|
|
|
46
46
|
*/
|
|
47
47
|
async getUserKarmaTotal(userId: string): Promise<any> {
|
|
48
48
|
try {
|
|
49
|
-
return await this.makeRequest('GET', `/
|
|
49
|
+
return await this.makeRequest('GET', `/karma/${userId}/total`, undefined, {
|
|
50
50
|
cache: true,
|
|
51
51
|
cacheTTL: CACHE_TIMES.MEDIUM,
|
|
52
52
|
});
|
|
@@ -68,7 +68,7 @@ export function OxyServicesKarmaMixin<T extends typeof OxyServicesBase>(Base: T)
|
|
|
68
68
|
if (limit) params.limit = limit;
|
|
69
69
|
if (offset) params.offset = offset;
|
|
70
70
|
|
|
71
|
-
return await this.makeRequest('GET', `/
|
|
71
|
+
return await this.makeRequest('GET', `/karma/${userId}/history`, params, {
|
|
72
72
|
cache: true,
|
|
73
73
|
cacheTTL: CACHE_TIMES.MEDIUM,
|
|
74
74
|
});
|
|
@@ -83,7 +83,7 @@ export function OxyServicesKarmaMixin<T extends typeof OxyServicesBase>(Base: T)
|
|
|
83
83
|
*/
|
|
84
84
|
async getKarmaLeaderboard(): Promise<any> {
|
|
85
85
|
try {
|
|
86
|
-
return await this.makeRequest('GET', '/
|
|
86
|
+
return await this.makeRequest('GET', '/karma/leaderboard', undefined, {
|
|
87
87
|
cache: true,
|
|
88
88
|
cacheTTL: CACHE_TIMES.LONG,
|
|
89
89
|
});
|
|
@@ -98,7 +98,7 @@ export function OxyServicesKarmaMixin<T extends typeof OxyServicesBase>(Base: T)
|
|
|
98
98
|
*/
|
|
99
99
|
async getKarmaRules(): Promise<any> {
|
|
100
100
|
try {
|
|
101
|
-
return await this.makeRequest('GET', '/
|
|
101
|
+
return await this.makeRequest('GET', '/karma/rules', undefined, {
|
|
102
102
|
cache: true,
|
|
103
103
|
cacheTTL: CACHE_TIMES.EXTRA_LONG, // Rules don't change often
|
|
104
104
|
});
|
|
@@ -17,7 +17,7 @@ export function OxyServicesLocationMixin<T extends typeof OxyServicesBase>(Base:
|
|
|
17
17
|
*/
|
|
18
18
|
async updateLocation(latitude: number, longitude: number): Promise<any> {
|
|
19
19
|
try {
|
|
20
|
-
return await this.makeRequest('POST', '/
|
|
20
|
+
return await this.makeRequest('POST', '/location', {
|
|
21
21
|
latitude,
|
|
22
22
|
longitude
|
|
23
23
|
}, { cache: false });
|
|
@@ -34,7 +34,7 @@ export function OxyServicesLocationMixin<T extends typeof OxyServicesBase>(Base:
|
|
|
34
34
|
async getNearbyUsers(radius?: number): Promise<any[]> {
|
|
35
35
|
try {
|
|
36
36
|
const params: any = radius ? { radius } : undefined;
|
|
37
|
-
return await this.makeRequest('GET', '/
|
|
37
|
+
return await this.makeRequest('GET', '/location/nearby', params, {
|
|
38
38
|
cache: false, // Don't cache location data - always get fresh data
|
|
39
39
|
});
|
|
40
40
|
} catch (error) {
|
|
@@ -19,7 +19,7 @@ export function OxyServicesPaymentMixin<T extends typeof OxyServicesBase>(Base:
|
|
|
19
19
|
*/
|
|
20
20
|
async createPayment(data: any): Promise<any> {
|
|
21
21
|
try {
|
|
22
|
-
return await this.makeRequest('POST', '/
|
|
22
|
+
return await this.makeRequest('POST', '/payments', data, { cache: false });
|
|
23
23
|
} catch (error) {
|
|
24
24
|
throw this.handleError(error);
|
|
25
25
|
}
|
|
@@ -32,7 +32,7 @@ export function OxyServicesPaymentMixin<T extends typeof OxyServicesBase>(Base:
|
|
|
32
32
|
*/
|
|
33
33
|
async getPayment(paymentId: string): Promise<any> {
|
|
34
34
|
try {
|
|
35
|
-
return await this.makeRequest('GET', `/
|
|
35
|
+
return await this.makeRequest('GET', `/payments/${paymentId}`, undefined, {
|
|
36
36
|
cache: true,
|
|
37
37
|
cacheTTL: CACHE_TIMES.LONG,
|
|
38
38
|
});
|
|
@@ -47,7 +47,7 @@ export function OxyServicesPaymentMixin<T extends typeof OxyServicesBase>(Base:
|
|
|
47
47
|
*/
|
|
48
48
|
async getUserPayments(): Promise<any[]> {
|
|
49
49
|
try {
|
|
50
|
-
return await this.makeRequest('GET', '/
|
|
50
|
+
return await this.makeRequest('GET', '/payments/user', undefined, {
|
|
51
51
|
cache: false, // Don't cache user payments - always get fresh data
|
|
52
52
|
});
|
|
53
53
|
} catch (error) {
|
|
@@ -62,7 +62,7 @@ export function OxyServicesPaymentMixin<T extends typeof OxyServicesBase>(Base:
|
|
|
62
62
|
*/
|
|
63
63
|
async getSubscription(userId: string): Promise<any> {
|
|
64
64
|
try {
|
|
65
|
-
return await this.makeRequest('GET', `/
|
|
65
|
+
return await this.makeRequest('GET', `/subscription/${userId}`, undefined, {
|
|
66
66
|
cache: true,
|
|
67
67
|
cacheTTL: CACHE_TIMES.MEDIUM,
|
|
68
68
|
});
|
|
@@ -94,7 +94,7 @@ export function OxyServicesPaymentMixin<T extends typeof OxyServicesBase>(Base:
|
|
|
94
94
|
*/
|
|
95
95
|
async getWallet(userId: string): Promise<any> {
|
|
96
96
|
try {
|
|
97
|
-
return await this.makeRequest('GET', `/
|
|
97
|
+
return await this.makeRequest('GET', `/wallet/${userId}`, undefined, {
|
|
98
98
|
cache: true,
|
|
99
99
|
cacheTTL: CACHE_TIMES.SHORT, // Cache wallet for short time as balance changes frequently
|
|
100
100
|
});
|
|
@@ -132,7 +132,7 @@ export function OxyServicesPaymentMixin<T extends typeof OxyServicesBase>(Base:
|
|
|
132
132
|
if (options?.offset) params.append('offset', options.offset.toString());
|
|
133
133
|
|
|
134
134
|
const queryString = params.toString();
|
|
135
|
-
const url = `/
|
|
135
|
+
const url = `/wallet/transactions/${userId}${queryString ? `?${queryString}` : ''}`;
|
|
136
136
|
|
|
137
137
|
return await this.makeRequest('GET', url, undefined, {
|
|
138
138
|
cache: false, // Don't cache transactions - always get fresh data
|
|
@@ -120,7 +120,7 @@ export function OxyServicesPopupAuthMixin<T extends typeof OxyServicesBase>(Base
|
|
|
120
120
|
try {
|
|
121
121
|
const userData = await this.makeRequest<any>(
|
|
122
122
|
'GET',
|
|
123
|
-
`/
|
|
123
|
+
`/session/user/${session.sessionId}`,
|
|
124
124
|
undefined,
|
|
125
125
|
{ cache: false }
|
|
126
126
|
);
|
|
@@ -53,7 +53,7 @@ export function OxyServicesPrivacyMixin<T extends typeof OxyServicesBase>(Base:
|
|
|
53
53
|
*/
|
|
54
54
|
async getBlockedUsers(): Promise<BlockedUser[]> {
|
|
55
55
|
try {
|
|
56
|
-
return await this.makeRequest<BlockedUser[]>('GET', '/
|
|
56
|
+
return await this.makeRequest<BlockedUser[]>('GET', '/privacy/blocked', undefined, {
|
|
57
57
|
cache: true,
|
|
58
58
|
cacheTTL: 1 * 60 * 1000, // 1 minute cache
|
|
59
59
|
});
|
|
@@ -72,7 +72,7 @@ export function OxyServicesPrivacyMixin<T extends typeof OxyServicesBase>(Base:
|
|
|
72
72
|
if (!userId) {
|
|
73
73
|
throw new Error('User ID is required');
|
|
74
74
|
}
|
|
75
|
-
return await this.makeRequest<{ message: string }>('POST', `/
|
|
75
|
+
return await this.makeRequest<{ message: string }>('POST', `/privacy/blocked/${userId}`, undefined, {
|
|
76
76
|
cache: false,
|
|
77
77
|
});
|
|
78
78
|
} catch (error) {
|
|
@@ -90,7 +90,7 @@ export function OxyServicesPrivacyMixin<T extends typeof OxyServicesBase>(Base:
|
|
|
90
90
|
if (!userId) {
|
|
91
91
|
throw new Error('User ID is required');
|
|
92
92
|
}
|
|
93
|
-
return await this.makeRequest<{ message: string }>('DELETE', `/
|
|
93
|
+
return await this.makeRequest<{ message: string }>('DELETE', `/privacy/blocked/${userId}`, undefined, {
|
|
94
94
|
cache: false,
|
|
95
95
|
});
|
|
96
96
|
} catch (error) {
|
|
@@ -121,7 +121,7 @@ export function OxyServicesPrivacyMixin<T extends typeof OxyServicesBase>(Base:
|
|
|
121
121
|
*/
|
|
122
122
|
async getRestrictedUsers(): Promise<RestrictedUser[]> {
|
|
123
123
|
try {
|
|
124
|
-
return await this.makeRequest<RestrictedUser[]>('GET', '/
|
|
124
|
+
return await this.makeRequest<RestrictedUser[]>('GET', '/privacy/restricted', undefined, {
|
|
125
125
|
cache: true,
|
|
126
126
|
cacheTTL: 1 * 60 * 1000, // 1 minute cache
|
|
127
127
|
});
|
|
@@ -140,7 +140,7 @@ export function OxyServicesPrivacyMixin<T extends typeof OxyServicesBase>(Base:
|
|
|
140
140
|
if (!userId) {
|
|
141
141
|
throw new Error('User ID is required');
|
|
142
142
|
}
|
|
143
|
-
return await this.makeRequest<{ message: string }>('POST', `/
|
|
143
|
+
return await this.makeRequest<{ message: string }>('POST', `/privacy/restricted/${userId}`, undefined, {
|
|
144
144
|
cache: false,
|
|
145
145
|
});
|
|
146
146
|
} catch (error) {
|
|
@@ -158,7 +158,7 @@ export function OxyServicesPrivacyMixin<T extends typeof OxyServicesBase>(Base:
|
|
|
158
158
|
if (!userId) {
|
|
159
159
|
throw new Error('User ID is required');
|
|
160
160
|
}
|
|
161
|
-
return await this.makeRequest<{ message: string }>('DELETE', `/
|
|
161
|
+
return await this.makeRequest<{ message: string }>('DELETE', `/privacy/restricted/${userId}`, undefined, {
|
|
162
162
|
cache: false,
|
|
163
163
|
});
|
|
164
164
|
} catch (error) {
|
|
@@ -31,7 +31,7 @@ export function OxyServicesSecurityMixin<T extends typeof OxyServicesBase>(Base:
|
|
|
31
31
|
|
|
32
32
|
const response = await this.makeRequest<SecurityActivityResponse>(
|
|
33
33
|
'GET',
|
|
34
|
-
'/
|
|
34
|
+
'/security/activity',
|
|
35
35
|
params,
|
|
36
36
|
{ cache: false }
|
|
37
37
|
);
|
|
@@ -65,7 +65,7 @@ export function OxyServicesSecurityMixin<T extends typeof OxyServicesBase>(Base:
|
|
|
65
65
|
try {
|
|
66
66
|
await this.makeRequest<{ success: boolean }>(
|
|
67
67
|
'POST',
|
|
68
|
-
'/
|
|
68
|
+
'/security/activity/private-key-exported',
|
|
69
69
|
{ deviceId },
|
|
70
70
|
{ cache: false }
|
|
71
71
|
);
|
|
@@ -87,7 +87,7 @@ export function OxyServicesSecurityMixin<T extends typeof OxyServicesBase>(Base:
|
|
|
87
87
|
try {
|
|
88
88
|
await this.makeRequest<{ success: boolean }>(
|
|
89
89
|
'POST',
|
|
90
|
-
'/
|
|
90
|
+
'/security/activity/backup-created',
|
|
91
91
|
{ deviceId },
|
|
92
92
|
{ cache: false }
|
|
93
93
|
);
|
|
@@ -15,7 +15,7 @@ export function OxyServicesUserMixin<T extends typeof OxyServicesBase>(Base: T)
|
|
|
15
15
|
*/
|
|
16
16
|
async getProfileByUsername(username: string): Promise<User> {
|
|
17
17
|
try {
|
|
18
|
-
return await this.makeRequest<User>('GET', `/
|
|
18
|
+
return await this.makeRequest<User>('GET', `/profiles/username/${username}`, undefined, {
|
|
19
19
|
cache: true,
|
|
20
20
|
cacheTTL: 5 * 60 * 1000, // 5 minutes cache for profiles
|
|
21
21
|
});
|
|
@@ -35,7 +35,7 @@ export function OxyServicesUserMixin<T extends typeof OxyServicesBase>(Base: T)
|
|
|
35
35
|
|
|
36
36
|
const response = await this.makeRequest<SearchProfilesResponse | User[]>(
|
|
37
37
|
'GET',
|
|
38
|
-
'/
|
|
38
|
+
'/profiles/search',
|
|
39
39
|
paramsObj,
|
|
40
40
|
{
|
|
41
41
|
cache: true,
|
|
@@ -97,7 +97,7 @@ export function OxyServicesUserMixin<T extends typeof OxyServicesBase>(Base: T)
|
|
|
97
97
|
[key: string]: any;
|
|
98
98
|
}>> {
|
|
99
99
|
return this.withAuthRetry(async () => {
|
|
100
|
-
return await this.makeRequest('GET', '/
|
|
100
|
+
return await this.makeRequest('GET', '/profiles/recommendations', undefined, { cache: true });
|
|
101
101
|
}, 'getProfileRecommendations');
|
|
102
102
|
}
|
|
103
103
|
|
|
@@ -106,7 +106,7 @@ export function OxyServicesUserMixin<T extends typeof OxyServicesBase>(Base: T)
|
|
|
106
106
|
*/
|
|
107
107
|
async getUserById(userId: string): Promise<User> {
|
|
108
108
|
try {
|
|
109
|
-
return await this.makeRequest<User>('GET', `/
|
|
109
|
+
return await this.makeRequest<User>('GET', `/users/${userId}`, undefined, {
|
|
110
110
|
cache: true,
|
|
111
111
|
cacheTTL: 5 * 60 * 1000, // 5 minutes cache
|
|
112
112
|
});
|
|
@@ -120,7 +120,7 @@ export function OxyServicesUserMixin<T extends typeof OxyServicesBase>(Base: T)
|
|
|
120
120
|
*/
|
|
121
121
|
async getCurrentUser(): Promise<User> {
|
|
122
122
|
return this.withAuthRetry(async () => {
|
|
123
|
-
return await this.makeRequest<User>('GET', '/
|
|
123
|
+
return await this.makeRequest<User>('GET', '/users/me', undefined, {
|
|
124
124
|
cache: true,
|
|
125
125
|
cacheTTL: 1 * 60 * 1000, // 1 minute cache for current user
|
|
126
126
|
});
|
|
@@ -133,7 +133,7 @@ export function OxyServicesUserMixin<T extends typeof OxyServicesBase>(Base: T)
|
|
|
133
133
|
*/
|
|
134
134
|
async updateProfile(updates: Record<string, any>): Promise<User> {
|
|
135
135
|
try {
|
|
136
|
-
return await this.makeRequest<User>('PUT', '/
|
|
136
|
+
return await this.makeRequest<User>('PUT', '/users/me', updates, { cache: false });
|
|
137
137
|
} catch (error) {
|
|
138
138
|
const errorAny = error as any;
|
|
139
139
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
@@ -162,7 +162,7 @@ export function OxyServicesUserMixin<T extends typeof OxyServicesBase>(Base: T)
|
|
|
162
162
|
async getPrivacySettings(userId?: string): Promise<any> {
|
|
163
163
|
try {
|
|
164
164
|
const id = userId || (await this.getCurrentUser()).id;
|
|
165
|
-
return await this.makeRequest<any>('GET', `/
|
|
165
|
+
return await this.makeRequest<any>('GET', `/privacy/${id}/privacy`, undefined, {
|
|
166
166
|
cache: true,
|
|
167
167
|
cacheTTL: 2 * 60 * 1000, // 2 minutes cache
|
|
168
168
|
});
|
|
@@ -179,7 +179,7 @@ export function OxyServicesUserMixin<T extends typeof OxyServicesBase>(Base: T)
|
|
|
179
179
|
async updatePrivacySettings(settings: Record<string, any>, userId?: string): Promise<any> {
|
|
180
180
|
try {
|
|
181
181
|
const id = userId || (await this.getCurrentUser()).id;
|
|
182
|
-
return await this.makeRequest<any>('PATCH', `/
|
|
182
|
+
return await this.makeRequest<any>('PATCH', `/privacy/${id}/privacy`, settings, {
|
|
183
183
|
cache: false,
|
|
184
184
|
});
|
|
185
185
|
} catch (error) {
|
|
@@ -192,7 +192,7 @@ export function OxyServicesUserMixin<T extends typeof OxyServicesBase>(Base: T)
|
|
|
192
192
|
*/
|
|
193
193
|
async requestAccountVerification(reason: string, evidence?: string): Promise<{ message: string; requestId: string }> {
|
|
194
194
|
try {
|
|
195
|
-
return await this.makeRequest<{ message: string; requestId: string }>('POST', '/
|
|
195
|
+
return await this.makeRequest<{ message: string; requestId: string }>('POST', '/users/verify/request', {
|
|
196
196
|
reason,
|
|
197
197
|
evidence,
|
|
198
198
|
}, { cache: false });
|
|
@@ -209,7 +209,7 @@ export function OxyServicesUserMixin<T extends typeof OxyServicesBase>(Base: T)
|
|
|
209
209
|
// Use httpService for blob responses (it handles blob responses automatically)
|
|
210
210
|
const result = await this.getClient().request<Blob>({
|
|
211
211
|
method: 'GET',
|
|
212
|
-
url: `/
|
|
212
|
+
url: `/users/me/data`,
|
|
213
213
|
params: { format },
|
|
214
214
|
cache: false,
|
|
215
215
|
});
|
|
@@ -227,7 +227,7 @@ export function OxyServicesUserMixin<T extends typeof OxyServicesBase>(Base: T)
|
|
|
227
227
|
*/
|
|
228
228
|
async deleteAccount(password: string, confirmText: string): Promise<{ message: string }> {
|
|
229
229
|
try {
|
|
230
|
-
return await this.makeRequest<{ message: string }>('DELETE', '/
|
|
230
|
+
return await this.makeRequest<{ message: string }>('DELETE', '/users/me', {
|
|
231
231
|
password,
|
|
232
232
|
confirmText,
|
|
233
233
|
}, { cache: false });
|
|
@@ -242,7 +242,7 @@ export function OxyServicesUserMixin<T extends typeof OxyServicesBase>(Base: T)
|
|
|
242
242
|
*/
|
|
243
243
|
async followUser(userId: string): Promise<{ success: boolean; message: string }> {
|
|
244
244
|
try {
|
|
245
|
-
return await this.makeRequest('POST', `/
|
|
245
|
+
return await this.makeRequest('POST', `/users/${userId}/follow`, undefined, { cache: false });
|
|
246
246
|
} catch (error) {
|
|
247
247
|
throw this.handleError(error);
|
|
248
248
|
}
|
|
@@ -253,7 +253,7 @@ export function OxyServicesUserMixin<T extends typeof OxyServicesBase>(Base: T)
|
|
|
253
253
|
*/
|
|
254
254
|
async unfollowUser(userId: string): Promise<{ success: boolean; message: string }> {
|
|
255
255
|
try {
|
|
256
|
-
return await this.makeRequest('DELETE', `/
|
|
256
|
+
return await this.makeRequest('DELETE', `/users/${userId}/follow`, undefined, { cache: false });
|
|
257
257
|
} catch (error) {
|
|
258
258
|
throw this.handleError(error);
|
|
259
259
|
}
|
|
@@ -264,7 +264,7 @@ export function OxyServicesUserMixin<T extends typeof OxyServicesBase>(Base: T)
|
|
|
264
264
|
*/
|
|
265
265
|
async getFollowStatus(userId: string): Promise<{ isFollowing: boolean }> {
|
|
266
266
|
try {
|
|
267
|
-
return await this.makeRequest('GET', `/
|
|
267
|
+
return await this.makeRequest('GET', `/users/${userId}/follow-status`, undefined, {
|
|
268
268
|
cache: true,
|
|
269
269
|
cacheTTL: 1 * 60 * 1000, // 1 minute cache
|
|
270
270
|
});
|
|
@@ -282,7 +282,7 @@ export function OxyServicesUserMixin<T extends typeof OxyServicesBase>(Base: T)
|
|
|
282
282
|
): Promise<{ followers: User[]; total: number; hasMore: boolean }> {
|
|
283
283
|
try {
|
|
284
284
|
const params = buildPaginationParams(pagination || {});
|
|
285
|
-
const response = await this.makeRequest<{ data: User[]; pagination: { total: number; hasMore: boolean } }>('GET', `/
|
|
285
|
+
const response = await this.makeRequest<{ data: User[]; pagination: { total: number; hasMore: boolean } }>('GET', `/users/${userId}/followers`, params, {
|
|
286
286
|
cache: true,
|
|
287
287
|
cacheTTL: 2 * 60 * 1000, // 2 minutes cache
|
|
288
288
|
});
|
|
@@ -305,7 +305,7 @@ export function OxyServicesUserMixin<T extends typeof OxyServicesBase>(Base: T)
|
|
|
305
305
|
): Promise<{ following: User[]; total: number; hasMore: boolean }> {
|
|
306
306
|
try {
|
|
307
307
|
const params = buildPaginationParams(pagination || {});
|
|
308
|
-
const response = await this.makeRequest<{ data: User[]; pagination: { total: number; hasMore: boolean } }>('GET', `/
|
|
308
|
+
const response = await this.makeRequest<{ data: User[]; pagination: { total: number; hasMore: boolean } }>('GET', `/users/${userId}/following`, params, {
|
|
309
309
|
cache: true,
|
|
310
310
|
cacheTTL: 2 * 60 * 1000, // 2 minutes cache
|
|
311
311
|
});
|
|
@@ -324,7 +324,7 @@ export function OxyServicesUserMixin<T extends typeof OxyServicesBase>(Base: T)
|
|
|
324
324
|
*/
|
|
325
325
|
async getNotifications(): Promise<Notification[]> {
|
|
326
326
|
return this.withAuthRetry(async () => {
|
|
327
|
-
return await this.makeRequest<Notification[]>('GET', '/
|
|
327
|
+
return await this.makeRequest<Notification[]>('GET', '/notifications', undefined, {
|
|
328
328
|
cache: false, // Don't cache notifications - always get fresh data
|
|
329
329
|
});
|
|
330
330
|
}, 'getNotifications');
|
|
@@ -335,7 +335,7 @@ export function OxyServicesUserMixin<T extends typeof OxyServicesBase>(Base: T)
|
|
|
335
335
|
*/
|
|
336
336
|
async getUnreadCount(): Promise<number> {
|
|
337
337
|
try {
|
|
338
|
-
const res = await this.makeRequest<{ count: number }>('GET', '/
|
|
338
|
+
const res = await this.makeRequest<{ count: number }>('GET', '/notifications/unread-count', undefined, {
|
|
339
339
|
cache: false, // Don't cache unread count - always get fresh data
|
|
340
340
|
});
|
|
341
341
|
return res.count;
|
|
@@ -349,7 +349,7 @@ export function OxyServicesUserMixin<T extends typeof OxyServicesBase>(Base: T)
|
|
|
349
349
|
*/
|
|
350
350
|
async createNotification(data: Partial<Notification>): Promise<Notification> {
|
|
351
351
|
try {
|
|
352
|
-
return await this.makeRequest<Notification>('POST', '/
|
|
352
|
+
return await this.makeRequest<Notification>('POST', '/notifications', data, { cache: false });
|
|
353
353
|
} catch (error) {
|
|
354
354
|
throw this.handleError(error);
|
|
355
355
|
}
|
|
@@ -360,7 +360,7 @@ export function OxyServicesUserMixin<T extends typeof OxyServicesBase>(Base: T)
|
|
|
360
360
|
*/
|
|
361
361
|
async markNotificationAsRead(notificationId: string): Promise<void> {
|
|
362
362
|
try {
|
|
363
|
-
await this.makeRequest('PUT', `/
|
|
363
|
+
await this.makeRequest('PUT', `/notifications/${notificationId}/read`, undefined, { cache: false });
|
|
364
364
|
} catch (error) {
|
|
365
365
|
throw this.handleError(error);
|
|
366
366
|
}
|
|
@@ -371,7 +371,7 @@ export function OxyServicesUserMixin<T extends typeof OxyServicesBase>(Base: T)
|
|
|
371
371
|
*/
|
|
372
372
|
async markAllNotificationsAsRead(): Promise<void> {
|
|
373
373
|
try {
|
|
374
|
-
await this.makeRequest('PUT', '/
|
|
374
|
+
await this.makeRequest('PUT', '/notifications/read-all', undefined, { cache: false });
|
|
375
375
|
} catch (error) {
|
|
376
376
|
throw this.handleError(error);
|
|
377
377
|
}
|
|
@@ -382,7 +382,7 @@ export function OxyServicesUserMixin<T extends typeof OxyServicesBase>(Base: T)
|
|
|
382
382
|
*/
|
|
383
383
|
async deleteNotification(notificationId: string): Promise<void> {
|
|
384
384
|
try {
|
|
385
|
-
await this.makeRequest('DELETE', `/
|
|
385
|
+
await this.makeRequest('DELETE', `/notifications/${notificationId}`, undefined, { cache: false });
|
|
386
386
|
} catch (error) {
|
|
387
387
|
throw this.handleError(error);
|
|
388
388
|
}
|
|
@@ -68,7 +68,7 @@ export function OxyServicesUtilityMixin<T extends typeof OxyServicesBase>(Base:
|
|
|
68
68
|
title: string;
|
|
69
69
|
description: string;
|
|
70
70
|
image?: string;
|
|
71
|
-
}>('GET', '/
|
|
71
|
+
}>('GET', '/link-metadata', { url }, {
|
|
72
72
|
cache: true,
|
|
73
73
|
cacheTTL: CACHE_TIMES.EXTRA_LONG,
|
|
74
74
|
});
|
|
@@ -83,25 +83,36 @@ export function OxyServicesUtilityMixin<T extends typeof OxyServicesBase>(Base:
|
|
|
83
83
|
* Validates JWT tokens against the Oxy API and attaches user data to requests.
|
|
84
84
|
* Uses server-side session validation for security (not just JWT decode).
|
|
85
85
|
*
|
|
86
|
+
* **Design note — jwtDecode vs jwt.verify:**
|
|
87
|
+
* This middleware intentionally uses `jwtDecode()` (decode-only, no signature
|
|
88
|
+
* verification) for user tokens. This is by design, NOT a security gap:
|
|
89
|
+
* - Third-party apps using `oxy.auth()` don't have the Oxy JWT secret
|
|
90
|
+
* - Security comes from API-based session validation (`validateSession()`)
|
|
91
|
+
* which checks the session server-side on every request
|
|
92
|
+
* - Service tokens (type: 'service') DO use cryptographic HMAC verification
|
|
93
|
+
* via the `jwtSecret` option, since they are stateless
|
|
94
|
+
* - The backend's own `authMiddleware` uses `jwt.verify()` because it has
|
|
95
|
+
* direct access to `ACCESS_TOKEN_SECRET`
|
|
96
|
+
*
|
|
86
97
|
* @example
|
|
87
98
|
* ```typescript
|
|
88
99
|
* import { OxyServices } from '@oxyhq/core';
|
|
89
100
|
*
|
|
90
101
|
* const oxy = new OxyServices({ baseURL: 'https://api.oxy.so' });
|
|
91
102
|
*
|
|
92
|
-
* // Protect all routes under /
|
|
93
|
-
* app.use('/
|
|
103
|
+
* // Protect all routes under /protected
|
|
104
|
+
* app.use('/protected', oxy.auth());
|
|
94
105
|
*
|
|
95
106
|
* // Access user in route handler
|
|
96
|
-
* app.get('/
|
|
107
|
+
* app.get('/protected/me', (req, res) => {
|
|
97
108
|
* res.json({ userId: req.userId, user: req.user });
|
|
98
109
|
* });
|
|
99
110
|
*
|
|
100
111
|
* // Load full user profile from API
|
|
101
|
-
* app.use('/
|
|
112
|
+
* app.use('/admin', oxy.auth({ loadUser: true }));
|
|
102
113
|
*
|
|
103
114
|
* // Optional auth - attach user if present, don't block if absent
|
|
104
|
-
* app.use('/
|
|
115
|
+
* app.use('/public', oxy.auth({ optional: true }));
|
|
105
116
|
* ```
|
|
106
117
|
*
|
|
107
118
|
* @param options Optional configuration
|
|
@@ -138,6 +149,7 @@ export function OxyServicesUtilityMixin<T extends typeof OxyServicesBase>(Base:
|
|
|
138
149
|
}
|
|
139
150
|
|
|
140
151
|
const error = {
|
|
152
|
+
error: 'MISSING_TOKEN',
|
|
141
153
|
message: 'Access token required',
|
|
142
154
|
code: 'MISSING_TOKEN',
|
|
143
155
|
status: 401
|
|
@@ -158,6 +170,7 @@ export function OxyServicesUtilityMixin<T extends typeof OxyServicesBase>(Base:
|
|
|
158
170
|
}
|
|
159
171
|
|
|
160
172
|
const error = {
|
|
173
|
+
error: 'INVALID_TOKEN_FORMAT',
|
|
161
174
|
message: 'Invalid token format',
|
|
162
175
|
code: 'INVALID_TOKEN_FORMAT',
|
|
163
176
|
status: 401
|
|
@@ -177,6 +190,7 @@ export function OxyServicesUtilityMixin<T extends typeof OxyServicesBase>(Base:
|
|
|
177
190
|
return next();
|
|
178
191
|
}
|
|
179
192
|
const error = {
|
|
193
|
+
error: 'SERVICE_TOKEN_NOT_CONFIGURED',
|
|
180
194
|
message: 'Service token verification not configured',
|
|
181
195
|
code: 'SERVICE_TOKEN_NOT_CONFIGURED',
|
|
182
196
|
status: 403
|
|
@@ -206,13 +220,23 @@ export function OxyServicesUtilityMixin<T extends typeof OxyServicesBase>(Base:
|
|
|
206
220
|
if (sigBuf.length !== expectedBuf.length || !timingSafeEqual(sigBuf, expectedBuf)) {
|
|
207
221
|
throw new Error('Invalid signature');
|
|
208
222
|
}
|
|
209
|
-
} catch {
|
|
223
|
+
} catch (verifyError) {
|
|
224
|
+
const isSignatureError = verifyError instanceof Error &&
|
|
225
|
+
(verifyError.message === 'Invalid signature' || verifyError.message === 'Invalid token structure');
|
|
226
|
+
|
|
227
|
+
if (!isSignatureError) {
|
|
228
|
+
console.error('[oxy.auth] Unexpected error during service token verification:', verifyError);
|
|
229
|
+
const error = { error: 'AUTH_INTERNAL_ERROR', message: 'Internal authentication error', code: 'AUTH_INTERNAL_ERROR', status: 500 };
|
|
230
|
+
if (onError) return onError(error);
|
|
231
|
+
return res.status(500).json(error);
|
|
232
|
+
}
|
|
233
|
+
|
|
210
234
|
if (optional) {
|
|
211
235
|
req.userId = null;
|
|
212
236
|
req.user = null;
|
|
213
237
|
return next();
|
|
214
238
|
}
|
|
215
|
-
const error = { message: 'Invalid service token signature', code: 'INVALID_SERVICE_TOKEN', status: 401 };
|
|
239
|
+
const error = { error: 'INVALID_SERVICE_TOKEN', message: 'Invalid service token signature', code: 'INVALID_SERVICE_TOKEN', status: 401 };
|
|
216
240
|
if (onError) return onError(error);
|
|
217
241
|
return res.status(401).json(error);
|
|
218
242
|
}
|
|
@@ -224,7 +248,7 @@ export function OxyServicesUtilityMixin<T extends typeof OxyServicesBase>(Base:
|
|
|
224
248
|
req.user = null;
|
|
225
249
|
return next();
|
|
226
250
|
}
|
|
227
|
-
const error = { message: 'Service token expired', code: 'TOKEN_EXPIRED', status: 401 };
|
|
251
|
+
const error = { error: 'TOKEN_EXPIRED', message: 'Service token expired', code: 'TOKEN_EXPIRED', status: 401 };
|
|
228
252
|
if (onError) return onError(error);
|
|
229
253
|
return res.status(401).json(error);
|
|
230
254
|
}
|
|
@@ -236,7 +260,7 @@ export function OxyServicesUtilityMixin<T extends typeof OxyServicesBase>(Base:
|
|
|
236
260
|
req.user = null;
|
|
237
261
|
return next();
|
|
238
262
|
}
|
|
239
|
-
const error = { message: 'Invalid service token: missing appId', code: 'INVALID_SERVICE_TOKEN', status: 401 };
|
|
263
|
+
const error = { error: 'INVALID_SERVICE_TOKEN', message: 'Invalid service token: missing appId', code: 'INVALID_SERVICE_TOKEN', status: 401 };
|
|
240
264
|
if (onError) return onError(error);
|
|
241
265
|
return res.status(401).json(error);
|
|
242
266
|
}
|
|
@@ -268,6 +292,7 @@ export function OxyServicesUtilityMixin<T extends typeof OxyServicesBase>(Base:
|
|
|
268
292
|
}
|
|
269
293
|
|
|
270
294
|
const error = {
|
|
295
|
+
error: 'INVALID_TOKEN_PAYLOAD',
|
|
271
296
|
message: 'Token missing user ID',
|
|
272
297
|
code: 'INVALID_TOKEN_PAYLOAD',
|
|
273
298
|
status: 401
|
|
@@ -285,6 +310,7 @@ export function OxyServicesUtilityMixin<T extends typeof OxyServicesBase>(Base:
|
|
|
285
310
|
}
|
|
286
311
|
|
|
287
312
|
const error = {
|
|
313
|
+
error: 'TOKEN_EXPIRED',
|
|
288
314
|
message: 'Token expired',
|
|
289
315
|
code: 'TOKEN_EXPIRED',
|
|
290
316
|
status: 401
|
|
@@ -309,6 +335,7 @@ export function OxyServicesUtilityMixin<T extends typeof OxyServicesBase>(Base:
|
|
|
309
335
|
}
|
|
310
336
|
|
|
311
337
|
const error = {
|
|
338
|
+
error: 'INVALID_SESSION',
|
|
312
339
|
message: 'Session invalid or expired',
|
|
313
340
|
code: 'INVALID_SESSION',
|
|
314
341
|
status: 401
|
|
@@ -346,6 +373,7 @@ export function OxyServicesUtilityMixin<T extends typeof OxyServicesBase>(Base:
|
|
|
346
373
|
}
|
|
347
374
|
|
|
348
375
|
const error = {
|
|
376
|
+
error: 'SESSION_VALIDATION_ERROR',
|
|
349
377
|
message: 'Session validation failed',
|
|
350
378
|
code: 'SESSION_VALIDATION_ERROR',
|
|
351
379
|
status: 401
|
|
@@ -406,6 +434,8 @@ export function OxyServicesUtilityMixin<T extends typeof OxyServicesBase>(Base:
|
|
|
406
434
|
* Returns a middleware function for Socket.IO that validates JWT tokens
|
|
407
435
|
* from the handshake auth object and attaches user data to the socket.
|
|
408
436
|
*
|
|
437
|
+
* Uses `jwtDecode()` + API session validation (same rationale as `auth()`).
|
|
438
|
+
*
|
|
409
439
|
* @example
|
|
410
440
|
* ```typescript
|
|
411
441
|
* import { OxyServices } from '@oxyhq/core';
|
|
@@ -504,7 +534,7 @@ export function OxyServicesUtilityMixin<T extends typeof OxyServicesBase>(Base:
|
|
|
504
534
|
* });
|
|
505
535
|
* ```
|
|
506
536
|
*/
|
|
507
|
-
serviceAuth(options: { debug?: boolean } = {}) {
|
|
537
|
+
serviceAuth(options: { debug?: boolean; jwtSecret?: string } = {}) {
|
|
508
538
|
const innerAuth = this.auth({ ...options });
|
|
509
539
|
|
|
510
540
|
return async (req: any, res: any, next: any) => {
|