@oxyhq/services 5.8.1 → 5.8.2

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 (137) hide show
  1. package/lib/commonjs/index.js +9 -27
  2. package/lib/commonjs/index.js.map +1 -1
  3. package/lib/commonjs/node/createAuth.js +7 -585
  4. package/lib/commonjs/node/createAuth.js.map +1 -1
  5. package/lib/commonjs/node/index.js +1 -38
  6. package/lib/commonjs/node/index.js.map +1 -1
  7. package/lib/commonjs/ui/components/FollowButton.js +100 -12
  8. package/lib/commonjs/ui/components/FollowButton.js.map +1 -1
  9. package/lib/commonjs/ui/components/Header.js +40 -6
  10. package/lib/commonjs/ui/components/Header.js.map +1 -1
  11. package/lib/commonjs/ui/components/OxyProvider.js +5 -0
  12. package/lib/commonjs/ui/components/OxyProvider.js.map +1 -1
  13. package/lib/commonjs/ui/context/OxyContext.js +63 -125
  14. package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
  15. package/lib/commonjs/ui/hooks/index.js +6 -0
  16. package/lib/commonjs/ui/hooks/index.js.map +1 -1
  17. package/lib/commonjs/ui/hooks/useFollow.js +59 -2
  18. package/lib/commonjs/ui/hooks/useFollow.js.map +1 -1
  19. package/lib/commonjs/ui/navigation/OxyRouter.js +10 -0
  20. package/lib/commonjs/ui/navigation/OxyRouter.js.map +1 -1
  21. package/lib/commonjs/ui/screens/AccountSettingsScreen.js +9 -0
  22. package/lib/commonjs/ui/screens/AccountSettingsScreen.js.map +1 -1
  23. package/lib/commonjs/ui/screens/ProfileScreen.js +214 -37
  24. package/lib/commonjs/ui/screens/ProfileScreen.js.map +1 -1
  25. package/lib/commonjs/ui/screens/UserLinksScreen.js +90 -0
  26. package/lib/commonjs/ui/screens/UserLinksScreen.js.map +1 -0
  27. package/lib/commonjs/ui/screens/karma/KarmaAboutScreen.js +9 -6
  28. package/lib/commonjs/ui/screens/karma/KarmaAboutScreen.js.map +1 -1
  29. package/lib/commonjs/ui/screens/karma/KarmaCenterScreen.js +3 -30
  30. package/lib/commonjs/ui/screens/karma/KarmaCenterScreen.js.map +1 -1
  31. package/lib/commonjs/ui/screens/karma/KarmaFAQScreen.js +37 -46
  32. package/lib/commonjs/ui/screens/karma/KarmaFAQScreen.js.map +1 -1
  33. package/lib/commonjs/ui/screens/karma/KarmaLeaderboardScreen.js +9 -12
  34. package/lib/commonjs/ui/screens/karma/KarmaLeaderboardScreen.js.map +1 -1
  35. package/lib/commonjs/ui/screens/karma/KarmaRewardsScreen.js +9 -12
  36. package/lib/commonjs/ui/screens/karma/KarmaRewardsScreen.js.map +1 -1
  37. package/lib/commonjs/ui/screens/karma/KarmaRulesScreen.js +9 -12
  38. package/lib/commonjs/ui/screens/karma/KarmaRulesScreen.js.map +1 -1
  39. package/lib/commonjs/ui/stores/authStore.js +24 -6
  40. package/lib/commonjs/ui/stores/authStore.js.map +1 -1
  41. package/lib/commonjs/ui/stores/followStore.js +106 -1
  42. package/lib/commonjs/ui/stores/followStore.js.map +1 -1
  43. package/lib/module/index.js +1 -3
  44. package/lib/module/index.js.map +1 -1
  45. package/lib/module/node/createAuth.js +7 -584
  46. package/lib/module/node/createAuth.js.map +1 -1
  47. package/lib/module/node/index.js +1 -7
  48. package/lib/module/node/index.js.map +1 -1
  49. package/lib/module/ui/components/FollowButton.js +101 -13
  50. package/lib/module/ui/components/FollowButton.js.map +1 -1
  51. package/lib/module/ui/components/Header.js +40 -6
  52. package/lib/module/ui/components/Header.js.map +1 -1
  53. package/lib/module/ui/components/OxyProvider.js +5 -0
  54. package/lib/module/ui/components/OxyProvider.js.map +1 -1
  55. package/lib/module/ui/context/OxyContext.js +63 -125
  56. package/lib/module/ui/context/OxyContext.js.map +1 -1
  57. package/lib/module/ui/hooks/index.js +1 -1
  58. package/lib/module/ui/hooks/index.js.map +1 -1
  59. package/lib/module/ui/hooks/useFollow.js +57 -1
  60. package/lib/module/ui/hooks/useFollow.js.map +1 -1
  61. package/lib/module/ui/navigation/OxyRouter.js +10 -0
  62. package/lib/module/ui/navigation/OxyRouter.js.map +1 -1
  63. package/lib/module/ui/screens/AccountSettingsScreen.js +9 -0
  64. package/lib/module/ui/screens/AccountSettingsScreen.js.map +1 -1
  65. package/lib/module/ui/screens/ProfileScreen.js +214 -37
  66. package/lib/module/ui/screens/ProfileScreen.js.map +1 -1
  67. package/lib/module/ui/screens/UserLinksScreen.js +85 -0
  68. package/lib/module/ui/screens/UserLinksScreen.js.map +1 -0
  69. package/lib/module/ui/screens/karma/KarmaAboutScreen.js +9 -6
  70. package/lib/module/ui/screens/karma/KarmaAboutScreen.js.map +1 -1
  71. package/lib/module/ui/screens/karma/KarmaCenterScreen.js +3 -30
  72. package/lib/module/ui/screens/karma/KarmaCenterScreen.js.map +1 -1
  73. package/lib/module/ui/screens/karma/KarmaFAQScreen.js +37 -46
  74. package/lib/module/ui/screens/karma/KarmaFAQScreen.js.map +1 -1
  75. package/lib/module/ui/screens/karma/KarmaLeaderboardScreen.js +9 -12
  76. package/lib/module/ui/screens/karma/KarmaLeaderboardScreen.js.map +1 -1
  77. package/lib/module/ui/screens/karma/KarmaRewardsScreen.js +9 -12
  78. package/lib/module/ui/screens/karma/KarmaRewardsScreen.js.map +1 -1
  79. package/lib/module/ui/screens/karma/KarmaRulesScreen.js +9 -12
  80. package/lib/module/ui/screens/karma/KarmaRulesScreen.js.map +1 -1
  81. package/lib/module/ui/stores/authStore.js +24 -6
  82. package/lib/module/ui/stores/authStore.js.map +1 -1
  83. package/lib/module/ui/stores/followStore.js +106 -1
  84. package/lib/module/ui/stores/followStore.js.map +1 -1
  85. package/lib/typescript/index.d.ts +1 -1
  86. package/lib/typescript/index.d.ts.map +1 -1
  87. package/lib/typescript/node/createAuth.d.ts +0 -112
  88. package/lib/typescript/node/createAuth.d.ts.map +1 -1
  89. package/lib/typescript/node/index.d.ts +0 -2
  90. package/lib/typescript/node/index.d.ts.map +1 -1
  91. package/lib/typescript/ui/components/FollowButton.d.ts +1 -0
  92. package/lib/typescript/ui/components/FollowButton.d.ts.map +1 -1
  93. package/lib/typescript/ui/components/Header.d.ts +2 -0
  94. package/lib/typescript/ui/components/Header.d.ts.map +1 -1
  95. package/lib/typescript/ui/components/OxyProvider.d.ts.map +1 -1
  96. package/lib/typescript/ui/context/OxyContext.d.ts.map +1 -1
  97. package/lib/typescript/ui/hooks/index.d.ts +1 -1
  98. package/lib/typescript/ui/hooks/index.d.ts.map +1 -1
  99. package/lib/typescript/ui/hooks/useFollow.d.ts +20 -0
  100. package/lib/typescript/ui/hooks/useFollow.d.ts.map +1 -1
  101. package/lib/typescript/ui/navigation/OxyRouter.d.ts.map +1 -1
  102. package/lib/typescript/ui/screens/AccountSettingsScreen.d.ts.map +1 -1
  103. package/lib/typescript/ui/screens/ProfileScreen.d.ts.map +1 -1
  104. package/lib/typescript/ui/screens/UserLinksScreen.d.ts +15 -0
  105. package/lib/typescript/ui/screens/UserLinksScreen.d.ts.map +1 -0
  106. package/lib/typescript/ui/screens/karma/KarmaAboutScreen.d.ts.map +1 -1
  107. package/lib/typescript/ui/screens/karma/KarmaCenterScreen.d.ts.map +1 -1
  108. package/lib/typescript/ui/screens/karma/KarmaFAQScreen.d.ts.map +1 -1
  109. package/lib/typescript/ui/screens/karma/KarmaLeaderboardScreen.d.ts.map +1 -1
  110. package/lib/typescript/ui/screens/karma/KarmaRewardsScreen.d.ts.map +1 -1
  111. package/lib/typescript/ui/screens/karma/KarmaRulesScreen.d.ts.map +1 -1
  112. package/lib/typescript/ui/stores/authStore.d.ts +3 -1
  113. package/lib/typescript/ui/stores/authStore.d.ts.map +1 -1
  114. package/lib/typescript/ui/stores/followStore.d.ts +10 -0
  115. package/lib/typescript/ui/stores/followStore.d.ts.map +1 -1
  116. package/package.json +1 -1
  117. package/src/index.ts +2 -10
  118. package/src/node/createAuth.ts +7 -623
  119. package/src/node/index.ts +1 -19
  120. package/src/ui/components/FollowButton.tsx +95 -11
  121. package/src/ui/components/Header.tsx +45 -4
  122. package/src/ui/components/OxyProvider.tsx +6 -0
  123. package/src/ui/context/OxyContext.tsx +65 -136
  124. package/src/ui/hooks/index.ts +1 -1
  125. package/src/ui/hooks/useFollow.ts +63 -0
  126. package/src/ui/navigation/OxyRouter.tsx +10 -0
  127. package/src/ui/screens/AccountSettingsScreen.tsx +8 -0
  128. package/src/ui/screens/ProfileScreen.tsx +191 -28
  129. package/src/ui/screens/UserLinksScreen.tsx +96 -0
  130. package/src/ui/screens/karma/KarmaAboutScreen.tsx +9 -2
  131. package/src/ui/screens/karma/KarmaCenterScreen.tsx +1 -20
  132. package/src/ui/screens/karma/KarmaFAQScreen.tsx +40 -24
  133. package/src/ui/screens/karma/KarmaLeaderboardScreen.tsx +9 -3
  134. package/src/ui/screens/karma/KarmaRewardsScreen.tsx +9 -3
  135. package/src/ui/screens/karma/KarmaRulesScreen.tsx +9 -3
  136. package/src/ui/stores/authStore.ts +22 -7
  137. package/src/ui/stores/followStore.ts +102 -1
