Connecting Users: How do they see each other?

37 views
Skip to first unread message

Nathan McKaskle

unread,
Nov 18, 2015, 11:42:58 AM11/18/15
to loopb...@googlegroups.com

Let's say I have a social app where users connect with friends on their contacts to do something. How do those users find each other? See their e-mails? So far no user can see another user. What is the best way to do this? This specific need is not anywhere in the documentation that I can find and on Stackoverflow this question gets downvoted by trolls for no apparent reason. It's not answered in the documentation that I can find anywhere. I've looked and searched and searched Google. I don't know if I'm looking for it wrong or what.


If I GET the user model whether it's extended to a model called people or whether I just use the built in user model, I get this error when I query from the explorer using the GET method on my person model:

{   
"error": {
        "name": "Error",
        "status": 401,
        "message": "Authorization Required",
        "statusCode": 401,
        "code": "AUTHORIZATION_REQUIRED",
        "stack": "Error: Authorization Required at...    } 
}

It doesn't even matter if I add this to the person.json in the model (and I'm not even sure if I should be doing this):

{
      "accessType": "EXECUTE",
      "principalType": "ROLE",
      "principalId": "$everyone",
      "permission": "ALLOW",
      "property": "__get__People",
      "model": "Person"
    },

What is the problem here? What is recommended? How do users connect with each other in Loopback?

Kevin Coleman

unread,
Nov 18, 2015, 12:51:59 PM11/18/15
to LoopbackJS
A simplistic approach would be allow all logged-in users to get a list of all e-mail addresses.

You probably don't want to use the built-in REST methods to do this (otherwise you'll wind up exposing all user information to everyone), so you'll want to create a new method on your extended users model (people) like findEmailAddresses.

Your ACL would look something like:

{
  "principalType": "ROLE",
  "principalId": "$authenticated",
  "permission": "ALLOW",
  "property": "findEmailAddresses"
}

If you take this simplistic approach, your users probably won't be happy that all users will have access to their e-mail address.

A better approach would be to use a graph data structure so that you can relate users to each other and store privacy preferences per user similar to how Facebook works. For example, you can only see friends of your friends that have given friends of their friends permission to see their information.

(K) 

Nathan McKaskle

unread,
Nov 18, 2015, 1:57:13 PM11/18/15
to LoopbackJS
The only e-mails it will find to begin with are the ones it matches to those found on the users contacts. At least in beta. For now I just want to see if I can get the basics working.

What can I do to get it to see the e-mail addresses? I mean the findEmailAddresses method would still need access but where? In what model? Maybe that's where I'm confused is where exactly to add the ACL and how to give it access to what user info. In the user.json? In the person.json? Because even when I gave everyone access in person.json to everything like below:

{
      "accessType": "EXECUTE",
      "principalType": "ROLE",
      "principalId": "$everyone",
      "permission": "ALLOW",
      "property": "__get__People",
      "model": "Person"
    },

I still couldn't see anything and got authorization required.

Nathan McKaskle

unread,
Nov 18, 2015, 3:28:30 PM11/18/15
to LoopbackJS
The more important question I may need to ask is in the method, what is the command to find all users and return just the e-mail? I see findById but I don't see one to just list all users.


On Wednesday, November 18, 2015 at 12:51:59 PM UTC-5, Kevin Coleman wrote:

Kevin Coleman

unread,
Nov 18, 2015, 5:06:32 PM11/18/15
to LoopbackJS
It's not clear how you have set up the relationships between users. Have you created model relationships? 

You use the PersistedModel.find([filter], callback) method in your remote method to return a list of users.

ACLs only apply to REST API endpoints, so you'll only need to add an ACL for your findEmailAddresses remote method.

Nathan McKaskle

unread,
Nov 19, 2015, 11:39:46 AM11/19/15
to LoopbackJS
Well, the person model is the extension of the user model so it just has user as its base.  So instead of Person.find I do PersistedModel.find?

