relayjs: authentication using relay, which mutation to use?

前端 未结 3 662
感动是毒
感动是毒 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'
      })
    );
    
    0 讨论(0)
  • 2021-02-13 13:29

    Relay is intentionally agnostic about authentication mechanisms, so using a custom header via the network layer is appropriate.

    As for how to handle the post-login response, it's probably best to trigger a full page refresh or a redirect at that point, because Relay doesn't currently have a way to reset all internal state (although it is on the list of desirable items). Given that viewer identity can so drastically affect item visibility, a full reset is pretty much required in order to maintain correct/robust behavior.

    0 讨论(0)
  • 2021-02-13 13:54

    There exists an undocumented config type, which looks right for that use case: https://github.com/facebook/relay/issues/237

    0 讨论(0)
提交回复
热议问题