Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add function for retrieving user permissions #264

Closed
wants to merge 24 commits into from
Closed

Add function for retrieving user permissions #264

wants to merge 24 commits into from

Conversation

seawolf42
Copy link
Contributor

This adds a function get_permissions() that returns the user permissions from the Graph API. To use this you must supply a user token.

For testing, set the environment variable FACEBOOK_USER_ACCESS_TOKEN to a token retrieved from the Graph API explorer... if this is not set then the test will be skipped.

@seawolf42
Copy link
Contributor Author

Can someone describe to me how I get the Travis CI build to pass? The error is about environment variables being set... presumably I need to set environment variables so that it can test against the Facebook API, but I don't know how to do this.

@martey
Copy link
Member

martey commented Jan 13, 2016

The environment variables are set automatically from the .travis.yml file. RIght now, your pull request is causing the build to fail because it doesn't pass the flake8 linting:

facebook/__init__.py:107:19: E201 whitespace after '{'
facebook/__init__.py:107:65: E901 SyntaxError: invalid syntax
facebook/__init__.py:107:79: E202 whitespace before '}'
facebook/__init__.py:107:80: E501 line too long (80 > 79 characters)

test/test_facebook.py:220:1: W293 blank line contains whitespace
test/test_facebook.py:224:1: W293 blank line contains whitespace
test/test_facebook.py:227:1: W293 blank line contains whitespace
test/test_facebook.py:235:1: W293 blank line contains whitespace

@seawolf42
Copy link
Contributor Author

Ah, I see. Now I know how what to do with Travis CI output... thanks!

It looks like I am using a decorator that exists in unittest in python 2.7 but not in 2.6. Do you have a preferred method for skipping a unit test if the necessary environment variable does not exist? I could import unittest2 but this might require additional changes throughout the project. I could use a regular if statement, but this will skip the test silently. Thoughts?

@seawolf42
Copy link
Contributor Author

Actually, a slightly different question. Is there any compelling reason to continue supporting python 2.6? Are there metrics anywhere of how many users are using this module on a 2.6 installation?

@martey
Copy link
Member

martey commented Jan 13, 2016

It would be simpler if you assumed that FACEBOOK_APP_ID and FACEBOOK_SECRET exist. If they do not exist, the tests should fail.

@seawolf42
Copy link
Contributor Author

This is a different parameter, FACEBOOK_USER_ACCESS_TOKEN. Since these expire they can't really be inserted into the .travis.yml file, so the test should be skipped in this case. If you want to test locally you will need to retrieve a valid token in addition to the other environment variables.

@martey
Copy link
Member

martey commented Jan 14, 2016

