2016-05-20 3 views
10

Wie kann ich überprüfen, ob der Benutzer die Berechtigung hat, zu sehen oder Abfrage etwas? Ich habe keine Ahnung, wie ich das machen soll.Wie überprüft man Berechtigungen und andere Bedingungen in der GraphQL-Abfrage?

  • In args? Wie würde das überhaupt funktionieren?
  • In resolve()? Sehen Sie, ob der Benutzer die Erlaubnis hat und irgendwie einige der Argumente beseitigen/ändern?

Beispiel:

Wenn Benutzer "Besucher", so kann er nur öffentliche Beiträge sehen, "admin" kann alles sehen.

const userRole = 'admin'; // Let's say this could be "admin" or "visitor" 

const Query = new GraphQLObjectType({ 
    name: 'Query', 
    fields:() => { 
     return { 
      posts: { 
       type: new GraphQLList(Post), 
       args: { 
        id: { 
         type: GraphQLString 
        }, 
        title: { 
         type: GraphQLString 
        }, 
        content: { 
         type: GraphQLString 
        }, 
        status: { 
         type: GraphQLInt // 0 means "private", 1 means "public" 
        }, 
       }, 

       // MongoDB/Mongoose magic happens here 
       resolve(root, args) { 
        return PostModel.find(args).exec() 
       } 
      } 
     } 
    } 
}) 

aktualisieren - Mongoose Modell sieht wie folgt aus etwas:

import mongoose from 'mongoose' 

const postSchema = new mongoose.Schema({ 
    title: { 
     type: String 
    }, 
    content: { 
     type: String 
    }, 
    author: { 
     type: mongoose.Schema.Types.ObjectId, // From user model/collection 
     ref: 'User' 
    }, 
    date: { 
     type: Date, 
     default: Date.now 
    }, 
    status: { 
     type: Number, 
     default: 0 // 0 -> "private", 1 -> "public" 
    }, 
}) 

export default mongoose.model('Post', postSchema) 

Antwort

12

