Why the affected user by ID counts always show zero? - djaty

I've integrated Djaty NodeJS SDK with my project as the following:
djaty.init({
apiKey: 'xxxxxxxxx',
apiSecret: 'xxxxxxxxx',
});
I started receiving bugs normally but the affected user counts always show zero. What am I missing?

By default, Djaty gets the user data (userId, logon) from req.user but if the user data don't exist inside the req.user, you can pass parseUser() option as the following:
djaty.init({
apiKey: 'xxxxxxxxx',
apiSecret: 'xxxxxxxxx',
parseUser: req => ({
// Fetch the `userId` and `username` from `req.session` for example.
userId: req.session.user.userId,
logon: req.session.user.username,
}),
});

Related

Can't receive valid test on specific test controller

I'm testing a sign-in controller and therefore I've written the following test:
it("return 200 when user signed in successfully", async () => {
await request(app)
.post("/api/v1/signup")
.send({
name: "some-name",
email: "test#mail.com",
password: "abcdefg",
})
.expect(StatusCodes.CREATED);
await request(app).post("/api/v1/signin")
.send({
name: "some-name",
email: "test#mail.com",
password: "abcdefg",
});
.expect(StatusCodes.OK);
});
The test code is straightforward. When the two controllers are tested in postman, everything work well and when start to test in jest, I receive bad request when a user try to sign in. The reason for this bad request is because when try to find an user by email in the signin controller, I receive null which I really don't understand what is the cause of this result.
What I must take into account to resolve this issue when testing in jest?
After doing a deep research into this problem, I had realised that when I use the supertest post-request to save particular data into an user collection, this doesn't seems to work. A workaround for this problem is to import the user-model to create particular data into the collection.
Updated Code
it("return 200 when user signed in successfully", async () => {
await new User({
name: "some-name",
email: "test#mail.com",
password: "abcdefg",
}).save();
const response = await request(app)
.post("/api/v1/signin")
.send({
name: "some-name",
email: "test#mail.com",
password: "abcdefg",
});
expect(response.status).toBe(StatusCodes.OK);
});

I would like to update only one state and return the updated state in reactjs

