Skip to content

Commit

Permalink
added authertication resolvers
Browse files Browse the repository at this point in the history
  • Loading branch information
jalajcodes committed Aug 7, 2020
1 parent 4e6f35d commit 152f237
Show file tree
Hide file tree
Showing 5 changed files with 184 additions and 0 deletions.
121 changes: 121 additions & 0 deletions src/graphql/resolvers/Viewer/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
import { IResolvers } from 'apollo-server-express';
import crypto from 'crypto';
import { Viewer, User, Database } from '../../../libs/types';
import { Google } from '../../../libs/api';
import { LogInArgs } from './types';

const loginViaGoogle = async (code: string, token: string, db: Database): Promise<User | undefined> => {
const { user } = await Google.login(code);
if (!user) {
throw new Error('Google Login Error');
}

// Names/Photos/Emails List
const userNamesList = user.names && user.names.length ? user.names : null;
const userPhotosList = user.photos && user.photos.length ? user.photos : null;
const userEmailsList = user.emailAddresses && user.emailAddresses.length ? user.emailAddresses : null;

// User Display Name
const userName = userNamesList ? userNamesList[0].displayName : null;

// User Id
const userId =
userNamesList && userNamesList[0].metadata && userNamesList[0].metadata.source
? userNamesList[0].metadata.source.id
: null;

// User Avatar
const userAvatar = userPhotosList && userPhotosList[0].url ? userPhotosList[0].url : null;

// User Email
const userEmail = userEmailsList && userEmailsList[0].value ? userEmailsList[0].value : null;

// Check above variables are not null
if (!userId || !userName || !userAvatar || !userEmail) {
throw new Error('Google login error');
}

// Finally, check if user already exists then update their data
const updateResult = await db.users.findOneAndUpdate(
{ _id: userId },
{
$set: {
name: userName,
avatar: userAvatar,
contact: userEmail,
token,
},
},
{ returnOriginal: false }
);

let viewer = updateResult.value;

// But if user don't exist, create one. (updateResult.value return the updated user details)
if (!viewer) {
const insertResult = await db.users.insertOne({
_id: userId,
token,
name: userName,
avatar: userAvatar,
contact: userEmail,
income: 0,
bookings: [],
listings: [],
});

viewer = insertResult.ops[0];
}
return viewer;
};

export const ViewerResolver: IResolvers = {
Query: {
authUrl: (): string => {
try {
return Google.authUrl;
} catch (error) {
throw new Error(`Failed to query Google Auth Url : ${error}`);
}
},
},
Mutation: {
login: async (root: undefined, { input }: LogInArgs, { db }): Promise<Viewer> => {
try {
const code = input ? input.code : null;
const token = crypto.randomBytes(16).toString('hex');

const viewer: User | undefined = code ? await loginViaGoogle(code, token, db) : undefined;

if (!viewer) {
return { didRequest: true };
}

return {
_id: viewer._id,
token: viewer.token,
avatar: viewer.avatar,
walletId: viewer.walletId,
didRequest: true,
};
} catch (err) {
throw new Error(`Unable to login: ${err}`);
}
},
logout: (): Viewer => {
try {
return { didRequest: true };
} catch (error) {
throw new Error(`Failed to log out: ${error}`);
}
},
},
Viewer: {
id: (viewer: Viewer): string | undefined => {
return viewer._id;
},
hasWallet: (viewer: Viewer): boolean | undefined => {
return viewer.walletId ? true : undefined;
},
},
};
3 changes: 3 additions & 0 deletions src/graphql/resolvers/Viewer/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export interface LogInArgs {
input: { code: string } | null;
}
25 changes: 25 additions & 0 deletions src/libs/api/Google.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { google } from 'googleapis';

const auth = new google.auth.OAuth2(
process.env.G_CLIENT_ID,
process.env.G_CLIENT_SECRET,
`${process.env.PUBLIC_URL}/login`
);

export const Google = {
authUrl: auth.generateAuthUrl({
access_type: 'online',
scope: ['https://www.googleapis.com/auth/userinfo.email', 'https://www.googleapis.com/auth/userinfo.profile'],
}),
login: async (code: string) => {
const { tokens } = await auth.getToken(code);
auth.setCredentials(tokens);

const { data } = await google.people({ version: 'v1', auth }).people.get({
resourceName: 'people/me',
personFields: 'emailAdresses,names,photos',
});

return { user: data };
},
};
1 change: 1 addition & 0 deletions src/libs/api/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './Google';
34 changes: 34 additions & 0 deletions src/temp/clear.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import dotenv from 'dotenv';
dotenv.config();

import { connectDatabase } from '../database';

const clear = async () => {
try {
console.log('[clear] : running...');

const db = await connectDatabase();

const bookings = await db.bookings.find({}).toArray();
const listings = await db.listings.find({}).toArray();
const users = await db.users.find({}).toArray();

if (bookings.length > 0) {
await db.bookings.drop();
}

if (listings.length > 0) {
await db.listings.drop();
}

if (users.length > 0) {
await db.users.drop();
}

console.log('[clear] : success');
} catch {
throw new Error('failed to clear database');
}
};

clear();

0 comments on commit 152f237

Please sign in to comment.