mcp-twin 1.2.0 → 1.3.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.
@@ -0,0 +1,291 @@
1
+ "use strict";
2
+ /**
3
+ * Auth Routes
4
+ * MCP Twin Cloud
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ const express_1 = require("express");
8
+ const db_1 = require("../db");
9
+ const auth_1 = require("../auth");
10
+ const router = (0, express_1.Router)();
11
+ /**
12
+ * POST /api/auth/signup
13
+ * Create a new account
14
+ */
15
+ router.post('/signup', async (req, res) => {
16
+ try {
17
+ const { email, password } = req.body;
18
+ // Validate input
19
+ if (!email || !password) {
20
+ res.status(400).json({
21
+ error: {
22
+ code: 'VALIDATION_ERROR',
23
+ message: 'Email and password are required',
24
+ },
25
+ });
26
+ return;
27
+ }
28
+ if (password.length < 8) {
29
+ res.status(400).json({
30
+ error: {
31
+ code: 'VALIDATION_ERROR',
32
+ message: 'Password must be at least 8 characters',
33
+ },
34
+ });
35
+ return;
36
+ }
37
+ // Check if user exists
38
+ const existing = await (0, db_1.queryOne)('SELECT id FROM users WHERE email = $1', [email.toLowerCase()]);
39
+ if (existing) {
40
+ res.status(409).json({
41
+ error: {
42
+ code: 'USER_EXISTS',
43
+ message: 'An account with this email already exists',
44
+ },
45
+ });
46
+ return;
47
+ }
48
+ // Create user
49
+ const passwordHash = await (0, auth_1.hashPassword)(password);
50
+ const users = await (0, db_1.query)(`INSERT INTO users (email, password_hash)
51
+ VALUES ($1, $2)
52
+ RETURNING id, email, tier, created_at`, [email.toLowerCase(), passwordHash]);
53
+ const user = users[0];
54
+ // Generate initial API key
55
+ const { key, hash, prefix } = await (0, auth_1.generateApiKey)();
56
+ await (0, db_1.query)(`INSERT INTO api_keys (user_id, key_hash, key_prefix, name)
57
+ VALUES ($1, $2, $3, $4)`, [user.id, hash, prefix, 'Default API Key']);
58
+ // Generate session token
59
+ const sessionToken = (0, auth_1.generateSessionToken)({
60
+ id: user.id,
61
+ email: user.email,
62
+ tier: user.tier,
63
+ });
64
+ res.status(201).json({
65
+ message: 'Account created successfully',
66
+ user: {
67
+ id: user.id,
68
+ email: user.email,
69
+ tier: user.tier,
70
+ },
71
+ apiKey: key,
72
+ sessionToken,
73
+ });
74
+ }
75
+ catch (error) {
76
+ console.error('[Auth] Signup error:', error);
77
+ res.status(500).json({
78
+ error: {
79
+ code: 'INTERNAL_ERROR',
80
+ message: 'Failed to create account',
81
+ },
82
+ });
83
+ }
84
+ });
85
+ /**
86
+ * POST /api/auth/login
87
+ * Login and get session token
88
+ */
89
+ router.post('/login', async (req, res) => {
90
+ try {
91
+ const { email, password } = req.body;
92
+ if (!email || !password) {
93
+ res.status(400).json({
94
+ error: {
95
+ code: 'VALIDATION_ERROR',
96
+ message: 'Email and password are required',
97
+ },
98
+ });
99
+ return;
100
+ }
101
+ // Find user
102
+ const user = await (0, db_1.queryOne)('SELECT * FROM users WHERE email = $1', [email.toLowerCase()]);
103
+ if (!user) {
104
+ res.status(401).json({
105
+ error: {
106
+ code: 'INVALID_CREDENTIALS',
107
+ message: 'Invalid email or password',
108
+ },
109
+ });
110
+ return;
111
+ }
112
+ // Verify password
113
+ const valid = await (0, auth_1.verifyPassword)(password, user.password_hash);
114
+ if (!valid) {
115
+ res.status(401).json({
116
+ error: {
117
+ code: 'INVALID_CREDENTIALS',
118
+ message: 'Invalid email or password',
119
+ },
120
+ });
121
+ return;
122
+ }
123
+ // Generate session token
124
+ const sessionToken = (0, auth_1.generateSessionToken)({
125
+ id: user.id,
126
+ email: user.email,
127
+ tier: user.tier,
128
+ });
129
+ res.json({
130
+ message: 'Login successful',
131
+ user: {
132
+ id: user.id,
133
+ email: user.email,
134
+ tier: user.tier,
135
+ },
136
+ sessionToken,
137
+ expiresIn: '7d',
138
+ });
139
+ }
140
+ catch (error) {
141
+ console.error('[Auth] Login error:', error);
142
+ res.status(500).json({
143
+ error: {
144
+ code: 'INTERNAL_ERROR',
145
+ message: 'Login failed',
146
+ },
147
+ });
148
+ }
149
+ });
150
+ /**
151
+ * GET /api/auth/me
152
+ * Get current user info
153
+ */
154
+ router.get('/me', auth_1.authenticateApiKey, async (req, res) => {
155
+ try {
156
+ const user = await (0, db_1.queryOne)('SELECT id, email, tier, stripe_customer_id, created_at FROM users WHERE id = $1', [req.user.id]);
157
+ if (!user) {
158
+ res.status(404).json({
159
+ error: {
160
+ code: 'NOT_FOUND',
161
+ message: 'User not found',
162
+ },
163
+ });
164
+ return;
165
+ }
166
+ // Get API key count
167
+ const apiKeys = await (0, db_1.query)('SELECT COUNT(*) as count FROM api_keys WHERE user_id = $1 AND revoked_at IS NULL', [user.id]);
168
+ // Get twin count
169
+ const twins = await (0, db_1.query)('SELECT COUNT(*) as count FROM twins WHERE user_id = $1', [user.id]);
170
+ res.json({
171
+ user: {
172
+ id: user.id,
173
+ email: user.email,
174
+ tier: user.tier,
175
+ createdAt: user.created_at,
176
+ },
177
+ stats: {
178
+ apiKeys: parseInt(apiKeys[0]?.count || '0'),
179
+ twins: parseInt(twins[0]?.count || '0'),
180
+ },
181
+ });
182
+ }
183
+ catch (error) {
184
+ console.error('[Auth] Get me error:', error);
185
+ res.status(500).json({
186
+ error: {
187
+ code: 'INTERNAL_ERROR',
188
+ message: 'Failed to get user info',
189
+ },
190
+ });
191
+ }
192
+ });
193
+ /**
194
+ * POST /api/auth/api-keys
195
+ * Create a new API key
196
+ */
197
+ router.post('/api-keys', auth_1.authenticateApiKey, async (req, res) => {
198
+ try {
199
+ const { name } = req.body;
200
+ // Generate new key
201
+ const { key, hash, prefix } = await (0, auth_1.generateApiKey)();
202
+ const keys = await (0, db_1.query)(`INSERT INTO api_keys (user_id, key_hash, key_prefix, name)
203
+ VALUES ($1, $2, $3, $4)
204
+ RETURNING id, key_prefix, name, created_at`, [req.user.id, hash, prefix, name || 'API Key']);
205
+ res.status(201).json({
206
+ message: 'API key created',
207
+ apiKey: {
208
+ id: keys[0].id,
209
+ key, // Only returned once at creation
210
+ prefix: keys[0].key_prefix,
211
+ name: keys[0].name,
212
+ createdAt: keys[0].created_at,
213
+ },
214
+ });
215
+ }
216
+ catch (error) {
217
+ console.error('[Auth] Create API key error:', error);
218
+ res.status(500).json({
219
+ error: {
220
+ code: 'INTERNAL_ERROR',
221
+ message: 'Failed to create API key',
222
+ },
223
+ });
224
+ }
225
+ });
226
+ /**
227
+ * GET /api/auth/api-keys
228
+ * List user's API keys
229
+ */
230
+ router.get('/api-keys', auth_1.authenticateApiKey, async (req, res) => {
231
+ try {
232
+ const keys = await (0, db_1.query)(`SELECT id, key_prefix, name, last_used_at, created_at
233
+ FROM api_keys
234
+ WHERE user_id = $1 AND revoked_at IS NULL
235
+ ORDER BY created_at DESC`, [req.user.id]);
236
+ res.json({
237
+ apiKeys: keys.map((k) => ({
238
+ id: k.id,
239
+ prefix: k.key_prefix,
240
+ name: k.name,
241
+ lastUsedAt: k.last_used_at,
242
+ createdAt: k.created_at,
243
+ })),
244
+ });
245
+ }
246
+ catch (error) {
247
+ console.error('[Auth] List API keys error:', error);
248
+ res.status(500).json({
249
+ error: {
250
+ code: 'INTERNAL_ERROR',
251
+ message: 'Failed to list API keys',
252
+ },
253
+ });
254
+ }
255
+ });
256
+ /**
257
+ * DELETE /api/auth/api-keys/:id
258
+ * Revoke an API key
259
+ */
260
+ router.delete('/api-keys/:id', auth_1.authenticateApiKey, async (req, res) => {
261
+ try {
262
+ const { id } = req.params;
263
+ const result = await (0, db_1.query)(`UPDATE api_keys
264
+ SET revoked_at = NOW()
265
+ WHERE id = $1 AND user_id = $2 AND revoked_at IS NULL
266
+ RETURNING id`, [id, req.user.id]);
267
+ if (result.length === 0) {
268
+ res.status(404).json({
269
+ error: {
270
+ code: 'NOT_FOUND',
271
+ message: 'API key not found',
272
+ },
273
+ });
274
+ return;
275
+ }
276
+ res.json({
277
+ message: 'API key revoked',
278
+ });
279
+ }
280
+ catch (error) {
281
+ console.error('[Auth] Revoke API key error:', error);
282
+ res.status(500).json({
283
+ error: {
284
+ code: 'INTERNAL_ERROR',
285
+ message: 'Failed to revoke API key',
286
+ },
287
+ });
288
+ }
289
+ });
290
+ exports.default = router;
291
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../../src/cloud/routes/auth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Twins Routes
3
+ * MCP Twin Cloud
4
+ */
5
+ declare const router: import("express-serve-static-core").Router;
6
+ export default router;
7
+ //# sourceMappingURL=twins.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"twins.d.ts","sourceRoot":"","sources":["../../../src/cloud/routes/twins.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,QAAA,MAAM,MAAM,4CAAW,CAAC;AAi4BxB,eAAe,MAAM,CAAC"}