i'm trying to add authentication to my app using jwt token. I've created a LoginMutation with the FIELDS_CHANGE type but it looks like relay doesn't hook it up with the existing model.
I've listed my relay mutation and schema mutation.
My LoginMutation:
import Relay from 'react-relay';
export default class LoginMutation extends Relay.Mutation {
static fragments = {
viewer: () => Relay.QL`
fragment on User {
id
}
`
};
getMutation() {
return Relay.QL`mutation{loginUser}`;
}
getFatQuery() {
return Relay.QL`
fragment on LoginPayload {
viewer {
userId
email
password
jwt_token
}
}
`;
}
getConfigs() {
return [{
type: 'FIELDS_CHANGE',
fieldIDs: {
viewer: this.props.viewer.id
}
}];
}
getVariables() {
// inputs to the mutation
return {
email: this.props.credentials.email,
password: this.props.credentials.password
};
}
getOptimisticResponse() {
return {
viewer: {
email: this.props.credentials.email
}
};
}
}
const loginMutation = mutationWithClientMutationId({
name: 'Login',
inputFields: {
email: {
type: new GraphQLNonNull(GraphQLString)
},
password: {
type: new GraphQLNonNull(GraphQLString)
}
},
outputFields: {
viewer: {
type: userType,
resolve: (user) => user
}
},
mutateAndGetPayload: ({ email, password }, request) => {
return getUserByCredentials(email, password)
.then((user) => {
if (!user) {
return newUser;
}
user.jwt_token = jwt.sign({
id: user.id,
name: user.name,
email: user.email
}, JWT_SECRET);
return user;
})
.catch((error) => { throw error; });
}
});
Related
I have added authorization to my Nuxt app, but something is wrong. When i enter wrong password or email, I am still redirected to the main page of the application, although I have to stay on the authorization page and try to log in again.
Here is my code:
import {
createUserWithEmailAndPassword,
signInWithEmailAndPassword,
signOut
} from 'firebase/auth'
export default {
data() {
return {
snackBar: false,
snackBarText: 'No Error Message',
auth: {
email: '',
password: ''
}
}
},
methods: {
login() {
let that = this
this.$fire.auth.signInWithEmailAndPassword(this.auth.email, this.auth.password)
.catch(function (error) {
console.log(error.message);
that.snackBarText = error.message
that.snackBar = true
// $nuxt.$router.push('/login')
}).then((user) => {
console.log(user);
$nuxt.$router.push('/')
})
}
}
}
middleware:
export default function ({ app, route, redirect }) {
if (route.path !== '/login') {
// we are on the protected route
if (!app.$fire.auth.currentUser) {
// take them to sign in in a page
return redirect('/login')
}
} else if (route.path === '/login') {
if (!app.$fire.auth.currentUser) {
// leave them on the sign in page
} else {
return redirect('/')
}
}
}
store:
const state = () => ({
user: null,
};
const mutations = {
SET_USER(state, user) {
state.user = user
},
}
const actions = {
async onAuthStateChangedAction(context, { authUser, claims }) {
if (!authUser) {
context.commit('SET_USER', null)
this.$router.push({
path: '/login'
})
} else {
const { uid, email } = authUser;
context.commit('SET_USER', {
uid,
email
})
}
}
}
const getters = {
getUser(state) {
return state.user
}
}
export default {
state,
actions,
mutations,
getters,
}
Form for authorization is in component popup, which is sent to page login.vue
i was following brad traversy's one of his udemy course. after working on adding experience in profile in profile routes. i all time get server error. but it should end up with full profile details like in brad course. this is my github link for that project
https://github.com/arshad007hossain/findDevs
profile.js
const express = require("express");
const router = express.Router();
const auth = require("../../middleware/authmiddleware");
const { check, validationResult } = require("express-validator");
const Profile = require("../../models/Profile");
const User = require("../../models/User");
// #route GET api/profile/me
// #desc Get current users profile
// #access Private
router.get("/me", auth, async (req, res) => {
try {
const profile = await Profile.findOne({
user: req.user.id,
}).populate("user", ["name", "avatar"]);
if (!profile) {
return res.status(400).json({ msg: "There is no profile for this user" });
}
res.json(profile);
} catch (err) {
console.error(err.message);
res.status(500).send("Server Error");
}
});
// #route POST api/profile/me
// #desc create or update users profile
// #access Private
router.post(
"/",
[
auth,
[
check("status", "status is required").not().isEmpty(),
check("skills", "skills is required").not().isEmpty(),
],
],
async (req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
const {
company,
website,
location,
bio,
status,
githubusername,
facebook,
linkedin,
twitter,
instagram,
youtube,
skills,
} = req.body;
//build user profile
const profileFields = {};
profileFields.user = req.user.id;
if (company) profileFields.company = company;
if (website) profileFields.website = website;
if (location) profileFields.location = location;
if (bio) profileFields.bio = bio;
if (status) profileFields.status = company;
if (githubusername) profileFields.githubusername = githubusername;
if (skills) {
profileFields.skills = skills.split(",").map((skill) => skill.trim());
}
//build social objects
profileFields.social = {};
if (youtube) profileFields.social.youtube = youtube;
if (twitter) profileFields.social.twitter = twitter;
if (linkedin) profileFields.social.linkedin = linkedin;
if (instagram) profileFields.social.instagram = instagram;
if (facebook) profileFields.social.facebook = facebook;
//console.log(profileFields.skills);
try {
let profile = await Profile.findOne({ user: req.user.id });
if (profile) {
//Update
profile = await Profile.findOneAndUpdate(
{ user: req.user.id },
{ $set: profileFields },
{ new: true }
);
return res.json(profile);
}
//create
profile = new Profile(profileFields);
await profile.save();
res.json(profile);
} catch (err) {
console.errora(err.message);
res.status(500).json("server error");
}
}
);
// #route GET api/profile
// #desc Get all profile
// #access Public
router.get("/", async (req, res) => {
try {
let profiles = await Profile.find().populate("user", ["name", "avatar"]);
res.json(profiles);
} catch (err) {
console.error(err.message);
res.status(500).json("server error");
}
});
// #route GET api/profile/user/user_id
// #desc Get single profile
// #access Public
router.get("/user/:user_id", async (req, res) => {
try {
const profile = await Profile.findOne({
user: req.params.user_id,
}).populate("user", ["name", "avatar"]);
if (!profile) return res.status(400).json({ msg: "Profile not found" });
res.json(profile);
} catch (err) {
if (err.kind == "ObjectId") {
return res.status(400).json({ msg: "Profile not found" });
}
console.error(err.message);
res.status(500).json("server error");
}
});
// #route DELETE api/profile
// #desc Delete profile, user
// #access Private
router.delete("/", auth, async (req, res) => {
try {
// Remove profile
await Profile.findOneAndRemove({ user: req.user.id });
// Remove user
await User.findOneAndRemove({ _id: req.user.id });
res.json({ msg: "User deleted" });
} catch (err) {
console.error(err.message);
res.status(500).send("Server Error");
}
});
// #route PUT api/profile/experience
// #desc Add profile experience
// #access Private
router.put(
'/experience',
[
auth,
[
check('title', 'Title is required field').not().isEmpty(),
check('company', 'Company is required field').not().isEmpty(),
check('from', 'From date is required field').not().isEmpty(),
],
],
async (req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
const {
title,
company,
location,
from,
to,
current,
description,
} = req.body;
const newExp = {
title,
company,
location,
from,
to,
current,
description,
};
try {
const profile = await Profile.findOne({ user: req.user.id });
profile.experience.unshift(newExp);
await profile.save();
res.json(profile);
} catch (err) {
console.error(err.message);
res.status(500).send('Server Error');
}
});
module.exports = router;
User.js
const mongoose = require("mongoose");
const UserSchema = new mongoose.Schema({
name: {
type: String,
required: true,
},
email: {
type: String,
required: true,
unique: true,
},
password: {
type: String,
required: true,
},
avatar: {
type: String,
},
date: {
type: Date,
default: Date.now,
},
});
module.exports = User = mongoose.model("user", UserSchema);
Profile.js Model
const mongoose = require('mongoose');
const ProfileSchema = new mongoose.Schema({
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'user'
},
company: {
type: String
},
website: {
type: String
},
location: {
type: String
},
status: {
type: String,
required: true
},
skills: {
type: [String],
required: true
},
bio: {
type: String
},
githubusername: {
type: String
},
experience: [
{
title: {
type: String,
required: true
},
company: {
type: String,
required: true
},
location: {
type: String
},
from: {
type: Date,
required: true
},
to: {
type: Date
},
current: {
type: Boolean,
default: false
},
description: {
type: String
}
}
],
education: [
{
school: {
type: String,
required: true
},
degree: {
type: String,
required: true
},
fieldofstudy: {
type: String,
required: true
},
from: {
type: Date,
required: true
},
to: {
type: Date
},
current: {
type: Boolean,
default: false
},
description: {
type: String
}
}
],
social: {
youtube: {
type: String
},
twitter: {
type: String
},
facebook: {
type: String
},
linkedin: {
type: String
},
instagram: {
type: String
}
},
date: {
type: Date,
default: Date.now
}
});
module.exports = mongoose.model('profile', ProfileSchema);
I wrote a class which extends a Model, and I need create a method to compareSync password:
const { Model, DataTypes } = require('sequelize');
class User extends Model {
static init(sequelize) {
super.init({
username: DataTypes.STRING,
password: DataTypes.STRING,
role: DataTypes.STRING,
status: DataTypes.INTEGER
},
{
sequelize,
hooks: {
beforeCreate: (user) => {
const salt = bcrypt.genSaltSync();
user.password = bcrypt.hashSync(user.password, salt);
}
}
}
)
}
static associate(model) {
this.belongsToMany(models.Movie, { through: models.Ratings });
}
}
module.exports = User;
The hook is working, I thought to add after beforeCreate a:
instanceMethods: {
validPassword: function (password) {
return bcrypt.compareSync(password, this.password);
}
}
Using this class how I can define an user method?
I got this:
const { Model, DataTypes } = require('sequelize');
const bcrypt = require("bcrypt")
class User extends Model {
static init(sequelize) {
super.init({
username: DataTypes.STRING,
password: DataTypes.STRING,
role: DataTypes.STRING,
status: DataTypes.INTEGER
},
{
sequelize,
hooks: {
beforeCreate: (user) => {
const salt = bcrypt.genSaltSync();
user.password = bcrypt.hashSync(user.password, salt);
}
}
}
)
}
static associate(model) {
this.belongsToMany(models.Movie, { through: models.Ratings });
}
validPassword(password) {
return bcrypt.compareSync(password, this.password);
}
}
module.exports = User;
If I wanna use the method inside controller for example:
const login = async (req, res) => {
const { username, password } = req.params;
const user = await User.findOne({
where: { username }
});
if (!user) {
return res.status(400).send("User not find!")
}
if(!user.validPassword(password)){..}
res.send(user)
}
I want to retrieve user profile data to show the information in user profile page.
In the realtime database, I could insert the data as the picture below.
But some information such as address, business, city, phone and post, those information is undefined, so I cannot retrieve the data.
And this is the dev tool network tab.
I am using vuex, and this is my code, store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
import fireApp from '#/plugins/firebase'
//import 'firebase/firebase-auth'
Vue.use(Vuex)
export default new Vuex.Store({
namespaced: true,
state: {
user: null,
error: null,
busy: false,
jobDone: false
},
mutations: {
setUser (state, payload) {
state.user = payload
},
setError (state, payload) {
state.error = payload
},
clearError (state) {
state.error = null
},
setBusy (state, payload) {
state.busy = payload
},
setJobDone (state, payload) {
state.jobDone = payload
},
},
actions: {
loginUser({commit}, payload) {
commit('setBusy', true)
commit('clearError')
//1.login user
//2.Find group user logins
//3.set logged in user
let LoggedinUser = null;
fireApp.auth().signInWithEmailAndPassword(payload.email, payload.password)
.then(userCredential => {
LoggedinUser = userCredential.user;
var user = fireApp.auth().currentUser;
const authUser = {
id: user.uid,
contact: user.displayName,
business: user.business,
email: user.email,
phone: user.phone,
address: user.address,
post: user.post,
city: user.city,
}
return fireApp.database().ref('groups').orderByChild('name').equalTo('Pro').once('value')
.then(snapShot => {
const groupKey = Object.keys(snapShot.val())[0]
return fireApp.database().ref(`userGroups/${groupKey}`).child(`${authUser.id}`).once('value')
.then(ugroupSnap => {
if (ugroupSnap.exists()) {
authUser.role = 'pro'
}
console.log('USER', authUser)
commit('setUser', authUser)
commit('setBusy', false)
commit('setJobDone', true)
})
})
})
.catch(error => {
console.log(error)
commit('setBusy', false)
commit('setError', error)
})
},
},
getters: {
user (state) {
return state.user
},
loginStatusPro (state) {
return state.user !== null && state.user !== undefined
},
userRole (state) {
const isLoggedIn = state.user !== null && state.user !== undefined
return(isLoggedIn) ? state.user.role : 'Pro'
},
error (state) {
return state.error
},
busy (state) {
return state.busy
},
jobDone (state) {
return state.jobDone
}
},
modules: {
}
})
This is user profile page. Profile.vue
<script>
import ErrorBar from '#/components/ErrorBar'
import apiJobMixin from '#/mixins/apiJobMixin'
export default {
data() {
return {
//contact: "",
business: "",
address: "",
post: "",
city: "",
}
},
mixins: [apiJobMixin],
components: {
ErrorBar: ErrorBar
},
created () {
this.$store.commit('clearError')
const user = this.$store.getters.user
if (user) {
//this.contact = user.contact
this.business = user.business
this.address = user.address
this.post = user.post
this.city = user.city
}
},
computed: {
userData () {
return this.$store.getters.user
}
},
watch: {
userData (value) {
if (value) {
//this.contact = value.contact
this.business = value.business
this.address = value.address
this.post = value.post
this.city = value.city
}
}
}
}
</script>
I hope you can help me out.
I'm new to GraphQL so I'm doing my first query and I'm trying to query for a nested key, email
Here is my schema
const UserLogin = new GraphQLObjectType({
name: 'UserLoginType',
fields: () => ({
login: { type: GraphQLString },
email: { type: GraphQLString },
}),
});
exports.UserType = new GraphQLObjectType({
name: 'UserType',
fields: () => ({
id: NotNullStringType,
name: { type: GraphQLString },
state: { type: GraphQLString },
login: { type: UserLogin },
}),
});
And what I'm trying to do is build a query that takes an email and searches for the UserType.login.email value and return the first value that matches that email or null.
Thanks!
Edit: In my redux/actions.js file I added:
export const fetchLoginsByEmail = (userEmail) => {
return createGraphqlAction(
{
query: `
query fetchUserByEmail($userEmail: String!) {
fetchUserByEmail(email: $userEmail) {
login {
email
}
state
name
id
}
}
`,
variables: {
userEmail,
}
},
FETCH_LOGINS_BY_EMAIL,
);
};
And in my query.js file I have this in my model.exports object:
fetchUserByEmail: {
type: UserType,
resolve: async (source, args, { user, loginId }) => {
if (!user) {
return null;
}
return serailize({
...user,
login: await getLogin(loginId),
});
},
},
It looks like you're missing the arguments parameter for your query resolver.
Update your query.js into something like:
fetchUserByEmail: {
type: UserType,
args: {
email { type: GraphQLString }
},
resolve: async (source, args, { user, loginId }) => {
// You can now use args.email here and filter your results with it
console.log(args.email);
if (!user) {
return null;
}
return serailize({
...user,
login: await getLogin(loginId),
});
},
},