relayjs: authentication using relay, which mutation to use?

前端 未结 3 672
感动是毒
感动是毒 2021-02-13 13:10

I am currently handling authentication outside of relay with custom header set in DefaultNetworkLayer. Is it preferred way and Is there a way to do it in relay? I was stuck when

3条回答
  •  爱一瞬间的悲伤
    2021-02-13 13:27

    I had this issue on my project as well, here is how I handled it. I did a User Schema with that fields

    export var GraphQLUser = new GraphQLObjectType({
      name: 'User',
      fields: {
      id: globalIdField('User'), //this id is an immutable string that never change.
      userID: {
        type: GraphQLString,
        description: 'the database user\'s id',
      },
      name: {
        type: GraphQLString,
        description: 'the name of the user',
      },
      mail: {
        type: GraphQLString,
        description: 'the mail of the user',
      }
    })
    

    then here is how my user field on my Root schema looks like

    var GraphQLRoot = new GraphQLObjectType({
      user: {
      type: new GraphQLNonNull(GraphQLUser),
      description: 'the user',
      resolve: (root, {id}, {rootValue}) => co(function*() {
        var user = yield getUser(rootValue);
        return user;
      })
    }
    

    on your Root schema you ask for the getUser function that I implemented as follows, here is the main hack!

    const logID = 'qldfjbe2434RZRFeerg'; // random logID that will  remain the same forever for any user logged in, this is the id I use for my FIELD_CHANGE mutation client side
    
    export function getUser(rootValue) {
      //IF there is no userID cookie field, no-one is logged in
      if (!rootValue.cookies.get('userID')) return {
        name: '',
        mail: '',
        id: logID
      };
      return co(function*() {
        var user =  yield getDatabaseUserByID(rootValue.cookies.get('userID'));
        user.userID = user.id;
        user.id = logID // change the id field with default immutable logID to handle FIELD_CHANGE mutation
        return user;
      })
    }
    

    here is the loginMutation client Side

    export default class LoginMutation extends Relay.Mutation {
      static fragments = {
        user: () => Relay.QL`
         fragment on User {
          id,
          mail
        }`,
      }
      getMutation() {
        return Relay.QL`mutation{Login}`;
      }
    
      getVariables() {
        return {
          mail: this.props.credentials.pseudo,
          password: this.props.credentials.password,
          id: this.props.user.id
        };
      }
      getConfigs() {
        return [{
          type: 'FIELDS_CHANGE',
          fieldIDs: {
            user: this.props.user.id,
          }
        }];
      }
      getOptimisticResponse() {
        return {
          mail: this.props.credentials.pseudo,
          id: this.props.user.id
        };
      }
      getFatQuery() {
        return Relay.QL`
        fragment on LoginPayload {
          user {
            userID,
            mail,
            name,
          }
        }
        `;
      }
    

    then here is the loginMutation server Side

    export var LoginMutation = mutationWithClientMutationId({
      name: 'Login',
      inputFields: {
        mail: {
          type: new GraphQLNonNull(GraphQLString)
        },
        password: {
          type: new GraphQLNonNull(GraphQLString)
         },
         id: {
           type: new GraphQLNonNull(GraphQLString)
        }
      },
      outputFields: {
        user: {
          type: GraphQLUser,
          resolve: (newUser) => newUser
        }
      },
      mutateAndGetPayload: (credentials, {rootValue}) => co(function*() {
        var newUser = yield getUserByCredentials(credentials, rootValue);
        //don't forget to fill your cookie with the new userID (database id)
        rootValue.cookies.set('userID', user.userID);
        return newUser;
      })
    });
    

    Et voilà! To answer your question I used the FIELD_CHANGE mutation and shared the same id doesnt matter which user is logged in, the real id used to get the right user is actually userID. It works fine on my project. You can have a look on it here Relay-Graphql-repo

    PS: You'll have to add it on your networkLayer to accept cookies

    Relay.injectNetworkLayer(
      new Relay.DefaultNetworkLayer('/graphql', {
      credentials: 'same-origin'
      })
    );
    

提交回复
热议问题