That said, I noticed the method only get permissions for the current user (me); it would be better if it allowed using arbitrary user IDs. I am also not sure whether you are willing to write support for deleting specific permissions as well (see my comment on #35), but it would be a great addition.

Finally, from https://developers.facebook.com/docs/graph-api/reference/user/permissions (emphasis mine):

This request must be made with a user access token or an app access token for the current app.

I think it should be possible to rewrite your test case so it uses app access tokens instead of a user access token, which should sidestep the issues of Python 2.6 compatibility and having an automated test that never runs automatically.

@seawolf42
Copy link
Contributor Author

I’ll give that a try. I had taken a stab at that but I thought I received an error. Let me check.


jeffrey k eliasen - technologist, philosopher, agent of change
blog http://jeff.jke.net/ | linkedin http://www.linkedin.com/pub/jeffrey-eliasen/3/a83/b76 | google+ http://plus.google.com/+JeffreyEliasen | facebook http://facebook.com/jeffrey.eliasen | twitter http://twitter.com/jeffreyeliasen

On Jan 13, 2016, at 14:38, Martey Dodoo [email protected] wrote:

That said, I noticed the method only get permissions for the current user (me); it would be better if it allowed using arbitrary user IDs. I am also not sure whether you are willing to write support for deleting specific permissions as well (see my comment on #35 #35), but it would be a great addition.

Finally, from https://developers.facebook.com/docs/graph-api/reference/user/permissions https://developers.facebook.com/docs/graph-api/reference/user/permissions (emphasis mine):

This request must be made with a user access token or an app access token for the current app.

I think it should be possible to rewrite your test case so it uses app access tokens instead of a user access token, which should sidestep the issues of Python 2.6 compatibility and having an automated test that never runs automatically.


Reply to this email directly or view it on GitHub #264 (comment).

@seawolf42
Copy link
Contributor Author

On second thought, that won't work. The user permissions that I am retrieving are specific to a session. This isn't data about the user, it's data about the token (which permissions the token has been granted)... without a user access token the test is meaningless.

@martey
Copy link
Member

martey commented Jan 14, 2016

The user permissions that I am retrieving are specific to a session. This isn't data about the user, it's data about the token (which permissions the token has been granted)...

I don't understand. If you have an app access token and a user ID that has granted permissions to that app, you should be able to use the app token to query said user ID's permissions.

Facebook permissions are per-app and per-user, but (as far as I know) are not per-token.

@seawolf42
Copy link
Contributor Author

I think you are right about the per-app and per-user, but even for that case we still need a way to grant a known user a specific permission for the app, and that takes user involvement to create in the first place.

Someone will need to login to FB to grant a token for a test user of some sort (do you have a dummy user and a web app for this purpose?), but if/when that is completed then I can possibly set the test up as you ask. If we do not grant at least the base permissions to any user then there is no way to test that the returned dictionary is structured properly (it will be empty), and if the user in question ever deauthenticates the app then the test will start failing for all developers, so it's kind of convoluted no matter how we do it.

I'm totally open to suggestions here, I'd just like to get closure on this enhancement.

@seawolf42
Copy link
Contributor Author

Any additional thoughts on this? The function itself is straightforward, but as I mentioned and as far as I can tell, no test is possible without first granting at least one permission to at least one user, so we either need a dummy user that we know will never deauthorize the app or we need to skip the test; otherwise we run the risk of the test suddenly starting to fail because the permission for the user went away.

@martey
Copy link
Member

martey commented Jan 21, 2016

we either need a dummy user that we know will never deauthorize the app

I can do this with the Facebook application that is used in Travis CI.

@seawolf42
Copy link
Contributor Author

That would be great! If you let me know the user’s FB ID, I’ll modify the test.


jeffrey k eliasen - technologist, philosopher, agent of change
blog http://jeff.jke.net/ | linkedin http://www.linkedin.com/pub/jeffrey-eliasen/3/a83/b76 | google+ http://plus.google.com/+JeffreyEliasen | facebook http://facebook.com/jeffrey.eliasen | twitter http://twitter.com/jeffreyeliasen

On Jan 20, 2016, at 14:46, Martey Dodoo [email protected] wrote:

we either need a dummy user that we know will never deauthorize the app

I can do this with the Facebook application that is used in Travis CI.


Reply to this email directly or view it on GitHub #264 (comment).

@seawolf42
Copy link
Contributor Author

Where can I find the user ID for the dummy user you have in Travis CI? I'm happy to update the test so we can close this out...

@seawolf42
Copy link
Contributor Author

ping :)

I'd really like to get closure on this. Just need the Facebook User ID for the dummy user that you mentioned.

@martey
Copy link
Member

martey commented Feb 28, 2016

I haven't gotten the chance to create the test user yet. If you can update the test without it, I can make the necessary modifications (to add in the user ID) when I can.

@seawolf42
Copy link
Contributor Author

One additional note, I put a dummy user ID in .travis.yml. For the main test to pass, we need a user ID that has authorized the app to replace the 12345 ID in that file.

@seawolf42
Copy link
Contributor Author

Regarding "I am also not sure whether you are willing to write support for deleting specific permissions as well (see my comment on #35), but it would be a great addition.", I'm actually happy to do this if it still needs to be done.

@seawolf42
Copy link
Contributor Author

Documentation added.

@seawolf42 seawolf42 mentioned this pull request Aug 15, 2016
@seawolf42
Copy link
Contributor Author

seawolf42 commented Nov 24, 2016

Although this fails tests, this is because it needs a user ID for a FB user who has given permission for the test app to link to his account. Once that user is created, all tests will pass.

@seawolf42
Copy link
Contributor Author

D'oh! How about if this time I submit actually working code. My bad :)

Now the only thing left is to create a user which has been authorized in the FB app so that I can un-skip the relevant test.

@seawolf42
Copy link
Contributor Author

Hey @martey, I'd really love to get this finalized, the only thing that's necessary is a user for testing. What do you need from me to get this the last mile?

Copy link
Member

@martey martey left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have added some comments.

I also think this pull request's commits could also be rebased into one singular commit - see https://github.com/edx/edx-platform/wiki/How-to-Rebase-a-Pull-Request#squash-your-changes for an example of how to do this.

@@ -16,3 +16,4 @@ env:
global:
- FACEBOOK_APP_ID=198798870326423
- FACEBOOK_SECRET=2db4d76fe8a336cf292470c20a5a5684
- FACEBOOK_USER_ID=12345
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@juhopaak added methods to create test users programmatically (fdc36cc). I think using them is a better solution than using a hardcoded user ID.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, though this feature wasn't there when we first talked about this :) ... happy to figure out how to make that change.

@@ -102,6 +102,14 @@ def __init__(self, access_token=None, timeout=None, version=None,
else:
self.version = "v" + default_version

def get_permissions(self, user_id, **args):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

args doesn't seem to be used in this method. Is there a reason that it has been included?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

had used it at one point, I think, and forgot to remove it. thanks!

def get_permissions(self, user_id, **args):
"""Fetches the permissions object from the graph."""
response = self.request(
self.version + "/" + str(user_id) + "/permissions")["data"]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we use .format here instead of manually concatenating strings?

@@ -235,7 +243,7 @@ def request(
# or it does not need `access_token`.
if post_args and "access_token" not in post_args:
post_args["access_token"] = self.access_token
elif "access_token" not in args:
elif args and "access_token" not in args:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this related to user permissions, or is it a fix for a different bug?

Copy link
Contributor Author

@seawolf42 seawolf42 Jan 6, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is probably a different bug... I had a test that was failing before, though when I revert this now that same test isn't failing, so I'm not sure what changed. Your call, do you want this reverted or included? If reverted, should I submit a different PR for it?

Copy link
Contributor Author

@seawolf42 seawolf42 Jan 6, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I take that back, that is necessary for one of my unit tests to pass. Otherwise I get:

Traceback (most recent call last):
  File "/Users/seawolf/repos/facebook-sdk-jke/test/test_facebook.py", line 223, in test_get_user_permissions_nonexistant_user
    facebook.GraphAPI(token).get_permissions(1)
  File "facebook/__init__.py", line 108, in get_permissions
    "{0}/{1}/permissions".format(self.version, user_id)
  File "facebook/__init__.py", line 247, in request
    elif "access_token" not in args:
TypeError: argument of type 'NoneType' is not iterable

The method defaults args to None, but if it is unset then line 246 throws the exception.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Per the Contributing Guidelines, a pull request should only contain commits that aren't relevant to its core feature. If it doesn't have to do with user permissions, it should be in a different pull request.

The purpose of that code is to ensure that the arguments passed to Facebook include an access token. With your code, it is necessary to set args, otherwise this will not happen.

This should have been fixed in #341, so if you rebase your branch off of the current master, the error will go away.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Totally makes sense, removed the change to the request method and added an empty args dict to the call.

@martey martey added this to the v3.0.0 milestone Jan 6, 2017
@seawolf42
Copy link
Contributor Author

I'll fix those items and squash it all, should have it to you by the end of the weekend. Thanks!

@seawolf42
Copy link
Contributor Author

Because I had made my changes on master (bad me), I will need to close this PR and create a new one. I've created PR 342 which contains the requested changes.

@seawolf42 seawolf42 closed this Jan 7, 2017
@seawolf42
Copy link
Contributor Author

@martey hoping I didn't mess this up by closing this PR and opening the other one... did this fall off the radar as a result?

@martey
Copy link
Member

martey commented Jan 10, 2017

@seawolf42 No, I have just been really busy over the past couple of days. The other pull request should be merged soon.

@seawolf42
Copy link
Contributor Author

seawolf42 commented Jan 10, 2017 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants