@qwickapps/server 1.5.2 → 1.6.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 (80) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/dist/core/control-panel.js +8 -8
  3. package/dist/core/control-panel.js.map +1 -1
  4. package/dist/plugins/api-keys/api-keys-plugin.d.ts +46 -0
  5. package/dist/plugins/api-keys/api-keys-plugin.d.ts.map +1 -0
  6. package/dist/plugins/api-keys/api-keys-plugin.js +329 -0
  7. package/dist/plugins/api-keys/api-keys-plugin.js.map +1 -0
  8. package/dist/plugins/api-keys/index.d.ts +14 -0
  9. package/dist/plugins/api-keys/index.d.ts.map +1 -0
  10. package/dist/plugins/api-keys/index.js +17 -0
  11. package/dist/plugins/api-keys/index.js.map +1 -0
  12. package/dist/plugins/api-keys/middleware/bearer-token-auth.d.ts +74 -0
  13. package/dist/plugins/api-keys/middleware/bearer-token-auth.d.ts.map +1 -0
  14. package/dist/plugins/api-keys/middleware/bearer-token-auth.js +201 -0
  15. package/dist/plugins/api-keys/middleware/bearer-token-auth.js.map +1 -0
  16. package/dist/plugins/api-keys/middleware/index.d.ts +7 -0
  17. package/dist/plugins/api-keys/middleware/index.d.ts.map +1 -0
  18. package/dist/plugins/api-keys/middleware/index.js +7 -0
  19. package/dist/plugins/api-keys/middleware/index.js.map +1 -0
  20. package/dist/plugins/api-keys/stores/index.d.ts +7 -0
  21. package/dist/plugins/api-keys/stores/index.d.ts.map +1 -0
  22. package/dist/plugins/api-keys/stores/index.js +7 -0
  23. package/dist/plugins/api-keys/stores/index.js.map +1 -0
  24. package/dist/plugins/api-keys/stores/postgres-store.d.ts +34 -0
  25. package/dist/plugins/api-keys/stores/postgres-store.d.ts.map +1 -0
  26. package/dist/plugins/api-keys/stores/postgres-store.js +360 -0
  27. package/dist/plugins/api-keys/stores/postgres-store.js.map +1 -0
  28. package/dist/plugins/api-keys/types.d.ts +268 -0
  29. package/dist/plugins/api-keys/types.d.ts.map +1 -0
  30. package/dist/plugins/api-keys/types.js +56 -0
  31. package/dist/plugins/api-keys/types.js.map +1 -0
  32. package/dist/plugins/auth/auth-plugin.js +1 -1
  33. package/dist/plugins/auth/auth-plugin.js.map +1 -1
  34. package/dist/plugins/auth/env-config.js +2 -2
  35. package/dist/plugins/auth/env-config.js.map +1 -1
  36. package/dist/plugins/frontend-app-plugin.d.ts.map +1 -1
  37. package/dist/plugins/frontend-app-plugin.js +5 -2
  38. package/dist/plugins/frontend-app-plugin.js.map +1 -1
  39. package/dist/plugins/users/__tests__/postgres-store.test.js +1 -0
  40. package/dist/plugins/users/__tests__/postgres-store.test.js.map +1 -1
  41. package/dist/plugins/users/__tests__/users-plugin.test.js +3 -0
  42. package/dist/plugins/users/__tests__/users-plugin.test.js.map +1 -1
  43. package/dist/plugins/users/stores/postgres-store.d.ts.map +1 -1
  44. package/dist/plugins/users/stores/postgres-store.js +59 -1
  45. package/dist/plugins/users/stores/postgres-store.js.map +1 -1
  46. package/dist/plugins/users/types.d.ts +22 -0
  47. package/dist/plugins/users/types.d.ts.map +1 -1
  48. package/dist-ui/assets/index-5nX8fM1a.js +469 -0
  49. package/dist-ui/assets/index-5nX8fM1a.js.map +1 -0
  50. package/dist-ui/index.html +1 -1
  51. package/dist-ui-lib/api/controlPanelApi.d.ts +62 -0
  52. package/dist-ui-lib/components/index.d.ts +2 -1
  53. package/dist-ui-lib/index.js +2588 -2238
  54. package/dist-ui-lib/index.js.map +1 -1
  55. package/dist-ui-lib/pages/APIKeysPage.d.ts +13 -0
  56. package/dist-ui-lib/pages/AcceptInvitationPage.d.ts +28 -0
  57. package/package.json +3 -2
  58. package/src/core/control-panel.ts +8 -8
  59. package/src/plugins/api-keys/api-keys-plugin.ts +397 -0
  60. package/src/plugins/api-keys/index.ts +49 -0
  61. package/src/plugins/api-keys/middleware/bearer-token-auth.ts +250 -0
  62. package/src/plugins/api-keys/middleware/index.ts +12 -0
  63. package/src/plugins/api-keys/stores/index.ts +7 -0
  64. package/src/plugins/api-keys/stores/postgres-store.ts +487 -0
  65. package/src/plugins/api-keys/types.ts +243 -0
  66. package/src/plugins/auth/auth-plugin.ts +1 -1
  67. package/src/plugins/auth/env-config.ts +2 -2
  68. package/src/plugins/frontend-app-plugin.ts +7 -2
  69. package/src/plugins/users/__tests__/postgres-store.test.ts +1 -0
  70. package/src/plugins/users/__tests__/users-plugin.test.ts +3 -0
  71. package/src/plugins/users/stores/postgres-store.ts +69 -0
  72. package/src/plugins/users/types.ts +25 -0
  73. package/ui/src/App.tsx +6 -1
  74. package/ui/src/api/controlPanelApi.ts +157 -0
  75. package/ui/src/components/index.ts +6 -0
  76. package/ui/src/pages/APIKeysPage.tsx +661 -0
  77. package/ui/src/pages/AcceptInvitationPage.tsx +169 -0
  78. package/ui/src/pages/UsersPage.tsx +225 -2
  79. package/dist-ui/assets/index-BfC7mG5L.js +0 -469
  80. package/dist-ui/assets/index-BfC7mG5L.js.map +0 -1
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Bearer Token Authentication Middleware
3
+ *
4
+ * Middleware for authenticating API requests using Bearer tokens (API keys).
5
+ * Verifies the token, checks expiration and active status, and attaches
6
+ * the authenticated key info to the request.
7
+ *
8
+ * Copyright (c) 2025 QwickApps.com. All rights reserved.
9
+ */
10
+ import type { Request, Response, NextFunction } from 'express';
11
+ import type { ApiKeyScope } from '../types.js';
12
+ /**
13
+ * Extended Express Request with API key authentication info
14
+ */
15
+ export interface ApiKeyAuthenticatedRequest extends Request {
16
+ apiKey?: {
17
+ id: string;
18
+ user_id: string;
19
+ scopes: ApiKeyScope[];
20
+ key_type: 'm2m' | 'pat';
21
+ };
22
+ }
23
+ /**
24
+ * Options for bearer token authentication middleware
25
+ */
26
+ export interface BearerTokenAuthOptions {
27
+ /** Required scopes (all must be present) */
28
+ requiredScopes?: ApiKeyScope[];
29
+ /** Allow only specific key types */
30
+ allowedKeyTypes?: ('m2m' | 'pat')[];
31
+ /** Custom error handler */
32
+ onUnauthorized?: (req: Request, res: Response, reason: string) => void;
33
+ }
34
+ /**
35
+ * Bearer Token Authentication Middleware
36
+ *
37
+ * Validates API keys sent as Bearer tokens in the Authorization header.
38
+ * Attaches authenticated key info to the request for downstream handlers.
39
+ *
40
+ * @param options Configuration options
41
+ * @returns Express middleware function
42
+ *
43
+ * @example
44
+ * ```ts
45
+ * import { bearerTokenAuth } from '@qwickapps/server';
46
+ *
47
+ * // Require authentication
48
+ * app.get('/api/data', bearerTokenAuth(), (req, res) => {
49
+ * const { apiKey } = req as ApiKeyAuthenticatedRequest;
50
+ * res.json({ user_id: apiKey?.user_id });
51
+ * });
52
+ *
53
+ * // Require specific scopes
54
+ * app.post('/api/data', bearerTokenAuth({
55
+ * requiredScopes: ['write'],
56
+ * }), (req, res) => {
57
+ * // Handler code
58
+ * });
59
+ *
60
+ * // Allow only M2M keys
61
+ * app.post('/api/admin', bearerTokenAuth({
62
+ * allowedKeyTypes: ['m2m'],
63
+ * requiredScopes: ['admin'],
64
+ * }), (req, res) => {
65
+ * // Handler code
66
+ * });
67
+ * ```
68
+ */
69
+ export declare function bearerTokenAuth(options?: BearerTokenAuthOptions): (req: Request, res: Response, next: NextFunction) => Promise<void>;
70
+ /**
71
+ * Helper type guard for API key authenticated requests
72
+ */
73
+ export declare function isApiKeyAuthenticated(req: Request): req is ApiKeyAuthenticatedRequest;
74
+ //# sourceMappingURL=bearer-token-auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bearer-token-auth.d.ts","sourceRoot":"","sources":["../../../../src/plugins/api-keys/middleware/bearer-token-auth.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC/D,OAAO,KAAK,EAAU,WAAW,EAAE,MAAM,aAAa,CAAC;AAIvD;;GAEG;AACH,MAAM,WAAW,0BAA2B,SAAQ,OAAO;IACzD,MAAM,CAAC,EAAE;QACP,EAAE,EAAE,MAAM,CAAC;QACX,OAAO,EAAE,MAAM,CAAC;QAChB,MAAM,EAAE,WAAW,EAAE,CAAC;QACtB,QAAQ,EAAE,KAAK,GAAG,KAAK,CAAC;KACzB,CAAC;CACH;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,4CAA4C;IAC5C,cAAc,CAAC,EAAE,WAAW,EAAE,CAAC;IAC/B,oCAAoC;IACpC,eAAe,CAAC,EAAE,CAAC,KAAK,GAAG,KAAK,CAAC,EAAE,CAAC;IACpC,2BAA2B;IAC3B,cAAc,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;CACxE;AA8FD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,wBAAgB,eAAe,CAAC,OAAO,GAAE,sBAA2B,IAOpD,KAAK,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,KAAG,OAAO,CAAC,IAAI,CAAC,CAqE9E;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,0BAA0B,CAErF"}
@@ -0,0 +1,201 @@
1
+ /**
2
+ * Bearer Token Authentication Middleware
3
+ *
4
+ * Middleware for authenticating API requests using Bearer tokens (API keys).
5
+ * Verifies the token, checks expiration and active status, and attaches
6
+ * the authenticated key info to the request.
7
+ *
8
+ * Copyright (c) 2025 QwickApps.com. All rights reserved.
9
+ */
10
+ import { getApiKeysStore } from '../api-keys-plugin.js';
11
+ import { incrementLimit, isLimited } from '../../rate-limit/rate-limit-service.js';
12
+ /**
13
+ * Extract Bearer token from Authorization header
14
+ *
15
+ * @param req Express request
16
+ * @returns Bearer token or null if not found
17
+ */
18
+ function extractBearerToken(req) {
19
+ const authHeader = req.headers.authorization;
20
+ if (!authHeader) {
21
+ return null;
22
+ }
23
+ // Check for "Bearer <token>" format
24
+ const parts = authHeader.split(' ');
25
+ if (parts.length !== 2 || parts[0] !== 'Bearer') {
26
+ return null;
27
+ }
28
+ return parts[1];
29
+ }
30
+ /**
31
+ * Check if API key has all required scopes
32
+ *
33
+ * @param keyScopes Scopes granted to the API key
34
+ * @param requiredScopes Scopes required for the endpoint
35
+ * @returns True if key has all required scopes
36
+ */
37
+ function hasRequiredScopes(keyScopes, requiredScopes) {
38
+ return requiredScopes.every(required => keyScopes.includes(required));
39
+ }
40
+ /**
41
+ * Default unauthorized handler
42
+ */
43
+ function defaultUnauthorizedHandler(req, res, reason) {
44
+ res.status(401).json({
45
+ error: 'Unauthorized',
46
+ message: reason,
47
+ });
48
+ }
49
+ /**
50
+ * Get rate limit identifier for API key authentication
51
+ * Uses IP address as the identifier
52
+ */
53
+ function getRateLimitIdentifier(req) {
54
+ const ip = req.ip ||
55
+ req.headers['x-forwarded-for']?.toString().split(',')[0].trim() ||
56
+ req.socket?.remoteAddress ||
57
+ 'unknown';
58
+ return `api-key-auth:${ip}`;
59
+ }
60
+ /**
61
+ * Check if rate limit has been exceeded
62
+ * Uses the existing rate-limit plugin with specific limits for API key auth
63
+ */
64
+ async function checkRateLimit(identifier) {
65
+ try {
66
+ // Check rate limit: 100 requests per 15 minutes
67
+ return await isLimited(identifier, {
68
+ maxRequests: 100,
69
+ windowMs: 15 * 60 * 1000, // 15 minutes
70
+ strategy: 'sliding-window',
71
+ });
72
+ }
73
+ catch (error) {
74
+ // If rate limit service not available, allow the request
75
+ // (fail open - let other security measures handle it)
76
+ console.warn('[bearerTokenAuth] Rate limit service unavailable:', error);
77
+ return false;
78
+ }
79
+ }
80
+ /**
81
+ * Record a failed authentication attempt
82
+ * Increments the rate limit counter
83
+ */
84
+ async function recordFailedAttempt(identifier) {
85
+ try {
86
+ await incrementLimit(identifier, {
87
+ maxRequests: 100,
88
+ windowMs: 15 * 60 * 1000, // 15 minutes
89
+ strategy: 'sliding-window',
90
+ });
91
+ }
92
+ catch (error) {
93
+ // Non-critical - log and continue
94
+ console.warn('[bearerTokenAuth] Failed to record attempt:', error);
95
+ }
96
+ }
97
+ /**
98
+ * Bearer Token Authentication Middleware
99
+ *
100
+ * Validates API keys sent as Bearer tokens in the Authorization header.
101
+ * Attaches authenticated key info to the request for downstream handlers.
102
+ *
103
+ * @param options Configuration options
104
+ * @returns Express middleware function
105
+ *
106
+ * @example
107
+ * ```ts
108
+ * import { bearerTokenAuth } from '@qwickapps/server';
109
+ *
110
+ * // Require authentication
111
+ * app.get('/api/data', bearerTokenAuth(), (req, res) => {
112
+ * const { apiKey } = req as ApiKeyAuthenticatedRequest;
113
+ * res.json({ user_id: apiKey?.user_id });
114
+ * });
115
+ *
116
+ * // Require specific scopes
117
+ * app.post('/api/data', bearerTokenAuth({
118
+ * requiredScopes: ['write'],
119
+ * }), (req, res) => {
120
+ * // Handler code
121
+ * });
122
+ *
123
+ * // Allow only M2M keys
124
+ * app.post('/api/admin', bearerTokenAuth({
125
+ * allowedKeyTypes: ['m2m'],
126
+ * requiredScopes: ['admin'],
127
+ * }), (req, res) => {
128
+ * // Handler code
129
+ * });
130
+ * ```
131
+ */
132
+ export function bearerTokenAuth(options = {}) {
133
+ const { requiredScopes = [], allowedKeyTypes, onUnauthorized = defaultUnauthorizedHandler, } = options;
134
+ return async (req, res, next) => {
135
+ try {
136
+ // Check rate limit first
137
+ const rateLimitId = getRateLimitIdentifier(req);
138
+ if (await checkRateLimit(rateLimitId)) {
139
+ res.status(429).json({
140
+ error: 'Too Many Requests',
141
+ message: 'Too many authentication attempts. Please try again later.',
142
+ });
143
+ return;
144
+ }
145
+ // Extract token from Authorization header
146
+ const token = extractBearerToken(req);
147
+ if (!token) {
148
+ recordFailedAttempt(rateLimitId);
149
+ onUnauthorized(req, res, 'Missing or invalid Authorization header');
150
+ return;
151
+ }
152
+ // Get store instance
153
+ const store = getApiKeysStore();
154
+ if (!store) {
155
+ console.error('[bearerTokenAuth] API Keys plugin not initialized');
156
+ res.status(500).json({ error: 'Authentication service unavailable' });
157
+ return;
158
+ }
159
+ // Verify the token
160
+ const apiKey = await store.verify(token);
161
+ if (!apiKey) {
162
+ recordFailedAttempt(rateLimitId);
163
+ onUnauthorized(req, res, 'Invalid, expired, or inactive API key');
164
+ return;
165
+ }
166
+ // Check key type if restrictions apply
167
+ if (allowedKeyTypes && !allowedKeyTypes.includes(apiKey.key_type)) {
168
+ onUnauthorized(req, res, `This endpoint requires ${allowedKeyTypes.join(' or ')} keys`);
169
+ return;
170
+ }
171
+ // Check scopes if required
172
+ if (requiredScopes.length > 0 && !hasRequiredScopes(apiKey.scopes, requiredScopes)) {
173
+ onUnauthorized(req, res, `Insufficient scopes. Required: ${requiredScopes.join(', ')}`);
174
+ return;
175
+ }
176
+ // Record usage (non-blocking)
177
+ store.recordUsage(apiKey.id).catch(err => {
178
+ console.error('[bearerTokenAuth] Failed to record key usage:', err);
179
+ });
180
+ // Attach authenticated key info to request
181
+ req.apiKey = {
182
+ id: apiKey.id,
183
+ user_id: apiKey.user_id,
184
+ scopes: apiKey.scopes,
185
+ key_type: apiKey.key_type,
186
+ };
187
+ next();
188
+ }
189
+ catch (error) {
190
+ console.error('[bearerTokenAuth] Authentication error:', error);
191
+ res.status(500).json({ error: 'Authentication failed' });
192
+ }
193
+ };
194
+ }
195
+ /**
196
+ * Helper type guard for API key authenticated requests
197
+ */
198
+ export function isApiKeyAuthenticated(req) {
199
+ return 'apiKey' in req && req.apiKey !== undefined;
200
+ }
201
+ //# sourceMappingURL=bearer-token-auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bearer-token-auth.js","sourceRoot":"","sources":["../../../../src/plugins/api-keys/middleware/bearer-token-auth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * API Keys Middleware Index
3
+ *
4
+ * Copyright (c) 2025 QwickApps.com. All rights reserved.
5
+ */
6
+ export { bearerTokenAuth, isApiKeyAuthenticated, type ApiKeyAuthenticatedRequest, type BearerTokenAuthOptions, } from './bearer-token-auth.js';
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/plugins/api-keys/middleware/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,eAAe,EACf,qBAAqB,EACrB,KAAK,0BAA0B,EAC/B,KAAK,sBAAsB,GAC5B,MAAM,wBAAwB,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * API Keys Middleware Index
3
+ *
4
+ * Copyright (c) 2025 QwickApps.com. All rights reserved.
5
+ */
6
+ export { bearerTokenAuth, isApiKeyAuthenticated, } from './bearer-token-auth.js';
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/plugins/api-keys/middleware/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,eAAe,EACf,qBAAqB,GAGtB,MAAM,wBAAwB,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * API Keys Stores Index
3
+ *
4
+ * Copyright (c) 2025 QwickApps.com. All rights reserved.
5
+ */
6
+ export { postgresApiKeyStore } from './postgres-store.js';
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/plugins/api-keys/stores/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * API Keys Stores Index
3
+ *
4
+ * Copyright (c) 2025 QwickApps.com. All rights reserved.
5
+ */
6
+ export { postgresApiKeyStore } from './postgres-store.js';
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/plugins/api-keys/stores/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * PostgreSQL API Keys Store
3
+ *
4
+ * API key storage implementation using PostgreSQL with Row-Level Security (RLS).
5
+ * Uses SHA-256 for token hashing (high-entropy keys don't need bcrypt's slowness).
6
+ *
7
+ * RLS Context Pattern:
8
+ * Each operation uses an explicit transaction and sets `app.current_user_id`
9
+ * as a transaction-local configuration variable. The RLS policy checks this
10
+ * variable to enforce that users can only access their own API keys.
11
+ *
12
+ * Copyright (c) 2025 QwickApps.com. All rights reserved.
13
+ */
14
+ import type { ApiKeyStore, PostgresApiKeyStoreConfig } from '../types.js';
15
+ /**
16
+ * Create a PostgreSQL API keys store with RLS
17
+ *
18
+ * @param config Configuration including a pg Pool instance
19
+ * @returns ApiKeyStore implementation
20
+ *
21
+ * @example
22
+ * ```ts
23
+ * import { Pool } from 'pg';
24
+ * import { postgresApiKeyStore } from '@qwickapps/server';
25
+ *
26
+ * const pool = new Pool({ connectionString: process.env.DATABASE_URL });
27
+ * const store = postgresApiKeyStore({ pool });
28
+ *
29
+ * // Or with lazy initialization:
30
+ * const store = postgresApiKeyStore({ pool: () => getPostgres().getPool() });
31
+ * ```
32
+ */
33
+ export declare function postgresApiKeyStore(config: PostgresApiKeyStoreConfig): ApiKeyStore;
34
+ //# sourceMappingURL=postgres-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"postgres-store.d.ts","sourceRoot":"","sources":["../../../../src/plugins/api-keys/stores/postgres-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAIH,OAAO,KAAK,EACV,WAAW,EACX,yBAAyB,EAK1B,MAAM,aAAa,CAAC;AAuKrB;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,yBAAyB,GAAG,WAAW,CAsRlF"}