How can I access an object from a Mongoose Schema through the form? - node.js

I have this mongoose schema:
var mongoose = require("mongoose"),
passportLocalMongoose = require("passport-local-mongoose");
let userSchema = new mongoose.Schema({
username:
{type: String,
unique: true
},
password: String,
privileges:
{
region: [Number],
read: [Boolean],
write: [Boolean],
edit: [Boolean],
delete: [Boolean]
}
});
userSchema.plugin(passportLocalMongoose);
module.exports = mongoose.model("User", userSchema);
and I'm using this with the following form:
<form action="/register" method="POST">
<input type="text" name="username"><br/>
<input type="password" name="password"><br/>
<input type="text" name="privileges.region"><br/>
<input type="text" name="privileges.read"><br/>
<input type="text" name="privileges.write"><br/>
<input type="text" name="privileges.edit"><br/>
<input type="text" name="privileges.delete"><br/>
<button>Submit</button>
</form>
I suppose the name is okay because privileges is an object, so every property should be accessed with the dot notation. If it's not, please let me know.
req.body looks like this:
When I try to console.log(req.body.privileges.region) or any other property, I get undefined. How should I access one of the privileges objects properties? Thanks.

The keys for the dictionary coming back on the request are actually the strings: 'privileges.region', 'privileges.delete', etc. So you must access them as
req.body['privileges.region']
People will generally write a helper function that handles this sort of notation to map it back their original model. Or they might do the mapping when the form is submitted in the browser in order to get the data in the shape you really want it:
{username
permissions:{region, ...}
...
}

Related

How to update a record in mongo db using node js

I have created a simple signup and login using node js and mongoDb. I can successfully do signup and login and now I want to add some more data to the user model after logging in from the secret page. How can I do that?
This is my user model and I want to add some text to user.text field after loggin in:
var mongoose = require("mongoose");
var UserSchema = mongoose.Schema({
username: String,
password: String,
text:String
});
module.exports = mongoose.model("User", UserSchema);
This is my view page (i.e., the secret page)
<h1>Hi, <%= user.username %></h1>
<form action="/birthday" method="post">
<input type="text" name="text">
<button type="submit">Update database</button>
</form>
The text should be shown here after updating.
Thanks!
You need to make an API on the node process to send the data to. I suggest you take a look at stuff like Express.js and google about REST API:s.

How to get Express route's body parameters as 'string' instead of 'any' in Typescript?

I'm sending a string productId using a hidden input type through a <form>:
<form action="/cart" method="POST">
<button class="btn" type="submit">Add to Cart</button>
<input type="hidden" name="productId" value="<%= product.id %> "> // EJS template engine
</form>
And then receiving the productId in an Express route as follows:
export const postCart = async (request: Request, response: Response): Promise<void> => {
const productId = request.body.productId // This is inferred as type 'any'
const allProducts = //...Array<Product>
const requestedProduct = allProducts.find((product) => product.id === productId) // Problem: this is always false
}
Problem
The condition product.id === productId is always false because the type of product.id from the database is string and type of productId received from the body is any. I need a way for both of them to be of same type.
What I tried so far
I tried annotating and casting the type of productId:
const productId: string = request.body.productId // Doesn't work
const productId: string = request.body.productId as string // Doesn't work
const productId: string = request.body.productId + '' // Doesn't work
The only thing that works is, if I create the Numbers from the ids:
Number(product.id) === Number(productId)
But this can't be a solution because I'm using UUID strings for representing the product id. And casting UUIDs to the numbers may not be a good idea.
Any input would be much appreciated.
So we chatted out in the comment section but the problem seems to have been the trailing space in the html:
<input type="hidden" name="productId" value="<%= product.id %> ">
updated to:
<input type="hidden" name="productId" value="<%= product.id %>">

Getting "Cannot POST" with registration page using Sequelize