@@ -1,463 +1,13 @@
1
- import express, { Request, Response } from 'express';
2
- import type { NextFunction } from 'express-serve-static-core';
1
+ import express from 'express';
2
+ import type { Request, Response } from 'express';
3
3
  import { OxyServices } from '../core';
4
- import { jwtDecode } from 'jwt-decode';
5
-
6
- // Types for enhanced authentication
7
- export interface AuthRequest extends Request {
8
- user?: any;
9
- userId?: string;
10
- accessToken?: string;
11
- sessionId?: string;
12
- deviceFingerprint?: string;
13
- }
14
-
15
- export interface AuthOptions {
16
- baseURL: string;
17
- jwtSecret?: string; // For local JWT validation
18
- loadFullUser?: boolean;
19
- enableSessionAuth?: boolean;
20
- enableDeviceAuth?: boolean;
21
- cacheUserData?: boolean;
22
- userCacheTTL?: number; // in seconds
23
- }
24
-
25
- export interface AuthMiddlewareOptions {
26
- required?: boolean;
27
- loadFullUser?: boolean;
28
- roles?: string[];
29
- permissions?: string[];
30
- onError?: (error: any, req: AuthRequest, res: Response) => void;
31
- }
32
-
33
- export interface TokenValidationResult {
34
- valid: boolean;
35
- userId?: string;
36
- user?: any;
37
- error?: string;
38
- code?: string;
39
- expiresAt?: number;
40
- cached?: boolean;
41
- }
42
-
43
- // User cache for performance
44
- class UserCache {
45
- private cache = new Map<string, { user: any; expiresAt: number }>();
46
- private ttl: number;
47
-
48
- constructor(ttl: number = 300) { // 5 minutes default
49
- this.ttl = ttl * 1000;
50
- }
51
-
52
- set(userId: string, user: any): void {
53
- this.cache.set(userId, {
54
- user,
55
- expiresAt: Date.now() + this.ttl
56
- });
57
- }
58
-
59
- get(userId: string): any | null {
60
- const item = this.cache.get(userId);
61
- if (!item || Date.now() > item.expiresAt) {
62
- this.cache.delete(userId);
63
- return null;
64
- }
65
- return item.user;
66
- }
67
-
68
- clear(): void {
69
- this.cache.clear();
70
- }
71
- }
72
-
73
- /**
74
- * Enhanced OxyAuth class for backend authentication
75
- */
76
- export class OxyAuth {
77
- private oxy: OxyServices;
78
- private options: AuthOptions;
79
- private userCache: UserCache | null = null;
80
-
81
- constructor(options: AuthOptions) {
82
- this.options = {
83
- loadFullUser: true,
84
- enableSessionAuth: true,
85
- enableDeviceAuth: true,
86
- cacheUserData: true,
87
- userCacheTTL: 300,
88
- ...options
89
- };
90
-
91
- this.oxy = new OxyServices({ baseURL: options.baseURL });
92
-
93
- if (this.options.cacheUserData) {
94
- this.userCache = new UserCache(this.options.userCacheTTL);
95
- }
96
- }
97
-
98
- /**
99
- * Create authentication middleware
100
- */
101
- createAuthMiddleware(options: AuthMiddlewareOptions = {}): (req: AuthRequest, res: Response, next: NextFunction) => Promise<void> {
102
- return async (req: AuthRequest, res: Response, next: NextFunction) => {
103
- try {
104
- const result = await this.authenticateRequest(req);
105
-
106
- if (!result.valid && options.required !== false) {
107
- const error = { message: 'Authentication required', code: 'AUTH_REQUIRED' };
108
- if (options.onError) {
109
- options.onError(error, req, res);
110
- } else {
111
- res.status(401).json(error);
112
- }
113
- return;
114
- }
115
-
116
- // Check roles if specified
117
- if (result.valid && options.roles && result.user) {
118
- const hasRole = options.roles.some(role =>
119
- result.user.roles?.includes(role) || result.user.role === role
120
- );
121
- if (!hasRole) {
122
- const error = { message: 'Insufficient permissions', code: 'INSUFFICIENT_ROLES' };
123
- if (options.onError) {
124
- options.onError(error, req, res);
125
- } else {
126
- res.status(403).json(error);
127
- }
128
- return;
129
- }
130
- }
131
-
132
- // Check permissions if specified
133
- if (result.valid && options.permissions && result.userId) {
134
- for (const permission of options.permissions) {
135
- const hasPermission = await this.hasPermission(result.userId!, permission);
136
- if (!hasPermission) {
137
- const error = { message: 'Insufficient permissions', code: 'INSUFFICIENT_PERMISSIONS' };
138
- if (options.onError) {
139
- options.onError(error, req, res);
140
- } else {
141
- res.status(403).json(error);
142
- }
143
- return;
144
- }
145
- }
146
- }
147
-
148
- next();
149
- } catch (error) {
150
- if (options.onError) {
151
- options.onError(error, req, res);
152
- } else {
153
- res.status(500).json({ message: 'Authentication error' });
154
- }
155
- }
156
- };
157
- }
158
-
159
- /**
160
- * Authenticate request and populate user data
161
- */
162
- private async authenticateRequest(req: AuthRequest): Promise<TokenValidationResult & { accessToken?: string }> {
163
- // Try JWT token first
164
- const authHeader = req.headers.authorization;
165
- if (authHeader && authHeader.startsWith('Bearer ')) {
166
- const token = authHeader.substring(7);
167
- const result = await this.validateToken(token);
168
- if (result.valid) {
169
- req.user = result.user;
170
- req.userId = result.userId;
171
- req.accessToken = token;
172
- return { ...result, accessToken: token };
173
- }
174
- }
175
-
176
- // Try session-based auth
177
- if (this.options.enableSessionAuth) {
178
- const sessionId = req.headers['x-session-id'] as string;
179
- if (sessionId) {
180
- const result = await this.validateSession(sessionId);
181
- if (result.valid) {
182
- req.user = result.user;
183
- req.userId = result.userId;
184
- req.sessionId = sessionId;
185
- return result;
186
- }
187
- }
188
- }
189
-
190
- // Try device-based auth
191
- if (this.options.enableDeviceAuth) {
192
- const deviceFingerprint = req.headers['x-device-fingerprint'] as string;
193
- const userId = req.headers['x-user-id'] as string;
194
- if (deviceFingerprint && userId) {
195
- const result = await this.validateDevice(userId, deviceFingerprint);
196
- if (result.valid) {
197
- req.user = result.user;
198
- req.userId = result.userId;
199
- req.deviceFingerprint = deviceFingerprint;
200
- return result;
201
- }
202
- }
203
- }
204
-
205
- return { valid: false, error: 'No valid authentication found' };
206
- }
207
-
208
- /**
209
- * Validate JWT token
210
- */
211
- async validateToken(token: string): Promise<TokenValidationResult> {
212
- try {
213
- // Local JWT validation if secret is provided
214
- if (this.options.jwtSecret) {
215
- const decoded = jwtDecode(token) as any;
216
- const currentTime = Math.floor(Date.now() / 1000);
217
-
218
- if (decoded.exp && decoded.exp < currentTime) {
219
- return {
220
- valid: false,
221
- error: 'Token expired',
222
- code: 'TOKEN_EXPIRED',
223
- expiresAt: decoded.exp
224
- };
225
- }
226
-
227
- const userId = decoded.userId || decoded.id;
228
- if (!userId) {
229
- return {
230
- valid: false,
231
- error: 'Invalid token payload',
232
- code: 'INVALID_PAYLOAD'
233
- };
234
- }
235
-
236
- // Get user data from cache or API
237
- let user = this.userCache?.get(userId);
238
- const cached = !!user;
239
-
240
- if (!user && this.options.loadFullUser) {
241
- try {
242
- user = await this.oxy.getUserById(userId);
243
- this.userCache?.set(userId, user);
244
- } catch (error) {
245
- user = { id: userId };
246
- }
247
- } else if (!user) {
248
- user = { id: userId };
249
- }
250
-
251
- return {
252
- valid: true,
253
- userId,
254
- user,
255
- expiresAt: decoded.exp,
256
- cached
257
- };
258
- }
259
-
260
- // Remote validation using OxyServices
261
- const tempOxy = new OxyServices({ baseURL: this.oxy.getBaseURL() });
262
- tempOxy.setTokens(token, '');
263
-
264
- const isValid = await tempOxy.validate();
265
- if (!isValid) {
266
- return {
267
- valid: false,
268
- error: 'Invalid token',
269
- code: 'INVALID_TOKEN'
270
- };
271
- }
272
-
273
- const userId = tempOxy.getCurrentUserId();
274
- if (!userId) {
275
- return {
276
- valid: false,
277
- error: 'Invalid token payload',
278
- code: 'INVALID_PAYLOAD'
279
- };
280
- }
281
-
282
- // Get user data
283
- let user = this.userCache?.get(userId);
284
- const cached = !!user;
285
-
286
- if (!user && this.options.loadFullUser) {
287
- try {
288
- user = await tempOxy.getUserById(userId);
289
- this.userCache?.set(userId, user);
290
- } catch (error) {
291
- user = { id: userId };
292
- }
293
- } else if (!user) {
294
- user = { id: userId };
295
- }
296
-
297
- return {
298
- valid: true,
299
- userId,
300
- user,
301
- cached
302
- };
303
- } catch (error) {
304
- return {
305
- valid: false,
306
- error: 'Token validation failed',
307
- code: 'VALIDATION_ERROR'
308
- };
309
- }
310
- }
311
-
312
- /**
313
- * Validate session-based authentication
314
- */
315
- async validateSession(sessionId: string, deviceFingerprint?: string): Promise<TokenValidationResult> {
316
- try {
317
- // This would integrate with your session management system
318
- // For now, it's a placeholder implementation
319
- return {
320
- valid: false,
321
- error: 'Session validation not implemented',
322
- code: 'NOT_IMPLEMENTED'
323
- };
324
- } catch (error) {
325
- return {
326
- valid: false,
327
- error: 'Session validation failed',
328
- code: 'VALIDATION_ERROR'
329
- };
330
- }
331
- }
332
-
333
- /**
334
- * Validate device-based authentication
335
- */
336
- async validateDevice(userId: string, deviceFingerprint: string): Promise<TokenValidationResult> {
337
- try {
338
- // This would validate device fingerprint against stored data
339
- // For now, it's a placeholder implementation
340
- return {
341
- valid: false,
342
- error: 'Device validation not implemented',
343
- code: 'NOT_IMPLEMENTED'
344
- };
345
- } catch (error) {
346
- return {
347
- valid: false,
348
- error: 'Device validation failed',
349
- code: 'VALIDATION_ERROR'
350
- };
351
- }
352
- }
353
-
354
- /**
355
- * Create role-based middleware
356
- */
357
- requireRole(roles: string | string[]): (req: AuthRequest, res: Response, next: NextFunction) => Promise<void> {
358
- const roleArray = Array.isArray(roles) ? roles : [roles];
359
- return this.createAuthMiddleware({
360
- required: true,
361
- roles: roleArray
362
- });
363
- }
364
-
365
- /**
366
- * Create permission-based middleware
367
- */
368
- requirePermission(permissions: string | string[]): (req: AuthRequest, res: Response, next: NextFunction) => Promise<void> {
369
- const permissionArray = Array.isArray(permissions) ? permissions : [permissions];
370
- return this.createAuthMiddleware({
371
- required: true,
372
- permissions: permissionArray
373
- });
374
- }
375
-
376
- /**
377
- * Create optional authentication middleware
378
- */
379
- optionalAuth(): (req: AuthRequest, res: Response, next: NextFunction) => Promise<void> {
380
- return this.createAuthMiddleware({
381
- required: false,
382
- onError: () => {} // No error thrown for optional auth
383
- });
384
- }
385
-
386
- /**
387
- * Clear user cache
388
- */
389
- clearCache(): void {
390
- this.userCache?.clear();
391
- }
392
-
393
- /**
394
- * Check if user data is cached for a given token
395
- */
396
- isUserCached(token: string): boolean {
397
- try {
398
- const decoded = jwtDecode(token) as any;
399
- const userId = decoded.userId || decoded.id;
400
- return userId ? this.userCache?.get(userId) !== null : false;
401
- } catch {
402
- return false;
403
- }
404
- }
405
-
406
- /**
407
- * Check if user has a specific permission
408
- */
409
- async hasPermission(userId: string, permission: string): Promise<boolean> {
410
- try {
411
- // This is a placeholder implementation
412
- // In a real implementation, you would check against user roles/permissions
413
- const user = this.userCache?.get(userId) || await this.oxy.getUserById(userId);
414
- return user?.permissions?.includes(permission) || user?.role === 'admin' || false;
415
- } catch {
416
- return false;
417
- }
418
- }
419
-
420
- /**
421
- * Get OxyServices instance
422
- */
423
- getOxyServices(): OxyServices {
424
- return this.oxy;
425
- }
426
- }
427
4
 
