very-express
Version:
based on json schema and openapi, generate Express RestApi server with mongoDb
87 lines (74 loc) • 3.01 kB
text/typescript
// {{headerComment}}
import { UserModel, UserDocument } from "./../../_models/UserModel.gen";
import { User } from "./../../_types/User.gen";
import profileMapping, { IProfile } from "./profileMapping.gen";
import { sanitizeUser } from "./token.gen";
import vex from "../../_utils/index.gen";
export default async function oauthVerify(accessToken: string, refreshToken: string, profile: IProfile, done: (error: any, user?: any) => void) : Promise<void> {
try {
let user: UserDocument;
const authUser = profileMapping(profile);
// find user by authProfiles.authId or email
const existingUser = await UserModel.findOne<UserDocument>({
email: authUser.email,
$or: authUser.authProfiles?.map((p) => {
return { "authProfiles.authId": p.authId };
}),
});
// 1. create new user
if ( !existingUser ){
user = await createNewUser(authUser);
}
// 2. update existing user
else {
console.log("OAuthVerify UpdateUser");
user = await processExistingUser(authUser, existingUser);
}
// set req.user
done(null, {
provider: profile.provider,
profile: sanitizeUser(user),
});
}
catch(err) {
return done(err);
}
}
async function createNewUser(authProfile: User): Promise<UserDocument>{
vex.log.info("OAuthVerify > createNewUser");
const newUser = new UserModel(authProfile);
return await newUser.save();
}
async function processExistingUser( authUser: User, existingUser: UserDocument): Promise<UserDocument>{
vex.log.info("OAuthVerify > processExistingUser");
let userUpdated = false;
const authProfile = authUser.authProfiles?.[0] || undefined;
const userProfiles = existingUser.authProfiles as User["authProfiles"] || [];
if(!authProfile){
vex.log.errorNoExit("OAuthVerify > Invalid OAuth Callback \"authProfile\"");
throw new Error("Invalid OAuth Callback \"authProfile\"");
}
// B.1. check current provider exist in authProfiles
const providerExists = userProfiles.length > 0 && userProfiles.find((p) => {
return (p.provider === authProfile.provider) && (p.authId === authProfile.authId);
});
// B.2. add if not exist
if (!providerExists){
vex.log.info("OAuthVerify > add new provider",authProfile.provider);
userProfiles.push(authProfile);
userUpdated = true;
}
// B.3 update if username changed
else if (providerExists && providerExists.username !== authProfile.username){
vex.log.info("OAuthVerify > update username", authProfile.provider);
providerExists.username = authProfile.username;
userUpdated = true;
}
if (userUpdated){
vex.log.info("OAuthVerify > Update user");
return await existingUser.updateOne({ authProfiles: userProfiles });
}
else {
return existingUser;
}
}