Nathan McKaskle

unread,
Nov 19, 2015, 11:40:54 AM11/19/15
to loopb...@googlegroups.com
Here's what I have in my Person.js now and yet I can't find the findEmailAddresses method in the explorer, the copy/paste wasn't perfect:

module.exports = function(Person) {
Person.getPrefs = function(personId, cb) {
Person.findById(personId,{ 
include: [{ 
relation: 'foodPrefs', 
scope: { 
include: { 
relation: 'food_pref_to_food_type' 
}
}
}]
}, function(err, personFound) {
if (err) {
return cb(err);
}

cb(null, personFound);
});
}

Person.findEmailAddresses = function(cb) {
   Person.find(function(err, peopleFound) {
       if (err) {
           return cb(err);
       }
       cb(null, peopleFound);
   });
}

Person.remoteMethod(
   'getPrefs', {
       http: {path: '/:personId/getPrefs', verb: 'get'},
       accepts: [{arg: 'personId', type: 'number'}],
       returns: {arg: 'type', type: 'object'},
       description: ['a person object']
   }
);

Person.remoteMethod(
   'findEmailAddresses', {
       http: {
           path: '/:Person',
           verb: 'get'
       },
       returns: [{
           arg: 'email',
           type: 'array'
       }],
       description: ['all emails']
   }
);

};

Kevin Coleman

unread,
Nov 19, 2015, 12:20:13 PM11/19/15
to LoopbackJS
No, your model inherits from User, which inherits from PersistedModel.

Kevin Coleman

unread,
Nov 19, 2015, 12:31:26 PM11/19/15
to LoopbackJS
I think your path: specification is not correct. The path should be relative to the model. For example: '/findEmailAddress'.

(K)

Nathan McKaskle

unread,
Nov 19, 2015, 1:25:39 PM11/19/15
to LoopbackJS
You're right, that worked, now I got it listing every user, but it should just list e-mails. Hmmmm

Nathan McKaskle

unread,
Nov 19, 2015, 1:27:48 PM11/19/15
to LoopbackJS
I take that back, it's showing e-mails and an extended part of the person model that I added, First Name and Last Name and their ID, for some reason, as part of the email array. Strange.

Nathan McKaskle

unread,
Nov 19, 2015, 1:35:35 PM11/19/15
to LoopbackJS
So I added two extra properties, fname and lname to the Person model and I have these fake users that get created in the db memory when the server starts each time for testing (node .)

This is what it shows for "email" returning, it's odd really:

{
  "email": [
    {
      "fname": "Me",
      "lname": "You",
      "email": "m...@home.com",
      "id": 1
    },
    {
      "fname": "Lazy",
      "lname": "Bastard",
      "email": "la...@home.com",
      "id": 2
    },
    {
      "fname": "Bored",
      "lname": "Athome",
      "email": "bo...@home.com",
      "id": 3
    }
  ]
}

Kevin Coleman

unread,
Nov 19, 2015, 2:03:41 PM11/19/15
to LoopbackJS
That's because your .find is asking for all fields for all people. Check the PersistedModel.find docs for find parameters to limit returned fields.

(K) 

Nathan McKaskle

unread,
Nov 19, 2015, 3:47:59 PM11/19/15
to loopb...@googlegroups.com
Thanks for all this help, soooo close now "The query filter [{\"fields\":{\"email\":true}}] is not an object"

Person.findEmailAddresses = function(cb) {
   
Person.find([ { fields: { email: true } } ], function(err, peopleFound) {

Kevin Coleman

unread,
Nov 19, 2015, 3:54:31 PM11/19/15
to LoopbackJS
That's because you're passing it as an array (of objects). Remove the brackets.

Nathan McKaskle

unread,
Nov 19, 2015, 4:11:23 PM11/19/15
to LoopbackJS
Awesome that did it!! Thanks so much!!
Reply all
Reply to author
Forward
0 new messages