Revert "*: providers and sources -> channels, PolicyModel to PolicyBindingModel that uses custom M2M through"
This reverts commit 7ed3ceb960.
			
			
This commit is contained in:
		@ -1,4 +0,0 @@
 | 
			
		||||
"""passbook core inlet form fields"""
 | 
			
		||||
 | 
			
		||||
INLET_FORM_FIELDS = ["name", "slug", "enabled"]
 | 
			
		||||
INLET_SERIALIZER_FIELDS = ["pk", "name", "slug", "enabled"]
 | 
			
		||||
							
								
								
									
										4
									
								
								passbook/admin/forms/source.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								passbook/admin/forms/source.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,4 @@
 | 
			
		||||
"""passbook core source form fields"""
 | 
			
		||||
 | 
			
		||||
SOURCE_FORM_FIELDS = ["name", "slug", "enabled"]
 | 
			
		||||
SOURCE_SERIALIZER_FIELDS = ["pk", "name", "slug", "enabled"]
 | 
			
		||||
@ -8,12 +8,12 @@ from passbook.admin.views import (
 | 
			
		||||
    debug,
 | 
			
		||||
    flows,
 | 
			
		||||
    groups,
 | 
			
		||||
    inlets,
 | 
			
		||||
    invitations,
 | 
			
		||||
    outlets,
 | 
			
		||||
    overview,
 | 
			
		||||
    policies,
 | 
			
		||||
    policy,
 | 
			
		||||
    property_mapping,
 | 
			
		||||
    providers,
 | 
			
		||||
    sources,
 | 
			
		||||
    stages,
 | 
			
		||||
    users,
 | 
			
		||||
)
 | 
			
		||||
@ -39,49 +39,51 @@ urlpatterns = [
 | 
			
		||||
        applications.ApplicationDeleteView.as_view(),
 | 
			
		||||
        name="application-delete",
 | 
			
		||||
    ),
 | 
			
		||||
    # Inlets
 | 
			
		||||
    path("inlets/", inlets.InletListView.as_view(), name="inlets"),
 | 
			
		||||
    path("inlets/create/", inlets.InletCreateView.as_view(), name="inlet-create"),
 | 
			
		||||
    # Sources
 | 
			
		||||
    path("sources/", sources.SourceListView.as_view(), name="sources"),
 | 
			
		||||
    path("sources/create/", sources.SourceCreateView.as_view(), name="source-create"),
 | 
			
		||||
    path(
 | 
			
		||||
        "inlets/<uuid:pk>/update/",
 | 
			
		||||
        inlets.InletUpdateView.as_view(),
 | 
			
		||||
        name="inlet-update",
 | 
			
		||||
        "sources/<uuid:pk>/update/",
 | 
			
		||||
        sources.SourceUpdateView.as_view(),
 | 
			
		||||
        name="source-update",
 | 
			
		||||
    ),
 | 
			
		||||
    path(
 | 
			
		||||
        "inlets/<uuid:pk>/delete/",
 | 
			
		||||
        inlets.InletDeleteView.as_view(),
 | 
			
		||||
        name="inlet-delete",
 | 
			
		||||
        "sources/<uuid:pk>/delete/",
 | 
			
		||||
        sources.SourceDeleteView.as_view(),
 | 
			
		||||
        name="source-delete",
 | 
			
		||||
    ),
 | 
			
		||||
    # Policies
 | 
			
		||||
    path("policies/", policies.PolicyListView.as_view(), name="policies"),
 | 
			
		||||
    path("policies/create/", policies.PolicyCreateView.as_view(), name="policy-create"),
 | 
			
		||||
    path("policies/", policy.PolicyListView.as_view(), name="policies"),
 | 
			
		||||
    path("policies/create/", policy.PolicyCreateView.as_view(), name="policy-create"),
 | 
			
		||||
    path(
 | 
			
		||||
        "policies/<uuid:pk>/update/",
 | 
			
		||||
        policies.PolicyUpdateView.as_view(),
 | 
			
		||||
        policy.PolicyUpdateView.as_view(),
 | 
			
		||||
        name="policy-update",
 | 
			
		||||
    ),
 | 
			
		||||
    path(
 | 
			
		||||
        "policies/<uuid:pk>/delete/",
 | 
			
		||||
        policies.PolicyDeleteView.as_view(),
 | 
			
		||||
        policy.PolicyDeleteView.as_view(),
 | 
			
		||||
        name="policy-delete",
 | 
			
		||||
    ),
 | 
			
		||||
    path(
 | 
			
		||||
        "policies/<uuid:pk>/test/",
 | 
			
		||||
        policies.PolicyTestView.as_view(),
 | 
			
		||||
        name="policy-test",
 | 
			
		||||
        "policies/<uuid:pk>/test/", policy.PolicyTestView.as_view(), name="policy-test"
 | 
			
		||||
    ),
 | 
			
		||||
    # Outlets
 | 
			
		||||
    path("outlets/", outlets.OutletListView.as_view(), name="outlets"),
 | 
			
		||||
    path("outlets/create/", outlets.OutletCreateView.as_view(), name="outlet-create",),
 | 
			
		||||
    # Providers
 | 
			
		||||
    path("providers/", providers.ProviderListView.as_view(), name="providers"),
 | 
			
		||||
    path(
 | 
			
		||||
        "outlets/<int:pk>/update/",
 | 
			
		||||
        outlets.OutletUpdateView.as_view(),
 | 
			
		||||
        name="outlet-update",
 | 
			
		||||
        "providers/create/",
 | 
			
		||||
        providers.ProviderCreateView.as_view(),
 | 
			
		||||
        name="provider-create",
 | 
			
		||||
    ),
 | 
			
		||||
    path(
 | 
			
		||||
        "outlets/<int:pk>/delete/",
 | 
			
		||||
        outlets.OutletDeleteView.as_view(),
 | 
			
		||||
        name="outlet-delete",
 | 
			
		||||
        "providers/<int:pk>/update/",
 | 
			
		||||
        providers.ProviderUpdateView.as_view(),
 | 
			
		||||
        name="provider-update",
 | 
			
		||||
    ),
 | 
			
		||||
    path(
 | 
			
		||||
        "providers/<int:pk>/delete/",
 | 
			
		||||
        providers.ProviderDeleteView.as_view(),
 | 
			
		||||
        name="provider-delete",
 | 
			
		||||
    ),
 | 
			
		||||
    # Stages
 | 
			
		||||
    path("stages/", stages.StageListView.as_view(), name="stages"),
 | 
			
		||||
 | 
			
		||||
@ -5,9 +5,8 @@ from django.views.generic import TemplateView
 | 
			
		||||
 | 
			
		||||
from passbook import __version__
 | 
			
		||||
from passbook.admin.mixins import AdminRequiredMixin
 | 
			
		||||
from passbook.core.models import Application, Inlet, Outlet, User
 | 
			
		||||
from passbook.core.models import Application, Policy, Provider, Source, User
 | 
			
		||||
from passbook.flows.models import Flow, Stage
 | 
			
		||||
from passbook.policies.models import Policy
 | 
			
		||||
from passbook.root.celery import CELERY_APP
 | 
			
		||||
from passbook.stages.invitation.models import Invitation
 | 
			
		||||
 | 
			
		||||
