@oxyhq/services 5.16.13 → 5.16.15

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 (58) hide show
  1. package/lib/commonjs/core/mixins/OxyServices.security.js +54 -0
  2. package/lib/commonjs/core/mixins/OxyServices.security.js.map +1 -0
  3. package/lib/commonjs/core/mixins/index.js +3 -2
  4. package/lib/commonjs/core/mixins/index.js.map +1 -1
  5. package/lib/commonjs/index.js +14 -0
  6. package/lib/commonjs/index.js.map +1 -1
  7. package/lib/commonjs/ui/hooks/mutations/useAccountMutations.js +16 -2
  8. package/lib/commonjs/ui/hooks/mutations/useAccountMutations.js.map +1 -1
  9. package/lib/commonjs/ui/hooks/queries/index.js +13 -0
  10. package/lib/commonjs/ui/hooks/queries/index.js.map +1 -1
  11. package/lib/commonjs/ui/hooks/queries/queryKeys.js +6 -0
  12. package/lib/commonjs/ui/hooks/queries/queryKeys.js.map +1 -1
  13. package/lib/commonjs/ui/hooks/queries/useSecurityQueries.js +58 -0
  14. package/lib/commonjs/ui/hooks/queries/useSecurityQueries.js.map +1 -0
  15. package/lib/commonjs/ui/utils/avatarUtils.js +4 -0
  16. package/lib/commonjs/ui/utils/avatarUtils.js.map +1 -1
  17. package/lib/module/core/mixins/OxyServices.security.js +50 -0
  18. package/lib/module/core/mixins/OxyServices.security.js.map +1 -0
  19. package/lib/module/core/mixins/index.js +2 -1
  20. package/lib/module/core/mixins/index.js.map +1 -1
  21. package/lib/module/index.js +3 -1
  22. package/lib/module/index.js.map +1 -1
  23. package/lib/module/ui/hooks/mutations/useAccountMutations.js +16 -2
  24. package/lib/module/ui/hooks/mutations/useAccountMutations.js.map +1 -1
  25. package/lib/module/ui/hooks/queries/index.js +3 -0
  26. package/lib/module/ui/hooks/queries/index.js.map +1 -1
  27. package/lib/module/ui/hooks/queries/queryKeys.js +6 -0
  28. package/lib/module/ui/hooks/queries/queryKeys.js.map +1 -1
  29. package/lib/module/ui/hooks/queries/useSecurityQueries.js +52 -0
  30. package/lib/module/ui/hooks/queries/useSecurityQueries.js.map +1 -0
  31. package/lib/module/ui/utils/avatarUtils.js +4 -0
  32. package/lib/module/ui/utils/avatarUtils.js.map +1 -1
  33. package/lib/typescript/core/mixins/OxyServices.security.d.ts +67 -0
  34. package/lib/typescript/core/mixins/OxyServices.security.d.ts.map +1 -0
  35. package/lib/typescript/core/mixins/index.d.ts +48 -0
  36. package/lib/typescript/core/mixins/index.d.ts.map +1 -1
  37. package/lib/typescript/index.d.ts +2 -2
  38. package/lib/typescript/index.d.ts.map +1 -1
  39. package/lib/typescript/models/interfaces.d.ts +34 -0
  40. package/lib/typescript/models/interfaces.d.ts.map +1 -1
  41. package/lib/typescript/ui/hooks/mutations/useAccountMutations.d.ts.map +1 -1
  42. package/lib/typescript/ui/hooks/queries/index.d.ts +1 -0
  43. package/lib/typescript/ui/hooks/queries/index.d.ts.map +1 -1
  44. package/lib/typescript/ui/hooks/queries/queryKeys.d.ts +5 -0
  45. package/lib/typescript/ui/hooks/queries/queryKeys.d.ts.map +1 -1
  46. package/lib/typescript/ui/hooks/queries/useSecurityQueries.d.ts +15 -0
  47. package/lib/typescript/ui/hooks/queries/useSecurityQueries.d.ts.map +1 -0
  48. package/lib/typescript/ui/utils/avatarUtils.d.ts.map +1 -1
  49. package/package.json +2 -2
  50. package/src/core/mixins/OxyServices.security.ts +59 -0
  51. package/src/core/mixins/index.ts +14 -11
  52. package/src/index.ts +9 -1
  53. package/src/models/interfaces.ts +47 -0
  54. package/src/ui/hooks/mutations/useAccountMutations.ts +17 -2
  55. package/src/ui/hooks/queries/index.ts +6 -0
  56. package/src/ui/hooks/queries/queryKeys.ts +9 -0
  57. package/src/ui/hooks/queries/useSecurityQueries.ts +64 -0
  58. package/src/ui/utils/avatarUtils.ts +4 -0
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Security Methods Mixin
3
+ */
4
+ import type { OxyServicesBase } from '../OxyServices.base';
5
+ import type { SecurityActivity, SecurityActivityResponse, SecurityEventType } from '../../models/interfaces';
6
+
7
+ export function OxyServicesSecurityMixin<T extends typeof OxyServicesBase>(Base: T) {
8
+ return class extends Base {
9
+ constructor(...args: any[]) {
10
+ super(...(args as [any]));
11
+ }
12
+
13
+ /**
14
+ * Get user's security activity with pagination
15
+ * @param limit - Number of results (default: 50, max: 100)
16
+ * @param offset - Pagination offset (default: 0)
17
+ * @param eventType - Optional filter by event type
18
+ * @returns Security activity response with pagination
19
+ */
20
+ async getSecurityActivity(
21
+ limit?: number,
22
+ offset?: number,
23
+ eventType?: SecurityEventType
24
+ ): Promise<SecurityActivityResponse> {
25
+ try {
26
+ const params: any = {};
27
+ if (limit !== undefined) params.limit = limit;
28
+ if (offset !== undefined) params.offset = offset;
29
+ if (eventType) params.eventType = eventType;
30
+
31
+ const response = await this.makeRequest<SecurityActivityResponse>(
32
+ 'GET',
33
+ '/api/security/activity',
34
+ params,
35
+ { cache: false }
36
+ );
37
+
38
+ return response;
39
+ } catch (error) {
40
+ throw this.handleError(error);
41
+ }
42
+ }
43
+
44
+ /**
45
+ * Get recent security activity (convenience method)
46
+ * @param limit - Number of recent events to fetch (default: 10)
47
+ * @returns Array of recent security activities
48
+ */
49
+ async getRecentSecurityActivity(limit: number = 10): Promise<SecurityActivity[]> {
50
+ try {
51
+ const response = await this.getSecurityActivity(limit, 0);
52
+ return response.data || [];
53
+ } catch (error) {
54
+ throw this.handleError(error);
55
+ }
56
+ }
57
+ };
58
+ }
59
+
@@ -17,6 +17,7 @@ import { OxyServicesDeveloperMixin } from './OxyServices.developer';
17
17
  import { OxyServicesLocationMixin } from './OxyServices.location';
