@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.
Files changed (277) hide show
  1. package/README.md +50 -0
  2. package/dist/cjs/AuthManager.js +361 -0
  3. package/dist/cjs/CrossDomainAuth.js +258 -0
  4. package/dist/cjs/HttpService.js +618 -0
  5. package/dist/cjs/OxyServices.base.js +263 -0
  6. package/dist/cjs/OxyServices.errors.js +22 -0
  7. package/dist/cjs/OxyServices.js +63 -0
  8. package/dist/cjs/constants/version.js +16 -0
  9. package/dist/cjs/crypto/index.js +20 -0
  10. package/dist/cjs/crypto/keyManager.js +887 -0
  11. package/dist/cjs/crypto/polyfill.js +64 -0
  12. package/dist/cjs/crypto/recoveryPhrase.js +169 -0
  13. package/dist/cjs/crypto/signatureService.js +296 -0
  14. package/dist/cjs/i18n/index.js +73 -0
  15. package/dist/cjs/i18n/locales/ar-SA.json +120 -0
  16. package/dist/cjs/i18n/locales/ca-ES.json +120 -0
  17. package/dist/cjs/i18n/locales/de-DE.json +120 -0
  18. package/dist/cjs/i18n/locales/en-US.json +956 -0
  19. package/dist/cjs/i18n/locales/es-ES.json +944 -0
  20. package/dist/cjs/i18n/locales/fr-FR.json +120 -0
  21. package/dist/cjs/i18n/locales/it-IT.json +120 -0
  22. package/dist/cjs/i18n/locales/ja-JP.json +119 -0
  23. package/dist/cjs/i18n/locales/ko-KR.json +120 -0
  24. package/dist/cjs/i18n/locales/locales/ar-SA.json +120 -0
  25. package/dist/cjs/i18n/locales/locales/ca-ES.json +120 -0
  26. package/dist/cjs/i18n/locales/locales/de-DE.json +120 -0
  27. package/dist/cjs/i18n/locales/locales/en-US.json +956 -0
  28. package/dist/cjs/i18n/locales/locales/es-ES.json +944 -0
  29. package/dist/cjs/i18n/locales/locales/fr-FR.json +120 -0
  30. package/dist/cjs/i18n/locales/locales/it-IT.json +120 -0
  31. package/dist/cjs/i18n/locales/locales/ja-JP.json +119 -0
  32. package/dist/cjs/i18n/locales/locales/ko-KR.json +120 -0
  33. package/dist/cjs/i18n/locales/locales/pt-PT.json +120 -0
  34. package/dist/cjs/i18n/locales/locales/zh-CN.json +120 -0
  35. package/dist/cjs/i18n/locales/pt-PT.json +120 -0
  36. package/dist/cjs/i18n/locales/zh-CN.json +120 -0
  37. package/dist/cjs/index.js +153 -0
  38. package/dist/cjs/mixins/OxyServices.analytics.js +49 -0
  39. package/dist/cjs/mixins/OxyServices.assets.js +380 -0
  40. package/dist/cjs/mixins/OxyServices.auth.js +259 -0
  41. package/dist/cjs/mixins/OxyServices.developer.js +97 -0
  42. package/dist/cjs/mixins/OxyServices.devices.js +116 -0
  43. package/dist/cjs/mixins/OxyServices.features.js +309 -0
  44. package/dist/cjs/mixins/OxyServices.fedcm.js +435 -0
  45. package/dist/cjs/mixins/OxyServices.karma.js +108 -0
  46. package/dist/cjs/mixins/OxyServices.language.js +154 -0
  47. package/dist/cjs/mixins/OxyServices.location.js +43 -0
  48. package/dist/cjs/mixins/OxyServices.payment.js +158 -0
  49. package/dist/cjs/mixins/OxyServices.popup.js +371 -0
  50. package/dist/cjs/mixins/OxyServices.privacy.js +162 -0
  51. package/dist/cjs/mixins/OxyServices.redirect.js +345 -0
  52. package/dist/cjs/mixins/OxyServices.security.js +81 -0
  53. package/dist/cjs/mixins/OxyServices.user.js +355 -0
  54. package/dist/cjs/mixins/OxyServices.utility.js +156 -0
  55. package/dist/cjs/mixins/index.js +79 -0
  56. package/dist/cjs/mixins/mixinHelpers.js +53 -0
  57. package/dist/cjs/models/interfaces.js +20 -0
  58. package/dist/cjs/models/session.js +2 -0
  59. package/dist/cjs/shared/index.js +70 -0
  60. package/dist/cjs/shared/utils/colorUtils.js +153 -0
  61. package/dist/cjs/shared/utils/debugUtils.js +73 -0
  62. package/dist/cjs/shared/utils/errorUtils.js +183 -0
  63. package/dist/cjs/shared/utils/index.js +49 -0
  64. package/dist/cjs/shared/utils/networkUtils.js +183 -0
  65. package/dist/cjs/shared/utils/themeUtils.js +106 -0
  66. package/dist/cjs/utils/apiUtils.js +61 -0
  67. package/dist/cjs/utils/asyncUtils.js +194 -0
  68. package/dist/cjs/utils/cache.js +226 -0
  69. package/dist/cjs/utils/deviceManager.js +205 -0
  70. package/dist/cjs/utils/errorUtils.js +154 -0
  71. package/dist/cjs/utils/index.js +26 -0
  72. package/dist/cjs/utils/languageUtils.js +165 -0
  73. package/dist/cjs/utils/loggerUtils.js +126 -0
  74. package/dist/cjs/utils/platform.js +144 -0
  75. package/dist/cjs/utils/requestUtils.js +209 -0
  76. package/dist/cjs/utils/sessionUtils.js +181 -0
  77. package/dist/cjs/utils/validationUtils.js +173 -0
  78. package/dist/esm/AuthManager.js +356 -0
  79. package/dist/esm/CrossDomainAuth.js +253 -0
  80. package/dist/esm/HttpService.js +614 -0
  81. package/dist/esm/OxyServices.base.js +259 -0
  82. package/dist/esm/OxyServices.errors.js +17 -0
  83. package/dist/esm/OxyServices.js +59 -0
  84. package/dist/esm/constants/version.js +13 -0
  85. package/dist/esm/crypto/index.js +13 -0
  86. package/dist/esm/crypto/keyManager.js +850 -0
  87. package/dist/esm/crypto/polyfill.js +61 -0
  88. package/dist/esm/crypto/recoveryPhrase.js +132 -0
  89. package/dist/esm/crypto/signatureService.js +259 -0
  90. package/dist/esm/i18n/index.js +69 -0
  91. package/dist/esm/i18n/locales/ar-SA.json +120 -0
  92. package/dist/esm/i18n/locales/ca-ES.json +120 -0
  93. package/dist/esm/i18n/locales/de-DE.json +120 -0
  94. package/dist/esm/i18n/locales/en-US.json +956 -0
  95. package/dist/esm/i18n/locales/es-ES.json +944 -0
  96. package/dist/esm/i18n/locales/fr-FR.json +120 -0
  97. package/dist/esm/i18n/locales/it-IT.json +120 -0
  98. package/dist/esm/i18n/locales/ja-JP.json +119 -0
  99. package/dist/esm/i18n/locales/ko-KR.json +120 -0
  100. package/dist/esm/i18n/locales/locales/ar-SA.json +120 -0
  101. package/dist/esm/i18n/locales/locales/ca-ES.json +120 -0
  102. package/dist/esm/i18n/locales/locales/de-DE.json +120 -0
  103. package/dist/esm/i18n/locales/locales/en-US.json +956 -0
  104. package/dist/esm/i18n/locales/locales/es-ES.json +944 -0
  105. package/dist/esm/i18n/locales/locales/fr-FR.json +120 -0
  106. package/dist/esm/i18n/locales/locales/it-IT.json +120 -0
  107. package/dist/esm/i18n/locales/locales/ja-JP.json +119 -0
  108. package/dist/esm/i18n/locales/locales/ko-KR.json +120 -0
  109. package/dist/esm/i18n/locales/locales/pt-PT.json +120 -0
  110. package/dist/esm/i18n/locales/locales/zh-CN.json +120 -0
  111. package/dist/esm/i18n/locales/pt-PT.json +120 -0
  112. package/dist/esm/i18n/locales/zh-CN.json +120 -0
  113. package/dist/esm/index.js +55 -0
  114. package/dist/esm/mixins/OxyServices.analytics.js +46 -0
  115. package/dist/esm/mixins/OxyServices.assets.js +377 -0
  116. package/dist/esm/mixins/OxyServices.auth.js +256 -0
  117. package/dist/esm/mixins/OxyServices.developer.js +94 -0
  118. package/dist/esm/mixins/OxyServices.devices.js +113 -0
  119. package/dist/esm/mixins/OxyServices.features.js +306 -0
  120. package/dist/esm/mixins/OxyServices.fedcm.js +433 -0
  121. package/dist/esm/mixins/OxyServices.karma.js +105 -0
  122. package/dist/esm/mixins/OxyServices.language.js +118 -0
  123. package/dist/esm/mixins/OxyServices.location.js +40 -0
  124. package/dist/esm/mixins/OxyServices.payment.js +155 -0
  125. package/dist/esm/mixins/OxyServices.popup.js +369 -0
  126. package/dist/esm/mixins/OxyServices.privacy.js +159 -0
  127. package/dist/esm/mixins/OxyServices.redirect.js +343 -0
  128. package/dist/esm/mixins/OxyServices.security.js +78 -0
  129. package/dist/esm/mixins/OxyServices.user.js +352 -0
  130. package/dist/esm/mixins/OxyServices.utility.js +153 -0
  131. package/dist/esm/mixins/index.js +76 -0
  132. package/dist/esm/mixins/mixinHelpers.js +48 -0
  133. package/dist/esm/models/interfaces.js +17 -0
  134. package/dist/esm/models/session.js +1 -0
  135. package/dist/esm/shared/index.js +31 -0
  136. package/dist/esm/shared/utils/colorUtils.js +143 -0
  137. package/dist/esm/shared/utils/debugUtils.js +65 -0
  138. package/dist/esm/shared/utils/errorUtils.js +170 -0
  139. package/dist/esm/shared/utils/index.js +15 -0
  140. package/dist/esm/shared/utils/networkUtils.js +173 -0
  141. package/dist/esm/shared/utils/themeUtils.js +98 -0
  142. package/dist/esm/utils/apiUtils.js +55 -0
  143. package/dist/esm/utils/asyncUtils.js +179 -0
  144. package/dist/esm/utils/cache.js +218 -0
  145. package/dist/esm/utils/deviceManager.js +168 -0
  146. package/dist/esm/utils/errorUtils.js +146 -0
  147. package/dist/esm/utils/index.js +7 -0
  148. package/dist/esm/utils/languageUtils.js +158 -0
  149. package/dist/esm/utils/loggerUtils.js +115 -0
  150. package/dist/esm/utils/platform.js +102 -0
  151. package/dist/esm/utils/requestUtils.js +203 -0
  152. package/dist/esm/utils/sessionUtils.js +171 -0
  153. package/dist/esm/utils/validationUtils.js +153 -0
  154. package/dist/types/AuthManager.d.ts +143 -0
  155. package/dist/types/CrossDomainAuth.d.ts +160 -0
  156. package/dist/types/HttpService.d.ts +163 -0
  157. package/dist/types/OxyServices.base.d.ts +126 -0
  158. package/dist/types/OxyServices.d.ts +81 -0
  159. package/dist/types/OxyServices.errors.d.ts +11 -0
  160. package/dist/types/constants/version.d.ts +13 -0
  161. package/dist/types/crypto/index.d.ts +11 -0
  162. package/dist/types/crypto/keyManager.d.ts +189 -0
  163. package/dist/types/crypto/polyfill.d.ts +11 -0
  164. package/dist/types/crypto/recoveryPhrase.d.ts +58 -0
  165. package/dist/types/crypto/signatureService.d.ts +86 -0
  166. package/dist/types/i18n/index.d.ts +3 -0
  167. package/dist/types/index.d.ts +50 -0
  168. package/dist/types/mixins/OxyServices.analytics.d.ts +66 -0
  169. package/dist/types/mixins/OxyServices.assets.d.ts +135 -0
  170. package/dist/types/mixins/OxyServices.auth.d.ts +186 -0
  171. package/dist/types/mixins/OxyServices.developer.d.ts +99 -0
  172. package/dist/types/mixins/OxyServices.devices.d.ts +96 -0
  173. package/dist/types/mixins/OxyServices.features.d.ts +228 -0
  174. package/dist/types/mixins/OxyServices.fedcm.d.ts +200 -0
  175. package/dist/types/mixins/OxyServices.karma.d.ts +85 -0
  176. package/dist/types/mixins/OxyServices.language.d.ts +81 -0
  177. package/dist/types/mixins/OxyServices.location.d.ts +64 -0
  178. package/dist/types/mixins/OxyServices.payment.d.ts +111 -0
  179. package/dist/types/mixins/OxyServices.popup.d.ts +205 -0
  180. package/dist/types/mixins/OxyServices.privacy.d.ts +122 -0
  181. package/dist/types/mixins/OxyServices.redirect.d.ts +245 -0
  182. package/dist/types/mixins/OxyServices.security.d.ts +78 -0
  183. package/dist/types/mixins/OxyServices.user.d.ts +182 -0
  184. package/dist/types/mixins/OxyServices.utility.d.ts +93 -0
  185. package/dist/types/mixins/index.d.ts +30 -0
  186. package/dist/types/mixins/mixinHelpers.d.ts +31 -0
  187. package/dist/types/models/interfaces.d.ts +415 -0
  188. package/dist/types/models/session.d.ts +27 -0
  189. package/dist/types/shared/index.d.ts +28 -0
  190. package/dist/types/shared/utils/colorUtils.d.ts +104 -0
  191. package/dist/types/shared/utils/debugUtils.d.ts +48 -0
  192. package/dist/types/shared/utils/errorUtils.d.ts +97 -0
  193. package/dist/types/shared/utils/index.d.ts +13 -0
  194. package/dist/types/shared/utils/networkUtils.d.ts +139 -0
  195. package/dist/types/shared/utils/themeUtils.d.ts +90 -0
  196. package/dist/types/utils/apiUtils.d.ts +53 -0
  197. package/dist/types/utils/asyncUtils.d.ts +58 -0
  198. package/dist/types/utils/cache.d.ts +127 -0
  199. package/dist/types/utils/deviceManager.d.ts +65 -0
  200. package/dist/types/utils/errorUtils.d.ts +46 -0
  201. package/dist/types/utils/index.d.ts +6 -0
  202. package/dist/types/utils/languageUtils.d.ts +37 -0
  203. package/dist/types/utils/loggerUtils.d.ts +48 -0
  204. package/dist/types/utils/platform.d.ts +40 -0
  205. package/dist/types/utils/requestUtils.d.ts +123 -0
  206. package/dist/types/utils/sessionUtils.d.ts +54 -0
  207. package/dist/types/utils/validationUtils.d.ts +85 -0
  208. package/package.json +84 -0
  209. package/src/AuthManager.ts +436 -0
  210. package/src/CrossDomainAuth.ts +307 -0
  211. package/src/HttpService.ts +752 -0
  212. package/src/OxyServices.base.ts +334 -0
  213. package/src/OxyServices.errors.ts +26 -0
  214. package/src/OxyServices.ts +129 -0
  215. package/src/constants/version.ts +15 -0
  216. package/src/crypto/index.ts +25 -0
  217. package/src/crypto/keyManager.ts +962 -0
  218. package/src/crypto/polyfill.ts +70 -0
  219. package/src/crypto/recoveryPhrase.ts +166 -0
  220. package/src/crypto/signatureService.ts +323 -0
  221. package/src/i18n/index.ts +75 -0
  222. package/src/i18n/locales/ar-SA.json +120 -0
  223. package/src/i18n/locales/ca-ES.json +120 -0
  224. package/src/i18n/locales/de-DE.json +120 -0
  225. package/src/i18n/locales/en-US.json +956 -0
  226. package/src/i18n/locales/es-ES.json +944 -0
  227. package/src/i18n/locales/fr-FR.json +120 -0
  228. package/src/i18n/locales/it-IT.json +120 -0
  229. package/src/i18n/locales/ja-JP.json +119 -0
  230. package/src/i18n/locales/ko-KR.json +120 -0
  231. package/src/i18n/locales/pt-PT.json +120 -0
  232. package/src/i18n/locales/zh-CN.json +120 -0
  233. package/src/index.ts +153 -0
  234. package/src/mixins/OxyServices.analytics.ts +53 -0
  235. package/src/mixins/OxyServices.assets.ts +412 -0
  236. package/src/mixins/OxyServices.auth.ts +358 -0
  237. package/src/mixins/OxyServices.developer.ts +114 -0
  238. package/src/mixins/OxyServices.devices.ts +119 -0
  239. package/src/mixins/OxyServices.features.ts +428 -0
  240. package/src/mixins/OxyServices.fedcm.ts +494 -0
  241. package/src/mixins/OxyServices.karma.ts +111 -0
  242. package/src/mixins/OxyServices.language.ts +127 -0
  243. package/src/mixins/OxyServices.location.ts +46 -0
  244. package/src/mixins/OxyServices.payment.ts +163 -0
  245. package/src/mixins/OxyServices.popup.ts +443 -0
  246. package/src/mixins/OxyServices.privacy.ts +182 -0
  247. package/src/mixins/OxyServices.redirect.ts +397 -0
  248. package/src/mixins/OxyServices.security.ts +103 -0
  249. package/src/mixins/OxyServices.user.ts +392 -0
  250. package/src/mixins/OxyServices.utility.ts +191 -0
  251. package/src/mixins/index.ts +91 -0
  252. package/src/mixins/mixinHelpers.ts +69 -0
  253. package/src/models/interfaces.ts +511 -0
  254. package/src/models/session.ts +30 -0
  255. package/src/shared/index.ts +82 -0
  256. package/src/shared/utils/colorUtils.ts +155 -0
  257. package/src/shared/utils/debugUtils.ts +73 -0
  258. package/src/shared/utils/errorUtils.ts +181 -0
  259. package/src/shared/utils/index.ts +59 -0
  260. package/src/shared/utils/networkUtils.ts +248 -0
  261. package/src/shared/utils/themeUtils.ts +115 -0
  262. package/src/types/bip39.d.ts +32 -0
  263. package/src/types/buffer.d.ts +97 -0
  264. package/src/types/color.d.ts +20 -0
  265. package/src/types/elliptic.d.ts +62 -0
  266. package/src/utils/apiUtils.ts +88 -0
  267. package/src/utils/asyncUtils.ts +252 -0
  268. package/src/utils/cache.ts +264 -0
  269. package/src/utils/deviceManager.ts +198 -0
  270. package/src/utils/errorUtils.ts +216 -0
  271. package/src/utils/index.ts +21 -0
  272. package/src/utils/languageUtils.ts +174 -0
  273. package/src/utils/loggerUtils.ts +153 -0
  274. package/src/utils/platform.ts +117 -0
  275. package/src/utils/requestUtils.ts +237 -0
  276. package/src/utils/sessionUtils.ts +206 -0
  277. 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
+ }