No more promises except the needed ones

This commit is contained in:
Luis Fernando Molina committed 2018-09-09 19:46:24 +02:00
1 parent 76da420e2a
commit 4490041a8a
6 files changed
+258 -122

No files matched your search

+2 -2
View File
@@ -11,8 +11,8 @@ class LoggedInUser extends Component {
const user = this.props.data.userByAuthId;
console.log('loggedInUser');
console.log(user);
console.log('loggedInUser data', this.props.data);
console.log('loggedInUser', user);
if(user){
+3 -1
View File
@@ -55,7 +55,9 @@ class NavBar extends Component {
if (userStored !== null && userStored !== undefined && userStored !== 'undefined') {
const user = JSON.parse(userStored);
const authId = user.authId;
const authId = user.sub;
console.log("user", user);
console.log("authid", authId);
this.setState({ authId: authId });
}
}
+34 -2
View File
@@ -1,3 +1,35 @@
/* Debugging */
global.INFO_LOG = true;
global.ERROR_LOG = true;
/* Callbacks default responses. */
global.DEFAULT_OK_RESPONSE = {
result: "Ok",
message: "Operation Succeeded"
};
global.DEFAULT_FAIL_RESPONSE = {
result: "Fail",
message: "Operation Failed"
};
global.DEFAULT_RETRY_RESPONSE = {
result: "Retry",
message: "Retry Later"
};
global.CUSTOM_OK_RESPONSE = {
result: "Ok, but check Message",
message: "Custom Message"
};
global.CUSTOM_FAIL_RESPONSE = {
result: "Fail Because",
message: "Custom Message"
};
const express = require('express');
const graphqlHTTP = require('express-graphql');
const schema = require('./schema/schema');
@@ -19,6 +51,8 @@ mongoose.connection.once('open', () => {
console.log('Connected to database');
})
/* Here we bind all requests to this endpoint to be procecced by the GraphQL Library. */
app.get('/graphql', graphqlHTTP({
schema,
graphiql: true
@@ -39,8 +73,6 @@ app.post('/graphql', checkJwt, (err, req, res, next) => {
app.post('/graphql', (req, res, done) => getUser(req, res, done));
app.listen(4000,() => {
console.log('Now listening for requests on port 4000');
});
+91
View File
@@ -0,0 +1,91 @@
const MODULE_NAME = "TokenDecoder";
/*
JSON Web Token (JWT) is a compact, URL-safe means of representing
claims to be transferred between two parties. The claims in a JWT
are encoded as a JSON object that is used as the payload of a JSON
Web Signature (JWS) structure or as the plaintext of a JSON Web
Encryption (JWE) structure, enabling the claims to be digitally
signed or integrity protected with a Message Authentication Code
(MAC) and/or encrypted.
*/
const JSONWebToken = require('jsonwebtoken'); // A library to deal with JSON Web Tokens.
const webTokenLibrary = require('jwks-rsa'); // A library to retrieve RSA signing keys from a JWKS (JSON Web Key Set) endpoint.
const AUTH_CONFIG = require('./Auth0'); // Config where we have our secrets.
const decoder = webTokenLibrary({
cache: true,
rateLimit: true,
jwksRequestsPerMinute: 1,
jwksUri: `https://${AUTH_CONFIG.domain}/.well-known/jwks.json`
})
function decodeToken (token, callBackFunction) {
try{
if (global.INFO_LOG === true) { console.log("[INFO] " + MODULE_NAME + " -> decodeToken -> Entering function."); }
const decoded = JSONWebToken.decode(token, { complete: true });
const header = decoded.header;
const payload = decoded.payload;
if (
header === null ||
header.kid === null ||
payload === null
) {
if (global.ERROR_LOG === true) { console.log ("[ERROR] " + MODULE_NAME + " -> decodeToken -> Invalid Token. "); }
if (global.ERROR_LOG === true) { console.log ("[ERROR] " + MODULE_NAME + " -> decodeToken -> token = " + token); }
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
return;
}
decoder.getSigningKey(header.kid, onKeyReady);
function onKeyReady(err, key) {
if (global.INFO_LOG === true) { console.log("[INFO] " + MODULE_NAME + " -> decodeToken -> onKeyReady -> Entering function."); }
if (err) {
if (global.ERROR_LOG === true) { console.log ("[ERROR] " + MODULE_NAME + " -> decodeToken -> onKeyReady -> Error getting the key. "); }
if (global.ERROR_LOG === true) { console.log ("[ERROR] " + MODULE_NAME + " -> decodeToken -> onKeyReady -> key = " + key); }
if (global.ERROR_LOG === true) { console.log ("[ERROR] " + MODULE_NAME + " -> decodeToken -> onKeyReady -> err = " + err); }
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
return;
}
JSONWebToken.verify(
token,
key.publicKey,
{ algorithms: ['RS256'] },
onVerified);
function onVerified(err, decoded) {
if (global.INFO_LOG === true) { console.log("[INFO] " + MODULE_NAME + " -> decodeToken -> onKeyReady -> onVerified -> Entering function."); }
if (err) {
if (global.ERROR_LOG === true) { console.log ("[ERROR] " + MODULE_NAME + " -> decodeToken -> onKeyReady -> onVerified -> Error verifying. "); }
if (global.ERROR_LOG === true) { console.log ("[ERROR] " + MODULE_NAME + " -> decodeToken -> onKeyReady -> onVerified -> decoded = " + decoded); }
if (global.ERROR_LOG === true) { console.log ("[ERROR] " + MODULE_NAME + " -> decodeToken -> onKeyReady -> onVerified -> err = " + err); }
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
return;
}
callBackFunction(global.DEFAULT_OK_RESPONSE, decoded);
}
}
} catch(err) {
if (global.ERROR_LOG === true) { console.log("[ERROR] " + MODULE_NAME + " -> decodeToken -> err = " + err); }
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
}
}
module.exports = decodeToken;
-69
View File
@@ -1,69 +0,0 @@
const _get = require('lodash.get')
const validateParseIdToken = require('./validate-auth0-token')
const createUser = require('./index')
const userLocationOnContext = 'request.user'
const bearerAccessToken = 'request.headers.authorization'
const ctxUser = ctx => _get(ctx, userLocationOnContext)
const ctxToken = ctx => _get(ctx, bearerAccessToken)
const isLoggedIn = async ctx => {
let user = ctxUser(ctx, userLocationOnContext)
let token = ctxToken(ctx, bearerAccessToken)
let userToken
if (!user && token) {
let scheme, credentials
const tokenParts = token.split(' ')
if (tokenParts.length === 2) {
scheme = tokenParts[0]
credentials = tokenParts[1]
}
if (/^Bearer$/i.test(scheme)) {
token = credentials
//verify token
try {
userToken = await validateParseIdToken(token)
const auth0id = userToken.sub
user = await ctx.db.query.user({ where: { auth0id } })
if (!user) {
user = await createUser(ctx, userToken)
}
} catch (err) {
userToken = false
}
}
}
if (!user) {
throw new Error(`Not logged in`)
}
return user
}
const isRequestingUserAlsoOwner = ({ ctx, userId, type, typeId }) =>
ctx.db.exists[type]({ id: typeId, owner: { auth0id: userId } })
const isRequestingUser = ({ ctx, userId }) => ctx.db.exists.User({ auth0id: userId })
const directiveResolvers = {
isAuthenticated: async (next, source, args, ctx) => {
let result = await isLoggedIn(ctx)
console.log('directive isAuthenticated: ', result)
return next(result)
},
hasRole: (next, source, { roles }, ctx) => {
const { role } = isLoggedIn(ctx)
console.log('directive hasRole: ', role)
if (roles.includes(role)) {
return next()
}
throw new Error(`Unauthorized, incorrect role`)
}
}
module.exports = { directiveResolvers }
+128 -48
View File
@@ -1,8 +1,10 @@
const MODULE_NAME = "schema";
const graphql = require('graphql');
const _ = require('lodash');
const User = require('../models/user');
const validateParseIdToken = require('../auth/validate-auth0-token');
const tokenDecoder = require('../auth/TokenDecoder');
const {
GraphQLObjectType,
@@ -79,19 +81,59 @@ const RootQuery = new GraphQLObjectType({
resolve(parent,args) {
// Code to get data from data source.
if (INFO_LOG === true) { console.log("[INFO] " + MODULE_NAME + " -> RootQuery -> userByAuthId -> resolve -> Entering function."); }
return new Promise((resolve, reject) => {
User.findOne({authId: args.authId}, (err, user) => {
if(err) reject(err);
else{
if (INFO_LOG === true) { console.log("[INFO] " + MODULE_NAME + " -> RootQuery -> userByAuthId -> resolve -> Promise -> Entering function."); }
if (user.authId === args.authId && user.authId !== undefined) {
return resolve(user);
} else {
return null;
if (args.authId === null || args.authId === undefined) {
if (INFO_LOG === true) { console.log("[INFO] " + MODULE_NAME + " -> RootQuery -> userByAuthId -> resolve -> Promise -> User requested not specified."); }
if (INFO_LOG === true) { console.log("[INFO] " + MODULE_NAME + " -> RootQuery -> userByAuthId -> resolve -> Promise -> args.authId = " + args.authId); }
reject({ error: "No user specified" });
return;
}
User.findOne({authId: args.authId}, onUserReceived)
function onUserReceived(err, user) {
if(err) {
if (ERROR_LOG === true) { console.log("[ERROR] " + MODULE_NAME + " -> RootQuery -> userByAuthId -> resolve -> Promise -> onUserReceived -> Database Error."); }
if (ERROR_LOG === true) { console.log("[ERROR] " + MODULE_NAME + " -> RootQuery -> userByAuthId -> resolve -> Promise -> onUserReceived -> err = " + err); }
reject(err);
}
else{
if (user === null) {
if (INFO_LOG === true) { console.log("[INFO] " + MODULE_NAME + " -> RootQuery -> userByAuthId -> resolve -> Promise -> onUserReceived -> User not found at Database."); }
if (INFO_LOG === true) { console.log("[INFO] " + MODULE_NAME + " -> RootQuery -> userByAuthId -> resolve -> Promise -> onUserReceived -> args.authId = " + args.authId); }
resolve({});
return;
}
if (user.authId === args.authId && user.authId !== undefined) {
if (INFO_LOG === true) { console.log("[INFO] " + MODULE_NAME + " -> RootQuery -> userByAuthId -> resolve -> Promise -> onUserReceived -> User found at Database."); }
if (INFO_LOG === true) { console.log("[INFO] " + MODULE_NAME + " -> RootQuery -> userByAuthId -> resolve -> Promise -> onUserReceived -> args.authId = " + args.authId); }
resolve(user);
return;
} else {
if (INFO_LOG === true) { console.log("[INFO] " + MODULE_NAME + " -> RootQuery -> userByAuthId -> resolve -> Promise -> onUserReceived -> User found at Database is not the user requested."); }
if (INFO_LOG === true) { console.log("[INFO] " + MODULE_NAME + " -> RootQuery -> userByAuthId -> resolve -> Promise -> onUserReceived -> args.authId = " + args.authId); }
if (INFO_LOG === true) { console.log("[INFO] " + MODULE_NAME + " -> RootQuery -> userByAuthId -> resolve -> Promise -> onUserReceived -> user.authId = " + user.authId); }
resolve({});
return;
}
}
}
})
})
}
@@ -125,51 +167,36 @@ const Mutation = new GraphQLObjectType({
name: 'Mutation',
fields: {
authenticate: {
type: UserType,
args: {
idToken: {type: new GraphQLNonNull(GraphQLString)}
},
resolve(parent, { idToken }) {
let userToken = null;
return validateParseIdToken(idToken)
.then(authProviderResponse => {
console.log('validateParseIdToken', authProviderResponse);
const authId = authProviderResponse.sub;
const alias = authProviderResponse.nickname;
const email = authProviderResponse.email;
const emailVerified = authProviderResponse.email_verified;
let user = new User({
alias: authId,
authId: alias,
email: email,
emailVerified: emailVerified,
roleId: "1"
});
user.save();
return { authId, alias };
})
.catch(err => { return {error: err } })
}
},
addUser:{
type: UserType,
args: {
alias: {type: new GraphQLNonNull(GraphQLString)},
authId: {type: new GraphQLNonNull(GraphQLString)}
idToken: {type: new GraphQLNonNull(GraphQLString)}
},
resolve(parent, args) {
let user = new User({
alias: args.alias,
authId: args.authId,
roleId: "1"
if (INFO_LOG === true) { console.log("[INFO] " + MODULE_NAME + " -> Mutation -> authenticate -> resolve -> Entering function."); }
/* In order to be able to wait for asyc calls to the database, and authorization authority, we need to return a promise to GraphQL. */
const promiseToGraphQL = new Promise((resolve, reject) => {
if (INFO_LOG === true) { console.log("[INFO] " + MODULE_NAME + " -> Mutation -> authenticate -> resolve -> Promise -> Entering function."); }
authenticate(args.idToken, onAuthenticated);
function onAuthenticated(err, responseToGraphQL) {
if (INFO_LOG === true) { console.log("[INFO] " + MODULE_NAME + " -> Mutation -> authenticate -> resolve -> Promise -> onAuthenticated -> Entering function."); }
if (INFO_LOG === true) { console.log("[INFO] " + MODULE_NAME + " -> Mutation -> authenticate -> resolve -> Promise -> onAuthenticated -> responseToGraphQL = " + JSON.stringify(responseToGraphQL)); }
if (err.result !== global.DEFAULT_OK_RESPONSE.result) {
if (global.ERROR_LOG === true) { console.log("[ERROR] " + MODULE_NAME + " -> authenticate -> onValidated -> err.message = " + err.message); }
reject (responseToGraphQL);
} else {
resolve (responseToGraphQL);
}
}
});
return user.save();
return promiseToGraphQL;
}
},
updateUser:{
@@ -210,6 +237,59 @@ const Mutation = new GraphQLObjectType({
}
})
function authenticate(encodedToken, callBackFunction) {
try {
if (INFO_LOG === true) { console.log("[INFO] " + MODULE_NAME + " -> authenticate -> Entering function."); }
let authId = "";
let alias = "";
let email = "";
let emailVerified = false;
tokenDecoder(encodedToken, onValidated);
function onValidated(err, decodedToken) {
if (global.INFO_LOG === true) { console.log("[INFO] " + MODULE_NAME + " -> authenticate -> onValidated -> Entering function."); }
if (err.result !== global.DEFAULT_OK_RESPONSE.result) {
if (global.ERROR_LOG === true) { console.log("[ERROR] " + MODULE_NAME + " -> authenticate -> onValidated -> err.message = " + err.message); }
callBackFunction(global.DEFAULT_FAIL_RESPONSE, { error: err });
return;
}
authId = decodedToken.sub;
alias = decodedToken.nickname;
email = decodedToken.email;
emailVerified = decodedToken.email_verified;
/* The authenticated user is NOT at our module database. We need to add him. */
let newUser = new User({
alias: alias,
authId: authId,
email: email,
emailVerified: emailVerified,
roleId: "1"
});
if (global.INFO_LOG === true) { console.log("[INFO] " + MODULE_NAME + " -> authenticate -> onValidated -> " + alias + " being added to the database"); }
newUser.save();
callBackFunction(global.DEFAULT_OK_RESPONSE, { authId, alias });
}
} catch(err) {
if (global.ERROR_LOG === true) { console.log("[ERROR] " + MODULE_NAME + " -> authenticate -> err.message = " + err.message); }
callBackFunction(global.DEFAULT_FAIL_RESPONSE, { error: err });
}
}
module.exports = new GraphQLSchema({
query: RootQuery,
mutation: Mutation