push-things/django-th

View on GitHub
django_th/models/__init__.py

Summary

Maintainability
A
25 mins
Test Coverage
# coding: utf-8
import arrow

from django.conf import settings
from django.contrib.auth.models import User
from django.core.exceptions import ObjectDoesNotExist
from django.db import models
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.utils.timezone import now
from django.utils.translation import ugettext_lazy as _

from django_th.signals import digest_event
from django_th.tools import warn_user_and_admin

from logging import getLogger

logger = getLogger('django_th.trigger_happy')


class ServicesActivated(models.Model):

    """
        Services Activated from the admin
    """
    name = models.CharField(max_length=200, unique=True)
    status = models.BooleanField(default=False)
    auth_required = models.BooleanField(default=True)
    self_hosted = models.BooleanField(default=False)
    description = models.CharField(max_length=200)

    class Meta:
        verbose_name = 'Services'
        verbose_name_plural = 'Services'

    def show(self):
        """

        :return: string representing object
        """
        return "Service Activated %s %s %s %s" % (self.name, self.status,
                                                  self.auth_required,
                                                  self.description)

    def __str__(self):
        return self.name


class UserService(models.Model):

    """
        UserService a model to link service and user
    """
    DAY = 'd'
    WEEK = 'w'
    MONTH = 'm'
    NONE = 'n'
    DURATION = (
        (DAY, _('Day')),
        (WEEK, _('Week')),
        (MONTH, _('Month')),
        (NONE, _('None'))
    )

    user = models.ForeignKey(User, on_delete=models.CASCADE)
    token = models.CharField(max_length=255, blank=True)
    name = models.ForeignKey(ServicesActivated, to_field='name', related_name='+', on_delete=models.CASCADE)
    username = models.CharField(_('username'), max_length=255, default='', blank=True)
    password = models.CharField(_('password'), max_length=128, default='', blank=True)
    host = models.URLField(_('host'), default='', blank=True)
    client_id = models.CharField(_('client id'), max_length=255, default='', blank=True)
    client_secret = models.CharField(_('client secret'), max_length=255, default='', blank=True)
    duration = models.CharField(max_length=1, choices=DURATION, default=NONE)
    counter_ok = models.IntegerField(default=0)
    counter_ko = models.IntegerField(default=0)

    def show(self):
        """

        :return: string representing object
        """
        return "User Service %s %s %s" % (self.user, self.token, self.name)

    def __str__(self):
        return self.name.name


class TriggerService(models.Model):

    """
        TriggerService
    """
    provider = models.ForeignKey(UserService, related_name='+', blank=True, on_delete=models.CASCADE)
    consumer = models.ForeignKey(UserService, related_name='+', blank=True, on_delete=models.CASCADE)
    description = models.CharField(max_length=200)
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    date_created = models.DateField(auto_now_add=True)
    date_triggered = models.DateTimeField(null=True)
    status = models.BooleanField(default=False)
    result = models.CharField(max_length=255, default='')
    date_result = models.DateTimeField(auto_now=True, null=True)
    provider_failed = models.IntegerField(db_index=True, default=0)
    consumer_failed = models.IntegerField(db_index=True, default=0)

    counter_ok = models.IntegerField(default=0)
    counter_ko = models.IntegerField(default=0)

    def show(self):
        """

        :return: string representing object
        """
        return "My Service %s - %s - %s - %s" % (self.user,
                                                 self.provider.name,
                                                 self.consumer.name,
                                                 self.description)

    def __str__(self):
        return "%s - %s - %s - %s" % (self.user,
                                      self.provider.name,
                                      self.consumer.name,
                                      self.description)


class Digest(models.Model):
    """
    Digest service to store the data from other service
    """
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    title = models.CharField(max_length=600)
    link = models.URLField()
    duration = models.CharField(max_length=1)
    date_end = models.DateField()
    provider = models.CharField(max_length=40)

    def show(self):
        """

        :return: string representing object
        """
        return "Digest %s - %s - %s - %s - %s - %s" % (
            self.user, self.provider, self.title, self.link, self.duration,
            self.date_end)

    def __str__(self):
        return "%s - %s - %s - %s - %s - %s" % (
            self.user, self.provider, self.title, self.link, self.duration,
            self.date_end)


def update_result(trigger_id, msg, status):
    """
    :param trigger_id: trigger id
    :param msg: result msg
    :param status: status of the handling of the current trigger
    :return:
    """
    service = TriggerService.objects.get(id=trigger_id)
    # if status is True, reset *_failed counter
    if status:
        provider_failed = 0
        consumer_failed = 0
        counter_ok = service.counter_ok + 1
        counter_ko = service.counter_ko
    # otherwise, add 1 to the consumer_failed
    else:
        provider_failed = service.provider_failed
        consumer_failed = service.consumer_failed + 1
        counter_ok = service.counter_ko
        counter_ko = service.counter_ko + 1

        status = False if consumer_failed > settings.DJANGO_TH.get('failed_tries', 5) else True

        warn_user_and_admin('consumer', service)

    TriggerService.objects.filter(id=trigger_id).update(
        result=msg,
        date_result=now(),
        provider_failed=provider_failed,
        consumer_failed=consumer_failed,
        counter_ok=counter_ok,
        counter_ko=counter_ko,
        status=status)

    UserService.objects.filter(user=service.user, name=service.consumer.name).update(
        counter_ok=counter_ok,
        counter_ko=counter_ko)


def th_create_user_profile(sender, instance, created, **kwargs):
    # create the default service that does not
    # need any third party auth
    user = instance
    if user.last_login is None:
        for service in settings.SERVICES_NEUTRAL:
            try:
                sa = ServicesActivated.objects.get(name=service)
                UserService.objects.get_or_create(user=user, name=sa)
            except ObjectDoesNotExist:
                logger.debug("A new user %s has been connected but %s "
                             "could not be added to his services because "
                             "the service is present in th_settings.py file but not"
                             " activated from the Admin Panel" % (user, service))


post_save.connect(th_create_user_profile, sender=User, dispatch_uid="create_user_profile")


@receiver(digest_event)
def digest_save(sender, **kwargs):
    """

    :param sender:
    :param kwargs:
    :return:
    """
    # set the deadline of the publication of the digest data
    duration = kwargs.get('duration')
    if duration not in ('d', 'w', 'm'):
        return
    # get the current date
    now = arrow.utcnow().to(settings.TIME_ZONE)

    # set the deadline
    if duration == 'd':
        # set tomorrow
        tomorrow = now.shift(days=+1)
        date_end = tomorrow.date()  # noqa extrat the date part
    elif duration == 'w':
        # set next week
        next_week = now.shift(weeks=+1)
        date_end = next_week.date()
    else:
        # set next month
        next_month = now.shift(months=+1)
        date_end = next_month.date()

    Digest.objects.create(user=kwargs.get('user'),
                          title=kwargs.get('title'),
                          link=kwargs.get('link'),
                          duration=duration,
                          date_end=str(date_end),
                          provider=sender)