128 lines
3.4 KiB
TypeScript
128 lines
3.4 KiB
TypeScript
import { createClient, type GenericCtx } from '@convex-dev/better-auth';
|
|
import { convex } from '@convex-dev/better-auth/plugins';
|
|
import { components } from './_generated/api';
|
|
import { type DataModel } from './_generated/dataModel';
|
|
import { MutationCtx, query, QueryCtx } from './_generated/server';
|
|
import { betterAuth } from 'better-auth';
|
|
|
|
// Usar SITE_URL se disponível, caso contrário usar CONVEX_SITE_URL ou um valor padrão
|
|
const siteUrl = process.env.SITE_URL || process.env.CONVEX_SITE_URL || 'http://localhost:5173';
|
|
|
|
// The component client has methods needed for integrating Convex with Better Auth,
|
|
// as well as helper methods for general use.
|
|
export const authComponent = createClient<DataModel>(components.betterAuth);
|
|
|
|
export const createAuth = (
|
|
ctx: GenericCtx<DataModel>,
|
|
{ optionsOnly } = { optionsOnly: false }
|
|
) => {
|
|
return betterAuth({
|
|
// disable logging when createAuth is called just to generate options.
|
|
// this is not required, but there's a lot of noise in logs without it.
|
|
logger: {
|
|
disabled: optionsOnly
|
|
},
|
|
baseURL: siteUrl,
|
|
database: authComponent.adapter(ctx),
|
|
// Configure simple, non-verified email/password to get started
|
|
emailAndPassword: {
|
|
enabled: true,
|
|
requireEmailVerification: false
|
|
},
|
|
plugins: [
|
|
// The Convex plugin is required for Convex compatibility
|
|
convex()
|
|
]
|
|
});
|
|
};
|
|
|
|
// Example function for getting the current user
|
|
// Feel free to edit, omit, etc.
|
|
export const getCurrentUser = query({
|
|
args: {},
|
|
handler: async (ctx) => {
|
|
try {
|
|
const authUser = await authComponent.safeGetAuthUser(ctx);
|
|
if (!authUser) {
|
|
return;
|
|
}
|
|
|
|
const user = await ctx.db
|
|
.query('usuarios')
|
|
.withIndex('authId', (q) => q.eq('authId', authUser._id))
|
|
.unique();
|
|
|
|
if (!user) {
|
|
return;
|
|
}
|
|
|
|
// Buscar foto de perfil e role em paralelo para melhor performance
|
|
const [fotoPerfilUrl, role] = await Promise.all([
|
|
user.fotoPerfil ? ctx.storage.getUrl(user.fotoPerfil).catch(() => null) : Promise.resolve(null),
|
|
user.roleId
|
|
? ctx.db
|
|
.query('roles')
|
|
.withIndex('by_id', (q) => q.eq('_id', user.roleId))
|
|
.unique()
|
|
.catch(() => null)
|
|
: Promise.resolve(null)
|
|
]);
|
|
|
|
return { ...user, role: role || null, fotoPerfilUrl };
|
|
} catch (error) {
|
|
// Log do erro mas não falhar completamente - retornar null para permitir retry
|
|
console.error('Erro ao buscar usuário atual:', error);
|
|
return;
|
|
}
|
|
}
|
|
});
|
|
|
|
export const getCurrentUserFunction = async (ctx: QueryCtx | MutationCtx) => {
|
|
const authUser = await authComponent.safeGetAuthUser(ctx);
|
|
if (!authUser) {
|
|
return;
|
|
}
|
|
|
|
const user = await ctx.db
|
|
.query('usuarios')
|
|
.withIndex('authId', (q) => q.eq('authId', authUser._id))
|
|
.unique();
|
|
if (!user) {
|
|
return;
|
|
}
|
|
return user;
|
|
};
|
|
|
|
export const createAuthUser = async (
|
|
ctx: MutationCtx,
|
|
args: { nome: string; email: string; password: string }
|
|
) => {
|
|
const { auth, headers } = await authComponent.getAuth(createAuth, ctx);
|
|
|
|
const result = await auth.api.signUpEmail({
|
|
headers,
|
|
body: {
|
|
name: args.nome,
|
|
email: args.email,
|
|
password: args.password
|
|
}
|
|
});
|
|
|
|
return result.user.id;
|
|
};
|
|
|
|
export const updatePassword = async (
|
|
ctx: MutationCtx,
|
|
args: { newPassword: string; currentPassword: string }
|
|
) => {
|
|
const { auth, headers } = await authComponent.getAuth(createAuth, ctx);
|
|
|
|
await auth.api.changePassword({
|
|
headers,
|
|
body: {
|
|
currentPassword: args.currentPassword,
|
|
newPassword: args.newPassword
|
|
}
|
|
});
|
|
};
|