I do not know why I unable to retrieve user id when creating a new account and add a role for this user.
methods.js :methods for update and insert new account driver with which I would assign the roles 'driver' for every new account ,registering a new account is going successfully, but the addition of a role does not work
import { Meteor } from 'meteor/meteor';
import { Accounts } from 'meteor/accounts-base';
import { CONST } from '../../common/constants.js';
import { Roles } from 'meteor/alanning:roles';
Meteor.methods({
updateUserProfile: (newProfile) => {
const userId = Meteor.userId();
// var isEmailChanged = currentProfile ?
// newProfile.email != currentProfile.email :
Meteor.users.update(userId, {
$set: {
profile: newProfile,
},
}, {
validationContext: 'updateUserProfile',
});
},
createDriver: (newUser) => {
var id =Accounts.createUser({
username: newUser.username,
email: newUser.email,
password: newUser.password,
profile: newUser.profile,
roles: CONST.USER_ROLES.DRIVER,
});
//console.log(Meteor.userId());
Roles.addUsersToRoles(id, roles);
},
});
Driver-join.js
Meteor.call('createDriver', data, (error) => {
if (error) {
Session.set(SESSION.ERROR, error);
} else {
FlowRouter.go('/s/driver/vehicles'); // TODO : replace with redirection by root name
}
});
roles
roles: {
type: [String],
optional: true,
allowedValues: [CONST.USER_ROLES.CLIENT, CONST.USER_ROLES.DRIVER, CONST.USER_ROLES.ADMIN],
defaultValue: CONST.USER_ROLES.CLIENT,
},
What if add this to the server?
Meteor.users.after.insert(function (userId, doc) {
Roles.addUsersToRoles(doc._id, [CONST.USER_ROLES.DRIVER])
});
Also remove roles property when you add new user, it doesn't work.
But your code should work as well. What is the roles in Roles.addUsersToRoles(id, roles);?
Related
I'm currently wondering if its possible to get data from more than one table in a single query?
We have a teamMember table, and a user table. We want to fetch information on each user in the teamMember table, and get the corresponding data from the user table.
Is this possible to do in one query? Or would I have to use two findMany queries?
const members = await prisma.teamMember.findMany({
where: {
teamId,
},
});
const membersInfo = [];
members.map(async (e) => {
const response = await prisma.user.findFirst({
where: {
id: e.userId,
},
});
if(response) membersInfo.push(response);
});```
Yes, you could query User data while fetching TeamMember information.
Consider this example:
schema.prisma
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model TeamMember {
id Int #id #default(autoincrement())
team_id Int
User User? #relation(fields: [userId], references: [id])
userId Int?
}
model User {
id Int #id #default(autoincrement())
name String
email String
password String
team TeamMember[]
}
index.ts
import { PrismaClient } from '#prisma/client';
const prisma = new PrismaClient({
log: ['query'],
});
async function main() {
await prisma.user.create({
data: {
email: 'test#test.com',
name: 'test',
password: 'test',
team: {
create: {
team_id: 1,
},
},
},
});
console.log('Created user');
const teamWithUsers = await prisma.teamMember.findUnique({
where: {
id: 1,
},
include: {
User: true,
},
});
console.log('teamWithUsers', teamWithUsers);
}
main()
.catch((e) => {
throw e;
})
.finally(async () => {
await prisma.$disconnect();
});
Here's the response:
teamWithUsers {
id: 1,
team_id: 1,
userId: 1,
User: { id: 1, name: 'test', email: 'test#test.com', password: 'test' }
}
By default relation fields are not fetched, if you need to get the relation fields data in that case you would need to specify the include clause as demonstrated in the above example.
So, I Have:
UserProfile:
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile', unique=False)
orders = models.ManyToManyField(Order, blank=True)
Order:
class Order(models.Model):
car_brand = models.CharField(max_length=30)
car_model = models.CharField(max_length=30)
repair_type = models.CharField(max_length=30)
Register.js:
...
// Handling the form submission
const handleSubmit = (e) => {
e.preventDefault();
if (name === '' || email === '' || password === '') {
setError(true);
} else {
console.log('component Register registering ')
let user = {
username: name,
email: email,
password: password,
is_active: false,
}
axios.post('http://localhost:8000/api/users/', {
username: name,
email: email,
password: password,
is_active: false,
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error.response);
});
axios.post('http://localhost:8000/api/profiles/', {
user: null,
orders: []
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error.response);
});
setSubmitted(true);
setError(false);
}
};
...
Question is:
User creation works fine, its create the user, it shows at the rest-api, and .db
How to create UserProfile? How I can add user, which I created first, and the add empty orders list??
I think you need to set the OrderSerializer in the UserProfileSerializer.
class UserProfileSerializer(serializers.ModelSerializer):
orders = OrderSerializer(many = True)
user_id = serializers.IntegerField(write_only = True)
user = UserSerializer(read_only = True)
class Meta:
model = UserProfile
fields = ['user', 'orders', 'user_id']
def create(self, validated_data):
order_ids = []
order_data = validated_data.pop('orders')
for order_item in order_data:
new_order = Order.objects.create(**order_item)
order_ids.append(new_order.id)
new_profile = UserProfile.objects.create(user_id = validated_data['user_id'])
new_profile.set(order_ids)
return new_profile
Then in post API, you need to upload user_id and orders like the following. Here I assume user has already been created and orders need to be created.
{
"user_id": 1,
"orders": [
{
"car_brand": "...",
"car_model": "...",
"repair_type": "..."
},
...
]
}
Of course, you can create user when create user profile, but in order to do that, you can change a code little bit.
I’m refactoring a Google Books app from a Restful API to GraphQL, and I am stuck on a mutation not behaving the way I expect.
When a user fills out the form found on Signup.js the Mutation ADD_USER should create a user within Mongoose, this user should have a JWT token assigned to them, and user should be logged in upon successful execution of the Mutation.
Actions observed:
• Mutation is being fired off from the front end. When I open developer tools in the browser I can see the Username, Email and Password being passed as variables.
• I have tried console logging the token, and keep getting an undefined return
• When I try to run the mutation in the GraphQL sandbox I get a null value returned.
• When I console log the args in resolvers.js no value appears on the console, which tells me the request is not reaching the resolver.
SignupForm.js (React FE Page)
import React, { useState } from "react";
import { Form, Button, Alert } from "react-bootstrap";
import { useMutation } from "#apollo/client";
import { ADD_USER } from "../utils/mutations";
import Auth from "../utils/auth";
const SignupForm = () => {
// set initial form state
const [userFormData, setUserFormData] = useState({
username: "",
email: "",
password: "",
});
// set state for form validation
const [validated] = useState(false);
// set state for alert
const [showAlert, setShowAlert] = useState(false);
const [addUser] = useMutation(ADD_USER);
const handleInputChange = (event) => {
const { name, value } = event.target;
setUserFormData({ ...userFormData, [name]: value });
};
const handleFormSubmit = async (event) => {
event.preventDefault();
// check if form has everything (as per react-bootstrap docs)
const form = event.currentTarget;
if (form.checkValidity() === false) {
event.preventDefault();
event.stopPropagation();
}
try {
///Add user is not returning data. payload is being passed as an object
const response = await addUser({
variables: { ...userFormData },
});
if (!response.ok) {
throw new Error("OH NO!SOMETHING WENT WRONG!");
}
const { token, user } = await response.json();
console.log(user);
Auth.login(token);
} catch (err) {
console.error(err);
setShowAlert(true);
}
setUserFormData({
username: "",
email: "",
password: "",
});
};
Mutation.js
export const ADD_USER = gql`
mutation addUser($username: String!, $email: String!, $password: String!) {
addUser(username: $username, email: $email, password: $password) {
token
user {
username
email
}
}
}
`;
typeDefs.js
const { gql } = require("apollo-server-express");
const typeDefs = gql`
input SavedBooks {
authors: [String]
description: String
bookId: String
image: String
link: String
title: String
}
type Books {
authors: [String]
description: String
bookId: ID
image: String
link: String
title: String
}
type User {
_id: ID
username: String
email: String
password: String
savedBooks: [Books]
}
type Auth {
token: ID!
user: User
}
type Query {
me: User
}
type Mutation {
##creates a user profile through the Auth type, that way we can pass a token upon creation
addUser(username: String!, email: String!, password: String!): Auth
login(email: String!, password: String!): Auth
saveBook(bookData: SavedBooks): User
deleteBook(bookId: ID!): User
}
`;
module.exports = typeDefs;
resolvers.js
const { User, Book } = require("../models");
const { AuthenticationError } = require("apollo-server-express");
const { signToken } = require("../utils/auth");
const resolvers = {
Query: {
me: async (parent, args, context) => {
if (context.user) {
return User.findOne({ _id: context.user._id }).populate("books");
}
throw new AuthenticationError("You need to log in");
},
},
};
Mutation: {
//try refactoring as a .then
addUser: async (parent, args) => {
//create user profile
await console.log("resolver test");
console.log(args);
const user = await User.create({ username, email, password });
//assign token to user
const token = signToken(user);
return { token, user };
};
login: async (parent, { email, password }) => {
const user = User.findOne({ email });
if (!user) {
throw new AuthenticationError("Invalid Login Credentials");
}
const correctPw = await profile.isCorrectPassword(password);
if (!correctPw) {
throw new AuthenticationError("Invalid Login Credentials");
}
const token = signToken(user);
return { token, user };
};
saveBook: async (parent, { bookData }, context) => {
if (context.user) {
return User.findOneAndUpdate(
{ _id: context.user._id },
{ $addToSet: { savedBooks: bookData } },
{ new: true }
);
}
throw new AuthenticationError("You need to log in");
};
deleteBook: async (parent, { bookId }, context) => {
if (context.user) {
return User.findOneAndUpdate(
{ _id: contex.user._id },
//remove selected books from the savedBooks Array
{ $pull: { savedBooks: context.bookId } },
{ new: true }
);
}
throw new AuthenticationError("You need to log in");
};
}
module.exports = resolvers;
auth.js
const jwt = require("jsonwebtoken");
// set token secret and expiration date
const secret = "mysecretsshhhhh";
const expiration = "2h";
module.exports = {
// function for our authenticated routes
authMiddleware: function ({ req }) {
// allows token to be sent via req.query or headers
let token = req.query.token || req.headers.authorization || req.body.token;
// ["Bearer", "<tokenvalue>"]
if (req.headers.authorization) {
token = token.split(" ").pop().trim();
}
if (!token) {
return req;
}
// verify token and get user data out of it
try {
const { data } = jwt.verify(token, secret, { maxAge: expiration });
req.user = data;
} catch {
console.log("Invalid token");
return res.status(400).json({ message: "invalid token!" });
}
// send to next endpoint
return req;
},
signToken: function ({ username, email, _id }) {
const payload = { username, email, _id };
return jwt.sign({ data: payload }, secret, { expiresIn: expiration });
},
};
Basically, I have combed from front to back end looking for where I introduced this bug, and am stuck. Any suggestions or feedback is greatly appreciated.
I was able to figure out the issue. First, a syntax error on resolver.js was preventing my mutations from being read.
Next, I made the following adjustment to handleFormSubmit on SignupForm.js
try {
///Add user is not returning data. payload is being passed as an object
const {data} = await addUser({
variables: { ...userFormData },
});
console.log(data)
console.log(userFormData)
**Auth.login(data.addUser.token);**
} catch (err) {
console.error(err);
setShowAlert(true);
}
That way my FE was properly accounting for what my Auth Middleware was passing back after successful user creation. Thanks for your help xadm, being able to talk this out got me thinking about where else to attack the bug.
I have Course Schema like below
const studentSchema = new mongoose.Schema({
name: {
type: String,
required: true
},
current_education: {
type: String,
required: true
},
course_name: {
type: mongoose.Schema.Types.ObjectId,
ref:'Course'
},
address: {
type: String,
required: true
},
mobile_number: {
type: Number,
required: true
},
date: {
type: Date,
default: Date.now
}
})
and I'm trying to make relationship student to the course. In the controller, I'm trying to populate the course details based on the course ID like below
exports.createStudent = async (req, res) => {
try {
const student = new Student(req.body);
const result = await student.save().then(t => Course.findById(req.body.course_name).populate('courses'));
if (!result) res.send('something went wrong');
res.send(result)
} catch (e) {
res.send(e);
}
}
In the postman how I'm posting you can check it below
{
"name":"Ram",
"current_education":"B.tech",
"course_name":"5cb804f1e97ba91cb8ca9dac",
"address":"Bangalore",
"mobile_number":7894561236
}
Important: Here courseID is existed in the database
the data is saved successfully in the database but the course details not populated except id. the resultant data in the database look like below
I guess you want Student details along with the course details:
Here's how you achieve it:
exports.createStudent = async (req, res) => {
try {
const student = new Student(req.body);
const result = await student.save().then(t =>
Student.findById(student._id).populate('course_name')); // Pass new ID and then populate the "course_name"
if (!result) res.send('something went wrong');
res.send(result)
} catch (e) {
res.send(e);
}
}
Hope this solves your query!
I have a User model that contains an array of customers. I want to delete a specific customer based on the customer _id. From what I've read in the Mongoose docs, I should use Model.deleteOne to delete a single document.
Here is my attempt
User Schema (it's been shortened for brevity):
const mongoose = require('mongoose');
const UserSchema = new mongoose.Schema({
username: {
type: String,
default: ''
},
password: {
type: String,
default: '',
},
registerDate: {
type: Date,
default: Date.now()
},
customer: [{
name: {
type: String,
default: '',
},
email: {
type: String,
default: 'No email name found'
},
fleet: [{
unitNumber: {
type: String,
default: 'N/A',
}
}]
}]
});
module.exports = mongoose.model('User', UserSchema);
Here is a look at the route and controller:
const express = require('express');
const router = express.Router();
const customer_controller = require('../../controllers/customers');
router.delete('/customers/:custid', customer_controller.customer_remove);
module.exports = router;
And finally the controller:
exports.customer_remove = (req, res) => {
const { params } = req;
const { custid } = params;
User.deleteOne({ 'customer._id': custid }, (err) => {
if (err)
throw err;
else
console.log(custid, 'is deleted');
});
};
From what I thought, User.deleteOne({ 'customer.id': custid }) would find the customer _id matching the custid that is passed in via the req.params. When I test this route in Postman, it deletes the entire User collection that the customer is found in, instead of just deleting the customer. Can I get a nudge in the right direction? I feel like I am close here (or not lol).
deleteOne operates at the document level, so your code will delete the first User document that contains a customer element with a matching _id.
Instead, you want update the user document(s) to remove a specific element from the customer array field using $pull. To remove the customer from all users:
User.updateMany({}, { $pull: { customer: { _id: custid } } }, (err) => { ...
Using Mongoose you can do this:
model.findOneAndUpdate({ 'customer._id': custid }, {$pull: { $pull: {
customer: { _id: custid } }}, {new: true}).lean();
Removing subdocs.
Each sub document has an _id by default. Mongoose document arrays have a special id method for searching a document array to find a document with a given _id.
Visit: https://mongoosejs.com/docs/subdocs.html
parent.children.id(_id).remove();
Use async-await, may be that will work.
exports.customer_remove = async (req, res) => {
const { params } = req;
const { custid } = params;
try {
await User.deleteOne({ 'customer._id': custid });
console.log(custid, 'is deleted');
} catch (err) {
throw err;
}
};