I'm sure there's a sound reason as to why I can't get this to work but I've been staring at the code for a long time and I'm brutally stuck. I'm trying to build out a very basic registration form that should store the data in my PostgreSQL database. I'm using bcrypt to hash out the password, but even without still having issues.
My HTML has the following:
<form action="/register/new" method="post">
<label for="username">Username</label>
<input type="text" name="username">
<label for="password">Password</label>
<input type="password" name="password">
<label for="confirm">Confirm Password</label>
<input type="password" name="confirm">
<button type="submit">Submit</button>
</form>
Then for the code I have:
app.get("/register", function(req,res){
res.render("register");
})
app.post('register', function(req,res){
let newUser = {
username: req.body.username,
passwordHash: bcrypt.hashSynce(req.body.password, 8)
}
models.Users.create(newUser).then(function(){
res.redirect('/login');
})
});
The plan for the registration data to be stored and the user redirected to the login page, login stores them in session, and so on. I thought for a bit that the issue was the action on the form but regardless I'm getting Cannot POST /register/new. I've also played around with doing a findOrCreate and do a comparison but I wanted to start with actually just creating before I make it more complex. The same issue occurs with cannot post.
Any thoughts on what I need to change?
Probably would've worked better if I did a app.post("/register"...
Simple miss of an "/"
try this modified code...
app.post('/register', function(req,res) {
let newUser = {
username: req.body.username,
passwordHash: bcrypt.hashSync(req.body.password, 8)
}
// if it does not connect/save try using models.User instead of models.Users below.
models.Users.create(newUser).then(function(){
res.location('/login');
res.redirect('/login');
})
});

sailsjs: Avoid saving some form inputs in database

I am trying to make a signup page, following irl nathans guide. Now everything works, however sail.js seems to save everything from the form in the database. For an example, I have this form:
<form class="form-signup" name="signup-form" action="/user/create" method="POST">
<input type="text" name="username" placeholder="<%= __('username') %>"> %>">
<input type="text" name="email" placeholder="<%= __('email') %>">
<input type="password" name="password" placeholder="<%= __('password') %>">
<input type="password" name="confirmation" placeholder="<%= __('confirm-password') %>">
<input class="button" type="submit" value="<%= __('signup') %>"/>
<input type="hidden" name="_csrf" value="<%= _csrf %>"/>
</form>
In this example it saves both the password and the password-confirmation in the database, which it shouldn't.
In my User.js model I have the following attributes, but these are just saved alongside the two passwords. I also have an encryptedPassword, that encrypts the password if they match.
module.exports = {
attributes: {
username: {
type: 'string',
required: true,
unique: true
},
email: {
type: 'string',
required: true,
isEmail: true,
unique: true
},
encryptedPassword: {
type: 'string'
},
// more unimportant code here.
}
I would like to know whether and it is possible to prevent sails.js from saving the two unencrypted passwords in the database whenever the form is submitted. I know I can just remove it afterwards from the database, however, that seems kind of stupid.
The saved record in the database, when submitted:
{
"username": "testuser",
"password": "2",
"confirmation": "2",
"email": "myemail#email.com",
"createdAt": 1496268539155,
"updatedAt": 1496268539155,
"encryptedPassword": "$2a$10$BkwvQnu3TA4DQ1kDMZmi6O7Z/K5uX90fHi/6zkZF.nkKi8MU.zWTS",
"id": "592f3efbaa4d2563e159dc20"
}
Since I am encrypting the password, it shouldn't also save the unencrypted passwords, just because they were part of the submit form. How do I prevent it from doing so?
Where you setup your db connection (connections.js or in your /env/development.js) specify schema: true
For example:
someDbServer: {
adapter: 'sails-mongo',
host: 'localhost',
port: 27017,
user: 'username',
password: 'pwd',
database: 'db_name',
schema: true
}
Setting schema to true means only attributes in the model js file can be inserted.
For encrypting your password you want to do that in beforeCreate and beforeUpdate. Take a look at lifecycle callbacks -sailsjs lifecycle callbacks
Thank you for the answers, however, I managed to solve the problem by passing an object to the .create() function. This object contains all the parameters I want to save, instead of using req.params.all().
var userObj = {
username : req.param('username'),
firstname : req.param('firstname'),
encryptedPassword : password,
surname : req.param('surname'),
email : req.param('email')
}

Create a Schema object in Mongoose/Handlebars with custom keys/values

I want to create a form to input custom keys and values of an object in an mongo/mongoose schema to eventually see in a handlebars view. See example to better explain. Any help would be great. :)
Mongoose/Mongodb Schema:
var docketSchema = new Schema({
staff: [{ String: String, String: String }]
});
Handlebars input view:
<div class="form-group">
<input value="{{input.staffkey1}}">
<input value="{{input.staffvalue1}}">
</div>
<div class="form-group">
<input value="{{input.staffkey2}}">
<input value="{{input.staffvalue2}}">
</div>
the reason to use mongoose is usually to ensure that your documents have some known keys and to validate new objects so they conform to your schema.
If you explicitly don't want your objects to have the same keys use the schema-type Mixed - http://mongoosejs.com/docs/schematypes.html:
var docketSchema = new Schema({
staff: [{}]
});
You can add strict: false to your schema to add fields to your schema which are not defined.
var docketSchema = new Schema({
//
}, {strict: false});
Nevertheless it is always better to define your fields.

Resources