I have a nodejs and reactjs web application. Though I am still learning reactjs. I have a system where users login, I captured the user's name, id and token coming from my nodejs: I am using react useContext() to mange the app's state.
Login:
dispatch({type: "LOGIN_START"})
try{
const response = await axios.post("/auth/login", {
username: userRef.current.value,
password: passwordRef.current.value
});
console.log(response.data.token)
dispatch({type:"LOGIN_SUCCESS", payload: response.data.user, tokenData: response.data.token});
}catch(err){
dispatch({type: "LOGIN_FAILURE"})
};
I saved the response.data.user and response.data.token in my localstorage.
const INITIAL_STATE = {
user: JSON.parse(localStorage.getItem("user")) || null,
token: JSON.parse(localStorage.getItem("token")) || null,
export const Context = React.createContext();
export const ContextProvider = ({children}) =>{
const [state, dispatch] = useReducer(Reducer, INITIAL_STATE);
//useEffect to enable the user details to be stored in their local storage
useEffect(() => {
localStorage.setItem("user", JSON.stringify(state.user, ));
localStorage.setItem("token", JSON.stringify(state.token, ));
}, [state.user], [state.token]);
return(
<Context.Provider value={{
user:state.user,
token: state.token,
dispatch,
}}>
{children}
</Context.Provider>
)
};
I created the login action like this which enabled me to capture the user's details and token:
export const LoginSucess = (user, token) => ({
type: "LOGIN_SUCCESS",
payload: user,
tokenData: token
});
And the useReducer was written like this:
case "LOGIN_SUCCESS":
return{
user: action.payload,
token: action.tokenData,
};
If I want to update the token alone, it does't work as I wanted. Here is the code:
case "UPDATE_TOKEN":
return{
...state,
token: action.tokenData,
isFetching: false,
error: true,
};
It just does't update at all. If I remove ...state, it will update the token but the state.user will become undefined.
If I dont separate the token and user's details during sign-in action, it becomes a problem when the user wants to update their profile. Surely, the user wouldn't be updating their token when updating their profile and this will return user's details without a token. Token is updated via refresh token route or when user logs-in again.
I want to separate the token state from the user's name and id state. The token changes every 15 minutes, needs to have it own state. How do I implement this?
I decided to create another usecontext and usereducer to handle the token state since it will always change every 15 minutes.

Can't post to firebase's database

When I try to post data with postman to firebase I get this error:
Error: Value for argument "data" is not a valid Firestore document. Cannot use "undefined" as a Firestore value (found in field body).
I checked and body and userHandle comes back as undefined but I don't know why. With postman I use POST and in the body I send a json like this:
{
"body": "scream 2",
"userHandle": "user2"
}
as raw JSON(application/json)
const functions = require('firebase-functions');
const admin = require('firebase-admin');
let firebaseConfig = {
apiKey: '*******',
authDomain: '******',
databaseURL: '*****',
projectId: '*****',
storageBucket: '****',
messagingSenderId: '*****',
appId: '*******'
};
admin.initializeApp(firebaseConfig);
exports.createScream = functions.https.onRequest((req, res) => {
if (req.method !== 'POST') {
return res.status(400).json({ error: 'Method not allowed' });
}
const newScream = {
body: req.body.body,
userHandle: req.body.userHandle,
createdAt: admin.firestore.Timestamp.fromDate(new Date())
};
admin
.firestore()
.collection('screams')
.add(newScream)
.then(doc => {
res.json({ message: `document ${doc.id} created successfully` });
})
.catch(err => {
res.status(500).json({ error: 'something went wrong' });
console.error(err);
});
});
Acording to my experience:
Lot of people while using postman forget to change the body to JSON (by Default it's text). Check the picture below:
So if you will see in the right-end you will find JSON highlighted in orange color. That must be set to JSON (If you are trying to push JSON ofcourse). By default i found that it is in text.
Rest about the code you have posted in the question is up to mark.
I really thought it might help someone facing the simliar problem therefore decided to mention this.
Happy coding.
The error message is saying that one of the fields you're adding to the Firestore document is undefined:
const newScream = {
body: req.body.body,
userHandle: req.body.userHandle,
createdAt: admin.firestore.Timestamp.fromDate(new Date())
};
Since what you're showing is all variables whose values we can't see, we can't tell which one might be undefined. You will have to debug this on your own to figure out which one is undefined, and modify your code to check that the inputs are valid.
Okay it's a little weird but in postman the body was set to raw JSON (application/json)but I set it again to JSON(application/json) and now it's working.

Firebase Admin SDK - Create user with custom fields

I've been following the Firebase SDK Admin - Manager User docs and everything went find for me with it's system. Either way, i want to extend my users information with fields such as first name, last name, nacionality, etc etc.
Right now i'm using Vue.JS (fronted), Axios (Http client) and Express.js (server) to manage my project and this is the way i create my users:
Vue.JS createUser method:
createUser() {
axios.post('http://localhost:3000/users',
{
username: this.username,
email: this.email,
firstName: this.firstName,
lastName: this.lastName,
password: this.password,
}).then(r => {
console.log(r)
}).catch(e => {
console.log(e)
})
// createUser
}
Each field: username, email, firstName, etc... got its value form a common HTML Form and they work just fine.
This is my "user create" route on the server side:
router.post('/', function (req, res, next) {
firebase.auth().createUser({
email: req.body.email,
username: req.body.username,
firstName: req.body.firstName,
lastName: req.body.lastName,
emailVerified: false,
password: req.body.password,
disabled: false
}).then(function(userRecord) {
console.log("Successfully created new user:", userRecord.uid);
}).catch(function(error) {
console.log("Error creating new user:", error);
});
});
And this is how i retrieve the users information:
router.get('/', function(req, res, next) {
firebase.auth().listUsers()
.then(function(listUsersResult) {
res.send(listUsersResult.users);
}).catch(function(error) {
console.log("Error listing users:", error);
})
});
The problem is that i can't get the custom fields i added (or they simply does not exists). Here's is a pictures of the data once i get it with the next method:
getItems() {
axios.get('http://localhost:3000/users').then(r => {
this.users = r.data
}).catch(e => {
console.log(e)
})
},
Is there a way to set custom fields on my user creation or (if my process is right) a way to retrieve them?
Firebase users are not customizable, unfortunately you can not add custom fields to the user... check out these docs for the properties of this object. Also check out this question & answer where Frank explains that you need to store any extra info separately... this is typically done in a table (named something like /userDetails) in your database.
FEBRUARY 2022 EDIT:
Since writing this answer, custom user claims are now a thing. It's meant for authentication / rules purposes and not data-storage, so most things should still be kept in the database as originally stated. Note that you CAN access the custom fields client-side.
Keep in mind, this is adding additional data to the ID token that gets sent with EVERY server request, so you should try to limit usage of this to role/permission based things and not, say, image data for a 2nd profile avatar. Read the best practices for custom claims on the official docs.
You can set a user's profile, immediately after creating.
firebase.auth().createUserWithEmailAndPassword(
email,
password,
).then(credential => {
if (credential) {
credential.user.updateProfile({
displayName: username
})
}
}

getting info about facebook user using passport

this are my first steps in node.js in general and passport in particular and i came across a really annoying issue. i am trying to get the events user attended to with hes Facebook profile but no matter what i tried it simply didn't work. So i thought "ok, lets and get other data" but except for the basic display name and profile pic any other attempt (birthday,events,friends list etc..) ends up with no data. i tried using Facebook's api alot in the last few days (for the first time) and simply couldnt figure it out...this is my last attempt:
passport.use(new FacebookStrategy({
clientID: config.fb.appID,
clientSecret: config.fb.appSecret,
callbackURL: config.fb.callbackURL,
profileFields: ['id', 'displayName', 'photos', 'birthday', 'events', 'profileUrl', 'emails', 'likes']
}, function(accessToken, refershToken, profile, done){
//Check if the user exists in our Mongo DB database
//if not, create one and return the profile
//if exists, return profile
userModel.findOne({'profileID':profile.id}, function(err, result){
if(result){
done(null,result);
} else {
// Create a new user in our mongoLab account
var newFbUSer = new userModel({
profileID: profile.id,
fullname: profile.displayName,
profilePic:profile.photos[0].value || '',
birthday:profile.birthday,
//friends:profile.user.friends[0],
profileUrl:profile.profileUrl
});
newFbUSer.save(function(err){
done(null,newFbUSer);
console.log(newFbUSer.displayName);
})
}
})
}))
any help with how can i get and use user's friends list/ events??
Maybe you haven't passed the details of information you need to facebook while calling the Facebook login. While calling the facebook login you need to specify what all information you need in the scope. For example if you need public_profile,email,user_friends following is the code which you will add in routes:
app.get('/auth/facebook', passport.authenticate('facebook', { scope : 'public_profile,email,user_friends' }));
Try this for the full name:
fullName: profile.name.givenName + ' ' + profile.name.familyName

Resources