core: add basic model against which rules can be checked
This commit is contained in:
parent
849f9c9251
commit
095a5c0268
|
@ -20,12 +20,24 @@ class User(AbstractUser):
|
|||
|
||||
@reversion.register()
|
||||
class Provider(models.Model):
|
||||
"""Application-independant Provider instance. For example SAML2 Remote, OAuth2 Application"""
|
||||
"""Application-independent Provider instance. For example SAML2 Remote, OAuth2 Application"""
|
||||
|
||||
# This class defines no field for easier inheritance
|
||||
|
||||
class RuleModel(UUIDModel, CreatedUpdatedModel):
|
||||
"""Base model which can have rules applied to it"""
|
||||
|
||||
rules = models.ManyToManyField('Rule')
|
||||
|
||||
def passes(self, user: User) -> bool:
|
||||
"""Return true if user passes, otherwise False or raise Exception"""
|
||||
for rule in self.rules:
|
||||
if not rule.passes(user):
|
||||
return False
|
||||
return True
|
||||
|
||||
@reversion.register()
|
||||
class Application(UUIDModel, CreatedUpdatedModel):
|
||||
class Application(RuleModel):
|
||||
"""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"""
|
||||
|
@ -45,7 +57,7 @@ class Application(UUIDModel, CreatedUpdatedModel):
|
|||
return self.name
|
||||
|
||||
@reversion.register()
|
||||
class Source(UUIDModel, CreatedUpdatedModel):
|
||||
class Source(RuleModel):
|
||||
"""Base Authentication source, i.e. an OAuth Provider, SAML Remote or LDAP Server"""
|
||||
|
||||
name = models.TextField()
|
||||
|
@ -82,7 +94,6 @@ class Rule(UUIDModel, CreatedUpdatedModel):
|
|||
)
|
||||
|
||||
name = models.TextField(blank=True, null=True)
|
||||
application = models.ForeignKey(Application, on_delete=models.CASCADE)
|
||||
action = models.CharField(max_length=20, choices=ACTIONS)
|
||||
negate = models.BooleanField(default=False)
|
||||
|
||||
|
@ -91,9 +102,9 @@ class Rule(UUIDModel, CreatedUpdatedModel):
|
|||
def __str__(self):
|
||||
if self.name:
|
||||
return self.name
|
||||
return "%s action %s" % (self.application, self.action)
|
||||
return "%s action %s" % (self.name, self.action)
|
||||
|
||||
def user_passes(self, user: User) -> bool:
|
||||
def passes(self, user: User) -> bool:
|
||||
"""Check if user instance passes this rule"""
|
||||
raise NotImplementedError()
|
||||
|
||||
|
@ -120,13 +131,13 @@ class FieldMatcherRule(Rule):
|
|||
value = models.TextField()
|
||||
|
||||
def __str__(self):
|
||||
description = "app %s, user.%s %s '%s'" % (self.application, self.user_field,
|
||||
self.match_action, self.value)
|
||||
description = "%s, user.%s %s '%s'" % (self.name, self.user_field,
|
||||
self.match_action, self.value)
|
||||
if self.name:
|
||||
description = "%s: %s" % (self.name, description)
|
||||
return description
|
||||
|
||||
def user_passes(self, user: User) -> bool:
|
||||
def passes(self, user: User) -> bool:
|
||||
"""Check if user instance passes this role"""
|
||||
if not hasattr(user, self.user_field):
|
||||
raise ValueError("Field does not exist")
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
django>=2.0
|
||||
django-reversion
|
||||
django-model-utils
|
||||
django-crispy-forms
|
||||
djangorestframework
|
||||
PyYAML
|
||||
raven
|
||||
djangorestframework
|
||||
markdown
|
||||
django-model-utils
|
||||
colorlog
|
|
@ -54,8 +54,10 @@ INSTALLED_APPS = [
|
|||
'django.contrib.staticfiles',
|
||||
'reversion',
|
||||
'rest_framework',
|
||||
'crispy_forms',
|
||||
'passbook.core',
|
||||
'passbook.admin',
|
||||
'passbook.audit',
|
||||
'passbook.lib',
|
||||
'passbook.ldap',
|
||||
'passbook.oauth_client',
|
||||
|
|
|
@ -53,8 +53,8 @@
|
|||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="nav navbar-nav navbar-primary">
|
||||
{# FIXME: Detect active application #}
|
||||
{% is_active_app 'passbook_admin' as is_admin %}
|
||||
<ul class="nav navbar-nav navbar-primary {% if is_admin == 'active' %}persistent-secondary{% endif %}">
|
||||
<li class="{% is_active_app 'passbook_core' %}">
|
||||
<a href="{% url 'passbook_core:overview' %}">{% trans 'Overview' %}</a>
|
||||
</li>
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
{% extends "overview/base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container">
|
||||
<div class="row row-cards-pf">
|
||||
<!-- Important: if you need to nest additional .row within a .row.row-cards-pf, do *not* use .row-cards-pf on the nested .row -->
|
||||
<div class="col-xs-12 col-sm-6 col-md-3">
|
||||
|
@ -58,4 +59,5 @@
|
|||
</div>
|
||||
</div>
|
||||
</div><!-- /row -->
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -26,7 +26,7 @@ urlpatterns = [
|
|||
for _passbook_app in get_apps():
|
||||
if hasattr(_passbook_app, 'mountpoint'):
|
||||
_path = path(_passbook_app.mountpoint, include((_passbook_app.name+'.urls',
|
||||
_passbook_app.name),
|
||||
_passbook_app.label),
|
||||
namespace=_passbook_app.label))
|
||||
urlpatterns.append(_path)
|
||||
LOGGER.debug("Loaded %s's URLs", _passbook_app.name)
|
||||
|
|
|
@ -11,5 +11,5 @@ class OverviewView(LoginRequiredMixin, TemplateView):
|
|||
template_name = 'overview/index.html'
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
kwargs['applications'] = self.request.user.applications.objects.all()
|
||||
kwargs['applications'] = self.request.user.applications.all()
|
||||
return super().get_context_data(**kwargs)
|
||||
|
|
Reference in New Issue