Strapi - Update Additional Fields on User Model - rest

Problem Statement: Able to register user but unable to update customFields on same model in single request. Detail explanation below.
I have added additional fields to UserModel on Strapi. UserModel Attached
I am building a front end using Nuxt, where admin user can create new users who can access the website. This is not Regular Signup, This is User getting created by admin of the site. I guess even a regular signup I would face this issue.
Admin has all the rights to crud users.
When I submit the form I am getting Forbidden error. Form Attached
Below is my code which handled the submit. I first register the user and based on the user id I try to update First Name and Last name.
handleSubmit() {
if (this.$refs.form.validate()) {
this.loading = true
// console.log(this.username, this.email, this.password)
strapi
.register(this.username, this.email, this.password)
.then(response => {
console.log(response)
strapi
.updateEntry('users', response.user.id, {
firstName: this.firstname,
lastname: this.lastname
})
.then(response => {
this.loading = false
this.$router.push('/users')
})
.catch(err => {
this.loading = false
// alert(err.message || 'An error occurred.')
this.errorMessage = true
this.errorMessageContent = err.message || 'An error occurred.'
})
})
.catch(err => {
this.loading = false
// alert(err.message || 'An error occurred.')
this.errorMessage = true
this.errorMessageContent = err.message || 'An error occurred.'
})
}
}
Below is the console message.

Do you want to update the additional user fields (using PUT method) or passing them to the back-end in the register process (using POST method) ?
If you want to update them, you have to do the following:
Adding fields to you user model (already done)
Make the /update endpoint available in the users-permissions configuration.
See screenshot:
Now you are able to use the PUT method on the endpoint users/:id, which you could do e.g. like this:

Related

Use Firebase Cloud Function for Create User(Remove Automatically Login When register user)

When user register from client side(mobile app) , user automatically login app i dont want auto login so, I did some research, I had to use a firebase cloud function to solve this.
But I get a few errors when calling the function , how can i fix these errors
First error :
Access to XMLHttpRequest at 'https://***.cloudfunctions.net/createUser' from origin 'http://localhost:8100' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
second error :
zone-evergreen.js:2845 POST https://****.cloudfunctions.net/createUser net::ERR_FAILED
Third Error
core.js:4197 ERROR HttpErrorResponse {headers: HttpHeaders, status: 0, statusText: "Unknown Error", url: "https://***.cloudfunctions.net/createUser", ok: false, …}
Firebase Console log
2:02:23.363 ÖS
createUser
Function execution started
2:02:23.390 ÖS
createUser
Function execution took 28 ms, finished with status: 'crash'
cloud function :
const functions = require('firebase-functions');
const cors = require('cors')({ origin: true });
const admin = require('firebase-admin')
admin.initializeApp();
exports.createUser = functions.https.onRequest((request, response) => {
return cors(req, res, () => {
if (request.method !== "POST") {
response.status(405).send("Method Not Allowed");
} else {
let body = request.body;
const email = body.email;
const password = body.password;
admin.auth().createUser({
email: email,
emailVerified: false,
password: password,
})
.then((userRecord) => {
return response.status(200).send("Successfully created new user: " +userRecord.uid);
})
.catch((error) => {
return response.status(400).send("Failed to create user: " + error);
});
}
})
});
client side :
signUp(email,password){
let body = {
email : email,
password : password
}
this.http.post(
'https://****.cloudfunctions.net/createUser',
body
).subscribe(a=>{console.log("Work")});
}
EDIT (new cloud function code) :
1st and 2nd bug fixed 3 still continues but I can create users.
exports.createUser = functions.https.onRequest((req, res) => {
res.set('Access-Control-Allow-Origin', '*');
res.set('Access-Control-Allow-Methods', ' POST, OPTIONS');
res.set('Access-Control-Allow-Headers', '*');
if (req.method === 'OPTIONS') {
res.end();
}
else {
let body = req.body;
console.log(body.email)
console.log("body.password")
const email = body.email;
const password = body.password;
admin.auth().createUser({
email: email,
emailVerified: false,
password: password,
})
.then((userRecord) => {
return res.status(200).send("Successfully created new user: " +userRecord.uid);
})
.catch((error) => {
return res.status(400).send("Failed to create user: " + error);
});
}
});
Cross origin error has many reason, first problem is your current url that probably like a ads url, please change the url pattern and clear browser cache. If you are using a VPN turn off it. The Chrome blocks url that contain ads url. This problem is not happen on production environment.
If your problem not fixed with top solution, use chrome in security disable mode.
Open start menu and type chrome.exe --disable-web-security and
make sure that this headers set in your backend
header('Access-Control-Allow-Origin: *');
header('Access-Control-Request-Method:*');
header('Access-Control-Allow-Headers: Origin,token, Authorization, X-Requested-With, Content-Type, Accept');
header('Access-Control-Allow-Credentials: true');