428
5
  export interface CreateAuthOptions {
429
6
  baseURL: string;
430
- jwtSecret?: string;
431
- loadFullUser?: boolean;
432
- enableSessionAuth?: boolean;
433
- enableDeviceAuth?: boolean;
434
- cacheUserData?: boolean;
435
- userCacheTTL?: number;
436
7
  }
437
8
 
438
- /**
439
- * Enhanced createAuth function that provides both router and middleware capabilities
440
- *
441
- * This is a unified authentication system that:
442
- * 1. Maintains backward compatibility with the old router-based approach
443
- * 2. Adds powerful new middleware capabilities
444
- * 3. Includes caching, role-based access, and performance optimizations
445
- * 4. Supports multiple authentication strategies
446
- */
447
9
  export function createAuth(options: CreateAuthOptions) {
448
- // Create the enhanced OxyAuth instance
449
- const authOptions: AuthOptions = {
450
- baseURL: options.baseURL,
451
- jwtSecret: options.jwtSecret,
452
- loadFullUser: options.loadFullUser ?? true,
453
- enableSessionAuth: options.enableSessionAuth ?? true,
454
- enableDeviceAuth: options.enableDeviceAuth ?? true,
455
- cacheUserData: options.cacheUserData ?? true,
456
- userCacheTTL: options.userCacheTTL ?? 300
457
- };
458
-
459
- const oxyAuth = new OxyAuth(authOptions);
460
- const oxy = oxyAuth.getOxyServices();
10
+ const oxy = new OxyServices({ baseURL: options.baseURL });
461
11
  const router = express.Router();
462
12
 
463
13
  // Helper to handle async route functions
@@ -472,261 +22,95 @@ export function createAuth(options: CreateAuthOptions) {
472
22
  }
473
23
  };
