@chaaskit/server 0.1.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.
- package/dist/api/admin.js +438 -0
- package/dist/api/admin.js.map +1 -0
- package/dist/api/agents.js +21 -0
- package/dist/api/agents.js.map +1 -0
- package/dist/api/api-keys.js +122 -0
- package/dist/api/api-keys.js.map +1 -0
- package/dist/api/auth.js +399 -0
- package/dist/api/auth.js.map +1 -0
- package/dist/api/chat.js +900 -0
- package/dist/api/chat.js.map +1 -0
- package/dist/api/config.js +91 -0
- package/dist/api/config.js.map +1 -0
- package/dist/api/documents.js +237 -0
- package/dist/api/documents.js.map +1 -0
- package/dist/api/export.js +107 -0
- package/dist/api/export.js.map +1 -0
- package/dist/api/health.js +25 -0
- package/dist/api/health.js.map +1 -0
- package/dist/api/mcp-server.js +84 -0
- package/dist/api/mcp-server.js.map +1 -0
- package/dist/api/mcp.js +400 -0
- package/dist/api/mcp.js.map +1 -0
- package/dist/api/mentions.js +94 -0
- package/dist/api/mentions.js.map +1 -0
- package/dist/api/oauth.js +366 -0
- package/dist/api/oauth.js.map +1 -0
- package/dist/api/payments.js +473 -0
- package/dist/api/payments.js.map +1 -0
- package/dist/api/projects.js +301 -0
- package/dist/api/projects.js.map +1 -0
- package/dist/api/scheduled-prompts.js +617 -0
- package/dist/api/scheduled-prompts.js.map +1 -0
- package/dist/api/search.js +85 -0
- package/dist/api/search.js.map +1 -0
- package/dist/api/share.js +188 -0
- package/dist/api/share.js.map +1 -0
- package/dist/api/slack.js +468 -0
- package/dist/api/slack.js.map +1 -0
- package/dist/api/teams.js +693 -0
- package/dist/api/teams.js.map +1 -0
- package/dist/api/templates.js +134 -0
- package/dist/api/templates.js.map +1 -0
- package/dist/api/threads.js +323 -0
- package/dist/api/threads.js.map +1 -0
- package/dist/api/upload.js +57 -0
- package/dist/api/upload.js.map +1 -0
- package/dist/api/user.js +111 -0
- package/dist/api/user.js.map +1 -0
- package/dist/api/v1/openai.js +245 -0
- package/dist/api/v1/openai.js.map +1 -0
- package/dist/app.js +168 -0
- package/dist/app.js.map +1 -0
- package/dist/bin/cli.js +57 -0
- package/dist/bin/cli.js.map +1 -0
- package/dist/commands/db-sync.js +108 -0
- package/dist/commands/db-sync.js.map +1 -0
- package/dist/config/loader.js +374 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/documents/extractors.js +136 -0
- package/dist/documents/extractors.js.map +1 -0
- package/dist/extensions/glob.js +53 -0
- package/dist/extensions/glob.js.map +1 -0
- package/dist/extensions/loader.js +72 -0
- package/dist/extensions/loader.js.map +1 -0
- package/dist/index.js +25 -0
- package/dist/index.js.map +1 -0
- package/dist/loaders/index.js +75 -0
- package/dist/loaders/index.js.map +1 -0
- package/dist/mcp/client.js +551 -0
- package/dist/mcp/client.js.map +1 -0
- package/dist/mcp/server.js +335 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/middleware/apiKeyAuth.js +136 -0
- package/dist/middleware/apiKeyAuth.js.map +1 -0
- package/dist/middleware/auth.js +192 -0
- package/dist/middleware/auth.js.map +1 -0
- package/dist/middleware/errorHandler.js +41 -0
- package/dist/middleware/errorHandler.js.map +1 -0
- package/dist/middleware/mcpServerAuth.js +164 -0
- package/dist/middleware/mcpServerAuth.js.map +1 -0
- package/dist/middleware/requestLogger.js +9 -0
- package/dist/middleware/requestLogger.js.map +1 -0
- package/dist/middleware/team.js +132 -0
- package/dist/middleware/team.js.map +1 -0
- package/dist/oauth/server.js +410 -0
- package/dist/oauth/server.js.map +1 -0
- package/dist/queue/cli.js +93 -0
- package/dist/queue/cli.js.map +1 -0
- package/dist/queue/handlers/index.js +91 -0
- package/dist/queue/handlers/index.js.map +1 -0
- package/dist/queue/handlers/scheduled-prompt.js +270 -0
- package/dist/queue/handlers/scheduled-prompt.js.map +1 -0
- package/dist/queue/index.js +91 -0
- package/dist/queue/index.js.map +1 -0
- package/dist/queue/providers/memory.js +296 -0
- package/dist/queue/providers/memory.js.map +1 -0
- package/dist/queue/providers/sqs.js +275 -0
- package/dist/queue/providers/sqs.js.map +1 -0
- package/dist/queue/scheduler.js +355 -0
- package/dist/queue/scheduler.js.map +1 -0
- package/dist/queue/types.js +5 -0
- package/dist/queue/types.js.map +1 -0
- package/dist/queue/worker.js +230 -0
- package/dist/queue/worker.js.map +1 -0
- package/dist/registry/index.js +40 -0
- package/dist/registry/index.js.map +1 -0
- package/dist/server.js +207 -0
- package/dist/server.js.map +1 -0
- package/dist/services/agent.js +530 -0
- package/dist/services/agent.js.map +1 -0
- package/dist/services/agents.js +194 -0
- package/dist/services/agents.js.map +1 -0
- package/dist/services/documents.js +507 -0
- package/dist/services/documents.js.map +1 -0
- package/dist/services/email/index.js +91 -0
- package/dist/services/email/index.js.map +1 -0
- package/dist/services/email/providers/ses.js +97 -0
- package/dist/services/email/providers/ses.js.map +1 -0
- package/dist/services/email/templates.js +194 -0
- package/dist/services/email/templates.js.map +1 -0
- package/dist/services/email/types.js +5 -0
- package/dist/services/email/types.js.map +1 -0
- package/dist/services/encryption.js +69 -0
- package/dist/services/encryption.js.map +1 -0
- package/dist/services/oauth-discovery.js +226 -0
- package/dist/services/oauth-discovery.js.map +1 -0
- package/dist/services/pendingConfirmation.js +105 -0
- package/dist/services/pendingConfirmation.js.map +1 -0
- package/dist/services/scheduledPrompts.js +70 -0
- package/dist/services/scheduledPrompts.js.map +1 -0
- package/dist/services/slack/client.js +174 -0
- package/dist/services/slack/client.js.map +1 -0
- package/dist/services/slack/events.js +189 -0
- package/dist/services/slack/events.js.map +1 -0
- package/dist/services/slack/index.js +6 -0
- package/dist/services/slack/index.js.map +1 -0
- package/dist/services/slack/notifications.js +124 -0
- package/dist/services/slack/notifications.js.map +1 -0
- package/dist/services/slack/signature.js +74 -0
- package/dist/services/slack/signature.js.map +1 -0
- package/dist/services/slack/thread-context.js +191 -0
- package/dist/services/slack/thread-context.js.map +1 -0
- package/dist/services/toolConfirmation.js +55 -0
- package/dist/services/toolConfirmation.js.map +1 -0
- package/dist/services/usage.js +241 -0
- package/dist/services/usage.js.map +1 -0
- package/dist/ssr/build.js +90 -0
- package/dist/ssr/build.js.map +1 -0
- package/dist/ssr/components/SSRMessageList.js +120 -0
- package/dist/ssr/components/SSRMessageList.js.map +1 -0
- package/dist/ssr/entry.client.js +8 -0
- package/dist/ssr/entry.client.js.map +1 -0
- package/dist/ssr/entry.server.js +71 -0
- package/dist/ssr/entry.server.js.map +1 -0
- package/dist/ssr/handler.js +51 -0
- package/dist/ssr/handler.js.map +1 -0
- package/dist/ssr/root.js +184 -0
- package/dist/ssr/root.js.map +1 -0
- package/dist/ssr/routes/login.js +140 -0
- package/dist/ssr/routes/login.js.map +1 -0
- package/dist/ssr/routes/pricing.js +195 -0
- package/dist/ssr/routes/pricing.js.map +1 -0
- package/dist/ssr/routes/privacy.js +39 -0
- package/dist/ssr/routes/privacy.js.map +1 -0
- package/dist/ssr/routes/register.js +148 -0
- package/dist/ssr/routes/register.js.map +1 -0
- package/dist/ssr/routes/shared.$shareId.js +153 -0
- package/dist/ssr/routes/shared.$shareId.js.map +1 -0
- package/dist/ssr/routes/terms.js +39 -0
- package/dist/ssr/routes/terms.js.map +1 -0
- package/dist/storage/index.js +43 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/providers/database.js +38 -0
- package/dist/storage/providers/database.js.map +1 -0
- package/dist/storage/providers/filesystem.js +51 -0
- package/dist/storage/providers/filesystem.js.map +1 -0
- package/dist/storage/types.js +2 -0
- package/dist/storage/types.js.map +1 -0
- package/dist/tools/documents.js +336 -0
- package/dist/tools/documents.js.map +1 -0
- package/dist/tools/get-plan-usage.js +82 -0
- package/dist/tools/get-plan-usage.js.map +1 -0
- package/dist/tools/index.js +106 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/types.js +2 -0
- package/dist/tools/types.js.map +1 -0
- package/dist/tools/web-scrape.js +145 -0
- package/dist/tools/web-scrape.js.map +1 -0
- package/package.json +93 -0
package/dist/api/auth.js
ADDED
|
@@ -0,0 +1,399 @@
|
|
|
1
|
+
import { Router } from 'express';
|
|
2
|
+
import bcrypt from 'bcryptjs';
|
|
3
|
+
import crypto from 'crypto';
|
|
4
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
5
|
+
import { db } from '@chaaskit/db';
|
|
6
|
+
import { HTTP_STATUS } from '@chaaskit/shared';
|
|
7
|
+
import { AppError } from '../middleware/errorHandler.js';
|
|
8
|
+
import { generateToken, requireAuth } from '../middleware/auth.js';
|
|
9
|
+
import { getConfig } from '../config/loader.js';
|
|
10
|
+
import { z } from 'zod';
|
|
11
|
+
import { isEmailEnabled, sendEmail, generateVerificationEmailHtml, generateVerificationEmailText, } from '../services/email/index.js';
|
|
12
|
+
export const authRouter = Router();
|
|
13
|
+
// Helper function to generate a 6-digit numeric verification code
|
|
14
|
+
function generateVerificationCode(length = 6) {
|
|
15
|
+
const digits = '0123456789';
|
|
16
|
+
let code = '';
|
|
17
|
+
for (let i = 0; i < length; i++) {
|
|
18
|
+
code += digits[crypto.randomInt(0, digits.length)];
|
|
19
|
+
}
|
|
20
|
+
return code;
|
|
21
|
+
}
|
|
22
|
+
// Helper function to check if email verification is required
|
|
23
|
+
function isEmailVerificationRequired() {
|
|
24
|
+
const config = getConfig();
|
|
25
|
+
return config.auth.emailVerification?.enabled === true && isEmailEnabled();
|
|
26
|
+
}
|
|
27
|
+
// Helper function to create and send verification code
|
|
28
|
+
async function createAndSendVerificationCode(userId, email) {
|
|
29
|
+
const config = getConfig();
|
|
30
|
+
const codeLength = config.auth.emailVerification?.codeLength ?? 6;
|
|
31
|
+
const expiresInMinutes = config.auth.emailVerification?.expiresInMinutes ?? 15;
|
|
32
|
+
// Generate plain code
|
|
33
|
+
const code = generateVerificationCode(codeLength);
|
|
34
|
+
// Hash the code for storage
|
|
35
|
+
const codeHash = await bcrypt.hash(code, 10);
|
|
36
|
+
// Calculate expiration
|
|
37
|
+
const expiresAt = new Date(Date.now() + expiresInMinutes * 60 * 1000);
|
|
38
|
+
// Invalidate existing codes for this user
|
|
39
|
+
await db.emailVerification.updateMany({
|
|
40
|
+
where: {
|
|
41
|
+
userId,
|
|
42
|
+
usedAt: null,
|
|
43
|
+
},
|
|
44
|
+
data: {
|
|
45
|
+
usedAt: new Date(), // Mark as used to invalidate
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
// Create new verification record
|
|
49
|
+
await db.emailVerification.create({
|
|
50
|
+
data: {
|
|
51
|
+
code: codeHash,
|
|
52
|
+
userId,
|
|
53
|
+
expiresAt,
|
|
54
|
+
},
|
|
55
|
+
});
|
|
56
|
+
// Send verification email
|
|
57
|
+
const html = generateVerificationEmailHtml(code, config);
|
|
58
|
+
const text = generateVerificationEmailText(code, config);
|
|
59
|
+
const result = await sendEmail({
|
|
60
|
+
to: email,
|
|
61
|
+
subject: `Your ${config.app.name} verification code: ${code}`,
|
|
62
|
+
html,
|
|
63
|
+
text,
|
|
64
|
+
});
|
|
65
|
+
if (result) {
|
|
66
|
+
console.log(`[Auth] Verification email sent to ${email} (messageId: ${result.messageId})`);
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
// Email disabled - log the code for development
|
|
70
|
+
console.log(`[Auth] Email disabled - verification code for ${email}: ${code}`);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
const registerSchema = z.object({
|
|
74
|
+
email: z.string().email(),
|
|
75
|
+
password: z.string().min(8),
|
|
76
|
+
name: z.string().optional(),
|
|
77
|
+
});
|
|
78
|
+
const loginSchema = z.object({
|
|
79
|
+
email: z.string().email(),
|
|
80
|
+
password: z.string(),
|
|
81
|
+
});
|
|
82
|
+
const magicLinkSchema = z.object({
|
|
83
|
+
email: z.string().email(),
|
|
84
|
+
});
|
|
85
|
+
// Register with email/password
|
|
86
|
+
authRouter.post('/register', async (req, res, next) => {
|
|
87
|
+
try {
|
|
88
|
+
const config = getConfig();
|
|
89
|
+
if (!config.auth.methods.includes('email-password')) {
|
|
90
|
+
throw new AppError(HTTP_STATUS.BAD_REQUEST, 'Email/password registration is not enabled');
|
|
91
|
+
}
|
|
92
|
+
const { email, password, name } = registerSchema.parse(req.body);
|
|
93
|
+
// Check if user exists
|
|
94
|
+
const existingUser = await db.user.findUnique({
|
|
95
|
+
where: { email },
|
|
96
|
+
});
|
|
97
|
+
if (existingUser) {
|
|
98
|
+
throw new AppError(HTTP_STATUS.CONFLICT, 'Email already registered');
|
|
99
|
+
}
|
|
100
|
+
// Hash password
|
|
101
|
+
const passwordHash = await bcrypt.hash(password, 12);
|
|
102
|
+
// Determine if email verification is required
|
|
103
|
+
const requiresVerification = isEmailVerificationRequired();
|
|
104
|
+
// Create user - auto-verify if email verification is not configured
|
|
105
|
+
const user = await db.user.create({
|
|
106
|
+
data: {
|
|
107
|
+
email,
|
|
108
|
+
passwordHash,
|
|
109
|
+
name,
|
|
110
|
+
emailVerified: !requiresVerification,
|
|
111
|
+
},
|
|
112
|
+
select: {
|
|
113
|
+
id: true,
|
|
114
|
+
email: true,
|
|
115
|
+
name: true,
|
|
116
|
+
avatarUrl: true,
|
|
117
|
+
emailVerified: true,
|
|
118
|
+
plan: true,
|
|
119
|
+
},
|
|
120
|
+
});
|
|
121
|
+
const token = generateToken(user.id, user.email);
|
|
122
|
+
res.cookie('token', token, {
|
|
123
|
+
httpOnly: true,
|
|
124
|
+
secure: process.env.NODE_ENV === 'production',
|
|
125
|
+
sameSite: 'lax',
|
|
126
|
+
maxAge: 7 * 24 * 60 * 60 * 1000, // 7 days
|
|
127
|
+
});
|
|
128
|
+
// Send verification email if required
|
|
129
|
+
if (requiresVerification) {
|
|
130
|
+
await createAndSendVerificationCode(user.id, user.email);
|
|
131
|
+
}
|
|
132
|
+
res.status(HTTP_STATUS.CREATED).json({
|
|
133
|
+
user,
|
|
134
|
+
token,
|
|
135
|
+
requiresVerification,
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
catch (error) {
|
|
139
|
+
next(error);
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
// Login with email/password
|
|
143
|
+
authRouter.post('/login', async (req, res, next) => {
|
|
144
|
+
try {
|
|
145
|
+
const config = getConfig();
|
|
146
|
+
if (!config.auth.methods.includes('email-password')) {
|
|
147
|
+
throw new AppError(HTTP_STATUS.BAD_REQUEST, 'Email/password login is not enabled');
|
|
148
|
+
}
|
|
149
|
+
const { email, password } = loginSchema.parse(req.body);
|
|
150
|
+
const user = await db.user.findUnique({
|
|
151
|
+
where: { email },
|
|
152
|
+
});
|
|
153
|
+
if (!user || !user.passwordHash) {
|
|
154
|
+
throw new AppError(HTTP_STATUS.UNAUTHORIZED, 'Invalid credentials');
|
|
155
|
+
}
|
|
156
|
+
const isValid = await bcrypt.compare(password, user.passwordHash);
|
|
157
|
+
if (!isValid) {
|
|
158
|
+
throw new AppError(HTTP_STATUS.UNAUTHORIZED, 'Invalid credentials');
|
|
159
|
+
}
|
|
160
|
+
const token = generateToken(user.id, user.email);
|
|
161
|
+
res.cookie('token', token, {
|
|
162
|
+
httpOnly: true,
|
|
163
|
+
secure: process.env.NODE_ENV === 'production',
|
|
164
|
+
sameSite: 'lax',
|
|
165
|
+
maxAge: 7 * 24 * 60 * 60 * 1000,
|
|
166
|
+
});
|
|
167
|
+
// Check if user needs to verify email
|
|
168
|
+
const requiresVerification = isEmailVerificationRequired() && !user.emailVerified;
|
|
169
|
+
res.json({
|
|
170
|
+
user: {
|
|
171
|
+
id: user.id,
|
|
172
|
+
email: user.email,
|
|
173
|
+
name: user.name,
|
|
174
|
+
avatarUrl: user.avatarUrl,
|
|
175
|
+
emailVerified: user.emailVerified,
|
|
176
|
+
plan: user.plan,
|
|
177
|
+
},
|
|
178
|
+
token,
|
|
179
|
+
requiresVerification,
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
catch (error) {
|
|
183
|
+
next(error);
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
// Send magic link
|
|
187
|
+
authRouter.post('/magic-link', async (req, res, next) => {
|
|
188
|
+
try {
|
|
189
|
+
const config = getConfig();
|
|
190
|
+
if (!config.auth.magicLink.enabled) {
|
|
191
|
+
throw new AppError(HTTP_STATUS.BAD_REQUEST, 'Magic link is not enabled');
|
|
192
|
+
}
|
|
193
|
+
const { email } = magicLinkSchema.parse(req.body);
|
|
194
|
+
// Find or create user
|
|
195
|
+
let user = await db.user.findUnique({ where: { email } });
|
|
196
|
+
if (!user) {
|
|
197
|
+
user = await db.user.create({
|
|
198
|
+
data: { email },
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
// Create magic link token
|
|
202
|
+
const token = uuidv4();
|
|
203
|
+
const expiresAt = new Date(Date.now() + config.auth.magicLink.expiresInMinutes * 60 * 1000);
|
|
204
|
+
await db.magicLink.create({
|
|
205
|
+
data: {
|
|
206
|
+
token,
|
|
207
|
+
userId: user.id,
|
|
208
|
+
expiresAt,
|
|
209
|
+
},
|
|
210
|
+
});
|
|
211
|
+
// TODO: Send email with magic link
|
|
212
|
+
// In development, log the link
|
|
213
|
+
console.log(`Magic link for ${email}: ${process.env.APP_URL}/auth/magic-link?token=${token}`);
|
|
214
|
+
res.json({ message: 'Magic link sent' });
|
|
215
|
+
}
|
|
216
|
+
catch (error) {
|
|
217
|
+
next(error);
|
|
218
|
+
}
|
|
219
|
+
});
|
|
220
|
+
// Verify magic link
|
|
221
|
+
authRouter.get('/magic-link/verify', async (req, res, next) => {
|
|
222
|
+
try {
|
|
223
|
+
const { token } = req.query;
|
|
224
|
+
if (!token || typeof token !== 'string') {
|
|
225
|
+
throw new AppError(HTTP_STATUS.BAD_REQUEST, 'Token is required');
|
|
226
|
+
}
|
|
227
|
+
const magicLink = await db.magicLink.findUnique({
|
|
228
|
+
where: { token },
|
|
229
|
+
include: { user: true },
|
|
230
|
+
});
|
|
231
|
+
if (!magicLink || magicLink.usedAt || magicLink.expiresAt < new Date()) {
|
|
232
|
+
throw new AppError(HTTP_STATUS.BAD_REQUEST, 'Invalid or expired token');
|
|
233
|
+
}
|
|
234
|
+
// Mark as used
|
|
235
|
+
await db.magicLink.update({
|
|
236
|
+
where: { id: magicLink.id },
|
|
237
|
+
data: { usedAt: new Date() },
|
|
238
|
+
});
|
|
239
|
+
// Update user as verified
|
|
240
|
+
await db.user.update({
|
|
241
|
+
where: { id: magicLink.userId },
|
|
242
|
+
data: { emailVerified: true },
|
|
243
|
+
});
|
|
244
|
+
const authToken = generateToken(magicLink.user.id, magicLink.user.email);
|
|
245
|
+
res.cookie('token', authToken, {
|
|
246
|
+
httpOnly: true,
|
|
247
|
+
secure: process.env.NODE_ENV === 'production',
|
|
248
|
+
sameSite: 'lax',
|
|
249
|
+
maxAge: 7 * 24 * 60 * 60 * 1000,
|
|
250
|
+
});
|
|
251
|
+
res.json({
|
|
252
|
+
user: {
|
|
253
|
+
id: magicLink.user.id,
|
|
254
|
+
email: magicLink.user.email,
|
|
255
|
+
name: magicLink.user.name,
|
|
256
|
+
avatarUrl: magicLink.user.avatarUrl,
|
|
257
|
+
plan: magicLink.user.plan,
|
|
258
|
+
},
|
|
259
|
+
token: authToken,
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
catch (error) {
|
|
263
|
+
next(error);
|
|
264
|
+
}
|
|
265
|
+
});
|
|
266
|
+
// Logout
|
|
267
|
+
authRouter.post('/logout', (req, res) => {
|
|
268
|
+
res.clearCookie('token');
|
|
269
|
+
res.json({ message: 'Logged out' });
|
|
270
|
+
});
|
|
271
|
+
// Get current user
|
|
272
|
+
authRouter.get('/me', requireAuth, (req, res) => {
|
|
273
|
+
res.json({ user: req.user });
|
|
274
|
+
});
|
|
275
|
+
// OAuth routes (Google, GitHub)
|
|
276
|
+
authRouter.get('/oauth/:provider', (req, res, next) => {
|
|
277
|
+
const { provider } = req.params;
|
|
278
|
+
const config = getConfig();
|
|
279
|
+
if (!config.auth.methods.includes(provider)) {
|
|
280
|
+
return next(new AppError(HTTP_STATUS.BAD_REQUEST, `OAuth provider ${provider} is not enabled`));
|
|
281
|
+
}
|
|
282
|
+
// Redirect to OAuth provider
|
|
283
|
+
// In a full implementation, this would use passport.js
|
|
284
|
+
res.redirect(`/api/auth/${provider}/redirect`);
|
|
285
|
+
});
|
|
286
|
+
authRouter.get('/callback/:provider', async (req, res, next) => {
|
|
287
|
+
// Handle OAuth callback
|
|
288
|
+
// In a full implementation, this would use passport.js
|
|
289
|
+
try {
|
|
290
|
+
const { provider } = req.params;
|
|
291
|
+
// Placeholder for OAuth callback handling
|
|
292
|
+
res.redirect(`${process.env.APP_URL}?auth=success`);
|
|
293
|
+
}
|
|
294
|
+
catch (error) {
|
|
295
|
+
next(error);
|
|
296
|
+
}
|
|
297
|
+
});
|
|
298
|
+
// Verify email with 6-digit code
|
|
299
|
+
const verifyEmailSchema = z.object({
|
|
300
|
+
code: z.string().min(4).max(8),
|
|
301
|
+
});
|
|
302
|
+
authRouter.post('/verify-email', requireAuth, async (req, res, next) => {
|
|
303
|
+
try {
|
|
304
|
+
const { code } = verifyEmailSchema.parse(req.body);
|
|
305
|
+
const userId = req.user.id;
|
|
306
|
+
// Check if user is already verified
|
|
307
|
+
const user = await db.user.findUnique({
|
|
308
|
+
where: { id: userId },
|
|
309
|
+
select: { emailVerified: true, email: true },
|
|
310
|
+
});
|
|
311
|
+
if (user?.emailVerified) {
|
|
312
|
+
res.json({ message: 'Email already verified', verified: true });
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
315
|
+
// Find the most recent unused verification code for this user
|
|
316
|
+
const verification = await db.emailVerification.findFirst({
|
|
317
|
+
where: {
|
|
318
|
+
userId,
|
|
319
|
+
usedAt: null,
|
|
320
|
+
expiresAt: { gt: new Date() },
|
|
321
|
+
},
|
|
322
|
+
orderBy: { createdAt: 'desc' },
|
|
323
|
+
});
|
|
324
|
+
if (!verification) {
|
|
325
|
+
throw new AppError(HTTP_STATUS.BAD_REQUEST, 'No valid verification code found. Please request a new code.');
|
|
326
|
+
}
|
|
327
|
+
// Check if too many attempts
|
|
328
|
+
const MAX_ATTEMPTS = 5;
|
|
329
|
+
if (verification.attempts >= MAX_ATTEMPTS) {
|
|
330
|
+
throw new AppError(HTTP_STATUS.TOO_MANY_REQUESTS, 'Too many attempts. Please request a new code.');
|
|
331
|
+
}
|
|
332
|
+
// Increment attempt counter
|
|
333
|
+
await db.emailVerification.update({
|
|
334
|
+
where: { id: verification.id },
|
|
335
|
+
data: { attempts: { increment: 1 } },
|
|
336
|
+
});
|
|
337
|
+
// Verify the code
|
|
338
|
+
const isValid = await bcrypt.compare(code, verification.code);
|
|
339
|
+
if (!isValid) {
|
|
340
|
+
const remainingAttempts = MAX_ATTEMPTS - verification.attempts - 1;
|
|
341
|
+
throw new AppError(HTTP_STATUS.BAD_REQUEST, `Invalid verification code. ${remainingAttempts} attempts remaining.`);
|
|
342
|
+
}
|
|
343
|
+
// Mark code as used and verify user's email
|
|
344
|
+
await db.$transaction([
|
|
345
|
+
db.emailVerification.update({
|
|
346
|
+
where: { id: verification.id },
|
|
347
|
+
data: { usedAt: new Date() },
|
|
348
|
+
}),
|
|
349
|
+
db.user.update({
|
|
350
|
+
where: { id: userId },
|
|
351
|
+
data: { emailVerified: true },
|
|
352
|
+
}),
|
|
353
|
+
]);
|
|
354
|
+
console.log(`[Auth] Email verified for user ${userId}`);
|
|
355
|
+
res.json({ message: 'Email verified successfully', verified: true });
|
|
356
|
+
}
|
|
357
|
+
catch (error) {
|
|
358
|
+
next(error);
|
|
359
|
+
}
|
|
360
|
+
});
|
|
361
|
+
// Resend verification email
|
|
362
|
+
authRouter.post('/resend-verification', requireAuth, async (req, res, next) => {
|
|
363
|
+
try {
|
|
364
|
+
const config = getConfig();
|
|
365
|
+
const userId = req.user.id;
|
|
366
|
+
// Check if user is already verified
|
|
367
|
+
const user = await db.user.findUnique({
|
|
368
|
+
where: { id: userId },
|
|
369
|
+
select: { emailVerified: true, email: true },
|
|
370
|
+
});
|
|
371
|
+
if (user?.emailVerified) {
|
|
372
|
+
res.json({ message: 'Email already verified' });
|
|
373
|
+
return;
|
|
374
|
+
}
|
|
375
|
+
// Check rate limiting - find the most recent verification code
|
|
376
|
+
const recentCode = await db.emailVerification.findFirst({
|
|
377
|
+
where: {
|
|
378
|
+
userId,
|
|
379
|
+
usedAt: null,
|
|
380
|
+
},
|
|
381
|
+
orderBy: { createdAt: 'desc' },
|
|
382
|
+
});
|
|
383
|
+
if (recentCode) {
|
|
384
|
+
const cooldownSeconds = config.auth.emailVerification?.allowResendAfterSeconds ?? 60;
|
|
385
|
+
const cooldownTime = new Date(recentCode.createdAt.getTime() + cooldownSeconds * 1000);
|
|
386
|
+
if (new Date() < cooldownTime) {
|
|
387
|
+
const remainingSeconds = Math.ceil((cooldownTime.getTime() - Date.now()) / 1000);
|
|
388
|
+
throw new AppError(HTTP_STATUS.TOO_MANY_REQUESTS, `Please wait ${remainingSeconds} seconds before requesting a new code`);
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
// Create and send new verification code
|
|
392
|
+
await createAndSendVerificationCode(userId, user.email);
|
|
393
|
+
res.json({ message: 'Verification code sent' });
|
|
394
|
+
}
|
|
395
|
+
catch (error) {
|
|
396
|
+
next(error);
|
|
397
|
+
}
|
|
398
|
+
});
|
|
399
|
+
//# sourceMappingURL=auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/api/auth.ts"],"names":[],"mappings":"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"}
|