feat: add organizations and members

This commit is contained in:
Mauricio Siu
2025-02-17 02:48:42 -06:00
parent c7d47a6003
commit b73e4102dd
17 changed files with 5385 additions and 329 deletions

View File

@@ -3,6 +3,7 @@ import { db } from "@dokploy/server/db";
import {
account,
type apiCreateUserInvitation,
invitation,
member,
organization,
users_temp,
@@ -64,6 +65,13 @@ export const findUserById = async (userId: string) => {
return user;
};
export const findOrganizationById = async (organizationId: string) => {
const organizationResult = await db.query.organization.findFirst({
where: eq(organization.id, organizationId),
});
return organizationResult;
};
export const updateUser = async (userId: string, userData: Partial<User>) => {
const user = await db
.update(users_temp)
@@ -106,24 +114,34 @@ export const isAdminPresent = async () => {
};
export const getUserByToken = async (token: string) => {
const user = await db.query.users_temp.findFirst({
where: eq(users_temp.token, token),
const user = await db.query.invitation.findFirst({
where: eq(invitation.id, token),
columns: {
id: true,
email: true,
token: true,
isRegistered: true,
status: true,
expiresAt: true,
role: true,
inviterId: true,
},
});
if (!user) {
throw new TRPCError({
code: "NOT_FOUND",
message: "Invitation not found",
});
}
const userAlreadyExists = await db.query.users_temp.findFirst({
where: eq(users_temp.email, user?.email || ""),
});
const { expiresAt, ...rest } = user;
return {
...user,
isExpired: user.isRegistered,
...rest,
isExpired: user.expiresAt < new Date(),
userAlreadyExists: !!userAlreadyExists,
};
};

View File

@@ -137,76 +137,76 @@ export const symmetricDecrypt = async ({ key, data }) => {
const chacha = managedNonce(xchacha20poly1305)(new Uint8Array(keyAsBytes));
return new TextDecoder().decode(chacha.decrypt(dataAsBytes));
};
export const migrateExistingSecret = async (
existingBase32Secret: string,
encryptionKey: string,
) => {
try {
// 1. Primero asegurarnos que el secreto base32 tenga el padding correcto
let paddedSecret = existingBase32Secret;
while (paddedSecret.length % 8 !== 0) {
paddedSecret += "=";
}
// export const migrateExistingSecret = async (
// existingBase32Secret: string,
// encryptionKey: string,
// ) => {
// try {
// // 1. Primero asegurarnos que el secreto base32 tenga el padding correcto
// let paddedSecret = existingBase32Secret;
// while (paddedSecret.length % 8 !== 0) {
// paddedSecret += "=";
// }
// 2. Decodificar el base32 a bytes usando hi-base32
const bytes = encode.decode.asBytes(paddedSecret.toUpperCase());
// // 2. Decodificar el base32 a bytes usando hi-base32
// const bytes = encode.decode.asBytes(paddedSecret.toUpperCase());
// 3. Convertir los bytes a hex
const hexSecret = Buffer.from(bytes).toString("hex");
// // 3. Convertir los bytes a hex
// const hexSecret = Buffer.from(bytes).toString("hex");
// 4. Encriptar el secreto hex usando Better Auth
const encryptedSecret = await symmetricEncrypt({
key: encryptionKey,
data: hexSecret,
});
// // 4. Encriptar el secreto hex usando Better Auth
// const encryptedSecret = await symmetricEncrypt({
// key: encryptionKey,
// data: hexSecret,
// });
// 5. Crear TOTP con el secreto original para validación
const originalTotp = new TOTP({
issuer: "Dokploy",
label: "migration-test",
algorithm: "SHA1",
digits: 6,
secret: existingBase32Secret,
});
// // 5. Crear TOTP con el secreto original para validación
// const originalTotp = new TOTP({
// issuer: "Dokploy",
// label: "migration-test",
// algorithm: "SHA1",
// digits: 6,
// secret: existingBase32Secret,
// });
// 6. Generar un código de prueba con el secreto original
const testCode = originalTotp.generate();
// // 6. Generar un código de prueba con el secreto original
// const testCode = originalTotp.generate();
// 7. Validar que el código funcione con el secreto original
const isValid = originalTotp.validate({ token: testCode }) !== null;
// // 7. Validar que el código funcione con el secreto original
// const isValid = originalTotp.validate({ token: testCode }) !== null;
return {
originalSecret: existingBase32Secret,
hexSecret,
encryptedSecret, // Este es el valor que debes guardar en la base de datos
isValid,
testCode,
secretLength: hexSecret.length,
};
} catch (error: unknown) {
const errorMessage =
error instanceof Error ? error.message : "Unknown error";
console.error("Error durante la migración:", errorMessage);
throw new Error(`Error al migrar el secreto: ${errorMessage}`);
}
};
// return {
// originalSecret: existingBase32Secret,
// hexSecret,
// encryptedSecret, // Este es el valor que debes guardar en la base de datos
// isValid,
// testCode,
// secretLength: hexSecret.length,
// };
// } catch (error: unknown) {
// const errorMessage =
// error instanceof Error ? error.message : "Unknown error";
// console.error("Error durante la migración:", errorMessage);
// throw new Error(`Error al migrar el secreto: ${errorMessage}`);
// }
// };
// // Ejemplo de uso con el secreto de prueba
// const testMigration = await migrateExistingSecret(
// "46JMUCG4NJ3CIU6LQAIVFWUW",
// process.env.BETTER_AUTH_SECRET || "your-encryption-key",
// );
// console.log("\nPrueba de migración:");
// console.log("Secreto original (base32):", testMigration.originalSecret);
// console.log("Secreto convertido (hex):", testMigration.hexSecret);
// console.log("Secreto encriptado:", testMigration.encryptedSecret);
// console.log("Longitud del secreto hex:", testMigration.secretLength);
// console.log("¿Conversión válida?:", testMigration.isValid);
// console.log("Código de prueba:", testMigration.testCode);
const secret = "46JMUCG4NJ3CIU6LQAIVFWUW";
const isValid = createOTP(secret, {
digits: 6,
period: 30,
}).verify("123456");
// // // Ejemplo de uso con el secreto de prueba
// // const testMigration = await migrateExistingSecret(
// // "46JMUCG4NJ3CIU6LQAIVFWUW",
// // process.env.BETTER_AUTH_SECRET || "your-encryption-key",
// // );
// // console.log("\nPrueba de migración:");
// // console.log("Secreto original (base32):", testMigration.originalSecret);
// // console.log("Secreto convertido (hex):", testMigration.hexSecret);
// // console.log("Secreto encriptado:", testMigration.encryptedSecret);
// // console.log("Longitud del secreto hex:", testMigration.secretLength);
// // console.log("¿Conversión válida?:", testMigration.isValid);
// // console.log("Código de prueba:", testMigration.testCode);
// const secret = "46JMUCG4NJ3CIU6LQAIVFWUW";
// const isValid = createOTP(secret, {
// digits: 6,
// period: 30,
// }).verify("123456");
console.log(isValid.then((isValid) => console.log(isValid)));
// console.log(isValid.then((isValid) => console.log(isValid)));