Source code for eynnyd.response_cookie_builder

import arrow
from optional import Optional

from eynnyd.exceptions import InvalidCookieBuildException
from eynnyd.internal.utils.cookies import rfc
from eynnyd.internal.utils.cookies.response_cookie import ResponseCookie


[docs]class ResponseCookieBuilder: """ Response cookies are generally just key-value pairs but can be more complicated. Using this builder allows for simple creation of generic or complex cookies with validation. """
[docs] def __init__(self, name, value): """ Constructs an initial ResponseCookieBuilder with common defaults. :param name: a valid cookie name (via rfc spec) :param value: a valid cookie value (via rfc spec) """ self._name = name self._value = value self._expires = Optional.empty() self._max_age = Optional.empty() self._domain = Optional.empty() self._path = Optional.empty() self._secure = True self._http_only = True
[docs] def set_expires(self, expires): """ Sets the cookie to include an expiry date. :param expires: a date, parsable by python Arrow :return: This builder to allow for fluent design. """ try: encoded = arrow.get(expires) except arrow.parser.ParserError as e: raise InvalidCookieBuildException("Invalid datetime {d}, unable to parse.".format(d=expires), e) self._expires = Optional.of(encoded) return self
[docs] def set_expires_in_days(self, days_till_expiry): """ Sets the cookie to include an expiry date in days from now. :param days_till_expiry: number of days from now to the expiry time. :return: This builder to allow for fluent design. """ try: encoded = int(days_till_expiry) except ValueError as e: raise InvalidCookieBuildException("Invalid days {d}".format(d=days_till_expiry), e) self._expires = Optional.of(arrow.utcnow().shift(days=encoded)) return self
[docs] def set_max_age(self, max_age): """ Sets the max age of the cookie. :param max_age: an rfc compliant max age :return: This builder to allow for fluent design. """ if not bool(rfc.VALID_RFC_MAX_AGE.fullmatch(str(max_age))): raise InvalidCookieBuildException("Max Age {m} does not comply with RFC Cookies Specs.".format(m=max_age)) self._max_age = Optional.of(str(max_age)) return self
[docs] def set_domain(self, domain): """ Sets the limiting domain for the cookie. :param domain: an rfc compliant domain :return: This builder to allow for fluent design. """ if not bool(rfc.VALID_RFC_DOMAIN.fullmatch(domain)): raise InvalidCookieBuildException("Domain {d} does not comply with RFC Cookie Specs.".format(d=domain)) self._domain = Optional.of(domain) return self
[docs] def set_path(self, path): """ Sets the limiting path for the cookie. :param path: an rfc compliant path :return: This builder to allow for fluent design. """ if not bool(rfc.VALID_RFC_PATH.fullmatch(path)): raise InvalidCookieBuildException("Path {p} does not comply with RFC Cookie Specs.".format(p=path)) self._path = Optional.of(path) return self
[docs] def set_secure(self, secure): """ Sets whether the cookie is secure or not. :param secure: a boolean to indicate if we are setting secure or insecure :return: This builder to allow for fluent design. """ self._secure = bool(secure) return self
[docs] def set_http_only(self, http_only): """ Sets whether the cookie is http only or not. :param http_only: a boolean to indicate if we are setting http only or not :return: This builder to allow for fluent design. """ self._http_only = bool(http_only) return self
[docs] def build(self): """ Validates the name and value and builds the ResponseCookie object. :return: a valid ResponseCookie object. """ if not bool(rfc.VALID_RFC_COOKIE_NAME.fullmatch(self._name)): raise InvalidCookieBuildException("Cookie Name {n} does not comply with RFC Cookie Specs.".format(n=self._name)) if not bool(rfc.VALID_RFC_COOKIE_VALUE.fullmatch((self._value))): raise InvalidCookieBuildException( "Cookie Value {v} does not comply with RFC Cookie Specs.".format(v=self._value)) return ResponseCookie( self._name, self._value, self._expires, self._max_age, self._domain, self._path, self._secure, self._http_only)