DEV Community

RJ-1998
RJ-1998

Posted on

3 1

Graphql Enthusiasts! I need your help🙏

I've been trying to get some help from #help section but no one came up with a solution. Graphql Enthusiasts I need your help🙏.

I want to create a simple Login/Logout functionality using reactjs and graphql. I followed some YouTube videos and some blogs on other websites and all of them end up with creating a separate auth.js file and resolver.js file which is completely different from the context of my project.

Here's my schema file

const graphql = require('graphql');
const User = require('../models/user');
const Post = require('../models/post');
const Login = require('../models/login')
const {
GraphQLObjectType,
GraphQLString,
GraphQLSchema,
GraphQLID,
GraphQLInt,
GraphQLList,
GraphQLNonNull
} = graphql;
const loginSchema = new GraphQLObjectType({
name: 'Login',
fields: () =>({
email: {type: GraphQLString},
password: {type: GraphQLString},
ok: {type: GraphQLString}
})
});
const postTags = new GraphQLObjectType({
name: 'postTags',
fields: () =>({
tag1: {type: GraphQLString},
tag2: {type: GraphQLString},
tag3: {type: GraphQLString},
tag4: {type: GraphQLString},
tag5: {type: GraphQLString}
})
});
const userSocialURL = new GraphQLObjectType({
name: 'SocialURL',
fields: () =>({
facebookurl: {type: GraphQLString},
githuburl: {type: GraphQLString},
twitterurl: {type: GraphQLString}
})
});
const userProfile = new GraphQLObjectType({
name: 'Profile',
fields: () =>({
age: {type: GraphQLInt},
bio: {type: GraphQLString},
uname: {type: GraphQLString},
occupation: {type: GraphQLString},
socialurl: {type: userSocialURL}
})
});
const PostType = new GraphQLObjectType({
name: 'Post',
fields: () =>({
id: {type: GraphQLID},
title: {type: GraphQLString},
body: {type: GraphQLString},
loves: {type: GraphQLInt},
date: {type: GraphQLString},
tags: {type: postTags},
user: {
type: UserType,
resolve(parent,args){
return User.findById(parent.userId);
}
}
})
});
const UserType = new GraphQLObjectType({
name: 'User',
fields: () =>({
id: {type: GraphQLID},
fname: {type: GraphQLString},
lname: {type: GraphQLString},
email: {type: GraphQLString},
password: {type: GraphQLString},
phone: {type: GraphQLString},
profile: {type: userProfile},
posts: {
type: new GraphQLList(PostType),
resolve(parent,args){
return Post.find({userId: parent.id});
}
}
})
});
const RootQuery = new GraphQLObjectType({
name: 'RootQueryType',
fields: {
post: {
type: PostType,
args: {id: {type: GraphQLID}},
resolve(parent,args){ // to get data from DATABASE
return Post.findById(args.id); // to find a particular post by id
}
},
user: {
type: UserType,
args: {id: {type: GraphQLID}},
resolve(parent,args){
return User.findById(args.id); // to find a particular user
}
},
posts: {
type: new GraphQLList(PostType),
resolve(parent,args){
return Post.find({}); // to find all posts
}
},
users: {
type: new GraphQLList(UserType),
resolve(parent,args){
return User.find({}); // to find all users
}
}
}
});
const Mutation = new GraphQLObjectType({
name: 'Mutation',
fields: {
addUser: {
type: UserType,
args: {
fname: {type: new GraphQLNonNull(GraphQLString)},
lname: {type: new GraphQLNonNull(GraphQLString)},
email: {type: new GraphQLNonNull(GraphQLString)},
password: {type: new GraphQLNonNull(GraphQLString)},
phone: {type: new GraphQLNonNull(GraphQLString)}
},
resolve(parent,args){
let user = new User({
fname: args.fname,
lname: args.lname,
email: args.email,
password: args.password,
phone: args.phone
});
return user.save();
}
},
addPost: {
type: PostType,
args: {
title: {type: new GraphQLNonNull(GraphQLString)},
body: {type: new GraphQLNonNull(GraphQLString)},
date: {type: new GraphQLNonNull(GraphQLString)}
//userId: {type: new GraphQLNonNull(GraphQLString)},
//tags: {type: new GraphQLNonNull(GraphQLString)}
},
resolve(parent,args){
let post = new Post({
title: args.title,
body: args.body,
userId: args.userId,
date: args.date
//tags: args.tags,
});
return post.save();
}
}
}
});
module.exports = new GraphQLSchema({
query: RootQuery,
mutation: Mutation
});
view raw schema.js hosted with ❤ by GitHub

I want to perform a login mutation just like addPost mutation and addUser mutation, I don't know how to do it. I think there is something to do with resolve method but I'm unable to figure out.

Here's my Login react component

import React, { Component } from 'react'
import { AUTH_TOKEN } from '../../../constants'
import { compose, graphql } from 'react-apollo'
import { loginMutation } from '../../../queries/queries'
export class Login extends Component {
state = {
login: true, // switch between Login and SignUp
email: '',
password: '',
}
handleSubmit = (e) =>{
e.preventDefault();
this.props.loginMutation({
variables: {
email: this.state.email,
password: this.state.password,
}
});
document.getElementById('email').value="";
document.getElementById('password').value="";
}
handleChange = (e) =>{
this.setState({
[e.target.id]: e.target.value
})
}
render() {
return (
<div className="container-fluid">
<div className="form row">
<div className="col-lg-3"></div>
<form className="col-lg-6" onSubmit={this.handleSubmit} onCompleted = {data => this._confirm(data)}>
<div>
<h1 className="text-white"><center>Login to Your Account</center></h1>
</div>
<div className="form-group">
<label htmlFor="email">Email</label>
<input id="email" type="text" className="form-control" onChange={this.handleChange}/>
</div>
<div className="form-group">
<label htmlFor="password">Password</label>
<input id="password" type="text" className="form-control" onChange={this.handleChange}/>
</div>
<div>
<button className="btn btn-primary submitbutton btn-lg btn-block" type="submit">Login
</button>
</div>
</form>
</div>
</div>
)
}
_confirm = async data => {
const { token } = this.state.login ? data.login : data.login
this._saveUserData(token)
this.props.history.push(`/`)
}
_saveUserData = token => {
localStorage.setItem(AUTH_TOKEN, token)
}
}
export default compose(
graphql(loginMutation,{name: 'loginMutation'})
)(Login);
view raw Login.js hosted with ❤ by GitHub

I want to receive a confirmation here that if the user is able logged in or not and if he is then he should remain logged in until he clicks the logout button.

Guys please help me, although it's not a big deal to create a login/logout feature but this graphql thing looks hard to conceive for me.

I hope someone will come up with a good solution.

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

Top comments (1)

Collapse
 
zspencer profile image
Zee • • Edited

Hey RJ!

My recommendation for login/logout is that the Login mutation returns a Session object. That Session object includes an access token that the consuming app may use to make further requests.

I've created an authenticate mutation and a register mutation in Rails.

Each of them return a UserSession payload object.

On each GraphQL request, I query the database to find a user with the access token provided via the HTTP Headers; and add it to the context so that the GraphQL Resolvers may use it later.

From there, each resolver can make decisions about how they should behave

I apologize that this isn't in node; but most of my API work is done using Rails for the backend since it has such rich tooling for database schema management and providing vectors for customer success teams / clients to administer the data. That's not to say you should totally use Rails for whatever you're doing; as it looks like Yoga/Apollo-Server are some damn-fine piees of software. I'm just not as familiar with them and don't have any open source code I can point to for how to do registration and authentication in them just yet.

Zee

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

đź‘‹ Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay