Esempio n. 1
0
    def from_data(data):
        """Return a DebitNote that has been extracted from the passed
           json-decoded dictionary

           Args:
                data (dict): Dictionary from which to create object
           Returns:
                DebitNote: Created from dictionary
        """
        d = DebitNote()

        if (data and len(data) > 0):
            from Acquire.Accounting import Transaction as _Transaction
            from Acquire.Identity import Authorisation as _Authorisation
            from Acquire.ObjectStore import string_to_datetime \
                as _string_to_datetime

            d._transaction = _Transaction.from_data(data["transaction"])
            d._account_uid = data["account_uid"]
            d._authorisation = _Authorisation.from_data(data["authorisation"])
            d._is_provisional = data["is_provisional"]
            d._datetime = _string_to_datetime(data["datetime"])
            d._uid = data["uid"]

            if d._is_provisional:
                d._receipt_by = _string_to_datetime(data["receipt_by"])

        return d
Esempio n. 2
0
    def from_data(data):
        """Construct and return a new CreditNote from the passed json-decoded
            dictionary

            Args:
                data (dict): JSON serialised dictionary of object
            Returns:
                CreditNote: CreditNote created from JSON data
        """
        note = CreditNote()

        if (data and len(data) > 0):
            from Acquire.ObjectStore import string_to_datetime \
                as _string_to_datetime
            from Acquire.Accounting import create_decimal as _create_decimal

            note._account_uid = data["account_uid"]
            note._debit_account_uid = data["debit_account_uid"]
            note._uid = data["uid"]
            note._debit_note_uid = data["debit_note_uid"]
            note._datetime = _string_to_datetime(data["datetime"])
            note._value = _create_decimal(data["value"])
            note._is_provisional = data["is_provisional"]

            if note._is_provisional:
                note._receipt_by = _string_to_datetime(data["receipt_by"])

        return note
Esempio n. 3
0
def validate_is_uid(uid):
    """Validate that the passed 'uid' is actually a UID. This checks
       that the string is not something weird that is trying to
       break the system
    """
    if uid is None:
        raise TypeError("'None' is not a valid UID!")

    uid = str(uid)

    len_uid = len(uid)

    import re as _re
    from Acquire.ObjectStore import string_to_datetime \
        as _string_to_datetime

    if len_uid == 8:
        # this is a short UID
        if _re.match(r'[a-f0-9]{8}', uid):
            return
    elif len_uid == 35:
        # this is a short UID with a datetime
        parts = uid.split("/")
        try:
            dt = _string_to_datetime(parts[0])
            if _re.match(r'[a-f0-9]{8}', parts[1]):
                return
        except Exception as e:
            print(e)
            pass
    elif len_uid == 36:
        # this is a long UID
        if _re.match(
                r'[a-f0-9]{8}\-[a-f0-9]{4}\-[a-f0-9]{4}\-[a-f0-9]{4}\-[a-f0-9]{12}',
                uid):
            return
    elif len_uid == 63:
        # this is a long UID with a datetime
        parts = uid.split("/")
        try:
            dt = _string_to_datetime(parts[0])
            if _re.match(
                    r'[a-f0-9]{8}\-[a-f0-9]{4}\-[a-f0-9]{4}\-[a-f0-9]{4}\-[a-f0-9]{12}',
                    parts[1]):
                return
        except:
            pass

    raise TypeError("'%s' is not a valid UID!" % uid)
Esempio n. 4
0
    def from_data(data):
        """Return an authorisation created from the json-decoded dictionary"""
        auth = Authorisation()

        if (data and len(data) > 0):
            from Acquire.ObjectStore import string_to_datetime \
                as _string_to_datetime
            from Acquire.ObjectStore import string_to_bytes \
                as _string_to_bytes

            auth._user_uid = data["user_uid"]
            auth._session_uid = data["session_uid"]
            auth._identity_url = data["identity_url"]
            auth._identity_uid = data["identity_uid"]
            auth._uid = data["uid"]
            parts = auth._uid.split("/")
            auth._auth_datetime = _string_to_datetime(parts[0])
            auth._signature = _string_to_bytes(data["signature"])
            auth._siguid = _string_to_bytes(data["siguid"])
            auth._last_validated_datetime = None

            if "is_testing" in data:
                auth._is_testing = data["is_testing"]

        return auth
def _get_driver_details_from_data(data):
    from Acquire.ObjectStore import string_to_datetime \
        as _string_to_datetime

    import copy as _copy
    details = _copy.copy(data)

    if "created_datetime" in details:
        details["created_datetime"] = _string_to_datetime(
            details["created_datetime"])

    return details
