2025-06-23 09:34:30 +00:00
|
|
|
import { Hono } from "hono";
|
2025-10-05 08:45:39 +00:00
|
|
|
import { authMiddleware, streamChatMiddleware } from "./middleware.js";
|
2025-07-01 20:28:49 +00:00
|
|
|
import type { SupabaseClient, User } from "@supabase/supabase-js";
|
2025-06-23 09:34:30 +00:00
|
|
|
import { StreamChat } from "stream-chat";
|
2025-07-01 20:28:49 +00:00
|
|
|
import type { Transporter } from "nodemailer";
|
2025-09-23 20:14:02 +00:00
|
|
|
import type { Tables } from "./database.types.ts";
|
2025-10-05 08:45:39 +00:00
|
|
|
import { transporter } from "./transporter.js";
|
2025-06-23 09:34:30 +00:00
|
|
|
|
|
|
|
|
export const userRouter = new Hono<{
|
|
|
|
|
Variables: {
|
|
|
|
|
user: User;
|
2025-07-01 20:28:49 +00:00
|
|
|
supabase: SupabaseClient;
|
|
|
|
|
transporter: Transporter;
|
2025-07-05 13:16:42 +00:00
|
|
|
streamServerClient: StreamChat;
|
2025-06-23 09:34:30 +00:00
|
|
|
};
|
|
|
|
|
}>();
|
|
|
|
|
|
|
|
|
|
userRouter.use(authMiddleware);
|
2025-07-05 13:16:42 +00:00
|
|
|
userRouter.use(streamChatMiddleware);
|
2025-06-23 09:34:30 +00:00
|
|
|
|
2025-07-05 13:16:42 +00:00
|
|
|
userRouter.post("/sign-up-to-stream", async (c) => {
|
|
|
|
|
const { id } = c.get("user");
|
|
|
|
|
const supabase = c.get("supabase");
|
2025-06-23 09:34:30 +00:00
|
|
|
|
2025-07-05 13:16:42 +00:00
|
|
|
const { data } = await supabase
|
|
|
|
|
.from("profiles")
|
|
|
|
|
.select("*")
|
|
|
|
|
.eq("id", id)
|
|
|
|
|
.single();
|
2025-06-24 20:15:46 +00:00
|
|
|
|
2025-07-05 13:16:42 +00:00
|
|
|
const user = data as Tables<"profiles">;
|
|
|
|
|
|
|
|
|
|
const streamServerClient = c.get("streamServerClient");
|
|
|
|
|
await streamServerClient.upsertUser({
|
|
|
|
|
id,
|
|
|
|
|
name: user.name ?? "",
|
|
|
|
|
language: "fr",
|
|
|
|
|
});
|
2025-06-23 09:34:30 +00:00
|
|
|
|
|
|
|
|
return c.json({
|
2025-07-05 13:16:42 +00:00
|
|
|
message: "User signed up to stream",
|
2025-06-23 09:34:30 +00:00
|
|
|
});
|
|
|
|
|
});
|
2025-07-01 20:28:49 +00:00
|
|
|
|
2025-07-05 13:16:42 +00:00
|
|
|
userRouter.get("/me", async (c) => {
|
|
|
|
|
const user = c.get("user");
|
2025-07-03 19:42:49 +00:00
|
|
|
const supabase = c.get("supabase");
|
2025-07-05 13:16:42 +00:00
|
|
|
const streamServerClient = c.get("streamServerClient");
|
2025-07-01 20:28:49 +00:00
|
|
|
|
2025-07-05 13:16:42 +00:00
|
|
|
const { data, error } = await supabase
|
|
|
|
|
.from("profiles")
|
2025-07-03 19:42:49 +00:00
|
|
|
.select("*")
|
2025-07-05 13:16:42 +00:00
|
|
|
.eq("id", user.id)
|
2025-07-03 19:42:49 +00:00
|
|
|
.single();
|
|
|
|
|
|
2025-07-05 13:16:42 +00:00
|
|
|
const userData = data as Tables<"profiles">;
|
2025-07-03 20:24:41 +00:00
|
|
|
|
2025-07-05 13:16:42 +00:00
|
|
|
if (!userData) {
|
|
|
|
|
return c.json({ error: "User not found" }, 404);
|
2025-07-03 19:42:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (error) {
|
|
|
|
|
return c.json({ error: error.message }, 500);
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-05 13:16:42 +00:00
|
|
|
const user_id = data.id;
|
|
|
|
|
const token = streamServerClient.createToken(user_id);
|
2025-07-01 20:28:49 +00:00
|
|
|
|
2025-07-03 19:42:49 +00:00
|
|
|
return c.json({
|
2025-07-05 13:16:42 +00:00
|
|
|
...userData,
|
|
|
|
|
streamToken: token,
|
2025-07-03 19:42:49 +00:00
|
|
|
});
|
2025-07-01 20:28:49 +00:00
|
|
|
});
|
2025-10-02 16:45:35 +00:00
|
|
|
|
|
|
|
|
userRouter.post("/mark-temporary", async (c) => {
|
|
|
|
|
const user = c.get("user");
|
|
|
|
|
const supabase = c.get("supabase");
|
|
|
|
|
|
|
|
|
|
const body = await c.req.json();
|
|
|
|
|
const { temporary_password } = body;
|
|
|
|
|
|
|
|
|
|
const { data: profile, error } = await supabase
|
|
|
|
|
.from("profiles")
|
|
|
|
|
.update({
|
|
|
|
|
is_temporary: true,
|
|
|
|
|
})
|
|
|
|
|
.eq("id", user.id)
|
|
|
|
|
.select()
|
|
|
|
|
.single();
|
|
|
|
|
|
|
|
|
|
if (error) {
|
|
|
|
|
return c.json({ error: error.message }, 500);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
if (profile?.email) {
|
|
|
|
|
const mailOptions = {
|
|
|
|
|
from: process.env.EMAIL_USER,
|
|
|
|
|
to: profile.email,
|
|
|
|
|
subject: "Bienvenue sur XTablo - Votre mot de passe temporaire",
|
|
|
|
|
text: `Bienvenue sur XTablo !
|
|
|
|
|
|
|
|
|
|
Votre compte a été créé avec succès. Voici vos informations de connexion :
|
|
|
|
|
|
|
|
|
|
Email : ${profile.email}
|
|
|
|
|
Mot de passe temporaire : ${temporary_password}
|
|
|
|
|
|
|
|
|
|
Pour des raisons de sécurité, nous vous recommandons fortement de changer ce mot de passe temporaire lors de votre première connexion.
|
|
|
|
|
|
|
|
|
|
Connectez-vous sur : ${process.env.FRONTEND_URL || "https://app.xtablo.com"}
|
|
|
|
|
|
|
|
|
|
Cordialement,
|
|
|
|
|
L'équipe XTablo`,
|
|
|
|
|
html: `
|
|
|
|
|
<div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto;">
|
|
|
|
|
<h2 style="color: #333;">Bienvenue sur XTablo !</h2>
|
|
|
|
|
|
|
|
|
|
<p>Votre compte a été créé avec succès. Voici vos informations de connexion :</p>
|
|
|
|
|
|
|
|
|
|
<div style="background-color: #f5f5f5; padding: 15px; border-radius: 5px; margin: 20px 0;">
|
|
|
|
|
<p><strong>Email :</strong> ${profile.email}</p>
|
|
|
|
|
<p><strong>Mot de passe temporaire :</strong> <code style="background-color: #e1e1e1; padding: 2px 4px; border-radius: 3px;">${temporary_password}</code></p>
|
|
|
|
|
</div>
|
|
|
|
|
|
2025-10-02 17:54:42 +00:00
|
|
|
<p style="color: #d9534f; margin-bottom: 20px;"><strong>Important :</strong> Pour des raisons de sécurité, nous vous recommandons fortement de changer ce mot de passe temporaire lors de votre première connexion.</p>
|
2025-10-02 16:45:35 +00:00
|
|
|
|
|
|
|
|
<p>
|
|
|
|
|
<a href="${process.env.FRONTEND_URL || "https://app.tablo.fr"}"
|
|
|
|
|
style="background-color: #007bff; color: white; padding: 10px 20px; text-decoration: none; border-radius: 5px; display: inline-block;">
|
|
|
|
|
Se connecter à XTablo
|
|
|
|
|
</a>
|
|
|
|
|
</p>
|
|
|
|
|
|
|
|
|
|
<p style="color: #666; font-size: 14px; margin-top: 30px;">
|
|
|
|
|
Cordialement,<br>
|
|
|
|
|
L'équipe XTablo
|
|
|
|
|
</p>
|
|
|
|
|
</div>
|
|
|
|
|
`,
|
|
|
|
|
};
|
|
|
|
|
await transporter.sendMail(mailOptions);
|
|
|
|
|
console.log(`Sending welcome email to temporary user: ${profile.email}`);
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error("Failed to send welcome email:", error);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return c.json({
|
|
|
|
|
message: "User marked as temporary",
|
|
|
|
|
});
|
|
|
|
|
});
|