Sie können eine Erlaubnis des Benutzers überprüfen in der Entschlossenheit Funktion oder in der Modellschicht. Hier sind die Schritte, die Sie ergreifen müssen:

  1. Authentifizieren Sie den Benutzer vor dem Ausführen der Abfrage. Dies liegt an Ihrem Server und geschieht normalerweise außerhalb von graphql, z. B. indem Sie den Cookie betrachten, der mit der Anfrage gesendet wurde. Weitere Informationen zur Verwendung von Passport.js finden Sie unter this Medium post.
  2. Fügen Sie dem Kontext das authentifizierte Benutzerobjekt oder die Benutzer-ID hinzu. In Express-graphql können Sie es über das Kontext Argument tun:

    app.use('/graphql', (req, res) => { 
        graphqlHTTP({ schema: Schema, context: { user: req.user } })(req, res); 
    } 
    
  3. Verwenden Sie den Kontext in der Entschlossenheit Funktion wie folgt aus:

    resolve(parent, args, context){ 
        if(!context.user.isAdmin){ 
        args.isPublic = true; 
        } 
        return PostModel.find(args).exec(); 
    } 
    

Sie Genehmigung tun können Schecks direkt in resolve Funktionen , aber wenn Sie eine Modellschicht haben, empfehle ich dringend, sie dort zu implementieren, indem Sie das Benutzerobjekt an die Modellschicht übergeben. Auf diese Weise wird Ihr Code modularer, einfacher wiederzuverwenden und Sie müssen sich nicht darum sorgen, irgendwo in einem Resolver einige Überprüfungen zu vergessen.

Weitere Hintergrundinformationen über Genehmigung, diesen Beitrag check out (auch von mir geschrieben): Auth in GraphQL - part 2

+1

Wenn Sie Mongoose verwenden, ist es am einfachsten, die Überprüfungen in den Auflösungsfunktionen durchzuführen. Ich bin mit Mongoose nicht besonders vertraut, aber ich habe vor einiger Zeit ein Tutorial für GraphQL-Server geschrieben, das Mungo und SQLite verwendet. Es verwendet apolloServer anstelle von express-graphql. Es sieht ein bisschen anders aus, aber für Auflösungsfunktionen und Datenabruf ist alles ziemlich gleich. Sie finden es [hier] (https://medium.com/apollo-stack/tutorial-building-a-graphql-server-cddaa023c035). – helfer

+1

Ja, Sie können entweder null zurückgeben oder einen Fehler ausgeben und GraphQL hört auf, in den Zweig der Abfrage zu gehen. Wenn Sie Berechtigungen anhand von Daten in der Datenbank prüfen müssen (z. B. Rollen oder etwas), können Sie Versprechungen verketten. Rufen Sie zuerst das Element und die mit dem Element verknüpften Berechtigungen ab. Wenn das zurückgegeben wird, überprüfen Sie, ob der Benutzer berechtigt ist. Wenn der Benutzer keine Berechtigung hat, wird der Fehler zurückgegeben oder null zurückgegeben. Wenn der Benutzer die Berechtigung hat, gib den Gegenstand (oder etwas Ähnliches) zurück. – helfer

8

Ein Ansatz, der uns zu lösen Genehmigung bei uns dabei geholfen hat, ist etwa Resolvern als eine Zusammensetzung von Middleware zu denken. Das obige Beispiel ist großartig, aber es wird unkontrolliert im Maßstab, besonders wenn Ihre Autorisierungsmechanismen fortgeschrittener werden.

Ein Beispiel für einen Resolver als eine Zusammensetzung von Middleware könnte wie folgt aussehen:

type ResolverMiddlewareFn = 
    (fn: GraphQLFieldResolver) => GraphQLFieldResolver; 

A ResolverMiddlewareFn ist eine Funktion, die ein GraphQLFieldResolver und und gibt ein GraphQLFieldResolver nimmt.

Um unsere Resolver-Middleware-Funktionen zu erstellen, verwenden wir (Sie haben es erraten) die Compose-Funktion! Hier ist eine example of compose in Javascript implementiert, aber Sie können auch finden, komponieren Funktionen in ramda und anderen funktionalen Bibliotheken. Mit Compose können wir einfache Funktionen kombinieren, um komplexere Funktionen zu erstellen.

Zurück zu den GraphQL Berechtigungen Problem sehen wir uns ein einfaches Beispiel an. Angenommen, wir möchten den Resolver protokollieren, den Benutzer autorisieren und dann das Fleisch und die Kartoffeln ausführen. Mit Compose können wir diese drei Teile so kombinieren, dass wir sie problemlos in unserer Anwendung testen und wiederverwenden können.

const traceResolve = 
    (fn: GraphQLFieldResolver) => 
    async (obj: any, args: any, context: any, info: any) => { 
    const start = new Date().getTime(); 
    const result = await fn(obj, args, context, info); 
    const end = new Date().getTime(); 
    console.log(`Resolver took ${end - start} ms`); 
    return result; 
    }; 

const isAdminAuthorized = 
    (fn: GraphQLFieldResolver) => 
    async (obj: any, args: any, context: any, info: any) => { 
    if (!context.user.isAdmin) { 
     throw new Error('User lacks admin authorization.'); 
    } 
    return await fn(obj, args, context, info); 
    } 

const getPost = (obj: any, args: any, context: any, info: any) => { 
    return PostModel.find(args).exec(); 
} 

const getUser = (obj: any, args: any, context: any, info: any) => { 
    return UserModel.find(args).exec(); 
} 

// You can then define field resolve functions like this: 
postResolver: compose(traceResolve, isAdminAuthorized)(getPost) 

// And then others like this: 
userResolver: compose(traceResolve, isAdminAuthorized)(getUser) 
+0

große Antwort! Danke Michael –

Verwandte Themen