Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 5
Language library refactor#37
base:develop
Are you sure you want to change the base?
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
236ea0ba2e09a63c679a4d6799d9f76a6e81230438aa3cc13ad1da3e4ba88b00635cc35d7ae27276008bde242602d27608453c0ea9da5024f32ec21205a1cbeb80a8b0616c0baad114ea047ddaea710e815aa251be1639a3ac3e53e0e816762fc11aa5bafd2241187905ff6d7e4daab19cf10a48cefa843ab7e37ecaa3705f850fbbcfbfd80b45f778460a07e6a03dc31826c8c90ed54f44460da0ec572e29fb830dc53e3b7eb00d934b36387bcc27a8d1bb7dfd243321e7f30f1889265166251df7beb4a57b3eeb9a84e6e39358c416d7ad9b1e7e80822d14f4afb3f3d7d2d2cc662e9837ef2ab019990fbbef1a751e261dd135eb781677185961256a704f7f704f06882068b62cc4b723560929dee6f4022fc98dd9559b6de4799c36a9a085d1f924e1f44bf2cc5f61ff6176aa7acb75a380eb603ae22bd95088a7fe786e3fa38a201481161872d08dd013c4a9a4b579486f942fc2aa701789c6a25488276db7e24c312f004549055e7651dbe3ffc14fe88b821f9c97fc0114ebfff60b6ab3d2657acc6bffe89d5ace2e319d2a59896f28d0213038288f1b6ac17c327adf87bf72d76866349433d308de116c51b1ac3815a4444ac34b706764348c475730023b40521b68af098ecfd29b15845b972884d5e1702b2ac7371a121413077caab0b102f94a72283aea5be652f23fa41145da5990facb4894695396b60f95035943c3c57bdd540f239a5fce7cab3758670ecc1ec60dcde61e5fb12f42cad48f7877a015cf3114b03ca33b40b90d985a15142454f844d5e7f84aa7d0c2bf0609330cc12c3f6113b3209c51c51cbf8b437e9d4a72103e4567fb3e843cdf99d15d67885f0886691470c0c79f5c7a4b1c00cb471c0dc61349c5c4353b8e5ee6c6497d0c988202a40a04334b1b23b515086a9026b115bb028aa95bdcde3f61a9115f291720a4c3cb5625e799e13c5dd8cb26764e6cd64af51d9c19e33d8c1cb2da9202e6e9ad94b7ce02b0e5c5f54188e6ef4571b26502c86c410e78f2f75fcf9dc71de39865d501153b862c0c6cf664eda74935dddd526ef109152081729971d2490b0b0ede1ef2b9afe94dc00371537abce78948314a205a4f1bb5ed48bfbf85e045d79314f7706330c81d9f20c6cbc32f47beb71816ff0eac923fc9aad3d05346de42f067124709b7878f29a1fadddf92718ca207b8f341c39a8cae28bf57705539c412c1323e5083c366b1a43aFile filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -2,4 +2,4 @@ | ||
| omit = | ||
| */python?.?/* | ||
| */site-packages/nose/* | ||
| tests.py | ||
| test/* | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -54,3 +54,7 @@ Icon | ||
| ### Added by etg | ||
| setenv | ||
| ### Added by ndm | ||
| venv | ||
| .idea | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,9 +1,10 @@ | ||
| language: python | ||
| python: | ||
| - 2.6 | ||
| - 2.7 | ||
| install: | ||
| - pip install -r requirements.txt --use-mirrors | ||
| script: | ||
| nosetests tests.py --with-coverage --cover-package=toopher | ||
| nosetests --with-coverage test | ||
| after_success: | ||
| coveralls |
This file was deleted.
Uh oh!
There was an error while loading. Please reload this page.
This file was deleted.
Uh oh!
There was an error while loading. Please reload this page.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,85 +1,104 @@ | ||
| #ToopherPython | ||
| #ToopherPython [](https://travis-ci.org/toopher/toopher-python) | ||
| [](https://travis-ci.org/toopher/toopher-python) | ||
| ToopherPython is a Toopher API library that simplifies the task of interfacing with the Toopher API from Python code. | ||
| This project wrangles all the dependency libraries and handles the required OAuth and JSON functionality so you can | ||
| focus on just using the API. | ||
| #### Introduction | ||
| ToopherPython is a Toopher API library that simplifies the task of interfacing with the Toopher API from Python code. This project wrangles all the required OAuth and JSON functionality so you can focus on just using the API. | ||
| ### Python Version | ||
| * 3.6 | ||
| #### Learn the Toopher API | ||
| ### Documentation | ||
| Make sure you visit [https://dev.toopher.com](https://dev.toopher.com) to get acquainted with the Toopher API fundamentals. The documentation there will tell you the details about the operations this API wrapper library provides. | ||
| #### OAuth Authentication | ||
| First off, to access the Toopher API you'll need to sign up for an account at the [Toopher developers portal](https://dev.toopher.com) and create a "requester". When that process is complete, your requester is issued OAuth 1.0a credentials in the form of a consumer key and secret. Your key is used to identify your requester when Toopher interacts with your customers, and the secret is used to sign each request so that we know it is generated by you. This library properly formats each request with your credentials automatically. | ||
| ## ToopherApi Workflow | ||
| #### The Toopher Two-Step | ||
| Interacting with the Toopher web service involves two steps: pairing, and authenticating. | ||
| ##### Pair | ||
| Before you can enhance your website's actions with Toopher, your customers will need to pair their phone's Toopher app with your website. To do this, they generate a unique, nonsensical "pairing phrase" from within the app on their phone. You will need to prompt them for a pairing phrase as part of the Toopher enrollment process. Once you have a pairing phrase, just send it to the Toopher web service and we'll return a pairing ID that you can use whenever you want to authenticate an action for that user. | ||
| ##### Authenticate | ||
| You have complete control over what actions you want to authenticate using Toopher (for example: logging in, changing account information, making a purchase, etc.). Just send us the user's pairing ID, a name for the terminal they're using, and a description of the action they're trying to perform and we'll make sure they actually want it to happen. | ||
| #### Librarified | ||
| This library makes it super simple to do the Toopher two-step. Check it out: | ||
| ### Step 1: Pair | ||
| Before you can enhance your website's actions with Toopher, your customers will need to pair their mobile device's Toopher app with your website. To do this, they generate a unique pairing phrase from within the app on their mobile device. You will need to prompt them for a pairing phrase as part of the Toopher enrollment process. Once you have a pairing phrase, just send it to the Toopher web service along with your requester credentials and we'll return a pairing ID that you can use whenever you want to authenticate an action for that user. | ||
| ```python | ||
| import toopher | ||
| # Create an API object using your credentials | ||
| api = toopher.ToopherApi("<your consumer key>", "<your consumer secret>") | ||
| # Step 1 - Pair with their phone's Toopher app | ||
| pairing_status = api.pair("pairing phrase", "username@yourservice.com") | ||
| # Step 1 - Pair with their mobile device's Toopher app | ||
| pairing = api.pair("username@yourservice.com", "pairing phrase") | ||
| ``` | ||
| ### Step 2: Authenticate | ||
| You have complete control over what actions you want to authenticate using Toopher (logging in, changing account | ||
| information, making a purchase, etc.). Just send us the username or pairing ID and we'll make sure they actually want it to happen | ||
| . You can also choose to provide the following optional parameters: terminal name, requester specified ID and | ||
| action name (*default: "Log in"*). | ||
| ```python | ||
| # Step 2 - Authenticate a log in | ||
| auth = api.authenticate(pairing_status.id, "my computer") | ||
| authentication_request = api.authenticate("username@yourservice.com", "terminal name") | ||
| # Once they've responded you can then check the status | ||
| auth_status = api.get_authentication_status(auth.id) | ||
| if (auth_status.pending == False and auth_status.granted == True): | ||
| authentication_request.refresh_from_server() | ||
| if not authentication_request.pending and authentication_request.granted: | ||
| # Success! | ||
| ``` | ||
| #### Handling Errors | ||
| If any request runs into an error a `ToopherApiError` will be thrown with more details on what went wrong. | ||
| ## ToopherIframe Workflow | ||
| #### Zero-Storage usage option | ||
| Requesters can choose to integrate the Toopher API in a way does not require storing any per-user data such as Pairing ID and Terminal ID - all of the storage | ||
| is handled by the Toopher API Web Service, allowing your local database to remain unchanged. If the Toopher API needs more data, it will `raise()` a specific | ||
| error that allows your code to respond appropriately. | ||
| ### Step 1: Embed a request in an IFRAME | ||
| 1. Generate an authentication URL by providing a username. | ||
| 2. Display a webpage to your user that embeds this URL within an `<iframe>` element. | ||
| ```python | ||
| try: | ||
| # optimistically try to authenticate against Toopher API with username and a Terminal Identifier | ||
| # Terminal Identifer is typically a randomly generated secure browser cookie. It does not | ||
| # need to be human-readable | ||
| auth = api.authenticate_by_user_name(user_name, requester_terminal_id) | ||
| # if you got here, everything is good! poll the auth request status as described above | ||
| # there are four distinct errors ToopherAPI can return if it needs more data | ||
| except UserDisabledError: | ||
| # you have marked this user as disabled in the Toopher API. | ||
| except UserUnknownError: | ||
| # This user has not yet paired a mobile device with their account. Pair them | ||
| # using api.pair() as described above, then re-try authentication | ||
| except TerminalUnknownError: | ||
| # This user has not assigned a "Friendly Name" to this terminal identifier. | ||
| # Prompt them to enter a terminal name, then submit that "friendly name" to | ||
| # the Toopher API: | ||
| # api.create_user_terminal(user_name, terminal_name, requester_terminal_id) | ||
| # Afterwards, re-try authentication | ||
| except PairingDeactivatedError: | ||
| # this user does not have an active pairing, | ||
| # typically because they deleted the pairing. You can prompt | ||
| # the user to re-pair with a new mobile device. | ||
| import toopher | ||
| # Create an API object using your credentials | ||
| iframe_api = toopher.ToopherIframe("<your consumer key>", "<your consumer secret>") | ||
| auth_iframe_url = iframe_api.get_authentication_url("username@yourservice.com"); | ||
| # Add an <iframe> element to your HTML: | ||
| # <iframe id="toopher_iframe" src=auth_iframe_url /> | ||
Member There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should add some information about how to style the iframe - they should make it 300px tall. Width should be at least 400px, with 720px or wider being preferred Author There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The plan was to have the original HTML markup info moved to the dev site. Do you think it needs to be included here as well? | ||
| ``` | ||
| #### Dependencies | ||
| This library uses the [Requests](http://docs.python-requests.org/en/latest/) library to handle OAuth signing and to make the web requests. If you install using pip (or easy_install) they'll be installed automatically for you. | ||
| ### Step 2: Validate the postback data | ||
| The simplest way to validate the postback data is to call `is_authentication_granted` to check if the authentication request was granted. | ||
| #### Try it out | ||
| Check out `demo.py` for an example program that walks you through the whole process! Just download the contents of this repo, make sure you have the dependencies listed above installed, and then run it like-a-this: | ||
| ```python | ||
| # Retrieve the postback data as a string from POST parameter 'iframe_postback_data' | ||
| postback_data = request.args['iframe_postback_data'] | ||
| # Returns boolean indicating if authentication request was granted by user | ||
| authentication_request_granted = iframe_api.is_authentication_granted(postback_data) | ||
| if authentication_request_granted: | ||
| # Success! | ||
| ``` | ||
| ### Handling Errors | ||
| If any request runs into an error a `ToopherApiError` will be thrown with more details on what went wrong. | ||
| ### Demo | ||
| Check out `demo.py` for an example program that walks you through the whole process! Just download the contents of | ||
| this repo, make sure you have the dependencies installed, and run the command below: | ||
| ```shell | ||
| $ python demo.py | ||
| ``` | ||
| ## Contributing | ||
| ### Dependencies | ||
| This library uses the [Requests](http://docs.python-requests.org/en/latest/) library and [OAuthLib](https://oauthlib.readthedocs.org/en/latest/index.html) to handle OAuth signing and make the web requests. | ||
| Toopher uses [pip](https://pypi.python.org/pypi/pip) to install Python packages. To ensure all dependencies are up-to-date run: | ||
| ```shell | ||
| $ python ./demo.py | ||
| $ pip install -r requirements.txt | ||
| ``` | ||
| ### Tests | ||
| To run the tests using [nose](http://nose.readthedocs.org/en/latest/) enter: | ||
| ```shell | ||
| $ nosetests test | ||
| ``` | ||
| ## License | ||
| ToopherPython is licensed under the MIT License. See LICENSE.txt for the full text. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| (function(window, $){ | ||
| var postToUrl = function (path, params, method){ | ||
| method = method || 'POST'; | ||
| var form = $('<form />').attr('method', method).attr('action', path); | ||
| for (var key in params){ | ||
| if (params.hasOwnProperty(key)){ | ||
| var hiddenField = $('<input />').attr('type', 'hidden').attr('name', key).attr('value', params[key]); | ||
| form.append(hiddenField); | ||
| } | ||
| } | ||
| $('body').append(form); | ||
| form.submit(); | ||
| } | ||
| var handleMessage = function(e){ | ||
| var msgData = JSON.parse(e.data); | ||
| if (msgData.status === 'toopher-api-complete'){ | ||
| var iframe = $('#toopher_iframe'); | ||
| var frameworkPostArgsJSON = iframe.attr('framework_post_args'); | ||
| var frameworkPostArgs = {}; | ||
| if(frameworkPostArgsJSON){ | ||
| frameworkPostArgs = $.parseJSON(frameworkPostArgsJSON); | ||
| } | ||
| var postData = $.extend({}, msgData.payload, frameworkPostArgs); | ||
| var toopherData = {'toopher_iframe_data': $.param(postData)}; | ||
| if(iframe.attr('use_ajax_postback')){ | ||
| $.post(iframe.attr('toopher_postback'), toopherData) | ||
| .done(function(data){ | ||
| data = $.parseJSON(data); | ||
| }); | ||
| } else { | ||
| postToUrl(iframe.attr('toopher_postback'), toopherData, 'POST'); | ||
| } | ||
| } | ||
| } | ||
| if (window.addEventListener) { | ||
| window.addEventListener('message', handleMessage, false); | ||
| } else { | ||
| window.attachEvent('onmessage', handleMessage); | ||
| } | ||
| })(window, jQuery); |
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to check that the user has responded affirmatively like we do after the
authenticatecall below--can you please add a similar check here? Note that pairings areenabledrather thangranted.