18
18
  import { OxyServicesAnalyticsMixin } from './OxyServices.analytics';
19
19
  import { OxyServicesDevicesMixin } from './OxyServices.devices';
20
+ import { OxyServicesSecurityMixin } from './OxyServices.security';
20
21
  import { OxyServicesUtilityMixin } from './OxyServices.utility';
21
22
 
22
23
  /**
@@ -29,17 +30,19 @@ import { OxyServicesUtilityMixin } from './OxyServices.utility';
29
30
  */
30
31
  export function composeOxyServices() {
31
32
  return OxyServicesUtilityMixin(
32
- OxyServicesDevicesMixin(
33
- OxyServicesAnalyticsMixin(
34
- OxyServicesLocationMixin(
35
- OxyServicesDeveloperMixin(
36
- OxyServicesAssetsMixin(
37
- OxyServicesKarmaMixin(
38
- OxyServicesPaymentMixin(
39
- OxyServicesLanguageMixin(
40
- OxyServicesPrivacyMixin(
41
- OxyServicesUserMixin(
42
- OxyServicesAuthMixin(OxyServicesBase)
33
+ OxyServicesSecurityMixin(
34
+ OxyServicesDevicesMixin(
35
+ OxyServicesAnalyticsMixin(
36
+ OxyServicesLocationMixin(
37
+ OxyServicesDeveloperMixin(
38
+ OxyServicesAssetsMixin(
39
+ OxyServicesKarmaMixin(
40
+ OxyServicesPaymentMixin(
41
+ OxyServicesLanguageMixin(
42
+ OxyServicesPrivacyMixin(
43
+ OxyServicesUserMixin(
44
+ OxyServicesAuthMixin(OxyServicesBase)
45
+ )
43
46
  )
44
47
  )
45
48
  )
package/src/index.ts CHANGED
@@ -103,7 +103,12 @@ export type {
103
103
  AssetUpdateVisibilityResponse,
104
104
  // Account storage usage
105
105
  AccountStorageCategoryUsage,
106
- AccountStorageUsageResponse
106
+ AccountStorageUsageResponse,
107
+ // Security activity
108
+ SecurityEventType,
109
+ SecurityEventSeverity,
110
+ SecurityActivity,
111
+ SecurityActivityResponse
107
112
  } from './models/interfaces';
108
113
 
109
114
  export type {
@@ -148,6 +153,9 @@ export {
148
153
  useDeviceSessions,
149
154
  useUserDevices,
150
155
  useSecurityInfo,
156
+ // Security activity queries
157
+ useSecurityActivity,
158
+ useRecentSecurityActivity,
151
159
  } from './ui/hooks/queries';
152
160
 
153
161
  // UI hooks - Mutation hooks (TanStack Query)
@@ -403,6 +403,53 @@ export interface AccountStorageUsageResponse {
403
403
  updatedAt: string;
404
404
  }
405
405
 
406
+ /**
407
+ * Security activity event types
408
+ */
409
+ export type SecurityEventType =
410
+ | 'sign_in'
411
+ | 'sign_out'
412
+ | 'email_changed'
413
+ | 'profile_updated'
414
+ | 'device_added'
415
+ | 'device_removed'
416
+ | 'account_recovery'
417
+ | 'security_settings_changed'
418
+ | 'suspicious_activity';
419
+
420
+ /**
421
+ * Security event severity levels
422
+ */
423
+ export type SecurityEventSeverity = 'low' | 'medium' | 'high' | 'critical';
424
+
425
+ /**
426
+ * Security activity event
427
+ */
428
+ export interface SecurityActivity {
429
+ id: string;
430
+ userId: string;
431
+ eventType: SecurityEventType;
432
+ eventDescription: string;
433
+ metadata?: Record<string, any>;
434
+ ipAddress?: string;
435
+ userAgent?: string;
436
+ deviceId?: string;
437
+ timestamp: string;
438
+ severity: SecurityEventSeverity;
439
+ createdAt: string;
440
+ }
441
+
442
+ /**
443
+ * Security activity response with pagination
444
+ */
445
+ export interface SecurityActivityResponse {
446
+ data: SecurityActivity[];
447
+ total: number;
448
+ limit: number;
449
+ offset: number;
450
+ hasMore: boolean;
451
+ }
452
+
406
453
  export interface AssetUploadProgress {
407
454
  fileId: string;
408
455
  uploaded: number;
@@ -4,6 +4,7 @@ import { queryKeys, invalidateAccountQueries, invalidateUserQueries } from '../q
4
4
  import { useOxy } from '../../context/OxyContext';
5
5
  import { toast } from '../../../lib/sonner';
6
6
  import { refreshAvatarInStore } from '../../utils/avatarUtils';
7
+ import { useAuthStore } from '../../stores/authStore';
7
8
 
8
9
  /**
9
10
  * Update user profile with optimistic updates and offline queue support
@@ -107,6 +108,9 @@ export const useUpdateProfile = () => {
107
108
  queryClient.setQueryData(queryKeys.users.profile(activeSessionId), data);
108
109
  }
109
110
 
111
+ // Update authStore so frontend components see the changes immediately
112
+ useAuthStore.getState().setUser(data);
113
+
110
114
  // If avatar was updated, refresh accountStore with cache-busted URL
111
115
  if (updates.avatar && activeSessionId && oxyServices) {
112
116
  refreshAvatarInStore(activeSessionId, updates.avatar, oxyServices);
@@ -220,6 +224,9 @@ export const useUploadAvatar = () => {
220
224
  queryClient.setQueryData(queryKeys.users.profile(activeSessionId), data);
221
225
  }
222
226
 
227
+ // Update authStore so frontend components see the changes immediately
228
+ useAuthStore.getState().setUser(data);
229
+
223
230
  // Refresh accountStore with cache-busted URL if avatar was updated
224
231
  if (data?.avatar && activeSessionId && oxyServices) {
225
232
  refreshAvatarInStore(activeSessionId, data.avatar, oxyServices);
@@ -268,6 +275,10 @@ export const useUpdateAccountSettings = () => {
268
275
  },
269
276
  onSuccess: (data) => {
270
277
  queryClient.setQueryData(queryKeys.accounts.current(), data);
278
+
279
+ // Update authStore so frontend components see the changes immediately
280
+ useAuthStore.getState().setUser(data);
281
+
271
282
  invalidateAccountQueries(queryClient);
272
283
  toast.success('Settings updated successfully');
273
284
  },
@@ -394,10 +405,14 @@ export const useUpdatePrivacySettings = () => {
394
405
  // Also update account query if it contains privacy settings
395
406
  const currentUser = queryClient.getQueryData<User>(queryKeys.accounts.current());
396
407
  if (currentUser) {
397
- queryClient.setQueryData<User>(queryKeys.accounts.current(), {
408
+ const updatedUser = {
398
409
  ...currentUser,
399
410
  privacySettings: data,
400
- });
411
+ };
412
+ queryClient.setQueryData<User>(queryKeys.accounts.current(), updatedUser);
413
+
414
+ // Update authStore so frontend components see the changes immediately
415
+ useAuthStore.getState().setUser(updatedUser);
401
416
  }
402
417
  invalidateAccountQueries(queryClient);
403
418
  },
@@ -25,6 +25,12 @@ export {
25
25
  useSecurityInfo,
26
26
  } from './useServicesQueries';
27
27
 
28
+ // Security activity query hooks
29
+ export {
30
+ useSecurityActivity,
31
+ useRecentSecurityActivity,
32
+ } from './useSecurityQueries';
33
+
28
34
  // Query keys and invalidation helpers (for advanced usage)
29
35
  export { queryKeys, invalidateAccountQueries, invalidateUserQueries, invalidateSessionQueries } from './queryKeys';
30
36
 
@@ -54,6 +54,15 @@ export const queryKeys = {
54
54
  all: ['privacy'] as const,
55
55
  settings: (userId?: string) => [...queryKeys.privacy.all, 'settings', userId || 'current'] as const,
56
56
  },
57
+
58
+ // Security activity queries
59
+ security: {
60
+ all: ['security'] as const,
61
+ activity: (limit?: number, offset?: number, eventType?: string) =>
62
+ [...queryKeys.security.all, 'activity', limit, offset, eventType] as const,
63
+ recent: (limit: number) =>
64
+ [...queryKeys.security.all, 'recent', limit] as const,
65
+ },
57
66
  } as const;
58
67
 
59
68
  /**
@@ -0,0 +1,64 @@
1
+ import { useQuery } from '@tanstack/react-query';
2
+ import { queryKeys } from './queryKeys';
3
+ import { useOxy } from '../../context/OxyContext';
4
+ import type { SecurityActivity, SecurityEventType } from '../../../models/interfaces';
5
+
6
+ /**
7
+ * Get user's security activity with pagination
8
+ */
9
+ export const useSecurityActivity = (
10
+ options?: {
11
+ limit?: number;
12
+ offset?: number;
13
+ eventType?: SecurityEventType;
14
+ enabled?: boolean;
15
+ }
16
+ ) => {
17
+ const { oxyServices, activeSessionId } = useOxy();
18
+
19
+ return useQuery({
20
+ queryKey: queryKeys.security.activity(
21
+ options?.limit,
22
+ options?.offset,
23
+ options?.eventType
24
+ ),
25
+ queryFn: async () => {
26
+ if (!activeSessionId) {
27
+ throw new Error('No active session');
28
+ }
29
+
30
+ const response = await oxyServices.getSecurityActivity(
31
+ options?.limit,
32
+ options?.offset,
33
+ options?.eventType
34
+ );
35
+
36
+ return response;
37
+ },
38
+ enabled: (options?.enabled !== false) && !!activeSessionId,
39
+ staleTime: 5 * 60 * 1000, // 5 minutes
40
+ gcTime: 10 * 60 * 1000, // 10 minutes
41
+ });
42
+ };
43
+
44
+ /**
45
+ * Get recent security activity (convenience hook)
46
+ */
47
+ export const useRecentSecurityActivity = (limit: number = 10) => {
48
+ const { oxyServices, activeSessionId } = useOxy();
49
+
50
+ return useQuery<SecurityActivity[]>({
51
+ queryKey: queryKeys.security.recent(limit),
52
+ queryFn: async () => {
53
+ if (!activeSessionId) {
54
+ throw new Error('No active session');
55
+ }
56
+
57
+ return await oxyServices.getRecentSecurityActivity(limit);
58
+ },
59
+ enabled: !!activeSessionId,
60
+ staleTime: 5 * 60 * 1000, // 5 minutes
61
+ gcTime: 10 * 60 * 1000, // 10 minutes
62
+ });
63
+ };
64
+
@@ -1,6 +1,7 @@
1
1
  import type { OxyServices } from '../../core';
2
2
  import type { User } from '../../models/interfaces';
3
3
  import { useAccountStore } from '../stores/accountStore';
4
+ import { useAuthStore } from '../stores/authStore';
4
5
  import { QueryClient } from '@tanstack/react-query';
5
6
  import { queryKeys, invalidateUserQueries, invalidateAccountQueries } from '../hooks/queries/queryKeys';
6
7
 
@@ -103,6 +104,9 @@ export async function updateProfileWithAvatar(
103
104
  queryClient.setQueryData(queryKeys.users.profile(activeSessionId), data);
104
105
  }
105
106
 
107
+ // Update authStore so frontend components see the changes immediately
108
+ useAuthStore.getState().setUser(data);
109
+
106
110
  // If avatar was updated, refresh accountStore with cache-busted URL
107
111
  if (updates.avatar && activeSessionId) {
108
112
  refreshAvatarInStore(activeSessionId, updates.avatar, oxyServices);