アプリがあります。Facebookでログインしようとすると、エラーが発生します。
エラー {"error":"E_VALIDATION","status":400,"summary":"1 つの属性が無効です","model":"User","invalidAttributes":{"email":[{"rule": "string","message":"undefined
は文字列でなければなりません (オブジェクトである \"null\" ではなく)"},{"rule":"email","message":"\"email\" 検証入力のルールに失敗しました: null"},{"rule":"required","message":"\"required\" 入力の検証ルールに失敗しました: null"}]}} [TypeError: のプロパティ 'ニックネーム' を読み取れません未定義]
私のユーザーモデルは次のようになります。
/**
* User
*
* @module :: Model
* @description :: A short summary of how this model works and what it represents.
* @docs :: http://sailsjs.org/#!documentation/models
*/
var Q=require('q')
module.exports = {
/* e.g.
nickname: 'string'
*/
attributes : {
provider: {
type:'string',
required:true
},
uid: {
type:'integer',
required:true
},
name: 'string',
email: {
type:'string',
email:true,
required:true
},
firstname: {
type:'string'
},
lastname: {
type:'string'
},
admin:{
type:'boolean',
defaultsTo:false
},
lastLoginAt:{
type:'date'
},
firstLoggedInAt:{
type:'date'
},
profileUpdated:{
type:'boolean',
defaultsTo:false
},
phoneNumber:{
type:'integer'
},
dealClaims:{
collection:'dealClaim',
via:'user'
},
parties:{
collection:'party',
via:'user'
},
origin:{
type:'string',
defaultsTo:'web'
},
city:{
type:'string',
defaultsTo:'Bangalore'
},
currentCity:function(){
return this.city||'Bangalore'
},
claimDealWith:function(dealId){
var deferredClaim= Q.defer()
sails.log.info('Im here',this.email,dealId,this.phoneNumber);
Dealclaim.create({email:this.email,phoneNumber:this.phoneNumber,deal:dealId,user:this.id},function(err,dealClaim){
if(err||!dealClaim){
deferredClaim.reject(err)
return
}
sails.log.info('dealClaim',dealClaim)
Deal.findOne(dealClaim.deal)
.populate('listing')
.then(function(deal){
deferredClaim.resolve({deal:deal,dealClaim:dealClaim})
})
.fail(function(err){
deferredClaim.reject(err)
})
})
return deferredClaim.promise
},
login:function(){
var deferred= Q.defer()
var currentDate=new Date()
var updateConditions={lastLoginAt:currentDate}
if(!this.firstLoggedInAt){
updateConditions.firstLoggedInAt=currentDate
}
User.update(this.id,updateConditions,function (err){
sails.log.info('last login date for user:',this.id)
if(err){
deferred.reject(err)
}
deferred.resolve()
})
return deferred.promise
},
completeProfile:function(data){
var deferred= Q.defer()
this.phoneNumber=(data.phoneNumber||this.phoneNumber);
this.email=(data.email||this.email)
this.city=(data.city||this.city)
sails.log.info('city==>',this.city)
//sails.log.info('email',this.email,User.validateEmail(this.email),(this.email==='dnd@testgulp.com'||(!this.email)||User.validateEmail(this.email)),'phone',this.phoneNumber)
if(this.email==='dnd@vgulp.com'||(!this.email)||!User.validateEmail(this.email)){
deferred.reject({ValidationError:{invalidEmail:'Invalid Email'}})
return deferred.promise
}
if((!this.phoneNumber)||isNaN(this.phoneNumber)){
deferred.reject({ValidationError:{invalidPhoneNumber:'Invalid Phone number'}})
return deferred.promise
}
this.profileUpdated=true
this.save(function(err){
if(err){
sails.log.error(err.stack)
deferred.reject(err)
}else{
deferred.resolve()
}
})
return deferred.promise
},
providedEmail:function(){
return this.email==='dnd@testgulp.com'?undefined:this.email;
},
planMyParty:function(party){
var deferred= Q.defer()
//i should us
this.parties.add({numberOfPeople:party.numberOfPeople,locationOrPlace:party.locationOrPlace})
this.save(function(err){
if(err){
deferred.reject(err)
return
}
deferred.resolve(party)
})
return deferred.promise
}
},
validateEmail:function(email){
var regex = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return regex.test(email)
},
beforeCreate:function makeAdmin(values,next){
sails.log.warn("BOOYA IM HERE!!")
var deferred=Q.defer()
Admin.findOneByEmail(values.email).then(function foundAdmin(err,admin){
if(err || !admin){
sails.log.warn("User with email"+values.email+" tried to gain access to restricted urls")
//return next({err:["only admins allowed"]},null)
values.admin=false
} else{
values.admin=true
}
deferred.resolve()
})
deferred.promise.fin(function(){
next()
})
return deferred.promise
},
createSession:function(profile){
var deferred= Q.defer();
if(!profile){
deferred.reject(new Error("Unable to login to the server"))
return deferred.promise
}
User.findOne({
or: [
{uid: parseInt(profile.id)},
{uid: profile.id}
]
}
).exec(function (err, user) {
if (user) {
//sails.log.info('User Exists')
user.login()
.then(function(){
deferred.resolve(user);
}).fail(function(){
deferred.reject();
})
} else {
var data = {
provider: profile.provider,
uid: profile.id,
name: profile.displayName
};
if (profile.emails && profile.emails[0] && profile.emails[0].value) {
data.email = profile.emails[0].value;
}
if (profile.name && profile.name.givenName) {
data.firstname = profile.name.givenName;
}
if (profile.name && profile.name.familyName) {
data.lastname = profile.name.familyName;
}
if(!profile.email){
data.email='dnd@testglpu.com'
}
data.origin=profile.origin
User.create(data).exec(function (err, user) {
if(err||!user){
sails.log.error('Unable to create user',err.stack)
deferred.reject(err)
}
if(user){
user.login()
.then(function(){
deferred.resolve(user);
}).fail(function(){
deferred.reject();
})
}
});
}
});
return deferred.promise;
},
findForClaim:function(id){
var deferred= Q.defer();
User.findOne(id)
.exec(function(err,user){
if(err){
deferred.reject(err)
return
}
if((!user.email)||(!user.phoneNumber)){
deferred.reject('No email or phoneNumber')
return
}
sails.log.info('Here-->',user.email)
deferred.resolve(user)
})
return deferred.promise
}
};
AuthController コードは次のようになります。
facebook: function (req, res) {
passport.authenticate('facebook', { failureRedirect: '/login', scope: ['public_profile','email'] },
function (err, user) {
req.logIn(user, function (err) {
if (err) {
console.log(err);
res.view('500');
return;
}
res.redirect('/');
return;
});
})(req, res);
},
Facebook の設定ファイルは次のようになります。
facebook:{
clientID: "ID",
clientSecret: "SECRET",
callbackURL: "http://localhost:1337/auth/facebook/callback"
}
ビューページは次のようになります。
<div class="main">
<% if(flash && flash.err) { %>
<ul class="alert alert-danger">
<% Object.keys(flash.err).forEach(function(index){%>
<% if (flash.err[index].message != undefined) {%>
<li><%=JSON.stringify(flash.err[index].message)%></li>
<% } %>
<% })%>
<li></li>
</ul>
<% }%>
<h1 id="main-title">Please sign in</h1>
<a href="/auth/facebook/" class="btn">with Facebook</a>
<a href="/logout" class="btn">Logout</a>
「With facebook」ボタンをクリックすると、次のようなログが表示されます。
info: Device type { type: 'desktop' }
verbose: Running res.view([object Object])...
verbose: Using layout: /home/testgulp/Desktop/funtestgulp/views/layoutBW
verbose: Rendering view :: site/index (located @ /home/testgulp/Desktop/funtestgulp/views/site/index)
info: inside flash policy
verbose: Running res.view()...
verbose: Using layout: /home/testgulp/Desktop/funtestgulp/views/layoutBW
verbose: Rendering view :: auth/index (located @ /home/testgulp/Desktop/funtestgulp/views/auth/index)
info: inside flash policy
info: inside flash policy
info: Error {"error":"E_VALIDATION","status":400,"summary":"1 attribute is invalid","model":"User","invalidAttributes":{"email":[{"rule":"string","message":"`undefined` should be a string (instead of \"null\", which is a object)"},{"rule":"email","message":"\"email\" validation rule failed for input: null"},{"rule":"required","message":"\"required\" validation rule failed for input: null"}]}}
[TypeError: Cannot read property 'nickname' of undefined]
verbose: Running res.view(500)...
verbose: Using layout: /home/testhulp/Desktop/funtestgulp/views/layoutBW
verbose: Rendering view :: 500 (located @ /home/testgulp/Desktop/funtestgulp/views/500)