No more promises except the needed ones
This commit is contained in:
1 parent
76da420e2a
commit
4490041a8a
6 files changed
+258
-122
No files matched your search
@@ -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){
|
||||
|
||||
|
||||
@@ -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
@@ -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');
|
||||
});
|
||||
@@ -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;
|
||||
@@ -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
@@ -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
|
||||
|
||||
Reference in new issue
Block a user