コード例 #1
0
def lninvoice_paid_handler(sender, instance, **kwargs):
    print("received...!")
    print(f"received Sender: {sender}")
    print(f"received Instance: {instance}")

    shop_item_content_type = instance.po.item_details.first().content_type
    shop_item_id = instance.po.item_details.first().object_id

    if shop_item_content_type == ContentType.objects.get_for_model(TorBridge):
        shop_item = TorBridge.objects.get(id=shop_item_id)
    elif shop_item_content_type == ContentType.objects.get_for_model(RSshTunnel):
        shop_item = RSshTunnel.objects.get(id=shop_item_id)
    else:
        raise NotImplementedError

    if shop_item.status == Bridge.INITIAL:
        print(f"set to PENDING")
        shop_item.status = Bridge.NEEDS_ACTIVATE

    elif shop_item.status == Bridge.ACTIVE:
        print(f"is already ACTIVE - assume extend")
        # ToDo(frennkie): check/set suspend after time
        shop_item.suspend_after = shop_item.suspend_after + timedelta(seconds=shop_item.host.tor_bridge_duration)

    elif shop_item.status == Bridge.SUSPENDED or shop_item.status == Bridge.NEEDS_SUSPEND:
        print(f"is reactivate")
        shop_item.status = Bridge.NEEDS_ACTIVATE

        # ToDo(frennkie): check/set suspend after time
        if shop_item.suspend_after <= timezone.now():
            shop_item.suspend_after = timezone.now() + timedelta(seconds=shop_item.host.tor_bridge_duration)

    shop_item.save()
    add_change_log_entry(shop_item, "ran lninvoice_paid_handler")
コード例 #2
0
def set_needs_delete_on_initial_tor_bridges(days=3):
    counter = 0
    initials = TorBridge.objects.filter(status=TorBridge.INITIAL)
    if initials:
        for item in initials:
            logger.debug('Running on: %s' % item)
            if timezone.now() > item.modified_at + timedelta(days=days):
                logger.debug('Needs to be set to deleted.')
                item.status = TorBridge.NEEDS_DELETE
                item.save()
                add_change_log_entry(item, "set to NEEDS_DELETE")
                counter += 1

    return f'Set NEEDS_DELETE on {counter}/{len(initials)} Tor Bridge(s) (previous state: INITIAL).'
コード例 #3
0
def set_needs_delete_on_suspended_tor_bridges(days=45):
    counter = 0
    suspended = TorBridge.objects.filter(status=TorBridge.SUSPENDED)
    if suspended:
        for item in suspended:
            logger.debug('Running on: %s' % item)
            if timezone.now() > item.modified_at + timedelta(days=days):
                logger.debug('Needs to be set to deleted.')
                item.status = TorBridge.NEEDS_DELETE
                item.save()
                add_change_log_entry(item, "set to NEEDS_DELETE")
                counter += 1

    return f'Set NEEDS_DELETE on {counter}/{len(suspended)} Tor Bridge(s) (previous state: SUSPENDED).'
コード例 #4
0
def set_needs_suspend_on_expired_tor_bridges():
    counter = 0
    actives = TorBridge.objects.filter(status=TorBridge.ACTIVE)
    if actives:
        for item in actives:
            logger.info('Running on: %s' % item)

            if timezone.now() > item.suspend_after:
                logger.info('Needs to be suspended.')
                item.status = TorBridge.NEEDS_SUSPEND
                item.save()
                add_change_log_entry(item, "set to NEEDS_SUSPEND")
                counter += 1

    return f'Set NEEDS_SUSPEND on {counter}/{len(actives)} Tor Bridge(s) (previous state: ACTIVE).'
コード例 #5
0
    def create(self, host, target, comment=None):
        tor_bridge = TorBridge.objects.create(comment=comment,
                                              host=host,
                                              target=target)

        po = PurchaseOrder.objects.create()
        po_item = PurchaseOrderItemDetail(price=host.tor_bridge_price_initial,
                                          product=tor_bridge,
                                          quantity=1)
        po.item_details.add(po_item, bulk=False)
        po_item.save()
        add_change_log_entry(po_item, "added item_details")
        po.save()
        add_change_log_entry(po, "new po created")

        return po
コード例 #6
0
    def lnnode_sync_invoice(self):
        previous_status = self.status
        super().lnnode_sync_invoice()

        if previous_status == self.status:
            return

        if self.po.status == PurchaseOrder.PAID:
            return

        if self.status == self.PAID:
            self.po.status = PurchaseOrder.PAID
            self.po.save()
            add_change_log_entry(self.po, "set to PAID")

        elif self.status != self.PAID:
            self.po.status = PurchaseOrder.NEEDS_TO_BE_PAID
            self.po.save()
            add_change_log_entry(self.po, "set to NEEDS_TO_BE_PAID")