how to reset password of users whose email is not verified in loopback?

So I ran into this issue.
I have a user who has emailedVerified as false.
So, when I try to reset password for that user as follows it gives me user unverified error.
Person.resetPassword({
email: email
}, function (err) {
if (err) return res.status(422).send(err);
});
So if user has emailVerified as false I created a token for the user with token data as follows:
const tokenData = {
ttl: 900,
scopes: ['reset-password'],
};
user.createAccessToken(tokenData, req, function (err, token) {
//email link with token
});
Now when I try to change password with following request.
/api/people/reset-password?access_token=generated-token and data message as {newPassword: “newPassword”}
I’m getting Access Denied for POST /api/people/reset-password?access_token=token
--Context scopes of Person.setPassword()
This happening only for generated token (either for verified user or non-verified user). If verified user request for password-change its successful which is done by following code.
Person.resetPassword({
email: email
}, function (err) {
if (err) return res.status(422).send(err);
});
I have following settings in person model, which i removed, but still it says access denied.
"restrictResetPasswordTokenScope": true,
"emailVerificationRequired": true,
I found this code in loopback/common/models/user.js:
User.resetPassword = function(options, cb) {
...
if (UserModel.settings.emailVerificationRequired && !user.emailVerified) {
err = new Error(g.f('Email has not been verified'));
err.statusCode = 401;
err.code = 'RESET_FAILED_EMAIL_NOT_VERIFIED';
return cb(err);
}
...
}
Looks like email verification validation only depends on the emailVerificationRequired setting. The value should be false if you want to enable reset password for not verified users:
"emailVerificationRequired": false, // The deletion of this property should also work as I don't see a default value in user.json
If it will not help, I suggest just debug the method above. I think it should be easy to find the problem, when you know the place to search.

ionic3+firebase+angularfire2 facebook email null with Multiple accounts per email address

In my firebase dashboard I have set multiple accounts for one email option.
firebase dashboard
The configuration of Angularfire2 is the standard so I do not hit the code of app.modules.ts
home.ts
facebookir(){
let goPagePrehome:boolean = false;
let userDB:any;
firebase.auth().signInWithPopup(new firebase.auth.FacebookAuthProvider())
.then(res => {
console.log(res);
console.info(JSON.stringify(res));
this.userService.getUsers()
.forEach((users) => {
users.forEach((user) =>{
if(user['user_email'] == res.additionalUserInfo.profile.email){
// console.log('res.additionalUserInfo.profile.email');
// console.log(user);
userDB = user;
goPagePrehome= true;
}
});
if(goPagePrehome){
this.goNextPagePrehome(userDB);
}else{
this.singup();
}
});
}); }
In the previous code, the user's email is created and verified in our database. And is sent to the record "this.singup ();" Or to the home "this.goNextPagePrehome (userDB);"
sign.ts
this.afAuth.authState.subscribe( user => {
console.log('find user facebook 2');
console.log(user);
if (user){
if(user.providerData["0"].providerId == "facebook.com"){
if(this.userData['picture'] == '' || this.userData['picture'] == undefined || this.userData['picture']== null){
console.info('find user facebook 2 - si');
this.userData['name']=this.userData['username']= user.providerData["0"].displayName;
this.userData['email']= user.providerData["0"].email;
this.userData['picture']= user.providerData["0"].photoURL;
console.log(this.userData);
}
}
//this.envioCorreoFacebook();
} else {
console.info('find user facebook 2 - no');
}
});
As you can see in both files I am verifying the mail for the data supplied by the provider as "providerData [" 0 "]" and "res.additionalUserInfo.profile.email".
The firebase response is:
firebase images
I need your help to correct this problem that some facebook accounts work with firebase.?
I got the mail again; although by default it should bring it to all facebook accounts.
var provider = new firebase.auth.FacebookAuthProvider();
provider.addScope('email');
firebase.auth().signInWithPopup(provider)
.then(res => {...});

