add sentry client
This commit is contained in:
		| @ -1,5 +1,6 @@ | ||||
| """passbook provider""" | ||||
| from allauth.socialaccount.providers.oauth2.urls import default_urlpatterns | ||||
| 
 | ||||
| from allauth_passbook.provider import PassbookProvider | ||||
| 
 | ||||
| urlpatterns = default_urlpatterns(PassbookProvider) | ||||
| @ -1,10 +1,10 @@ | ||||
| """passbook adapter""" | ||||
| import requests | ||||
| 
 | ||||
| from allauth.socialaccount import app_settings | ||||
| from allauth.socialaccount.providers.oauth2.views import (OAuth2Adapter, | ||||
|                                                           OAuth2CallbackView, | ||||
|                                                           OAuth2LoginView) | ||||
| 
 | ||||
| from allauth_passbook.provider import PassbookProvider | ||||
| 
 | ||||
| 
 | ||||
							
								
								
									
										5
									
								
								client-packages/sentry-auth-passbook/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								client-packages/sentry-auth-passbook/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,5 @@ | ||||
| *.pyc | ||||
| *.egg-info/ | ||||
| *.eggs | ||||
| /dist | ||||
| /build | ||||
							
								
								
									
										32
									
								
								client-packages/sentry-auth-passbook/.travis.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								client-packages/sentry-auth-passbook/.travis.yml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,32 @@ | ||||