474
24
 
475
- // Enhanced signup with validation
476
25
  router.post(
477
26
  '/signup',
478
27
  wrap(async (req, res) => {
479
28
  const { username, email, password } = req.body;
480
-
481
- // Enhanced validation
482
- if (!username || !email || !password) {
483
- return res.status(400).json({
484
- message: 'Username, email, and password are required'
485
- });
486
- }
487
-
488
29
  const result = await oxy.signUp(username, email, password);
489
30
  res.json(result);
490
31
  })
491
32
  );
492
33
 
493
- // Enhanced login with device fingerprinting
494
34
  router.post(
495
35
  '/login',
496
36
  wrap(async (req, res) => {
497
- const { username, password, deviceFingerprint } = req.body;
498
-
499
- if (!username || !password) {
500
- return res.status(400).json({
501
- message: 'Username and password are required'
502
- });
503
- }
504
-
37
+ const { username, password } = req.body;
505
38
  const result = await oxy.login(username, password);
506
-
507
- // Store device fingerprint if provided
508
- if (deviceFingerprint && result.user?.id) {
509
- // This could be stored in a database for device tracking
510
- console.log(`Device login: ${deviceFingerprint} for user ${result.user.id}`);
511
- }
512
-
513
39
  res.json(result);
514
40
  })
515
41
  );
