Skip to content

Instantly share code, notes, and snippets.

@Tsugami
Created October 15, 2021 21:40
Show Gist options
  • Save Tsugami/23f83e31db9fb4c1f786f9a857435048 to your computer and use it in GitHub Desktop.
Save Tsugami/23f83e31db9fb4c1f786f9a857435048 to your computer and use it in GitHub Desktop.
MongooseNextAuthAdapter.
import mongoose, { Types, Document } from 'mongoose';
import {
Adapter,
AdapterUser,
AdapterSession,
VerificationToken as AdapterVerificationToken,
} from 'next-auth/adapters';
import { Account as AdapterAccount } from 'next-auth';
import UserModel, { IUser } from '../modules/user/UserModel';
import AccountModel, { IAccount } from '../modules/auth/AccountModel';
import SessionModel, { ISession } from '../modules/auth/SessionModel';
import VerificationTokenModel from '../modules/auth/VerificationTokenModel';
function _id(hex?: string) {
if (hex?.length !== 24) return new Types.ObjectId();
return new Types.ObjectId(hex);
}
const from = <A>(data: Document): A => {
return {
...data,
id: data._id,
} as unknown as A;
};
const adapterUser = (user: IUser): AdapterUser => from<AdapterUser>(user);
const adapterAccount = (account: IAccount): AdapterAccount => from<AdapterAccount>(account);
const adapterSession = (session: ISession): AdapterSession => from<AdapterSession>(session);
const MongooseNextAuthAdapter = (): Adapter => {
return {
createUser: async (user) => {
const newUser = await UserModel.create(user);
return adapterUser(newUser);
},
getUser: async (id) => {
const user = await UserModel.findOne({ _id: _id(id) });
if (!user) return null;
return adapterUser(user);
},
getUserByEmail: async (email) => {
const user = await UserModel.findOne({ email });
if (!user) return null;
return adapterUser(user);
},
getUserByAccount: async (provider) => {
const account = await AccountModel.findOne(provider);
if (!account) return null;
const user = await UserModel.findOne({ _id: account.userId });
if (!user) return null;
return adapterUser(user);
},
async updateUser(data) {
await UserModel.updateOne({ _id: _id(data.id) }, { $set: data });
return MongooseNextAuthAdapter().getUser(data.id as string) as AdapterUser;
},
deleteUser: async (userId) => {
const session = await mongoose.startSession();
AccountModel.deleteMany({ userId }, { session });
SessionModel.deleteMany({ userId }, { session });
UserModel.deleteOne({ _id: userId }, { session });
await session.endSession();
},
linkAccount: async (account) => {
const newaAcount = await AccountModel.create(account);
return adapterAccount(newaAcount);
},
async unlinkAccount(accountProvider) {
await AccountModel.deleteOne(accountProvider);
},
createSession: async (data) => {
const newSession = await SessionModel.create(data);
return adapterSession(newSession);
},
getSessionAndUser: async (sessionToken) => {
const session = await SessionModel.findOne({ sessionToken: sessionToken });
if (!session) return null;
const user = await UserModel.findOne({ _id: session.userId });
if (!user) return null;
return { session: adapterSession(session), user: adapterUser(user) };
},
async updateSession(data) {
await SessionModel.updateOne(
{
sessionToken: data.sessionToken,
},
{ $set: data },
);
const session = await SessionModel.findOne({
sessionToken: data.sessionToken,
});
return session ? adapterSession(session) : null;
},
async deleteSession(sessionToken) {
await SessionModel.deleteOne({ sessionToken });
},
async createVerificationToken(data) {
await VerificationTokenModel.create(data);
return data;
},
async useVerificationToken(identifier_token) {
const data = await VerificationTokenModel.findOne(identifier_token);
if (!data) return null;
await VerificationTokenModel.deleteOne(identifier_token);
return from<AdapterVerificationToken>(data);
},
};
};
export default MongooseNextAuthAdapter;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment