Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 20 additions & 7 deletions sources/apollo/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ const StoryAPI = require('./stories/story.datasources.js');
const typeDefs = require('./schema.js');
const resolvers = require('./resolvers.js');
const {firebaseApp}=require("../helpers/firebase");
const {populatePermissions } = require("../helpers/permissions");
const { populatePermissions } = require("../helpers/permissions");

const NodeCache = require( "node-cache" );
const tokenCache = new NodeCache();


//Datasources
Expand Down Expand Up @@ -41,13 +44,23 @@ const server = new ApolloServer({
context: async ({ req }) => {
if (req.headers && req.headers.authorization) {
const idToken=req.headers.authorization;
try {
const decodedToken = await firebaseApp.auth().verifyIdToken(idToken)
const {uid} = decodedToken;
if(decodedToken.mongoID){
return {uid, permissions: await populatePermissions(decodedToken.mongoID)};
try {
console.time("firebase");

let userToken = tokenCache.get(idToken);
if (userToken === undefined) {
const decodedToken = await firebaseApp.auth().verifyIdToken(idToken)
// eslint-disable-next-line prefer-destructuring
userToken={ uid: decodedToken.uid, mongoID: decodedToken.mongoID }
tokenCache.set(idToken, userToken,36000);
}
Comment on lines +47 to +60
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Scenario
at t=0, Firebase minted JWT for the user
at t=30 min, App sent that token to the server
This caches the JWT for 60 mins, whereas it should cache only for 30 mins

Ideally
Store the exp of the JWT when you cache and check it also

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great Suggestion. Will do it soon! 🚀


console.timeEnd("firebase");

if(userToken.mongoID){
return {uid: userToken.uid, permissions: await populatePermissions(userToken.mongoID)};
}
return {uid, permissions: ["users.Auth"]};
return {uid: userToken.uid, permissions: ["users.Auth"]};

} catch (error) {
const errorMessage= error.errorInfo? error.errorInfo.message : error;
Expand Down
37 changes: 22 additions & 15 deletions sources/apollo/users/user.datasources.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,19 @@ class UserAPI extends DataSource {
getUserByUsername(username) {
return Users.findOne({ username });
}
async updateUserAfterSignUp(newUser,uid) {
const accessLevelObj = {
level: '1',
name:newUser.name,
user: newUser
};
const createdAccessLevel = await AccessLevel.create(accessLevelObj);
await newUser.clubAccess.push(createdAccessLevel);
await newUser.save();
if (process.env.NODE_ENV !== "test") {
firebase.updateJWT(uid,{mongoID:newUser._id});
}
}
/**
* Single function which handles both sign up and sign in of a user
* If the user already exists in the database, it simply fetches the existing doucment
Expand All @@ -28,9 +41,10 @@ class UserAPI extends DataSource {
* @param {String} uid firebase uid
* @returns {Object} created user object
*/
async authUser(user,uid) {
async authUser(user, uid) {
console.time("authuser");
let incomingUser;
const exisitingUser=await Users.findOne({firebaseUID:uid});
const exisitingUser=await Users.findOne({firebaseUID:uid}).lean();
// User document exists(Sign in)
if(exisitingUser){
incomingUser=exisitingUser;
Expand All @@ -48,19 +62,12 @@ class UserAPI extends DataSource {
emergencyContact: user.emergencyContact,
displayPicture: user.displayPicture,
});
const accessLevelObj = {
level: '1',
name:newUser.name,
user: newUser,
};
const createdAccessLevel = await AccessLevel.create(accessLevelObj);
await newUser.clubAccess.push(createdAccessLevel);
await newUser.save();
if (process.env.NODE_ENV !== "test") {
firebase.updateJWT(uid,{mongoID:newUser._id});
}
incomingUser= await Users.findOne({firebaseUID:uid})
this.updateUserAfterSignUp(newUser,uid)
// incomingUser = await Users.findOne({ firebaseUID: uid }).lean()
incomingUser = newUser
// console.log(newUser, incomingUser);
}
console.timeEnd("authuser");
return incomingUser;
}
/**
Expand Down Expand Up @@ -112,7 +119,7 @@ class UserAPI extends DataSource {
return {...INVALID_INPUT,message:"User Not Found"};
}

await Users.deleteOne({ id: foundUser._id })
await Users.deleteOne({ _id: foundUser._id })
await AccessLevel.deleteMany({ user: foundUser._id });

if(process.env.NODE_ENV !== "test") {
Expand Down
7 changes: 5 additions & 2 deletions sources/helpers/permissions.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,11 @@ const rolesPermissionsMap={
*
* @param {String} id Mongo User id
*/
const populatePermissions = async id => {
const userAccessLevels = await AccessLevels.find({ user: id })
const populatePermissions = async id => {
console.time("permission")
const userAccessLevels = await AccessLevels.find({ user: id }).select({club:1,level:1}).lean()

console.timeEnd("permission")
if(userAccessLevels===null){
throw new Error("User not found, Possibly outdated JWT")
}else{
Expand Down
3 changes: 2 additions & 1 deletion sources/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@
"firebase-admin": "^9.4.2",
"graphql": "^15.4.0",
"graphql-iso-date": "^3.6.1",
"mongoose": "^5.11.10"
"mongoose": "^5.11.10",
"node-cache": "^5.1.2"
},
"devDependencies": {
"apollo-server-testing": "^2.19.2",
Expand Down