516
42
 
517
- // Enhanced logout with session management
518
43
  router.post(
519
44
  '/logout',
520
45
  wrap(async (req, res) => {
521
46
  const token = req.headers.authorization?.split(' ')[1];
522
47
  const refreshToken = req.body.refreshToken;
523
- const sessionId = req.body.sessionId;
524
-
525
48
  if (token) oxy.setTokens(token, refreshToken);
526
-
527
- // Enhanced logout with session tracking
528
- if (sessionId) {
529
- await oxy.logoutSession(sessionId);
530
- } else {
531
- await oxy.logout();
532
- }
533
-
49
+ await oxy.logout();
534
50
  res.json({ success: true });
535
51
  })
536
52
  );
537
53
 
538
- // Enhanced token refresh
539
54
  router.post(
540
55
  '/refresh',
541
56
  wrap(async (req, res) => {
542
57
  const refreshToken = req.body.refreshToken;
543
58
  const accessToken = req.headers.authorization?.split(' ')[1] || '';
544
-
545
- if (!refreshToken) {
546
- return res.status(400).json({ message: 'Refresh token is required' });
547
- }
548
-
549
59
  oxy.setTokens(accessToken, refreshToken);
550
60
  const tokens = await oxy.refreshTokens();
551
61
  res.json(tokens);
552
62
  })
553
63
  );