facebook messenger bot encoding error

I have written sample echo message bot using facebook messenger api and wit.ai actions.
My message from facebook page is received and the proper action function defined using wit api's is also getting called. However
while returning the response, i am getting followin error as -
Oops! An error occurred while forwarding the response to : Error: (#100) Param message[text] must be a UTF-8 encoded string
at fetch.then.then.json (/app/index.js:106:13)
at process._tickCallback (internal/process/next_tick.js:103:7)
Here is the function which is used to return the response -
const fbMessage = (id, text) => {
const body = JSON.stringify({
recipient: { id },
message: { text },
});
const qs = 'access_token=' + encodeURIComponent(FB_PAGE_ACCESS_TOKEN);
return fetch('https://graph.facebook.com/v2.6/me/messages?' + qs, {
method: 'POST',
headers: {'Content-Type': 'application/json; charset=UTF-8'},
body
})
.then(rsp => rsp.json())
.then(json => {
if (json.error && json.error.message) {
throw new Error(json.error.message);`enter code here`
}
return json;
});
};
I have copied this function from the messenger.js file from the documentation since i am just trying the POC.
I checked the values for text and id in this function and verified using console.log statements and those are coming properly.
Can some experts help me to solve this error?
Note - I tried encoding the text using text.toString("utf8"); but it returns the encoding string as [object object] and thats the
response i get from bot. so it doesnt work.
Get the latest code from node-wit, there is a change in facebook id usage,
According to Facebook:
On Tue May 17 format of user and page ids delivered via webhooks will
change from an int to a string to better support default json encoder
in js (that trims long ints). Please make sure your app works with
string ids returned from webhooks as well as with ints.
Still you are getting issue with the api try to add if(event.message && !event.message.is_echo) condition as shown in below code.
// Message handler
app.post('/webhook', (req, res) => {
const data = req.body;
if (data.object === 'page') {
data.entry.forEach(entry => {
entry.messaging.forEach(event => {
if (event.message && !event.message.is_echo) {
const sender = event.sender.id;
const sessionId = findOrCreateSession(sender);
const {text, attachments} = event.message;
if (attachments) {
fbMessage(sender, 'Sorry I can only process text messages for now.')
.catch(console.error);
} else if (text) {
wit.runActions(
sessionId, // the user's current session
text, // the user's message
sessions[sessionId].context // the user's current session state
).then((context) => {
console.log('Waiting for next user messages');
sessions[sessionId].context = context;
})
.catch((err) => {
console.error('Oops! Got an error from Wit: ', err.stack || err);
})
}
} else {
console.log('received event', JSON.stringify(event));
}
});
});
}
res.sendStatus(200);
});
Reference:
no matching user bug
no matching user fix

Facebook Login is returning 'Undefined' Fields in user profile and it doesn't return email. MEANJs + Passport-facebook

I am using Meanjs.org boilerplate and Facebook Signup returns me to the Signup page.
Following are the steps that I have taken so far.
1) Setting up the Facebook App Site URL
http://localhost:3000/
and the callback URI of OAuth
http://localhost:3000/auth/facebook/callback
2) Placing the APP_ID and APP_Secret in as Client_ID and Client_Secret
facebook: {
clientID: process.env.FACEBOOK_ID || '*****',
clientSecret: process.env.FACEBOOK_SECRET || '*****',
callbackURL: 'http://localhost:3000/auth/facebook/callback',
profileFields: ['id','emails', 'first_name', 'last_name', 'displayName', 'link', 'about_me', 'photos' ]
},
3) Code is as follows
--Routes
// Setting the facebook oauth routes
app.route('/auth/facebook').get(passport.authenticate('facebook', {
scope: ['email']
}));
app.route('/auth/facebook/callback').get(users.oauthCallback('facebook'));
-- The oauthCallback function,
exports.oauthCallback = function(strategy) {
return function(req, res, next) {
passport.authenticate(strategy, function(err, user, redirectURL) {
if (err || !user) {
console.log('1' + err);
//console.log(user);
return res.redirect('/#!/signin');
}
req.login(user, function(err) {
if (err) {
console.log('2' + err);
return res.redirect('/#!/signin');
}
return res.redirect(redirectURL || '/');
});
})(req, res, next);
};
};
-- Passport-Facebook Strategy
module.exports = function() {
// Use facebook strategy
passport.use(new FacebookStrategy({
clientID: config.facebook.clientID,
clientSecret: config.facebook.clientSecret,
callbackURL: config.facebook.callbackURL,
passReqToCallback: true
},
function(req, accessToken, refreshToken, profile, done) {
console.log('facebook Strategy Started');
// Set the provider data and include tokens
var providerData = profile._json;
providerData.accessToken = accessToken;
providerData.refreshToken = refreshToken;
// console.log(JSON.stringify(profile));
console.log(profile);
// console.log(JSON.stringify(profile.name.givenName));
// Create the user OAuth profile
var providerUserProfile = {
firstName: profile.name.givenName,
lastName: profile.name.familyName,
displayName: profile.displayName,
email: profile.emails[0].value,
username: profile.username,
provider: 'facebook',
providerIdentifierField: 'id',
providerData: providerData
};
//console.log('provider' + providerUserProfile);
// Save the user OAuth profile
users.saveOAuthUserProfile(req, providerUserProfile, done);
}
));
};
4) Debugging
Logging err under oauthCallback function returns the following,
1TypeError: Cannot read property '0' of undefined
What Facebook returns as profile in Passport-Facebook module is as follows,
{ id: 'Id_of_the_person',
username: undefined,
displayName: 'Full_name_of_person',
name:
{ familyName: undefined,
givenName: undefined,
middleName: undefined },
gender: undefined,
profileUrl: undefined,
provider: 'facebook',
_raw: '{"name":"Full_name_of_person","id":"Id_of_the_person"}',
_json:
{ name: 'Id_of_the_person',
id: 'Id_of_the_person',
accessToken: 'access_token_value',
refreshToken: undefined } }
Can anyone be kind to guide me about getting the correct user profile from Facebook including user email?
Thank you so much.
I have my profile fields set to the following
profileFields: ['email','id', 'first_name', 'gender', 'last_name', 'picture']
Even though you set email it might return emails if the user has multiple emails. So you need to check if email was returned profile.email or profile.emails[0].value. You must also check if it is undefined, because there is people that register with facebook that never verify their email account and there is people that sign up with a phone number, in both those cases their emails will always be undefined.
you want to check that any required fields have values.
var email = profile.email || profile.emails[0].value;
if (! email){
console.log('this user has no email in his FB');
var err = {message:'this user is missing an email'};
return done(err);
}
now i can do this if they have an email
newUser.facebook.email = email;
if they don't have an email you can set a session for profile and send them to a page that asks them to enter an email.
It sounds like a pain, but you can never trust information from a third party api to have values.
Most of the passport examples I've seen online are wrong. They all assume an email is present.
First, profileFields field does not obey to Portable Contacts convention - and you can find the convention for passportjs here.
Second, in your example, after removing removed 'about_me', the Facebook signup returns no error. Before removing 'about_me', I had a different error: Tried accessing nonexisting field (about_me) on node type (User)
If the error persist, see this serie of 5 tutorials which helps me when I was doing the sign up page to authenticate with social networks accounts.