Querying User table/class - Do I need Cloud Function?

Hey Guys,

Trying to get a list of users from the user class table. I canā€™t seem to do this from the front end (as it just gives me the currently logged-in user). I tried to do it as a cloud function but no joy either.

Hereā€™s my code:

Front end:

loadUsers = async () => 
{
    const allusers = await Moralis.Cloud.run("loadUsers");
    console.log(allusers);
}

ā€¦and hereā€™s the cloud function:

Moralis.Cloud.define("loadUsers", async (request) =>
{
    const query = new Moralis.Query("User");
    const allusers = await query.find();
  	return allusers;
});

Hi @sgealbhain

You canā€™t call all users from the front end for security reasons and via cloud functions too.

You need to change your code to:
const allusers = await query.find({useMasterKey:true});

Donā€™t use {useMasterKey:true} in the front-end(only in cloud functions), itā€™s not safety!

Take a look at Using the Master Key in cloud code

Happy BUIDLing :man_mechanic:

Thanks that worked! But is this the best way to do what Iā€™m trying to do? Basically I am trying to display a list of all users ā€œFull Nameā€ and avatar pic on the homepage of my site?

I recommend you to create a new table ā€œUser Profilesā€

1 Like

Would it not be possible to to query the main user table/class and just filter the results in the Clound Function by using query.select to only give me fullnames etc? If so, what would be the syntax for that?

Hey @sgealbhain

Here is an example:

Moralis.Cloud.define("loadUsers", async (request) => {
  const pipeline = [
    { project: { email: 1, username: 1, objectId: 0  } } 
  ];

  const query = new Moralis.Query("User");

  return query.aggregate(pipeline, {useMasterKey:true})
    .then(function(results) {
    return results;
  })
    .catch(function(error) {
    return error;
  });
});

Curently .select doesnā€™t work correctly, so I suggest you to use pipelines Aggregate docs

1 Like

That works great thanks! The next part Iā€™m confused about is how I take this info back and display it on a html page?

I have this in my test.html page

loadUsers = async () => 
{
    const allusers = await Moralis.Cloud.run("loadUsers");
    console.log(allusers);
    return allusers;
}

But it just logs the usernames into the console. How would I reference them in my JS to write them to the page?

I think I figured it out with this:

    str = JSON.stringify(allusers);
    document.getElementById("display-4-text").textContent = str;
1 Like

Great work @sgealbhain

Yes, you can use this one.
Or you can get separately the text in the object.

document.getElementById("display-name").textContent = allusers.Name;
document.getElementById("display-surname").textContent = allusers.Surame;

Happy BUIDLing :man_mechanic:

Yes I went a little more advanced with it now to loop through returned users :slight_smile:

loadUsers = async () => 
{
    const allusers = await Moralis.Cloud.run("loadUsers");
    var userList = document.getElementById('userList');
    // var today = new Date();
    for (const usr of allusers)
    {
        // lastSeen = today.getDate - usr.updatedAt.getDate;
        var dateString = new Date(usr.updatedAt);
        let formatted_date = dateString.getDate() + "/" + (dateString.getMonth() + 1) + "/" + dateString.getFullYear()
        document.getElementById("userList").innerHTML += '<p><b>@'+usr.username+'</b><br><img src='+usr.Avatar._url+' height=50 width=50><br><i>Last Seen</i><br><b>'+formatted_date+'</b></p>';
        console.log(usr.Avatar._url);
    }

    console.log(allusers);
    return allusers;
}
1 Like

Now Iā€™ve hit another problem. Might be very noob! But Now now I have retrieved a list of users securely and can display them on my page. How do I make each user button clickable so when I click their button, it shows me their profile?

    for (const usr of allusers)
    {
        // lastSeen = today.getDate - usr.updatedAt.getDate;
        var dateString = new Date(usr.updatedAt);
        let formatted_date = dateString.getDate() + "/" + (dateString.getMonth() + 1) + "/" + dateString.getFullYear()
        document.getElementById("userList").innerHTML += '<p><b><button onclick='+showOtherProfile(usr.username,usr.TagLine)+'>'+usr.username+'</button></b><br><img src='+usr.Avatar._url+' height=50 width=50><br><i>Last Seen</i><br><b>'+formatted_date+'</b></p>';
    }

