Compare commits
	
		
			19 Commits
		
	
	
		
			version/0.
			...
			version/0.
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 9e46c8bfec | |||
| 1eaa9b9733 | |||
| ee05834b69 | |||
| fccc8f4959 | |||
| c721620f96 | |||
| c9f73d718e | |||
| bfa58be721 | |||
| 4bb602149e | |||
| 81ab9092fc | |||
| 29d5962c4c | |||
| 5c75339946 | |||
| 4774d9a46c | |||
| dbe16ba4fd | |||
| 6972cf00a0 | |||
| 0445be9712 | |||
| 89dbdd9585 | |||
| da88ce7150 | |||
| 5f50fcfcf5 | |||
| 96be087221 | 
| @ -1,5 +1,5 @@ | |||||||
| [bumpversion] | [bumpversion] | ||||||
| current_version = 0.1.20-beta | current_version = 0.1.23-beta | ||||||
| tag = True | tag = True | ||||||
| commit = True | commit = True | ||||||
| parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)\-(?P<release>.*) | parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)\-(?P<release>.*) | ||||||
|  | |||||||
| @ -54,7 +54,7 @@ package-docker: | |||||||
|     before_script: |     before_script: | ||||||
|         - echo "{\"auths\":{\"docker.$NEXUS_URL\":{\"auth\":\"$NEXUS_AUTH\"}}}" > /kaniko/.docker/config.json |         - echo "{\"auths\":{\"docker.$NEXUS_URL\":{\"auth\":\"$NEXUS_AUTH\"}}}" > /kaniko/.docker/config.json | ||||||
|     script: |     script: | ||||||
|         - /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile --destination docker.pkg.beryju.org/passbook:latest --destination docker.pkg.beryju.org/passbook:0.1.20-beta |         - /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile --destination docker.pkg.beryju.org/passbook:latest --destination docker.pkg.beryju.org/passbook:0.1.23-beta | ||||||
|     stage: build |     stage: build | ||||||
|     only: |     only: | ||||||
|         - tags |         - tags | ||||||
|  | |||||||
| @ -3,7 +3,7 @@ from setuptools import setup | |||||||
|  |  | ||||||
| setup( | setup( | ||||||
|     name='django-allauth-passbook', |     name='django-allauth-passbook', | ||||||
|     version='0.1.20-beta', |     version='0.1.23-beta', | ||||||
|     description='passbook support for django-allauth', |     description='passbook support for django-allauth', | ||||||
|     # long_description='\n'.join(read_simple('docs/index.md')[2:]), |     # long_description='\n'.join(read_simple('docs/index.md')[2:]), | ||||||
|     long_description_content_type='text/markdown', |     long_description_content_type='text/markdown', | ||||||
|  | |||||||
| @ -18,7 +18,7 @@ tests_require = [ | |||||||
|  |  | ||||||
| setup( | setup( | ||||||
|     name='sentry-auth-passbook', |     name='sentry-auth-passbook', | ||||||
|     version='0.1.20-beta', |     version='0.1.23-beta', | ||||||
|     author='BeryJu.org', |     author='BeryJu.org', | ||||||
|     author_email='support@beryju.org', |     author_email='support@beryju.org', | ||||||
|     url='https://passbook.beryju.org', |     url='https://passbook.beryju.org', | ||||||
|  | |||||||
							
								
								
									
										27
									
								
								debian/changelog
									
									
									
									
										vendored
									
									
								
							
							
						
						| @ -1,3 +1,30 @@ | |||||||
|  | passbook (0.1.23) stable; urgency=medium | ||||||
|  |  | ||||||
|  |   * add support for OpenID-Connect Discovery | ||||||
|  |  | ||||||
|  |  -- Jens Langhammer <jens.langhammer@beryju.org>  Thu, 18 Mar 2019 20:19:27 +0000 | ||||||
|  |  | ||||||
|  | passbook (0.1.22) stable; urgency=medium | ||||||
|  |  | ||||||
|  |   * bump version: 0.1.20-beta -> 0.1.21-beta | ||||||
|  |   * fix missing debug template | ||||||
|  |   * move icons to single folder, cleanup | ||||||
|  |   * fix layout when on mobile viewport and scrolling | ||||||
|  |   * fix delete form not working | ||||||
|  |   * point to correct icons | ||||||
|  |   * add Azure AD Source | ||||||
|  |   * Fix OAuth Client's disconnect view having invalid URL names | ||||||
|  |  | ||||||
|  |  -- Jens Langhammer <jens.langhammer@beryju.org>  Thu, 14 Mar 2019 20:19:27 +0000 | ||||||
|  |  | ||||||
|  | passbook (0.1.21) stable; urgency=medium | ||||||
|  |  | ||||||
|  |   * bump version: 0.1.19-beta -> 0.1.20-beta | ||||||
|  |   * add request debug view | ||||||
|  |   * detect HTTPS from reverse proxy | ||||||
|  |  | ||||||
|  |  -- Jens Langhammer <jens.langhammer@beryju.org>  Thu, 14 Mar 2019 17:01:49 +0000 | ||||||
|  |  | ||||||
| passbook (0.1.20) stable; urgency=medium | passbook (0.1.20) stable; urgency=medium | ||||||
|  |  | ||||||
|   * bump version: 0.1.18-beta -> 0.1.19-beta |   * bump version: 0.1.18-beta -> 0.1.19-beta | ||||||
|  | |||||||
| @ -1,6 +1,6 @@ | |||||||
| apiVersion: v1 | apiVersion: v1 | ||||||
| appVersion: "0.1.20-beta" | appVersion: "0.1.23-beta" | ||||||
| description: A Helm chart for passbook. | description: A Helm chart for passbook. | ||||||
| name: passbook | name: passbook | ||||||
| version: "0.1.20-beta" | version: "0.1.23-beta" | ||||||
| icon: https://passbook.beryju.org/images/logo.png | icon: https://passbook.beryju.org/images/logo.png | ||||||
|  | |||||||
| @ -123,6 +123,7 @@ data: | |||||||
|         - passbook.oauth_client.source_types.reddit |         - passbook.oauth_client.source_types.reddit | ||||||
|         - passbook.oauth_client.source_types.supervisr |         - passbook.oauth_client.source_types.supervisr | ||||||
|         - passbook.oauth_client.source_types.twitter |         - passbook.oauth_client.source_types.twitter | ||||||
|  |         - passbook.oauth_client.source_types.azure_ad | ||||||
|     saml_idp: |     saml_idp: | ||||||
|       signing: true |       signing: true | ||||||
|       autosubmit: false |       autosubmit: false | ||||||
|  | |||||||
| @ -5,7 +5,7 @@ | |||||||
| replicaCount: 1 | replicaCount: 1 | ||||||
|  |  | ||||||
| image: | image: | ||||||
|   tag: 0.1.20-beta |   tag: 0.1.23-beta | ||||||
|  |  | ||||||
| nameOverride: "" | nameOverride: "" | ||||||
|  |  | ||||||
|  | |||||||
| @ -1,2 +1,2 @@ | |||||||
| """passbook""" | """passbook""" | ||||||
| __version__ = '0.1.20-beta' | __version__ = '0.1.23-beta' | ||||||
|  | |||||||
| @ -1,2 +1,2 @@ | |||||||
| """passbook admin""" | """passbook admin""" | ||||||
| __version__ = '0.1.20-beta' | __version__ = '0.1.23-beta' | ||||||
|  | |||||||
							
								
								
									
										31
									
								
								passbook/admin/templates/administration/debug/request.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,31 @@ | |||||||
|  | {% extends "administration/base.html" %} | ||||||
|  |  | ||||||
|  | {% load i18n %} | ||||||
|  | {% load utils %} | ||||||
|  |  | ||||||
|  | {% block title %} | ||||||
|  | {% title %} | ||||||
|  | {% endblock %} | ||||||
|  |  | ||||||
|  | {% block content %} | ||||||
|  | <div class="container"> | ||||||
|  |     <h1><span class="pficon-applications"></span> {% trans "Request" %}</h1> | ||||||
|  |     <hr> | ||||||
|  |     <table class="table table-striped table-bordered"> | ||||||
|  |         <thead> | ||||||
|  |             <tr> | ||||||
|  |                 <th>{% trans 'Key' %}</th> | ||||||
|  |                 <th>{% trans 'Value' %}</th> | ||||||
|  |             </tr> | ||||||
|  |         </thead> | ||||||
|  |         <tbody> | ||||||
|  |             {% for key, value in request_dict.items %} | ||||||
|  |             <tr> | ||||||
|  |                 <td>{{ key }}</td> | ||||||
|  |                 <td>{{ value }}</td> | ||||||
|  |             </tr> | ||||||
|  |             {% endfor %} | ||||||
|  |         </tbody> | ||||||
|  |     </table> | ||||||
|  | </div> | ||||||
|  | {% endblock %} | ||||||
| @ -1,7 +1,7 @@ | |||||||
| """passbook URL Configuration""" | """passbook URL Configuration""" | ||||||
| from django.urls import include, path | from django.urls import include, path | ||||||
|  |  | ||||||
| from passbook.admin.views import (applications, audit, factors, groups, | from passbook.admin.views import (applications, audit, debug, factors, groups, | ||||||
|                                   invitations, overview, policy, |                                   invitations, overview, policy, | ||||||
|                                   property_mapping, providers, sources, users) |                                   property_mapping, providers, sources, users) | ||||||
|  |  | ||||||
| @ -77,5 +77,7 @@ urlpatterns = [ | |||||||
|     # Groups |     # Groups | ||||||
|     path('groups/', groups.GroupListView.as_view(), name='groups'), |     path('groups/', groups.GroupListView.as_view(), name='groups'), | ||||||
|     # API |     # API | ||||||
|     path('api/', include('passbook.admin.api.urls')) |     path('api/', include('passbook.admin.api.urls')), | ||||||
|  |     # Debug | ||||||
|  |     path('debug/request/', debug.DebugRequestView.as_view(), name='debug-request'), | ||||||
| ] | ] | ||||||
|  | |||||||
							
								
								
									
										17
									
								
								passbook/admin/views/debug.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,17 @@ | |||||||
|  | """passbook administration debug views""" | ||||||
|  |  | ||||||
|  | from django.views.generic import TemplateView | ||||||
|  |  | ||||||
|  | from passbook.admin.mixins import AdminRequiredMixin | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class DebugRequestView(AdminRequiredMixin, TemplateView): | ||||||
|  |     """Show debug info about request""" | ||||||
|  |  | ||||||
|  |     template_name = 'administration/debug/request.html' | ||||||
|  |  | ||||||
|  |     def get_context_data(self, **kwargs): | ||||||
|  |         kwargs['request_dict'] = {} | ||||||
|  |         for key in dir(self.request): | ||||||
|  |             kwargs['request_dict'][key] = getattr(self.request, key) | ||||||
|  |         return super().get_context_data(**kwargs) | ||||||
| @ -1,2 +1,2 @@ | |||||||
| """passbook api""" | """passbook api""" | ||||||
| __version__ = '0.1.20-beta' | __version__ = '0.1.23-beta' | ||||||
|  | |||||||
| @ -1,2 +1,2 @@ | |||||||
| """passbook audit Header""" | """passbook audit Header""" | ||||||
| __version__ = '0.1.20-beta' | __version__ = '0.1.23-beta' | ||||||
|  | |||||||
| @ -1,2 +1,2 @@ | |||||||
| """passbook captcha_factor Header""" | """passbook captcha_factor Header""" | ||||||
| __version__ = '0.1.20-beta' | __version__ = '0.1.23-beta' | ||||||
|  | |||||||
| @ -1,2 +1,2 @@ | |||||||
| """passbook core""" | """passbook core""" | ||||||
| __version__ = '0.1.20-beta' | __version__ = '0.1.23-beta' | ||||||
|  | |||||||
| @ -35,6 +35,7 @@ SECRET_KEY = CONFIG.get('secret_key') | |||||||
| DEBUG = CONFIG.get('debug') | DEBUG = CONFIG.get('debug') | ||||||
| INTERNAL_IPS = ['127.0.0.1'] | INTERNAL_IPS = ['127.0.0.1'] | ||||||
| ALLOWED_HOSTS = CONFIG.get('domains', []) | ALLOWED_HOSTS = CONFIG.get('domains', []) | ||||||
|  | SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') | ||||||
|  |  | ||||||
| LOGIN_URL = 'passbook_core:auth-login' | LOGIN_URL = 'passbook_core:auth-login' | ||||||
| # CSRF_FAILURE_VIEW = 'passbook.core.views.errors.CSRFErrorView.as_view' | # CSRF_FAILURE_VIEW = 'passbook.core.views.errors.CSRFErrorView.as_view' | ||||||
|  | |||||||
| @ -1,19 +0,0 @@ | |||||||
| <?xml version="1.0" encoding="utf-8"?> |  | ||||||
| <!-- Generator: Adobe Illustrator 22.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  --> |  | ||||||
| <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" |  | ||||||
| 	 width="20px" height="20px" viewBox="0 0 20 20" style="enable-background:new 0 0 20 20;" xml:space="preserve"> |  | ||||||
| <style type="text/css"> |  | ||||||
| 	.st0{fill:#FBBB00;} |  | ||||||
| 	.st1{fill:#518EF8;} |  | ||||||
| 	.st2{fill:#28B446;} |  | ||||||
| 	.st3{fill:#F14336;} |  | ||||||
| </style> |  | ||||||
| <path class="st0" d="M4.4,12.1l-0.7,2.6l-2.5,0.1C0.4,13.3,0,11.7,0,10c0-1.7,0.4-3.2,1.1-4.6h0l2.3,0.4l1,2.3 |  | ||||||
| 	C4.2,8.7,4.1,9.3,4.1,10C4.1,10.7,4.2,11.4,4.4,12.1z"/> |  | ||||||
| <path class="st1" d="M19.8,8.1C19.9,8.7,20,9.4,20,10c0,0.7-0.1,1.4-0.2,2.1c-0.5,2.3-1.8,4.3-3.5,5.7l0,0l-2.9-0.1L13,15.1 |  | ||||||
| 	c1.2-0.7,2.1-1.8,2.6-3h-5.3v-4h5.4H19.8L19.8,8.1z"/> |  | ||||||
| <path class="st2" d="M16.3,17.8L16.3,17.8C14.5,19.2,12.4,20,10,20c-3.8,0-7.1-2.1-8.8-5.3l3.2-2.7c0.8,2.3,3,3.9,5.6,3.9 |  | ||||||
| 	c1.1,0,2.1-0.3,3-0.8L16.3,17.8z"/> |  | ||||||
| <path class="st3" d="M16.4,2.3L13.1,5c-0.9-0.6-2-0.9-3.1-0.9c-2.6,0-4.8,1.7-5.6,4L1.1,5.4h0C2.8,2.2,6.1,0,10,0 |  | ||||||
| 	C12.4,0,14.7,0.9,16.4,2.3z"/> |  | ||||||
| </svg> |  | ||||||
| Before Width: | Height: | Size: 1.1 KiB | 
| Before Width: | Height: | Size: 15 KiB | 
| Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.7 KiB | 
| Before Width: | Height: | Size: 6.4 KiB After Width: | Height: | Size: 6.4 KiB | 
| Before Width: | Height: | Size: 9.4 KiB After Width: | Height: | Size: 9.4 KiB | 
| Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 4.4 KiB | 
| Before Width: | Height: | Size: 7.8 KiB After Width: | Height: | Size: 7.8 KiB | 
| Before Width: | Height: | Size: 8.0 KiB After Width: | Height: | Size: 8.0 KiB | 
							
								
								
									
										1
									
								
								passbook/core/static/img/logos/azure ad.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1 @@ | |||||||
|  | <svg xmlns="http://www.w3.org/2000/svg" width="21" height="21" viewBox="0 0 21 21"><title>MS-SymbolLockup</title><rect x="1" y="1" width="9" height="9" fill="#f25022"/><rect x="1" y="11" width="9" height="9" fill="#00a4ef"/><rect x="11" y="1" width="9" height="9" fill="#7fba00"/><rect x="11" y="11" width="9" height="9" fill="#ffb900"/></svg> | ||||||
| After Width: | Height: | Size: 343 B | 
| Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB | 
| Before Width: | Height: | Size: 750 B After Width: | Height: | Size: 750 B | 
| Before Width: | Height: | Size: 814 B After Width: | Height: | Size: 814 B | 
| Before Width: | Height: | Size: 788 B After Width: | Height: | Size: 788 B | 
| Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB | 
| Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB | 
| Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB | 
| Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB | 
| Before Width: | Height: | Size: 783 B After Width: | Height: | Size: 783 B | 
| Before Width: | Height: | Size: 688 B After Width: | Height: | Size: 688 B | 
| Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB | 
| Before Width: | Height: | Size: 6.0 KiB After Width: | Height: | Size: 6.0 KiB | 
| Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB | 
| Before Width: | Height: | Size: 889 B After Width: | Height: | Size: 889 B | 
| Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB | 
| Before Width: | Height: | Size: 8.8 KiB After Width: | Height: | Size: 8.8 KiB | 
| Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 23 KiB | 
| Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 4.0 KiB | 
| Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB | 
| Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB | 
| Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB | 
| @ -3,7 +3,7 @@ | |||||||
| {% load utils %} | {% load utils %} | ||||||
|  |  | ||||||
| <!DOCTYPE html> | <!DOCTYPE html> | ||||||
| <html lang="en"> | <html lang="en" class="layout-pf layout-pf-fixed transitions"> | ||||||
|  |  | ||||||
| <head> | <head> | ||||||
|   <meta charset="UTF-8"> |   <meta charset="UTF-8"> | ||||||
|  | |||||||
| @ -16,6 +16,7 @@ | |||||||
|                 Are you sure you want to delete {{ object_type }} "{{ object }}"? |                 Are you sure you want to delete {{ object_type }} "{{ object }}"? | ||||||
|                 {% endblocktrans %} |                 {% endblocktrans %} | ||||||
|             </p> |             </p> | ||||||
|  |             <input type="hidden" name="confirmdelete" value="yes"> | ||||||
|             <a href="{% back %}" class="btn btn-default">{% trans 'Back' %}</a> |             <a href="{% back %}" class="btn btn-default">{% trans 'Back' %}</a> | ||||||
|             <input type="submit" class="btn btn-danger" value="{% trans 'Delete' %}" /> |             <input type="submit" class="btn btn-danger" value="{% trans 'Delete' %}" /> | ||||||
|         </form> |         </form> | ||||||
|  | |||||||
| @ -51,7 +51,7 @@ | |||||||
|                 {% for url, icon, name in sources %} |                 {% for url, icon, name in sources %} | ||||||
|                 <li class="login-pf-social-link"> |                 <li class="login-pf-social-link"> | ||||||
|                     <a href="{{ url }}"> |                     <a href="{{ url }}"> | ||||||
|                         <img src="{% static 'img/' %}{{ icon }}.svg" alt="{{ name }}"> {{ name }} |                         <img src="{% static 'img/logos/' %}{{ icon }}.svg" alt="{{ name }}"> {{ name }} | ||||||
|                     </a> |                     </a> | ||||||
|                 </li> |                 </li> | ||||||
|                 {% endfor %} |                 {% endfor %} | ||||||
|  | |||||||
| @ -172,19 +172,27 @@ | |||||||
|                             </span> |                             </span> | ||||||
|                         </a> |                         </a> | ||||||
|                     </li> |                     </li> | ||||||
|  |                     <li class="list-group-item {% is_active 'passbook_admin:debug-request' %}"> | ||||||
|  |                         <a href="{% url 'passbook_admin:debug-request' %}"> | ||||||
|  |                             <span class="list-group-item-value"> | ||||||
|  |                                 {% trans 'Debug' %} | ||||||
|  |                             </span> | ||||||
|  |                         </a> | ||||||
|  |                     </li> | ||||||
|                 </ul> |                 </ul> | ||||||
|             </div> |             </div> | ||||||
|         </li> |         </li> | ||||||
|         {% endif %} |         {% endif %} | ||||||
|     </ul> |     </ul> | ||||||
| </div> | </div> | ||||||
| <div class="container-fluid container-cards-pf"> | <div class="container-fluid container-cards-pf container-pf-nav-pf-vertical hide-nav-pf"> | ||||||
|     {% block content %} |     {% block content %} | ||||||
|     {% endblock %} |     {% endblock %} | ||||||
| </div> | </div> | ||||||
| {% endblock %} | {% endblock %} | ||||||
|  |  | ||||||
| {% block scripts %} | {% block scripts %} | ||||||
|  | {{ block.super }} | ||||||
| <script> | <script> | ||||||
|     $(document).ready(function () { |     $(document).ready(function () { | ||||||
|         // initialize tooltips |         // initialize tooltips | ||||||
|  | |||||||
| @ -30,7 +30,7 @@ | |||||||
|                 {% for name, icon, link in us %} |                 {% for name, icon, link in us %} | ||||||
|                 <li class="{% if link == request.get_full_path %} active {% endif %}"> |                 <li class="{% if link == request.get_full_path %} active {% endif %}"> | ||||||
|                     <a href="{{ link }}"> |                     <a href="{{ link }}"> | ||||||
|                         <img src="{% static icon %}" alt=""> {{ name }} |                         <i class="{{ icon }}"></i> {{ name }} | ||||||
|                     </a> |                     </a> | ||||||
|                 </li> |                 </li> | ||||||
|                 {% endfor %} |                 {% endfor %} | ||||||
|  | |||||||
| @ -1,2 +1,2 @@ | |||||||
| """passbook hibp_policy""" | """passbook hibp_policy""" | ||||||
| __version__ = '0.1.20-beta' | __version__ = '0.1.23-beta' | ||||||
|  | |||||||
| @ -1,2 +1,2 @@ | |||||||
| """Passbook ldap app Header""" | """Passbook ldap app Header""" | ||||||
| __version__ = '0.1.20-beta' | __version__ = '0.1.23-beta' | ||||||
|  | |||||||
| @ -1,2 +1,2 @@ | |||||||
| """passbook lib""" | """passbook lib""" | ||||||
| __version__ = '0.1.20-beta' | __version__ = '0.1.23-beta' | ||||||
|  | |||||||
| @ -85,6 +85,7 @@ oauth_client: | |||||||
|     - passbook.oauth_client.source_types.reddit |     - passbook.oauth_client.source_types.reddit | ||||||
|     - passbook.oauth_client.source_types.supervisr |     - passbook.oauth_client.source_types.supervisr | ||||||
|     - passbook.oauth_client.source_types.twitter |     - passbook.oauth_client.source_types.twitter | ||||||
|  |     - passbook.oauth_client.source_types.azure_ad | ||||||
| saml_idp: | saml_idp: | ||||||
|   # List of python packages with provider types to load. |   # List of python packages with provider types to load. | ||||||
|   types: |   types: | ||||||
|  | |||||||
| @ -1,2 +1,2 @@ | |||||||
| """passbook oauth_client Header""" | """passbook oauth_client Header""" | ||||||
| __version__ = '0.1.20-beta' | __version__ = '0.1.23-beta' | ||||||
|  | |||||||
| @ -108,3 +108,17 @@ class GoogleOAuthSourceForm(OAuthSourceForm): | |||||||
|             'access_token_url': 'https://accounts.google.com/o/oauth2/token', |             'access_token_url': 'https://accounts.google.com/o/oauth2/token', | ||||||
|             'profile_url': ' https://www.googleapis.com/oauth2/v1/userinfo', |             'profile_url': ' https://www.googleapis.com/oauth2/v1/userinfo', | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class AzureADOAuthSourceForm(OAuthSourceForm): | ||||||
|  |     """OAuth Source form with pre-determined URL for AzureAD""" | ||||||
|  |  | ||||||
|  |     class Meta(OAuthSourceForm.Meta): | ||||||
|  |  | ||||||
|  |         overrides = { | ||||||
|  |             'provider_type': 'azure_ad', | ||||||
|  |             'request_token_url': '', | ||||||
|  |             'authorization_url': 'https://login.microsoftonline.com/common/oauth2/authorize', | ||||||
|  |             'access_token_url': 'https://login.microsoftonline.com/common/oauth2/token', | ||||||
|  |             'profile_url': ' https://graph.windows.net/myorganization/me?api-version=1.6', | ||||||
|  |         } | ||||||
|  | |||||||
| @ -29,9 +29,9 @@ class OAuthSource(Source): | |||||||
|     def get_login_button(self): |     def get_login_button(self): | ||||||
|         url = reverse_lazy('passbook_oauth_client:oauth-client-login', |         url = reverse_lazy('passbook_oauth_client:oauth-client-login', | ||||||
|                            kwargs={'source_slug': self.slug}) |                            kwargs={'source_slug': self.slug}) | ||||||
|         if self.provider_type == 'github': |         # if self.provider_type == 'github': | ||||||
|             return url, 'github-logo', _('GitHub') |         #     return url, 'github-logo', _('GitHub') | ||||||
|         return url, 'generic', _('Generic') |         return url, self.provider_type, self.name | ||||||
|  |  | ||||||
|     @property |     @property | ||||||
|     def additional_info(self): |     def additional_info(self): | ||||||
| @ -42,9 +42,12 @@ class OAuthSource(Source): | |||||||
|         """Entrypoint to integrate with User settings. Can either return False if no |         """Entrypoint to integrate with User settings. Can either return False if no | ||||||
|         user settings are available, or a tuple or string, string, string where the first string |         user settings are available, or a tuple or string, string, string where the first string | ||||||
|         is the name the item has, the second string is the icon and the third is the view-name.""" |         is the name the item has, the second string is the icon and the third is the view-name.""" | ||||||
|         icon = 'img/%s.svg' % self.get_login_button[1] |         icon_type = self.provider_type | ||||||
|  |         if icon_type == 'azure ad': | ||||||
|  |             icon_type = 'windows' | ||||||
|  |         icon_class = 'fa fa-%s' % icon_type | ||||||
|         view_name = 'passbook_oauth_client:oauth-client-user' |         view_name = 'passbook_oauth_client:oauth-client-user' | ||||||
|         return self.name, icon, reverse((view_name), kwargs={ |         return self.name, icon_class, reverse((view_name), kwargs={ | ||||||
|             'source_slug': self.slug |             'source_slug': self.slug | ||||||
|         }) |         }) | ||||||
|  |  | ||||||
| @ -113,6 +116,19 @@ class GoogleOAuthSource(OAuthSource): | |||||||
|         verbose_name = _('Google OAuth Source') |         verbose_name = _('Google OAuth Source') | ||||||
|         verbose_name_plural = _('Google OAuth Sources') |         verbose_name_plural = _('Google OAuth Sources') | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class AzureADOAuthSource(OAuthSource): | ||||||
|  |     """Abstract subclass of OAuthSource to specify AzureAD Form""" | ||||||
|  |  | ||||||
|  |     form = 'passbook.oauth_client.forms.AzureADOAuthSourceForm' | ||||||
|  |  | ||||||
|  |     class Meta: | ||||||
|  |  | ||||||
|  |         abstract = True | ||||||
|  |         verbose_name = _('Azure AD OAuth Source') | ||||||
|  |         verbose_name_plural = _('Azure AD OAuth Sources') | ||||||
|  |  | ||||||
|  |  | ||||||
| class UserOAuthSourceConnection(UserSourceConnection): | class UserOAuthSourceConnection(UserSourceConnection): | ||||||
|     """Authorized remote OAuth provider.""" |     """Authorized remote OAuth provider.""" | ||||||
|  |  | ||||||
|  | |||||||
							
								
								
									
										52
									
								
								passbook/oauth_client/source_types/azure_ad.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,52 @@ | |||||||
|  | """AzureAD OAuth2 Views""" | ||||||
|  | import json | ||||||
|  | import uuid | ||||||
|  | from logging import getLogger | ||||||
|  |  | ||||||
|  | from requests.exceptions import RequestException | ||||||
|  |  | ||||||
|  | from passbook.oauth_client.clients import OAuth2Client | ||||||
|  | from passbook.oauth_client.source_types.manager import MANAGER, RequestKind | ||||||
|  | from passbook.oauth_client.utils import user_get_or_create | ||||||
|  | from passbook.oauth_client.views.core import OAuthCallback | ||||||
|  |  | ||||||
|  | LOGGER = getLogger(__name__) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class AzureADOAuth2Client(OAuth2Client): | ||||||
|  |     """AzureAD OAuth2 Client""" | ||||||
|  |  | ||||||
|  |     def get_profile_info(self, raw_token): | ||||||
|  |         "Fetch user profile information." | ||||||
|  |         try: | ||||||
|  |             token = json.loads(raw_token)['access_token'] | ||||||
|  |             headers = { | ||||||
|  |                 'Authorization': 'Bearer %s' % token | ||||||
|  |             } | ||||||
|  |             response = self.request('get', self.source.profile_url, | ||||||
|  |                                     headers=headers) | ||||||
|  |             response.raise_for_status() | ||||||
|  |         except RequestException as exc: | ||||||
|  |             LOGGER.warning('Unable to fetch user profile: %s', exc) | ||||||
|  |             return None | ||||||
|  |         else: | ||||||
|  |             return response.json() or response.text | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @MANAGER.source(kind=RequestKind.callback, name='Azure AD') | ||||||
|  | class AzureADOAuthCallback(OAuthCallback): | ||||||
|  |     """AzureAD OAuth2 Callback""" | ||||||
|  |  | ||||||
|  |     client_class = AzureADOAuth2Client | ||||||
|  |  | ||||||
|  |     def get_user_id(self, source, info): | ||||||
|  |         return uuid.UUID(info.get('objectId')).int | ||||||
|  |  | ||||||
|  |     def get_or_create_user(self, source, access, info): | ||||||
|  |         user_data = { | ||||||
|  |             'username': info.get('displayName'), | ||||||
|  |             'email': info.get('mail', None) or info.get('otherMails')[0], | ||||||
|  |             'name': info.get('displayName'), | ||||||
|  |             'password': None, | ||||||
|  |         } | ||||||
|  |         return user_get_or_create(**user_data) | ||||||
| @ -194,7 +194,9 @@ class OAuthCallback(OAuthClientMixin, View): | |||||||
|             messages.success(self.request, _("Successfully linked %(source)s!" % { |             messages.success(self.request, _("Successfully linked %(source)s!" % { | ||||||
|                 'source': self.source.name |                 'source': self.source.name | ||||||
|             })) |             })) | ||||||
|             return redirect(reverse('user_settings')) |             return redirect(reverse('passbook_oauth_client:oauth-client-user', kwargs={ | ||||||
|  |                 'source_slug': self.source.slug | ||||||
|  |             })) | ||||||
|         messages.success(self.request, _("Successfully authenticated with %(source)s!" % { |         messages.success(self.request, _("Successfully authenticated with %(source)s!" % { | ||||||
|             'source': self.source.name |             'source': self.source.name | ||||||
|         })) |         })) | ||||||
| @ -207,26 +209,28 @@ class DisconnectView(LoginRequiredMixin, View): | |||||||
|     source = None |     source = None | ||||||
|     aas = None |     aas = None | ||||||
|  |  | ||||||
|     def dispatch(self, request, source): |     def dispatch(self, request, source_slug): | ||||||
|         self.source = get_object_or_404(OAuthSource, name=source) |         self.source = get_object_or_404(OAuthSource, slug=source_slug) | ||||||
|         self.aas = get_object_or_404(UserOAuthSourceConnection, |         self.aas = get_object_or_404(UserOAuthSourceConnection, | ||||||
|                                      source=self.source, user=request.user) |                                      source=self.source, user=request.user) | ||||||
|         return super().dispatch(request, source) |         return super().dispatch(request, source_slug) | ||||||
|  |  | ||||||
|     def post(self, request, source): |     def post(self, request, source_slug): | ||||||
|         """Delete connection object""" |         """Delete connection object""" | ||||||
|         if 'confirmdelete' in request.POST: |         if 'confirmdelete' in request.POST: | ||||||
|             # User confirmed deletion |             # User confirmed deletion | ||||||
|             self.aas.delete() |             self.aas.delete() | ||||||
|             messages.success(request, _('Connection successfully deleted')) |             messages.success(request, _('Connection successfully deleted')) | ||||||
|             return redirect(reverse('user_settings')) |             return redirect(reverse('passbook_oauth_client:oauth-client-user', kwargs={ | ||||||
|         return self.get(request, source) |                 'source_slug': self.source.slug | ||||||
|  |             })) | ||||||
|  |         return self.get(request, source_slug) | ||||||
|  |  | ||||||
|     def get(self, request, source): |     def get(self, request, source): | ||||||
|         """Show delete form""" |         """Show delete form""" | ||||||
|         return render(request, 'generic/delete.html', { |         return render(request, 'generic/delete.html', { | ||||||
|             'object': 'OAuth Connection with %s' % self.source.name, |             'object': self.source, | ||||||
|             'delete_url': reverse('oauth-client-disconnect', kwargs={ |             'delete_url': reverse('passbook_oauth_client:oauth-client-disconnect', kwargs={ | ||||||
|                 'source': self.source.name, |                 'source_slug': self.source.slug, | ||||||
|             }) |             }) | ||||||
|         }) |         }) | ||||||
|  | |||||||
| @ -1,2 +1,2 @@ | |||||||
| """passbook oauth_provider Header""" | """passbook oauth_provider Header""" | ||||||
| __version__ = '0.1.20-beta' | __version__ = '0.1.23-beta' | ||||||
|  | |||||||
| @ -3,7 +3,7 @@ | |||||||
| from django.urls import path | from django.urls import path | ||||||
| from oauth2_provider import views | from oauth2_provider import views | ||||||
|  |  | ||||||
| from passbook.oauth_provider.views import oauth2 | from passbook.oauth_provider.views import oauth2, openid | ||||||
|  |  | ||||||
| urlpatterns = [ | urlpatterns = [ | ||||||
|     # Custom OAuth 2 Authorize View |     # Custom OAuth 2 Authorize View | ||||||
| @ -14,8 +14,12 @@ urlpatterns = [ | |||||||
|     path('authorize/permission_denied/', oauth2.OAuthPermissionDenied.as_view(), |     path('authorize/permission_denied/', oauth2.OAuthPermissionDenied.as_view(), | ||||||
|          name='oauth2-permission-denied'), |          name='oauth2-permission-denied'), | ||||||
|     # OAuth API |     # OAuth API | ||||||
|     path("authorize/", views.AuthorizationView.as_view(), name="authorize"), |  | ||||||
|     path("token/", views.TokenView.as_view(), name="token"), |     path("token/", views.TokenView.as_view(), name="token"), | ||||||
|     path("revoke_token/", views.RevokeTokenView.as_view(), name="revoke-token"), |     path("revoke_token/", views.RevokeTokenView.as_view(), name="revoke-token"), | ||||||
|     path("introspect/", views.IntrospectTokenView.as_view(), name="introspect"), |     path("introspect/", views.IntrospectTokenView.as_view(), name="introspect"), | ||||||
|  |     # OpenID-Connect Discovery | ||||||
|  |     path('.well-known/openid-configuration', openid.OpenIDConfigurationView.as_view(), | ||||||
|  |          name='openid-discovery'), | ||||||
|  |     path('.well-known/jwks.json', openid.JSONWebKeyView.as_view(), | ||||||
|  |          name='openid-jwks'), | ||||||
| ] | ] | ||||||
|  | |||||||
							
								
								
									
										30
									
								
								passbook/oauth_provider/views/openid.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,30 @@ | |||||||
|  | """passbook oauth provider OpenID Views""" | ||||||
|  |  | ||||||
|  | from django.http import HttpRequest, JsonResponse | ||||||
|  | from django.shortcuts import reverse | ||||||
|  | from django.views.generic import View | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class OpenIDConfigurationView(View): | ||||||
|  |     """Return OpenID Configuration""" | ||||||
|  |  | ||||||
|  |     def get(self, request: HttpRequest): | ||||||
|  |         """Get Response conform to https://openid.net/specs/openid-connect-discovery-1_0.html""" | ||||||
|  |         return JsonResponse({ | ||||||
|  |             'issuer': request.build_absolute_uri(reverse('passbook_core:overview')), | ||||||
|  |             'authorization_endpoint': request.build_absolute_uri( | ||||||
|  |                 reverse('passbook_oauth_provider:oauth2-authorize')), | ||||||
|  |             'token_endpoint': request.build_absolute_uri(reverse('passbook_oauth_provider:token')), | ||||||
|  |             "jwks_uri": request.build_absolute_uri(reverse('passbook_oauth_provider:openid-jwks')), | ||||||
|  |             "scopes_supported": [ | ||||||
|  |                 "openid:userinfo", | ||||||
|  |             ], | ||||||
|  |         }) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class JSONWebKeyView(View): | ||||||
|  |     """JSON Web Key View""" | ||||||
|  |  | ||||||
|  |     def get(self, request: HttpRequest): | ||||||
|  |         """JSON Webkeys are not implemented yet, hence return an empty object""" | ||||||
|  |         return JsonResponse({}) | ||||||
| @ -1,2 +1,2 @@ | |||||||
| """passbook otp Header""" | """passbook otp Header""" | ||||||
| __version__ = '0.1.20-beta' | __version__ = '0.1.23-beta' | ||||||
|  | |||||||
| @ -1,2 +1,2 @@ | |||||||
| """passbook password_expiry""" | """passbook password_expiry""" | ||||||
| __version__ = '0.1.20-beta' | __version__ = '0.1.23-beta' | ||||||
|  | |||||||
| @ -1,2 +1,2 @@ | |||||||
| """passbook saml_idp Header""" | """passbook saml_idp Header""" | ||||||
| __version__ = '0.1.20-beta' | __version__ = '0.1.23-beta' | ||||||
|  | |||||||
