how to explicitly create a new user in KeyStone.js - javascript

I am trying to modify keyStone.js project to match my requirements,i am having problems adding a new user from the server side
var User = keystone.list('User');
User.add({
name: {first:"Abcd",
last:"xyz" },
email: "abc#xyz.com",
password: "password",
isAdmin: true
});
User.register();
But this isn't creating a new user in the MongoDB, any ideas what i maybe doing wrong?

You are mixing up schema definition for User and creation of a User
This could be your schema definition in models/User.js:
var User = keystone.list('User');
User.add({
name: { type: Types.Name, required: true, initial: true },
email: { type: Types.Email, required: true, initial: true },
password: { type: Types.Password, required: true, initial: true },
isAdmin: { type: Boolean },
});
User.register();
Then you can create a user like this:
var User = keystone.list('User').model;
var user = new User({
name: { first:'Abcd', last:'xyz' },
email: 'abc#xyz.com',
password: 'password',
isAdmin: true
});
user.save(function (err) {
if (err) {
// handle error
return console.log(err);
}
// user has been saved
console.log(user);
});

Related

Mongoose update field if included in request object

I'm creating a form for users to update their profile, including their profile picture. If they have included a profile picture in the form they've submitted, then I want to update their profilePic field to the image link returned from AWS once that upload is complete. If they haven't included a profile pic, then leave the previous image link in the database as is. In either case, the remaining fields will be updated with whatever was submitted.
My MongoDB query:
let user = await User.findByIdAndUpdate(req.body._id, {
// if user submitted a profile pic (if there is a req.file) then update to the new image link
$cond: {
if: req.file,
then: {profilePic: imageLink}
},
// update the remaining fields regardless
username: req.body.username,
email: req.body.email,
shortDescription: req.body.shortDescription,
fullDescription: req.body.fullDescription,
paymentInfo: req.body.paymentInfo,
})
While this successfully changes the remaining fields, it does not change the profilePic field when a new profile picture is submitted. I have console logged the imageLink value and confirmed that it is in fact the new image link from the AWS S3 bucket.
Here is my user schema:
const userSchema = new Schema({
profilePic: {
type: String,
default: < link to default image on AWS >
},
username: {
type: String,
required: true
},
email: {
type: String,
unique: true,
trim: true,
lowercase: true,
required: true
},
password: {
type: String,
trim: true,
minLength: 8,
required: true
},
shortDescription: {
type: String,
trim: true,
maxLength: 70,
default: '',
},
fullDescription: {
type: String,
trim: true,
maxLength: 4000,
default: '',
},
paymentInfo: {type: String},
publisherAgreement: {
type: Boolean,
default: false
},
subscriptions: [{
publisherId: {
type: mongoose.Schema.Types.ObjectId,
},
}],
}, {
timestamps: true,
toJSON: {
transform: function(doc, ret) {
delete ret.password
return ret
}
}
})
Any help is greatly appreciated!
No need to use $cond, you can just conditionally add the profilePic field in JavaScript:
const update = {
username: req.body.username,
email: req.body.email,
shortDescription: req.body.shortDescription,
fullDescription: req.body.fullDescription,
paymentInfo: req.body.paymentInfo,
};
if (req.file) {
update.profilePic = imageLink;
}
await User.findByIdAndUpdate(req.body._id, update);

Beginner of Node.js and MongoDB. I just wondering why there is no "isAdmin" in my MongoDB?

Beginner of Node.js and MongoDB. I just wondering why there is no "isAdmin" in my MongoDB and how to fix it? Thank you~
import mongoose from "mongoose";
const UserSchema = new mongoose.Schema(
{
username: {
type: String,
required: true,
unique: true,
},
email: {
type: String,
required: true,
unique: true,
},
password: {
type: String,
required: true,
},
isAdmin: {
type: Boolean,
required: false,
},
},
{ timestamps: true }
);
export default mongoose.model("User", UserSchema);
The user at database is without "isAdmin" like this:
username: "johnAdmin"
email: "johnAdmin#gmail.com"
password: "$2a$10$pjuVsWEe8BhP0nvgNcjS3eSp0vKwyzDUZNGDf5nYn3/Rn2yunh.iy"
createdAt: 2022-11-05T21:44:42.402+00:00
updatedAt: 2022-11-05T21:44:42.402+00:00
I have tried to change "required" to true, but it still does not work.
You can set a default value for isAdmin
isAdmin: {
type: Boolean,
default: false,
},
or
check while saving the user you have isAdmin field in the object
let user = User({
username: req.body.username,
email: req.body.email,
password: req.body.password,
isAdmin: req.body.isAdmin
})
user.save()

What is the difference between surrounding the type with square brackets and surrounding the whole object