コード例 #7
0
    def lnnode_create_invoice(self):

        add_change_log_entry(self, "create_invoice on node started")

        create_result = self.lnnode.create_invoice(
            memo=f'{self.label}',
            value=int(self.amount_full_satoshi),
            expiry=self.expiry)

        add_change_log_entry(self, "create_invoice on node finished")

        self.refresh_from_db()

        # ToDo(frennkie) error handling?
        _r_hash = create_result.get('r_hash')
        if _r_hash:
            self.payment_hash = base64.b64decode(_r_hash)

        self.status = self.UNPAID
        self.save()
        add_change_log_entry(self, "set to UNPAID")

        self.refresh_from_db()

        self.lnnode_sync_invoice()

        lninvoice_invoice_created_on_node.send(sender=self.__class__,
                                               instance=self)

        return True
コード例 #8
0
def post_save_tor_bridge(sender, instance: TorBridge, **kwargs):
    created = kwargs.get('created')

    if instance.previous_status != instance.status or created:
        if instance.status == sender.ACTIVE:
            instance.process_activation()
        elif instance.status == sender.NEEDS_SUSPEND:
            instance.process_suspension()

    if created:
        print("Tor Bridge created - setting random port...")
        instance.port = instance.host.get_random_port()

        if instance.host.tor_bridge_duration == 0:
            instance.suspend_after = timezone.make_aware(timezone.datetime.max,
                                                         timezone.get_default_timezone())
        else:
            instance.suspend_after = timezone.now() \
                                     + timedelta(seconds=instance.host.tor_bridge_duration) \
                                     + timedelta(seconds=getattr(settings, 'SHOP_BRIDGE_DURATION_GRACE_TIME', 600))

        instance.save()
        add_change_log_entry(instance, "created")
コード例 #9
0
    def extend(self, request, pk=None):
        tor_bridge = self.get_object()

        # create a new PO
        po = PurchaseOrder.objects.create()
        po_item = PurchaseOrderItemDetail(
            price=tor_bridge.host.tor_bridge_price_extension,
            product=tor_bridge,
            quantity=1)
        po.item_details.add(po_item, bulk=False)
        po_item.save()
        add_change_log_entry(po_item, "set created")
        po.save()
        add_change_log_entry(po, "added item_details")

        return Response({
            'status':
            'ok',
            'po_id':
            po.id,
            'po':
            reverse('v1:purchaseorder-detail', args=(po.id, ), request=request)
        })
コード例 #10
0
    def lnnode_sync_invoice(self):
        payment_detected = False
        # ToDo(frennkie) error handling?
        lookup_result = self.lnnode.get_invoice(r_hash=self.payment_hash)

        # ToDo(frennkie) sync *complete* data here..
        if not self.preimage:
            _r_preimage = lookup_result.get('r_preimage')
            if _r_preimage:
                self.preimage = base64.b64decode(_r_preimage)

        if not self.payment_request:
            _payment_request = lookup_result.get('payment_request')
            if _payment_request:
                self.payment_request = _payment_request

        _expiry = lookup_result.get('expiry')
        if self.expiry:
            if _expiry:
                if self.expiry != int(_expiry):
                    self.expiry = int(_expiry)
        else:
            if _expiry:
                self.expiry = int(_expiry)

        if not self.creation_at:
            try:
                _creation_date = lookup_result.get('creation_date')
                if _creation_date:
                    self.creation_at = make_aware(
                        timezone.datetime.utcfromtimestamp(
                            int(_creation_date)))
            except TypeError:
                return

        if not self.expires_at:
            if self.creation_at:
                expire_date = self.creation_at + timezone.timedelta(
                    seconds=self.expiry)
                self.expires_at = expire_date

        if not self.qr_image:
            temp_name, file_obj_qr_image = self.make_qr_image()
            self.qr_image.save(temp_name, file_obj_qr_image, True)

        if self.status == self.INITIAL:
            self.status = self.UNPAID

        if self.status == self.UNPAID:
            if lookup_result.get('settled'):
                payment_detected = True

                self.status = self.PAID
                self.paid_at = make_aware(
                    timezone.datetime.utcfromtimestamp(
                        int(lookup_result.get('settle_date'))))

        if self.has_expired and self.status != self.PAID:
            self.status = self.EXPIRED

        self.save()
        add_change_log_entry(self, f"synced (current status: {self.status})")

        if payment_detected:
            print('Has been PAID!')  # ToDo(frennkie) remove this
            add_change_log_entry(self, "payment detected")

            key = f'ip2tor.metrics.payments.sats'
            con = get_redis_connection("default")
            con.rpush(key, self.amount_full_satoshi)

            lninvoice_paid.send(sender=self.__class__, instance=self)

        return True
