DEV Community

Tom Liang
Tom Liang

Posted on • Edited on

User validation with Passport.js and fp-ts

I had a first try on using fp-ts to do user validation with passport.js.

import argon2 from "argon2";
import * as E from "fp-ts/lib/Either";
import { flow, pipe } from "fp-ts/lib/function";
import * as O from "fp-ts/lib/Option";
import * as TE from "fp-ts/lib/TaskEither";
import * as passport from "passport";
import * as PassportLocal from "passport-local";
import logger from "./logger";
import {
    UserProfile,
    UserProfileRepository,
} from "../db/entities/user_profile";

const verifyPassport: PassportLocal.VerifyFunction = (
    userName: string,
    password: string,
    done
) => {
    const onUserFound = (optionUser: O.Option<UserProfile>) => {
        const onSome = (user: UserProfile) => () =>
            argon2
                .verify(user.userPassword, password)
                .then((valid) =>
                    valid
                        ? E.right(user)
                        : E.left(new Error(`invalid user name or password`))
                )
                .catch(E.left);
        const onNone = () =>
            TE.left(new Error(`user name ${userName} doesn't exist`));
        return pipe(optionUser, O.match(onNone, onSome));
    };
    pipe(
        userName,
        UserProfileRepository.findOneByUserName /*returns TE.TaskEither<Error, O.Option<UserProfile>> */,
        TE.chain(onUserFound),
        TE.bimap(
            ({ message }) => done(null, false, { message }),
            (user) => done(null, user)
        )
    )();
};

Enter fullscreen mode Exit fullscreen mode

Top comments (0)