Esempio n. 6
0
    def from_data(data, passphrase=None):
        """Return a OSPar constructed from the passed json-deserliased
           dictionary

           Args:
                data (dict): JSON-deserialised dictionary from which to
                create OSPar
            Returns:
                OSPar: OSPar object created from dict
        """
        if data is None or len(data) == 0:
            return OSPar()

        from Acquire.ObjectStore import string_to_datetime \
            as _string_to_datetime
        from Acquire.ObjectStore import string_to_bytes \
            as _string_to_bytes

        par = OSPar()

        par._url = _string_to_bytes(data["url"])
        par._key = data["key"]
        par._uid = data["uid"]

        if par._key is not None:
            par._key = str(par._key)

        par._expires_datetime = _string_to_datetime(data["expires_datetime"])
        par._is_readable = data["is_readable"]
        par._is_writeable = data["is_writeable"]

        if "service_url" in data:
            par._service_url = data["service_url"]

        if "privkey" in data:
            if passphrase is not None:
                from Acquire.Crypto import PrivateKey as _PrivateKey
                par._privkey = _PrivateKey.from_data(data["privkey"],
                                                     passphrase)

        # note that we don't load the driver details as this
        # is stored and loaded separately on the service

        return par
Esempio n. 7
0
def _get_driver_details_from_data(data):
    """Internal function used to get the OCI driver details from the
       passed data

       Args:
            data (dict): Dict holding OCI driver details
       Returns:
            dict: Dict holding OCI driver details
    """
    from Acquire.ObjectStore import string_to_datetime \
        as _string_to_datetime

    import copy as _copy
    details = _copy.copy(data)

    if "created_datetime" in details:
        details["created_datetime"] = _string_to_datetime(
                                            details["created_datetime"])

    return details
Esempio n. 8
0
    def from_data(data):
        """Return a PAR constructed from the json-deserialised passed
           dictionary
        """
        if data is None or len(data) == 0:
            return PAR()

        f = PAR()

        from Acquire.Client import Location as _Location
        from Acquire.Client import ACLRule as _ACLRule
        from Acquire.ObjectStore import string_to_datetime \
            as _string_to_datetime

        f._location = _Location.from_data(data["location"])
        f._aclrule = _ACLRule.from_data(data["aclrule"])
        f._expires_datetime = _string_to_datetime(data["expires_datetime"])
        f._uid = data["uid"]

        return f
Esempio n. 9
0
    def from_data(data):
        """Return a new FileMeta constructed from the passed json-deserialised
           dictionary
        """
        f = FileMeta()

        if data is not None and len(data) > 0:
            f._filename = data["filename"]

            if "uid" in data:
                f._uid = data["uid"]

            if "filesize" in data:
                f._filesize = data["filesize"]

            if "checksum" in data:
                f._checksum = data["checksum"]

            if "user_guid" in data:
                f._user_guid = data["user_guid"]

            if "datetime" in data:
                from Acquire.ObjectStore import string_to_datetime \
                    as _string_to_datetime
                f._datetime = _string_to_datetime(data["datetime"])

            if "compression" in data:
                f._compression = data["compression"]

            if "acl" in data:
                from Acquire.Client import ACLRule as _ACLRule
                f._acl = _ACLRule.from_data(data["acl"])

            if "aclrules" in data:
                from Acquire.Storage import ACLRules as _ACLRules
                f._aclrules = _ACLRules.from_data(data["aclrules"])

        return f