コード例 #11
0
def process_initial_purchase_order(obj_id):
    logger.info('Running on ID: %s' % obj_id)

    # checks
    obj: PurchaseOrder = PurchaseOrder.objects \
        .filter(id=obj_id) \
        .filter(status=PurchaseOrder.INITIAL) \
        .first()

    if not obj:
        logger.info('Not found')
        return None

    if not obj.total_price_msat:
        logger.info('No total price - skipping: %s' % obj)
        return None

    logger.debug('set to: NEEDS_LOCAL_CHECKS')
    obj.status = PurchaseOrder.NEEDS_LOCAL_CHECKS
    obj.save()
    add_change_log_entry(obj, 'set to: NEEDS_LOCAL_CHECKS')

    # ToDo(frennkie) this should not live in Django Charged
    target_with_port = obj.item_details.first().product.target
    try:
        target = target_with_port.split(':')[0]
    except IndexError:
        target = target_with_port

    try:
        target_port = target_with_port.split(':')[1]
    except IndexError:
        target_port = 80

    if TorDenyList.objects.filter(is_denied=True).filter(target=target):
        logger.info('Target is on Deny List: %s' % target)
        obj.status = PurchaseOrder.REJECTED
        obj.message = "Target is on Deny List"
        obj.save()
        add_change_log_entry(obj, 'set to: REJECTED')
        return None

    logger.debug('set to: NEEDS_REMOTE_CHECKS')
    obj.status = PurchaseOrder.NEEDS_REMOTE_CHECKS
    obj.save()
    add_change_log_entry(obj, 'set to: NEEDS_REMOTE_CHECKS')

    # ToDo(frennkie) move to settings (env)
    whitelisted_service_ports = ['8333', '9735']
    if target_port in whitelisted_service_ports:
        logger.info('REMOTE CHECKS: target port is whitelisted: %s' %
                    target_port)

    else:
        url = f'https://{target}:{target_port}/'
        result = ensure_https(url)
        if not result:
            logger.info('REMOTE CHECKS: Target is not HTTPS')
            obj.status = PurchaseOrder.REJECTED
            obj.message = "Target is not HTTPS"
            obj.save()
            add_change_log_entry(obj, 'set to: REJECTED')
            return None

    logger.debug('set to: NEEDS_INVOICE')
    obj.status = PurchaseOrder.NEEDS_INVOICE
    obj.save()
    add_change_log_entry(obj, 'set to: NEEDS_INVOICE')

    tax_ex_rate_obj = FiatRate.objects \
        .filter(is_aggregate=False) \
        .filter(fiat_symbol=FiatRate.EUR) \
        .first()

    if tax_ex_rate_obj:
        tax_ex_rate = tax_ex_rate_obj.rate
    else:
        tax_ex_rate = Money(0.00, getattr(settings,
                                          'CHARGED_TAX_CURRENCY_FIAT'))

    info_ex_rate_obj = FiatRate.objects \
        .filter(is_aggregate=False) \
        .filter(fiat_symbol=FiatRate.USD) \
        .first()

    if info_ex_rate_obj:
        info_ex_rate = info_ex_rate_obj.rate
    else:
        info_ex_rate = Money(0.00,
                             getattr(settings, 'CHARGED_TAX_CURRENCY_FIAT'))

    # ToDo(frennkie) check this!
    owned_nodes = get_all_nodes(obj.owner.id)
    for node_tuple in owned_nodes:
        node = node_tuple[1]

        if not node.is_enabled:
            continue  # skip disabled nodes
        if not node.is_alive:
            continue  # skip dead nodes

        invoice = PurchaseOrderInvoice(label="PO: {}".format(obj.id),
                                       msatoshi=obj.total_price_msat,
                                       tax_rate=Decimal.from_float(
                                           getattr(settings,
                                                   'CHARGED_TAX_RATE')),
                                       tax_currency_ex_rate=tax_ex_rate,
                                       info_currency_ex_rate=info_ex_rate,
                                       lnnode=node)

        invoice.save()
        add_change_log_entry(invoice, f'created poi for po: {obj.id}')

        obj.ln_invoices.add(invoice)
        add_change_log_entry(obj, f'added new poi: {invoice.id}')

        obj.status = PurchaseOrder.NEEDS_TO_BE_PAID
        obj.save()
        add_change_log_entry(obj, 'set to: NEEDS_TO_BE_PAID')

        logger.info('Created LnInvoice: %s (%s)' % (invoice.id, invoice))

        break

    else:
        raise RuntimeError("no owned nodes found")

    if invoice:
        return invoice.id
    else:
        raise NoInvoiceCreatedError