| sudo: false | ||||
| language: python | ||||
| services: | ||||
|   - memcached | ||||
|   - postgresql | ||||
|   - redis-server | ||||
| python: | ||||
|   - '2.7' | ||||
| cache: | ||||
|   directories: | ||||
|     - node_modules | ||||
|     - "$HOME/.cache/pip" | ||||
| deploy: | ||||
|   provider: pypi | ||||
|   user: getsentry | ||||
|   password: | ||||
|     secure: kVmxKHkBWRLYyZme05p+WZSJmb8GjHV9uyuaSCVMRlqWCW+GXRB7P1xXR2jb9URTlNdcs56Ab/UrwzCbMFGC8LmwCeFVgIR/ltytVZG2FgXZPWaeA4dH25qK2oGWgzJ/xeiMpmuJqN9hRl25MX6jG7FZKvrrOkG7+8tpPd1yO+uYWZQbnebZMjcPBqEpn7CC0hR39GSoyVAbydpMe5hwENGQM26CepcicdrelfawItoUrXrkJzBHkIQQTO/xRSbCtRJOtzI5lwtv3GP0hcbOy5tI5dhG/93pLwZRc5+dZaCaP7oaVeOcBjN0zfINRQobt8d6h2Qgvd/YyFkGi0/xKn1zMmKIVLOG6VsYwEAUq8wNOsP4A/jdm4Y0J/1oEZStCkpaGpx85TYi4kq1hWQdyqaVJSPhh4Tk4roIaS2zOYQl+nIpbHqmJ4FJrg1il+TCdjBXobATQ1mKRBUrjD+RDzH/r4ogbd8+UwvvvevpqS2K+/wgT6UD0MzDInv9S29CUQvuFhPoqyJb5XRddHMRE9EEK/2Z8tFN91sDATnqfXHgwnvu00q/nKP5JnijBPzGmx7ydgUViIukklDrlPvo9BbRJz0Vr2vbAvMTrLMLCXqi5CwTm+v+iaOf/YaCziaG2vx0eVASYjpOLCedSgRZBubPM8z4E/HMXhChN7sVDWk= | ||||
|   on: | ||||
|     tags: true | ||||
|   distributions: sdist bdist_wheel | ||||
| env: | ||||
|   global: | ||||
|     - PIP_DOWNLOAD_CACHE=".pip_download_cache" | ||||
| before_install: | ||||
|   - pip install codecov | ||||
| install: | ||||
|   - make develop | ||||
| script: | ||||
|   - PYFLAKES_NODOCTEST=1 flake8 | ||||
|   - coverage run --source=. -m py.test tests | ||||
| after_success: | ||||
|   - codecov | ||||
							
								
								
									
										201
									
								
								client-packages/sentry-auth-passbook/LICENSE
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										201
									
								
								client-packages/sentry-auth-passbook/LICENSE
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,201 @@ | ||||
|                               Apache License | ||||
|                         Version 2.0, January 2004 | ||||
|                      http://www.apache.org/licenses/ | ||||
|  | ||||
| TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION | ||||
|  | ||||
| 1. Definitions. | ||||
|  | ||||
|    "License" shall mean the terms and conditions for use, reproduction, | ||||
|    and distribution as defined by Sections 1 through 9 of this document. | ||||
|  | ||||
|    "Licensor" shall mean the copyright owner or entity authorized by | ||||
|    the copyright owner that is granting the License. | ||||
|  | ||||
|    "Legal Entity" shall mean the union of the acting entity and all | ||||
|    other entities that control, are controlled by, or are under common | ||||
|    control with that entity. For the purposes of this definition, | ||||
|    "control" means (i) the power, direct or indirect, to cause the | ||||
|    direction or management of such entity, whether by contract or | ||||
|    otherwise, or (ii) ownership of fifty percent (50%) or more of the | ||||
|    outstanding shares, or (iii) beneficial ownership of such entity. | ||||
|  | ||||
|    "You" (or "Your") shall mean an individual or Legal Entity | ||||
|    exercising permissions granted by this License. | ||||
|  | ||||
|    "Source" form shall mean the preferred form for making modifications, | ||||
|    including but not limited to software source code, documentation | ||||
|    source, and configuration files. | ||||
|  | ||||
|    "Object" form shall mean any form resulting from mechanical | ||||
|    transformation or translation of a Source form, including but | ||||
|    not limited to compiled object code, generated documentation, | ||||
|    and conversions to other media types. | ||||
|  | ||||
|    "Work" shall mean the work of authorship, whether in Source or | ||||
|    Object form, made available under the License, as indicated by a | ||||
|    copyright notice that is included in or attached to the work | ||||
|    (an example is provided in the Appendix below). | ||||
|  | ||||
|    "Derivative Works" shall mean any work, whether in Source or Object | ||||
|    form, that is based on (or derived from) the Work and for which the | ||||
|    editorial revisions, annotations, elaborations, or other modifications | ||||
|    represent, as a whole, an original work of authorship. For the purposes | ||||
|    of this License, Derivative Works shall not include works that remain | ||||
|    separable from, or merely link (or bind by name) to the interfaces of, | ||||
|    the Work and Derivative Works thereof. | ||||
|  | ||||
|    "Contribution" shall mean any work of authorship, including | ||||
|    the original version of the Work and any modifications or additions | ||||
|    to that Work or Derivative Works thereof, that is intentionally | ||||
|    submitted to Licensor for inclusion in the Work by the copyright owner | ||||
|    or by an individual or Legal Entity authorized to submit on behalf of | ||||
|    the copyright owner. For the purposes of this definition, "submitted" | ||||
|    means any form of electronic, verbal, or written communication sent | ||||
|    to the Licensor or its representatives, including but not limited to | ||||
|    communication on electronic mailing lists, source code control systems, | ||||
|    and issue tracking systems that are managed by, or on behalf of, the | ||||
|    Licensor for the purpose of discussing and improving the Work, but | ||||
|    excluding communication that is conspicuously marked or otherwise | ||||
|    designated in writing by the copyright owner as "Not a Contribution." | ||||
|  | ||||
|    "Contributor" shall mean Licensor and any individual or Legal Entity | ||||
|    on behalf of whom a Contribution has been received by Licensor and | ||||
|    subsequently incorporated within the Work. | ||||
|  | ||||
| 2. Grant of Copyright License. Subject to the terms and conditions of | ||||
|    this License, each Contributor hereby grants to You a perpetual, | ||||
|    worldwide, non-exclusive, no-charge, royalty-free, irrevocable | ||||
|    copyright license to reproduce, prepare Derivative Works of, | ||||
|    publicly display, publicly perform, sublicense, and distribute the | ||||
|    Work and such Derivative Works in Source or Object form. | ||||
|  | ||||
| 3. Grant of Patent License. Subject to the terms and conditions of | ||||
|    this License, each Contributor hereby grants to You a perpetual, | ||||
|    worldwide, non-exclusive, no-charge, royalty-free, irrevocable | ||||
|    (except as stated in this section) patent license to make, have made, | ||||
|    use, offer to sell, sell, import, and otherwise transfer the Work, | ||||
|    where such license applies only to those patent claims licensable | ||||
|    by such Contributor that are necessarily infringed by their | ||||
|    Contribution(s) alone or by combination of their Contribution(s) | ||||
|    with the Work to which such Contribution(s) was submitted. If You | ||||
|    institute patent litigation against any entity (including a | ||||
|    cross-claim or counterclaim in a lawsuit) alleging that the Work | ||||
|    or a Contribution incorporated within the Work constitutes direct | ||||
|    or contributory patent infringement, then any patent licenses | ||||
|    granted to You under this License for that Work shall terminate | ||||
|    as of the date such litigation is filed. | ||||
|  | ||||
| 4. Redistribution. You may reproduce and distribute copies of the | ||||
|    Work or Derivative Works thereof in any medium, with or without | ||||
|    modifications, and in Source or Object form, provided that You | ||||
|    meet the following conditions: | ||||
|  | ||||
|    (a) You must give any other recipients of the Work or | ||||
|        Derivative Works a copy of this License; and | ||||
|  | ||||
|    (b) You must cause any modified files to carry prominent notices | ||||
|        stating that You changed the files; and | ||||
|  | ||||
|    (c) You must retain, in the Source form of any Derivative Works | ||||
|        that You distribute, all copyright, patent, trademark, and | ||||
|        attribution notices from the Source form of the Work, | ||||
|        excluding those notices that do not pertain to any part of | ||||
|        the Derivative Works; and | ||||
|  | ||||
|    (d) If the Work includes a "NOTICE" text file as part of its | ||||
|        distribution, then any Derivative Works that You distribute must | ||||
|        include a readable copy of the attribution notices contained | ||||
|        within such NOTICE file, excluding those notices that do not | ||||
|        pertain to any part of the Derivative Works, in at least one | ||||
|        of the following places: within a NOTICE text file distributed | ||||
|        as part of the Derivative Works; within the Source form or | ||||
|        documentation, if provided along with the Derivative Works; or, | ||||
|        within a display generated by the Derivative Works, if and | ||||
|        wherever such third-party notices normally appear. The contents | ||||
|        of the NOTICE file are for informational purposes only and | ||||
|        do not modify the License. You may add Your own attribution | ||||
|        notices within Derivative Works that You distribute, alongside | ||||
|        or as an addendum to the NOTICE text from the Work, provided | ||||
|        that such additional attribution notices cannot be construed | ||||
|        as modifying the License. | ||||
|  | ||||
|    You may add Your own copyright statement to Your modifications and | ||||
|    may provide additional or different license terms and conditions | ||||
|    for use, reproduction, or distribution of Your modifications, or | ||||
|    for any such Derivative Works as a whole, provided Your use, | ||||
|    reproduction, and distribution of the Work otherwise complies with | ||||
|    the conditions stated in this License. | ||||
|  | ||||
| 5. Submission of Contributions. Unless You explicitly state otherwise, | ||||
|    any Contribution intentionally submitted for inclusion in the Work | ||||
|    by You to the Licensor shall be under the terms and conditions of | ||||
|    this License, without any additional terms or conditions. | ||||
|    Notwithstanding the above, nothing herein shall supersede or modify | ||||
|    the terms of any separate license agreement you may have executed | ||||
|    with Licensor regarding such Contributions. | ||||
|  | ||||
| 6. Trademarks. This License does not grant permission to use the trade | ||||
|    names, trademarks, service marks, or product names of the Licensor, | ||||
|    except as required for reasonable and customary use in describing the | ||||
|    origin of the Work and reproducing the content of the NOTICE file. | ||||
|  | ||||
| 7. Disclaimer of Warranty. Unless required by applicable law or | ||||
|    agreed to in writing, Licensor provides the Work (and each | ||||
|    Contributor provides its Contributions) on an "AS IS" BASIS, | ||||
|    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or | ||||
|    implied, including, without limitation, any warranties or conditions | ||||
|    of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A | ||||
|    PARTICULAR PURPOSE. You are solely responsible for determining the | ||||
|    appropriateness of using or redistributing the Work and assume any | ||||
|    risks associated with Your exercise of permissions under this License. | ||||
|  | ||||
| 8. Limitation of Liability. In no event and under no legal theory, | ||||
|    whether in tort (including negligence), contract, or otherwise, | ||||
|    unless required by applicable law (such as deliberate and grossly | ||||
|    negligent acts) or agreed to in writing, shall any Contributor be | ||||
|    liable to You for damages, including any direct, indirect, special, | ||||
|    incidental, or consequential damages of any character arising as a | ||||
|    result of this License or out of the use or inability to use the | ||||
|    Work (including but not limited to damages for loss of goodwill, | ||||
|    work stoppage, computer failure or malfunction, or any and all | ||||
|    other commercial damages or losses), even if such Contributor | ||||
|    has been advised of the possibility of such damages. | ||||
|  | ||||
| 9. Accepting Warranty or Additional Liability. While redistributing | ||||
|    the Work or Derivative Works thereof, You may choose to offer, | ||||
|    and charge a fee for, acceptance of support, warranty, indemnity, | ||||
|    or other liability obligations and/or rights consistent with this | ||||
|    License. However, in accepting such obligations, You may act only | ||||
|    on Your own behalf and on Your sole responsibility, not on behalf | ||||
|    of any other Contributor, and only if You agree to indemnify, | ||||
|    defend, and hold each Contributor harmless for any liability | ||||
|    incurred by, or claims asserted against, such Contributor by reason | ||||
|    of your accepting any such warranty or additional liability. | ||||
|  | ||||
| END OF TERMS AND CONDITIONS | ||||
|  | ||||
| APPENDIX: How to apply the Apache License to your work. | ||||
|  | ||||
|    To apply the Apache License to your work, attach the following | ||||
|    boilerplate notice, with the fields enclosed by brackets "[]" | ||||
|    replaced with your own identifying information. (Don't include | ||||
|    the brackets!)  The text should be enclosed in the appropriate | ||||
|    comment syntax for the file format. We also recommend that a | ||||
|    file or class name and description of purpose be included on the | ||||
|    same "printed page" as the copyright notice for easier | ||||
|    identification within third-party archives. | ||||
|  | ||||
| Copyright 2016 Functional Software, Inc. | ||||
|  | ||||
| Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| you may not use this file except in compliance with the License. | ||||
| You may obtain a copy of the License at | ||||
|  | ||||
|     http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
| Unless required by applicable law or agreed to in writing, software | ||||
| distributed under the License is distributed on an "AS IS" BASIS, | ||||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
| See the License for the specific language governing permissions and | ||||
| limitations under the License. | ||||
							
								
								
									
										3
									
								
								client-packages/sentry-auth-passbook/MANIFEST.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								client-packages/sentry-auth-passbook/MANIFEST.in
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| include setup.py package.json webpack.config.js README.rst MANIFEST.in LICENSE AUTHORS | ||||
| recursive-include sentry_auth_supervisr/templates * | ||||
| global-exclude *~ | ||||
							
								
								
									
										26
									
								
								client-packages/sentry-auth-passbook/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								client-packages/sentry-auth-passbook/Makefile
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,26 @@ | ||||
| .PHONY: clean develop install-tests lint publish test | ||||
|  | ||||
| develop: | ||||
| 	pip install "pip>=7" | ||||
| 	pip install -e . | ||||
| 	make install-tests | ||||
|  | ||||
| install-tests: | ||||
| 	pip install .[tests] | ||||
|  | ||||
| lint: | ||||
| 	@echo "--> Linting python" | ||||
| 	flake8 | ||||
| 	@echo "" | ||||
|  | ||||
| test: | ||||
| 	@echo "--> Running Python tests" | ||||
| 	py.test tests || exit 1 | ||||
| 	@echo "" | ||||
|  | ||||
| publish: | ||||
| 	python setup.py sdist bdist_wheel upload | ||||
|  | ||||
| clean: | ||||
| 	rm -rf *.egg-info src/*.egg-info | ||||
| 	rm -rf dist build | ||||
							
								
								
									
										55
									
								
								client-packages/sentry-auth-passbook/README.rst
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								client-packages/sentry-auth-passbook/README.rst
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,55 @@ | ||||
| GitHub Auth for Sentry | ||||
| ====================== | ||||
|  | ||||
| An SSO provider for Sentry which enables GitHub organization-restricted authentication. | ||||
|  | ||||
| Install | ||||
| ------- | ||||
|  | ||||
| :: | ||||
|  | ||||
|     $ pip install https://github.com/getsentry/sentry-auth-github/archive/master.zip | ||||
|  | ||||
| Setup | ||||
| ----- | ||||
|  | ||||
| Create a new application under your organization in GitHub. Enter the **Authorization | ||||
| callback URL** as the prefix to your Sentry installation: | ||||
|  | ||||
| :: | ||||
|  | ||||
|     https://example.sentry.com | ||||
|  | ||||
|  | ||||
| Once done, grab your API keys and drop them in your ``sentry.conf.py``: | ||||
|  | ||||
| .. code-block:: python | ||||
|  | ||||
|     GITHUB_APP_ID = "" | ||||
|  | ||||
|     GITHUB_API_SECRET = "" | ||||
|  | ||||
|  | ||||
| Verified email addresses can optionally be required: | ||||
|  | ||||
| .. code-block:: python | ||||
|  | ||||
|     GITHUB_REQUIRE_VERIFIED_EMAIL = True | ||||
|  | ||||
|  | ||||
| Optionally you may also specify the domain (for GHE users): | ||||
|  | ||||
| .. code-block:: python | ||||
|  | ||||
|     GITHUB_BASE_DOMAIN = "git.example.com" | ||||
|  | ||||
|     GITHUB_API_DOMAIN = "api.git.example.com" | ||||
|  | ||||
|  | ||||
| If Subdomain isolation is disabled in GHE: | ||||
|  | ||||
| .. code-block:: python | ||||
|  | ||||
|     GITHUB_BASE_DOMAIN = "git.example.com" | ||||
|  | ||||
|     GITHUB_API_DOMAIN = "git.example.com/api/v3" | ||||
							
								
								
									
										14
									
								
								client-packages/sentry-auth-passbook/conftest.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								client-packages/sentry-auth-passbook/conftest.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,14 @@ | ||||
| from __future__ import absolute_import | ||||
|  | ||||
| # Run tests against sqlite for simplicity | ||||
| import os | ||||
| import os.path | ||||
| import sys | ||||
|  | ||||
| sys.path.insert(0, os.path.join(os.path.dirname(__file__))) | ||||
|  | ||||
| os.environ.setdefault('DB', 'sqlite') | ||||
|  | ||||
| pytest_plugins = [ | ||||
|     'sentry.utils.pytest' | ||||
| ] | ||||
| @ -0,0 +1,7 @@ | ||||
| from __future__ import absolute_import | ||||
|  | ||||
| from sentry.auth import register | ||||
|  | ||||
| from .provider import PassbookOAuth2Provider | ||||
|  | ||||
| register('passbook', PassbookOAuth2Provider) | ||||
| @ -0,0 +1,45 @@ | ||||
| from __future__ import absolute_import, print_function | ||||
|  | ||||
| from requests.exceptions import RequestException | ||||
|  | ||||
| from sentry import http | ||||
| from sentry.utils import json | ||||
|  | ||||
| from .constants import BASE_DOMAIN | ||||
|  | ||||
|  | ||||
| class SupervisrApiError(Exception): | ||||
|     def __init__(self, message='', status=0): | ||||
|         super(SupervisrApiError, self).__init__(message) | ||||
|         self.status = status | ||||
|  | ||||
|  | ||||
| class SupervisrClient(object): | ||||
|     def __init__(self, client_id, client_secret): | ||||
|         self.client_id = client_id | ||||
|         self.client_secret = client_secret | ||||
|         self.http = http.build_session() | ||||
|  | ||||
|     def _request(self, path, access_token): | ||||
|         params = { | ||||
|             'client_id': self.client_id, | ||||
|             'client_secret': self.client_secret, | ||||
|         } | ||||
|  | ||||
|         headers = { | ||||
|             'Authorization': 'Bearer {0}'.format(access_token), | ||||
|         } | ||||
|  | ||||
|         try: | ||||
|             req = self.http.get('https://{0}/{1}'.format(BASE_DOMAIN, path.lstrip('/')), | ||||
|                 params=params, | ||||
|                 headers=headers, | ||||
|             ) | ||||
|         except RequestException as e: | ||||
|             raise SupervisrApiError(unicode(e), status=getattr(e, 'status_code', 0)) | ||||
|         if req.status_code < 200 or req.status_code >= 300: | ||||
|             raise SupervisrApiError(req.content, status=req.status_code) | ||||
|         return json.loads(req.content) | ||||
|  | ||||
|     def get_user(self, access_token): | ||||
|         return self._request('/api/core/v1/accounts/me/?format=openid', access_token) | ||||
| @ -0,0 +1,14 @@ | ||||
| from __future__ import absolute_import, print_function | ||||
|  | ||||
| from django.conf import settings | ||||
|  | ||||
| CLIENT_ID = getattr(settings, 'PASSBOOK_APP_ID', None) | ||||
|  | ||||
| CLIENT_SECRET = getattr(settings, 'PASSBOOK_API_SECRET', None) | ||||
|  | ||||
| SCOPE = 'openid:userinfo' | ||||
|  | ||||
| BASE_DOMAIN = getattr(settings, 'PASSBOOK_BASE_DOMAIN', 'id.beryju.org') | ||||
|  | ||||
| ACCESS_TOKEN_URL = 'https://{0}/application/oauth/token/'.format(BASE_DOMAIN) | ||||
| AUTHORIZE_URL = 'https://{0}/application/oauth/authorize/'.format(BASE_DOMAIN) | ||||
| @ -0,0 +1,62 @@ | ||||
| from __future__ import absolute_import, print_function | ||||
|  | ||||
| from sentry.auth.exceptions import IdentityNotValid | ||||
| from sentry.auth.providers.oauth2 import (OAuth2Callback, OAuth2Login, | ||||
|                                           OAuth2Provider) | ||||
|  | ||||
| from .client import PassbookApiError, PassbookClient | ||||
| from .constants import (ACCESS_TOKEN_URL, AUTHORIZE_URL, CLIENT_ID, | ||||
|                         CLIENT_SECRET, SCOPE) | ||||
| from .views import FetchUser, PassbookConfigureView | ||||
|  | ||||
|  | ||||
| class PassbookOAuth2Provider(OAuth2Provider): | ||||
|     access_token_url = ACCESS_TOKEN_URL | ||||
|     authorize_url = AUTHORIZE_URL | ||||
|     name = 'Passbook' | ||||
|     client_id = CLIENT_ID | ||||
|     client_secret = CLIENT_SECRET | ||||
|  | ||||
|     def __init__(self, **config): | ||||
|         super(PassbookOAuth2Provider, self).__init__(**config) | ||||
|  | ||||
|     def get_configure_view(self): | ||||
|         return PassbookConfigureView.as_view() | ||||
|  | ||||
|     def get_auth_pipeline(self): | ||||
|         return [ | ||||
|             OAuth2Login( | ||||
|                 authorize_url=self.authorize_url, | ||||
|                 client_id=self.client_id, | ||||
|                 scope=SCOPE, | ||||
|             ), | ||||
|             OAuth2Callback( | ||||
|                 access_token_url=self.access_token_url, | ||||
|                 client_id=self.client_id, | ||||
|                 client_secret=self.client_secret, | ||||
|             ), | ||||
|             FetchUser( | ||||
|                 client_id=self.client_id, | ||||
|                 client_secret=self.client_secret, | ||||
|             ), | ||||
|         ] | ||||
|  | ||||
|     def get_refresh_token_url(self): | ||||
|         return ACCESS_TOKEN_URL | ||||
|  | ||||
|     def build_identity(self, state): | ||||
|         data = state['data'] | ||||
|         user_data = state['user'] | ||||
|         return { | ||||
|             'id': user_data['email'], | ||||
|             'email': user_data['email'], | ||||
|             'name': user_data['name'], | ||||
|             'data': self.get_oauth_data(data), | ||||
|         } | ||||
|  | ||||
|     def build_config(self, state): | ||||
|         return {} | ||||
|  | ||||
|     def refresh_identity(self, auth_identity): | ||||
|         client = PassbookClient(self.client_id, self.client_secret) | ||||
|         access_token = auth_identity.data['access_token'] | ||||
| @ -0,0 +1,75 @@ | ||||
| from __future__ import absolute_import, print_function | ||||
|  | ||||
| from django import forms | ||||
|  | ||||
| from sentry.auth.view import AuthView, ConfigureView | ||||
| from sentry.models import AuthIdentity | ||||
|  | ||||
| from .client import PassbookClient | ||||
|  | ||||
|  | ||||
| def _get_name_from_email(email): | ||||
|     """ | ||||
|     Given an email return a capitalized name. Ex. john.smith@example.com would return John Smith. | ||||
|     """ | ||||
|     name = email.rsplit('@', 1)[0] | ||||
|     name = ' '.join([n_part.capitalize() for n_part in name.split('.')]) | ||||
|     return name | ||||
|  | ||||
|  | ||||
| class FetchUser(AuthView): | ||||
|     def __init__(self, client_id, client_secret, *args, **kwargs): | ||||
|         self.client = PassbookClient(client_id, client_secret) | ||||
|         super(FetchUser, self).__init__(*args, **kwargs) | ||||
|  | ||||
|     def handle(self, request, helper): | ||||
|         access_token = helper.fetch_state('data')['access_token'] | ||||
|  | ||||
|         user = self.client.get_user(access_token) | ||||
|  | ||||
|         # A user hasn't set their name in their Passbook profile so it isn't | ||||
|         # populated in the response | ||||
|         if not user.get('name'): | ||||
|             user['name'] = _get_name_from_email(user['email']) | ||||
|  | ||||
|         helper.bind_state('user', user) | ||||
|  | ||||
|         return helper.next_step() | ||||
|  | ||||
|  | ||||
| class ConfirmEmailForm(forms.Form): | ||||
|     email = forms.EmailField(label='Email') | ||||
|  | ||||
|  | ||||
| class ConfirmEmail(AuthView): | ||||
|     def handle(self, request, helper): | ||||
|         user = helper.fetch_state('user') | ||||
|  | ||||
|         # TODO(dcramer): this isnt ideal, but our current flow doesnt really | ||||
|         # support this behavior; | ||||
|         try: | ||||
|             auth_identity = AuthIdentity.objects.select_related('user').get( | ||||
|                 auth_provider=helper.auth_provider, | ||||
|                 ident=user['id'], | ||||
|             ) | ||||
|         except AuthIdentity.DoesNotExist: | ||||
|             pass | ||||
|         else: | ||||
|             user['email'] = auth_identity.user.email | ||||
|  | ||||
|         if user.get('email'): | ||||
|             return helper.next_step() | ||||
|  | ||||
|         form = ConfirmEmailForm(request.POST or None) | ||||
|         if form.is_valid(): | ||||
|             user['email'] = form.cleaned_data['email'] | ||||
|             helper.bind_state('user', user) | ||||
|             return helper.next_step() | ||||
|  | ||||
|         return self.respond('sentry_auth_passbook/enter-email.html', { | ||||
|             'form': form, | ||||
|         }) | ||||
|  | ||||
| class PassbookConfigureView(ConfigureView): | ||||
|     def dispatch(self, request, organization, auth_provider): | ||||
|         return self.render('sentry_auth_passbook/configure.html') | ||||
							
								
								
									
										12
									
								
								client-packages/sentry-auth-passbook/setup.cfg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								client-packages/sentry-auth-passbook/setup.cfg
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,12 @@ | ||||
| [wheel] | ||||
| universal = 1 | ||||
|  | ||||
| [pytest] | ||||
| python_files = test*.py | ||||
| addopts = --tb=native -p no:doctest | ||||
| norecursedirs = bin dist docs htmlcov script hooks node_modules .* {args} | ||||
|  | ||||
| [flake8] | ||||
| ignore = F999,E501,E128,E124,E402,W503,E731,C901 | ||||
| max-line-length = 100 | ||||
| exclude = .tox,.git,*/migrations/*,node_modules/*,docs/* | ||||
							
								
								
									
										45
									
								
								client-packages/sentry-auth-passbook/setup.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								client-packages/sentry-auth-passbook/setup.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,45 @@ | ||||
| #!/usr/bin/env python | ||||
| """ | ||||
| sentry-auth-passbook | ||||
| ================== | ||||
|  | ||||
| :copyright: (c) 2016 Functional Software, Inc | ||||
| """ | ||||
| from setuptools import find_packages, setup | ||||
|  | ||||
| install_requires = [ | ||||
|     'sentry>=7.0.0', | ||||
| ] | ||||
|  | ||||
| tests_require = [ | ||||
|     'mock', | ||||
|     'flake8>=2.0,<2.1', | ||||
| ] | ||||
|  | ||||
| setup( | ||||
|     name='sentry-auth-passbook', | ||||
|     version='1.0.0', | ||||
|     author='BeryJu.org', | ||||
|     author_email='support@beryju.org', | ||||
|     url='https://passbook.beryju.org', | ||||
|     description='passbook authentication provider for Sentry', | ||||
|     long_description=__doc__, | ||||
|     license='MIT', | ||||
|     packages=find_packages(exclude=['tests']), | ||||
|     zip_safe=False, | ||||
|     install_requires=install_requires, | ||||
|     tests_require=tests_require, | ||||
|     extras_require={'tests': tests_require}, | ||||
|     include_package_data=True, | ||||
|     entry_points={ | ||||
|         'sentry.apps': [ | ||||
|             'auth_passbook = sentry_auth_passbook', | ||||
|         ], | ||||
|     }, | ||||
|     classifiers=[ | ||||
|         'Intended Audience :: Developers', | ||||
|         'Intended Audience :: System Administrators', | ||||
|         'Operating System :: OS Independent', | ||||
|         'Topic :: Software Development' | ||||
|     ], | ||||
| ) | ||||
| @ -0,0 +1,6 @@ | ||||
| from sentry.testutils import TestCase | ||||
|  | ||||
|  | ||||
| class GitHubOAuth2ProviderTest(TestCase): | ||||
|     def test_simple(self): | ||||
|         pass | ||||
							
								
								
									
										17
									
								
								client-packages/sentry-auth-passbook/tests/test_views.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								client-packages/sentry-auth-passbook/tests/test_views.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,17 @@ | ||||
| from __future__ import absolute_import, print_function | ||||
|  | ||||
| import pytest | ||||
| from sentry_auth_sentry.views import _get_name_from_email | ||||
|  | ||||
| expected_data = [ | ||||
|     ('john.smith@example.com', 'John Smith'), | ||||
|     ('john@example.com', 'John'), | ||||
|     ('XYZ-234=3523@example.com', 'Xyz-234=3523'), | ||||
|     ('XYZ.1111@example.com', 'Xyz 1111'), | ||||
|     ('JOHN@example.com', 'John'), | ||||
| ] | ||||
|  | ||||
|  | ||||
| @pytest.mark.parametrize("email,expected_name", expected_data) | ||||
| def test_get_name_from_email(email, expected_name): | ||||
|     assert _get_name_from_email(email) == expected_name | ||||
| @ -1,5 +1,5 @@ | ||||
| -r requirements.txt | ||||
| -r allauth/requirements.txt | ||||
| -r client-packages/allauth/requirements.txt | ||||
| coverage | ||||
| isort | ||||
| astroid==2.0.4 | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	 Jens Langhammer
					Jens Langhammer