I fail to receive information from my postgres db when trying to connect with graphql.
I receive the following response:
{
"errors": [
{
"message": "password authentication failed for user \"admin\"",
"locations": [
{
"line": 2,
"column": 3
}
],
"path": [
"account"
]
}
],
"data": {
"account": null
}
}
I honestly don't know where to define the user and pass.
const express = require('express');
const expressGraphQL = require('express-graphql');
const schema = require('./schema');
const app = express();
app.use('/graphql', expressGraphQL({
schema,
graphiql: true
}))
app.listen(4000, () => {
console.log('Listening...')
})
and this is my schema file
const graphql = require('graphql');
const connectionString = 'myURI';
const pgp = require('pg-promise')();
const db = {}
db.conn = pgp(connectionString);
const {
GraphQLObjectType,
GraphQLID,
GraphQLString,
GraphQLBoolean,
GraphQLList,
GraphQLSchema
} = graphql;
const AccountType = new GraphQLObjectType({
name: 'account',
fields: () => ({
id: { type: GraphQLID },
name: { type: GraphQLString },
busines_name: { type: GraphQLString },
email: {
type: new GraphQLList(EmailType),
resolve(parentValue, args) {
const query = `SELECT * FROM "emails" WHERE
account=${parentValue.id}`;
return db.conn.many(query)
.then(data => {
return data;
})
.catch(err => {
return 'The error is', err;
});
}
}
})
})
const EmailType = new GraphQLObjectType({
name: 'Email',
fields: {
id: { type: GraphQLID },
email: { type: GraphQLString },
primary: { type: GraphQLBoolean }
}
})
const RootQuery = new GraphQLObjectType({
name: 'RootQueryType',
fields: {
account: {
type: AccountType,
args: { id: { type: GraphQLID } },
resolve(parentValue, args) {
const query = `SELECT * FROM "account" WHERE id=${args.id}`;
return db.conn.one(query)
.then(data => {
return data;
})
.catch(err => {
return 'The error is', err;
});
}
},
emails: {
type: EmailType,
args: { id: { type: GraphQLID } },
resolve(parentValue, args) {
const query = `SELECT * FROM "emails" WHERE id=${args.id}`;
return db.conn.one(query)
.then(data => {
return data;
})
.catch(err => {
return 'The error is', err;
});
}
}
}
})
module.exports = new GraphQLSchema({
query: RootQuery
})
I would like to know where to define the user and the password for the db of what i'm doing wrong besides that.
const connectionString = 'myURI';
It should be enough if your connection string includes the username and password. Is your DB connection string of the form postgres://username:password#server:5432 ?
See https://www.postgresql.org/docs/10/libpq-connect.html#LIBPQ-CONNSTRING
Related
Problem:When I try and send/store data in my database I get this error. Specifically, I am trying to create/save a classroom with student names.
Tech Used:
Prisma/Postgres connected to AWS RDS and Next.js, deployed on Vercel, etc.
Error Message
PrismaClientValidationError: Argument data.classrooms.upsert.0.create.students.connectOrCreate.0.create.school.connect of type schoolWhereUniqueInput needs at least one argument.
Argument data.classrooms.upsert.0.update.students.upsert.0.create.school.connect of type schoolWhereUniqueInput needs at least one argument.
at Document.validate (/var/task/node_modules/#prisma/client/runtime/index.js:29501:20)
at serializationFn (/var/task/node_modules/#prisma/client/runtime/index.js:33060:19)
at runInChildSpan (/var/task/node_modules/#prisma/client/runtime/index.js:22550:12)
at PrismaClient._executeRequest (/var/task/node_modules/#prisma/client/runtime/index.js:33067:31)
at async PrismaClient._request (/var/task/node_modules/#prisma/client/runtime/index.js:32994:16)
at async profile (/var/task/.next/server/pages/api/user/profile.js:175:27)
at async Object.apiResolver (/var/task/node_modules/next/dist/server/api-utils/node.js:366:9)
at async NextNodeServer.runApi (/var/task/node_modules/next/dist/server/next-server.js:481:9)
at async Object.fn (/var/task/node_modules/next/dist/server/next-server.js:735:37)
at async Router.execute (/var/task/node_modules/next/dist/server/router.js:247:36) {
clientVersion: '4.9.0'
}
DB Models with relationships: school (1 to many w/students); students (many to many with classrooms); teachers (one to many with students, many to many with classrooms)
Code/Prisma Query
export default async (req, res) => {
...
classroom.students.forEach((student) => {
const totalStudentPoints = student.rewardsRecieved.reduce(
(totalPoints, reward) => {
return totalPoints + reward.pointValue;
},
0
);
groups[student.group.name] += totalStudentPoints;
});
return { ...classroom, groupsTotalPoints: groups };
});
user.classrooms = newClassrooms;
res.json(user);
} else {
console.log("Could Not Find User");
res.status(401).json({
error: "Not authorized",
});
}
}
if (req.method === "PUT") {
const connectStudents = (shouldUpsert) => {
const students = req.body.students;
return students.map((student) => {
const UNSAFEHASH = md5(student.id);
const studentQuery: any = {
where: {
id: student.id,
},
create: {
id: student.id,
firstName: student.firstName,
lastName: student.lastName,
profilePicture: student.profilePicture,
userKey: UNSAFEHASH,
school: {
connect: {
id: req.body.schoolId,
},
},
group: {
connect: {
id: student.group.id,
},
},
},
};
if (shouldUpsert) {
studentQuery.update = {
firstName: student.firstName,
lastName: student.lastName,
profilePicture: student.profilePicture,
userKey: UNSAFEHASH,
group: {
connect: {
id: student.group.id,
},
},
};
}
return studentQuery;
});
};
try {
const user = await prisma.staff.update({
where: {
id: session.id,
},
data: {
firstName: req.body.firstName,
lastName: req.body.lastName,
classrooms: {
upsert: [
{
where: {
id: req.body.classId || "-1",
},
create: {
// id: req.body.classId,
name: req.body.className,
subject: req.body.classSubject,
students: {
connectOrCreate: connectStudents(false),
},
},
update: {
name: req.body.className,
subject: req.body.classSubject,
students: {
upsert: connectStudents(true),
},
},
},
],
},
},
});
Take a look at the PUT request and the prima.staff.update method more specifically. I was looking at the UPSERT I have there, but I can't figure out what's wrong.
I have a User schema which has reference to a profile schema.
const UserSchema = new Schema(
{
_id: mongoose.Schema.Types.ObjectId,
email: {
....email props...
},
password: {
...password props...
},
profile: [{
type: mongoose.Schema.Types.ObjectId,
ref: "Profile",
}],
},
);
const Profile = new Schema({
_user: {
type: Schema.Types.ObjectId, ref: 'User'
},
'displayName': {
type: String,
default: ''
},
'interestedActivities': ['Ping-pong'], <---- This bad boy/girl is an array
'memberSince': { type: Date, default: Date.now }
}
)
I'd like to create a route which can update the User properties AND the Profile properties in one shot—with a caveat one of the properties on the Profile model is an array!!!
I tried this....
handler
.use(auth)
.put((req, res, next) => {
emailValidator(req, res, next, 'email');
},
async (req, res, next) => {
await connectDB()
const {
profileDisplayName,
profileEmail,
interestedActivities } = req.body;
const update = {
email: profileEmail,
'profile.$.displayName': profileDisplayName,
'profile.$.interestedActivities': interestedActivities
}
const filter = { _id: req.user.id };
const updatedUser = await User.findOneAndUpdate(filter, update, { new: true })
try {
console.log("updatedUser ", updatedUser);
if (updatedUser) {
return res.status(200).send({
updatedUser,
msg: `You have updated your profile, good job!`
});
}
} catch (error) {
errorHandler(error, res)
}
})
export default handler;
My response is:
Status Code: 500 Internal Server Error
Cast to ObjectId failed for value "[
{
id: 'ae925393-0935-45da-93cb-7db509aedf20',
name: 'interestedActivities',
value: []
}
]" (type Array) at path "profile.$"
Does anyone know how I could also afford for the property which is an array?
Thank you in advance!
I wrote 2 resolvers (signup and login). They return a JWToken. In playground, I'm testing the functions and it won't let me make a mutation without specifying some subfields to display. They all are null and sometimes I get a "Cannot return null for non-nullable field users._id". I'm using express and mongodb.
const { UserTC, UserSchema } = require("../models/user");
const bcrypt = require('bcrypt')
const jsonwebtoken = require('jsonwebtoken')
const resolver = function () {};
resolver.me = UserTC.addResolver({
name: "me",
type: UserTC,
args: { record: UserTC.getInputType() },
resolve: async ({ source, args }) => {
if (!args.record) {
throw new Error('You are not authenticated!')
}
return await UserSchema.findById(args.record._id)
}
});
resolver.signup = UserTC.addResolver({
name: "signup",
type: UserTC,
args: { record: UserTC.getInputType() },
resolve: async ({ source, args }) => {
const user = await UserSchema.create({
firstName: args.record.firstName,
lastName: args.record.lastName,
email: args.record.email,
password: await bcrypt.hash(args.record.password, 10)
});
return jsonwebtoken.sign(
{ id: user._id, email: user.email },
process.env.JWT_SECRET,
{ expiresIn: '1y' }
)
},
});
resolver.login = UserTC.addResolver({
name: "login",
type: UserTC,
args: { record: UserTC.getInputType() },
resolve: async ({ source, args }) => {
const user = await UserSchema.findOne({email: args.record.email });
if (!user) {
throw new Error('Incorrect email')
}
const valid = await bcrypt.compare(args.record.password, user.password);
if (!valid) {
throw new Error('Incorrect password')
}
return jsonwebtoken.sign(
{ id: user._id, email: user.email },
process.env.JWT_SECRET,
{ expiresIn: '1y' }
)
},
});
module.exports = resolver;
Here are the queries:
mutation {
signup(
record: {
firstName: "Ben2"
lastName: "Dormant"
email: "Ben2.Dormant#gmail.com"
password: "qwerty"
}
)
}
mutation {
login(record: {
email: "nicolas.sursock#gmail.com",
password: "azerty" })
}
I founded a bug, try like this because you can not use await in reutrn
resolver.me = UserTC.addResolver({
name: "me",
type: UserTC,
args: { record: UserTC.getInputType() },
resolve: async ({ source, args }) => {
if (!args.record) {
throw new Error('You are not authenticated!')
}
let result = await UserSchema.findById(args.record._id)
return result
}
});
const message: Message = {
conversationId: conversationId,
content: this.message,
createdAt: id,
sender: this.senderId,
isSent: false,
id: id,
};
this.appsync.hc().then((client) => {
client
.mutate({
mutation: createMessage,
variables: message,
optimisticResponse: () => ({
createMessage: {
...message,
__typename: "Message",
},
}),
update: (proxy, { data: { createMessage: _message } }) => {
const options = {
query: getConversationMessages,
variables: {
conversationId: conversationId,
first: constants.messageFirst,
},
};
// error on below line
const data = proxy.readQuery(options);
const _tmp = unshiftMessage(data, _message);
proxy.writeQuery({ ...options, data: _tmp });
},
})
.then(({ data }) => {
console.log("mutation complete", data);
console.log("mutation complete", data);
})
.catch((err) => console.log("Error creating message", err));
});
Analytics.record("Chat MSG Sent");
}
ERROR
errorHandling.js:7 Error: Can't find field allMessageConnection({"conversationId":"XXXXXXXXXXXXXXXXXXXXXXXXXXX","first":100}) on object {
"me": {
"type": "id",
"generated": false,
"id": "User:XXXXXXXXXXXXXXXXXXX",
"typename": "User"
}
}.
I'm following this video series.
Here i have problem with getting data about user who created the event in following script
here's my app.js
const express = require('express');
const bodyParser = require('body-parser');
const graphqlHttp = require('express-graphql')
const { buildSchema } = require('graphql');
const mongoose = require('mongoose');
const bcrypt = require('bcrypt');
const Event = require('./models/event');
const User = require('./models/user');
const app = express();
const conString = `mongodb+srv://${process.env.MONGO_USER}:${process.env.MONGO_PASSWORD}#clusterpl-qiufl.mongodb.net/${process.env.MONGO_DB}?retryWrites=true&w=majority`
app.use(bodyParser.json());
app.use(
'/graphql',
graphqlHttp({
schema: buildSchema(`
type Event {
_id: ID!
title: String!
description: String!
price: Float!
date: String!
creator: User!
}
type User {
_id: ID!
email: String!
password: String!
createdEvents: [Event!]
}
input UserInput {
email: String!
password: String!
}
input EventInput {
title: String!
description: String!
price: Float!
date: String!
}
type RootQuery {
events: [Event!]!
}
type RootMutation {
createEvent(eventInput: EventInput): Event
createUser(userInput: UserInput): User
}
schema {
query: RootQuery,
mutation: RootMutation
}
`) ,
rootValue: {
events: () => {
return Event.find().populate('creator')
.then(events => {
console.log(events)
return events.map(event => {
console.log(event)
return {
...event._doc,
_id: event.id
};
});
})
.catch(err => {
throw err;
})
},
..
},
graphiql: true
})
);
mongoose.connect(conString, {useNewUrlParser: true}).then(
() => {console.log('Success !')},
err => { console.log(err) }
)
app.listen(3000);
user.js and event.js
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const userSchema = new Schema({
email: {
type: String,
required: true
},
password: {
type: String,
required: true
},
createdEvents: [
{
type: Schema.Types.ObjectId,
ref: 'Event'
}
]
});
module.exports = mongoose.model('User', userSchema)
const mongoose = require('mongoose');
const Schema = mongoose.Schema
const eventSchema = new Schema({
title: {
type: String,
required: true
},
description: {
type: String,
required: true
},
price: {
type: Number,
required: true
},
date: {
type: Date,
required: true
},
creator: [
{
type: Schema.Types.ObjectId,
ref: 'User'
}
]
});
module.exports = mongoose.model('Event', eventSchema);
once i submit this graphql query
query{
events {
creator {
email
}
}
}
returns "message": "Cannot return null for non-nullable field User.email.",
I'm completly new to graphql and any answer would be much appreciate.
maybe this might helps someone else, i don't know what happens there but i got expected results, by adding
const user = userId => {
return User.findById(userId).then(user => {
return { ...user._doc, _id: user.id };
})
.catch(err => {
throw err;
});
}
method and used it in event resolver function like this
events: () => {
return Event.find()
.populate('creator')
.then(events => {
return events.map(event => {
console.log('ev',event._doc)
return {
...event._doc,
_id: event.id,
// creator: {
// ...event._doc.creator._doc,
// _id: event._doc.creator.id
// }
creator: user.bind(this, event._doc.creator)
};
})
})
.catch(err => {
throw err;
})
},