Compare commits
	
		
			21 Commits
		
	
	
		
			version/0.
			...
			version/0.
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| bfa58be721 | |||
| 4bb602149e | |||
| 81ab9092fc | |||
| 29d5962c4c | |||
| 5c75339946 | |||
| 4774d9a46c | |||
| dbe16ba4fd | |||
| 6972cf00a0 | |||
| 0445be9712 | |||
| 89dbdd9585 | |||
| da88ce7150 | |||
| 5f50fcfcf5 | |||
| 96be087221 | |||
| a53a269a8c | |||
| 59565a5286 | |||
| ae3c092238 | |||
| e98e5e4e3e | |||
| d50c7ec8d4 | |||
| c0fdf377d1 | |||
| 70c11c8988 | |||
| 67b19becc1 | 
@ -1,5 +1,5 @@
 | 
			
		||||
[bumpversion]
 | 
			
		||||
current_version = 0.1.18-beta
 | 
			
		||||
current_version = 0.1.22-beta
 | 
			
		||||
tag = True
 | 
			
		||||
commit = True
 | 
			
		||||
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)\-(?P<release>.*)
 | 
			
		||||
 | 
			
		||||
@ -54,7 +54,7 @@ package-docker:
 | 
			
		||||
    before_script:
 | 
			
		||||
        - echo "{\"auths\":{\"docker.$NEXUS_URL\":{\"auth\":\"$NEXUS_AUTH\"}}}" > /kaniko/.docker/config.json
 | 
			
		||||
    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.18-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.22-beta
 | 
			
		||||
    stage: build
 | 
			
		||||
    only:
 | 
			
		||||
        - tags
 | 
			
		||||
 | 
			
		||||
@ -3,7 +3,7 @@ from setuptools import setup
 | 
			
		||||
 | 
			
		||||
setup(
 | 
			
		||||
    name='django-allauth-passbook',
 | 
			
		||||
    version='0.1.18-beta',
 | 
			
		||||
    version='0.1.22-beta',
 | 
			
		||||
    description='passbook support for django-allauth',
 | 
			
		||||
    # long_description='\n'.join(read_simple('docs/index.md')[2:]),
 | 
			
		||||
    long_description_content_type='text/markdown',
 | 
			
		||||
 | 
			
		||||
@ -8,13 +8,13 @@ from sentry.utils import json
 | 
			
		||||
from .constants import BASE_DOMAIN
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class SupervisrApiError(Exception):
 | 
			
		||||
class PassbookApiError(Exception):
 | 
			
		||||
    def __init__(self, message='', status=0):
 | 
			
		||||
        super(SupervisrApiError, self).__init__(message)
 | 
			
		||||
        super(PassbookApiError, self).__init__(message)
 | 
			
		||||
        self.status = status
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class SupervisrClient(object):
 | 
			
		||||
class PassbookClient(object):
 | 
			
		||||
    def __init__(self, client_id, client_secret):
 | 
			
		||||
        self.client_id = client_id
 | 
			
		||||
        self.client_secret = client_secret
 | 
			
		||||
@ -36,10 +36,10 @@ class SupervisrClient(object):
 | 
			
		||||
                headers=headers,
 | 
			
		||||
            )
 | 
			
		||||
        except RequestException as e:
 | 
			
		||||
            raise SupervisrApiError(unicode(e), status=getattr(e, 'status_code', 0))
 | 
			
		||||
            raise PassbookApiError(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)
 | 
			
		||||
            raise PassbookApiError(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)
 | 
			
		||||
        return self._request('/api/v1/openid/', access_token)
 | 
			
		||||
 | 
			
		||||