The above results in brickā€¦

Hey @sgealbhain

Sorry for long response.

Take a look at:

And then yoy can add Attributes using:

elem.setAttribute("onclick","openUser();");
1 Like

Hi @Yomoo

I tried that but itā€™s only ever alerting the last user loaded when I click their button?

loadUsers = async () => 
{
    const allusers = await Moralis.Cloud.run("loadUsers");
    var userList = parent.document.getElementById('userList');
    // var today = new Date();
    for (usr of allusers)
    {
        // lastSeen = today.getDate - usr.updatedAt.getDate;
        var dateString = new Date(usr.updatedAt);
        let formatted_date = dateString.getDate() + "/" + (dateString.getMonth() + 1) + "/" + dateString.getFullYear()

        // 28th
        const uList = document.getElementById("userList");
        let newUserItem = document.createElement('div');
        newUserItem.setAttribute("id", usr.username);
        newUserItem.setAttribute("onClick", "alert(usr.username);");
        newUserItem.innerHTML = '<b><button id='+usr.username+'>'+usr.username+'</button></b><br><img src='+usr.Avatar._url+' height=50 width=50><br><i>Last Seen</i><br><b>'+formatted_date+'</b>';
        uList.appendChild(newUserItem);
        // 28th /

    }

    console.log(allusers);
    return allusers;
}

Hi,
Is this the alert part that you talk about that it doesnā€™t have the right user?

Yes, it always alerts the last username. So if there are 3 users, it will only alert User3, regardless of which button I click

that "alert(usr.username);" doesnā€™t look like it should even work for me, maybe something like "alert(" + usr.username + ");"

Itā€™s always advisable to have an event listener instead of adding onClick functionality manually. When does the click even get called anyway? Do you click the div element or do you just run the above code for the ā€œalertā€ to occur?

Using an event listener avoids sync issues between DOM rendering and function assignment.

@malik Iā€™m somewhat of a noob to JS. The ā€œonClickā€ gets called when you click a button or a div, just to alert the username for now, for testing purposes only. Once I get this bit working, it will pass the username and other user information to a function to display their profile modal.

I am looping through my Moralis user database and displaying a list of usernames. When I click on the users DIV with the id of their username, I want to display their profile modal.

Could you please show me how Iā€™d add the event listener? I tried the below, but still the same issue. It only alerts the last username loaded in the loop regardless of which div/button I click.

loadUsers = async () => 
{
    const allusers = await Moralis.Cloud.run("loadUsers");
    var userList = parent.document.getElementById('userList');
    // var today = new Date();
    for (usr of allusers)
    {
        // lastSeen = today.getDate - usr.updatedAt.getDate;
        var dateString = new Date(usr.updatedAt);
        let formatted_date = dateString.getDate() + "/" + (dateString.getMonth() + 1) + "/" + dateString.getFullYear()

        uList = document.getElementById("userList");
        let newUserItem = document.createElement('div');
        newUserItem.setAttribute("id", usr.username);
        newUserItem.setAttribute("onClick", "alert(usr.username);");
        newUserItem.innerHTML = '<b><button id='+usr.username+'>'+usr.username+'</button></b><br><img src='+usr.Avatar._url+' height=50 width=50><br><i>Last Seen</i><br><b>'+formatted_date+'</b>';
        newUserItem.addEventListener("click", function(){ alert(usr.username); });
        uList.appendChild(newUserItem);
    }

    console.log(allusers);
    return allusers;
}

Figured it out guys! Apparently, this relates to ā€œHoistingā€. All I had to do in the for loop was change from this:

for (usr of allusers)

To this:

for (let usr of allusers)
3 Likes