-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
4e6f35d
commit 152f237
Showing
5 changed files
with
184 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
}, | ||
}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
export interface LogInArgs { | ||
input: { code: string } | null; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 }; | ||
}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from './Google'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); |