@ -18,7 +18,7 @@ tests_require = [
 | 
			
		||||
 | 
			
		||||
setup(
 | 
			
		||||
    name='sentry-auth-passbook',
 | 
			
		||||
    version='0.1.18-beta',
 | 
			
		||||
    version='0.1.22-beta',
 | 
			
		||||
    author='BeryJu.org',
 | 
			
		||||
    author_email='support@beryju.org',
 | 
			
		||||
    url='https://passbook.beryju.org',
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										42
									
								
								debian/changelog
									
									
									
									
										vendored
									
									
								
							
							
						
						@ -1,3 +1,45 @@
 | 
			
		||||
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
 | 
			
		||||
 | 
			
		||||
  * bump version: 0.1.18-beta -> 0.1.19-beta
 | 
			
		||||
  * fix GitHub Pretend again
 | 
			
		||||
  * add user settings for Sources
 | 
			
		||||
 | 
			
		||||
 -- Jens Langhammer <jens.langhammer@beryju.org>  Wed, 13 Mar 2019 15:49:44 +0000
 | 
			
		||||
 | 
			
		||||
passbook (0.1.18) stable; urgency=medium
 | 
			
		||||
 | 
			
		||||
  * bump version: 0.1.16-beta -> 0.1.17-beta
 | 
			
		||||
  * fix Server Error when downloading metadata
 | 
			
		||||
  * add sentry client
 | 
			
		||||
  * fix included yaml file
 | 
			
		||||
  * adjust versions for client packages, auto build client-packages
 | 
			
		||||
  * bump version: 0.1.17-beta -> 0.1.18-beta
 | 
			
		||||
  * fix API Call for sentry-client, add missing template
 | 
			
		||||
  * fix GitHub Pretend throwing a 500 error
 | 
			
		||||
 | 
			
		||||
 -- Jens Langhammer <jens.langhammer@beryju.org>  Wed, 13 Mar 2019 14:14:10 +0000
 | 
			
		||||
 | 
			
		||||
passbook (0.1.17) stable; urgency=medium
 | 
			
		||||
 | 
			
		||||
  * bump version: 0.1.15-beta -> 0.1.16-beta
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,6 @@
 | 
			
		||||
apiVersion: v1
 | 
			
		||||
appVersion: "0.1.18-beta"
 | 
			
		||||
appVersion: "0.1.22-beta"
 | 
			
		||||
description: A Helm chart for passbook.
 | 
			
		||||
name: passbook
 | 
			
		||||
version: "0.1.18-beta"
 | 
			
		||||
version: "0.1.22-beta"
 | 
			
		||||
icon: https://passbook.beryju.org/images/logo.png
 | 
			
		||||
 | 
			
		||||
@ -123,6 +123,7 @@ data:
 | 
			
		||||
        - passbook.oauth_client.source_types.reddit
 | 
			
		||||
        - passbook.oauth_client.source_types.supervisr
 | 
			
		||||
        - passbook.oauth_client.source_types.twitter
 | 
			
		||||
        - passbook.oauth_client.source_types.azure_ad
 | 
			
		||||
    saml_idp:
 | 
			
		||||
      signing: true
 | 
			
		||||
      autosubmit: false
 | 
			
		||||
 | 
			
		||||
@ -5,7 +5,7 @@
 | 
			
		||||
replicaCount: 1
 | 
			
		||||
 | 
			
		||||
image:
 | 
			
		||||
  tag: 0.1.18-beta
 | 
			
		||||
  tag: 0.1.22-beta
 | 
			
		||||
 | 
			
		||||
nameOverride: ""
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,2 +1,2 @@
 | 
			
		||||
"""passbook"""
 | 
			
		||||
__version__ = '0.1.18-beta'
 | 
			
		||||
__version__ = '0.1.22-beta'
 | 
			
		||||
 | 
			
		||||
@ -1,2 +1,2 @@
 | 
			
		||||
"""passbook admin"""
 | 
			
		||||
__version__ = '0.1.18-beta'
 | 
			
		||||
__version__ = '0.1.22-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"""
 | 
			
		||||
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,
 | 
			
		||||
                                  property_mapping, providers, sources, users)
 | 
			
		||||
 | 
			
		||||
@ -77,5 +77,7 @@ urlpatterns = [
 | 
			
		||||
    # Groups
 | 
			
		||||
    path('groups/', groups.GroupListView.as_view(), name='groups'),
 | 
			
		||||
    # 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"""
 | 
			
		||||
__version__ = '0.1.18-beta'
 | 
			
		||||
__version__ = '0.1.22-beta'
 | 
			
		||||
 | 
			
		||||
@ -1,2 +1,2 @@
 | 
			
		||||
"""passbook audit Header"""
 | 
			
		||||
__version__ = '0.1.18-beta'
 | 
			
		||||
__version__ = '0.1.22-beta'
 | 
			
		||||
 | 
			
		||||
@ -1,2 +1,2 @@
 | 
			
		||||
"""passbook captcha_factor Header"""
 | 
			
		||||
__version__ = '0.1.18-beta'
 | 
			
		||||
__version__ = '0.1.22-beta'
 | 
			
		||||
 | 
			
		||||
@ -1,2 +1,2 @@
 | 
			
		||||
"""passbook core"""
 | 
			
		||||
__version__ = '0.1.18-beta'
 | 
			
		||||
__version__ = '0.1.22-beta'
 | 
			
		||||
 | 
			
		||||
@ -186,6 +186,12 @@ class Source(PolicyModel):
 | 
			
		||||
        """Return additional Info, such as a callback URL. Show in the administration interface."""
 | 
			
		||||
        return None
 | 
			
		||||
 | 
			
		||||
    def has_user_settings(self):
 | 
			
		||||
        """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
 | 
			
		||||
        is the name the item has, the second string is the icon and the third is the view-name."""
 | 
			
		||||
        return False
 | 
			
		||||
 | 
			
		||||
    def __str__(self):
 | 
			
		||||
        return self.name
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -35,6 +35,7 @@ SECRET_KEY = CONFIG.get('secret_key')
 | 
			
		||||
DEBUG = CONFIG.get('debug')
 | 
			
		||||
INTERNAL_IPS = ['127.0.0.1']
 | 
			
		||||
ALLOWED_HOSTS = CONFIG.get('domains', [])
 | 
			
		||||
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
 | 
			
		||||
 | 
			
		||||
LOGIN_URL = 'passbook_core:auth-login'
 | 
			
		||||
# 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 %}
 | 
			
		||||
 | 
			
		||||
<!DOCTYPE html>
 | 
			
		||||
<html lang="en">
 | 
			
		||||
<html lang="en" class="layout-pf layout-pf-fixed transitions">
 | 
			
		||||
 | 
			
		||||
<head>
 | 
			
		||||
  <meta charset="UTF-8">
 | 
			
		||||
 | 
			
		||||
@ -16,6 +16,7 @@
 | 
			
		||||
                Are you sure you want to delete {{ object_type }} "{{ object }}"?
 | 
			
		||||
                {% endblocktrans %}
 | 
			
		||||
            </p>
 | 
			
		||||
            <input type="hidden" name="confirmdelete" value="yes">
 | 
			
		||||
            <a href="{% back %}" class="btn btn-default">{% trans 'Back' %}</a>
 | 
			
		||||
            <input type="submit" class="btn btn-danger" value="{% trans 'Delete' %}" />
 | 
			
		||||
        </form>
 | 
			
		||||
 | 
			
		||||
@ -51,7 +51,7 @@
 | 
			
		||||
                {% for url, icon, name in sources %}
 | 
			
		||||
                <li class="login-pf-social-link">
 | 
			
		||||
                    <a href="{{ url }}">
 | 
			
		||||
                        <img src="{% static 'img/' %}{{ icon }}.svg" alt="{{ name }}"> {{ name }}
 | 
			
		||||
                        <img src="{% static 'img/logos/' %}{{ icon }}.svg" alt="{{ name }}"> {{ name }}
 | 
			
		||||
                    </a>
 | 
			
		||||
                </li>
 | 
			
		||||
                {% endfor %}
 | 
			
		||||
 | 
			
		||||
@ -26,7 +26,7 @@
 | 
			
		||||
            <li class="dropdown">
 | 
			
		||||
                <button class="btn btn-link dropdown-toggle nav-item-iconic" id="dropdownMenu1" data-toggle="dropdown"
 | 
			
		||||
                    aria-haspopup="true" aria-expanded="true">
 | 
			
		||||
                    <span title="Help" class="fa pficon-help dropdown-title"></span>
 | 
			
		||||
                    <span title="Help" class="fa pficon-help"></span>
 | 
			
		||||
                </button>
 | 
			
		||||
                <ul class="dropdown-menu" aria-labelledby="dropdownMenu1">
 | 
			
		||||
                    {% comment %} <li><a href="#0">Help</a></li> {% endcomment %}
 | 
			
		||||
@ -172,19 +172,27 @@
 | 
			
		||||
                            </span>
 | 
			
		||||
                        </a>
 | 
			
		||||
                    </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>
 | 
			
		||||
            </div>
 | 
			
		||||
        </li>
 | 
			
		||||
        {% endif %}
 | 
			
		||||
    </ul>
 | 
			
		||||
</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 %}
 | 
			
		||||
    {% endblock %}
 | 
			
		||||
</div>
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
{% block scripts %}
 | 
			
		||||
{{ block.super }}
 | 
			
		||||
<script>
 | 
			
		||||
    $(document).ready(function () {
 | 
			
		||||
        // initialize tooltips
 | 
			
		||||
 | 
			
		||||
@ -2,6 +2,7 @@
 | 
			
		||||
 | 
			
		||||
{% load i18n %}
 | 
			
		||||
{% load is_active %}
 | 
			
		||||
{% load static %}
 | 
			
		||||
{% load passbook_user_settings %}
 | 
			
		||||
 | 
			
		||||
{% block content %}
 | 
			
		||||
@ -24,6 +25,15 @@
 | 
			
		||||
                    </a>
 | 
			
		||||
                </li>
 | 
			
		||||
                {% endfor %}
 | 
			
		||||
                <li class="nav-divider"></li>
 | 
			
		||||
                {% user_sources as us %}
 | 
			
		||||
                {% for name, icon, link in us %}
 | 
			
		||||
                <li class="{% if link == request.get_full_path %} active {% endif %}">
 | 
			
		||||
                    <a href="{{ link }}">
 | 
			
		||||
                        <i class="{{ icon }}"></i> {{ name }}
 | 
			
		||||
                    </a>
 | 
			
		||||
                </li>
 | 
			
		||||
                {% endfor %}
 | 
			
		||||
            </ul>
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
@ -2,7 +2,7 @@
 | 
			
		||||
 | 
			
		||||
from django import template
 | 
			
		||||
 | 
			
		||||
from passbook.core.models import Factor
 | 
			
		||||
from passbook.core.models import Factor, Source
 | 
			
		||||
from passbook.core.policies import PolicyEngine
 | 
			
		||||
 | 
			
		||||
register = template.Library()
 | 
			
		||||
@ -20,3 +20,17 @@ def user_factors(context):
 | 
			
		||||
        if policy_engine.passing and _link:
 | 
			
		||||
            matching_factors.append(_link)
 | 
			
		||||
    return matching_factors
 | 
			
		||||
 | 
			
		||||
@register.simple_tag(takes_context=True)
 | 
			
		||||
def user_sources(context):
 | 
			
		||||
    """Return a list of all sources which are enabled for the user"""
 | 
			
		||||
    user = context.get('request').user
 | 
			
		||||
    _all_sources = Source.objects.filter(enabled=True).select_subclasses()
 | 
			
		||||
    matching_sources = []
 | 
			
		||||
    for factor in _all_sources:
 | 
			
		||||
        _link = factor.has_user_settings()
 | 
			
		||||
        policy_engine = PolicyEngine(factor.policies.all())
 | 
			
		||||
        policy_engine.for_user(user).with_request(context.get('request')).build()
 | 
			
		||||
        if policy_engine.passing and _link:
 | 
			
		||||
            matching_sources.append(_link)
 | 
			
		||||
    return matching_sources
 | 
			
		||||
 | 
			
		||||
@ -1,2 +1,2 @@
 | 
			
		||||
"""passbook hibp_policy"""
 | 
			
		||||
__version__ = '0.1.18-beta'
 | 
			
		||||
__version__ = '0.1.22-beta'
 | 
			
		||||
 | 
			
		||||
@ -1,2 +1,2 @@
 | 
			
		||||
"""Passbook ldap app Header"""
 | 
			
		||||
__version__ = '0.1.18-beta'
 | 
			
		||||
__version__ = '0.1.22-beta'
 | 
			
		||||
 | 
			
		||||
@ -1,2 +1,2 @@
 | 
			
		||||
"""passbook lib"""
 | 
			
		||||
__version__ = '0.1.18-beta'
 | 
			
		||||
__version__ = '0.1.22-beta'
 | 
			
		||||
 | 
			
		||||
@ -85,6 +85,7 @@ oauth_client:
 | 
			
		||||
    - passbook.oauth_client.source_types.reddit
 | 
			
		||||
    - passbook.oauth_client.source_types.supervisr
 | 
			
		||||
    - passbook.oauth_client.source_types.twitter
 | 
			
		||||
    - passbook.oauth_client.source_types.azure_ad
 | 
			
		||||
saml_idp:
 | 
			
		||||
  # List of python packages with provider types to load.
 | 
			
		||||
  types:
 | 
			
		||||
 | 
			
		||||
@ -1,2 +1,2 @@
 | 
			
		||||
"""passbook oauth_client Header"""
 | 
			
		||||
__version__ = '0.1.18-beta'
 | 
			
		||||
__version__ = '0.1.22-beta'
 | 
			
		||||
 | 
			
		||||
@ -108,3 +108,17 @@ class GoogleOAuthSourceForm(OAuthSourceForm):
 | 
			
		||||
            'access_token_url': 'https://accounts.google.com/o/oauth2/token',
 | 
			
		||||
            '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://login.microsoftonline.com/common/openid/userinfo',
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,7 @@
 | 
			
		||||
"""OAuth Client models"""
 | 
			
		||||
 | 
			
		||||
from django.db import models
 | 
			
		||||
from django.urls import reverse_lazy
 | 
			
		||||
from django.urls import reverse, reverse_lazy
 | 
			
		||||
from django.utils.translation import gettext as _
 | 
			
		||||
 | 
			
		||||
from passbook.core.models import Source, UserSourceConnection
 | 
			
		||||
@ -29,15 +29,28 @@ class OAuthSource(Source):
 | 
			
		||||
    def get_login_button(self):
 | 
			
		||||
        url = reverse_lazy('passbook_oauth_client:oauth-client-login',
 | 
			
		||||
                           kwargs={'source_slug': self.slug})
 | 
			
		||||
        if self.provider_type == 'github':
 | 
			
		||||
            return url, 'github-logo', _('GitHub')
 | 
			
		||||
        return url, 'generic', _('Generic')
 | 
			
		||||
        # if self.provider_type == 'github':
 | 
			
		||||
        #     return url, 'github-logo', _('GitHub')
 | 
			
		||||
        return url, self.provider_type, self.name
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def additional_info(self):
 | 
			
		||||
        return "Callback URL: '%s'" % reverse_lazy('passbook_oauth_client:oauth-client-callback',
 | 
			
		||||
                                                   kwargs={'source_slug': self.slug})
 | 
			
		||||
 | 
			
		||||
    def has_user_settings(self):
 | 
			
		||||
        """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
 | 
			
		||||
        is the name the item has, the second string is the icon and the third is the view-name."""
 | 
			
		||||
        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'
 | 
			
		||||
        return self.name, icon_class, reverse((view_name), kwargs={
 | 
			
		||||
            'source_slug': self.slug
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
 | 
			
		||||
        verbose_name = _('Generic OAuth Source')
 | 
			
		||||
@ -103,6 +116,19 @@ class GoogleOAuthSource(OAuthSource):
 | 
			
		||||
        verbose_name = _('Google OAuth Source')
 | 
			
		||||
        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):
 | 
			
		||||
    """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)
 | 
			
		||||
@ -1,6 +0,0 @@
 | 
			
		||||
{% load passbook_oauth_client %}
 | 
			
		||||
 | 
			
		||||
{% any_provider as enabled %}
 | 
			
		||||
{% if enabled %}
 | 
			
		||||
<div class="btn-group btn-primary btn-block">
 | 
			
		||||
{% endif %}
 | 
			
		||||
@ -1,6 +0,0 @@
 | 
			
		||||
{% load passbook_oauth_client %}
 | 
			
		||||
 | 
			
		||||
{% provider_exists 'facebook' as facebook_enabled %}
 | 
			
		||||
{% if facebook_enabled %}
 | 
			
		||||
<a href="{% url 'passbook_oauth_client:oauth-client-login' provider='facebook' %}" class="btn" style="background-color:#4267b2;color:white;margin-top:10px;width:100%;"><i class="fa fa-facebook-official" aria-hidden="true"></i></a>
 | 
			
		||||
{% endif %}
 | 
			
		||||
@ -1,6 +0,0 @@
 | 
			
		||||
{% load passbook_oauth_client %}
 | 
			
		||||
 | 
			
		||||
{% provider_exists 'twitter' as twitter_enabled %}
 | 
			
		||||
{% if twitter_enabled %}
 | 
			
		||||
<a href="{% url 'passbook_oauth_client:oauth-client-login' provider='twitter' %}" class="btn" style="background-color:#55ACEE;color:white;margin-top:10px;width:100%;"><i class="fa fa-twitter" aria-hidden="true"></i></a>
 | 
			
		||||
{% endif %}
 | 
			
		||||
@ -1,7 +0,0 @@
 | 
			
		||||
{% load passbook_oauth_client %}
 | 
			
		||||
{% load static %}
 | 
			
		||||
 | 
			
		||||
{% provider_exists 'google' as google_enabled %}
 | 
			
		||||
{% if google_enabled %}
 | 
			
		||||
<a href="{% url 'passbook_oauth_client:oauth-client-login' provider='google' %}" class="btn" style="background-color:white;color:black;margin-top:10px;width:100%;"><img src="{% static 'img/google.svg' %}" style="height:12px"></a>
 | 
			
		||||
{% endif %}
 | 
			
		||||
@ -1,6 +0,0 @@
 | 
			
		||||
{% load passbook_oauth_client %}
 | 
			
		||||
 | 
			
		||||
{% provider_exists 'github' as github_enabled %}
 | 
			
		||||
{% if github_enabled %}
 | 
			
		||||
<a href="{% url 'passbook_oauth_client:oauth-client-login' provider='github' %}" class="btn" style="background-color:#444444;color:white;margin-top:10px;width:100%;"><i class="fa fa-github" aria-hidden="true"></i></a>
 | 
			
		||||
{% endif %}
 | 
			
		||||
@ -1,7 +0,0 @@
 | 
			
		||||
{% load passbook_oauth_client %}
 | 
			
		||||
{% load static %}
 | 
			
		||||
 | 
			
		||||
{% provider_exists 'discord' as discord_enabled %}
 | 
			
		||||
{% if discord_enabled %}
 | 
			
		||||
<a href="{% url 'passbook_oauth_client:oauth-client-login' provider='discord' %}" class="btn" style="background-color:#2C2F33;color:white;margin-top:10px;width:100%;"><img src="{% static 'img/discord.svg' %}" style="height:12px"></a>
 | 
			
		||||
{% endif %}
 | 
			
		||||
@ -1,7 +0,0 @@
 | 
			
		||||
{% load passbook_oauth_client %}
 | 
			
		||||
{% load static %}
 | 
			
		||||
 | 
			
		||||
{% provider_exists 'reddit' as reddit_enabled %}
 | 
			
		||||
{% if reddit_enabled %}
 | 
			
		||||
<a href="{% url 'passbook_oauth_client:oauth-client-login' provider='reddit' %}" class="btn" style="background-color:#ff4500;color:white;margin-top:10px;width:100%;"><img src="{% static 'img/reddit.svg' %}" style="height:20px;margin-top:-5px;"></a>
 | 
			
		||||
{% endif %}
 | 
			
		||||
@ -1,6 +0,0 @@
 | 
			
		||||
{% load passbook_oauth_client %}
 | 
			
		||||
 | 
			
		||||
{% any_provider as enabled %}
 | 
			
		||||
{% if enabled %}
 | 
			
		||||
</div>
 | 
			
		||||
{% endif %}
 | 
			
		||||
@ -1,54 +0,0 @@
 | 
			
		||||
{% extends "user/base.html" %}
 | 
			
		||||
 | 
			
		||||
{% load utils %}
 | 
			
		||||
{% load i18n %}
 | 
			
		||||
 | 
			
		||||
{% block title %}
 | 
			
		||||
{% title "Overview" %}
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
{% block content %}
 | 
			
		||||
<h1><clr-icon shape="connect" size="48"></clr-icon>{% trans "OAuth2" %}</h1>
 | 
			
		||||
<div class="row">
 | 
			
		||||
  <div class="col-md-12">
 | 
			
		||||
    <div class="card">
 | 
			
		||||
      <div class="card-header">
 | 
			
		||||
        {% trans "Connected Accounts" %}
 | 
			
		||||
      </div>
 | 
			
		||||
      <div class="card-footer">
 | 
			
		||||
        {% if provider_state %}
 | 
			
		||||
        <table class="table">
 | 
			
		||||
          <thead>
 | 
			
		||||
            <th>
 | 
			
		||||
              <th>{% trans 'Provider' %}</th>
 | 
			
		||||
              <th>{% trans 'Status' %}</th>
 | 
			
		||||
              <th>{% trans 'Action' %}</th>
 | 
			
		||||
              <th>{% trans 'ID' %}</th>
 | 
			
		||||
            </th>
 | 
			
		||||
          </thead>
 | 
			
		||||
          <tbody>
 | 
			
		||||
            {% for data in provider_state %}
 | 
			
		||||
            <tr>
 | 
			
		||||
              <td></td>
 | 
			
		||||
              <td>{% trans data.provider.ui_name %}</td>
 | 
			
		||||
              <td>{{ data.state|yesno:"Connected,Not Connected" }}</td>
 | 
			
		||||
              <td>
 | 
			
		||||
              {% if data.state == False %}
 | 
			
		||||
                <a href="{% url 'passbook_oauth_client:oauth-client-login' provider=data.provider.name %}">Connect</a>
 | 
			
		||||
              {% else %}
 | 
			
		||||
                <a href="{% url 'passbook_oauth_client:oauth-client-disconnect' provider=data.provider.name %}">Disconnect</a>
 | 
			
		||||
              {% endif %}
 | 
			
		||||
              </td>
 | 
			
		||||
              <td>{{ data.aas.first.identifier }}</td>
 | 
			
		||||
            </tr>
 | 
			
		||||
            {% endfor %}
 | 
			
		||||
          </tbody>
 | 
			
		||||
        </table>
 | 
			
		||||
        {% else %}
 | 
			
		||||
        <p>{% trans "No Providers configured!" %}</p>
 | 
			
		||||
        {% endif %}
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
  </div>
 | 
			
		||||
</div>
 | 
			
		||||
{% endblock %}
 | 
			
		||||
							
								
								
									
										18
									
								
								passbook/oauth_client/templates/oauth_client/user.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,18 @@
 | 
			
		||||
{% extends "user/base.html" %}
 | 
			
		||||
 | 
			
		||||
{% load i18n %}
 | 
			
		||||
 | 
			
		||||
{% block page %}
 | 
			
		||||
<h1>{{ source.name }}</h1>
 | 
			
		||||
{% if connections.exists %}
 | 
			
		||||
<p>{% trans 'Connected.' %}</p>
 | 
			
		||||
<a class="btn btn-danger" href="{% url 'passbook_oauth_client:oauth-client-disconnect' source_slug=source.slug %}">
 | 
			
		||||
    {% trans 'Disconnect' %}
 | 
			
		||||
</a>
 | 
			
		||||
{% else %}
 | 
			
		||||
<p>Not connected.</p>
 | 
			
		||||
<a class="btn btn-primary" href="{% url 'passbook_oauth_client:oauth-client-login' source_slug=source.slug %}">
 | 
			
		||||
    {% trans 'Connect' %}
 | 
			
		||||
</a>
 | 
			
		||||
{% endif %}
 | 
			
		||||
{% endblock %}
 | 
			
		||||
@ -3,7 +3,7 @@
 | 
			
		||||
from django.urls import path
 | 
			
		||||
 | 
			
		||||
from passbook.oauth_client.source_types.manager import RequestKind
 | 
			
		||||
from passbook.oauth_client.views import core, dispatcher
 | 
			
		||||
from passbook.oauth_client.views import core, dispatcher, user
 | 
			
		||||
 | 
			
		||||
urlpatterns = [
 | 
			
		||||
    path('login/<slug:source_slug>/', dispatcher.DispatcherView.as_view(
 | 
			
		||||
@ -12,4 +12,6 @@ urlpatterns = [
 | 
			
		||||
        kind=RequestKind.callback), name='oauth-client-callback'),
 | 
			
		||||
    path('disconnect/<slug:source_slug>/', core.DisconnectView.as_view(),
 | 
			
		||||
         name='oauth-client-disconnect'),
 | 
			
		||||
    path('user/<slug:source_slug>/', user.UserSettingsView.as_view(),
 | 
			
		||||
         name='oauth-client-user'),
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
@ -194,7 +194,9 @@ class OAuthCallback(OAuthClientMixin, View):
 | 
			
		||||
            messages.success(self.request, _("Successfully linked %(source)s!" % {
 | 
			
		||||
                '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!" % {
 | 
			
		||||
            'source': self.source.name
 | 
			
		||||
        }))
 | 
			
		||||
@ -207,26 +209,28 @@ class DisconnectView(LoginRequiredMixin, View):
 | 
			
		||||
    source = None
 | 
			
		||||
    aas = None
 | 
			
		||||
 | 
			
		||||
    def dispatch(self, request, source):
 | 
			
		||||
        self.source = get_object_or_404(OAuthSource, name=source)
 | 
			
		||||
    def dispatch(self, request, source_slug):
 | 
			
		||||
        self.source = get_object_or_404(OAuthSource, slug=source_slug)
 | 
			
		||||
        self.aas = get_object_or_404(UserOAuthSourceConnection,
 | 
			
		||||
                                     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"""
 | 
			
		||||
        if 'confirmdelete' in request.POST:
 | 
			
		||||
            # User confirmed deletion
 | 
			
		||||
            self.aas.delete()
 | 
			
		||||
            messages.success(request, _('Connection successfully deleted'))
 | 
			
		||||
            return redirect(reverse('user_settings'))
 | 
			
		||||
        return self.get(request, source)
 | 
			
		||||
            return redirect(reverse('passbook_oauth_client:oauth-client-user', kwargs={
 | 
			
		||||
                'source_slug': self.source.slug
 | 
			
		||||
            }))
 | 
			
		||||
        return self.get(request, source_slug)
 | 
			
		||||
 | 
			
		||||
    def get(self, request, source):
 | 
			
		||||
        """Show delete form"""
 | 
			
		||||
        return render(request, 'generic/delete.html', {
 | 
			
		||||
            'object': 'OAuth Connection with %s' % self.source.name,
 | 
			
		||||
            'delete_url': reverse('oauth-client-disconnect', kwargs={
 | 
			
		||||
                'source': self.source.name,
 | 
			
		||||
            'object': self.source,
 | 
			
		||||
            'delete_url': reverse('passbook_oauth_client:oauth-client-disconnect', kwargs={
 | 
			
		||||
                'source_slug': self.source.slug,
 | 
			
		||||
            })
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										20
									
								
								passbook/oauth_client/views/user.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,20 @@
 | 
			
		||||
"""passbook oauth_client user views"""
 | 
			
		||||
from django.contrib.auth.mixins import LoginRequiredMixin
 | 
			
		||||
from django.shortcuts import get_object_or_404
 | 
			
		||||
from django.views.generic import TemplateView
 | 
			
		||||
 | 
			
		||||
from passbook.oauth_client.models import OAuthSource, UserOAuthSourceConnection
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class UserSettingsView(LoginRequiredMixin, TemplateView):
 | 
			
		||||
    """Show user current connection state"""
 | 
			
		||||
 | 
			
		||||
    template_name = 'oauth_client/user.html'
 | 
			
		||||
 | 
			
		||||
    def get_context_data(self, **kwargs):
 | 
			
		||||
        source = get_object_or_404(OAuthSource, slug=self.kwargs.get('source_slug'))
 | 
			
		||||
        connections = UserOAuthSourceConnection.objects.filter(user=self.request.user,
 | 
			
		||||
                                                               source=source)
 | 
			
		||||
        kwargs['source'] = source
 | 
			
		||||
        kwargs['connections'] = connections
 | 
			
		||||
        return super().get_context_data(**kwargs)
 | 
			
		||||
@ -1,2 +1,2 @@
 | 
			
		||||
"""passbook oauth_provider Header"""
 | 
			
		||||
__version__ = '0.1.18-beta'
 | 
			
		||||
__version__ = '0.1.22-beta'
 | 
			
		||||
 | 
			
		||||
@ -1,2 +1,2 @@
 | 
			
		||||
"""passbook otp Header"""
 | 
			
		||||
__version__ = '0.1.18-beta'
 | 
			
		||||
__version__ = '0.1.22-beta'
 | 
			
		||||
 | 
			
		||||
@ -1,2 +1,2 @@
 | 
			
		||||
"""passbook password_expiry"""
 | 
			
		||||
__version__ = '0.1.18-beta'
 | 
			
		||||
__version__ = '0.1.22-beta'
 | 
			
		||||
 | 
			
		||||
@ -1,16 +1,24 @@
 | 
			
		||||
"""passbook pretend GitHub Views"""
 | 
			
		||||
from django.http import JsonResponse
 | 
			
		||||
from django.shortcuts import get_object_or_404
 | 
			
		||||
from django.views import View
 | 
			
		||||
from oauth2_provider.models import AccessToken
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class GitHubUserView(View):
 | 
			
		||||
    """Emulate GitHub's /user API Endpoint"""
 | 
			
		||||
 | 
			
		||||
    def verify_access_token(self):
 | 
			
		||||
        """Verify access token manually since github uses /user?access_token=..."""
 | 
			
		||||
        token = get_object_or_404(AccessToken, token=self.request.GET.get('access_token', ''))
 | 
			
		||||
        return token.user
 | 
			
		||||
 | 
			
		||||
    def get(self, request):
 | 
			
		||||
        """Emulate GitHub's /user API Endpoint"""
 | 
			
		||||
        user = self.verify_access_token()
 | 
			
		||||
        return JsonResponse({
 | 
			
		||||
            "login": request.user.username,
 | 
			
		||||
            "id": request.user.pk,
 | 
			
		||||
            "login": user.username,
 | 
			
		||||
            "id": user.pk,
 | 
			
		||||
            "node_id": "",
 | 
			
		||||
            "avatar_url": "",
 | 
			
		||||
            "gravatar_id": "",
 | 
			
		||||
@ -27,19 +35,19 @@ class GitHubUserView(View):
 | 
			
		||||
            "received_events_url": "",
 | 
			
		||||
            "type": "User",
 | 
			
		||||
            "site_admin": False,
 | 
			
		||||
            "name": request.user.name,
 | 
			
		||||
            "name": user.name,
 | 
			
		||||
            "company": "",
 | 
			
		||||
            "blog": "",
 | 
			
		||||
            "location": "",
 | 
			
		||||
            "email": request.user.email,
 | 
			
		||||
            "email": user.email,
 | 
			
		||||
            "hireable": False,
 | 
			
		||||
            "bio": "",
 | 
			
		||||
            "public_repos": 0,
 | 
			
		||||
            "public_gists": 0,
 | 
			
		||||
            "followers": 0,
 | 
			
		||||
            "following": 0,
 | 
			
		||||
            "created_at": request.user.date_joined,
 | 
			
		||||
            "updated_at": request.user.date_joined,
 | 
			
		||||
            "created_at": user.date_joined,
 | 
			
		||||
            "updated_at": user.date_joined,
 | 
			
		||||
            "private_gists": 0,
 | 
			
		||||
            "total_private_repos": 0,
 | 
			
		||||
            "owned_private_repos": 0,
 | 
			
		||||
 | 
			
		||||
@ -1,2 +1,2 @@
 | 
			
		||||
"""passbook saml_idp Header"""
 | 
			
		||||
__version__ = '0.1.18-beta'
 | 
			
		||||
__version__ = '0.1.22-beta'
 | 
			
		||||
 | 
			
		||||