lib: move SAML timestring utils into lib

This commit is contained in:
Jens Langhammer 2020-07-20 11:35:16 +02:00
parent 05c3393669
commit 37b2400cdb
9 changed files with 50 additions and 58 deletions

View file

@ -0,0 +1,38 @@
"""Time utilities"""
import datetime
from django.core.exceptions import ValidationError
from django.utils.translation import gettext_lazy as _
ALLOWED_KEYS = (
"days",
"seconds",
"microseconds",
"milliseconds",
"minutes",
"hours",
"weeks",
)
def timedelta_string_validator(value: str):
"""Validator for Django that checks if value can be parsed with `timedelta_from_string`"""
try:
timedelta_from_string(value)
except ValueError as exc:
raise ValidationError(
_("%(value)s is not in the correct format of 'hours=3;minutes=1'."),
params={"value": value},
) from exc
def timedelta_from_string(expr: str) -> datetime.timedelta:
"""Convert a string with the format of 'hours=1;minute=3;seconds=5' to a
`datetime.timedelta` Object with hours = 1, minutes = 3, seconds = 5"""
kwargs = {}
for duration_pair in expr.split(";"):
key, value = duration_pair.split("=")
if key.lower() not in ALLOWED_KEYS:
continue
kwargs[key.lower()] = float(value)
return datetime.timedelta(**kwargs)

View file

@ -3,7 +3,7 @@
import django.db.models.deletion
from django.db import migrations, models
import passbook.providers.saml.utils.time
import passbook.lib.utils.time
class Migration(migrations.Migration):
@ -66,9 +66,7 @@ class Migration(migrations.Migration):
models.TextField(
default="minutes=-5",
help_text="Assertion valid not before current time + this value (Format: hours=-1;minutes=-2;seconds=-3).",
validators=[
passbook.providers.saml.utils.time.timedelta_string_validator
],
validators=[passbook.lib.utils.time.timedelta_string_validator],
),
),
(
@ -76,9 +74,7 @@ class Migration(migrations.Migration):
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.providers.saml.utils.time.timedelta_string_validator
],
validators=[passbook.lib.utils.time.timedelta_string_validator],
),
),
(
@ -86,9 +82,7 @@ class Migration(migrations.Migration):
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.providers.saml.utils.time.timedelta_string_validator
],
validators=[passbook.lib.utils.time.timedelta_string_validator],
),
),
(

View file

@ -10,7 +10,7 @@ from structlog import get_logger
from passbook.core.models import PropertyMapping, Provider
from passbook.crypto.models import CertificateKeyPair
from passbook.lib.utils.template import render_to_string
from passbook.providers.saml.utils.time import timedelta_string_validator
from passbook.lib.utils.time import timedelta_string_validator
LOGGER = get_logger()

View file

@ -9,10 +9,11 @@ from signxml import XMLSigner, XMLVerifier
from structlog import get_logger
from passbook.core.exceptions import PropertyMappingExpressionException
from passbook.lib.utils.time import timedelta_from_string
from passbook.providers.saml.models import SAMLPropertyMapping, SAMLProvider
from passbook.providers.saml.processors.request_parser import AuthNRequest
from passbook.providers.saml.utils import get_random_id
from passbook.providers.saml.utils.time import get_time_string, timedelta_from_string
from passbook.providers.saml.utils.time import get_time_string
from passbook.sources.saml.exceptions import UnsupportedNameIDFormat
from passbook.sources.saml.processors.constants import (
NS_MAP,

View file

@ -4,10 +4,7 @@ from datetime import timedelta
from django.core.exceptions import ValidationError
from django.test import TestCase
from passbook.providers.saml.utils.time import (
timedelta_from_string,
timedelta_string_validator,
)
from passbook.lib.utils.time import timedelta_from_string, timedelta_string_validator
class TestTimeUtils(TestCase):

View file

@ -2,42 +2,6 @@
import datetime
from typing import Optional
from django.core.exceptions import ValidationError
from django.utils.translation import gettext_lazy as _
ALLOWED_KEYS = (
"days",
"seconds",
"microseconds",
"milliseconds",
"minutes",
"hours",
"weeks",
)
def timedelta_string_validator(value: str):
"""Validator for Django that checks if value can be parsed with `timedelta_from_string`"""
try:
timedelta_from_string(value)
except ValueError as exc:
raise ValidationError(
_("%(value)s is not in the correct format of 'hours=3;minutes=1'."),
params={"value": value},
) from exc
def timedelta_from_string(expr: str) -> datetime.timedelta:
"""Convert a string with the format of 'hours=1;minute=3;seconds=5' to a
`datetime.timedelta` Object with hours = 1, minutes = 3, seconds = 5"""
kwargs = {}
for duration_pair in expr.split(";"):
key, value = duration_pair.split("=")
if key.lower() not in ALLOWED_KEYS:
continue
kwargs[key.lower()] = float(value)
return datetime.timedelta(**kwargs)
def get_time_string(delta: Optional[datetime.timedelta] = None) -> str:
"""Get Data formatted in SAML format"""

View file

@ -3,7 +3,7 @@
import django.db.models.deletion
from django.db import migrations, models
import passbook.providers.saml.utils.time
import passbook.lib.utils.time
class Migration(migrations.Migration):
@ -27,9 +27,7 @@ class Migration(migrations.Migration):
field=models.TextField(
default="days=1",
help_text="Time offset when temporary users should be deleted. This only applies if your IDP uses the NameID Format 'transient', and the user doesn't log out manually. (Format: hours=1;minutes=2;seconds=3).",
validators=[
passbook.providers.saml.utils.time.timedelta_string_validator
],
validators=[passbook.lib.utils.time.timedelta_string_validator],
verbose_name="Delete temporary users after",
),
),

View file

@ -8,7 +8,7 @@ from django.utils.translation import gettext_lazy as _
from passbook.core.models import Source
from passbook.core.types import UILoginButton
from passbook.crypto.models import CertificateKeyPair
from passbook.providers.saml.utils.time import timedelta_string_validator
from passbook.lib.utils.time import timedelta_string_validator
from passbook.sources.saml.processors.constants import (
SAML_NAME_ID_FORMAT_EMAIL,
SAML_NAME_ID_FORMAT_PERSISTENT,

View file

@ -3,7 +3,7 @@ from django.utils.timezone import now
from structlog import get_logger
from passbook.core.models import User
from passbook.providers.saml.utils.time import timedelta_from_string
from passbook.lib.utils.time import timedelta_from_string
from passbook.root.celery import CELERY_APP
from passbook.sources.saml.models import SAMLSource