@oxyhq/core 1.0.0
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/README.md +50 -0
- package/dist/cjs/AuthManager.js +361 -0
- package/dist/cjs/CrossDomainAuth.js +258 -0
- package/dist/cjs/HttpService.js +618 -0
- package/dist/cjs/OxyServices.base.js +263 -0
- package/dist/cjs/OxyServices.errors.js +22 -0
- package/dist/cjs/OxyServices.js +63 -0
- package/dist/cjs/constants/version.js +16 -0
- package/dist/cjs/crypto/index.js +20 -0
- package/dist/cjs/crypto/keyManager.js +887 -0
- package/dist/cjs/crypto/polyfill.js +64 -0
- package/dist/cjs/crypto/recoveryPhrase.js +169 -0
- package/dist/cjs/crypto/signatureService.js +296 -0
- package/dist/cjs/i18n/index.js +73 -0
- package/dist/cjs/i18n/locales/ar-SA.json +120 -0
- package/dist/cjs/i18n/locales/ca-ES.json +120 -0
- package/dist/cjs/i18n/locales/de-DE.json +120 -0
- package/dist/cjs/i18n/locales/en-US.json +956 -0
- package/dist/cjs/i18n/locales/es-ES.json +944 -0
- package/dist/cjs/i18n/locales/fr-FR.json +120 -0
- package/dist/cjs/i18n/locales/it-IT.json +120 -0
- package/dist/cjs/i18n/locales/ja-JP.json +119 -0
- package/dist/cjs/i18n/locales/ko-KR.json +120 -0
- package/dist/cjs/i18n/locales/locales/ar-SA.json +120 -0
- package/dist/cjs/i18n/locales/locales/ca-ES.json +120 -0
- package/dist/cjs/i18n/locales/locales/de-DE.json +120 -0
- package/dist/cjs/i18n/locales/locales/en-US.json +956 -0
- package/dist/cjs/i18n/locales/locales/es-ES.json +944 -0
- package/dist/cjs/i18n/locales/locales/fr-FR.json +120 -0
- package/dist/cjs/i18n/locales/locales/it-IT.json +120 -0
- package/dist/cjs/i18n/locales/locales/ja-JP.json +119 -0
- package/dist/cjs/i18n/locales/locales/ko-KR.json +120 -0
- package/dist/cjs/i18n/locales/locales/pt-PT.json +120 -0
- package/dist/cjs/i18n/locales/locales/zh-CN.json +120 -0
- package/dist/cjs/i18n/locales/pt-PT.json +120 -0
- package/dist/cjs/i18n/locales/zh-CN.json +120 -0
- package/dist/cjs/index.js +153 -0
- package/dist/cjs/mixins/OxyServices.analytics.js +49 -0
- package/dist/cjs/mixins/OxyServices.assets.js +380 -0
- package/dist/cjs/mixins/OxyServices.auth.js +259 -0
- package/dist/cjs/mixins/OxyServices.developer.js +97 -0
- package/dist/cjs/mixins/OxyServices.devices.js +116 -0
- package/dist/cjs/mixins/OxyServices.features.js +309 -0
- package/dist/cjs/mixins/OxyServices.fedcm.js +435 -0
- package/dist/cjs/mixins/OxyServices.karma.js +108 -0
- package/dist/cjs/mixins/OxyServices.language.js +154 -0
- package/dist/cjs/mixins/OxyServices.location.js +43 -0
- package/dist/cjs/mixins/OxyServices.payment.js +158 -0
- package/dist/cjs/mixins/OxyServices.popup.js +371 -0
- package/dist/cjs/mixins/OxyServices.privacy.js +162 -0
- package/dist/cjs/mixins/OxyServices.redirect.js +345 -0
- package/dist/cjs/mixins/OxyServices.security.js +81 -0
- package/dist/cjs/mixins/OxyServices.user.js +355 -0
- package/dist/cjs/mixins/OxyServices.utility.js +156 -0
- package/dist/cjs/mixins/index.js +79 -0
- package/dist/cjs/mixins/mixinHelpers.js +53 -0
- package/dist/cjs/models/interfaces.js +20 -0
- package/dist/cjs/models/session.js +2 -0
- package/dist/cjs/shared/index.js +70 -0
- package/dist/cjs/shared/utils/colorUtils.js +153 -0
- package/dist/cjs/shared/utils/debugUtils.js +73 -0
- package/dist/cjs/shared/utils/errorUtils.js +183 -0
- package/dist/cjs/shared/utils/index.js +49 -0
- package/dist/cjs/shared/utils/networkUtils.js +183 -0
- package/dist/cjs/shared/utils/themeUtils.js +106 -0
- package/dist/cjs/utils/apiUtils.js +61 -0
- package/dist/cjs/utils/asyncUtils.js +194 -0
- package/dist/cjs/utils/cache.js +226 -0
- package/dist/cjs/utils/deviceManager.js +205 -0
- package/dist/cjs/utils/errorUtils.js +154 -0
- package/dist/cjs/utils/index.js +26 -0
- package/dist/cjs/utils/languageUtils.js +165 -0
- package/dist/cjs/utils/loggerUtils.js +126 -0
- package/dist/cjs/utils/platform.js +144 -0
- package/dist/cjs/utils/requestUtils.js +209 -0
- package/dist/cjs/utils/sessionUtils.js +181 -0
- package/dist/cjs/utils/validationUtils.js +173 -0
- package/dist/esm/AuthManager.js +356 -0
- package/dist/esm/CrossDomainAuth.js +253 -0
- package/dist/esm/HttpService.js +614 -0
- package/dist/esm/OxyServices.base.js +259 -0
- package/dist/esm/OxyServices.errors.js +17 -0
- package/dist/esm/OxyServices.js +59 -0
- package/dist/esm/constants/version.js +13 -0
- package/dist/esm/crypto/index.js +13 -0
- package/dist/esm/crypto/keyManager.js +850 -0
- package/dist/esm/crypto/polyfill.js +61 -0
- package/dist/esm/crypto/recoveryPhrase.js +132 -0
- package/dist/esm/crypto/signatureService.js +259 -0
- package/dist/esm/i18n/index.js +69 -0
- package/dist/esm/i18n/locales/ar-SA.json +120 -0
- package/dist/esm/i18n/locales/ca-ES.json +120 -0
- package/dist/esm/i18n/locales/de-DE.json +120 -0
- package/dist/esm/i18n/locales/en-US.json +956 -0
- package/dist/esm/i18n/locales/es-ES.json +944 -0
- package/dist/esm/i18n/locales/fr-FR.json +120 -0
- package/dist/esm/i18n/locales/it-IT.json +120 -0
- package/dist/esm/i18n/locales/ja-JP.json +119 -0
- package/dist/esm/i18n/locales/ko-KR.json +120 -0
- package/dist/esm/i18n/locales/locales/ar-SA.json +120 -0
- package/dist/esm/i18n/locales/locales/ca-ES.json +120 -0
- package/dist/esm/i18n/locales/locales/de-DE.json +120 -0
- package/dist/esm/i18n/locales/locales/en-US.json +956 -0
- package/dist/esm/i18n/locales/locales/es-ES.json +944 -0
- package/dist/esm/i18n/locales/locales/fr-FR.json +120 -0
- package/dist/esm/i18n/locales/locales/it-IT.json +120 -0
- package/dist/esm/i18n/locales/locales/ja-JP.json +119 -0
- package/dist/esm/i18n/locales/locales/ko-KR.json +120 -0
- package/dist/esm/i18n/locales/locales/pt-PT.json +120 -0
- package/dist/esm/i18n/locales/locales/zh-CN.json +120 -0
- package/dist/esm/i18n/locales/pt-PT.json +120 -0
- package/dist/esm/i18n/locales/zh-CN.json +120 -0
- package/dist/esm/index.js +55 -0
- package/dist/esm/mixins/OxyServices.analytics.js +46 -0
- package/dist/esm/mixins/OxyServices.assets.js +377 -0
- package/dist/esm/mixins/OxyServices.auth.js +256 -0
- package/dist/esm/mixins/OxyServices.developer.js +94 -0
- package/dist/esm/mixins/OxyServices.devices.js +113 -0
- package/dist/esm/mixins/OxyServices.features.js +306 -0
- package/dist/esm/mixins/OxyServices.fedcm.js +433 -0
- package/dist/esm/mixins/OxyServices.karma.js +105 -0
- package/dist/esm/mixins/OxyServices.language.js +118 -0
- package/dist/esm/mixins/OxyServices.location.js +40 -0
- package/dist/esm/mixins/OxyServices.payment.js +155 -0
- package/dist/esm/mixins/OxyServices.popup.js +369 -0
- package/dist/esm/mixins/OxyServices.privacy.js +159 -0
- package/dist/esm/mixins/OxyServices.redirect.js +343 -0
- package/dist/esm/mixins/OxyServices.security.js +78 -0
- package/dist/esm/mixins/OxyServices.user.js +352 -0
- package/dist/esm/mixins/OxyServices.utility.js +153 -0
- package/dist/esm/mixins/index.js +76 -0
- package/dist/esm/mixins/mixinHelpers.js +48 -0
- package/dist/esm/models/interfaces.js +17 -0
- package/dist/esm/models/session.js +1 -0
- package/dist/esm/shared/index.js +31 -0
- package/dist/esm/shared/utils/colorUtils.js +143 -0
- package/dist/esm/shared/utils/debugUtils.js +65 -0
- package/dist/esm/shared/utils/errorUtils.js +170 -0
- package/dist/esm/shared/utils/index.js +15 -0
- package/dist/esm/shared/utils/networkUtils.js +173 -0
- package/dist/esm/shared/utils/themeUtils.js +98 -0
- package/dist/esm/utils/apiUtils.js +55 -0
- package/dist/esm/utils/asyncUtils.js +179 -0
- package/dist/esm/utils/cache.js +218 -0
- package/dist/esm/utils/deviceManager.js +168 -0
- package/dist/esm/utils/errorUtils.js +146 -0
- package/dist/esm/utils/index.js +7 -0
- package/dist/esm/utils/languageUtils.js +158 -0
- package/dist/esm/utils/loggerUtils.js +115 -0
- package/dist/esm/utils/platform.js +102 -0
- package/dist/esm/utils/requestUtils.js +203 -0
- package/dist/esm/utils/sessionUtils.js +171 -0
- package/dist/esm/utils/validationUtils.js +153 -0
- package/dist/types/AuthManager.d.ts +143 -0
- package/dist/types/CrossDomainAuth.d.ts +160 -0
- package/dist/types/HttpService.d.ts +163 -0
- package/dist/types/OxyServices.base.d.ts +126 -0
- package/dist/types/OxyServices.d.ts +81 -0
- package/dist/types/OxyServices.errors.d.ts +11 -0
- package/dist/types/constants/version.d.ts +13 -0
- package/dist/types/crypto/index.d.ts +11 -0
- package/dist/types/crypto/keyManager.d.ts +189 -0
- package/dist/types/crypto/polyfill.d.ts +11 -0
- package/dist/types/crypto/recoveryPhrase.d.ts +58 -0
- package/dist/types/crypto/signatureService.d.ts +86 -0
- package/dist/types/i18n/index.d.ts +3 -0
- package/dist/types/index.d.ts +50 -0
- package/dist/types/mixins/OxyServices.analytics.d.ts +66 -0
- package/dist/types/mixins/OxyServices.assets.d.ts +135 -0
- package/dist/types/mixins/OxyServices.auth.d.ts +186 -0
- package/dist/types/mixins/OxyServices.developer.d.ts +99 -0
- package/dist/types/mixins/OxyServices.devices.d.ts +96 -0
- package/dist/types/mixins/OxyServices.features.d.ts +228 -0
- package/dist/types/mixins/OxyServices.fedcm.d.ts +200 -0
- package/dist/types/mixins/OxyServices.karma.d.ts +85 -0
- package/dist/types/mixins/OxyServices.language.d.ts +81 -0
- package/dist/types/mixins/OxyServices.location.d.ts +64 -0
- package/dist/types/mixins/OxyServices.payment.d.ts +111 -0
- package/dist/types/mixins/OxyServices.popup.d.ts +205 -0
- package/dist/types/mixins/OxyServices.privacy.d.ts +122 -0
- package/dist/types/mixins/OxyServices.redirect.d.ts +245 -0
- package/dist/types/mixins/OxyServices.security.d.ts +78 -0
- package/dist/types/mixins/OxyServices.user.d.ts +182 -0
- package/dist/types/mixins/OxyServices.utility.d.ts +93 -0
- package/dist/types/mixins/index.d.ts +30 -0
- package/dist/types/mixins/mixinHelpers.d.ts +31 -0
- package/dist/types/models/interfaces.d.ts +415 -0
- package/dist/types/models/session.d.ts +27 -0
- package/dist/types/shared/index.d.ts +28 -0
- package/dist/types/shared/utils/colorUtils.d.ts +104 -0
- package/dist/types/shared/utils/debugUtils.d.ts +48 -0
- package/dist/types/shared/utils/errorUtils.d.ts +97 -0
- package/dist/types/shared/utils/index.d.ts +13 -0
- package/dist/types/shared/utils/networkUtils.d.ts +139 -0
- package/dist/types/shared/utils/themeUtils.d.ts +90 -0
- package/dist/types/utils/apiUtils.d.ts +53 -0
- package/dist/types/utils/asyncUtils.d.ts +58 -0
- package/dist/types/utils/cache.d.ts +127 -0
- package/dist/types/utils/deviceManager.d.ts +65 -0
- package/dist/types/utils/errorUtils.d.ts +46 -0
- package/dist/types/utils/index.d.ts +6 -0
- package/dist/types/utils/languageUtils.d.ts +37 -0
- package/dist/types/utils/loggerUtils.d.ts +48 -0
- package/dist/types/utils/platform.d.ts +40 -0
- package/dist/types/utils/requestUtils.d.ts +123 -0
- package/dist/types/utils/sessionUtils.d.ts +54 -0
- package/dist/types/utils/validationUtils.d.ts +85 -0
- package/package.json +84 -0
- package/src/AuthManager.ts +436 -0
- package/src/CrossDomainAuth.ts +307 -0
- package/src/HttpService.ts +752 -0
- package/src/OxyServices.base.ts +334 -0
- package/src/OxyServices.errors.ts +26 -0
- package/src/OxyServices.ts +129 -0
- package/src/constants/version.ts +15 -0
- package/src/crypto/index.ts +25 -0
- package/src/crypto/keyManager.ts +962 -0
- package/src/crypto/polyfill.ts +70 -0
- package/src/crypto/recoveryPhrase.ts +166 -0
- package/src/crypto/signatureService.ts +323 -0
- package/src/i18n/index.ts +75 -0
- package/src/i18n/locales/ar-SA.json +120 -0
- package/src/i18n/locales/ca-ES.json +120 -0
- package/src/i18n/locales/de-DE.json +120 -0
- package/src/i18n/locales/en-US.json +956 -0
- package/src/i18n/locales/es-ES.json +944 -0
- package/src/i18n/locales/fr-FR.json +120 -0
- package/src/i18n/locales/it-IT.json +120 -0
- package/src/i18n/locales/ja-JP.json +119 -0
- package/src/i18n/locales/ko-KR.json +120 -0
- package/src/i18n/locales/pt-PT.json +120 -0
- package/src/i18n/locales/zh-CN.json +120 -0
- package/src/index.ts +153 -0
- package/src/mixins/OxyServices.analytics.ts +53 -0
- package/src/mixins/OxyServices.assets.ts +412 -0
- package/src/mixins/OxyServices.auth.ts +358 -0
- package/src/mixins/OxyServices.developer.ts +114 -0
- package/src/mixins/OxyServices.devices.ts +119 -0
- package/src/mixins/OxyServices.features.ts +428 -0
- package/src/mixins/OxyServices.fedcm.ts +494 -0
- package/src/mixins/OxyServices.karma.ts +111 -0
- package/src/mixins/OxyServices.language.ts +127 -0
- package/src/mixins/OxyServices.location.ts +46 -0
- package/src/mixins/OxyServices.payment.ts +163 -0
- package/src/mixins/OxyServices.popup.ts +443 -0
- package/src/mixins/OxyServices.privacy.ts +182 -0
- package/src/mixins/OxyServices.redirect.ts +397 -0
- package/src/mixins/OxyServices.security.ts +103 -0
- package/src/mixins/OxyServices.user.ts +392 -0
- package/src/mixins/OxyServices.utility.ts +191 -0
- package/src/mixins/index.ts +91 -0
- package/src/mixins/mixinHelpers.ts +69 -0
- package/src/models/interfaces.ts +511 -0
- package/src/models/session.ts +30 -0
- package/src/shared/index.ts +82 -0
- package/src/shared/utils/colorUtils.ts +155 -0
- package/src/shared/utils/debugUtils.ts +73 -0
- package/src/shared/utils/errorUtils.ts +181 -0
- package/src/shared/utils/index.ts +59 -0
- package/src/shared/utils/networkUtils.ts +248 -0
- package/src/shared/utils/themeUtils.ts +115 -0
- package/src/types/bip39.d.ts +32 -0
- package/src/types/buffer.d.ts +97 -0
- package/src/types/color.d.ts +20 -0
- package/src/types/elliptic.d.ts +62 -0
- package/src/utils/apiUtils.ts +88 -0
- package/src/utils/asyncUtils.ts +252 -0
- package/src/utils/cache.ts +264 -0
- package/src/utils/deviceManager.ts +198 -0
- package/src/utils/errorUtils.ts +216 -0
- package/src/utils/index.ts +21 -0
- package/src/utils/languageUtils.ts +174 -0
- package/src/utils/loggerUtils.ts +153 -0
- package/src/utils/platform.ts +117 -0
- package/src/utils/requestUtils.ts +237 -0
- package/src/utils/sessionUtils.ts +206 -0
- package/src/utils/validationUtils.ts +174 -0
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
export function OxyServicesPrivacyMixin(Base) {
|
|
2
|
+
return class extends Base {
|
|
3
|
+
constructor(...args) {
|
|
4
|
+
super(...args);
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Extract user ID from blocked/restricted user object
|
|
8
|
+
*/
|
|
9
|
+
extractUserId(userIdField) {
|
|
10
|
+
return typeof userIdField === 'string' ? userIdField : userIdField._id;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Check if a user is in a list (blocked or restricted)
|
|
14
|
+
*/
|
|
15
|
+
async isUserInList(userId, getUserList, getIdField) {
|
|
16
|
+
try {
|
|
17
|
+
if (!userId) {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
const users = await getUserList();
|
|
21
|
+
return users.some(item => {
|
|
22
|
+
const itemId = this.extractUserId(getIdField(item));
|
|
23
|
+
return itemId === userId;
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
catch (error) {
|
|
27
|
+
// If there's an error, assume not in list to avoid breaking functionality
|
|
28
|
+
if (__DEV__) {
|
|
29
|
+
console.warn('Error checking user list:', error);
|
|
30
|
+
}
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
// ============================================================================
|
|
35
|
+
// BLOCKED USERS METHODS
|
|
36
|
+
// ============================================================================
|
|
37
|
+
/**
|
|
38
|
+
* Get list of blocked users
|
|
39
|
+
* @returns Array of blocked users
|
|
40
|
+
*/
|
|
41
|
+
async getBlockedUsers() {
|
|
42
|
+
try {
|
|
43
|
+
return await this.makeRequest('GET', '/api/privacy/blocked', undefined, {
|
|
44
|
+
cache: true,
|
|
45
|
+
cacheTTL: 1 * 60 * 1000, // 1 minute cache
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
throw this.handleError(error);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Block a user
|
|
54
|
+
* @param userId - The user ID to block
|
|
55
|
+
* @returns Success message
|
|
56
|
+
*/
|
|
57
|
+
async blockUser(userId) {
|
|
58
|
+
try {
|
|
59
|
+
if (!userId) {
|
|
60
|
+
throw new Error('User ID is required');
|
|
61
|
+
}
|
|
62
|
+
return await this.makeRequest('POST', `/api/privacy/blocked/${userId}`, undefined, {
|
|
63
|
+
cache: false,
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
throw this.handleError(error);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Unblock a user
|
|
72
|
+
* @param userId - The user ID to unblock
|
|
73
|
+
* @returns Success message
|
|
74
|
+
*/
|
|
75
|
+
async unblockUser(userId) {
|
|
76
|
+
try {
|
|
77
|
+
if (!userId) {
|
|
78
|
+
throw new Error('User ID is required');
|
|
79
|
+
}
|
|
80
|
+
return await this.makeRequest('DELETE', `/api/privacy/blocked/${userId}`, undefined, {
|
|
81
|
+
cache: false,
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
throw this.handleError(error);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Check if a user is blocked
|
|
90
|
+
* @param userId - The user ID to check
|
|
91
|
+
* @returns True if the user is blocked, false otherwise
|
|
92
|
+
*/
|
|
93
|
+
async isUserBlocked(userId) {
|
|
94
|
+
return this.isUserInList(userId, () => this.getBlockedUsers(), (block) => block.blockedId);
|
|
95
|
+
}
|
|
96
|
+
// ============================================================================
|
|
97
|
+
// RESTRICTED USERS METHODS
|
|
98
|
+
// ============================================================================
|
|
99
|
+
/**
|
|
100
|
+
* Get list of restricted users
|
|
101
|
+
* @returns Array of restricted users
|
|
102
|
+
*/
|
|
103
|
+
async getRestrictedUsers() {
|
|
104
|
+
try {
|
|
105
|
+
return await this.makeRequest('GET', '/api/privacy/restricted', undefined, {
|
|
106
|
+
cache: true,
|
|
107
|
+
cacheTTL: 1 * 60 * 1000, // 1 minute cache
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
throw this.handleError(error);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Restrict a user (limit their interactions without fully blocking)
|
|
116
|
+
* @param userId - The user ID to restrict
|
|
117
|
+
* @returns Success message
|
|
118
|
+
*/
|
|
119
|
+
async restrictUser(userId) {
|
|
120
|
+
try {
|
|
121
|
+
if (!userId) {
|
|
122
|
+
throw new Error('User ID is required');
|
|
123
|
+
}
|
|
124
|
+
return await this.makeRequest('POST', `/api/privacy/restricted/${userId}`, undefined, {
|
|
125
|
+
cache: false,
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
catch (error) {
|
|
129
|
+
throw this.handleError(error);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Unrestrict a user
|
|
134
|
+
* @param userId - The user ID to unrestrict
|
|
135
|
+
* @returns Success message
|
|
136
|
+
*/
|
|
137
|
+
async unrestrictUser(userId) {
|
|
138
|
+
try {
|
|
139
|
+
if (!userId) {
|
|
140
|
+
throw new Error('User ID is required');
|
|
141
|
+
}
|
|
142
|
+
return await this.makeRequest('DELETE', `/api/privacy/restricted/${userId}`, undefined, {
|
|
143
|
+
cache: false,
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
catch (error) {
|
|
147
|
+
throw this.handleError(error);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Check if a user is restricted
|
|
152
|
+
* @param userId - The user ID to check
|
|
153
|
+
* @returns True if the user is restricted, false otherwise
|
|
154
|
+
*/
|
|
155
|
+
async isUserRestricted(userId) {
|
|
156
|
+
return this.isUserInList(userId, () => this.getRestrictedUsers(), (restrict) => restrict.restrictedId);
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
}
|
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
import { OxyAuthenticationError } from '../OxyServices.errors';
|
|
2
|
+
/**
|
|
3
|
+
* Redirect-based Cross-Domain Authentication Mixin
|
|
4
|
+
*
|
|
5
|
+
* Implements traditional OAuth2 redirect flow as a fallback when popup or
|
|
6
|
+
* FedCM are not available or fail (e.g., mobile browsers, popup blockers).
|
|
7
|
+
*
|
|
8
|
+
* Flow:
|
|
9
|
+
* 1. Save current URL
|
|
10
|
+
* 2. Redirect to auth.oxy.so/login
|
|
11
|
+
* 3. User signs in
|
|
12
|
+
* 4. Redirect back with token in URL
|
|
13
|
+
* 5. Extract token, restore session, clean URL
|
|
14
|
+
*
|
|
15
|
+
* Features:
|
|
16
|
+
* - Works on all browsers (including old mobile browsers)
|
|
17
|
+
* - Automatic URL cleanup after auth
|
|
18
|
+
* - State preservation option
|
|
19
|
+
* - CSRF protection via state parameter
|
|
20
|
+
*
|
|
21
|
+
* Trade-offs:
|
|
22
|
+
* - Loses JavaScript app state (full page navigation)
|
|
23
|
+
* - Visible redirect (user sees navigation)
|
|
24
|
+
* - Slower perceived performance
|
|
25
|
+
*/
|
|
26
|
+
export function OxyServicesRedirectAuthMixin(Base) {
|
|
27
|
+
var _a;
|
|
28
|
+
return _a = class extends Base {
|
|
29
|
+
constructor(...args) {
|
|
30
|
+
super(...args);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Sign in using full page redirect
|
|
34
|
+
*
|
|
35
|
+
* Redirects the user to auth.oxy.so for authentication. After successful
|
|
36
|
+
* sign-in, the user will be redirected back to the current page (or custom
|
|
37
|
+
* redirect URI) with authentication tokens in the URL.
|
|
38
|
+
*
|
|
39
|
+
* Call handleAuthCallback() on app startup to complete the flow.
|
|
40
|
+
*
|
|
41
|
+
* @param options - Redirect configuration options
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```typescript
|
|
45
|
+
* // Initiate sign-in
|
|
46
|
+
* const handleSignIn = () => {
|
|
47
|
+
* oxyServices.signInWithRedirect();
|
|
48
|
+
* };
|
|
49
|
+
*
|
|
50
|
+
* // Handle callback on app startup
|
|
51
|
+
* useEffect(() => {
|
|
52
|
+
* const session = oxyServices.handleAuthCallback();
|
|
53
|
+
* if (session) {
|
|
54
|
+
* setUser(session.user);
|
|
55
|
+
* }
|
|
56
|
+
* }, []);
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
59
|
+
signInWithRedirect(options = {}) {
|
|
60
|
+
if (typeof window === 'undefined') {
|
|
61
|
+
throw new OxyAuthenticationError('Redirect authentication requires browser environment');
|
|
62
|
+
}
|
|
63
|
+
const redirectUri = options.redirectUri || window.location.href;
|
|
64
|
+
const mode = options.mode || 'login';
|
|
65
|
+
const state = this.generateState();
|
|
66
|
+
const nonce = this.generateNonce();
|
|
67
|
+
// Store state for CSRF protection
|
|
68
|
+
this.storeAuthState(state, nonce);
|
|
69
|
+
// Save current URL to restore after auth (optional)
|
|
70
|
+
if (options.preserveUrl !== false) {
|
|
71
|
+
this.savePreAuthUrl(window.location.href);
|
|
72
|
+
}
|
|
73
|
+
const authUrl = this.buildAuthUrl({
|
|
74
|
+
mode,
|
|
75
|
+
redirectUri,
|
|
76
|
+
state,
|
|
77
|
+
nonce,
|
|
78
|
+
clientId: window.location.origin,
|
|
79
|
+
});
|
|
80
|
+
// Perform redirect
|
|
81
|
+
window.location.href = authUrl;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Sign up using full page redirect
|
|
85
|
+
*
|
|
86
|
+
* Same as signInWithRedirect but opens the signup page by default.
|
|
87
|
+
*/
|
|
88
|
+
signUpWithRedirect(options = {}) {
|
|
89
|
+
this.signInWithRedirect({ ...options, mode: 'signup' });
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Handle authentication callback
|
|
93
|
+
*
|
|
94
|
+
* Call this on app startup to check if the current page load is a
|
|
95
|
+
* redirect back from the authentication server. If it is, this method
|
|
96
|
+
* will extract the tokens, store them, and clean up the URL.
|
|
97
|
+
*
|
|
98
|
+
* @returns Session data if this is a callback, null otherwise
|
|
99
|
+
* @throws {OxyAuthenticationError} If state validation fails (CSRF attack)
|
|
100
|
+
*
|
|
101
|
+
* @example
|
|
102
|
+
* ```typescript
|
|
103
|
+
* // In your app's root component or startup logic
|
|
104
|
+
* useEffect(() => {
|
|
105
|
+
* try {
|
|
106
|
+
* const session = oxyServices.handleAuthCallback();
|
|
107
|
+
* if (session) {
|
|
108
|
+
* console.log('Logged in:', session.user);
|
|
109
|
+
* setUser(session.user);
|
|
110
|
+
* } else {
|
|
111
|
+
* // Not a callback, check for existing session
|
|
112
|
+
* const restored = oxyServices.restoreSession();
|
|
113
|
+
* if (!restored) {
|
|
114
|
+
* // No session, show login button
|
|
115
|
+
* }
|
|
116
|
+
* }
|
|
117
|
+
* } catch (error) {
|
|
118
|
+
* console.error('Auth callback failed:', error);
|
|
119
|
+
* }
|
|
120
|
+
* }, []);
|
|
121
|
+
* ```
|
|
122
|
+
*/
|
|
123
|
+
handleAuthCallback() {
|
|
124
|
+
if (typeof window === 'undefined') {
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
const url = new URL(window.location.href);
|
|
128
|
+
const accessToken = url.searchParams.get('access_token');
|
|
129
|
+
const sessionId = url.searchParams.get('session_id');
|
|
130
|
+
const expiresAt = url.searchParams.get('expires_at');
|
|
131
|
+
const state = url.searchParams.get('state');
|
|
132
|
+
const error = url.searchParams.get('error');
|
|
133
|
+
const errorDescription = url.searchParams.get('error_description');
|
|
134
|
+
// Check if this is an error callback
|
|
135
|
+
if (error) {
|
|
136
|
+
this.clearAuthState();
|
|
137
|
+
throw new OxyAuthenticationError(errorDescription || error);
|
|
138
|
+
}
|
|
139
|
+
// Check if this is an auth callback
|
|
140
|
+
if (!accessToken || !sessionId) {
|
|
141
|
+
return null; // Not a callback
|
|
142
|
+
}
|
|
143
|
+
// Verify state to prevent CSRF attacks
|
|
144
|
+
const savedState = this.getStoredState();
|
|
145
|
+
if (!savedState || state !== savedState) {
|
|
146
|
+
this.clearAuthState();
|
|
147
|
+
throw new OxyAuthenticationError('Invalid state parameter. Possible CSRF attack.');
|
|
148
|
+
}
|
|
149
|
+
// Store tokens
|
|
150
|
+
this.storeTokens(accessToken, sessionId);
|
|
151
|
+
this.httpService.setTokens(accessToken);
|
|
152
|
+
// Build session response (minimal - we'll fetch full user data separately)
|
|
153
|
+
const session = {
|
|
154
|
+
sessionId,
|
|
155
|
+
deviceId: '', // Not available in redirect flow
|
|
156
|
+
expiresAt: expiresAt || new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString(),
|
|
157
|
+
user: {}, // Will be fetched separately
|
|
158
|
+
};
|
|
159
|
+
// Clean up URL (remove auth parameters)
|
|
160
|
+
this.cleanAuthCallbackUrl(url);
|
|
161
|
+
// Clean up storage
|
|
162
|
+
this.clearAuthState();
|
|
163
|
+
return session;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Restore session from storage
|
|
167
|
+
*
|
|
168
|
+
* Attempts to restore a previously authenticated session from localStorage.
|
|
169
|
+
* Call this on app startup if handleAuthCallback() returns null.
|
|
170
|
+
*
|
|
171
|
+
* @returns True if session was restored, false otherwise
|
|
172
|
+
*
|
|
173
|
+
* @example
|
|
174
|
+
* ```typescript
|
|
175
|
+
* useEffect(() => {
|
|
176
|
+
* const session = oxyServices.handleAuthCallback();
|
|
177
|
+
* if (!session) {
|
|
178
|
+
* const restored = oxyServices.restoreSession();
|
|
179
|
+
* if (!restored) {
|
|
180
|
+
* // No session, user needs to sign in
|
|
181
|
+
* setShowLogin(true);
|
|
182
|
+
* }
|
|
183
|
+
* }
|
|
184
|
+
* }, []);
|
|
185
|
+
* ```
|
|
186
|
+
*/
|
|
187
|
+
restoreSession() {
|
|
188
|
+
if (typeof window === 'undefined') {
|
|
189
|
+
return false;
|
|
190
|
+
}
|
|
191
|
+
const token = localStorage.getItem(this.constructor.TOKEN_STORAGE_KEY);
|
|
192
|
+
const sessionId = localStorage.getItem(this.constructor.SESSION_STORAGE_KEY);
|
|
193
|
+
if (token && sessionId) {
|
|
194
|
+
this.httpService.setTokens(token);
|
|
195
|
+
return true;
|
|
196
|
+
}
|
|
197
|
+
return false;
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Clear stored session
|
|
201
|
+
*
|
|
202
|
+
* Removes all authentication data from storage. Call this on logout.
|
|
203
|
+
*/
|
|
204
|
+
clearStoredSession() {
|
|
205
|
+
if (typeof window === 'undefined') {
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
localStorage.removeItem(this.constructor.TOKEN_STORAGE_KEY);
|
|
209
|
+
localStorage.removeItem(this.constructor.SESSION_STORAGE_KEY);
|
|
210
|
+
this.httpService.clearTokens();
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Get stored session ID
|
|
214
|
+
*/
|
|
215
|
+
getStoredSessionId() {
|
|
216
|
+
if (typeof window === 'undefined') {
|
|
217
|
+
return null;
|
|
218
|
+
}
|
|
219
|
+
return localStorage.getItem(this.constructor.SESSION_STORAGE_KEY);
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Build authentication URL with query parameters
|
|
223
|
+
*
|
|
224
|
+
* @private
|
|
225
|
+
*/
|
|
226
|
+
buildAuthUrl(params) {
|
|
227
|
+
const url = new URL(`${this.constructor.AUTH_URL}/${params.mode}`);
|
|
228
|
+
url.searchParams.set('redirect_uri', params.redirectUri);
|
|
229
|
+
url.searchParams.set('state', params.state);
|
|
230
|
+
url.searchParams.set('nonce', params.nonce);
|
|
231
|
+
url.searchParams.set('client_id', params.clientId);
|
|
232
|
+
url.searchParams.set('response_type', 'token');
|
|
233
|
+
return url.toString();
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Store tokens in localStorage
|
|
237
|
+
*
|
|
238
|
+
* @private
|
|
239
|
+
*/
|
|
240
|
+
storeTokens(accessToken, sessionId) {
|
|
241
|
+
if (typeof window === 'undefined') {
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
localStorage.setItem(this.constructor.TOKEN_STORAGE_KEY, accessToken);
|
|
245
|
+
localStorage.setItem(this.constructor.SESSION_STORAGE_KEY, sessionId);
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Generate cryptographically secure state for CSRF protection
|
|
249
|
+
*
|
|
250
|
+
* @private
|
|
251
|
+
*/
|
|
252
|
+
generateState() {
|
|
253
|
+
if (typeof window !== 'undefined' && window.crypto && window.crypto.randomUUID) {
|
|
254
|
+
return window.crypto.randomUUID();
|
|
255
|
+
}
|
|
256
|
+
return `${Date.now()}-${Math.random().toString(36).substring(2, 15)}`;
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Generate nonce for replay attack prevention
|
|
260
|
+
*
|
|
261
|
+
* @private
|
|
262
|
+
*/
|
|
263
|
+
generateNonce() {
|
|
264
|
+
if (typeof window !== 'undefined' && window.crypto && window.crypto.randomUUID) {
|
|
265
|
+
return window.crypto.randomUUID();
|
|
266
|
+
}
|
|
267
|
+
return `${Date.now()}-${Math.random().toString(36).substring(2, 15)}`;
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Store auth state in session storage
|
|
271
|
+
*
|
|
272
|
+
* @private
|
|
273
|
+
*/
|
|
274
|
+
storeAuthState(state, nonce) {
|
|
275
|
+
if (typeof window === 'undefined') {
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
sessionStorage.setItem(this.constructor.STATE_STORAGE_KEY, state);
|
|
279
|
+
sessionStorage.setItem(this.constructor.NONCE_STORAGE_KEY, nonce);
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Get stored state
|
|
283
|
+
*
|
|
284
|
+
* @private
|
|
285
|
+
*/
|
|
286
|
+
getStoredState() {
|
|
287
|
+
if (typeof window === 'undefined') {
|
|
288
|
+
return null;
|
|
289
|
+
}
|
|
290
|
+
return sessionStorage.getItem(this.constructor.STATE_STORAGE_KEY);
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Clear auth state from storage
|
|
294
|
+
*
|
|
295
|
+
* @private
|
|
296
|
+
*/
|
|
297
|
+
clearAuthState() {
|
|
298
|
+
if (typeof window === 'undefined') {
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
sessionStorage.removeItem(this.constructor.STATE_STORAGE_KEY);
|
|
302
|
+
sessionStorage.removeItem(this.constructor.NONCE_STORAGE_KEY);
|
|
303
|
+
sessionStorage.removeItem(this.constructor.PRE_AUTH_URL_KEY);
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Save pre-authentication URL to restore later
|
|
307
|
+
*
|
|
308
|
+
* @private
|
|
309
|
+
*/
|
|
310
|
+
savePreAuthUrl(url) {
|
|
311
|
+
if (typeof window === 'undefined') {
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
314
|
+
sessionStorage.setItem(this.constructor.PRE_AUTH_URL_KEY, url);
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* Clean authentication parameters from URL
|
|
318
|
+
*
|
|
319
|
+
* @private
|
|
320
|
+
*/
|
|
321
|
+
cleanAuthCallbackUrl(url) {
|
|
322
|
+
// Remove auth parameters
|
|
323
|
+
url.searchParams.delete('access_token');
|
|
324
|
+
url.searchParams.delete('session_id');
|
|
325
|
+
url.searchParams.delete('expires_at');
|
|
326
|
+
url.searchParams.delete('state');
|
|
327
|
+
url.searchParams.delete('nonce');
|
|
328
|
+
url.searchParams.delete('error');
|
|
329
|
+
url.searchParams.delete('error_description');
|
|
330
|
+
// Update URL without reloading page
|
|
331
|
+
window.history.replaceState({}, '', url.toString());
|
|
332
|
+
}
|
|
333
|
+
},
|
|
334
|
+
_a.AUTH_URL = 'https://auth.oxy.so',
|
|
335
|
+
_a.TOKEN_STORAGE_KEY = 'oxy_access_token',
|
|
336
|
+
_a.SESSION_STORAGE_KEY = 'oxy_session_id',
|
|
337
|
+
_a.STATE_STORAGE_KEY = 'oxy_auth_state',
|
|
338
|
+
_a.PRE_AUTH_URL_KEY = 'oxy_pre_auth_url',
|
|
339
|
+
_a.NONCE_STORAGE_KEY = 'oxy_auth_nonce',
|
|
340
|
+
_a;
|
|
341
|
+
}
|
|
342
|
+
// Export the mixin function as both named and default
|
|
343
|
+
export { OxyServicesRedirectAuthMixin as RedirectAuthMixin };
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
export function OxyServicesSecurityMixin(Base) {
|
|
2
|
+
return class extends Base {
|
|
3
|
+
constructor(...args) {
|
|
4
|
+
super(...args);
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Get user's security activity with pagination
|
|
8
|
+
* @param limit - Number of results (default: 50, max: 100)
|
|
9
|
+
* @param offset - Pagination offset (default: 0)
|
|
10
|
+
* @param eventType - Optional filter by event type
|
|
11
|
+
* @returns Security activity response with pagination
|
|
12
|
+
*/
|
|
13
|
+
async getSecurityActivity(limit, offset, eventType) {
|
|
14
|
+
try {
|
|
15
|
+
const params = {};
|
|
16
|
+
if (limit !== undefined)
|
|
17
|
+
params.limit = limit;
|
|
18
|
+
if (offset !== undefined)
|
|
19
|
+
params.offset = offset;
|
|
20
|
+
if (eventType)
|
|
21
|
+
params.eventType = eventType;
|
|
22
|
+
const response = await this.makeRequest('GET', '/api/security/activity', params, { cache: false });
|
|
23
|
+
return response;
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
throw this.handleError(error);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Get recent security activity (convenience method)
|
|
31
|
+
* @param limit - Number of recent events to fetch (default: 10)
|
|
32
|
+
* @returns Array of recent security activities
|
|
33
|
+
*/
|
|
34
|
+
async getRecentSecurityActivity(limit = 10) {
|
|
35
|
+
try {
|
|
36
|
+
const response = await this.getSecurityActivity(limit, 0);
|
|
37
|
+
return response.data || [];
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
throw this.handleError(error);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Log private key exported event
|
|
45
|
+
* @param deviceId - Optional device ID for tracking
|
|
46
|
+
* @returns Promise that resolves when event is logged
|
|
47
|
+
*/
|
|
48
|
+
async logPrivateKeyExported(deviceId) {
|
|
49
|
+
try {
|
|
50
|
+
await this.makeRequest('POST', '/api/security/activity/private-key-exported', { deviceId }, { cache: false });
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
// Don't throw - logging failures shouldn't break user flow
|
|
54
|
+
// But log for monitoring
|
|
55
|
+
if (__DEV__) {
|
|
56
|
+
console.warn('[OxyServices] Failed to log private key exported event:', error);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Log backup created event
|
|
62
|
+
* @param deviceId - Optional device ID for tracking
|
|
63
|
+
* @returns Promise that resolves when event is logged
|
|
64
|
+
*/
|
|
65
|
+
async logBackupCreated(deviceId) {
|
|
66
|
+
try {
|
|
67
|
+
await this.makeRequest('POST', '/api/security/activity/backup-created', { deviceId }, { cache: false });
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
// Don't throw - logging failures shouldn't break user flow
|
|
71
|
+
// But log for monitoring
|
|
72
|
+
if (__DEV__) {
|
|
73
|
+
console.warn('[OxyServices] Failed to log backup created event:', error);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
}
|