Esempio n. 10
0
    def read(self, spend, resource, receipt_by):
        """Read the cheque - this will read the cheque to return the
           decrypted contents. This will only work if this function
           is called on the accounting service that will cash the
           cheque, if the signature on the cheque matches the
           service that is authorised to cash the cheque, and
           if the passed resource matches the resource
           encoded in the cheque. If this is all correct, then the
           returned dictionary will contain;

           {"recipient_url": The URL of the service which was sent the cheque,
            "recipient_key_fingerprint": Verified fingerprint of the service
                                         key that signed this cheque
            "spend": The amount authorised by this cheque,
            "uid": The unique ID for this cheque,
            "resource": String that identifies the resource this cheque will
                        be used to pay for,
            "account_uid": UID of the account from which funds will be drawn
            "authorisation" : Verified authorisation from the user who
                              says they own the account for the spend
            "receipt_by" : Time when we must receipt the cheque, or
                           we will lose the money
           }

           You must pass in the spend you want to draw from the cheque,
           a string representing the resource this cheque will
           be used to pay for, and the time by which you promise to receipt
           the cheque after cashing

           Args:
                spend (Decimal): Amount authorised by cheque
                resource (str): Resource to pay for
                receipt_by (datetime): Time cheque must be receipted
                by
           Returns:
                dict: Dictionary described above

        """

        if self._cheque is None:
            raise PaymentError("You cannot read a null cheque")

        from Acquire.ObjectStore import string_to_decimal \
            as _string_to_decimal
        from Acquire.ObjectStore import string_to_datetime \
            as _string_to_datetime
        from Acquire.ObjectStore import datetime_to_string \
            as _datetime_to_string
        from Acquire.Service import get_this_service as _get_this_service

        spend = _string_to_decimal(spend)
        resource = str(resource)
        receipt_by = _string_to_datetime(receipt_by)

        service = _get_this_service(need_private_access=True)

        # get the cheque data - this may have been signed
        try:
            cheque_data = _json.loads(self._cheque["signed_data"])
        except:
            cheque_data = self._cheque

        # decrypt the cheque's data - only possible on the accounting service
        cheque_data = service.decrypt_data(cheque_data)

        # the date comprises the user-authorisation that acts as a
        # signature that the user wrote this cheque, and the info
        # for the cheque to say how it is valid
        from Acquire.Identity import Authorisation as _Authorisation
        auth = _Authorisation.from_data(cheque_data["authorisation"])
        info = cheque_data["info"]

        # the json.dumps version is the resource used to verify
        # the above authorisation
        auth_resource = info

        # validate that the user authorised this cheque
        try:
            auth.verify(resource=info)
        except Exception as e:
            raise PaymentError(
                "The user's signature/authorisation for this cheque "
                "is not valid! ERROR: %s" % str(e))

        info = _json.loads(info)

        # the user signed this cheque :-)
        info["authorisation"] = auth

        # check the signature if one was needed
        try:
            recipient_url = info["recipient_url"]
        except:
            recipient_url = None

        if recipient_url:
            # the recipient was specified - verify that we trust
            # the recipient, and that they have signed the cheque
            recipient_service = service.get_trusted_service(
                                            service_url=recipient_url)
            recipient_service.verify_data(self._cheque)
            info["recipient_key_fingerprint"] = self._cheque["fingerprint"]

        # validate that the item signature is correct
        try:
            cheque_resource = info["resource"]
        except:
            cheque_resource = None

        if cheque_resource is not None:
            if resource != resource:
                raise PaymentError(
                    "Disagreement over the resource for which "
                    "this cheque has been signed")

        info["resource"] = resource
        info["auth_resource"] = auth_resource

        try:
            max_spend = info["max_spend"]
            del info["max_spend"]
        except:
            max_spend = None

        if max_spend is not None:
            max_spend = _string_to_decimal(max_spend)

            if max_spend < spend:
                raise PaymentError(
                    "The requested spend (%s) exceeds the authorised "
                    "maximum value of the cheque" % (spend))

        info["spend"] = spend

        try:
            expiry_date = info["expiry_date"]
            del expiry_date["expiry_date"]
        except:
            expiry_date = None

        if expiry_date is not None:
            expiry_date = _string_to_datetime(expiry_date)

            # validate that the cheque will not have expired
            # when we receipt it
            from Acquire.ObjectStore import get_datetime_now \
                as _get_datetime_now
            now = _get_datetime_now()

            if now > receipt_by:
                raise PaymentError(
                    "The time when you promised to receipt the cheque "
                    "has already passed!")

            if receipt_by > expiry_date:
                raise PaymentError(
                    "The cheque will have expired after you plan to "
                    "receipt it!: %s versus %s" %
                    (_datetime_to_string(receipt_by),
                     _datetime_to_string(expiry_date)))

        info["receipt_by"] = receipt_by

        return info
