lawjolla / prisma-auth0-example Goto Github PK
View Code? Open in Web Editor NEWBoilerplate Prisma Startup
License: MIT License
Boilerplate Prisma Startup
License: MIT License
Hi...
it was nice reading this article i am wondering if its possible to pass the argument that we receive in either query or mutation to directive
for example in here
post(id: ID!): Post @isOwnerOrHasRole(type: "Post", roles: ["ADMIN"])
if i want to post id to my function any idea how would i do it .... sorry i am a bit new to directives so i am unable to figure out if its possible
Thanks for your repo, it is really helpfull!
What if we want to limit access to limit access to specific field?
https://www.prisma.io/blog/graphql-directive-permissions-authorization-made-easy-54c076b5368e
You declare type User in 2 files:
datamodel.graphql
type User {
id: ID! @unique
email: String @unique
role: Role @default(value: CUSTOMER)
name: String
avatar: String
auth0id: String! @unique
identity: String
posts: [Post!]! @relation(name: "UserPosts")
}
schema.graphql
https://github.com/LawJolla/prisma-auth0-example/blob/master/server/src/schema.graphql#L22-L30
type User {
id: ID!
email: String @isOwner(type: "User")
role: Role
name: String
avatar: String
identity: String
posts: [Post!]!
}
There is no way to avoid duplicate and add directives in 1 file only (maybe schema.graphql
only?)
Thanks for your answer
Hi there,
Following the excellent tutorial, learning a lot about prisma and auth0 integration. However, I'm having the following server error output when trying to createUser using prisma-binding.
[GraphQL error]: Message: A unique constraint would be violated on User. Details: Field name = auth0id, Location: [object Object], Path: createUser
The user seems to get created in the database as I can see the entry. But the callback to localhost:8000 fails to redirect back to localhost:8000 and throws the above error.
I've upgraded all the packages to their latest version to see if that helps. So far, still getting the same error when signing up a new use.
This is true when signing up using email/password or using social sign on such as google.
Thanks for any tips on how to fix this bug!
:)
Jia
{ "name": "auth0-prisma-demo", "scripts": { "start": "nodemon -e js,graphql -x node -r dotenv/config src/index.js", "debug": "nodemon -e js,graphql -x node --inspect -r dotenv/config src/index.js", "playground": "graphql playground --dotenv dotenv/config", "dev": "npm-run-all --parallel debug playground" }, "dependencies": { "express-jwt": "5.3.1", "graphql-import": "0.6.0", "graphql-tools": "3.0.5", "graphql-yoga": "1.14.12", "jsonwebtoken": "8.3.0", "jwks-rsa": "1.3.0", "lodash.get": "^4.4.2", "nodemon": "1.18.3", "prisma-binding": "2.1.1" }, "devDependencies": { "graphql-cli": "2.16.4", "npm-run-all": "4.1.3", "prisma": "1.12.0" } }
Thanks for providing this great example! I'm trying to use it in my own server, but I get the following error when I run the 'authenticate' mutation:
query ($_where: UserWhereUniqueInput!) {
user(where: $_where)
}
operationName: null
variables:
{
"_where": {
"auth0id": "1580459988643362"
}
}
[GraphQL error]: Message: Field 'user' of type 'User' must have a sub selection. (line 2, column 3):
user(where: $_where)
^, Location: [object Object], Path: undefined
[Network error]: Error: Field 'user' of type 'User' must have a sub selection. (line 2, column 3):
user(where: $_where)
This is the line that errors out:
let user = await ctx.db.query.user({ where: { auth0id } }, info);
And this is my mutation:
mutation ($idToken: String!) {
authenticate(idToken: $idToken) {
user {
id
}
}
}
Any idea what's going on here? I'm still fresh from the GCF and this is all incredibly confusing. I did notice that taking out the info
param made the query work, but then you can't control what gets returned, right?
I have been hard at work on my own app, so this boilerplate hasn't gotten much love. That'll soon change.
Through working on my own app, I've overcome a lot of issues combining Auth0, NextJS, Apollo, and Prisma. I'm excited to detail those challenges and wins.
I'll also be making a PR to Prisma for their examples. I suspect they'll want a subset of these features, so if you want to see the kitchen sink, stay tuned to this repo.
Thanks for this great boilerplate. I've used it as a starting point for a current project. I've currently got everything working, but for some reason when I createPrismaUser
the idToken that is passed in does not have the users name, email, or picture. Is that something I have to setup in Auth0?
Hello!
const isRequestingUserAlsoOwner = ({ ctx, userId, type, typeId }) => ctx.db.exists[type]({ id: typeId, user: { id: userId } });
Am I right to assume that the above assumes that any type that is linked to the User
type to denote ownership must label the field as user
and not, for instance, owner
?
Hi @LawJolla! Thanks for the awesome example. Very cool!
I cannot understand how to run authenticated query or mutation in GraphQL Playground?
I tried to set Authorization1
header in the playground in the following way:
{
"Authorization" : {
"Bearer": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6IlJERTBNamN3UkRVNFFrTTNOakkyTkRRNE9EbERPRFZGTmp..."
}
}
So far it did not work. What else needs to be done to make it work?
Hello,
First of all thank you for your article and code example both has been very useful for me.
As I write in the title, the directive resolver does not stop the request when there is no user (no header authenticated) and it continues to the resolver, I think I am missing something...
Schema:
directive @isAuthenticated on QUERY | FIELD | MUTATION
directive @hasRole(roles: [String]) on QUERY | FIELD | MUTATION
type Query {
user(id: Int): User @hasRole(roles: ["ADMIN"])
allUsers: [User] @hasRole(roles: ["ADMIN"])
currentUser: User @isAuthenticated
}
Directive resolver:
const isLoggedIn = ctx => {
const user = ctxUser(ctx, userLocationOnContext);
if (!user) {
throw new NotLoggedInError();
}
return user;
}
const directiveResolvers = {
isAuthenticated(result, source, args, ctx) {
isLoggedIn(ctx);
return result;
},
}
The function ctxUser is the same as yours and the class NotLoggedInError is implemented as follows:
import { createError } from "apollo-errors";
export const NotLoggedInError = createError('NotLoggedInError', {
message: 'Not logged in.'
});
The user resolver is:
currentUser(root, args, context) {
return User.find({ where: context.req.user.id });
},
The getUser middleware is:
const getUser = async (req, res, next) => {
const token = getToken(_get(req, "headers.authorization"));
if (token) {
try {
const payload = validateAndParseTokenPayload(token);
const user = await User.findById(payload.id);
req.user = { id: payload.id, role: user.role, token: req.headers.authorization };
} catch (err) {
res.statusCode = 401;
return res.end('{"errors": [{"message": "token damaged"}]}');
}
}
next();
}
If I execute the query:
query {
currentUser {
id,
firstName,
lastName,
email,
role
}
}
I get the output:
TypeError: Cannot read property 'id' of undefined
at Object.currentUser (/Users/usuario/Music/mercado-capacitacion/graphql-server/src/resolvers/userResolvers.js:15:50)
It seems like the directive resolver does not stop and the user resolvers is executed normally.
isOwnerOrHasRole: async (next, source, { roles, type }, ctx, ...p)
May I ask waht the ...p
parameter above is used for?
After adding http://localhost:8000 to "Allowed Web Origins" in the Auth0 client console I was able to test login, but then I get:
auth.js:51:
{error: "access_denied", errorDescription: "Invalid URI "undefined/users/YXV0aDB8NWE4OWI1OTMzYWZmNzMxMDEzMjUxNzY5.json?auth=undefined"", state: "5p8LD.2Jl27.2uD1ot6wdwAqCNX0j5Bq"}
Using your example code, the field-level isOwner and isOwnerOrHasRole directives are working as expected, but when used a the query level, they don't seem to be restricting the query results to nodes owned by the querying user. In fact, after adding some logging, the directives don't appear to be firing at all on the query level.
Should I expect to be able to restrict query results to nodes owned by the querying user? Do I need to implement a different directive?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.