554
64
 
555
- // Enhanced token validation with caching
556
65
  router.get(
557
66
  '/validate',
558
67
  wrap(async (req, res) => {
559
68
  const token = req.headers.authorization?.split(' ')[1] || '';
560
-
561
- if (!token) {
562
- return res.status(401).json({ valid: false, message: 'No token provided' });
563
- }
564
-
565
69
  oxy.setTokens(token, '');
566
70
  const valid = await oxy.validate();
567
-
568
- // Enhanced response with more details
569
- res.json({
570
- valid,
571
- timestamp: new Date().toISOString(),
572
- cached: oxyAuth.isUserCached(token) // Check if user data is cached
573
- });
71
+ res.json({ valid });
574
72
  })
575
73
  );
576
74
 
577
- // Enhanced sessions management
578
75
  router.get(
579
76
  '/sessions',
580
77
  wrap(async (req, res) => {
581
78
  const token = req.headers.authorization?.split(' ')[1] || '';
582
-
583
- if (!token) {
584
- return res.status(401).json({ message: 'Authentication required' });
585
- }
586
-
587
79
  oxy.setTokens(token, '');
588
80
  const sessions = await oxy.getUserSessions();
589
81
  res.json(sessions);
590
82
  })
591
83
  );
592
84
 
593
- // Enhanced session deletion
594
85
  router.delete(
595
86
  '/sessions/:id',
596
87
  wrap(async (req, res) => {
597
88
  const token = req.headers.authorization?.split(' ')[1] || '';
598
-
599
- if (!token) {
600
- return res.status(401).json({ message: 'Authentication required' });
601
- }
602
-
603
89
  oxy.setTokens(token, '');
604
90
  const result = await oxy.logoutSession(req.params.id);
605
-
606
- // Clear cache for this user if logout was successful
607
- if (result.success) {
608
- oxyAuth.clearCache();
609
- }
610
-
611
91
  res.json(result);
612
92
  })
613
93
  );