Esempio n. 11
0
    def _get_user_public_cert(self, scope=None, permissions=None):
        """Internal function that returns the public certificate
           of the user who signed this authorisation. This will
           check that the authorisation was not signed after the
           user logged out, as well as validating the services
           that provide the user session keys etc.
        """
        must_fetch = False

        try:
            if scope != self._scope or permissions != self._permissions:
                must_fetch = True
        except:
            must_fetch = True

        if self._pubcert is not None:
            if not must_fetch:
                try:
                    return self._pubcert
                except:
                    pass

        try:
            testing_key = self._testing_key
        except:
            testing_key = None

        if testing_key is not None:
            if not self._is_testing:
                raise PermissionError(
                    "You cannot pass a test key to a non-testing "
                    "Authorisation")

            return testing_key

        # we need to get the public signing key for this session
        from Acquire.Service import get_trusted_service \
            as _get_trusted_service
        from Acquire.ObjectStore import get_datetime_now \
            as _get_datetime_now

        try:
            identity_service = _get_trusted_service(self._identity_url)
        except:
            raise PermissionError(
                "Unable to verify the authorisation as we do not trust "
                "the identity service at %s" % self._identity_url)

        if not identity_service.can_identify_users():
            raise PermissionError(
                "Cannot verify an Authorisation that does not use a "
                "valid identity service")

        if identity_service.uid() != self._identity_uid:
            raise PermissionError(
                "Cannot auth_once this Authorisation as the actual UID of "
                "the identity service at '%s' (%s) does not match "
                "the UID of the service that signed this authorisation "
                "(%s)" % (self._identity_url, identity_service.uid(),
                          self._identity_uid))

        response = identity_service.get_session_info(
            session_uid=self._session_uid,
            scope=scope,
            permissions=permissions)

        try:
            user_uid = response["user_uid"]
        except:
            pass

        if self._user_uid != user_uid:
            raise PermissionError(
                "Cannot verify the authorisation as there is "
                "disagreement over the UID of the user who signed "
                "the authorisation. %s versus %s" % (self._user_uid, user_uid))

        try:
            logout_datetime = _string_to_datetime(response["logout_datetime"])
        except:
            logout_datetime = None

        if logout_datetime:
            # the user has logged out from this session - ensure that
            # the authorisation was created before the user logged out
            if logout_datetime < self.signature_time():
                raise PermissionError(
                    "This authorisation was signed after the user logged "
                    "out. This means that the authorisation is not valid. "
                    "Please log in again and create a new authorisation.")

        from Acquire.Crypto import PublicKey as _PublicKey
        pubcert = _PublicKey.from_data(response["public_cert"])

        self._pubcert = pubcert
        self._scope = scope
        self._permissions = permissions
        return pubcert
Esempio n. 12
0
    def from_key(key):
        """Extract information from the passed object store key.

           This looks for a string that is;

           isoformat_datetime/UID/transactioncode

           where transactioncode is a string that matches
           '2 letters followed by a number'

           CL000100.005000
           DR000004.234100

           etc.

           For sent and received receipts there are two values;
           the receipted value and the original estimate. These
           have the standard format if the values are the same, e.g.

           RR000100.005000

           however, they have original value T receipted value if they are
           different, e.g.

           RR000100.005000T000090.000000

           Args:
                key: Object store key

        """
        from Acquire.ObjectStore import string_to_datetime \
            as _string_to_datetime
        from Acquire.Accounting import create_decimal as _create_decimal

        parts = key.split("/")

        # start at the end...
        nparts = len(parts)
        for i in range(0, nparts):
            j = nparts - i - 1
            t = TransactionInfo()

            try:
                t._datetime = _string_to_datetime(parts[j - 2])
            except:
                continue

            t._uid = parts[j - 1]

            part = parts[j]
            try:
                code = TransactionInfo._get_code(part[0:2])

                if code == TransactionCode.SENT_RECEIPT or \
                   code == TransactionCode.RECEIVED_RECEIPT:
                    values = part[2:].split("T")
                    try:
                        value = _create_decimal(values[0])
                        receipted_value = _create_decimal(values[1])
                        t._code = code
                        t._value = value
                        t._receipted_value = receipted_value
                        return t
                    except:
                        pass

                value = _create_decimal(part[2:])

                t._code = code
                t._value = value
                t._receipted_value = None

                return t
            except:
                pass

        raise ValueError("Cannot extract transaction info from '%s'" % (key))