What is the difference between this code:
const userSchema = new Schema(
{
name: { type: String, required: true },
email: { type: String, required: true, unique: true },
password: { type: String, required: true },
phoneNumber: { type: Number, required: false, unique: true },
address: [{ type: mongoose.Types.ObjectID, required: true, ref: "Address" }],
},
{
timestamps: true,
}
);
And this code:
const userSchema = new Schema(
{
name: { type: String, required: true },
email: { type: String, required: true, unique: true },
password: { type: String, required: true },
phoneNumber: { type: Number, required: false, unique: true },
address: { type: [mongoose.Types.ObjectID], required: true, ref: "Address" },
},
{
timestamps: true,
}
);
NOTICE:
In the first code, I surrounded the whole address object with square brackets.
In the second code, I only surrounded the type property of the address with square brackets.
What I want to know is how that will impact the app's behavior.
Is there any difference?
Thanks.
They both declare an array-of-references, but there are some subtle differences.
Let's take this simple schema:
const userSchema = mongoose.Schema({
address: { type: [ String ], required: true, default: undefined }
});
const User = mongoose.model('User', userSchema);
This will apply the options (required and default) to the address array-of-strings as a whole:
// This will fail validation:
// ValidatorError: Path `address` is required
const doc = new User({});
// This will pass validation:
const doc = new User({ address : [] });
Now change the position of the brackets in the schema:
const userSchema = mongoose.Schema({
address: [{ type: String, required: true, default: undefined }]
});
This will apply the options to the elements of the address array:
// This will pass validation, `address` itself isn't required:
const user = new User({});
// This will also pass validation, for the same reason:
const user = new User({ address : [] });
// This will fail validation, because elements of the array are required to have a proper value
// ValidatorError: Path `address.0` is required
const user = new User({ address : [ '' ] });
EDIT: if you want to enforce that the address field is always defined and has at least one element, you have to use a custom validator. For your schema, it would look like this:
address: {
type: [ mongoose.Schema.Types.ObjectID ],
ref: 'Address',
required: true,
default: undefined,
validate: a => Array.isArray(a) && a.length > 0
}

Destructuring a mongoose document

Using mongoose in my project, I ran into a problem.
I want to find all documents that have such a key and value pair role: USER. I can get a list of documents, but I cannot get the values of specific fields from it, no matter how I try.
Here is my code:
const getUsersList = async () => {
const users = await userModel.find({ role: USER });
//also I truing:
//In each case, I get undefined
const users = await userModel.find({ role: USER }).userName;
////
const users = await userModel.find({ role: USER }).exec();
////
Document.prototype.toObject(users);
////
JSON.stringify(users).userName
}
The request definitely gets the document, because console.log(users) lists the documents.
[
{
_id: new ObjectId("618b1a587d57e9c8e78865e1"),
userName: 'Username1',
name: 'Fullname1',
email: 'email1#gmail.com',
password: 'Password1',
status: 'INVITED',
role: 'USER',
__v: 0
},
{
_id: new ObjectId("618b1a6e7d57e9c8e78865e5"),
userName: 'Username3',
name: 'Fullname2',
email: 'email2#gmail.com',
password: 'Password2',
status: 'INVITED',
role: 'USER',
__v: 0
}
]
Judging by the documentation of the mongoose, I am doing everything right. It is also advised to cast a document into an object using toObject(), but mongoose does not find such a method for request
Моя схема:
const userSchema = new Schema(
{
userName: { type: String, unique: true, required: true },
name: { type: String, required: true },
email: { type: String, unique: true, required: true },
password: { type: String, required: true },
confirmationCode: { type: String, required: false },
status: { type: String, required: true, default: STATUS.INVITED },
role: { type: String, required: true, default: USER },
},
);
It's an array, so trying to get userName won't work. You need to get the specific element. Try this:
const userResponse = await userModel.find({ role: USER })
const firstUserName = userResponse[0].userName

Mongoose schema : SubDocument field only unique per Document

I have a little question. I have a User schema which contains a table fields redirecting to the Table schema.
A Table element can contain a name, I want this name to be unique per User but not between User.
Example:
User1 -> Table1.name: "foo"
User2 -> Table1.name: "foo"
But this User1 -> Table2.name: "foo" cannot be possible.
This is the User Schema:
var UserSchema = new mongoose.Schema({
username: { type: String, required: true, index: {
unique: true } },
email: { type: String, required: true, index: {unique: true } },
password: { type: String, required: true },
tables: [{ type: Schema.Types.ObjectId, ref: 'Table' }],
resetPasswordToken: String,
resetPasswordExpires: Date,
uuid: String,
});
This is the Table schema:
var TableSchema = Schema({
name: { type: String, required: true, index: { unique: true }},
logos: [{ type: Schema.Types.ObjectId, ref: 'Logo'}],
});
And this is where I do the queries:
app.post('/newTab', function(req, res){
var use = req.user.username;
var newTab = new Table({
name: req.body.name,
});
newTab.save(function(err, docs){
if (err)
{
console.error(err);
res.writeHead(500);
res.end();
}
else
{
User.findOne({username: req.user.username}, function(err, docs) {
if(err) {throw (err);}
else
{
docs.tables.push(newTab);
docs.save(function(err, docs){
if (err) return console.error(err);
res.writeHead(200);
res.end(userId);
});
}
});
}
});
For now, I cannot add the same table name for two different User ..
I also tried something with sparse index but can't figure how it works

Categories