taieb
April 11, 2018, 3:20am
1
I’m doing a register form and i want to add a username to “profile.name”.
but i can’t add it, i had to create in my collection schema a username attribute if i want the operation to be done.
don’t know what i’m doing wrong.
The password is posted , the email too, but the username no.
async function register() {
let credentials= {
email: req.query.email,
password: req.query.password,
username: req.query.username
}
return await Meteor.call('createuser', credentials, (err, res) => {
if (err) {
console.log(err)
}
else {
res.status(403).res.json(res);
}
}
)
}
let RegisterTheUser = register();
})
A few things wrong here, and you haven’t provided enough code for us to see what you’re doing:
Is this on the client or server? (I’m guessing server because of req, res)
Where does req/res come from? Connect Handler callback? Express?
Which code generates the request?
What happens in your method?
If this is the server, why are you using a method at all?
Why are you awaiting the Meteor.call
? It doesn’t return a promise.
If res is an instance of ServerResponse
, then res.status(403).res.json(res)
is an error.
Why are you sending a response directly in this function?
Why are you declaring a function just to call it afterwards
What are you doing with RegisterTheUser
? Why assign it?
Are you aware that register returns a Promise?
1 Like
taieb
April 11, 2018, 3:43am
3
Thank you for your reply.
It’s a Post Request using express.
I’m testing it on a REST Client.
I’m doing the await because if i do a normal function i get an error of bindEnvironement.
app.post('/register', (req, res, next) => {
let credentials= {
email: req.query.email,
password: req.query.password,
username: req.query.username
}
return Meteor.call('createuser', credentials, (err, res) => {
if (err) {
console.log(err)
}
else {
send(res);
}
}
)
})
Error: Meteor code must always run within a Fiber. Try wrapping callbacks that you pass to non-Meteor libraries with Meteor.bindEnvironment.
The method should add a user, but only post the email + password and not the username.
I’m having trouble understanding what you mean by “The method should add a user, but only post the email + password and not the username.”
Are you saying that req.query.username
is empty? Or that your method isn’t doing anything with it?
You can fix the Fiber error by doing exactly what it says in the error message: wrap the callback in a Meteor.bindEnvironment
like so:
app.post('/register', Meteor.bindEnvironment((req, res, next) => {
let credentials= {
email: req.query.email,
password: req.query.password,
username: req.query.username
}
return Meteor.call('createuser', credentials, (err, res) => {
if (err) {
console.log(err)
}
else {
send(res);
}
}
)
}))
Is there a specific reason you’re using a separate express app instead of using Meteor’s WebApp?
With WebApp.connectHandlers you can write express-like handlers and have them executed with the full Meteor context:
WebApp.connectHandlers.use('/register', (req, res, next) => {
if (req.method !== 'POST') return next();
const credentials= {
email: req.query.email,
password: req.query.password,
username: req.query.username
}
Meteor.call('createuser', credentials, (err, res) => {
if (err) return console.log(err);
res.writeHead(201); // 201 is HTTP for created
res.end();
});
});
1 Like
taieb
April 11, 2018, 4:32am
5
The method isn’t posting the value of the username.
I had to add
username:{
type:String
},
on my users.js ( collections )
My problem is that i want to store the value of req.query.username on
profile: {
type: Object,
optional: true
},
“profile.name”: {
type: String,
},
profile.name
Are you saying that you have a schema connected to the collection?
Are you using collection2
for automatic validation?
If the error is clearly in the method, why haven’t you posted the method’s code.
Further, since this is on the server, why are you using a Method at all? Why not use a standard function?
This is exactly why I asked for more code.
1 Like
taieb
April 11, 2018, 4:50am
7
> createUser : function (credentials) {
> check(credential, Object)
> // First we check if the User already exist and if he has PW
> const USER = Accounts.findUserByEmail(credentials.email)
> if (USER !== undefined && (USER.services === undefined || USER.services.password === undefined || USER.services.password.bcrypt === undefined)) {
> Accounts.setPassword(USER._id, credentials.password)
> result = 'newPassword'
> } else {
> // user account creation (via the app)
> result = Accounts.createUser(credentials)
>
> }
> return result
This is my method.
Would you mind answering the other questions?
1 Like
taieb
April 11, 2018, 4:53am
9
I followed your first suggestion and it worked with an error
` url must be absolute and start with http:// or https
It’s doing the post but sending me an error.
And yes i have a schema connected to the collection.
Can you post the schema?
Which suggestion was that, and where is the error coming from, is it from the mystery send
function?
1 Like
taieb
April 11, 2018, 4:58am
11
I edited the code with the bindEnv like you said.
Here is my Schema
let Schemas = {}
Schemas.User = new SimpleSchema({
createdAt: {
type: Date
},
// Services
services: {
type: Object,
optional: true
},
"services.password": {
type: Object,
optional: true
},
"services.password.bcrypt": {
type: String,
optional: true
},
"services.resume": {
type: Object,
blackbox: true,
optional: true
},
// Emails
emails: {
type: Array,
optional: true
},
"emails.$": {
type: Object
},
"emails.$.address": {
type: String,
regEx: SimpleSchema.RegEx.Email
},
"emails.$.verified": {
type: Boolean
},
// Name
profile: {
type: Object,
optional: true
},
"profile.name": {
// optional:true,
type: String,
},
// Features (Activated or not)
"profile.features": {
type: Object,
optional: true,
blackbox: true
},
pushIds: {
type: [String],
optional: true
},
// Roles
roles: {
type: [String],
optional: true,
blackbox: true
},
})
Meteor.users.attachSchema(Schemas.User)
Ah okay I think I understand now
The easiest way to set profile.name
to the username is to pass it into Accounts.createUser
The docs specify that Accounts.createUser
accepts an options object which includes the profile
You can do so in your method code:
createUser : function (credentials) {
check(credential, Object)
// First we check if the User already exist and if he has PW
const USER = Accounts.findUserByEmail(credentials.email)
if (USER !== undefined && (USER.services === undefined || USER.services.password === undefined || USER.services.password.bcrypt === undefined)) {
Accounts.setPassword(USER._id, credentials.password)
result = 'newPassword'
} else {
// user account creation (via the app)
credentials.profile = { name: credentials.username }, // <--- Just assign profile before passing to createUser
result = Accounts.createUser(credentials);
}
return result
I strongly recommend including username
in your schema as well, since Accounts will look for it
1 Like
taieb
April 11, 2018, 5:36am
13
Working like a charm thank you soo much.
The post is runing well but unfortunatly i got
[Error: url must be absolute and start with http:// or https://]
Whatever that error is, it’s source isn’t in any of the code you’ve posted
taieb
April 11, 2018, 5:45am
15
Is there a way to get ride of it and just return what i’ve posted ?
maybe i should change something here
return Meteor.call('createuser', credentials, (err, res) => {
if (err) {
console.log(err)
}
else {
res.json(req.credentials)
}
}
Sure. Why return the credentials though? Surely just sending a status code is enough