614
94
 
615
- // Enhanced logout other sessions
616
95
  router.post(
617
96
  '/sessions/logout-others',
618
97
  wrap(async (req, res) => {
619
98
  const token = req.headers.authorization?.split(' ')[1] || '';
620
-
621
- if (!token) {
622
- return res.status(401).json({ message: 'Authentication required' });
623
- }
624
-
625
99
  oxy.setTokens(token, '');
626
100
  const result = await oxy.logoutOtherSessions();
627
-
628
- // Clear cache for this user
629
- if (result.success) {
630
- oxyAuth.clearCache();
631
- }
632
-
633
101
  res.json(result);
634
102
  })
635
103
  );
636
104
 
637
- // Enhanced logout all sessions
638
105
  router.post(
639
106
  '/sessions/logout-all',
640
107
  wrap(async (req, res) => {
641
108
  const token = req.headers.authorization?.split(' ')[1] || '';
642
-
643
- if (!token) {
644
- return res.status(401).json({ message: 'Authentication required' });
645
- }
646
-
647
109
  oxy.setTokens(token, '');
648
110
  const result = await oxy.logoutAllSessions();
649
-
650
- // Clear all cache
651
- if (result.success) {
652
- oxyAuth.clearCache();
653
- }
654
-
655
111
  res.json(result);
656
112
  })
657
113
  );