@ -28,14 +27,16 @@ class AdministrationOverviewView(AdminRequiredMixin, TemplateView):
 | 
			
		||||
        kwargs["application_count"] = len(Application.objects.all())
 | 
			
		||||
        kwargs["policy_count"] = len(Policy.objects.all())
 | 
			
		||||
        kwargs["user_count"] = len(User.objects.all())
 | 
			
		||||
        kwargs["outlet_count"] = len(Outlet.objects.all())
 | 
			
		||||
        kwargs["inlet_count"] = len(Inlet.objects.all())
 | 
			
		||||
        kwargs["provider_count"] = len(Provider.objects.all())
 | 
			
		||||
        kwargs["source_count"] = len(Source.objects.all())
 | 
			
		||||
        kwargs["stage_count"] = len(Stage.objects.all())
 | 
			
		||||
        kwargs["flow_count"] = len(Flow.objects.all())
 | 
			
		||||
        kwargs["invitation_count"] = len(Invitation.objects.all())
 | 
			
		||||
        kwargs["version"] = __version__
 | 
			
		||||
        kwargs["worker_count"] = len(CELERY_APP.control.ping(timeout=0.5))
 | 
			
		||||
        kwargs["outlets_without_application"] = Outlet.objects.filter(application=None)
 | 
			
		||||
        kwargs["providers_without_application"] = Provider.objects.filter(
 | 
			
		||||
            application=None
 | 
			
		||||
        )
 | 
			
		||||
        kwargs["policies_without_binding"] = len(
 | 
			
		||||
            Policy.objects.filter(policymodel__isnull=True)
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
@ -13,10 +13,10 @@ from django.views.generic.detail import DetailView
 | 
			
		||||
from guardian.mixins import PermissionListMixin, PermissionRequiredMixin
 | 
			
		||||
 | 
			
		||||
from passbook.admin.forms.policies import PolicyTestForm
 | 
			
		||||
from passbook.core.models import Policy
 | 
			
		||||
from passbook.lib.utils.reflection import all_subclasses, path_to_class
 | 
			
		||||
from passbook.lib.views import CreateAssignPermView
 | 
			
		||||
from passbook.policies.engine import PolicyEngine
 | 
			
		||||
from passbook.policies.models import Policy
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class PolicyListView(LoginRequiredMixin, PermissionListMixin, ListView):
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
"""passbook Inlet administration"""
 | 
			
		||||
"""passbook Provider administration"""
 | 
			
		||||
from django.contrib import messages
 | 
			
		||||
from django.contrib.auth.mixins import LoginRequiredMixin
 | 
			
		||||
from django.contrib.auth.mixins import (
 | 
			
		||||
@ -11,23 +11,23 @@ from django.utils.translation import ugettext as _
 | 
			
		||||
from django.views.generic import DeleteView, ListView, UpdateView
 | 
			
		||||
from guardian.mixins import PermissionListMixin, PermissionRequiredMixin
 | 
			
		||||
 | 
			
		||||
from passbook.core.models import Inlet
 | 
			
		||||
from passbook.core.models import Provider
 | 
			
		||||
from passbook.lib.utils.reflection import all_subclasses, path_to_class
 | 
			
		||||
from passbook.lib.views import CreateAssignPermView
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class InletListView(LoginRequiredMixin, PermissionListMixin, ListView):
 | 
			
		||||
    """Show list of all inlets"""
 | 
			
		||||
class ProviderListView(LoginRequiredMixin, PermissionListMixin, ListView):
 | 
			
		||||
    """Show list of all providers"""
 | 
			
		||||
 | 
			
		||||
    model = Inlet
 | 
			
		||||
    permission_required = "passbook_core.view_inlet"
 | 
			
		||||
    ordering = "name"
 | 
			
		||||
    paginate_by = 40
 | 
			
		||||
    template_name = "administration/inlet/list.html"
 | 
			
		||||
    model = Provider
 | 
			
		||||
    permission_required = "passbook_core.add_provider"
 | 
			
		||||
    template_name = "administration/provider/list.html"
 | 
			
		||||
    paginate_by = 10
 | 
			
		||||
    ordering = "id"
 | 
			
		||||
 | 
			
		||||
    def get_context_data(self, **kwargs):
 | 
			
		||||
        kwargs["types"] = {
 | 
			
		||||
            x.__name__: x._meta.verbose_name for x in all_subclasses(Inlet)
 | 
			
		||||
            x.__name__: x._meta.verbose_name for x in all_subclasses(Provider)
 | 
			
		||||
        }
 | 
			
		||||
        return super().get_context_data(**kwargs)
 | 
			
		||||
 | 
			
		||||
@ -35,40 +35,40 @@ class InletListView(LoginRequiredMixin, PermissionListMixin, ListView):
 | 
			
		||||
        return super().get_queryset().select_subclasses()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class InletCreateView(
 | 
			
		||||
class ProviderCreateView(
 | 
			
		||||
    SuccessMessageMixin,
 | 
			
		||||
    LoginRequiredMixin,
 | 
			
		||||
    DjangoPermissionRequiredMixin,
 | 
			
		||||
    CreateAssignPermView,
 | 
			
		||||
):
 | 
			
		||||
    """Create new Inlet"""
 | 
			
		||||
    """Create new Provider"""
 | 
			
		||||
 | 
			
		||||
    model = Inlet
 | 
			
		||||
    permission_required = "passbook_core.add_inlet"
 | 
			
		||||
    model = Provider
 | 
			
		||||
    permission_required = "passbook_core.add_provider"
 | 
			
		||||
 | 
			
		||||
    template_name = "generic/create.html"
 | 
			
		||||
    success_url = reverse_lazy("passbook_admin:inlets")
 | 
			
		||||
    success_message = _("Successfully created Inlet")
 | 
			
		||||
    success_url = reverse_lazy("passbook_admin:providers")
 | 
			
		||||
    success_message = _("Successfully created Provider")
 | 
			
		||||
 | 
			
		||||
    def get_form_class(self):
 | 
			
		||||
        inlet_type = self.request.GET.get("type")
 | 
			
		||||
        model = next(x for x in all_subclasses(Inlet) if x.__name__ == inlet_type)
 | 
			
		||||
        provider_type = self.request.GET.get("type")
 | 
			
		||||
        model = next(x for x in all_subclasses(Provider) if x.__name__ == provider_type)
 | 
			
		||||
        if not model:
 | 
			
		||||
            raise Http404
 | 
			
		||||
        return path_to_class(model.form)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class InletUpdateView(
 | 
			
		||||
class ProviderUpdateView(
 | 
			
		||||
    SuccessMessageMixin, LoginRequiredMixin, PermissionRequiredMixin, UpdateView
 | 
			
		||||
):
 | 
			
		||||
    """Update inlet"""
 | 
			
		||||
    """Update provider"""
 | 
			
		||||
 | 
			
		||||
    model = Inlet
 | 
			
		||||
    permission_required = "passbook_core.change_inlet"
 | 
			
		||||
    model = Provider
 | 
			
		||||
    permission_required = "passbook_core.change_provider"
 | 
			
		||||
 | 
			
		||||
    template_name = "generic/update.html"
 | 
			
		||||
    success_url = reverse_lazy("passbook_admin:inlets")
 | 
			
		||||
    success_message = _("Successfully updated Inlet")
 | 
			
		||||
    success_url = reverse_lazy("passbook_admin:providers")
 | 
			
		||||
    success_message = _("Successfully updated Provider")
 | 
			
		||||
 | 
			
		||||
    def get_form_class(self):
 | 
			
		||||
        form_class_path = self.get_object().form
 | 
			
		||||
@ -77,25 +77,29 @@ class InletUpdateView(
 | 
			
		||||
 | 
			
		||||
    def get_object(self, queryset=None):
 | 
			
		||||
        return (
 | 
			
		||||
            Inlet.objects.filter(pk=self.kwargs.get("pk")).select_subclasses().first()
 | 
			
		||||
            Provider.objects.filter(pk=self.kwargs.get("pk"))
 | 
			
		||||
            .select_subclasses()
 | 
			
		||||
            .first()
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class InletDeleteView(
 | 
			
		||||
class ProviderDeleteView(
 | 
			
		||||
    SuccessMessageMixin, LoginRequiredMixin, PermissionRequiredMixin, DeleteView
 | 
			
		||||
):
 | 
			
		||||
    """Delete inlet"""
 | 
			
		||||
    """Delete provider"""
 | 
			
		||||
 | 
			
		||||
    model = Inlet
 | 
			
		||||
    permission_required = "passbook_core.delete_inlet"
 | 
			
		||||
    model = Provider
 | 
			
		||||
    permission_required = "passbook_core.delete_provider"
 | 
			
		||||
 | 
			
		||||
    template_name = "generic/delete.html"
 | 
			
		||||
    success_url = reverse_lazy("passbook_admin:inlets")
 | 
			
		||||
    success_message = _("Successfully deleted Inlet")
 | 
			
		||||
    success_url = reverse_lazy("passbook_admin:providers")
 | 
			
		||||
    success_message = _("Successfully deleted Provider")
 | 
			
		||||
 | 
			
		||||
    def get_object(self, queryset=None):
 | 
			
		||||
        return (
 | 
			
		||||
            Inlet.objects.filter(pk=self.kwargs.get("pk")).select_subclasses().first()
 | 
			
		||||
            Provider.objects.filter(pk=self.kwargs.get("pk"))
 | 
			
		||||
            .select_subclasses()
 | 
			
		||||
            .first()
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    def delete(self, request, *args, **kwargs):
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
"""passbook Outlet administration"""
 | 
			
		||||
"""passbook Source administration"""
 | 
			
		||||
from django.contrib import messages
 | 
			
		||||
from django.contrib.auth.mixins import LoginRequiredMixin
 | 
			
		||||
from django.contrib.auth.mixins import (
 | 
			
		||||
@ -11,23 +11,23 @@ from django.utils.translation import ugettext as _
 | 
			
		||||
from django.views.generic import DeleteView, ListView, UpdateView
 | 
			
		||||
from guardian.mixins import PermissionListMixin, PermissionRequiredMixin
 | 
			
		||||
 | 
			
		||||
from passbook.core.models import Outlet
 | 
			
		||||
from passbook.core.models import Source
 | 
			
		||||
from passbook.lib.utils.reflection import all_subclasses, path_to_class
 | 
			
		||||
from passbook.lib.views import CreateAssignPermView
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class OutletListView(LoginRequiredMixin, PermissionListMixin, ListView):
 | 
			
		||||
    """Show list of all outlets"""
 | 
			
		||||
class SourceListView(LoginRequiredMixin, PermissionListMixin, ListView):
 | 
			
		||||
    """Show list of all sources"""
 | 
			
		||||
 | 
			
		||||
    model = Outlet
 | 
			
		||||
    permission_required = "passbook_core.add_outlet"
 | 
			
		||||
    template_name = "administration/outlet/list.html"
 | 
			
		||||
    paginate_by = 10
 | 
			
		||||
    ordering = "id"
 | 
			
		||||
    model = Source
 | 
			
		||||
    permission_required = "passbook_core.view_source"
 | 
			
		||||
    ordering = "name"
 | 
			
		||||
    paginate_by = 40
 | 
			
		||||
    template_name = "administration/source/list.html"
 | 
			
		||||
 | 
			
		||||
    def get_context_data(self, **kwargs):
 | 
			
		||||
        kwargs["types"] = {
 | 
			
		||||
            x.__name__: x._meta.verbose_name for x in all_subclasses(Outlet)
 | 
			
		||||
            x.__name__: x._meta.verbose_name for x in all_subclasses(Source)
 | 
			
		||||
        }
 | 
			
		||||
        return super().get_context_data(**kwargs)
 | 
			
		||||
 | 
			
		||||
@ -35,40 +35,40 @@ class OutletListView(LoginRequiredMixin, PermissionListMixin, ListView):
 | 
			
		||||
        return super().get_queryset().select_subclasses()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class OutletCreateView(
 | 
			
		||||
class SourceCreateView(
 | 
			
		||||
    SuccessMessageMixin,
 | 
			
		||||
    LoginRequiredMixin,
 | 
			
		||||
    DjangoPermissionRequiredMixin,
 | 
			
		||||
    CreateAssignPermView,
 | 
			
		||||
):
 | 
			
		||||
    """Create new Outlet"""
 | 
			
		||||
    """Create new Source"""
 | 
			
		||||
 | 
			
		||||
    model = Outlet
 | 
			
		||||
    permission_required = "passbook_core.add_outlet"
 | 
			
		||||
    model = Source
 | 
			
		||||
    permission_required = "passbook_core.add_source"
 | 
			
		||||
 | 
			
		||||
    template_name = "generic/create.html"
 | 
			
		||||
    success_url = reverse_lazy("passbook_admin:outlets")
 | 
			
		||||
    success_message = _("Successfully created Outlet")
 | 
			
		||||
    success_url = reverse_lazy("passbook_admin:sources")
 | 
			
		||||
    success_message = _("Successfully created Source")
 | 
			
		||||
 | 
			
		||||
    def get_form_class(self):
 | 
			
		||||
        outlet_type = self.request.GET.get("type")
 | 
			
		||||
        model = next(x for x in all_subclasses(Outlet) if x.__name__ == outlet_type)
 | 
			
		||||
        source_type = self.request.GET.get("type")
 | 
			
		||||
        model = next(x for x in all_subclasses(Source) if x.__name__ == source_type)
 | 
			
		||||
        if not model:
 | 
			
		||||
            raise Http404
 | 
			
		||||
        return path_to_class(model.form)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class OutletUpdateView(
 | 
			
		||||
class SourceUpdateView(
 | 
			
		||||
    SuccessMessageMixin, LoginRequiredMixin, PermissionRequiredMixin, UpdateView
 | 
			
		||||
):
 | 
			
		||||
    """Update outlet"""
 | 
			
		||||
    """Update source"""
 | 
			
		||||
 | 
			
		||||
    model = Outlet
 | 
			
		||||
    permission_required = "passbook_core.change_outlet"
 | 
			
		||||
    model = Source
 | 
			
		||||
    permission_required = "passbook_core.change_source"
 | 
			
		||||
 | 
			
		||||
    template_name = "generic/update.html"
 | 
			
		||||
    success_url = reverse_lazy("passbook_admin:outlets")
 | 
			
		||||
    success_message = _("Successfully updated Outlet")
 | 
			
		||||
    success_url = reverse_lazy("passbook_admin:sources")
 | 
			
		||||
    success_message = _("Successfully updated Source")
 | 
			
		||||
 | 
			
		||||
    def get_form_class(self):
 | 
			
		||||
        form_class_path = self.get_object().form
 | 
			
		||||
@ -77,25 +77,25 @@ class OutletUpdateView(
 | 
			
		||||
 | 
			
		||||
    def get_object(self, queryset=None):
 | 
			
		||||
        return (
 | 
			
		||||
            Outlet.objects.filter(pk=self.kwargs.get("pk")).select_subclasses().first()
 | 
			
		||||
            Source.objects.filter(pk=self.kwargs.get("pk")).select_subclasses().first()
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class OutletDeleteView(
 | 
			
		||||
class SourceDeleteView(
 | 
			
		||||
    SuccessMessageMixin, LoginRequiredMixin, PermissionRequiredMixin, DeleteView
 | 
			
		||||
):
 | 
			
		||||
    """Delete outlet"""
 | 
			
		||||
    """Delete source"""
 | 
			
		||||
 | 
			
		||||
    model = Outlet
 | 
			
		||||
    permission_required = "passbook_core.delete_outlet"
 | 
			
		||||
    model = Source
 | 
			
		||||
    permission_required = "passbook_core.delete_source"
 | 
			
		||||
 | 
			
		||||
    template_name = "generic/delete.html"
 | 
			
		||||
    success_url = reverse_lazy("passbook_admin:outlets")
 | 
			
		||||
    success_message = _("Successfully deleted Outlet")
 | 
			
		||||
    success_url = reverse_lazy("passbook_admin:sources")
 | 
			
		||||
    success_message = _("Successfully deleted Source")
 | 
			
		||||
 | 
			
		||||
    def get_object(self, queryset=None):
 | 
			
		||||
        return (
 | 
			
		||||
            Outlet.objects.filter(pk=self.kwargs.get("pk")).select_subclasses().first()
 | 
			
		||||
            Source.objects.filter(pk=self.kwargs.get("pk")).select_subclasses().first()
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    def delete(self, request, *args, **kwargs):
 | 
			
		||||
@ -16,7 +16,7 @@ from guardian.mixins import (
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
from passbook.admin.forms.users import UserForm
 | 
			
		||||
from passbook.core.models import Token, User
 | 
			
		||||
from passbook.core.models import Nonce, User
 | 
			
		||||
from passbook.lib.views import CreateAssignPermView
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -92,12 +92,12 @@ class UserPasswordResetView(LoginRequiredMixin, PermissionRequiredMixin, DetailV
 | 
			
		||||
    permission_required = "passbook_core.reset_user_password"
 | 
			
		||||
 | 
			
		||||
    def get(self, request, *args, **kwargs):
 | 
			
		||||
        """Create token for user and return link"""
 | 
			
		||||
        """Create nonce for user and return link"""
 | 
			
		||||
        super().get(request, *args, **kwargs)
 | 
			
		||||
        # TODO: create plan for user, get token
 | 
			
		||||
        token = Token.objects.create(user=self.object)
 | 
			
		||||
        nonce = Nonce.objects.create(user=self.object)
 | 
			
		||||
        link = request.build_absolute_uri(
 | 
			
		||||
            reverse("passbook_flows:default-recovery", kwargs={"token": token.uuid})
 | 
			
		||||
            reverse("passbook_flows:default-recovery", kwargs={"nonce": nonce.uuid})
 | 
			
		||||
        )
 | 
			
		||||
        messages.success(
 | 
			
		||||
            request, _("Password reset link: <pre>%(link)s</pre>" % {"link": link})
 | 
			
		||||
 | 
			
		||||
@ -1,8 +1,8 @@
 | 
			
		||||
"""permission classes for django restframework"""
 | 
			
		||||
from rest_framework.permissions import BasePermission, DjangoObjectPermissions
 | 
			
		||||
 | 
			
		||||
from passbook.core.models import PolicyModel
 | 
			
		||||
from passbook.policies.engine import PolicyEngine
 | 
			
		||||
from passbook.policies.models import PolicyBindingModel
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class CustomObjectPermissions(DjangoObjectPermissions):
 | 
			
		||||
@ -24,7 +24,8 @@ class PolicyPermissions(BasePermission):
 | 
			
		||||
 | 
			
		||||
    policy_engine: PolicyEngine
 | 
			
		||||
 | 
			
		||||
    def has_object_permission(self, request, view, obj: PolicyBindingModel) -> bool:
 | 
			
		||||
        self.policy_engine = PolicyEngine(obj.policies.all(), request.user, request)
 | 
			
		||||
    def has_object_permission(self, request, view, obj: PolicyModel) -> bool:
 | 
			
		||||
        # if not obj.po
 | 
			
		||||
        self.policy_engine = PolicyEngine(obj.policies, request.user, request)
 | 
			
		||||
        self.policy_engine.request.obj = obj
 | 
			
		||||
        return self.policy_engine.build().passing
 | 
			
		||||
 | 
			
		||||
@ -9,18 +9,12 @@ from structlog import get_logger
 | 
			
		||||
 | 
			
		||||
from passbook.api.permissions import CustomObjectPermissions
 | 
			
		||||
from passbook.audit.api import EventViewSet
 | 
			
		||||
from passbook.channels.in_ldap.api import LDAPInletViewSet, LDAPPropertyMappingViewSet
 | 
			
		||||
from passbook.channels.in_oauth.api import OAuthInletViewSet
 | 
			
		||||
from passbook.channels.out_app_gw.api import ApplicationGatewayOutletViewSet
 | 
			
		||||
from passbook.channels.out_oauth.api import OAuth2OutletViewSet
 | 
			
		||||
from passbook.channels.out_oidc.api import OpenIDOutletViewSet
 | 
			
		||||
from passbook.channels.out_saml.api import SAMLOutletViewSet, SAMLPropertyMappingViewSet
 | 
			
		||||
from passbook.core.api.applications import ApplicationViewSet
 | 
			
		||||
from passbook.core.api.groups import GroupViewSet
 | 
			
		||||
from passbook.core.api.inlets import InletViewSet
 | 
			
		||||
from passbook.core.api.outlets import OutletViewSet
 | 
			
		||||
from passbook.core.api.policies import PolicyViewSet
 | 
			
		||||
from passbook.core.api.propertymappings import PropertyMappingViewSet
 | 
			
		||||
from passbook.core.api.providers import ProviderViewSet
 | 
			
		||||
from passbook.core.api.sources import SourceViewSet
 | 
			
		||||
from passbook.core.api.users import UserViewSet
 | 
			
		||||
from passbook.flows.api import FlowStageBindingViewSet, FlowViewSet, StageViewSet
 | 
			
		||||
from passbook.lib.utils.reflection import get_apps
 | 
			
		||||
@ -30,6 +24,12 @@ from passbook.policies.expression.api import ExpressionPolicyViewSet
 | 
			
		||||
from passbook.policies.hibp.api import HaveIBeenPwendPolicyViewSet
 | 
			
		||||
from passbook.policies.password.api import PasswordPolicyViewSet
 | 
			
		||||
from passbook.policies.reputation.api import ReputationPolicyViewSet
 | 
			
		||||
from passbook.providers.app_gw.api import ApplicationGatewayProviderViewSet
 | 
			
		||||
from passbook.providers.oauth.api import OAuth2ProviderViewSet
 | 
			
		||||
from passbook.providers.oidc.api import OpenIDProviderViewSet
 | 
			
		||||
from passbook.providers.saml.api import SAMLPropertyMappingViewSet, SAMLProviderViewSet
 | 
			
		||||
from passbook.sources.ldap.api import LDAPPropertyMappingViewSet, LDAPSourceViewSet
 | 
			
		||||
from passbook.sources.oauth.api import OAuthSourceViewSet
 | 
			
		||||
from passbook.stages.captcha.api import CaptchaStageViewSet
 | 
			
		||||
from passbook.stages.email.api import EmailStageViewSet
 | 
			
		||||
from passbook.stages.identification.api import IdentificationStageViewSet
 | 
			
		||||
@ -57,15 +57,9 @@ router.register("core/users", UserViewSet)
 | 
			
		||||
 | 
			
		||||
router.register("audit/events", EventViewSet)
 | 
			
		||||
 | 
			
		||||
router.register("inlets/all", InletViewSet)
 | 
			
		||||
router.register("inlets/ldap", LDAPInletViewSet)
 | 
			
		||||
router.register("inlets/oauth", OAuthInletViewSet)
 | 
			
		||||
 | 
			
		||||
router.register("outlets/all", OutletViewSet)
 | 
			
		||||
router.register("outlets/applicationgateway", ApplicationGatewayOutletViewSet)
 | 
			
		||||
router.register("outlets/oauth", OAuth2OutletViewSet)
 | 
			
		||||
router.register("outlets/openid", OpenIDOutletViewSet)
 | 
			
		||||
router.register("outlets/saml", SAMLOutletViewSet)
 | 
			
		||||
router.register("sources/all", SourceViewSet)
 | 
			
		||||
router.register("sources/ldap", LDAPSourceViewSet)
 | 
			
		||||
router.register("sources/oauth", OAuthSourceViewSet)
 | 
			
		||||
 | 
			
		||||
router.register("policies/all", PolicyViewSet)
 | 
			
		||||
router.register("policies/bindings", PolicyBindingViewSet)
 | 
			
		||||
@ -75,6 +69,12 @@ router.register("policies/password", PasswordPolicyViewSet)
 | 
			
		||||
router.register("policies/passwordexpiry", PasswordExpiryPolicyViewSet)
 | 
			
		||||
router.register("policies/reputation", ReputationPolicyViewSet)
 | 
			
		||||
 | 
			
		||||
router.register("providers/all", ProviderViewSet)
 | 
			
		||||
router.register("providers/applicationgateway", ApplicationGatewayProviderViewSet)
 | 
			
		||||
router.register("providers/oauth", OAuth2ProviderViewSet)
 | 
			
		||||
router.register("providers/openid", OpenIDProviderViewSet)
 | 
			
		||||
router.register("providers/saml", SAMLProviderViewSet)
 | 
			
		||||
 | 
			
		||||
router.register("propertymappings/all", PropertyMappingViewSet)
 | 
			
		||||
router.register("propertymappings/ldap", LDAPPropertyMappingViewSet)
 | 
			
		||||
router.register("propertymappings/saml", SAMLPropertyMappingViewSet)
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
# Generated by Django 3.0.5 on 2020-05-15 19:58
 | 
			
		||||
# Generated by Django 2.2.6 on 2019-10-07 14:07
 | 
			
		||||
 | 
			
		||||
import uuid
 | 
			
		||||
 | 
			
		||||
@ -18,7 +18,7 @@ class Migration(migrations.Migration):
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
        migrations.CreateModel(
 | 
			
		||||
            name="Event",
 | 
			
		||||
            name="AuditEntry",
 | 
			
		||||
            fields=[
 | 
			
		||||
                (
 | 
			
		||||
                    "uuid",
 | 
			
		||||
@ -33,16 +33,15 @@ class Migration(migrations.Migration):
 | 
			
		||||
                    "action",
 | 
			
		||||
                    models.TextField(
 | 
			
		||||
                        choices=[
 | 
			
		||||
                            ("LOGIN", "login"),
 | 
			
		||||
                            ("LOGIN_FAILED", "login_failed"),
 | 
			
		||||
                            ("LOGOUT", "logout"),
 | 
			
		||||
                            ("AUTHORIZE_APPLICATION", "authorize_application"),
 | 
			
		||||
                            ("SUSPICIOUS_REQUEST", "suspicious_request"),
 | 
			
		||||
                            ("SIGN_UP", "sign_up"),
 | 
			
		||||
                            ("PASSWORD_RESET", "password_reset"),
 | 
			
		||||
                            ("INVITE_CREATED", "invitation_created"),
 | 
			
		||||
                            ("INVITE_USED", "invitation_used"),
 | 
			
		||||
                            ("CUSTOM", "custom"),
 | 
			
		||||
                            ("login", "login"),
 | 
			
		||||
                            ("login_failed", "login_failed"),
 | 
			
		||||
                            ("logout", "logout"),
 | 
			
		||||
                            ("authorize_application", "authorize_application"),
 | 
			
		||||
                            ("suspicious_request", "suspicious_request"),
 | 
			
		||||
                            ("sign_up", "sign_up"),
 | 
			
		||||
                            ("password_reset", "password_reset"),
 | 
			
		||||
                            ("invitation_created", "invitation_created"),
 | 
			
		||||
                            ("invitation_used", "invitation_used"),
 | 
			
		||||
                        ]
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
@ -54,7 +53,7 @@ class Migration(migrations.Migration):
 | 
			
		||||
                        blank=True, default=dict
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
                ("client_ip", models.GenericIPAddressField(null=True)),
 | 
			
		||||
                ("request_ip", models.GenericIPAddressField()),
 | 
			
		||||
                ("created", models.DateTimeField(auto_now_add=True)),
 | 
			
		||||
                (
 | 
			
		||||
                    "user",
 | 
			
		||||
@ -66,8 +65,8 @@ class Migration(migrations.Migration):
 | 
			
		||||
                ),
 | 
			
		||||
            ],
 | 
			
		||||
            options={
 | 
			
		||||
                "verbose_name": "Audit Event",
 | 
			
		||||
                "verbose_name_plural": "Audit Events",
 | 
			
		||||
                "verbose_name": "Audit Entry",
 | 
			
		||||
                "verbose_name_plural": "Audit Entries",
 | 
			
		||||
            },
 | 
			
		||||
        ),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										16
									
								
								passbook/audit/migrations/0002_auto_20191028_0829.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								passbook/audit/migrations/0002_auto_20191028_0829.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,16 @@
 | 
			
		||||
# Generated by Django 2.2.6 on 2019-10-28 08:29
 | 
			
		||||
 | 
			
		||||
from django.conf import settings
 | 
			
		||||
from django.db import migrations
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Migration(migrations.Migration):
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
 | 
			
		||||
        ("passbook_audit", "0001_initial"),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
        migrations.RenameModel(old_name="AuditEntry", new_name="Event",),
 | 
			
		||||
    ]
 | 
			
		||||
							
								
								
									
										40
									
								
								passbook/audit/migrations/0003_auto_20191205_1407.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								passbook/audit/migrations/0003_auto_20191205_1407.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,40 @@
 | 
			
		||||
# Generated by Django 2.2.8 on 2019-12-05 14:07
 | 
			
		||||
 | 
			
		||||
from django.db import migrations, models
 | 
			
		||||
 | 
			
		||||
import passbook.audit.models
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Migration(migrations.Migration):
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        ("passbook_audit", "0002_auto_20191028_0829"),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
        migrations.AlterModelOptions(
 | 
			
		||||
            name="event",
 | 
			
		||||
            options={
 | 
			
		||||
                "verbose_name": "Audit Event",
 | 
			
		||||
                "verbose_name_plural": "Audit Events",
 | 
			
		||||
            },
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.AlterField(
 | 
			
		||||
            model_name="event",
 | 
			
		||||
            name="action",
 | 
			
		||||
            field=models.TextField(
 | 
			
		||||
                choices=[
 | 
			
		||||
                    ("LOGIN", "login"),
 | 
			
		||||
                    ("LOGIN_FAILED", "login_failed"),
 | 
			
		||||
                    ("LOGOUT", "logout"),
 | 
			
		||||
                    ("AUTHORIZE_APPLICATION", "authorize_application"),
 | 
			
		||||
                    ("SUSPICIOUS_REQUEST", "suspicious_request"),
 | 
			
		||||
                    ("SIGN_UP", "sign_up"),
 | 
			
		||||
                    ("PASSWORD_RESET", "password_reset"),
 | 
			
		||||
                    ("INVITE_CREATED", "invitation_created"),
 | 
			
		||||
                    ("INVITE_USED", "invitation_used"),
 | 
			
		||||
                    ("CUSTOM", "custom"),
 | 
			
		||||
                ]
 | 
			
		||||
            ),
 | 
			
		||||
        ),
 | 
			
		||||
    ]
 | 
			
		||||
							
								
								
									
										19
									
								
								passbook/audit/migrations/0004_auto_20191205_1502.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								passbook/audit/migrations/0004_auto_20191205_1502.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,19 @@
 | 
			
		||||
# Generated by Django 2.2.8 on 2019-12-05 15:02
 | 
			
		||||
 | 
			
		||||
from django.db import migrations, models
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Migration(migrations.Migration):
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        ("passbook_audit", "0003_auto_20191205_1407"),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
        migrations.RemoveField(model_name="event", name="request_ip",),
 | 
			
		||||
        migrations.AddField(
 | 
			
		||||
            model_name="event",
 | 
			
		||||
            name="client_ip",
 | 
			
		||||
            field=models.GenericIPAddressField(null=True),
 | 
			
		||||
        ),
 | 
			
		||||
    ]
 | 
			
		||||
@ -5,7 +5,7 @@ from django.test import TestCase
 | 
			
		||||
from guardian.shortcuts import get_anonymous_user
 | 
			
		||||
 | 
			
		||||
from passbook.audit.models import Event, EventAction
 | 
			
		||||
from passbook.policies.models import Policy
 | 
			
		||||
from passbook.core.models import Policy
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TestAuditEvent(TestCase):
 | 
			
		||||
 | 
			
		||||
@ -1,11 +0,0 @@
 | 
			
		||||
"""Passbook ldap app config"""
 | 
			
		||||
 | 
			
		||||
from django.apps import AppConfig
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class PassbookInletLDAPConfig(AppConfig):
 | 
			
		||||
    """Passbook ldap app config"""
 | 
			
		||||
 | 
			
		||||
    name = "passbook.channels.in_ldap"
 | 
			
		||||
    label = "passbook_channels_in_ldap"
 | 
			
		||||
    verbose_name = "passbook Inlets.LDAP"
 | 
			
		||||
@ -1,33 +0,0 @@
 | 
			
		||||
"""LDAP Sync tasks"""
 | 
			
		||||
from passbook.channels.in_ldap.connector import Connector
 | 
			
		||||
from passbook.channels.in_ldap.models import LDAPInlet
 | 
			
		||||
from passbook.root.celery import CELERY_APP
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@CELERY_APP.task()
 | 
			
		||||
def sync_groups(inlet_pk: int):
 | 
			
		||||
    """Sync LDAP Groups on background worker"""
 | 
			
		||||
    inlet = LDAPInlet.objects.get(pk=inlet_pk)
 | 
			
		||||
    connector = Connector(inlet)
 | 
			
		||||
    connector.bind()
 | 
			
		||||
    connector.sync_groups()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@CELERY_APP.task()
 | 
			
		||||
def sync_users(inlet_pk: int):
 | 
			
		||||
    """Sync LDAP Users on background worker"""
 | 
			
		||||
    inlet = LDAPInlet.objects.get(pk=inlet_pk)
 | 
			
		||||
    connector = Connector(inlet)
 | 
			
		||||
    connector.bind()
 | 
			
		||||
    connector.sync_users()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@CELERY_APP.task()
 | 
			
		||||
def sync():
 | 
			
		||||
    """Sync all inlets"""
 | 
			
		||||
    for inlet in LDAPInlet.objects.filter(enabled=True):
 | 
			
		||||
        connector = Connector(inlet)
 | 
			
		||||
        connector.bind()
 | 
			
		||||
        connector.sync_users()
 | 
			
		||||
        connector.sync_groups()
 | 
			
		||||
        connector.sync_membership()
 | 
			
		||||
@ -1,29 +0,0 @@
 | 
			
		||||
"""OAuth Inlet Serializer"""
 | 
			
		||||
from rest_framework.serializers import ModelSerializer
 | 
			
		||||
from rest_framework.viewsets import ModelViewSet
 | 
			
		||||
 | 
			
		||||
from passbook.admin.forms.inlet import INLET_SERIALIZER_FIELDS
 | 
			
		||||
from passbook.channels.in_oauth.models import OAuthInlet
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class OAuthInletSerializer(ModelSerializer):
 | 
			
		||||
    """OAuth Inlet Serializer"""
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
        model = OAuthInlet
 | 
			
		||||
        fields = INLET_SERIALIZER_FIELDS + [
 | 
			
		||||
            "inlet_type",
 | 
			
		||||
            "request_token_url",
 | 
			
		||||
            "authorization_url",
 | 
			
		||||
            "access_token_url",
 | 
			
		||||
            "profile_url",
 | 
			
		||||
            "consumer_key",
 | 
			
		||||
            "consumer_secret",
 | 
			
		||||
        ]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class OAuthInletViewSet(ModelViewSet):
 | 
			
		||||
    """Inlet Viewset"""
 | 
			
		||||
 | 
			
		||||
    queryset = OAuthInlet.objects.all()
 | 
			
		||||
    serializer_class = OAuthInletSerializer
 | 
			
		||||
@ -1,24 +0,0 @@
 | 
			
		||||
"""passbook oauth_client Authorization backend"""
 | 
			
		||||
 | 
			
		||||
from django.contrib.auth.backends import ModelBackend
 | 
			
		||||
from django.db.models import Q
 | 
			
		||||
 | 
			
		||||
from passbook.channels.in_oauth.models import OAuthInlet, UserOAuthInletConnection
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AuthorizedServiceBackend(ModelBackend):
 | 
			
		||||
    "Authentication backend for users registered with remote OAuth provider."
 | 
			
		||||
 | 
			
		||||
    def authenticate(self, request, inlet=None, identifier=None):
 | 
			
		||||
        "Fetch user for a given inlet by id."
 | 
			
		||||
        inlet_q = Q(inlet__name=inlet)
 | 
			
		||||
        if isinstance(inlet, OAuthInlet):
 | 
			
		||||
            inlet_q = Q(inlet=inlet)
 | 
			
		||||
        try:
 | 
			
		||||
            access = UserOAuthInletConnection.objects.filter(
 | 
			
		||||
                inlet_q, identifier=identifier
 | 
			
		||||
            ).select_related("user")[0]
 | 
			
		||||
        except IndexError:
 | 
			
		||||
            return None
 | 
			
		||||
        else:
 | 
			
		||||
            return access.user
 | 
			
		||||
@ -1,81 +0,0 @@
 | 
			
		||||
# Generated by Django 3.0.5 on 2020-05-15 19:59
 | 
			
		||||
 | 
			
		||||
import django.db.models.deletion
 | 
			
		||||
from django.db import migrations, models
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Migration(migrations.Migration):
 | 
			
		||||
 | 
			
		||||
    initial = True
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        ("passbook_core", "__first__"),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
        migrations.CreateModel(
 | 
			
		||||
            name="OAuthInlet",
 | 
			
		||||
            fields=[
 | 
			
		||||
                (
 | 
			
		||||
                    "inlet_ptr",
 | 
			
		||||
                    models.OneToOneField(
 | 
			
		||||
                        auto_created=True,
 | 
			
		||||
                        on_delete=django.db.models.deletion.CASCADE,
 | 
			
		||||
                        parent_link=True,
 | 
			
		||||
                        primary_key=True,
 | 
			
		||||
                        serialize=False,
 | 
			
		||||
                        to="passbook_core.Inlet",
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
                ("inlet_type", models.CharField(max_length=255)),
 | 
			
		||||
                (
 | 
			
		||||
                    "request_token_url",
 | 
			
		||||
                    models.CharField(
 | 
			
		||||
                        blank=True, max_length=255, verbose_name="Request Token URL"
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
                (
 | 
			
		||||
                    "authorization_url",
 | 
			
		||||
                    models.CharField(max_length=255, verbose_name="Authorization URL"),
 | 
			
		||||
                ),
 | 
			
		||||
                (
 | 
			
		||||
                    "access_token_url",
 | 
			
		||||
                    models.CharField(max_length=255, verbose_name="Access Token URL"),
 | 
			
		||||
                ),
 | 
			
		||||
                (
 | 
			
		||||
                    "profile_url",
 | 
			
		||||
                    models.CharField(max_length=255, verbose_name="Profile URL"),
 | 
			
		||||
                ),
 | 
			
		||||
                ("consumer_key", models.TextField()),
 | 
			
		||||
                ("consumer_secret", models.TextField()),
 | 
			
		||||
            ],
 | 
			
		||||
            options={
 | 
			
		||||
                "verbose_name": "Generic OAuth Inlet",
 | 
			
		||||
                "verbose_name_plural": "Generic OAuth Inlets",
 | 
			
		||||
            },
 | 
			
		||||
            bases=("passbook_core.inlet",),
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.CreateModel(
 | 
			
		||||
            name="UserOAuthInletConnection",
 | 
			
		||||
            fields=[
 | 
			
		||||
                (
 | 
			
		||||
                    "userinletconnection_ptr",
 | 
			
		||||
                    models.OneToOneField(
 | 
			
		||||
                        auto_created=True,
 | 
			
		||||
                        on_delete=django.db.models.deletion.CASCADE,
 | 
			
		||||
                        parent_link=True,
 | 
			
		||||
                        primary_key=True,
 | 
			
		||||
                        serialize=False,
 | 
			
		||||
                        to="passbook_core.UserInletConnection",
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
                ("identifier", models.CharField(max_length=255)),
 | 
			
		||||
                ("access_token", models.TextField(blank=True, default=None, null=True)),
 | 
			
		||||
            ],
 | 
			
		||||
            options={
 | 
			
		||||
                "verbose_name": "User OAuth Inlet Connection",
 | 
			
		||||
                "verbose_name_plural": "User OAuth Inlet Connections",
 | 
			
		||||
            },
 | 
			
		||||
            bases=("passbook_core.userinletconnection",),
 | 
			
		||||
        ),
 | 
			
		||||
    ]
 | 
			
		||||
@ -1,159 +0,0 @@
 | 
			
		||||
"""OAuth Client models"""
 | 
			
		||||
 | 
			
		||||
from django.db import models
 | 
			
		||||
from django.urls import reverse, reverse_lazy
 | 
			
		||||
from django.utils.translation import gettext_lazy as _
 | 
			
		||||
 | 
			
		||||
from passbook.channels.in_oauth.clients import get_client
 | 
			
		||||
from passbook.core.models import Inlet, UserInletConnection
 | 
			
		||||
from passbook.core.types import UILoginButton, UIUserSettings
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class OAuthInlet(Inlet):
 | 
			
		||||
    """Configuration for OAuth inlet."""
 | 
			
		||||
 | 
			
		||||
    inlet_type = models.CharField(max_length=255)
 | 
			
		||||
    request_token_url = models.CharField(
 | 
			
		||||
        blank=True, max_length=255, verbose_name=_("Request Token URL")
 | 
			
		||||
    )
 | 
			
		||||
    authorization_url = models.CharField(
 | 
			
		||||
        max_length=255, verbose_name=_("Authorization URL")
 | 
			
		||||
    )
 | 
			
		||||
    access_token_url = models.CharField(
 | 
			
		||||
        max_length=255, verbose_name=_("Access Token URL")
 | 
			
		||||
    )
 | 
			
		||||
    profile_url = models.CharField(max_length=255, verbose_name=_("Profile URL"))
 | 
			
		||||
    consumer_key = models.TextField()
 | 
			
		||||
    consumer_secret = models.TextField()
 | 
			
		||||
 | 
			
		||||
    form = "passbook.channels.in_oauth.forms.OAuthInletForm"
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def ui_login_button(self) -> UILoginButton:
 | 
			
		||||
        return UILoginButton(
 | 
			
		||||
            url=reverse_lazy(
 | 
			
		||||
                "passbook_channels_in_oauth:oauth-client-login",
 | 
			
		||||
                kwargs={"inlet_slug": self.slug},
 | 
			
		||||
            ),
 | 
			
		||||
            icon_path=f"passbook/inlets/{self.inlet_type}.svg",
 | 
			
		||||
            name=self.name,
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def ui_additional_info(self) -> str:
 | 
			
		||||
        url = reverse_lazy(
 | 
			
		||||
            "passbook_channels_in_oauth:oauth-client-callback",
 | 
			
		||||
            kwargs={"inlet_slug": self.slug},
 | 
			
		||||
        )
 | 
			
		||||
        return f"Callback URL: <pre>{url}</pre>"
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def ui_user_settings(self) -> UIUserSettings:
 | 
			
		||||
        icon_type = self.inlet_type
 | 
			
		||||
        if icon_type == "azure ad":
 | 
			
		||||
            icon_type = "windows"
 | 
			
		||||
        icon_class = f"fab fa-{icon_type}"
 | 
			
		||||
        view_name = "passbook_channels_in_oauth:oauth-client-user"
 | 
			
		||||
        return UIUserSettings(
 | 
			
		||||
            name=self.name,
 | 
			
		||||
            icon=icon_class,
 | 
			
		||||
            view_name=reverse((view_name), kwargs={"inlet_slug": self.slug}),
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
 | 
			
		||||
        verbose_name = _("Generic OAuth Inlet")
 | 
			
		||||
        verbose_name_plural = _("Generic OAuth Inlets")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class GitHubOAuthInlet(OAuthInlet):
 | 
			
		||||
    """Abstract subclass of OAuthInlet to specify GitHub Form"""
 | 
			
		||||
 | 
			
		||||
    form = "passbook.channels.in_oauth.forms.GitHubOAuthInletForm"
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
 | 
			
		||||
        abstract = True
 | 
			
		||||
        verbose_name = _("GitHub OAuth Inlet")
 | 
			
		||||
        verbose_name_plural = _("GitHub OAuth Inlets")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TwitterOAuthInlet(OAuthInlet):
 | 
			
		||||
    """Abstract subclass of OAuthInlet to specify Twitter Form"""
 | 
			
		||||
 | 
			
		||||
    form = "passbook.channels.in_oauth.forms.TwitterOAuthInletForm"
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
 | 
			
		||||
        abstract = True
 | 
			
		||||
        verbose_name = _("Twitter OAuth Inlet")
 | 
			
		||||
        verbose_name_plural = _("Twitter OAuth Inlets")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class FacebookOAuthInlet(OAuthInlet):
 | 
			
		||||
    """Abstract subclass of OAuthInlet to specify Facebook Form"""
 | 
			
		||||
 | 
			
		||||
    form = "passbook.channels.in_oauth.forms.FacebookOAuthInletForm"
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
 | 
			
		||||
        abstract = True
 | 
			
		||||
        verbose_name = _("Facebook OAuth Inlet")
 | 
			
		||||
        verbose_name_plural = _("Facebook OAuth Inlets")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DiscordOAuthInlet(OAuthInlet):
 | 
			
		||||
    """Abstract subclass of OAuthInlet to specify Discord Form"""
 | 
			
		||||
 | 
			
		||||
    form = "passbook.channels.in_oauth.forms.DiscordOAuthInletForm"
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
 | 
			
		||||
        abstract = True
 | 
			
		||||
        verbose_name = _("Discord OAuth Inlet")
 | 
			
		||||
        verbose_name_plural = _("Discord OAuth Inlets")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class GoogleOAuthInlet(OAuthInlet):
 | 
			
		||||
    """Abstract subclass of OAuthInlet to specify Google Form"""
 | 
			
		||||
 | 
			
		||||
    form = "passbook.channels.in_oauth.forms.GoogleOAuthInletForm"
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
 | 
			
		||||
        abstract = True
 | 
			
		||||
        verbose_name = _("Google OAuth Inlet")
 | 
			
		||||
        verbose_name_plural = _("Google OAuth Inlets")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AzureADOAuthInlet(OAuthInlet):
 | 
			
		||||
    """Abstract subclass of OAuthInlet to specify AzureAD Form"""
 | 
			
		||||
 | 
			
		||||
    form = "passbook.channels.in_oauth.forms.AzureADOAuthInletForm"
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
 | 
			
		||||
        abstract = True
 | 
			
		||||
        verbose_name = _("Azure AD OAuth Inlet")
 | 
			
		||||
        verbose_name_plural = _("Azure AD OAuth Inlets")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class UserOAuthInletConnection(UserInletConnection):
 | 
			
		||||
    """Authorized remote OAuth inlet."""
 | 
			
		||||
 | 
			
		||||
    identifier = models.CharField(max_length=255)
 | 
			
		||||
    access_token = models.TextField(blank=True, null=True, default=None)
 | 
			
		||||
 | 
			
		||||
    def save(self, *args, **kwargs):
 | 
			
		||||
        self.access_token = self.access_token or None
 | 
			
		||||
        super().save(*args, **kwargs)
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def api_client(self):
 | 
			
		||||
        """Get API Client"""
 | 
			
		||||
        return get_client(self.inlet, self.access_token or "")
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
 | 
			
		||||
        verbose_name = _("User OAuth Inlet Connection")
 | 
			
		||||
        verbose_name_plural = _("User OAuth Inlet Connections")
 | 
			
		||||
@ -1,15 +0,0 @@
 | 
			
		||||
"""Oauth2 Client Settings"""
 | 
			
		||||
 | 
			
		||||
AUTHENTICATION_BACKENDS = [
 | 
			
		||||
    "passbook.channels.in_oauth.backends.AuthorizedServiceBackend",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
PASSBOOK_SOURCES_OAUTH_TYPES = [
 | 
			
		||||
    "passbook.channels.in_oauth.types.discord",
 | 
			
		||||
    "passbook.channels.in_oauth.types.facebook",
 | 
			
		||||
    "passbook.channels.in_oauth.types.github",
 | 
			
		||||
    "passbook.channels.in_oauth.types.google",
 | 
			
		||||
    "passbook.channels.in_oauth.types.reddit",
 | 
			
		||||
    "passbook.channels.in_oauth.types.twitter",
 | 
			
		||||
    "passbook.channels.in_oauth.types.azure_ad",
 | 
			
		||||
]
 | 
			
		||||
@ -1,28 +0,0 @@
 | 
			
		||||
"""SAMLInlet API Views"""
 | 
			
		||||
from rest_framework.serializers import ModelSerializer
 | 
			
		||||
from rest_framework.viewsets import ModelViewSet
 | 
			
		||||
 | 
			
		||||
from passbook.channels.in_saml.models import SAMLInlet
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class SAMLInletSerializer(ModelSerializer):
 | 
			
		||||
    """SAMLInlet Serializer"""
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
 | 
			
		||||
        model = SAMLInlet
 | 
			
		||||
        fields = [
 | 
			
		||||
            "pk",
 | 
			
		||||
            "issuer",
 | 
			
		||||
            "idp_url",
 | 
			
		||||
            "idp_logout_url",
 | 
			
		||||
            "auto_logout",
 | 
			
		||||
            "signing_kp",
 | 
			
		||||
        ]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class SAMLInletViewSet(ModelViewSet):
 | 
			
		||||
    """SAMLInlet Viewset"""
 | 
			
		||||
 | 
			
		||||
    queryset = SAMLInlet.objects.all()
 | 
			
		||||
    serializer_class = SAMLInletSerializer
 | 
			
		||||
@ -1,12 +0,0 @@
 | 
			
		||||
"""Passbook SAML app config"""
 | 
			
		||||
 | 
			
		||||
from django.apps import AppConfig
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class PassbookInletSAMLConfig(AppConfig):
 | 
			
		||||
    """passbook saml_idp app config"""
 | 
			
		||||
 | 
			
		||||
    name = "passbook.channels.in_saml"
 | 
			
		||||
    label = "passbook_channels_in_saml"
 | 
			
		||||
    verbose_name = "passbook Inlets.SAML"
 | 
			
		||||
    mountpoint = "source/saml/"
 | 
			
		||||
@ -1,68 +0,0 @@
 | 
			
		||||
# Generated by Django 3.0.5 on 2020-05-15 19:59
 | 
			
		||||
 | 
			
		||||
import django.db.models.deletion
 | 
			
		||||
from django.db import migrations, models
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Migration(migrations.Migration):
 | 
			
		||||
 | 
			
		||||
    initial = True
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        ("passbook_crypto", "0001_initial"),
 | 
			
		||||
        ("passbook_core", "__first__"),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
        migrations.CreateModel(
 | 
			
		||||
            name="SAMLInlet",
 | 
			
		||||
            fields=[
 | 
			
		||||
                (
 | 
			
		||||
                    "inlet_ptr",
 | 
			
		||||
                    models.OneToOneField(
 | 
			
		||||
                        auto_created=True,
 | 
			
		||||
                        on_delete=django.db.models.deletion.CASCADE,
 | 
			
		||||
                        parent_link=True,
 | 
			
		||||
                        primary_key=True,
 | 
			
		||||
                        serialize=False,
 | 
			
		||||
                        to="passbook_core.Inlet",
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
                (
 | 
			
		||||
                    "issuer",
 | 
			
		||||
                    models.TextField(
 | 
			
		||||
                        blank=True,
 | 
			
		||||
                        default=None,
 | 
			
		||||
                        help_text="Also known as Entity ID. Defaults the Metadata URL.",
 | 
			
		||||
                        verbose_name="Issuer",
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
                ("idp_url", models.URLField(verbose_name="IDP URL")),
 | 
			
		||||
                (
 | 
			
		||||
                    "idp_logout_url",
 | 
			
		||||
                    models.URLField(
 | 
			
		||||
                        blank=True,
 | 
			
		||||
                        default=None,
 | 
			
		||||
                        null=True,
 | 
			
		||||
                        verbose_name="IDP Logout URL",
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
                ("auto_logout", models.BooleanField(default=False)),
 | 
			
		||||
                (
 | 
			
		||||
                    "signing_kp",
 | 
			
		||||
                    models.ForeignKey(
 | 
			
		||||
                        default=None,
 | 
			
		||||
                        help_text="Certificate Key Pair of the IdP which Assertions are validated against.",
 | 
			
		||||
                        null=True,
 | 
			
		||||
                        on_delete=django.db.models.deletion.SET_NULL,
 | 
			
		||||
                        to="passbook_crypto.CertificateKeyPair",
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
            ],
 | 
			
		||||
            options={
 | 
			
		||||
                "verbose_name": "SAML Inlet",
 | 
			
		||||
                "verbose_name_plural": "SAML Inlets",
 | 
			
		||||
            },
 | 
			
		||||
            bases=("passbook_core.inlet",),
 | 
			
		||||
        ),
 | 
			
		||||
    ]
 | 
			
		||||
@ -1,20 +0,0 @@
 | 
			
		||||
"""saml sp helpers"""
 | 
			
		||||
from django.http import HttpRequest
 | 
			
		||||
from django.shortcuts import reverse
 | 
			
		||||
 | 
			
		||||
from passbook.channels.in_saml.models import SAMLInlet
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def get_issuer(request: HttpRequest, inlet: SAMLInlet) -> str:
 | 
			
		||||
    """Get Inlet's Issuer, falling back to our Metadata URL if none is set"""
 | 
			
		||||
    issuer = inlet.issuer
 | 
			
		||||
    if issuer is None:
 | 
			
		||||
        return build_full_url("metadata", request, inlet)
 | 
			
		||||
    return issuer
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def build_full_url(view: str, request: HttpRequest, inlet: SAMLInlet) -> str:
 | 
			
		||||
    """Build Full ACS URL to be used in IDP"""
 | 
			
		||||
    return request.build_absolute_uri(
 | 
			
		||||
        reverse(f"passbook_channels_in_saml:{view}", kwargs={"inlet_slug": inlet.slug})
 | 
			
		||||
    )
 | 
			
		||||
@ -1,29 +0,0 @@
 | 
			
		||||
"""OAuth2Outlet API Views"""
 | 
			
		||||
from rest_framework.serializers import ModelSerializer
 | 
			
		||||
from rest_framework.viewsets import ModelViewSet
 | 
			
		||||
 | 
			
		||||
from passbook.channels.out_oauth.models import OAuth2Outlet
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class OAuth2OutletSerializer(ModelSerializer):
 | 
			
		||||
    """OAuth2Outlet Serializer"""
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
 | 
			
		||||
        model = OAuth2Outlet
 | 
			
		||||
        fields = [
 | 
			
		||||
            "pk",
 | 
			
		||||
            "name",
 | 
			
		||||
            "redirect_uris",
 | 
			
		||||
            "client_type",
 | 
			
		||||
            "authorization_grant_type",
 | 
			
		||||
            "client_id",
 | 
			
		||||
            "client_secret",
 | 
			
		||||
        ]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class OAuth2OutletViewSet(ModelViewSet):
 | 
			
		||||
    """OAuth2Outlet Viewset"""
 | 
			
		||||
 | 
			
		||||
    queryset = OAuth2Outlet.objects.all()
 | 
			
		||||
    serializer_class = OAuth2OutletSerializer
 | 
			
		||||
@ -1,12 +0,0 @@
 | 
			
		||||
"""passbook auth oauth provider app config"""
 | 
			
		||||
 | 
			
		||||
from django.apps import AppConfig
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class PassbookOutletOAuthConfig(AppConfig):
 | 
			
		||||
    """passbook auth oauth provider app config"""
 | 
			
		||||
 | 
			
		||||
    name = "passbook.channels.out_oauth"
 | 
			
		||||
    label = "passbook_channels_out_oauth"
 | 
			
		||||
    verbose_name = "passbook Outlets.OAuth"
 | 
			
		||||
    mountpoint = ""
 | 
			
		||||
@ -1,9 +0,0 @@
 | 
			
		||||
"""passbook OIDC Provider"""
 | 
			
		||||
 | 
			
		||||
INSTALLED_APPS = [
 | 
			
		||||
    "oidc_provider",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
OIDC_AFTER_USERLOGIN_HOOK = "passbook.channels.out_oidc.auth.check_permissions"
 | 
			
		||||
OIDC_IDTOKEN_INCLUDE_CLAIMS = True
 | 
			
		||||
OIDC_USERINFO = "passbook.channels.out_oidc.claims.userinfo"
 | 
			
		||||
@ -1,140 +0,0 @@
 | 
			
		||||
# Generated by Django 3.0.5 on 2020-05-15 19:59
 | 
			
		||||
 | 
			
		||||
import django.db.models.deletion
 | 
			
		||||
from django.db import migrations, models
 | 
			
		||||
 | 
			
		||||
import passbook.channels.out_saml.utils.time
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Migration(migrations.Migration):
 | 
			
		||||
 | 
			
		||||
    initial = True
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        ("passbook_core", "__first__"),
 | 
			
		||||
        ("passbook_crypto", "0001_initial"),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
        migrations.CreateModel(
 | 
			
		||||
            name="SAMLPropertyMapping",
 | 
			
		||||
            fields=[
 | 
			
		||||
                (
 | 
			
		||||
                    "propertymapping_ptr",
 | 
			
		||||
                    models.OneToOneField(
 | 
			
		||||
                        auto_created=True,
 | 
			
		||||
                        on_delete=django.db.models.deletion.CASCADE,
 | 
			
		||||
                        parent_link=True,
 | 
			
		||||
                        primary_key=True,
 | 
			
		||||
                        serialize=False,
 | 
			
		||||
                        to="passbook_core.PropertyMapping",
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
                ("saml_name", models.TextField(verbose_name="SAML Name")),
 | 
			
		||||
                (
 | 
			
		||||
                    "friendly_name",
 | 
			
		||||
                    models.TextField(blank=True, default=None, null=True),
 | 
			
		||||
                ),
 | 
			
		||||
            ],
 | 
			
		||||
            options={
 | 
			
		||||
                "verbose_name": "SAML Property Mapping",
 | 
			
		||||
                "verbose_name_plural": "SAML Property Mappings",
 | 
			
		||||
            },
 | 
			
		||||
            bases=("passbook_core.propertymapping",),
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.CreateModel(
 | 
			
		||||
            name="SAMLOutlet",
 | 
			
		||||
            fields=[
 | 
			
		||||
                (
 | 
			
		||||
                    "outlet_ptr",
 | 
			
		||||
                    models.OneToOneField(
 | 
			
		||||
                        auto_created=True,
 | 
			
		||||
                        on_delete=django.db.models.deletion.CASCADE,
 | 
			
		||||
                        parent_link=True,
 | 
			
		||||
                        primary_key=True,
 | 
			
		||||
                        serialize=False,
 | 
			
		||||
                        to="passbook_core.Outlet",
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
                ("name", models.TextField()),
 | 
			
		||||
                ("processor_path", models.CharField(choices=[], max_length=255)),
 | 
			
		||||
                ("acs_url", models.URLField(verbose_name="ACS URL")),
 | 
			
		||||
                ("audience", models.TextField(default="")),
 | 
			
		||||
                ("issuer", models.TextField(help_text="Also known as EntityID")),
 | 
			
		||||
                (
 | 
			
		||||
                    "assertion_valid_not_before",
 | 
			
		||||
                    models.TextField(
 | 
			
		||||
                        default="minutes=-5",
 | 
			
		||||
                        help_text="Assertion valid not before current time + this value (Format: hours=-1;minutes=-2;seconds=-3).",
 | 
			
		||||
                        validators=[
 | 
			
		||||
                            passbook.channels.out_saml.utils.time.timedelta_string_validator
 | 
			
		||||
                        ],
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
                (
 | 
			
		||||
                    "assertion_valid_not_on_or_after",
 | 
			
		||||
                    models.TextField(
 | 
			
		||||
                        default="minutes=5",
 | 
			
		||||
                        help_text="Assertion not valid on or after current time + this value (Format: hours=1;minutes=2;seconds=3).",
 | 
			
		||||
                        validators=[
 | 
			
		||||
                            passbook.channels.out_saml.utils.time.timedelta_string_validator
 | 
			
		||||
                        ],
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
                (
 | 
			
		||||
                    "session_valid_not_on_or_after",
 | 
			
		||||
                    models.TextField(
 | 
			
		||||
                        default="minutes=86400",
 | 
			
		||||
                        help_text="Session not valid on or after current time + this value (Format: hours=1;minutes=2;seconds=3).",
 | 
			
		||||
                        validators=[
 | 
			
		||||
                            passbook.channels.out_saml.utils.time.timedelta_string_validator
 | 
			
		||||
                        ],
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
                (
 | 
			
		||||
                    "digest_algorithm",
 | 
			
		||||
                    models.CharField(
 | 
			
		||||
                        choices=[("sha1", "SHA1"), ("sha256", "SHA256")],
 | 
			
		||||
                        default="sha256",
 | 
			
		||||
                        max_length=50,
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
                (
 | 
			
		||||
                    "signature_algorithm",
 | 
			
		||||
                    models.CharField(
 | 
			
		||||
                        choices=[
 | 
			
		||||
                            ("rsa-sha1", "RSA-SHA1"),
 | 
			
		||||
                            ("rsa-sha256", "RSA-SHA256"),
 | 
			
		||||
                            ("ecdsa-sha256", "ECDSA-SHA256"),
 | 
			
		||||
                            ("dsa-sha1", "DSA-SHA1"),
 | 
			
		||||
                        ],
 | 
			
		||||
                        default="rsa-sha256",
 | 
			
		||||
                        max_length=50,
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
                (
 | 
			
		||||
                    "require_signing",
 | 
			
		||||
                    models.BooleanField(
 | 
			
		||||
                        default=False,
 | 
			
		||||
                        help_text="Require Requests to be signed by an X509 Certificate. Must match the Certificate selected in `Singing Keypair`.",
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
                (
 | 
			
		||||
                    "signing_kp",
 | 
			
		||||
                    models.ForeignKey(
 | 
			
		||||
                        default=None,
 | 
			
		||||
                        help_text="Singing is enabled upon selection of a Key Pair.",
 | 
			
		||||
                        null=True,
 | 
			
		||||
                        on_delete=django.db.models.deletion.SET_NULL,
 | 
			
		||||
                        to="passbook_crypto.CertificateKeyPair",
 | 
			
		||||
                        verbose_name="Signing Keypair",
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
            ],
 | 
			
		||||
            options={
 | 
			
		||||
                "verbose_name": "SAML Outlet",
 | 
			
		||||
                "verbose_name_plural": "SAML Outlets",
 | 
			
		||||
            },
 | 
			
		||||
            bases=("passbook_core.outlet",),
 | 
			
		||||
        ),
 | 
			
		||||
    ]
 | 
			
		||||
@ -1,6 +0,0 @@
 | 
			
		||||
"""saml provider settings"""
 | 
			
		||||
 | 
			
		||||
PASSBOOK_PROVIDERS_SAML_PROCESSORS = [
 | 
			
		||||
    "passbook.channels.out_saml.processors.generic",
 | 
			
		||||
    "passbook.channels.out_saml.processors.salesforce",
 | 
			
		||||
]
 | 
			
		||||
@ -1,11 +0,0 @@
 | 
			
		||||
"""passbook saml provider app config"""
 | 
			
		||||
from django.apps import AppConfig
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class PassbookOutletSAMLv2Config(AppConfig):
 | 
			
		||||
    """passbook samlv2 provider app config"""
 | 
			
		||||
 | 
			
		||||
    name = "passbook.channels.out_samlv2"
 | 
			
		||||
    label = "passbook_channels_out_samlv2"
 | 
			
		||||
    verbose_name = "passbook Outlets.SAMLv2"
 | 
			
		||||
    mountpoint = "application/samlv2/"
 | 
			
		||||
@ -16,7 +16,7 @@ class ApplicationSerializer(ModelSerializer):
 | 
			
		||||
            "name",
 | 
			
		||||
            "slug",
 | 
			
		||||
            "skip_authorization",
 | 
			
		||||
            "outlet",
 | 
			
		||||
            "provider",
 | 
			
		||||
            "meta_launch_url",
 | 
			
		||||
            "meta_icon_url",
 | 
			
		||||
            "meta_description",
 | 
			
		||||
 | 
			
		||||
@ -1,31 +0,0 @@
 | 
			
		||||
"""Inlet API Views"""
 | 
			
		||||
from rest_framework.serializers import ModelSerializer, SerializerMethodField
 | 
			
		||||
from rest_framework.viewsets import ReadOnlyModelViewSet
 | 
			
		||||
 | 
			
		||||
from passbook.admin.forms.inlet import INLET_SERIALIZER_FIELDS
 | 
			
		||||
from passbook.core.models import Inlet
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class InletSerializer(ModelSerializer):
 | 
			
		||||
    """Inlet Serializer"""
 | 
			
		||||
 | 
			
		||||
    __type__ = SerializerMethodField(method_name="get_type")
 | 
			
		||||
 | 
			
		||||
    def get_type(self, obj):
 | 
			
		||||
        """Get object type so that we know which API Endpoint to use to get the full object"""
 | 
			
		||||
        return obj._meta.object_name.lower().replace("inlet", "")
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
 | 
			
		||||
        model = Inlet
 | 
			
		||||
        fields = INLET_SERIALIZER_FIELDS + ["__type__"]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class InletViewSet(ReadOnlyModelViewSet):
 | 
			
		||||
    """Inlet Viewset"""
 | 
			
		||||
 | 
			
		||||
    queryset = Inlet.objects.all()
 | 
			
		||||
    serializer_class = InletSerializer
 | 
			
		||||
 | 
			
		||||
    def get_queryset(self):
 | 
			
		||||
        return Inlet.objects.select_subclasses()
 | 
			
		||||
@ -1,30 +0,0 @@
 | 
			
		||||
"""Outlet API Views"""
 | 
			
		||||
from rest_framework.serializers import ModelSerializer, SerializerMethodField
 | 
			
		||||
from rest_framework.viewsets import ReadOnlyModelViewSet
 | 
			
		||||
 | 
			
		||||
from passbook.core.models import Outlet
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class OutletSerializer(ModelSerializer):
 | 
			
		||||
    """Outlet Serializer"""
 | 
			
		||||
 | 
			
		||||
    __type__ = SerializerMethodField(method_name="get_type")
 | 
			
		||||
 | 
			
		||||
    def get_type(self, obj):
 | 
			
		||||
        """Get object type so that we know which API Endpoint to use to get the full object"""
 | 
			
		||||
        return obj._meta.object_name.lower().replace("outlet", "")
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
 | 
			
		||||
        model = Outlet
 | 
			
		||||
        fields = ["pk", "property_mappings", "__type__"]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class OutletViewSet(ReadOnlyModelViewSet):
 | 
			
		||||
    """Outlet Viewset"""
 | 
			
		||||
 | 
			
		||||
    queryset = Outlet.objects.all()
 | 
			
		||||
    serializer_class = OutletSerializer
 | 
			
		||||
 | 
			
		||||
    def get_queryset(self):
 | 
			
		||||
        return Outlet.objects.select_subclasses()
 | 
			
		||||
@ -2,8 +2,8 @@
 | 
			
		||||
from rest_framework.serializers import ModelSerializer, SerializerMethodField
 | 
			
		||||
from rest_framework.viewsets import ReadOnlyModelViewSet
 | 
			
		||||
 | 
			
		||||
from passbook.core.models import Policy
 | 
			
		||||
from passbook.policies.forms import GENERAL_FIELDS
 | 
			
		||||
from passbook.policies.models import Policy
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class PolicySerializer(ModelSerializer):
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										30
									
								
								passbook/core/api/providers.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								passbook/core/api/providers.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,30 @@
 | 
			
		||||
"""Provider API Views"""
 | 
			
		||||
from rest_framework.serializers import ModelSerializer, SerializerMethodField
 | 
			
		||||
from rest_framework.viewsets import ReadOnlyModelViewSet
 | 
			
		||||
 | 
			
		||||
from passbook.core.models import Provider
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ProviderSerializer(ModelSerializer):
 | 
			
		||||
    """Provider Serializer"""
 | 
			
		||||
 | 
			
		||||
    __type__ = SerializerMethodField(method_name="get_type")
 | 
			
		||||
 | 
			
		||||
    def get_type(self, obj):
 | 
			
		||||
        """Get object type so that we know which API Endpoint to use to get the full object"""
 | 
			
		||||
        return obj._meta.object_name.lower().replace("provider", "")
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
 | 
			
		||||
        model = Provider
 | 
			
		||||
        fields = ["pk", "property_mappings", "__type__"]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ProviderViewSet(ReadOnlyModelViewSet):
 | 
			
		||||
    """Provider Viewset"""
 | 
			
		||||
 | 
			
		||||
    queryset = Provider.objects.all()
 | 
			
		||||
    serializer_class = ProviderSerializer
 | 
			
		||||
 | 
			
		||||
    def get_queryset(self):
 | 
			
		||||
        return Provider.objects.select_subclasses()
 | 
			
		||||
							
								
								
									
										31
									
								
								passbook/core/api/sources.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								passbook/core/api/sources.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,31 @@
 | 
			
		||||
"""Source API Views"""
 | 
			
		||||
from rest_framework.serializers import ModelSerializer, SerializerMethodField
 | 
			
		||||
from rest_framework.viewsets import ReadOnlyModelViewSet
 | 
			
		||||
 | 
			
		||||
from passbook.admin.forms.source import SOURCE_SERIALIZER_FIELDS
 | 
			
		||||
from passbook.core.models import Source
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class SourceSerializer(ModelSerializer):
 | 
			
		||||
    """Source Serializer"""
 | 
			
		||||
 | 
			
		||||
    __type__ = SerializerMethodField(method_name="get_type")
 | 
			
		||||
 | 
			
		||||
    def get_type(self, obj):
 | 
			
		||||
        """Get object type so that we know which API Endpoint to use to get the full object"""
 | 
			
		||||
        return obj._meta.object_name.lower().replace("source", "")
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
 | 
			
		||||
        model = Source
 | 
			
		||||
        fields = SOURCE_SERIALIZER_FIELDS + ["__type__"]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class SourceViewSet(ReadOnlyModelViewSet):
 | 
			
		||||
    """Source Viewset"""
 | 
			
		||||
 | 
			
		||||
    queryset = Source.objects.all()
 | 
			
		||||
    serializer_class = SourceSerializer
 | 
			
		||||
 | 
			
		||||
    def get_queryset(self):
 | 
			
		||||
        return Source.objects.select_subclasses()
 | 
			
		||||
@ -3,14 +3,14 @@ from django import forms
 | 
			
		||||
from django.contrib.admin.widgets import FilteredSelectMultiple
 | 
			
		||||
from django.utils.translation import gettext_lazy as _
 | 
			
		||||
 | 
			
		||||
from passbook.core.models import Application, Outlet
 | 
			
		||||
from passbook.core.models import Application, Provider
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ApplicationForm(forms.ModelForm):
 | 
			
		||||
    """Application Form"""
 | 
			
		||||
 | 
			
		||||
    outlet = forms.ModelChoiceField(
 | 
			
		||||
        queryset=Outlet.objects.all().order_by("pk").select_subclasses(),
 | 
			
		||||
    provider = forms.ModelChoiceField(
 | 
			
		||||
        queryset=Provider.objects.all().order_by("pk").select_subclasses(),
 | 
			
		||||
        required=False,
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
@ -21,7 +21,7 @@ class ApplicationForm(forms.ModelForm):
 | 
			
		||||
            "name",
 | 
			
		||||
            "slug",
 | 
			
		||||
            "skip_authorization",
 | 
			
		||||
            "outlet",
 | 
			
		||||
            "provider",
 | 
			
		||||
            "meta_launch_url",
 | 
			
		||||
            "meta_icon_url",
 | 
			
		||||
            "meta_description",
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
# Generated by Django 3.0.5 on 2020-05-15 19:59
 | 
			
		||||
# Generated by Django 2.2.6 on 2019-10-07 14:06
 | 
			
		||||
 | 
			
		||||
import uuid
 | 
			
		||||
 | 
			
		||||
@ -7,7 +7,6 @@ import django.contrib.auth.validators
 | 
			
		||||
import django.contrib.postgres.fields.jsonb
 | 
			
		||||
import django.db.models.deletion
 | 
			
		||||
import django.utils.timezone
 | 
			
		||||
import guardian.mixins
 | 
			
		||||
from django.conf import settings
 | 
			
		||||
from django.db import migrations, models
 | 
			
		||||
 | 
			
		||||
@ -20,7 +19,6 @@ class Migration(migrations.Migration):
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        ("auth", "0011_update_proxy_permissions"),
 | 
			
		||||
        ("passbook_policies", "0001_initial"),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
@ -107,41 +105,63 @@ class Migration(migrations.Migration):
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
                ("uuid", models.UUIDField(default=uuid.uuid4, editable=False)),
 | 
			
		||||
                ("name", models.TextField(help_text="User's display name.")),
 | 
			
		||||
                ("name", models.TextField()),
 | 
			
		||||
                ("password_change_date", models.DateTimeField(auto_now_add=True)),
 | 
			
		||||
                (
 | 
			
		||||
                    "attributes",
 | 
			
		||||
                    django.contrib.postgres.fields.jsonb.JSONField(
 | 
			
		||||
                        blank=True, default=dict
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
            ],
 | 
			
		||||
            options={"permissions": (("reset_user_password", "Reset Password"),),},
 | 
			
		||||
            bases=(guardian.mixins.GuardianUserMixin, models.Model),
 | 
			
		||||
            options={
 | 
			
		||||
                "verbose_name": "user",
 | 
			
		||||
                "verbose_name_plural": "users",
 | 
			
		||||
                "abstract": False,
 | 
			
		||||
            },
 | 
			
		||||
            managers=[("objects", django.contrib.auth.models.UserManager()),],
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.CreateModel(
 | 
			
		||||
            name="Inlet",
 | 
			
		||||
            name="Policy",
 | 
			
		||||
            fields=[
 | 
			
		||||
                ("created", models.DateTimeField(auto_now_add=True)),
 | 
			
		||||
                ("last_updated", models.DateTimeField(auto_now=True)),
 | 
			
		||||
                (
 | 
			
		||||
                    "policybindingmodel_ptr",
 | 
			
		||||
                    models.OneToOneField(
 | 
			
		||||
                        auto_created=True,
 | 
			
		||||
                        on_delete=django.db.models.deletion.CASCADE,
 | 
			
		||||
                        parent_link=True,
 | 
			
		||||
                    "uuid",
 | 
			
		||||
                    models.UUIDField(
 | 
			
		||||
                        default=uuid.uuid4,
 | 
			
		||||
                        editable=False,
 | 
			
		||||
                        primary_key=True,
 | 
			
		||||
                        serialize=False,
 | 
			
		||||
                        to="passbook_policies.PolicyBindingModel",
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
                ("name", models.TextField(help_text="Inlet's display Name.")),
 | 
			
		||||
                ("name", models.TextField(blank=True, null=True)),
 | 
			
		||||
                (
 | 
			
		||||
                    "slug",
 | 
			
		||||
                    models.SlugField(help_text="Internal source name, used in URLs."),
 | 
			
		||||
                    "action",
 | 
			
		||||
                    models.CharField(
 | 
			
		||||
                        choices=[("allow", "allow"), ("deny", "deny")], max_length=20
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
                ("enabled", models.BooleanField(default=True)),
 | 
			
		||||
                ("negate", models.BooleanField(default=False)),
 | 
			
		||||
                ("order", models.IntegerField(default=0)),
 | 
			
		||||
                ("timeout", models.IntegerField(default=30)),
 | 
			
		||||
            ],
 | 
			
		||||
            bases=("passbook_policies.policybindingmodel",),
 | 
			
		||||
            options={"abstract": False,},
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.CreateModel(
 | 
			
		||||
            name="PolicyModel",
 | 
			
		||||
            fields=[
 | 
			
		||||
                ("created", models.DateTimeField(auto_now_add=True)),
 | 
			
		||||
                ("last_updated", models.DateTimeField(auto_now=True)),
 | 
			
		||||
                (
 | 
			
		||||
                    "uuid",
 | 
			
		||||
                    models.UUIDField(
 | 
			
		||||
                        default=uuid.uuid4,
 | 
			
		||||
                        editable=False,
 | 
			
		||||
                        primary_key=True,
 | 
			
		||||
                        serialize=False,
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
                (
 | 
			
		||||
                    "policies",
 | 
			
		||||
                    models.ManyToManyField(blank=True, to="passbook_core.Policy"),
 | 
			
		||||
                ),
 | 
			
		||||
            ],
 | 
			
		||||
            options={"abstract": False,},
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.CreateModel(
 | 
			
		||||
            name="PropertyMapping",
 | 
			
		||||
@ -156,7 +176,6 @@ class Migration(migrations.Migration):
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
                ("name", models.TextField()),
 | 
			
		||||
                ("expression", models.TextField()),
 | 
			
		||||
            ],
 | 
			
		||||
            options={
 | 
			
		||||
                "verbose_name": "Property Mapping",
 | 
			
		||||
@ -164,38 +183,74 @@ class Migration(migrations.Migration):
 | 
			
		||||
            },
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.CreateModel(
 | 
			
		||||
            name="UserInletConnection",
 | 
			
		||||
            name="DebugPolicy",
 | 
			
		||||
            fields=[
 | 
			
		||||
                (
 | 
			
		||||
                    "id",
 | 
			
		||||
                    models.AutoField(
 | 
			
		||||
                    "policy_ptr",
 | 
			
		||||
                    models.OneToOneField(
 | 
			
		||||
                        auto_created=True,
 | 
			
		||||
                        on_delete=django.db.models.deletion.CASCADE,
 | 
			
		||||
                        parent_link=True,
 | 
			
		||||
                        primary_key=True,
 | 
			
		||||
                        serialize=False,
 | 
			
		||||
                        verbose_name="ID",
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
                ("created", models.DateTimeField(auto_now_add=True)),
 | 
			
		||||
                ("last_updated", models.DateTimeField(auto_now=True)),
 | 
			
		||||
                (
 | 
			
		||||
                    "inlet",
 | 
			
		||||
                    models.ForeignKey(
 | 
			
		||||
                        on_delete=django.db.models.deletion.CASCADE,
 | 
			
		||||
                        to="passbook_core.Inlet",
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
                (
 | 
			
		||||
                    "user",
 | 
			
		||||
                    models.ForeignKey(
 | 
			
		||||
                        on_delete=django.db.models.deletion.CASCADE,
 | 
			
		||||
                        to=settings.AUTH_USER_MODEL,
 | 
			
		||||
                        to="passbook_core.Policy",
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
                ("result", models.BooleanField(default=False)),
 | 
			
		||||
                ("wait_min", models.IntegerField(default=5)),
 | 
			
		||||
                ("wait_max", models.IntegerField(default=30)),
 | 
			
		||||
            ],
 | 
			
		||||
            options={"unique_together": {("user", "inlet")},},
 | 
			
		||||
            options={
 | 
			
		||||
                "verbose_name": "Debug Policy",
 | 
			
		||||
                "verbose_name_plural": "Debug Policies",
 | 
			
		||||
            },
 | 
			
		||||
            bases=("passbook_core.policy",),
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.CreateModel(
 | 
			
		||||
            name="Outlet",
 | 
			
		||||
            name="Factor",
 | 
			
		||||
            fields=[
 | 
			
		||||
                (
 | 
			
		||||
                    "policymodel_ptr",
 | 
			
		||||
                    models.OneToOneField(
 | 
			
		||||
                        auto_created=True,
 | 
			
		||||
                        on_delete=django.db.models.deletion.CASCADE,
 | 
			
		||||
                        parent_link=True,
 | 
			
		||||
                        primary_key=True,
 | 
			
		||||
                        serialize=False,
 | 
			
		||||
                        to="passbook_core.PolicyModel",
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
                ("name", models.TextField()),
 | 
			
		||||
                ("slug", models.SlugField(unique=True)),
 | 
			
		||||
                ("order", models.IntegerField()),
 | 
			
		||||
                ("enabled", models.BooleanField(default=True)),
 | 
			
		||||
            ],
 | 
			
		||||
            options={"abstract": False,},
 | 
			
		||||
            bases=("passbook_core.policymodel",),
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.CreateModel(
 | 
			
		||||
            name="Source",
 | 
			
		||||
            fields=[
 | 
			
		||||
                (
 | 
			
		||||
                    "policymodel_ptr",
 | 
			
		||||
                    models.OneToOneField(
 | 
			
		||||
                        auto_created=True,
 | 
			
		||||
                        on_delete=django.db.models.deletion.CASCADE,
 | 
			
		||||
                        parent_link=True,
 | 
			
		||||
                        primary_key=True,
 | 
			
		||||
                        serialize=False,
 | 
			
		||||
                        to="passbook_core.PolicyModel",
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
                ("name", models.TextField()),
 | 
			
		||||
                ("slug", models.SlugField()),
 | 
			
		||||
                ("enabled", models.BooleanField(default=True)),
 | 
			
		||||
            ],
 | 
			
		||||
            options={"abstract": False,},
 | 
			
		||||
            bases=("passbook_core.policymodel",),
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.CreateModel(
 | 
			
		||||
            name="Provider",
 | 
			
		||||
            fields=[
 | 
			
		||||
                (
 | 
			
		||||
                    "id",
 | 
			
		||||
@ -215,7 +270,7 @@ class Migration(migrations.Migration):
 | 
			
		||||
            ],
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.CreateModel(
 | 
			
		||||
            name="Token",
 | 
			
		||||
            name="Nonce",
 | 
			
		||||
            fields=[
 | 
			
		||||
                (
 | 
			
		||||
                    "uuid",
 | 
			
		||||
@ -229,11 +284,10 @@ class Migration(migrations.Migration):
 | 
			
		||||
                (
 | 
			
		||||
                    "expires",
 | 
			
		||||
                    models.DateTimeField(
 | 
			
		||||
                        default=passbook.core.models.default_token_duration
 | 
			
		||||
                        default=passbook.core.models.default_nonce_duration
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
                ("expiring", models.BooleanField(default=True)),
 | 
			
		||||
                ("description", models.TextField(blank=True, default="")),
 | 
			
		||||
                (
 | 
			
		||||
                    "user",
 | 
			
		||||
                    models.ForeignKey(
 | 
			
		||||
@ -242,14 +296,36 @@ class Migration(migrations.Migration):
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
            ],
 | 
			
		||||
            options={"verbose_name": "Token", "verbose_name_plural": "Tokens",},
 | 
			
		||||
            options={"verbose_name": "Nonce", "verbose_name_plural": "Nonces",},
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.AddField(
 | 
			
		||||
            model_name="inlet",
 | 
			
		||||
            name="property_mappings",
 | 
			
		||||
            field=models.ManyToManyField(
 | 
			
		||||
                blank=True, default=None, to="passbook_core.PropertyMapping"
 | 
			
		||||
            ),
 | 
			
		||||
        migrations.CreateModel(
 | 
			
		||||
            name="Invitation",
 | 
			
		||||
            fields=[
 | 
			
		||||
                (
 | 
			
		||||
                    "uuid",
 | 
			
		||||
                    models.UUIDField(
 | 
			
		||||
                        default=uuid.uuid4,
 | 
			
		||||
                        editable=False,
 | 
			
		||||
                        primary_key=True,
 | 
			
		||||
                        serialize=False,
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
                ("expires", models.DateTimeField(blank=True, default=None, null=True)),
 | 
			
		||||
                ("fixed_username", models.TextField(blank=True, default=None)),
 | 
			
		||||
                ("fixed_email", models.TextField(blank=True, default=None)),
 | 
			
		||||
                ("needs_confirmation", models.BooleanField(default=True)),
 | 
			
		||||
                (
 | 
			
		||||
                    "created_by",
 | 
			
		||||
                    models.ForeignKey(
 | 
			
		||||
                        on_delete=django.db.models.deletion.CASCADE,
 | 
			
		||||
                        to=settings.AUTH_USER_MODEL,
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
            ],
 | 
			
		||||
            options={
 | 
			
		||||
                "verbose_name": "Invitation",
 | 
			
		||||
                "verbose_name_plural": "Invitations",
 | 
			
		||||
            },
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.CreateModel(
 | 
			
		||||
            name="Group",
 | 
			
		||||
@ -265,7 +341,7 @@ class Migration(migrations.Migration):
 | 
			
		||||
                ),
 | 
			
		||||
                ("name", models.CharField(max_length=80, verbose_name="name")),
 | 
			
		||||
                (
 | 
			
		||||
                    "attributes",
 | 
			
		||||
                    "tags",
 | 
			
		||||
                    django.contrib.postgres.fields.jsonb.JSONField(
 | 
			
		||||
                        blank=True, default=dict
 | 
			
		||||
                    ),
 | 
			
		||||
@ -283,57 +359,11 @@ class Migration(migrations.Migration):
 | 
			
		||||
            ],
 | 
			
		||||
            options={"unique_together": {("name", "parent")},},
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.CreateModel(
 | 
			
		||||
            name="Application",
 | 
			
		||||
            fields=[
 | 
			
		||||
                (
 | 
			
		||||
                    "policybindingmodel_ptr",
 | 
			
		||||
                    models.OneToOneField(
 | 
			
		||||
                        auto_created=True,
 | 
			
		||||
                        on_delete=django.db.models.deletion.CASCADE,
 | 
			
		||||
                        parent_link=True,
 | 
			
		||||
                        primary_key=True,
 | 
			
		||||
                        serialize=False,
 | 
			
		||||
                        to="passbook_policies.PolicyBindingModel",
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
                ("name", models.TextField(help_text="Application's display Name.")),
 | 
			
		||||
                (
 | 
			
		||||
                    "slug",
 | 
			
		||||
                    models.SlugField(
 | 
			
		||||
                        help_text="Internal application name, used in URLs."
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
                ("skip_authorization", models.BooleanField(default=False)),
 | 
			
		||||
                ("meta_launch_url", models.URLField(blank=True, default="")),
 | 
			
		||||
                ("meta_icon_url", models.TextField(blank=True, default="")),
 | 
			
		||||
                ("meta_description", models.TextField(blank=True, default="")),
 | 
			
		||||
                ("meta_publisher", models.TextField(blank=True, default="")),
 | 
			
		||||
                (
 | 
			
		||||
                    "outlet",
 | 
			
		||||
                    models.OneToOneField(
 | 
			
		||||
                        blank=True,
 | 
			
		||||
                        default=None,
 | 
			
		||||
                        null=True,
 | 
			
		||||
                        on_delete=django.db.models.deletion.SET_DEFAULT,
 | 
			
		||||
                        to="passbook_core.Outlet",
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
            ],
 | 
			
		||||
            bases=("passbook_policies.policybindingmodel",),
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.AddField(
 | 
			
		||||
            model_name="user",
 | 
			
		||||
            name="groups",
 | 
			
		||||
            field=models.ManyToManyField(to="passbook_core.Group"),
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.AddField(
 | 
			
		||||
            model_name="user",
 | 
			
		||||
            name="inlets",
 | 
			
		||||
            field=models.ManyToManyField(
 | 
			
		||||
                through="passbook_core.UserInletConnection", to="passbook_core.Inlet"
 | 
			
		||||
            ),
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.AddField(
 | 
			
		||||
            model_name="user",
 | 
			
		||||
            name="user_permissions",
 | 
			
		||||
@ -347,33 +377,74 @@ class Migration(migrations.Migration):
 | 
			
		||||
            ),
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.CreateModel(
 | 
			
		||||
            name="PropertyMappingBinding",
 | 
			
		||||
            name="UserSourceConnection",
 | 
			
		||||
            fields=[
 | 
			
		||||
                (
 | 
			
		||||
                    "uuid",
 | 
			
		||||
                    models.UUIDField(
 | 
			
		||||
                        default=uuid.uuid4,
 | 
			
		||||
                        editable=False,
 | 
			
		||||
                    "id",
 | 
			
		||||
                    models.AutoField(
 | 
			
		||||
                        auto_created=True,
 | 
			
		||||
                        primary_key=True,
 | 
			
		||||
                        serialize=False,
 | 
			
		||||
                        verbose_name="ID",
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
                ("order", models.IntegerField(default=0)),
 | 
			
		||||
                ("created", models.DateTimeField(auto_now_add=True)),
 | 
			
		||||
                ("last_updated", models.DateTimeField(auto_now=True)),
 | 
			
		||||
                (
 | 
			
		||||
                    "outlet",
 | 
			
		||||
                    "user",
 | 
			
		||||
                    models.ForeignKey(
 | 
			
		||||
                        on_delete=django.db.models.deletion.CASCADE,
 | 
			
		||||
                        to="passbook_core.Outlet",
 | 
			
		||||
                        to=settings.AUTH_USER_MODEL,
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
                (
 | 
			
		||||
                    "property_mapping",
 | 
			
		||||
                    "source",
 | 
			
		||||
                    models.ForeignKey(
 | 
			
		||||
                        on_delete=django.db.models.deletion.CASCADE,
 | 
			
		||||
                        to="passbook_core.PropertyMapping",
 | 
			
		||||
                        to="passbook_core.Source",
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
            ],
 | 
			
		||||
            options={"unique_together": {("property_mapping", "outlet", "order")},},
 | 
			
		||||
            options={"unique_together": {("user", "source")},},
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.CreateModel(
 | 
			
		||||
            name="Application",
 | 
			
		||||
            fields=[
 | 
			
		||||
                (
 | 
			
		||||
                    "policymodel_ptr",
 | 
			
		||||
                    models.OneToOneField(
 | 
			
		||||
                        auto_created=True,
 | 
			
		||||
                        on_delete=django.db.models.deletion.CASCADE,
 | 
			
		||||
                        parent_link=True,
 | 
			
		||||
                        primary_key=True,
 | 
			
		||||
                        serialize=False,
 | 
			
		||||
                        to="passbook_core.PolicyModel",
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
                ("name", models.TextField()),
 | 
			
		||||
                ("slug", models.SlugField()),
 | 
			
		||||
                ("launch_url", models.URLField(blank=True, null=True)),
 | 
			
		||||
                ("icon_url", models.TextField(blank=True, null=True)),
 | 
			
		||||
                ("skip_authorization", models.BooleanField(default=False)),
 | 
			
		||||
                (
 | 
			
		||||
                    "provider",
 | 
			
		||||
                    models.OneToOneField(
 | 
			
		||||
                        blank=True,
 | 
			
		||||
                        default=None,
 | 
			
		||||
                        null=True,
 | 
			
		||||
                        on_delete=django.db.models.deletion.SET_DEFAULT,
 | 
			
		||||
                        to="passbook_core.Provider",
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
            ],
 | 
			
		||||
            options={"abstract": False,},
 | 
			
		||||
            bases=("passbook_core.policymodel",),
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.AddField(
 | 
			
		||||
            model_name="user",
 | 
			
		||||
            name="sources",
 | 
			
		||||
            field=models.ManyToManyField(
 | 
			
		||||
                through="passbook_core.UserSourceConnection", to="passbook_core.Source"
 | 
			
		||||
            ),
 | 
			
		||||
        ),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										17
									
								
								passbook/core/migrations/0002_auto_20191010_1058.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								passbook/core/migrations/0002_auto_20191010_1058.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,17 @@
 | 
			
		||||
# Generated by Django 2.2.6 on 2019-10-10 10:58
 | 
			
		||||
 | 
			
		||||
from django.db import migrations
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Migration(migrations.Migration):
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        ("passbook_core", "0001_initial"),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
        migrations.AlterModelOptions(
 | 
			
		||||
            name="user",
 | 
			
		||||
            options={"permissions": (("reset_user_password", "Reset Password"),)},
 | 
			
		||||
        ),
 | 
			
		||||
    ]
 | 
			
		||||
							
								
								
									
										18
									
								
								passbook/core/migrations/0002_nonce_description.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								passbook/core/migrations/0002_nonce_description.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,18 @@
 | 
			
		||||
# Generated by Django 2.2.6 on 2019-10-10 11:48
 | 
			
		||||
 | 
			
		||||
from django.db import migrations, models
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Migration(migrations.Migration):
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        ("passbook_core", "0001_initial"),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
        migrations.AddField(
 | 
			
		||||
            model_name="nonce",
 | 
			
		||||
            name="description",
 | 
			
		||||
            field=models.TextField(blank=True, default=""),
 | 
			
		||||
        ),
 | 
			
		||||
    ]
 | 
			
		||||
							
								
								
									
										31
									
								
								passbook/core/migrations/0003_auto_20191011_0914.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								passbook/core/migrations/0003_auto_20191011_0914.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,31 @@
 | 
			
		||||
# Generated by Django 2.2.6 on 2019-10-11 09:14
 | 
			
		||||
 | 
			
		||||
import django.contrib.postgres.fields.jsonb
 | 
			
		||||
from django.db import migrations, models
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Migration(migrations.Migration):
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        ("passbook_core", "0002_nonce_description"),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
        migrations.RenameField(
 | 
			
		||||
            model_name="group", old_name="tags", new_name="attributes",
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.AddField(
 | 
			
		||||
            model_name="source",
 | 
			
		||||
            name="property_mappings",
 | 
			
		||||
            field=models.ManyToManyField(
 | 
			
		||||
                blank=True, default=None, to="passbook_core.PropertyMapping"
 | 
			
		||||
            ),
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.AddField(
 | 
			
		||||
            model_name="user",
 | 
			
		||||
            name="attributes",
 | 
			
		||||
            field=django.contrib.postgres.fields.jsonb.JSONField(
 | 
			
		||||
                blank=True, default=dict
 | 
			
		||||
            ),
 | 
			
		||||
        ),
 | 
			
		||||
    ]
 | 
			
		||||
							
								
								
									
										13
									
								
								passbook/core/migrations/0003_merge_20191010_1541.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								passbook/core/migrations/0003_merge_20191010_1541.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,13 @@
 | 
			
		||||
# Generated by Django 2.2.6 on 2019-10-10 15:41
 | 
			
		||||
 | 
			
		||||
from django.db import migrations
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Migration(migrations.Migration):
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        ("passbook_core", "0002_auto_20191010_1058"),
 | 
			
		||||
        ("passbook_core", "0002_nonce_description"),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = []
 | 
			
		||||
							
								
								
									
										14
									
								
								passbook/core/migrations/0004_remove_policy_action.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								passbook/core/migrations/0004_remove_policy_action.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,14 @@
 | 
			
		||||
# Generated by Django 2.2.6 on 2019-10-14 11:56
 | 
			
		||||
 | 
			
		||||
from django.db import migrations
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Migration(migrations.Migration):
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        ("passbook_core", "0003_auto_20191011_0914"),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
        migrations.RemoveField(model_name="policy", name="action",),
 | 
			
		||||
    ]
 | 
			
		||||
							
								
								
									
										13
									
								
								passbook/core/migrations/0005_merge_20191025_2022.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								passbook/core/migrations/0005_merge_20191025_2022.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,13 @@
 | 
			
		||||
# Generated by Django 2.2.6 on 2019-10-25 20:22
 | 
			
		||||
 | 
			
		||||
from django.db import migrations
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Migration(migrations.Migration):
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        ("passbook_core", "0004_remove_policy_action"),
 | 
			
		||||
        ("passbook_core", "0003_merge_20191010_1541"),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = []
 | 
			
		||||
							
								
								
									
										19
									
								
								passbook/core/migrations/0006_propertymapping_template.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								passbook/core/migrations/0006_propertymapping_template.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,19 @@
 | 
			
		||||
# Generated by Django 3.0.3 on 2020-02-17 16:15
 | 
			
		||||
 | 
			
		||||
from django.db import migrations, models
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Migration(migrations.Migration):
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        ("passbook_core", "0005_merge_20191025_2022"),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
        migrations.AddField(
 | 
			
		||||
            model_name="propertymapping",
 | 
			
		||||
            name="template",
 | 
			
		||||
            field=models.TextField(default=""),
 | 
			
		||||
            preserve_default=False,
 | 
			
		||||
        ),
 | 
			
		||||
    ]
 | 
			
		||||
							
								
								
									
										16
									
								
								passbook/core/migrations/0007_auto_20200217_1934.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								passbook/core/migrations/0007_auto_20200217_1934.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,16 @@
 | 
			
		||||
# Generated by Django 3.0.3 on 2020-02-17 19:34
 | 
			
		||||
 | 
			
		||||
from django.db import migrations
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Migration(migrations.Migration):
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        ("passbook_core", "0006_propertymapping_template"),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
        migrations.RenameField(
 | 
			
		||||
            model_name="propertymapping", old_name="template", new_name="expression",
 | 
			
		||||
        ),
 | 
			
		||||
    ]
 | 
			
		||||
							
								
								
									
										29
									
								
								passbook/core/migrations/0008_auto_20200220_1242.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								passbook/core/migrations/0008_auto_20200220_1242.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,29 @@
 | 
			
		||||
# Generated by Django 3.0.3 on 2020-02-20 12:42
 | 
			
		||||
 | 
			
		||||
from django.db import migrations, models
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Migration(migrations.Migration):
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        ("passbook_core", "0007_auto_20200217_1934"),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
        migrations.RenameField(
 | 
			
		||||
            model_name="application", old_name="icon_url", new_name="meta_icon_url",
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.RenameField(
 | 
			
		||||
            model_name="application", old_name="launch_url", new_name="meta_launch_url",
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.AddField(
 | 
			
		||||
            model_name="application",
 | 
			
		||||
            name="meta_description",
 | 
			
		||||
            field=models.TextField(blank=True, null=True),
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.AddField(
 | 
			
		||||
            model_name="application",
 | 
			
		||||
            name="meta_publisher",
 | 
			
		||||
            field=models.TextField(blank=True, null=True),
 | 
			
		||||
        ),
 | 
			
		||||
    ]
 | 
			
		||||
							
								
								
									
										52
									
								
								passbook/core/migrations/0009_auto_20200221_1410.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								passbook/core/migrations/0009_auto_20200221_1410.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,52 @@
 | 
			
		||||
# Generated by Django 3.0.3 on 2020-02-21 14:10
 | 
			
		||||
 | 
			
		||||
from django.db import migrations, models
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Migration(migrations.Migration):
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        ("passbook_core", "0008_auto_20200220_1242"),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
        migrations.AlterField(
 | 
			
		||||
            model_name="application",
 | 
			
		||||
            name="name",
 | 
			
		||||
            field=models.TextField(help_text="Application's display Name."),
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.AlterField(
 | 
			
		||||
            model_name="application",
 | 
			
		||||
            name="slug",
 | 
			
		||||
            field=models.SlugField(
 | 
			
		||||
                help_text="Internal application name, used in URLs."
 | 
			
		||||
            ),
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.AlterField(
 | 
			
		||||
            model_name="factor",
 | 
			
		||||
            name="name",
 | 
			
		||||
            field=models.TextField(help_text="Factor's display Name."),
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.AlterField(
 | 
			
		||||
            model_name="factor",
 | 
			
		||||
            name="slug",
 | 
			
		||||
            field=models.SlugField(
 | 
			
		||||
                help_text="Internal factor name, used in URLs.", unique=True
 | 
			
		||||
            ),
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.AlterField(
 | 
			
		||||
            model_name="source",
 | 
			
		||||
            name="name",
 | 
			
		||||
            field=models.TextField(help_text="Source's display Name."),
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.AlterField(
 | 
			
		||||
            model_name="source",
 | 
			
		||||
            name="slug",
 | 
			
		||||
            field=models.SlugField(help_text="Internal source name, used in URLs."),
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.AlterField(
 | 
			
		||||
            model_name="user",
 | 
			
		||||
            name="name",
 | 
			
		||||
            field=models.TextField(help_text="User's display name."),
 | 
			
		||||
        ),
 | 
			
		||||
    ]
 | 
			
		||||
							
								
								
									
										33
									
								
								passbook/core/migrations/0010_auto_20200221_2208.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								passbook/core/migrations/0010_auto_20200221_2208.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,33 @@
 | 
			
		||||
# Generated by Django 3.0.3 on 2020-02-21 22:08
 | 
			
		||||
 | 
			
		||||
from django.db import migrations, models
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Migration(migrations.Migration):
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        ("passbook_core", "0009_auto_20200221_1410"),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
        migrations.AlterField(
 | 
			
		||||
            model_name="application",
 | 
			
		||||
            name="meta_description",
 | 
			
		||||
            field=models.TextField(blank=True, default=""),
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.AlterField(
 | 
			
		||||
            model_name="application",
 | 
			
		||||
            name="meta_icon_url",
 | 
			
		||||
            field=models.TextField(blank=True, default=""),
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.AlterField(
 | 
			
		||||
            model_name="application",
 | 
			
		||||
            name="meta_launch_url",
 | 
			
		||||
            field=models.URLField(blank=True, default=""),
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.AlterField(
 | 
			
		||||
            model_name="application",
 | 
			
		||||
            name="meta_publisher",
 | 
			
		||||
            field=models.TextField(blank=True, default=""),
 | 
			
		||||
        ),
 | 
			
		||||
    ]
 | 
			
		||||
							
								
								
									
										27
									
								
								passbook/core/migrations/0011_auto_20200222_1822.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								passbook/core/migrations/0011_auto_20200222_1822.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,27 @@
 | 
			
		||||
# Generated by Django 3.0.3 on 2020-02-22 18:22
 | 
			
		||||
 | 
			
		||||
from django.db import migrations
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def fix_application_null(apps, schema_editor):
 | 
			
		||||
    """Fix Application meta_fields being null"""
 | 
			
		||||
    Application = apps.get_model("passbook_core", "Application")
 | 
			
		||||
    for app in Application.objects.all():
 | 
			
		||||
        if app.meta_launch_url is None:
 | 
			
		||||
            app.meta_launch_url = ""
 | 
			
		||||
        if app.meta_icon_url is None:
 | 
			
		||||
            app.meta_icon_url = ""
 | 
			
		||||
        if app.meta_description is None:
 | 
			
		||||
            app.meta_description = ""
 | 
			
		||||
        if app.meta_publisher is None:
 | 
			
		||||
            app.meta_publisher = ""
 | 
			
		||||
        app.save()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Migration(migrations.Migration):
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        ("passbook_core", "0010_auto_20200221_2208"),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = [migrations.RunPython(fix_application_null)]
 | 
			
		||||
							
								
								
									
										14
									
								
								passbook/core/migrations/0012_delete_factor.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								passbook/core/migrations/0012_delete_factor.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,14 @@
 | 
			
		||||
# Generated by Django 3.0.3 on 2020-05-08 17:58
 | 
			
		||||
 | 
			
		||||
from django.db import migrations
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Migration(migrations.Migration):
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        ("passbook_core", "0011_auto_20200222_1822"),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
        migrations.DeleteModel(name="Factor",),
 | 
			
		||||
    ]
 | 
			
		||||
							
								
								
									
										16
									
								
								passbook/core/migrations/0013_delete_debugpolicy.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								passbook/core/migrations/0013_delete_debugpolicy.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,16 @@
 | 
			
		||||
# Generated by Django 3.0.5 on 2020-05-10 10:01
 | 
			
		||||
 | 
			
		||||
from django.db import migrations
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Migration(migrations.Migration):
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        ("passbook_policies", "0003_auto_20200508_1642"),
 | 
			
		||||
        ("passbook_stages_password", "0001_initial"),
 | 
			
		||||
        ("passbook_core", "0012_delete_factor"),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
        migrations.DeleteModel(name="DebugPolicy",),
 | 
			
		||||
    ]
 | 
			
		||||
							
								
								
									
										14
									
								
								passbook/core/migrations/0014_delete_invitation.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								passbook/core/migrations/0014_delete_invitation.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,14 @@
 | 
			
		||||
# Generated by Django 3.0.5 on 2020-05-11 19:57
 | 
			
		||||
 | 
			
		||||
from django.db import migrations
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Migration(migrations.Migration):
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        ("passbook_core", "0013_delete_debugpolicy"),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
        migrations.DeleteModel(name="Invitation",),
 | 
			
		||||
    ]
 | 
			
		||||
@ -10,6 +10,7 @@ from django.db import models
 | 
			
		||||
from django.http import HttpRequest
 | 
			
		||||
from django.utils.timezone import now
 | 
			
		||||
from django.utils.translation import gettext_lazy as _
 | 
			
		||||
from django_prometheus.models import ExportModelOperationsMixin
 | 
			
		||||
from guardian.mixins import GuardianUserMixin
 | 
			
		||||
from jinja2 import Undefined
 | 
			
		||||
from jinja2.exceptions import TemplateSyntaxError, UndefinedError
 | 
			
		||||
@ -21,18 +22,19 @@ from passbook.core.exceptions import PropertyMappingExpressionException
 | 
			
		||||
from passbook.core.signals import password_changed
 | 
			
		||||
from passbook.core.types import UILoginButton, UIUserSettings
 | 
			
		||||
from passbook.lib.models import CreatedUpdatedModel, UUIDModel
 | 
			
		||||
from passbook.policies.models import PolicyBindingModel
 | 
			
		||||
from passbook.policies.exceptions import PolicyException
 | 
			
		||||
from passbook.policies.types import PolicyRequest, PolicyResult
 | 
			
		||||
 | 
			
		||||
LOGGER = get_logger()
 | 
			
		||||
NATIVE_ENVIRONMENT = NativeEnvironment()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def default_token_duration():
 | 
			
		||||
    """Default duration a Token is valid"""
 | 
			
		||||
def default_nonce_duration():
 | 
			
		||||
    """Default duration a Nonce is valid"""
 | 
			
		||||
    return now() + timedelta(minutes=30)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Group(UUIDModel):
 | 
			
		||||
class Group(ExportModelOperationsMixin("group"), UUIDModel):
 | 
			
		||||
    """Custom Group model which supports a basic hierarchy"""
 | 
			
		||||
 | 
			
		||||
    name = models.CharField(_("name"), max_length=80)
 | 
			
		||||
@ -53,13 +55,13 @@ class Group(UUIDModel):
 | 
			
		||||
        unique_together = (("name", "parent",),)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class User(GuardianUserMixin, AbstractUser):
 | 
			
		||||
class User(ExportModelOperationsMixin("user"), GuardianUserMixin, AbstractUser):
 | 
			
		||||
    """Custom User model to allow easier adding o f user-based settings"""
 | 
			
		||||
 | 
			
		||||
    uuid = models.UUIDField(default=uuid4, editable=False)
 | 
			
		||||
    name = models.TextField(help_text=_("User's display name."))
 | 
			
		||||
 | 
			
		||||
    inlets = models.ManyToManyField("Inlet", through="UserInletConnection")
 | 
			
		||||
    sources = models.ManyToManyField("Source", through="UserSourceConnection")
 | 
			
		||||
    groups = models.ManyToManyField("Group")
 | 
			
		||||
    password_change_date = models.DateTimeField(auto_now_add=True)
 | 
			
		||||
 | 
			
		||||
@ -76,7 +78,29 @@ class User(GuardianUserMixin, AbstractUser):
 | 
			
		||||
        permissions = (("reset_user_password", "Reset Password"),)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Application(PolicyBindingModel):
 | 
			
		||||
class Provider(ExportModelOperationsMixin("provider"), models.Model):
 | 
			
		||||
    """Application-independent Provider instance. For example SAML2 Remote, OAuth2 Application"""
 | 
			
		||||
 | 
			
		||||
    property_mappings = models.ManyToManyField(
 | 
			
		||||
        "PropertyMapping", default=None, blank=True
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    objects = InheritanceManager()
 | 
			
		||||
 | 
			
		||||
    # This class defines no field for easier inheritance
 | 
			
		||||
    def __str__(self):
 | 
			
		||||
        if hasattr(self, "name"):
 | 
			
		||||
            return getattr(self, "name")
 | 
			
		||||
        return super().__str__()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class PolicyModel(UUIDModel, CreatedUpdatedModel):
 | 
			
		||||
    """Base model which can have policies applied to it"""
 | 
			
		||||
 | 
			
		||||
    policies = models.ManyToManyField("Policy", blank=True)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Application(ExportModelOperationsMixin("application"), PolicyModel):
 | 
			
		||||
    """Every Application which uses passbook for authentication/identification/authorization
 | 
			
		||||
    needs an Application record. Other authentication types can subclass this Model to
 | 
			
		||||
    add custom fields and other properties"""
 | 
			
		||||
@ -84,8 +108,8 @@ class Application(PolicyBindingModel):
 | 
			
		||||
    name = models.TextField(help_text=_("Application's display Name."))
 | 
			
		||||
    slug = models.SlugField(help_text=_("Internal application name, used in URLs."))
 | 
			
		||||
    skip_authorization = models.BooleanField(default=False)
 | 
			
		||||
    outlet = models.OneToOneField(
 | 
			
		||||
        "Outlet", null=True, blank=True, default=None, on_delete=models.SET_DEFAULT
 | 
			
		||||
    provider = models.OneToOneField(
 | 
			
		||||
        "Provider", null=True, blank=True, default=None, on_delete=models.SET_DEFAULT
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    meta_launch_url = models.URLField(default="", blank=True)
 | 
			
		||||
@ -95,20 +119,20 @@ class Application(PolicyBindingModel):
 | 
			
		||||
 | 
			
		||||
    objects = InheritanceManager()
 | 
			
		||||
 | 
			
		||||
    def get_outlet(self) -> Optional["Outlet"]:
 | 
			
		||||
        """Get casted outlet instance"""
 | 
			
		||||
        if not self.outlet:
 | 
			
		||||
    def get_provider(self) -> Optional[Provider]:
 | 
			
		||||
        """Get casted provider instance"""
 | 
			
		||||
        if not self.provider:
 | 
			
		||||
            return None
 | 
			
		||||
        return Outlet.objects.get_subclass(pk=self.outlet.pk)
 | 
			
		||||
        return Provider.objects.get_subclass(pk=self.provider.pk)
 | 
			
		||||
 | 
			
		||||
    def __str__(self):
 | 
			
		||||
        return self.name
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Inlet(PolicyBindingModel):
 | 
			
		||||
class Source(ExportModelOperationsMixin("source"), PolicyModel):
 | 
			
		||||
    """Base Authentication source, i.e. an OAuth Provider, SAML Remote or LDAP Server"""
 | 
			
		||||
 | 
			
		||||
    name = models.TextField(help_text=_("Inlet's display Name."))
 | 
			
		||||
    name = models.TextField(help_text=_("Source's display Name."))
 | 
			
		||||
    slug = models.SlugField(help_text=_("Internal source name, used in URLs."))
 | 
			
		||||
 | 
			
		||||
    enabled = models.BooleanField(default=True)
 | 
			
		||||
@ -141,69 +165,56 @@ class Inlet(PolicyBindingModel):
 | 
			
		||||
        return self.name
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class UserInletConnection(CreatedUpdatedModel):
 | 
			
		||||
    """Connection between User and Inlet."""
 | 
			
		||||
class UserSourceConnection(CreatedUpdatedModel):
 | 
			
		||||
    """Connection between User and Source."""
 | 
			
		||||
 | 
			
		||||
    user = models.ForeignKey(User, on_delete=models.CASCADE)
 | 
			
		||||
    inlet = models.ForeignKey(Inlet, on_delete=models.CASCADE)
 | 
			
		||||
    source = models.ForeignKey(Source, on_delete=models.CASCADE)
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
 | 
			
		||||
        unique_together = (("user", "inlet"),)
 | 
			
		||||
        unique_together = (("user", "source"),)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Token(UUIDModel):
 | 
			
		||||
class Policy(ExportModelOperationsMixin("policy"), UUIDModel, CreatedUpdatedModel):
 | 
			
		||||
    """Policies which specify if a user is authorized to use an Application. Can be overridden by
 | 
			
		||||
    other types to add other fields, more logic, etc."""
 | 
			
		||||
 | 
			
		||||
    name = models.TextField(blank=True, null=True)
 | 
			
		||||
    negate = models.BooleanField(default=False)
 | 
			
		||||
    order = models.IntegerField(default=0)
 | 
			
		||||
    timeout = models.IntegerField(default=30)
 | 
			
		||||
 | 
			
		||||
    objects = InheritanceManager()
 | 
			
		||||
 | 
			
		||||
    def __str__(self):
 | 
			
		||||
        return f"Policy {self.name}"
 | 
			
		||||
 | 
			
		||||
    def passes(self, request: PolicyRequest) -> PolicyResult:
 | 
			
		||||
        """Check if user instance passes this policy"""
 | 
			
		||||
        raise PolicyException()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Nonce(ExportModelOperationsMixin("nonce"), UUIDModel):
 | 
			
		||||
    """One-time link for password resets/sign-up-confirmations"""
 | 
			
		||||
 | 
			
		||||
    expires = models.DateTimeField(default=default_token_duration)
 | 
			
		||||
    user = models.ForeignKey("User", on_delete=models.CASCADE, related_name="+")
 | 
			
		||||
    expires = models.DateTimeField(default=default_nonce_duration)
 | 
			
		||||
    user = models.ForeignKey("User", on_delete=models.CASCADE)
 | 
			
		||||
    expiring = models.BooleanField(default=True)
 | 
			
		||||
    description = models.TextField(default="", blank=True)
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def is_expired(self) -> bool:
 | 
			
		||||
        """Check if token is expired yet."""
 | 
			
		||||
        """Check if nonce is expired yet."""
 | 
			
		||||
        return now() > self.expires
 | 
			
		||||
 | 
			
		||||
    def __str__(self):
 | 
			
		||||
        return f"Token f{self.uuid.hex} {self.description} (expires={self.expires})"
 | 
			
		||||
        return f"Nonce f{self.uuid.hex} {self.description} (expires={self.expires})"
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
 | 
			
		||||
        verbose_name = _("Token")
 | 
			
		||||
        verbose_name_plural = _("Tokens")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Outlet(models.Model):
 | 
			
		||||
    """Application-independent Outlet instance. For example SAML2 Remote, OAuth2 Application"""
 | 
			
		||||
 | 
			
		||||
    property_mappings = models.ManyToManyField(
 | 
			
		||||
        "PropertyMapping", default=None, blank=True
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    objects = InheritanceManager()
 | 
			
		||||
 | 
			
		||||
    # This class defines no field for easier inheritance
 | 
			
		||||
    def __str__(self):
 | 
			
		||||
        if hasattr(self, "name"):
 | 
			
		||||
            return getattr(self, "name")
 | 
			
		||||
        return super().__str__()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class PropertyMappingBinding(UUIDModel):
 | 
			
		||||
    """Binds a PropertyMapping instance to an outlet"""
 | 
			
		||||
 | 
			
		||||
    property_mapping = models.ForeignKey("PropertyMapping", on_delete=models.CASCADE)
 | 
			
		||||
    outlet = models.ForeignKey("Outlet", on_delete=models.CASCADE)
 | 
			
		||||
 | 
			
		||||
    order = models.IntegerField(default=0)
 | 
			
		||||
 | 
			
		||||
    def __str__(self):
 | 
			
		||||
        return f"PropertyMapping Binding p={self.property_mapping} outlet={self.outlet}"
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
 | 
			
		||||
        unique_together = (("property_mapping", "outlet", "order"),)
 | 
			
		||||
        verbose_name = _("Nonce")
 | 
			
		||||
        verbose_name_plural = _("Nonces")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class PropertyMapping(UUIDModel):
 | 
			
		||||
 | 
			
		||||
@ -17,7 +17,7 @@ password_changed = Signal(providing_args=["user", "password"])
 | 
			
		||||
# pylint: disable=unused-argument
 | 
			
		||||
def invalidate_policy_cache(sender, instance, **_):
 | 
			
		||||
    """Invalidate Policy cache when policy is updated"""
 | 
			
		||||
    from passbook.policies.models import Policy
 | 
			
		||||
    from passbook.core.models import Policy
 | 
			
		||||
    from passbook.policies.process import cache_key
 | 
			
		||||
 | 
			
		||||
    if isinstance(instance, Policy):
 | 
			
		||||
 | 
			
		||||
@ -2,14 +2,14 @@
 | 
			
		||||
from django.utils.timezone import now
 | 
			
		||||
from structlog import get_logger
 | 
			
		||||
 | 
			
		||||
from passbook.core.models import Token
 | 
			
		||||
from passbook.core.models import Nonce
 | 
			
		||||
from passbook.root.celery import CELERY_APP
 | 
			
		||||
 | 
			
		||||
LOGGER = get_logger()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@CELERY_APP.task()
 | 
			
		||||
def clean_tokens():
 | 
			
		||||
    """Remove expired tokens"""
 | 
			
		||||
    amount, _ = Token.objects.filter(expires__lt=now(), expiring=True).delete()
 | 
			
		||||
    LOGGER.debug("Deleted expired tokens", amount=amount)
 | 
			
		||||
def clean_nonces():
 | 
			
		||||
    """Remove expired nonces"""
 | 
			
		||||
    amount, _ = Nonce.objects.filter(expires__lt=now(), expiring=True).delete()
 | 
			
		||||
    LOGGER.debug("Deleted expired nonces", amount=amount)
 | 
			
		||||
 | 
			
		||||
@ -34,17 +34,17 @@
 | 
			
		||||
                </ul>
 | 
			
		||||
            </section>
 | 
			
		||||
            {% endif %}
 | 
			
		||||
            {% user_inlets as user_inlets_loc %}
 | 
			
		||||
            {% if user_inlets_loc %}
 | 
			
		||||
            {% user_sources as user_sources_loc %}
 | 
			
		||||
            {% if user_sources_loc %}
 | 
			
		||||
            <section class="pf-c-nav__section">
 | 
			
		||||
                <h2 class="pf-c-nav__section-title">{% trans 'Sources' %}</h2>
 | 
			
		||||
                <ul class="pf-c-nav__list">
 | 
			
		||||
                    {% for inlet in user_inlets_loc %}
 | 
			
		||||
                    {% for source in user_sources_loc %}
 | 
			
		||||
                    <li class="pf-c-nav__item">
 | 
			
		||||
                        <a href="{{ inlet.view_name }}"
 | 
			
		||||
                        <a href="{{ source.view_name }}"
 | 
			
		||||
                            class="pf-c-nav__link {% if user_settings.view_name == request.get_full_path %} pf-m-current {% endif %}">
 | 
			
		||||
                            <i class="{{ inlet.icon }}"></i>
 | 
			
		||||
                            {{ inlet.name }}
 | 
			
		||||
                            <i class="{{ source.icon }}"></i>
 | 
			
		||||
                            {{ source.name }}
 | 
			
		||||
                        </a>
 | 
			
		||||
                    </li>
 | 
			
		||||
                    {% endfor %}
 | 
			
		||||
 | 
			
		||||
@ -4,7 +4,7 @@ from typing import Iterable, List
 | 
			
		||||
from django import template
 | 
			
		||||
from django.template.context import RequestContext
 | 
			
		||||
 | 
			
		||||
from passbook.core.models import Inlet
 | 
			
		||||
from passbook.core.models import Source
 | 
			
		||||
from passbook.core.types import UIUserSettings
 | 
			
		||||
from passbook.flows.models import Stage
 | 
			
		||||
from passbook.policies.engine import PolicyEngine
 | 
			
		||||
@ -27,14 +27,14 @@ def user_stages(context: RequestContext) -> List[UIUserSettings]:
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@register.simple_tag(takes_context=True)
 | 
			
		||||
def user_inlets(context: RequestContext) -> List[UIUserSettings]:
 | 
			
		||||
    """Return a list of all inlets which are enabled for the user"""
 | 
			
		||||
def user_sources(context: RequestContext) -> List[UIUserSettings]:
 | 
			
		||||
    """Return a list of all sources which are enabled for the user"""
 | 
			
		||||
    user = context.get("request").user
 | 
			
		||||
    _all_inlets: Iterable[(Inlet)] = (
 | 
			
		||||
        (Inlet).objects.filter(enabled=True).select_subclasses()
 | 
			
		||||
    _all_sources: Iterable[Source] = (
 | 
			
		||||
        Source.objects.filter(enabled=True).select_subclasses()
 | 
			
		||||
    )
 | 
			
		||||
    matching_inlets: List[UIUserSettings] = []
 | 
			
		||||
    for source in _all_inlets:
 | 
			
		||||
    matching_sources: List[UIUserSettings] = []
 | 
			
		||||
    for source in _all_sources:
 | 
			
		||||
        user_settings = source.ui_user_settings
 | 
			
		||||
        if not user_settings:
 | 
			
		||||
            continue
 | 
			
		||||
@ -43,5 +43,5 @@ def user_inlets(context: RequestContext) -> List[UIUserSettings]:
 | 
			
		||||
        )
 | 
			
		||||
        policy_engine.build()
 | 
			
		||||
        if policy_engine.passing:
 | 
			
		||||
            matching_inlets.append(user_settings)
 | 
			
		||||
    return matching_inlets
 | 
			
		||||
            matching_sources.append(user_settings)
 | 
			
		||||
    return matching_sources
 | 
			
		||||
 | 
			
		||||
@ -6,7 +6,7 @@ from django.http import HttpRequest
 | 
			
		||||
from django.utils.translation import gettext as _
 | 
			
		||||
from structlog import get_logger
 | 
			
		||||
 | 
			
		||||
from passbook.core.models import Application, Outlet, User
 | 
			
		||||
from passbook.core.models import Application, Provider, User
 | 
			
		||||
from passbook.policies.engine import PolicyEngine
 | 
			
		||||
 | 
			
		||||
LOGGER = get_logger()
 | 
			
		||||
@ -14,19 +14,22 @@ LOGGER = get_logger()
 | 
			
		||||
 | 
			
		||||
class AccessMixin:
 | 
			
		||||
    """Mixin class for usage in Authorization views.
 | 
			
		||||
    Outlet functions to check application access, etc"""
 | 
			
		||||
    Provider functions to check application access, etc"""
 | 
			
		||||
 | 
			
		||||
    # request is set by view but since this Mixin has no base class
 | 
			
		||||
    request: HttpRequest = None
 | 
			
		||||
 | 
			
		||||
    def outlet_to_application(self, outlet: Outlet) -> Application:
 | 
			
		||||
        """Lookup application assigned to outlet, throw error if no application assigned"""
 | 
			
		||||
    def provider_to_application(self, provider: Provider) -> Application:
 | 
			
		||||
        """Lookup application assigned to provider, throw error if no application assigned"""
 | 
			
		||||
        try:
 | 
			
		||||
            return outlet.application
 | 
			
		||||
            return provider.application
 | 
			
		||||
        except Application.DoesNotExist as exc:
 | 
			
		||||
            messages.error(
 | 
			
		||||
                self.request,
 | 
			
		||||
                _('Outlet "%(name)s" has no application assigned' % {"name": outlet}),
 | 
			
		||||
                _(
 | 
			
		||||
                    'Provider "%(name)s" has no application assigned'
 | 
			
		||||
                    % {"name": provider}
 | 
			
		||||
                ),
 | 
			
		||||
            )
 | 
			
		||||
            raise exc
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,10 +1,24 @@
 | 
			
		||||
# Generated by Django 3.0.5 on 2020-05-15 19:58
 | 
			
		||||
# Generated by Django 3.0.3 on 2020-03-03 21:45
 | 
			
		||||
 | 
			
		||||
import uuid
 | 
			
		||||
 | 
			
		||||
from django.db import migrations, models
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def create_self_signed(apps, schema_editor):
 | 
			
		||||
    CertificateKeyPair = apps.get_model("passbook_crypto", "CertificateKeyPair")
 | 
			
		||||
    db_alias = schema_editor.connection.alias
 | 
			
		||||
    from passbook.crypto.builder import CertificateBuilder
 | 
			
		||||
 | 
			
		||||
    builder = CertificateBuilder()
 | 
			
		||||
    builder.build()
 | 
			
		||||
    CertificateKeyPair.objects.using(db_alias).create(
 | 
			
		||||
        name="passbook Self-signed Certificate",
 | 
			
		||||
        certificate_data=builder.certificate,
 | 
			
		||||
        key_data=builder.private_key,
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Migration(migrations.Migration):
 | 
			
		||||
 | 
			
		||||
    initial = True
 | 
			
		||||
@ -27,22 +41,27 @@ class Migration(migrations.Migration):
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
                ("name", models.TextField()),
 | 
			
		||||
                (
 | 
			
		||||
                    "certificate_data",
 | 
			
		||||
                    models.TextField(help_text="PEM-encoded Certificate data"),
 | 
			
		||||
                ),
 | 
			
		||||
                (
 | 
			
		||||
                    "key_data",
 | 
			
		||||
                    models.TextField(
 | 
			
		||||
                        blank=True,
 | 
			
		||||
                        default="",
 | 
			
		||||
                        help_text="Optional Private Key. If this is set, you can use this keypair for encryption.",
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
                ("certificate_data", models.TextField()),
 | 
			
		||||
                ("key_data", models.TextField(blank=True, default="")),
 | 
			
		||||
            ],
 | 
			
		||||
            options={
 | 
			
		||||
                "verbose_name": "Certificate-Key Pair",
 | 
			
		||||
                "verbose_name_plural": "Certificate-Key Pairs",
 | 
			
		||||
            },
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.RunPython(create_self_signed),
 | 
			
		||||
        migrations.AlterField(
 | 
			
		||||
            model_name="certificatekeypair",
 | 
			
		||||
            name="certificate_data",
 | 
			
		||||
            field=models.TextField(help_text="PEM-encoded Certificate data"),
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.AlterField(
 | 
			
		||||
            model_name="certificatekeypair",
 | 
			
		||||
            name="key_data",
 | 
			
		||||
            field=models.TextField(
 | 
			
		||||
                blank=True,
 | 
			
		||||
                default="",
 | 
			
		||||
                help_text="Optional Private Key. If this is set, you can use this keypair for encryption.",
 | 
			
		||||
            ),
 | 
			
		||||
        ),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
# Generated by Django 3.0.5 on 2020-05-15 19:58
 | 
			
		||||
# Generated by Django 3.0.3 on 2020-05-08 18:27
 | 
			
		||||
 | 
			
		||||
import uuid
 | 
			
		||||
 | 
			
		||||
@ -11,7 +11,7 @@ class Migration(migrations.Migration):
 | 
			
		||||
    initial = True
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        ("passbook_policies", "__first__"),
 | 
			
		||||
        ("passbook_policies", "0003_auto_20200508_1642"),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
@ -33,12 +33,10 @@ class Migration(migrations.Migration):
 | 
			
		||||
                    "designation",
 | 
			
		||||
                    models.CharField(
 | 
			
		||||
                        choices=[
 | 
			
		||||
                            ("authentication", "Authentication"),
 | 
			
		||||
                            ("invalidation", "Invalidation"),
 | 
			
		||||
                            ("enrollment", "Enrollment"),
 | 
			
		||||
                            ("unenrollment", "Unrenollment"),
 | 
			
		||||
                            ("recovery", "Recovery"),
 | 
			
		||||
                            ("password_change", "Password Change"),
 | 
			
		||||
                            ("AUTHENTICATION", "authentication"),
 | 
			
		||||
                            ("ENROLLMENT", "enrollment"),
 | 
			
		||||
                            ("RECOVERY", "recovery"),
 | 
			
		||||
                            ("PASSWORD_CHANGE", "password_change"),
 | 
			
		||||
                        ],
 | 
			
		||||
                        max_length=100,
 | 
			
		||||
                    ),
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										26
									
								
								passbook/flows/migrations/0003_auto_20200509_1258.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								passbook/flows/migrations/0003_auto_20200509_1258.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,26 @@
 | 
			
		||||
# Generated by Django 3.0.3 on 2020-05-09 12:58
 | 
			
		||||
 | 
			
		||||
from django.db import migrations, models
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Migration(migrations.Migration):
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        ("passbook_flows", "0002_default_flows"),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
        migrations.AlterField(
 | 
			
		||||
            model_name="flow",
 | 
			
		||||
            name="designation",
 | 
			
		||||
            field=models.CharField(
 | 
			
		||||
                choices=[
 | 
			
		||||
                    ("authentication", "Authentication"),
 | 
			
		||||
                    ("enrollment", "Enrollment"),
 | 
			
		||||
                    ("recovery", "Recovery"),
 | 
			
		||||
                    ("password_change", "Password Change"),
 | 
			
		||||
                ],
 | 
			
		||||
                max_length=100,
 | 
			
		||||
            ),
 | 
			
		||||
        ),
 | 
			
		||||
    ]
 | 
			
		||||
							
								
								
									
										27
									
								
								passbook/flows/migrations/0004_auto_20200510_2310.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								passbook/flows/migrations/0004_auto_20200510_2310.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,27 @@
 | 
			
		||||
# Generated by Django 3.0.5 on 2020-05-10 23:10
 | 
			
		||||
 | 
			
		||||
from django.db import migrations, models
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Migration(migrations.Migration):
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        ("passbook_flows", "0003_auto_20200509_1258"),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
        migrations.AlterField(
 | 
			
		||||
            model_name="flow",
 | 
			
		||||
            name="designation",
 | 
			
		||||
            field=models.CharField(
 | 
			
		||||
                choices=[
 | 
			
		||||
                    ("authentication", "Authentication"),
 | 
			
		||||
                    ("enrollment", "Enrollment"),
 | 
			
		||||
                    ("recovery", "Recovery"),
 | 
			
		||||
                    ("password_change", "Password Change"),
 | 
			
		||||
                    ("invalidation", "Invalidation"),
 | 
			
		||||
                ],
 | 
			
		||||
                max_length=100,
 | 
			
		||||
            ),
 | 
			
		||||
        ),
 | 
			
		||||
    ]
 | 
			
		||||
							
								
								
									
										28
									
								
								passbook/flows/migrations/0005_auto_20200512_1158.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								passbook/flows/migrations/0005_auto_20200512_1158.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,28 @@
 | 
			
		||||
# Generated by Django 3.0.5 on 2020-05-12 11:58
 | 
			
		||||
 | 
			
		||||
from django.db import migrations, models
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Migration(migrations.Migration):
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        ("passbook_flows", "0004_auto_20200510_2310"),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
        migrations.AlterField(
 | 
			
		||||
            model_name="flow",
 | 
			
		||||
            name="designation",
 | 
			
		||||
            field=models.CharField(
 | 
			
		||||
                choices=[
 | 
			
		||||
                    ("authentication", "Authentication"),
 | 
			
		||||
                    ("invalidation", "Invalidation"),
 | 
			
		||||
                    ("enrollment", "Enrollment"),
 | 
			
		||||
                    ("unenrollment", "Unrenollment"),
 | 
			
		||||
                    ("recovery", "Recovery"),
 | 
			
		||||
                    ("password_change", "Password Change"),
 | 
			
		||||
                ],
 | 
			
		||||
                max_length=100,
 | 
			
		||||
            ),
 | 
			
		||||
        ),
 | 
			
		||||
    ]
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
# Generated by Django 3.0.5 on 2020-05-15 19:58
 | 
			
		||||
# Generated by Django 3.0.5 on 2020-05-10 10:01
 | 
			
		||||
 | 
			
		||||
import django.db.models.deletion
 | 
			
		||||
from django.db import migrations, models
 | 
			
		||||
@ -9,7 +9,8 @@ class Migration(migrations.Migration):
 | 
			
		||||
    initial = True
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        ("passbook_policies", "0001_initial"),
 | 
			
		||||
        ("passbook_policies", "0003_auto_20200508_1642"),
 | 
			
		||||
        ("passbook_core", "0013_delete_debugpolicy"),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
@ -24,7 +25,7 @@ class Migration(migrations.Migration):
 | 
			
		||||
                        parent_link=True,
 | 
			
		||||
                        primary_key=True,
 | 
			
		||||
                        serialize=False,
 | 
			
		||||
                        to="passbook_policies.Policy",
 | 
			
		||||
                        to="passbook_core.Policy",
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
                ("result", models.BooleanField(default=False)),
 | 
			
		||||
@ -35,6 +36,6 @@ class Migration(migrations.Migration):
 | 
			
		||||
                "verbose_name": "Dummy Policy",
 | 
			
		||||
                "verbose_name_plural": "Dummy Policies",
 | 
			
		||||
            },
 | 
			
		||||
            bases=("passbook_policies.policy",),
 | 
			
		||||
            bases=("passbook_core.policy",),
 | 
			
		||||
        ),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
@ -6,7 +6,7 @@ from django.db import models
 | 
			
		||||
from django.utils.translation import gettext_lazy as _
 | 
			
		||||
from structlog import get_logger
 | 
			
		||||
 | 
			
		||||
from passbook.policies.models import Policy
 | 
			
		||||
from passbook.core.models import Policy
 | 
			
		||||
from passbook.policies.types import PolicyRequest, PolicyResult
 | 
			
		||||
 | 
			
		||||
LOGGER = get_logger()
 | 
			
		||||
 | 
			
		||||
@ -7,8 +7,7 @@ from django.core.cache import cache
 | 
			
		||||
from django.http import HttpRequest
 | 
			
		||||
from structlog import get_logger
 | 
			
		||||
 | 
			
		||||
from passbook.core.models import User
 | 
			
		||||
from passbook.policies.models import Policy
 | 
			
		||||
from passbook.core.models import Policy, User
 | 
			
		||||
from passbook.policies.process import PolicyProcess, cache_key
 | 
			
		||||
from passbook.policies.types import PolicyRequest, PolicyResult
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
# Generated by Django 3.0.5 on 2020-05-15 19:58
 | 
			
		||||
# Generated by Django 2.2.6 on 2019-10-07 14:07
 | 
			
		||||
 | 
			
		||||
import django.db.models.deletion
 | 
			
		||||
from django.db import migrations, models
 | 
			
		||||
@ -9,7 +9,7 @@ class Migration(migrations.Migration):
 | 
			
		||||
    initial = True
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        ("passbook_policies", "0001_initial"),
 | 
			
		||||
        ("passbook_core", "0001_initial"),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
@ -24,7 +24,7 @@ class Migration(migrations.Migration):
 | 
			
		||||
                        parent_link=True,
 | 
			
		||||
                        primary_key=True,
 | 
			
		||||
                        serialize=False,
 | 
			
		||||
                        to="passbook_policies.Policy",
 | 
			
		||||
                        to="passbook_core.Policy",
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
                ("deny_only", models.BooleanField(default=False)),
 | 
			
		||||
@ -34,6 +34,6 @@ class Migration(migrations.Migration):
 | 
			
		||||
                "verbose_name": "Password Expiry Policy",
 | 
			
		||||
                "verbose_name_plural": "Password Expiry Policies",
 | 
			
		||||
            },
 | 
			
		||||
            bases=("passbook_policies.policy",),
 | 
			
		||||
            bases=("passbook_core.policy",),
 | 
			
		||||
        ),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
@ -6,7 +6,7 @@ from django.utils.timezone import now
 | 
			
		||||
from django.utils.translation import gettext as _
 | 
			
		||||
from structlog import get_logger
 | 
			
		||||
 | 
			
		||||
from passbook.policies.models import Policy
 | 
			
		||||
from passbook.core.models import Policy
 | 
			
		||||
from passbook.policies.types import PolicyRequest, PolicyResult
 | 
			
		||||
 | 
			
		||||
LOGGER = get_logger()
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
# Generated by Django 3.0.5 on 2020-05-15 19:59
 | 
			
		||||
# Generated by Django 3.0.3 on 2020-02-18 14:00
 | 
			
		||||
 | 
			
		||||
import django.db.models.deletion
 | 
			
		||||
from django.db import migrations, models
 | 
			
		||||
@ -9,7 +9,7 @@ class Migration(migrations.Migration):
 | 
			
		||||
    initial = True
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        ("passbook_policies", "0001_initial"),
 | 
			
		||||
        ("passbook_core", "0007_auto_20200217_1934"),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
@ -24,7 +24,7 @@ class Migration(migrations.Migration):
 | 
			
		||||
                        parent_link=True,
 | 
			
		||||
                        primary_key=True,
 | 
			
		||||
                        serialize=False,
 | 
			
		||||
                        to="passbook_policies.Policy",
 | 
			
		||||
                        to="passbook_core.Policy",
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
                ("expression", models.TextField()),
 | 
			
		||||
@ -33,6 +33,6 @@ class Migration(migrations.Migration):
 | 
			
		||||
                "verbose_name": "Expression Policy",
 | 
			
		||||
                "verbose_name_plural": "Expression Policies",
 | 
			
		||||
            },
 | 
			
		||||
            bases=("passbook_policies.policy",),
 | 
			
		||||
            bases=("passbook_core.policy",),
 | 
			
		||||
        ),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
@ -2,8 +2,8 @@
 | 
			
		||||
from django.db import models
 | 
			
		||||
from django.utils.translation import gettext as _
 | 
			
		||||
 | 
			
		||||
from passbook.core.models import Policy
 | 
			
		||||
from passbook.policies.expression.evaluator import Evaluator
 | 
			
		||||
from passbook.policies.models import Policy
 | 
			
		||||
from passbook.policies.types import PolicyRequest, PolicyResult
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
# Generated by Django 3.0.5 on 2020-05-15 19:59
 | 
			
		||||
# Generated by Django 2.2.6 on 2019-10-07 14:07
 | 
			
		||||
 | 
			
		||||
import django.db.models.deletion
 | 
			
		||||
from django.db import migrations, models
 | 
			
		||||
@ -9,7 +9,7 @@ class Migration(migrations.Migration):
 | 
			
		||||
    initial = True
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        ("passbook_policies", "0001_initial"),
 | 
			
		||||
        ("passbook_core", "0001_initial"),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
@ -24,7 +24,7 @@ class Migration(migrations.Migration):
 | 
			
		||||
                        parent_link=True,
 | 
			
		||||
                        primary_key=True,
 | 
			
		||||
                        serialize=False,
 | 
			
		||||
                        to="passbook_policies.Policy",
 | 
			
		||||
                        to="passbook_core.Policy",
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
                ("allowed_count", models.IntegerField(default=0)),
 | 
			
		||||
@ -33,6 +33,6 @@ class Migration(migrations.Migration):
 | 
			
		||||
                "verbose_name": "Have I Been Pwned Policy",
 | 
			
		||||
                "verbose_name_plural": "Have I Been Pwned Policies",
 | 
			
		||||
            },
 | 
			
		||||
            bases=("passbook_policies.policy",),
 | 
			
		||||
            bases=("passbook_core.policy",),
 | 
			
		||||
        ),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
@ -6,8 +6,7 @@ from django.utils.translation import gettext as _
 | 
			
		||||
from requests import get
 | 
			
		||||
from structlog import get_logger
 | 
			
		||||
 | 
			
		||||
from passbook.policies.models import Policy
 | 
			
		||||
from passbook.policies.types import PolicyRequest, PolicyResult
 | 
			
		||||
from passbook.core.models import Policy, PolicyResult, User
 | 
			
		||||
 | 
			
		||||
LOGGER = get_logger()
 | 
			
		||||
 | 
			
		||||
@ -20,14 +19,14 @@ class HaveIBeenPwendPolicy(Policy):
 | 
			
		||||
 | 
			
		||||
    form = "passbook.policies.hibp.forms.HaveIBeenPwnedPolicyForm"
 | 
			
		||||
 | 
			
		||||
    def passes(self, request: PolicyRequest) -> PolicyResult:
 | 
			
		||||
    def passes(self, user: User) -> PolicyResult:
 | 
			
		||||
        """Check if password is in HIBP DB. Hashes given Password with SHA1, uses the first 5
 | 
			
		||||
        characters of Password in request and checks if full hash is in response. Returns 0
 | 
			
		||||
        if Password is not in result otherwise the count of how many times it was used."""
 | 
			
		||||
        # Only check if password is being set
 | 
			
		||||
        if not hasattr(request.user, "__password__"):
 | 
			
		||||
        if not hasattr(user, "__password__"):
 | 
			
		||||
            return PolicyResult(True)
 | 
			
		||||
        password = getattr(request.user, "__password__")
 | 
			
		||||
        password = getattr(user, "__password__")
 | 
			
		||||
        pw_hash = sha1(password.encode("utf-8")).hexdigest()  # nosec
 | 
			
		||||
        url = "https://api.pwnedpasswords.com/range/%s" % pw_hash[:5]
 | 
			
		||||
        result = get(url).text
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
# Generated by Django 3.0.5 on 2020-05-15 19:58
 | 
			
		||||
# Generated by Django 3.0.3 on 2020-05-07 18:35
 | 
			
		||||
 | 
			
		||||
import uuid
 | 
			
		||||
 | 
			
		||||
@ -10,30 +10,11 @@ class Migration(migrations.Migration):
 | 
			
		||||
 | 
			
		||||
    initial = True
 | 
			
		||||
 | 
			
		||||
    dependencies = []
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        ("passbook_core", "0011_auto_20200222_1822"),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
        migrations.CreateModel(
 | 
			
		||||
            name="Policy",
 | 
			
		||||
            fields=[
 | 
			
		||||
                ("created", models.DateTimeField(auto_now_add=True)),
 | 
			
		||||
                ("last_updated", models.DateTimeField(auto_now=True)),
 | 
			
		||||
                (
 | 
			
		||||
                    "uuid",
 | 
			
		||||
                    models.UUIDField(
 | 
			
		||||
                        default=uuid.uuid4,
 | 
			
		||||
                        editable=False,
 | 
			
		||||
                        primary_key=True,
 | 
			
		||||
                        serialize=False,
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
                ("name", models.TextField(blank=True, null=True)),
 | 
			
		||||
                ("negate", models.BooleanField(default=False)),
 | 
			
		||||
                ("order", models.IntegerField(default=0)),
 | 
			
		||||
                ("timeout", models.IntegerField(default=30)),
 | 
			
		||||
            ],
 | 
			
		||||
            options={"abstract": False,},
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.CreateModel(
 | 
			
		||||
            name="PolicyBinding",
 | 
			
		||||
            fields=[
 | 
			
		||||
@ -53,7 +34,7 @@ class Migration(migrations.Migration):
 | 
			
		||||
                    models.ForeignKey(
 | 
			
		||||
                        on_delete=django.db.models.deletion.CASCADE,
 | 
			
		||||
                        related_name="+",
 | 
			
		||||
                        to="passbook_policies.Policy",
 | 
			
		||||
                        to="passbook_core.Policy",
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
            ],
 | 
			
		||||
@ -77,17 +58,12 @@ class Migration(migrations.Migration):
 | 
			
		||||
                (
 | 
			
		||||
                    "policies",
 | 
			
		||||
                    models.ManyToManyField(
 | 
			
		||||
                        blank=True,
 | 
			
		||||
                        related_name="_policybindingmodel_policies_+",
 | 
			
		||||
                        through="passbook_policies.PolicyBinding",
 | 
			
		||||
                        to="passbook_policies.Policy",
 | 
			
		||||
                        to="passbook_core.Policy",
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
            ],
 | 
			
		||||
            options={
 | 
			
		||||
                "verbose_name": "Policy Binding Model",
 | 
			
		||||
                "verbose_name_plural": "Policy Binding Models",
 | 
			
		||||
            },
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.AddField(
 | 
			
		||||
            model_name="policybinding",
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										20
									
								
								passbook/policies/migrations/0002_auto_20200508_1230.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								passbook/policies/migrations/0002_auto_20200508_1230.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,20 @@
 | 
			
		||||
# Generated by Django 3.0.3 on 2020-05-08 12:30
 | 
			
		||||
 | 
			
		||||
from django.db import migrations
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Migration(migrations.Migration):
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        ("passbook_policies", "0001_initial"),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
        migrations.AlterModelOptions(
 | 
			
		||||
            name="policybindingmodel",
 | 
			
		||||
            options={
 | 
			
		||||
                "verbose_name": "Policy Binding Model",
 | 
			
		||||
                "verbose_name_plural": "Policy Binding Models",
 | 
			
		||||
            },
 | 
			
		||||
        ),
 | 
			
		||||
    ]
 | 
			
		||||
							
								
								
									
										24
									
								
								passbook/policies/migrations/0003_auto_20200508_1642.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								passbook/policies/migrations/0003_auto_20200508_1642.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,24 @@
 | 
			
		||||
# Generated by Django 3.0.3 on 2020-05-08 16:42
 | 
			
		||||
 | 
			
		||||
from django.db import migrations, models
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Migration(migrations.Migration):
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        ("passbook_core", "0011_auto_20200222_1822"),
 | 
			
		||||
        ("passbook_policies", "0002_auto_20200508_1230"),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
        migrations.AlterField(
 | 
			
		||||
            model_name="policybindingmodel",
 | 
			
		||||
            name="policies",
 | 
			
		||||
            field=models.ManyToManyField(
 | 
			
		||||
                blank=True,
 | 
			
		||||
                related_name="_policybindingmodel_policies_+",
 | 
			
		||||
                through="passbook_policies.PolicyBinding",
 | 
			
		||||
                to="passbook_core.Policy",
 | 
			
		||||
            ),
 | 
			
		||||
        ),
 | 
			
		||||
    ]
 | 
			
		||||
@ -1,30 +1,9 @@
 | 
			
		||||
"""Policy base models"""
 | 
			
		||||
from django.db import models
 | 
			
		||||
from django.utils.translation import gettext_lazy as _
 | 
			
		||||
from model_utils.managers import InheritanceManager
 | 
			
		||||
 | 
			
		||||
from passbook.lib.models import CreatedUpdatedModel, UUIDModel
 | 
			
		||||
from passbook.policies.exceptions import PolicyException
 | 
			
		||||
from passbook.policies.types import PolicyRequest, PolicyResult
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Policy(UUIDModel, CreatedUpdatedModel):
 | 
			
		||||
    """Policies which specify if a user is authorized to use an Application. Can be overridden by
 | 
			
		||||
    other types to add other fields, more logic, etc."""
 | 
			
		||||
 | 
			
		||||
    name = models.TextField(blank=True, null=True)
 | 
			
		||||
    negate = models.BooleanField(default=False)
 | 
			
		||||
    order = models.IntegerField(default=0)
 | 
			
		||||
    timeout = models.IntegerField(default=30)
 | 
			
		||||
 | 
			
		||||
    objects = InheritanceManager()
 | 
			
		||||
 | 
			
		||||
    def __str__(self):
 | 
			
		||||
        return f"Policy {self.name}"
 | 
			
		||||
 | 
			
		||||
    def passes(self, request: PolicyRequest) -> PolicyResult:
 | 
			
		||||
        """Check if user instance passes this policy"""
 | 
			
		||||
        raise PolicyException()
 | 
			
		||||
from passbook.core.models import Policy
 | 
			
		||||
from passbook.lib.models import UUIDModel
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class PolicyBindingModel(models.Model):
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
# Generated by Django 3.0.5 on 2020-05-15 19:59
 | 
			
		||||
# Generated by Django 2.2.6 on 2019-10-07 14:07
 | 
			
		||||
 | 
			
		||||
import django.db.models.deletion
 | 
			
		||||
from django.db import migrations, models
 | 
			
		||||
@ -9,7 +9,7 @@ class Migration(migrations.Migration):
 | 
			
		||||
    initial = True
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        ("passbook_policies", "0001_initial"),
 | 
			
		||||
        ("passbook_core", "0001_initial"),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
@ -24,7 +24,7 @@ class Migration(migrations.Migration):
 | 
			
		||||
                        parent_link=True,
 | 
			
		||||
                        primary_key=True,
 | 
			
		||||
                        serialize=False,
 | 
			
		||||
                        to="passbook_policies.Policy",
 | 
			
		||||
                        to="passbook_core.Policy",
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
                ("amount_uppercase", models.IntegerField(default=0)),
 | 
			
		||||
@ -41,6 +41,6 @@ class Migration(migrations.Migration):
 | 
			
		||||
                "verbose_name": "Password Policy",
 | 
			
		||||
                "verbose_name_plural": "Password Policies",
 | 
			
		||||
            },
 | 
			
		||||
            bases=("passbook_policies.policy",),
 | 
			
		||||
            bases=("passbook_core.policy",),
 | 
			
		||||
        ),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
@ -5,7 +5,7 @@ from django.db import models
 | 
			
		||||
from django.utils.translation import gettext as _
 | 
			
		||||
from structlog import get_logger
 | 
			
		||||
 | 
			
		||||
from passbook.policies.models import Policy
 | 
			
		||||
from passbook.core.models import Policy
 | 
			
		||||
from passbook.policies.types import PolicyRequest, PolicyResult
 | 
			
		||||
 | 
			
		||||
LOGGER = get_logger()
 | 
			
		||||
 | 
			
		||||
@ -6,9 +6,8 @@ from typing import Optional
 | 
			
		||||
from django.core.cache import cache
 | 
			
		||||
from structlog import get_logger
 | 
			
		||||
 | 
			
		||||
from passbook.core.models import User
 | 
			
		||||
from passbook.core.models import Policy, User
 | 
			
		||||
from passbook.policies.exceptions import PolicyException
 | 
			
		||||
from passbook.policies.models import Policy
 | 
			
		||||
from passbook.policies.types import PolicyRequest, PolicyResult
 | 
			
		||||
 | 
			
		||||
LOGGER = get_logger()
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
# Generated by Django 3.0.5 on 2020-05-15 19:59
 | 
			
		||||
# Generated by Django 2.2.6 on 2019-10-07 14:07
 | 
			
		||||
 | 
			
		||||
import django.db.models.deletion
 | 
			
		||||
from django.conf import settings
 | 
			
		||||
@ -10,7 +10,7 @@ class Migration(migrations.Migration):
 | 
			
		||||
    initial = True
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        ("passbook_policies", "0001_initial"),
 | 
			
		||||
        ("passbook_core", "0001_initial"),
 | 
			
		||||
        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
@ -43,7 +43,7 @@ class Migration(migrations.Migration):
 | 
			
		||||
                        parent_link=True,
 | 
			
		||||
                        primary_key=True,
 | 
			
		||||
                        serialize=False,
 | 
			
		||||
                        to="passbook_policies.Policy",
 | 
			
		||||
                        to="passbook_core.Policy",
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
                ("check_ip", models.BooleanField(default=True)),
 | 
			
		||||
@ -54,7 +54,7 @@ class Migration(migrations.Migration):
 | 
			
		||||
                "verbose_name": "Reputation Policy",
 | 
			
		||||
                "verbose_name_plural": "Reputation Policies",
 | 
			
		||||
            },
 | 
			
		||||
            bases=("passbook_policies.policy",),
 | 
			
		||||
            bases=("passbook_core.policy",),
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.CreateModel(
 | 
			
		||||
            name="UserReputation",
 | 
			
		||||
 | 
			
		||||
@ -2,9 +2,8 @@
 | 
			
		||||
from django.db import models
 | 
			
		||||
from django.utils.translation import gettext as _
 | 
			
		||||
 | 
			
		||||
from passbook.core.models import User
 | 
			
		||||
from passbook.core.models import Policy, User
 | 
			
		||||
from passbook.lib.utils.http import get_client_ip
 | 
			
		||||
from passbook.policies.models import Policy
 | 
			
		||||
from passbook.policies.types import PolicyRequest, PolicyResult
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -2,10 +2,9 @@
 | 
			
		||||
from django.core.cache import cache
 | 
			
		||||
from django.test import TestCase
 | 
			
		||||
 | 
			
		||||
from passbook.core.models import User
 | 
			
		||||
from passbook.core.models import Policy, User
 | 
			
		||||
from passbook.policies.dummy.models import DummyPolicy
 | 
			
		||||
from passbook.policies.engine import PolicyEngine
 | 
			
		||||
from passbook.policies.models import Policy
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class PolicyTestEngine(TestCase):
 | 
			
		||||
 | 
			
		||||
@ -1,17 +1,17 @@
 | 
			
		||||
"""ApplicationGatewayOutlet API Views"""
 | 
			
		||||
"""ApplicationGatewayProvider API Views"""
 | 
			
		||||
from oauth2_provider.generators import generate_client_id, generate_client_secret
 | 
			
		||||
from oidc_provider.models import Client
 | 
			
		||||
from rest_framework.serializers import ModelSerializer
 | 
			
		||||
from rest_framework.viewsets import ModelViewSet
 | 
			
		||||
 | 
			
		||||
from passbook.channels.out_app_gw.models import ApplicationGatewayOutlet
 | 
			
		||||
from passbook.channels.out_oidc.api import OpenIDOutletSerializer
 | 
			
		||||
from passbook.providers.app_gw.models import ApplicationGatewayProvider
 | 
			
		||||
from passbook.providers.oidc.api import OpenIDProviderSerializer
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ApplicationGatewayOutletSerializer(ModelSerializer):
 | 
			
		||||
    """ApplicationGatewayOutlet Serializer"""
 | 
			
		||||
class ApplicationGatewayProviderSerializer(ModelSerializer):
 | 
			
		||||
    """ApplicationGatewayProvider Serializer"""
 | 
			
		||||
 | 
			
		||||
    client = OpenIDOutletSerializer()
 | 
			
		||||
    client = OpenIDProviderSerializer()
 | 
			
		||||
 | 
			
		||||
    def create(self, validated_data):
 | 
			
		||||
        instance = super().create(validated_data)
 | 
			
		||||
@ -33,13 +33,13 @@ class ApplicationGatewayOutletSerializer(ModelSerializer):
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
 | 
			
		||||
        model = ApplicationGatewayOutlet
 | 
			
		||||
        model = ApplicationGatewayProvider
 | 
			
		||||
        fields = ["pk", "name", "internal_host", "external_host", "client"]
 | 
			
		||||
        read_only_fields = ["client"]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ApplicationGatewayOutletViewSet(ModelViewSet):
 | 
			
		||||
    """ApplicationGatewayOutlet Viewset"""
 | 
			
		||||
class ApplicationGatewayProviderViewSet(ModelViewSet):
 | 
			
		||||
    """ApplicationGatewayProvider Viewset"""
 | 
			
		||||
 | 
			
		||||
    queryset = ApplicationGatewayOutlet.objects.all()
 | 
			
		||||
    serializer_class = ApplicationGatewayOutletSerializer
 | 
			
		||||
    queryset = ApplicationGatewayProvider.objects.all()
 | 
			
		||||
    serializer_class = ApplicationGatewayProviderSerializer
 | 
			
		||||
@ -5,7 +5,7 @@ from django.apps import AppConfig
 | 
			
		||||
class PassbookApplicationApplicationGatewayConfig(AppConfig):
 | 
			
		||||
    """passbook app_gw app"""
 | 
			
		||||
 | 
			
		||||
    name = "passbook.channels.out_app_gw"
 | 
			
		||||
    label = "passbook_channels_out_app_gw"
 | 
			
		||||
    verbose_name = "passbook Outlets.Application Security Gateway"
 | 
			
		||||
    name = "passbook.providers.app_gw"
 | 
			
		||||
    label = "passbook_providers_app_gw"
 | 
			
		||||
    verbose_name = "passbook Providers.Application Security Gateway"
 | 
			
		||||
    mountpoint = "application/gateway/"
 | 
			
		||||
@ -3,11 +3,11 @@ from django import forms
 | 
			
		||||
from oauth2_provider.generators import generate_client_id, generate_client_secret
 | 
			
		||||
from oidc_provider.models import Client, ResponseType
 | 
			
		||||
 | 
			
		||||
from passbook.channels.out_app_gw.models import ApplicationGatewayOutlet
 | 
			
		||||
from passbook.providers.app_gw.models import ApplicationGatewayProvider
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ApplicationGatewayOutletForm(forms.ModelForm):
 | 
			
		||||
    """Security Gateway Outlet form"""
 | 
			
		||||
class ApplicationGatewayProviderForm(forms.ModelForm):
 | 
			
		||||
    """Security Gateway Provider form"""
 | 
			
		||||
 | 
			
		||||
    def save(self, *args, **kwargs):
 | 
			
		||||
        if not self.instance.pk:
 | 
			
		||||
@ -31,7 +31,7 @@ class ApplicationGatewayOutletForm(forms.ModelForm):
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
 | 
			
		||||
        model = ApplicationGatewayOutlet
 | 
			
		||||
        model = ApplicationGatewayProvider
 | 
			
		||||
        fields = ["name", "internal_host", "external_host"]
 | 
			
		||||
        widgets = {
 | 
			
		||||
            "name": forms.TextInput(),
 | 
			
		||||
							
								
								
									
										99
									
								
								passbook/providers/app_gw/migrations/0001_initial.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								passbook/providers/app_gw/migrations/0001_initial.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,99 @@
 | 
			
		||||
# Generated by Django 2.2.6 on 2019-10-07 14:07
 | 
			
		||||
 | 
			
		||||
import django.contrib.postgres.fields
 | 
			
		||||
import django.db.models.deletion
 | 
			
		||||
from django.db import migrations, models
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Migration(migrations.Migration):
 | 
			
		||||
 | 
			
		||||
    initial = True
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        ("passbook_core", "0001_initial"),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
        migrations.CreateModel(
 | 
			
		||||
            name="ApplicationGatewayProvider",
 | 
			
		||||
            fields=[
 | 
			
		||||
                (
 | 
			
		||||
                    "provider_ptr",
 | 
			
		||||
                    models.OneToOneField(
 | 
			
		||||
                        auto_created=True,
 | 
			
		||||
                        on_delete=django.db.models.deletion.CASCADE,
 | 
			
		||||
                        parent_link=True,
 | 
			
		||||
                        primary_key=True,
 | 
			
		||||
                        serialize=False,
 | 
			
		||||
                        to="passbook_core.Provider",
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
                (
 | 
			
		||||
                    "server_name",
 | 
			
		||||
                    django.contrib.postgres.fields.ArrayField(
 | 
			
		||||
                        base_field=models.TextField(), size=None
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
                (
 | 
			
		||||
                    "upstream",
 | 
			
		||||
                    django.contrib.postgres.fields.ArrayField(
 | 
			
		||||
                        base_field=models.TextField(), size=None
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
                ("enabled", models.BooleanField(default=True)),
 | 
			
		||||
                (
 | 
			
		||||
                    "authentication_header",
 | 
			
		||||
                    models.TextField(blank=True, default="X-Remote-User"),
 | 
			
		||||
                ),
 | 
			
		||||
                (
 | 
			
		||||
                    "default_content_type",
 | 
			
		||||
                    models.TextField(default="application/octet-stream"),
 | 
			
		||||
                ),
 | 
			
		||||
                ("upstream_ssl_verification", models.BooleanField(default=True)),
 | 
			
		||||
            ],
 | 
			
		||||
            options={
 | 
			
		||||
                "verbose_name": "Application Gateway Provider",
 | 
			
		||||
                "verbose_name_plural": "Application Gateway Providers",
 | 
			
		||||
            },
 | 
			
		||||
            bases=("passbook_core.provider",),
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.CreateModel(
 | 
			
		||||
            name="RewriteRule",
 | 
			
		||||
            fields=[
 | 
			
		||||
                (
 | 
			
		||||
                    "propertymapping_ptr",
 | 
			
		||||
                    models.OneToOneField(
 | 
			
		||||
                        auto_created=True,
 | 
			
		||||
                        on_delete=django.db.models.deletion.CASCADE,
 | 
			
		||||
                        parent_link=True,
 | 
			
		||||
                        primary_key=True,
 | 
			
		||||
                        serialize=False,
 | 
			
		||||
                        to="passbook_core.PropertyMapping",
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
                ("match", models.TextField()),
 | 
			
		||||
                ("halt", models.BooleanField(default=False)),
 | 
			
		||||
                ("replacement", models.TextField()),
 | 
			
		||||
                (
 | 
			
		||||
                    "redirect",
 | 
			
		||||
                    models.CharField(
 | 
			
		||||
                        choices=[
 | 
			
		||||
                            ("internal", "Internal"),
 | 
			
		||||
                            (301, "Moved Permanently"),
 | 
			
		||||
                            (302, "Found"),
 | 
			
		||||
                        ],
 | 
			
		||||
                        max_length=50,
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
                (
 | 
			
		||||
                    "conditions",
 | 
			
		||||
                    models.ManyToManyField(blank=True, to="passbook_core.Policy"),
 | 
			
		||||
                ),
 | 
			
		||||
            ],
 | 
			
		||||
            options={
 | 
			
		||||
                "verbose_name": "Rewrite Rule",
 | 
			
		||||
                "verbose_name_plural": "Rewrite Rules",
 | 
			
		||||
            },
 | 
			
		||||
            bases=("passbook_core.propertymapping",),
 | 
			
		||||
        ),
 | 
			
		||||
    ]
 | 
			
		||||
@ -0,0 +1,18 @@
 | 
			
		||||
# Generated by Django 2.2.7 on 2019-11-11 17:03
 | 
			
		||||
 | 
			
		||||
from django.db import migrations
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Migration(migrations.Migration):
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        ("passbook_core", "0005_merge_20191025_2022"),
 | 
			
		||||
        ("passbook_providers_app_gw", "0001_initial"),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
        migrations.RemoveField(model_name="rewriterule", name="conditions",),
 | 
			
		||||
        migrations.RemoveField(model_name="rewriterule", name="propertymapping_ptr",),
 | 
			
		||||
        migrations.DeleteModel(name="ApplicationGatewayProvider",),
 | 
			
		||||
        migrations.DeleteModel(name="RewriteRule",),
 | 
			
		||||
    ]
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
# Generated by Django 3.0.5 on 2020-05-15 19:59
 | 
			
		||||
# Generated by Django 2.2.7 on 2019-11-11 17:08
 | 
			
		||||
 | 
			
		||||
import django.db.models.deletion
 | 
			
		||||
from django.db import migrations, models
 | 
			
		||||
@ -9,28 +9,28 @@ class Migration(migrations.Migration):
 | 
			
		||||
    initial = True
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        ("passbook_core", "__first__"),
 | 
			
		||||
        ("passbook_core", "0005_merge_20191025_2022"),
 | 
			
		||||
        ("oidc_provider", "0026_client_multiple_response_types"),
 | 
			
		||||
        ("passbook_providers_app_gw", "0002_auto_20191111_1703"),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
        migrations.CreateModel(
 | 
			
		||||
            name="ApplicationGatewayOutlet",
 | 
			
		||||
            name="ApplicationGatewayProvider",
 | 
			
		||||
            fields=[
 | 
			
		||||
                (
 | 
			
		||||
                    "outlet_ptr",
 | 
			
		||||
                    "provider_ptr",
 | 
			
		||||
                    models.OneToOneField(
 | 
			
		||||
                        auto_created=True,
 | 
			
		||||
                        on_delete=django.db.models.deletion.CASCADE,
 | 
			
		||||
                        parent_link=True,
 | 
			
		||||
                        primary_key=True,
 | 
			
		||||
                        serialize=False,
 | 
			
		||||
                        to="passbook_core.Outlet",
 | 
			
		||||
                        to="passbook_core.Provider",
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
                ("name", models.TextField()),
 | 
			
		||||
                ("internal_host", models.TextField()),
 | 
			
		||||
                ("external_host", models.TextField()),
 | 
			
		||||
                ("host", models.TextField()),
 | 
			
		||||
                (
 | 
			
		||||
                    "client",
 | 
			
		||||
                    models.ForeignKey(
 | 
			
		||||
@ -40,9 +40,9 @@ class Migration(migrations.Migration):
 | 
			
		||||
                ),
 | 
			
		||||
            ],
 | 
			
		||||
            options={
 | 
			
		||||
                "verbose_name": "Application Gateway Outlet",
 | 
			
		||||
                "verbose_name_plural": "Application Gateway Outlets",
 | 
			
		||||
                "verbose_name": "Application Gateway Provider",
 | 
			
		||||
                "verbose_name_plural": "Application Gateway Providers",
 | 
			
		||||
            },
 | 
			
		||||
            bases=("passbook_core.outlet",),
 | 
			
		||||
            bases=("passbook_core.provider",),
 | 
			
		||||
        ),
 | 
			
		||||
    ]
 | 
			
		||||
@ -0,0 +1,24 @@
 | 
			
		||||
# Generated by Django 2.2.9 on 2020-01-02 15:05
 | 
			
		||||
 | 
			
		||||
from django.db import migrations, models
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Migration(migrations.Migration):
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        ("passbook_providers_app_gw", "0003_applicationgatewayprovider"),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
        migrations.RenameField(
 | 
			
		||||
            model_name="applicationgatewayprovider",
 | 
			
		||||
            old_name="host",
 | 
			
		||||
            new_name="external_host",
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.AddField(
 | 
			
		||||
            model_name="applicationgatewayprovider",
 | 
			
		||||
            name="internal_host",
 | 
			
		||||
            field=models.TextField(default=""),
 | 
			
		||||
            preserve_default=False,
 | 
			
		||||
        ),
 | 
			
		||||
    ]
 | 
			
		||||
@ -9,12 +9,12 @@ from django.utils.translation import gettext as _
 | 
			
		||||
from oidc_provider.models import Client
 | 
			
		||||
 | 
			
		||||
from passbook import __version__
 | 
			
		||||
from passbook.core.models import Outlet
 | 
			
		||||
from passbook.core.models import Provider
 | 
			
		||||
from passbook.lib.utils.template import render_to_string
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ApplicationGatewayOutlet(Outlet):
 | 
			
		||||
    """This outlet uses oauth2_proxy with the OIDC Outlet."""
 | 
			
		||||
class ApplicationGatewayProvider(Provider):
 | 
			
		||||
    """This provider uses oauth2_proxy with the OIDC Provider."""
 | 
			
		||||
 | 
			
		||||
    name = models.TextField()
 | 
			
		||||
    internal_host = models.TextField()
 | 
			
		||||
@ -22,7 +22,7 @@ class ApplicationGatewayOutlet(Outlet):
 | 
			
		||||
 | 
			
		||||
    client = models.ForeignKey(Client, on_delete=models.CASCADE)
 | 
			
		||||
 | 
			
		||||
    form = "passbook.channels.out_app_gw.forms.ApplicationGatewayOutletForm"
 | 
			
		||||
    form = "passbook.providers.app_gw.forms.ApplicationGatewayProviderForm"
 | 
			
		||||
 | 
			
		||||
    def html_setup_urls(self, request: HttpRequest) -> Optional[str]:
 | 
			
		||||
        """return template and context modal with URLs for authorize, token, openid-config, etc"""
 | 
			
		||||
@ -32,7 +32,7 @@ class ApplicationGatewayOutlet(Outlet):
 | 
			
		||||
        )
 | 
			
		||||
        return render_to_string(
 | 
			
		||||
            "app_gw/setup_modal.html",
 | 
			
		||||
            {"outlet": self, "cookie_secret": cookie_secret, "version": __version__},
 | 
			
		||||
            {"provider": self, "cookie_secret": cookie_secret, "version": __version__},
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    def __str__(self):
 | 
			
		||||
@ -40,5 +40,5 @@ class ApplicationGatewayOutlet(Outlet):
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
 | 
			
		||||
        verbose_name = _("Application Gateway Outlet")
 | 
			
		||||
        verbose_name_plural = _("Application Gateway Outlets")
 | 
			
		||||
        verbose_name = _("Application Gateway Provider")
 | 
			
		||||
        verbose_name_plural = _("Application Gateway Providers")
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user