lucia-auth / lucia

Authentication, simple and clean
https://lucia-auth.com
MIT License
8.61k stars 448 forks source link

[Bug]: Mongoose adapter - insertOne doesn't exist & 2 more bugs #1440

Closed ArthurOnTime closed 5 months ago

ArthurOnTime commented 5 months ago

Package

​@lucia-auth/adapter-mongodb

Describe the bug

At the moment, using mongoose with the mongodb adapter doesn't work.

  1. insertOne() doesn't exist in mongoose. mongoose uses create() instead.

    Can be fixed by - line 58 - in setSession() : replacing await this.Session.insertOne(value); // MUST be replaced for Mongoose by await this.Session.create(value); // WORKS for Mongoose

does the trick for mongoose but won't probably work for mongodb.

  1. this.User.collectionName doesn't exist in mongoose. mongoose uses this.User.collection.name

    Can be fixed by - line 20 - in getSessionAndUser() : replacing from: this.User.collectionName, by from: this.User.collection.name,

don't know whether collectionName works for mongodb without mongoose

  1. TypeError: cursor.toArray is not a function (I suppose it has to do with mongoose)

    Can be fixed by - line 28 & 29 - in getSessionAndUser() : replacing const sessionUsers = await cursor.toArray(); AND const sessionUser = sessionUsers?.at(0) ?? null; by const sessionUser = cursor?.at(0) ?? null;

By fixing these 3 issues in @lucia-auth/adapter-mongodb, I get the login & logout flow to work (I'm using Discord connect only) on my expressJS server.

I suppose the simplest solution would be to clone adapter-mongodb and create adapter-mongoose with the fix.

PS: I love you work and I'm looking fwd to the fix so I can push to prod :)

pilcrowOnPaper commented 5 months ago

How are you initializing the MongoDB adapter?

ArthurOnTime commented 5 months ago

import { MongodbAdapter } from '@lucia-auth/adapter-mongodb';

import User from '../mongodb/models/users.js'; // mongoose model import Session from '../mongodb/models/sessions.js'; // mongoose model

const adapter = new MongodbAdapter( Session, User );

export const lucia = new Lucia( adapter, { sessionCookie: { attributes: { secure: process.env.NODE_ENV === "production" } }, getUserAttributes: (attributes) => { return { discordId: attributes.discord_id, username: attributes.username, }; } });

pilcrowOnPaper commented 5 months ago

What's Session and User?

ArthurOnTime commented 5 months ago

Session import mongodb from 'mongoose';

const Session = mongodb.models.Session || mongodb.model("Session", new mongodb.Schema( { _id: { type: String, required: true }, user_id: { type: mongodb.Schema.Types.ObjectId, ref: 'User', required: true }, expires_at: { type: Date, required: true } }, { _id: false } ));

export default Session; User import mongodb from 'mongoose';

const User = mongodb.models.User || mongodb.model("User", new mongodb.Schema( { _id: { type: mongodb.Schema.Types.ObjectId, required: true }, discordId: { type: String, required: false }, createdAtTimestamp: { type: Date, required: false }, username: { type: String, required: true }, globalName: { type: String, required: false }, discriminator: { type: String, required: false }, isBot: { type: Boolean, required: false }, isSystem: { type: Boolean, required: false }, avatar: { type: String, required: false }, banner: { type: String, required: false }, permissions: { type: [String], // This specifies that "roles" is an array of strings required: false }, roles: { type: [String], // This specifies that "roles" is an array of strings required: false }, }, { _id: false } ));

export default User;

pilcrowOnPaper commented 5 months ago

This is expected since the adapter doesn't accept a Mongoose schema and instead accepts a MongoDB collection

Mongoose example: https://lucia-auth.com/database/mongoose

ArthurOnTime commented 5 months ago

Indeed. I confirm everything works by passing a MongoDB collection. Thanks a lot.