658
114
 
659
- // NEW: Get current user profile with caching
660
- router.get(
661
- '/profile',
662
- wrap(async (req, res) => {
663
- const token = req.headers.authorization?.split(' ')[1] || '';
664
-
665
- if (!token) {
666
- return res.status(401).json({ message: 'Authentication required' });
667
- }
668
-
669
- // Use the enhanced auth system for better performance
670
- const validation = await oxyAuth.validateToken(token);
671
-
672
- if (!validation.valid) {
673
- return res.status(401).json({ message: 'Invalid token' });
674
- }
675
-
676
- res.json({
677
- user: validation.user,
678
- cached: validation.cached,
679
- expiresAt: validation.expiresAt
680
- });
681
- })
682
- );
683
-
684
- // NEW: Check user permissions
685
- router.post(
686
- '/check-permissions',
687
- wrap(async (req, res) => {
688
- const token = req.headers.authorization?.split(' ')[1] || '';
689
- const { permissions } = req.body;
690
-
691
- if (!token) {
692
- return res.status(401).json({ message: 'Authentication required' });
693
- }
694
-
695
- if (!permissions || !Array.isArray(permissions)) {
696
- return res.status(400).json({ message: 'Permissions array is required' });
697
- }
698
-
699
- const validation = await oxyAuth.validateToken(token);
700
-
701
- if (!validation.valid) {
702
- return res.status(401).json({ message: 'Invalid token' });
703
- }
704
-
705
- // Check each permission
706
- const results = await Promise.all(
707
- permissions.map(async (permission) => {
708
- const hasPermission = await oxyAuth.hasPermission(validation.userId!, permission);
709
- return { permission, granted: hasPermission };
710
- })
711
- );
712
-
713
- res.json({ permissions: results });
714
- })
715
- );
716
-
717
- return {
718
- middleware: router,
719
- // NEW: Expose the enhanced auth system
720
- auth: oxyAuth,
721
- // NEW: Convenience methods for middleware
722
- requireAuth: (roles?: string | string[], permissions?: string | string[]) =>
723
- oxyAuth.createAuthMiddleware({
724
- required: true,
725
- roles: Array.isArray(roles) ? roles : roles ? [roles] : undefined,
726
- permissions: Array.isArray(permissions) ? permissions : permissions ? [permissions] : undefined
727
- }),
728
- optionalAuth: () => oxyAuth.optionalAuth(),
729
- requireRole: (roles: string | string[]) => oxyAuth.requireRole(roles),
730
- requirePermission: (permissions: string | string[]) => oxyAuth.requirePermission(permissions)
731
- };
115
+ return { middleware: router };
732
116
  }