Esempio n. 13
0
    def from_data(data):
        """Return a LoginSession constructed from the passed data
           (dictionary)
        """
        l = LoginSession()

        if data is not None and len(data) > 0:
            from Acquire.ObjectStore import string_to_datetime \
                as _string_to_datetime
            from Acquire.Crypto import PublicKey as _PublicKey

            l._uid = data["uid"]
            l._username = data["username"]
            l._request_datetime = _string_to_datetime(data["request_datetime"])
            l._pubcert = _PublicKey.from_data(data["public_certificate"])
            l._status = data["status"]

            try:
                l._pubkey = _PublicKey.from_data(data["public_key"])
            except:
                l._pubkey = None

            try:
                l._login_datatime = _string_to_datetime(data["login_datetime"])
            except:
                pass

            try:
                l._logout_datetime = _string_to_datetime(
                    data["logout_datetime"])
            except:
                pass

            try:
                l._ipaddr = data["ipaddr"]
            except:
                pass

            try:
                l._hostname = data["hostname"]
            except:
                pass

            try:
                l._login_message = data["login_message"]
            except:
                pass

            try:
                l._scope = data["scope"]
            except:
                pass

            try:
                l._permissions = data["permissions"]
            except:
                pass

            try:
                l._user_uid = data["user_uid"]
            except:
                pass

            try:
                l._device_uid = data["device_uid"]
            except:
                pass

        return l
Esempio n. 14
0
    def lock(self, timeout=None, lease_time=None):
        """Lock the mutex, blocking until the mutex is held, or until
           'timeout' seconds have passed. If we time out, then an exception is
           raised. The lock is held for a maximum of 'lease_time' seconds.

           Args:
                timeout (int): Number of seconds to block
                lease_time (int): Number of seconds to hold the lock
           Returns:
                None
        """
        # if the user does not provide a timeout, then we will set a timeout
        # to 10 seconds
        if timeout is None:
            timeout = 10.0
        else:
            timeout = float(timeout)

        # if the user does not provide a lease_time, then we will set a
        # default of only 10 seconds
        if lease_time is None:
            lease_time = 10.0
        else:
            lease_time = float(lease_time)

        from Acquire.ObjectStore import get_datetime_now as _get_datetime_now
        from Acquire.ObjectStore import datetime_to_string \
            as _datetime_to_string
        from Acquire.ObjectStore import string_to_datetime \
            as _string_to_datetime
        from Acquire.ObjectStore import ObjectStore as _ObjectStore

        if self.is_locked():
            # renew the lease - if there is less than a second remaining
            # on the lease then unlock and then lock again from scratch
            now = _get_datetime_now()

            if (now > self._end_lease) or (now - self._end_lease).seconds < 1:
                self.fully_unlock()
                self.lock(timeout, lease_time)
            else:
                self._end_lease = now + _datetime.timedelta(seconds=lease_time)

                self._lockstring = "%s{}%s" % (
                    self._secret, _datetime_to_string(self._end_lease))

                _ObjectStore.set_string_object(self._bucket, self._key,
                                               self._lockstring)

                self._is_locked += 1

            return

        now = _get_datetime_now()
        endtime = now + _datetime.timedelta(seconds=timeout)

        # This is the first time we are trying to get a lock
        while now < endtime:
            # does anyone else hold the lock?
            try:
                holder = _ObjectStore.get_string_object(
                    self._bucket, self._key)
            except:
                holder = None

            is_held = True

            if holder is None:
                is_held = False
            else:
                end_lease = _string_to_datetime(holder.split("{}")[-1])
                if now > end_lease:
                    # the lease from the other holder has expired :-)
                    is_held = False

            if not is_held:
                # no-one holds this mutex - try to hold it now
                self._end_lease = now + _datetime.timedelta(seconds=lease_time)

                self._lockstring = "%s{}%s" % (
                    self._secret, _datetime_to_string(self._end_lease))

                _ObjectStore.set_string_object(self._bucket, self._key,
                                               self._lockstring)

                holder = _ObjectStore.get_string_object(
                    self._bucket, self._key)
            else:
                self._lockstring = None

            if holder == self._lockstring:
                # it looks like we are the holder - read and write again
                # just to make sure
                holder = _ObjectStore.get_string_object(
                    self._bucket, self._key)

                if holder == self._lockstring:
                    # write again just to make sure
                    _ObjectStore.set_string_object(self._bucket, self._key,
                                                   self._lockstring)

                    holder = _ObjectStore.get_string_object(
                        self._bucket, self._key)

            if holder == self._lockstring:
                # we have read and written our secret to the object store
                # three times. While a race condition is still possible,
                # I'd hope it is now highly unlikely - we now hold the mutex
                self._is_locked = 1
                return

            # only try the lock 4 times a second
            _time.sleep(0.25)

            now = _get_datetime_now()

        from Acquire.ObjectStore import MutexTimeoutError
        raise MutexTimeoutError("Cannot acquire a mutex lock on the "
                                "key '%s'" % self._key)