Ejemplo n.º 1
0
class Migration(migrations.Migration):

    dependencies = [
        ('users', '__first__'),
    ]

    operations = [
        migrations.CreateModel(
            name='Comment',
            fields=[
                ('id',
                 models.AutoField(verbose_name='ID',
                                  serialize=False,
                                  auto_created=True,
                                  primary_key=True)),
                ('text', models.TextField()),
                ('date', models.DateTimeField(auto_now_add=True)),
                ('likes', models.PositiveIntegerField(default=0)),
                ('dislikes', models.PositiveIntegerField(default=0)),
                ('rank', models.IntegerField(default=0)),
                ('commenter',
                 models.ForeignKey(related_name='profileComments',
                                   to='users.Profile')),
                ('parent',
                 models.ForeignKey(related_name='children',
                                   blank=True,
                                   to='questions.Comment',
                                   null=True)),
            ],
        ),
        migrations.CreateModel(
            name='Question',
            fields=[
                ('id',
                 models.AutoField(verbose_name='ID',
                                  serialize=False,
                                  auto_created=True,
                                  primary_key=True)),
                ('allow_anonymous_voter', models.BooleanField(default=True)),
                ('context', models.TextField(null=True, blank=True)),
                ('data_require_vote', models.BooleanField(default=True)),
                ('date', models.DateTimeField(auto_now_add=True)),
                ('date_begin',
                 models.DateTimeField(default=django.utils.timezone.now)),
                ('date_end', models.DateTimeField(null=True, blank=True)),
                ('fromIp', models.GenericIPAddressField()),
                ('hide_data', models.BooleanField(default=False)),
                ('question', models.CharField(max_length=140)),
                ('token', models.TextField(default=b'default')),
                ('votes', models.IntegerField(default=0)),
                ('public', models.BooleanField(default=True)),
                ('asker',
                 models.ForeignKey(related_name='questions',
                                   blank=True,
                                   to='users.Profile',
                                   null=True)),
            ],
        ),
        migrations.CreateModel(
            name='Reply',
            fields=[
                ('id',
                 models.AutoField(verbose_name='ID',
                                  serialize=False,
                                  auto_created=True,
                                  primary_key=True)),
                ('color', models.CharField(max_length=7, null=True,
                                           blank=True)),
                ('hits', models.BigIntegerField(default=0)),
                ('replyText', models.CharField(max_length=50)),
                ('token', models.TextField(default=b'default')),
                ('question',
                 models.ForeignKey(related_name='replies',
                                   to='questions.Question')),
            ],
        ),
        migrations.CreateModel(
            name='ReplyVotedBy',
            fields=[
                ('id',
                 models.AutoField(verbose_name='ID',
                                  serialize=False,
                                  auto_created=True,
                                  primary_key=True)),
                ('fromIp', models.GenericIPAddressField()),
                ('date', models.DateTimeField(auto_now_add=True)),
                ('question',
                 models.ForeignKey(related_name='questionVotes',
                                   to='questions.Question')),
                ('reply',
                 models.ForeignKey(related_name='replyVote',
                                   to='questions.Reply')),
                ('voter',
                 models.ForeignKey(blank=True, to='users.Profile', null=True)),
            ],
        ),
        migrations.AddField(
            model_name='comment',
            name='question',
            field=models.ForeignKey(related_name='comments',
                                    to='questions.Question'),
        ),
    ]
Ejemplo n.º 2
0
class WorkOrderDeposit(models.Model):
    '''
    METADATA
    '''
    class Meta:
        app_label = 'tenant_foundation'
        db_table = 'workery_work_order_deposits'
        verbose_name = _('Work Order Deposit')
        verbose_name_plural = _('Work Order Deposits')
        default_permissions = ()
        permissions = (
            ("can_get_order_deposits", "Can get work order deposits"),
            ("can_get_order_deposit", "Can get work order deposit"),
            ("can_post_order_deposit", "Can create work order deposit"),
            ("can_put_order_deposit", "Can update work order deposit"),
            ("can_delete_order_deposit", "Can delete work order deposit"),
        )

    '''
    CONSTANTS
    '''

    class DEPOSIT_METHOD:
        CASH = 1
        CHEQUE = 2
        CREDIT = 3
        DEBIT = 4

    class DEPOSIT_FOR:
        LABOUR = 1
        MATERIALS = 2
        WASTE_REMOVAL = 3
        AMOUNT_DUE = 4

    '''
    CHOICES
    '''

    DEPOSIT_METHOD_CHOICES = (
        (DEPOSIT_METHOD.CASH, _('Cash')),
        (DEPOSIT_METHOD.CHEQUE, _('Cheque')),
        (DEPOSIT_METHOD.CREDIT, _('Credit')),
        (DEPOSIT_METHOD.DEBIT, _('Debit')),
    )

    DEPOSIT_FOR_CHOICES = (
        (DEPOSIT_FOR.LABOUR, _('Labour')),
        (DEPOSIT_FOR.MATERIALS, _('Materials')),
        (DEPOSIT_FOR.WASTE_REMOVAL, _('Waste Removal')),
        (DEPOSIT_FOR.AMOUNT_DUE, _('Amount Due')),
    )
    '''
    OBJECT MANAGERS
    '''

    objects = WorkOrderDepositManager()
    '''
    MODEL FIELDS
    '''

    id = models.BigAutoField(primary_key=True,
                             default=increment_order_deposit_id_number,
                             editable=False,
                             db_index=True)

    #
    #  FIELDS
    #

    order = models.ForeignKey(
        "WorkOrder",
        help_text=_('The order whom this deposit belongs to.'),
        related_name="work_order_deposits",
        on_delete=models.CASCADE,
    )
    paid_at = models.DateField(
        _("Paid at"),
        help_text=_('The date this deposit was paid.'),
        null=True,
        blank=True,
    )
    deposit_method = models.PositiveSmallIntegerField(
        _("Deposit Method"),
        help_text=_('The method used for this deposit'),
        choices=DEPOSIT_METHOD_CHOICES)
    paid_to = models.PositiveSmallIntegerField(
        _("Paid to"),
        help_text=_('Whom was paid by the client for this invoice.'),
        choices=WORK_ORDER_PAID_TO_CHOICES,
        blank=True,
        null=True,
    )
    amount = MoneyField(
        _("Amount"),
        help_text=_('The amount that was deposited.'),
        max_digits=10,
        decimal_places=2,
        default_currency=WORKERY_APP_DEFAULT_MONEY_CURRENCY,
        default=Money(0, WORKERY_APP_DEFAULT_MONEY_CURRENCY),
        blank=True,
    )
    paid_for = models.PositiveSmallIntegerField(
        _("Paid for"),
        help_text=_('What was this deposit for?'),
        choices=DEPOSIT_FOR_CHOICES,
        blank=True)
    is_archived = models.BooleanField(
        _("Is Archived"),
        help_text=_('Indicates whether deposit was archived.'),
        default=False,
        blank=True,
        db_index=True)

    #  SYSTEM FIELDS
    #

    created_at = models.DateTimeField(auto_now_add=True, db_index=True)
    created_by = models.ForeignKey(
        SharedUser,
        help_text=_('The user whom created this order.'),
        related_name="created_work_order_deposits",
        on_delete=models.SET_NULL,
        blank=True,
        null=True)
    created_from = models.GenericIPAddressField(
        _("Created from"),
        help_text=_('The IP address of the creator.'),
        blank=True,
        null=True)
    created_from_is_public = models.BooleanField(
        _("Is the IP "),
        help_text=_('Is creator a public IP and is routable.'),
        default=False,
        blank=True)
    last_modified_at = models.DateTimeField(auto_now=True)
    last_modified_by = models.ForeignKey(
        SharedUser,
        help_text=_('The user whom last modified this order.'),
        related_name="last_modified_work_order_deposits",
        on_delete=models.SET_NULL,
        blank=True,
        null=True)
    last_modified_from = models.GenericIPAddressField(
        _("Last modified from"),
        help_text=_('The IP address of the modifier.'),
        blank=True,
        null=True)
    last_modified_from_is_public = models.BooleanField(
        _("Is the IP "),
        help_text=_('Is modifier a public IP and is routable.'),
        default=False,
        blank=True)

    #
    #  FUNCTIONS
    #

    def __str__(self):
        return str(self.id)

    def get_pretty_deposit_method(self):
        return str(dict(self.DEPOSIT_METHOD_CHOICES).get(self.deposit_method))

    def get_pretty_paid_to(self):
        return str(dict(WORK_ORDER_PAID_TO_CHOICES).get(self.paid_to))

    def get_pretty_paid_for(self):
        return str(dict(self.DEPOSIT_FOR_CHOICES).get(self.paid_for))
Ejemplo n.º 3
0
class Comment(models.Model):
    user_name = models.CharField(_("name"), max_length=50)
    user_email = models.EmailField(_("email address"))
    user_url = models.URLField(_("homepage"), blank=True)

    comment = models.TextField(_('comment'), max_length=500)

    ip_address = models.GenericIPAddressField(_('ip address'),
                                              blank=True,
                                              null=True)
    useragent = models.CharField(_("user agent string"),
                                 max_length=100,
                                 blank=True,
                                 null=True)

    entry = models.ForeignKey(BaseEntry,
                              related_name='parent',
                              on_delete=models.CASCADE)
    parent = models.ForeignKey('self',
                               related_name='children',
                               default=None,
                               null=True,
                               blank=True,
                               on_delete=models.CASCADE)

    is_public = models.BooleanField(_('is public'), default=True)
    is_notice = models.BooleanField(_('receive email notify'), default=True)

    created_at = models.DateTimeField(_("Created on"), auto_now_add=True)
    updated_at = models.DateTimeField(_("Updated on"),
                                      null=True,
                                      blank=True,
                                      auto_now=True)

    #Inspired by http://www.djangosnippets.org/snippets/112/
    # &http://www.voidspace.org.uk/python/modules.shtml#akismet
    def comment_check(self):
        '''
        Check a comment.
        Return True for ham, False for spam.
        Use this function before save a comment.
        '''
        try:
            if hasattr(settings, 'BAN_NON_CJK') and settings.BAN_NON_CJK:
                import re
                if not re.search("[\u4E00-\u9FC3\u3041-\u30FF]", self.comment):
                    raise Exception()

            if hasattr(settings,
                       'AKISMET_API_KEY') and settings.AKISMET_API_KEY:
                from akismet import Akismet
                akismet_api = Akismet(key=settings.AKISMET_API_KEY,
                                      blog_url='http://%s/' %
                                      Site.objects.get_current().domain)
                if akismet_api.verify_key():
                    akismet_data = {
                        'comment_type': 'comment',
                        'user_ip': self.ip_address,
                        'user_agent': self.user_agent,
                        'referrer': '',
                    }
                    return not akismet_api.comment_check(
                        self.comment.encode("utf8"),
                        data=akismet_data,
                        build_data=True)
            else:
                return True
        except:
            return False

    class Meta:
        ordering = ['-updated_at']

    def __unicode__(self):
        return self.comment
Ejemplo n.º 4
0
        models.SlugField(),
        models.TextField(),
        models.BinaryField(),
        models.BooleanField(),
        models.NullBooleanField(),
        models.DateField(),
        models.DateTimeField(),
        models.DurationField(),
        models.TimeField(),
        models.DecimalField(decimal_places=2, max_digits=7),
        models.FloatField(),
        models.FileField(),
        models.FilePathField(),
        models.ImageField(),
        models.EmailField(),
        models.GenericIPAddressField(),
        models.URLField(),
        models.UUIDField(),
        models.ForeignKey(
            TargetModel,
            on_delete=models.CASCADE,
            related_name='+',
        ),
        models.OneToOneField(
            TargetModel,
            on_delete=models.CASCADE,
            related_name='+',
        ),
    ]
}
not_nullable_models.update({
Ejemplo n.º 5
0
class Agent(models.Model):
    name = models.CharField(max_length=50)
    status = models.BooleanField()
    env = models.CharField(max_length=20)
    version = models.CharField(max_length=5)
    address = models.GenericIPAddressField(max_length=39, protocol='IPv4')
Ejemplo n.º 6
0
class Credential(models.Model):
    protocol_choices = (('ssh-password', _('ssh-password')), ('ssh-key',
                                                              _('ssh-key')),
                        ('ssh-key-with-password', _('ssh-key-with-password')),
                        ('vnc', _('vnc')), ('rdp', _('rdp')), ('telnet',
                                                               _('telnet')))
    security_choices = (
        ('rdp', _('Standard RDP encryption')),
        ('nla', _('Network Level Authentication')),
        ('tls', _('TLS encryption')),
        ('any', _('Allow the server to choose the type of security')),
    )
    name = models.CharField(max_length=40,
                            verbose_name=_('Credential name'),
                            blank=False,
                            unique=True)
    username = models.CharField(max_length=40,
                                verbose_name=_('Auth user name'),
                                blank=False)
    port = models.PositiveIntegerField(default=22,
                                       blank=False,
                                       verbose_name=_('Port'))
    method = models.CharField(max_length=40,
                              choices=(('password', _('password')),
                                       ('key', _('key'))),
                              blank=False,
                              default='password',
                              verbose_name=_('Method'))
    key = models.TextField(blank=True, verbose_name=_('Key'))
    password = models.CharField(max_length=40,
                                blank=True,
                                verbose_name=_('Password'))
    proxy = models.BooleanField(default=False, verbose_name=_('Proxy'))
    proxyserverip = models.GenericIPAddressField(protocol='ipv4',
                                                 null=True,
                                                 blank=True,
                                                 verbose_name=_('Proxy ip'))
    proxyport = models.PositiveIntegerField(blank=True,
                                            null=True,
                                            verbose_name=_('Proxy port'))
    proxypassword = models.CharField(max_length=40,
                                     verbose_name=_('Proxy password'),
                                     blank=True)
    protocol = models.CharField(max_length=40,
                                default='ssh-password',
                                choices=protocol_choices,
                                verbose_name=_('Protocol'))
    width = models.PositiveIntegerField(verbose_name=_('width'), default=1024)
    height = models.PositiveIntegerField(verbose_name=_('height'), default=768)
    dpi = models.PositiveIntegerField(verbose_name=_('dpi'), default=96)
    security = models.CharField(max_length=40,
                                default='any',
                                choices=security_choices,
                                verbose_name=_('Security'))

    def __unicode__(self):
        return self.name

    def __str__(self):
        return self.name

    def clean(self):
        if self.protocol == 'ssh-password' or self.protocol == 'ssh-key':
            if self.method == 'password' and len(self.password) == 0:
                raise ValidationError(
                    _('If you choose password auth method,You must set password!'
                      ))
            if self.method == 'password' and len(self.key) > 0:
                raise ValidationError(
                    _('If you choose password auth method,You must make key field for blank!'
                      ))
            if self.method == 'key' and len(self.key) == 0:
                raise ValidationError(
                    _('If you choose key auth method,You must fill in key field!'
                      ))
            if self.method == 'key' and len(self.password) > 0:
                raise ValidationError(
                    _('If you choose key auth method,You must make password field for blank!'
                      ))
            if self.proxy:
                if self.proxyserverip is None or self.proxyport is None:
                    raise ValidationError(
                        _('If you choose auth proxy,You must fill in proxyserverip and proxyport field !'
                          ))

    class Meta:
        permissions = (
            ("can_add_credential", _("Can add credential")),
            ("can_change_credential", _("Can change credential info")),
            ("can_delete_credential", _("Can delete credential info")),
            ("can_view_credential", _("Can view credential info")),
        )
Ejemplo n.º 7
0
class Migration(migrations.Migration):

    dependencies = [
        ('assets', '0003_auto_20181228_1542'),
    ]

    operations = [
        migrations.CreateModel(
            name='CPU',
            fields=[
                ('id',
                 models.AutoField(auto_created=True,
                                  primary_key=True,
                                  serialize=False,
                                  verbose_name='ID')),
                ('cpu_model',
                 models.CharField(blank=True,
                                  max_length=128,
                                  null=True,
                                  verbose_name='CPU型号')),
                ('cpu_count',
                 models.PositiveSmallIntegerField(default=1,
                                                  verbose_name='物理CPU个数')),
                ('cpu_core_count',
                 models.PositiveSmallIntegerField(default=1,
                                                  verbose_name='CPU核数')),
                ('asset',
                 models.OneToOneField(
                     blank=True,
                     null=True,
                     on_delete=django.db.models.deletion.SET_NULL,
                     to='assets.Asset')),
            ],
            options={
                'verbose_name': 'CPU',
                'verbose_name_plural': 'CPU',
            },
        ),
        migrations.CreateModel(
            name='Disk',
            fields=[
                ('id',
                 models.AutoField(auto_created=True,
                                  primary_key=True,
                                  serialize=False,
                                  verbose_name='ID')),
                ('sn', models.CharField(max_length=128, verbose_name='硬盘SN号')),
                ('slot',
                 models.CharField(blank=True,
                                  max_length=64,
                                  null=True,
                                  verbose_name='所在插槽位')),
                ('model',
                 models.CharField(blank=True,
                                  max_length=128,
                                  null=True,
                                  verbose_name='磁盘型号')),
                ('manufacturer',
                 models.CharField(blank=True,
                                  max_length=128,
                                  null=True,
                                  verbose_name='磁盘制造商')),
                ('capacity',
                 models.FloatField(blank=True,
                                   null=True,
                                   verbose_name='磁盘容量(GB)')),
                ('interface_type',
                 models.CharField(choices=[('SATA', 'SATA'), ('SAS', 'SAS'),
                                           ('SCSI', 'SCSI'), ('SSD', 'SSD'),
                                           ('unknown', 'unknown')],
                                  default='unknown',
                                  max_length=16,
                                  verbose_name='接口类型')),
                ('asset',
                 models.ForeignKey(
                     blank=True,
                     null=True,
                     on_delete=django.db.models.deletion.SET_NULL,
                     to='assets.Asset')),
            ],
            options={
                'verbose_name': '硬盘',
                'verbose_name_plural': '硬盘',
            },
        ),
        migrations.CreateModel(
            name='NIC',
            fields=[
                ('id',
                 models.AutoField(auto_created=True,
                                  primary_key=True,
                                  serialize=False,
                                  verbose_name='ID')),
                ('name',
                 models.CharField(blank=True,
                                  max_length=64,
                                  null=True,
                                  verbose_name='网卡名称')),
                ('model', models.CharField(max_length=128,
                                           verbose_name='网卡型号')),
                ('mac', models.CharField(max_length=64, verbose_name='MAC地址')),
                ('ip_address',
                 models.GenericIPAddressField(blank=True,
                                              null=True,
                                              verbose_name='IP地址')),
                ('net_mask',
                 models.CharField(blank=True,
                                  max_length=64,
                                  null=True,
                                  verbose_name='掩码')),
                ('bonding',
                 models.CharField(blank=True,
                                  max_length=64,
                                  null=True,
                                  verbose_name='绑定地址')),
                ('asset',
                 models.ForeignKey(
                     blank=True,
                     null=True,
                     on_delete=django.db.models.deletion.SET_NULL,
                     to='assets.Asset')),
            ],
            options={
                'verbose_name': '网卡',
                'verbose_name_plural': '网卡',
            },
        ),
        migrations.CreateModel(
            name='RAM',
            fields=[
                ('id',
                 models.AutoField(auto_created=True,
                                  primary_key=True,
                                  serialize=False,
                                  verbose_name='ID')),
                ('sn',
                 models.CharField(blank=True,
                                  max_length=128,
                                  null=True,
                                  verbose_name='SN号')),
                ('model',
                 models.CharField(blank=True,
                                  max_length=128,
                                  null=True,
                                  verbose_name='内存型号')),
                ('manufacturer',
                 models.CharField(blank=True,
                                  max_length=128,
                                  null=True,
                                  verbose_name='内存制造商')),
                ('slot', models.CharField(max_length=64, verbose_name='插槽')),
                ('capacity',
                 models.IntegerField(blank=True,
                                     null=True,
                                     verbose_name='内存大小(GB)')),
                ('asset',
                 models.ForeignKey(
                     blank=True,
                     null=True,
                     on_delete=django.db.models.deletion.SET_NULL,
                     to='assets.Asset')),
            ],
            options={
                'verbose_name': '内存',
                'verbose_name_plural': '内存',
            },
        ),
        migrations.AddField(
            model_name='newassetapprovalzone',
            name='asset_code',
            field=models.CharField(blank=True,
                                   max_length=128,
                                   null=True,
                                   verbose_name='资产编码'),
        ),
        migrations.AlterField(
            model_name='newassetapprovalzone',
            name='asset_type',
            field=models.CharField(blank=True,
                                   choices=[('network_device', '网络设备'),
                                            ('server_device', '服务器设备'),
                                            ('ip_device', 'IP资源'),
                                            ('o_device', '其他设备')],
                                   default='server',
                                   max_length=64,
                                   null=True,
                                   verbose_name='资产类型'),
        ),
        migrations.AlterUniqueTogether(
            name='ram',
            unique_together={('asset', 'slot')},
        ),
        migrations.AlterUniqueTogether(
            name='nic',
            unique_together={('asset', 'model', 'mac')},
        ),
        migrations.AlterUniqueTogether(
            name='disk',
            unique_together={('asset', 'sn')},
        ),
    ]
Ejemplo n.º 8
0
class GenericIPAddress(models.Model):
    ip = models.GenericIPAddressField(null=True, protocol='ipv4')
Ejemplo n.º 9
0
class Device(TrackedModel):
    enable = models.BooleanField(
        default=True, help_text="Enable/Disable scanning of this device")
    groupname = models.ForeignKey(DeviceGroups,
                                  on_delete=models.PROTECT,
                                  null=True,
                                  blank=True,
                                  default=None,
                                  help_text="Device group")
    management_ip = models.GenericIPAddressField(unique=True,
                                                 default=None,
                                                 max_length=15,
                                                 blank=False,
                                                 null=False,
                                                 help_text="Management IP")
    hostname = models.CharField(default=None,
                                max_length=256,
                                blank=True,
                                null=True,
                                help_text="Device HOSTNAME")
    vendor = models.CharField(max_length=100,
                              blank=True,
                              help_text="Device vendor name")
    model = models.CharField(max_length=100,
                             blank=True,
                             help_text="Device model name")
    software = models.CharField(max_length=100,
                                blank=True,
                                help_text="Device software version")
    device_type = models.CharField(max_length=100,
                                   blank=True,
                                   help_text="Device softare filename")
    connection_protocol = models.ForeignKey(
        ConnectionProtocol,
        on_delete=models.PROTECT,
        blank=True,
        default=None,
        help_text="Choose connection protocol/port")
    credential = models.ForeignKey(Credential,
                                   on_delete=models.PROTECT,
                                   blank=True,
                                   default=None,
                                   help_text="Choose authentication username")
    device_type = models.ForeignKey(DeviceType,
                                    blank=True,
                                    on_delete=models.PROTECT)
    notes = models.TextField(default=None,
                             blank=True,
                             null=True,
                             help_text="Notes")

    def __str__(self):
        device_name = ""
        if self.hostname:
            device_name = self.hostname
            if self.management_ip:
                device_name += " (" + str(self.management_ip) + ")"
        elif self.management_ip:
            device_name = self.management_ip

        return device_name

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

    def save(self, *args, **kwargs):
        if self.changed is None:  # first time new object only
            self.created = timezone.now()
        self.changed = timezone.now()  # update every save/update
        super().save(*args, **kwargs)
Ejemplo n.º 10
0
class OtherTypesArrayModel(PostgreSQLModel):
    ips = ArrayField(models.GenericIPAddressField())
    uuids = ArrayField(models.UUIDField())
    decimals = ArrayField(models.DecimalField(max_digits=5, decimal_places=2))
Ejemplo n.º 11
0
class Order(MoneyPropped, models.Model):
    # Identification
    shop = UnsavedForeignKey("Shop",
                             on_delete=models.PROTECT,
                             verbose_name=_('shop'))
    created_on = models.DateTimeField(auto_now_add=True,
                                      editable=False,
                                      verbose_name=_('created on'))
    modified_on = models.DateTimeField(auto_now_add=True,
                                       editable=False,
                                       verbose_name=_('modified on'))
    identifier = InternalIdentifierField(unique=True,
                                         db_index=True,
                                         verbose_name=_('order identifier'))
    # TODO: label is actually a choice field, need to check migrations/choice deconstruction
    label = models.CharField(max_length=32,
                             db_index=True,
                             verbose_name=_('label'))
    # The key shouldn't be possible to deduce (i.e. it should be random), but it is
    # not a secret. (It could, however, be used as key material for an actual secret.)
    key = models.CharField(max_length=32,
                           unique=True,
                           blank=False,
                           verbose_name=_('key'))
    reference_number = models.CharField(max_length=64,
                                        db_index=True,
                                        unique=True,
                                        blank=True,
                                        null=True,
                                        verbose_name=_('reference number'))

    # Contact information
    customer = UnsavedForeignKey("Contact",
                                 related_name='customer_orders',
                                 blank=True,
                                 null=True,
                                 on_delete=models.PROTECT,
                                 verbose_name=_('customer'))
    orderer = UnsavedForeignKey("PersonContact",
                                related_name='orderer_orders',
                                blank=True,
                                null=True,
                                on_delete=models.PROTECT,
                                verbose_name=_('orderer'))
    billing_address = models.ForeignKey("ImmutableAddress",
                                        related_name="billing_orders",
                                        blank=True,
                                        null=True,
                                        on_delete=models.PROTECT,
                                        verbose_name=_('billing address'))
    shipping_address = models.ForeignKey("ImmutableAddress",
                                         related_name='shipping_orders',
                                         blank=True,
                                         null=True,
                                         on_delete=models.PROTECT,
                                         verbose_name=_('shipping address'))
    tax_number = models.CharField(max_length=20,
                                  blank=True,
                                  verbose_name=_('tax number'))
    phone = models.CharField(max_length=32,
                             blank=True,
                             verbose_name=_('phone'))
    email = models.EmailField(max_length=128,
                              blank=True,
                              verbose_name=_('email address'))

    # Status
    creator = UnsavedForeignKey(settings.AUTH_USER_MODEL,
                                related_name='orders_created',
                                blank=True,
                                null=True,
                                on_delete=models.PROTECT,
                                verbose_name=_('creating user'))
    modified_by = UnsavedForeignKey(settings.AUTH_USER_MODEL,
                                    related_name='orders_modified',
                                    blank=True,
                                    null=True,
                                    on_delete=models.PROTECT,
                                    verbose_name=_('modifier user'))
    deleted = models.BooleanField(db_index=True,
                                  default=False,
                                  verbose_name=_('deleted'))
    status = UnsavedForeignKey("OrderStatus",
                               verbose_name=_('status'),
                               on_delete=models.PROTECT)
    payment_status = EnumIntegerField(PaymentStatus,
                                      db_index=True,
                                      default=PaymentStatus.NOT_PAID,
                                      verbose_name=_('payment status'))
    shipping_status = EnumIntegerField(ShippingStatus,
                                       db_index=True,
                                       default=ShippingStatus.NOT_SHIPPED,
                                       verbose_name=_('shipping status'))

    # Methods
    payment_method = UnsavedForeignKey("PaymentMethod",
                                       related_name="payment_orders",
                                       blank=True,
                                       null=True,
                                       default=None,
                                       on_delete=models.PROTECT,
                                       verbose_name=_('payment method'))
    payment_method_name = models.CharField(
        max_length=100,
        blank=True,
        default="",
        verbose_name=_('payment method name'))
    payment_data = JSONField(blank=True,
                             null=True,
                             verbose_name=_('payment data'))

    shipping_method = UnsavedForeignKey("ShippingMethod",
                                        related_name='shipping_orders',
                                        blank=True,
                                        null=True,
                                        default=None,
                                        on_delete=models.PROTECT,
                                        verbose_name=_('shipping method'))
    shipping_method_name = models.CharField(
        max_length=100,
        blank=True,
        default="",
        verbose_name=_('shipping method name'))
    shipping_data = JSONField(blank=True,
                              null=True,
                              verbose_name=_('shipping data'))

    extra_data = JSONField(blank=True, null=True, verbose_name=_('extra data'))

    # Money stuff
    taxful_total_price = TaxfulPriceProperty('taxful_total_price_value',
                                             'currency')
    taxless_total_price = TaxlessPriceProperty('taxless_total_price_value',
                                               'currency')

    taxful_total_price_value = MoneyValueField(editable=False,
                                               verbose_name=_('grand total'),
                                               default=0)
    taxless_total_price_value = MoneyValueField(
        editable=False, verbose_name=_('taxless total'), default=0)
    currency = CurrencyField(verbose_name=_('currency'))
    prices_include_tax = models.BooleanField(
        verbose_name=_('prices include tax'))

    display_currency = CurrencyField(blank=True,
                                     verbose_name=_('display currency'))
    display_currency_rate = models.DecimalField(
        max_digits=36,
        decimal_places=9,
        default=1,
        verbose_name=_('display currency rate'))

    # Other
    ip_address = models.GenericIPAddressField(null=True,
                                              blank=True,
                                              verbose_name=_('IP address'))
    # order_date is not `auto_now_add` for backdating purposes
    order_date = models.DateTimeField(editable=False,
                                      verbose_name=_('order date'))
    payment_date = models.DateTimeField(null=True,
                                        editable=False,
                                        verbose_name=_('payment date'))

    language = LanguageField(blank=True, verbose_name=_('language'))
    customer_comment = models.TextField(blank=True,
                                        verbose_name=_('customer comment'))
    admin_comment = models.TextField(blank=True,
                                     verbose_name=_('admin comment/notes'))
    require_verification = models.BooleanField(
        default=False, verbose_name=_('requires verification'))
    all_verified = models.BooleanField(default=False,
                                       verbose_name=_('all lines verified'))
    marketing_permission = models.BooleanField(
        default=True, verbose_name=_('marketing permission'))
    _codes = JSONField(blank=True, null=True, verbose_name=_('codes'))

    common_select_related = ("billing_address", )
    objects = OrderQuerySet.as_manager()

    class Meta:
        ordering = ("-id", )
        verbose_name = _('order')
        verbose_name_plural = _('orders')

    def __str__(self):  # pragma: no cover
        if self.billing_address_id:
            name = self.billing_address.name
        else:
            name = "-"
        if settings.SHOOP_ENABLE_MULTIPLE_SHOPS:
            return "Order %s (%s, %s)" % (self.identifier, self.shop.name,
                                          name)
        else:
            return "Order %s (%s)" % (self.identifier, name)

    @property
    def codes(self):
        return list(self._codes or [])

    @codes.setter
    def codes(self, value):
        codes = []
        for code in value:
            if not isinstance(code, six.text_type):
                raise TypeError('codes must be a list of strings')
            codes.append(code)
        self._codes = codes

    def cache_prices(self):
        taxful_total = TaxfulPrice(0, self.currency)
        taxless_total = TaxlessPrice(0, self.currency)
        for line in self.lines.all():
            taxful_total += line.taxful_price
            taxless_total += line.taxless_price
        self.taxful_total_price = _round_price(taxful_total)
        self.taxless_total_price = _round_price(taxless_total)

    def _cache_contact_values(self):
        sources = [
            self.shipping_address,
            self.billing_address,
            self.customer,
            self.orderer,
        ]

        fields = ("tax_number", "email", "phone")

        for field in fields:
            if getattr(self, field, None):
                continue
            for source in sources:
                val = getattr(source, field, None)
                if val:
                    setattr(self, field, val)
                    break

    def _cache_values(self):
        self._cache_contact_values()

        if not self.label:
            self.label = settings.SHOOP_DEFAULT_ORDER_LABEL

        if not self.currency:
            self.currency = self.shop.currency

        if not self.prices_include_tax:
            self.prices_include_tax = self.shop.prices_include_tax

        if not self.display_currency:
            self.display_currency = self.currency
            self.display_currency_rate = 1

        if self.shipping_method_id and not self.shipping_method_name:
            self.shipping_method_name = self.shipping_method.safe_translation_getter(
                "name",
                default=self.shipping_method.identifier,
                any_language=True)

        if self.payment_method_id and not self.payment_method_name:
            self.payment_method_name = self.payment_method.safe_translation_getter(
                "name",
                default=self.payment_method.identifier,
                any_language=True)

        if not self.key:
            self.key = get_random_string(32)

        if not self.modified_by:
            self.modified_by = self.creator

    def _save_identifiers(self):
        self.identifier = "%s" % (get_order_identifier(self))
        self.reference_number = get_reference_number(self)
        super(Order, self).save(update_fields=(
            "identifier",
            "reference_number",
        ))

    def full_clean(self, exclude=None, validate_unique=True):
        self._cache_values()
        return super(Order, self).full_clean(exclude, validate_unique)

    def save(self, *args, **kwargs):
        if not self.creator_id:
            if not settings.SHOOP_ALLOW_ANONYMOUS_ORDERS:
                raise ValidationError(
                    "Anonymous (userless) orders are not allowed "
                    "when SHOOP_ALLOW_ANONYMOUS_ORDERS is not enabled.")
        self._cache_values()
        first_save = (not self.pk)
        super(Order, self).save(*args, **kwargs)
        if first_save:  # Have to do a double save the first time around to be able to save identifiers
            self._save_identifiers()
        for line in self.lines.exclude(product_id=None):
            line.supplier.module.update_stock(line.product_id)

    def delete(self, using=None):
        if not self.deleted:
            self.deleted = True
            self.add_log_entry("Deleted.", kind=LogEntryKind.DELETION)
            # Bypassing local `save()` on purpose.
            super(Order, self).save(update_fields=("deleted", ), using=using)

    def set_canceled(self):
        if self.status.role != OrderStatusRole.CANCELED:
            self.status = OrderStatus.objects.get_default_canceled()
            self.save()

    def _set_paid(self):
        if self.payment_status != PaymentStatus.FULLY_PAID:  # pragma: no branch
            self.add_log_entry(_('Order marked as paid.'))
            self.payment_status = PaymentStatus.FULLY_PAID
            self.payment_date = now()
            self.save()

    def _set_partially_paid(self):
        if self.payment_status != PaymentStatus.PARTIALLY_PAID:
            self.add_log_entry(_('Order marked as partially paid.'))
            self.payment_status = PaymentStatus.PARTIALLY_PAID
            self.save()

    def is_paid(self):
        return (self.payment_status == PaymentStatus.FULLY_PAID)

    def get_total_paid_amount(self):
        amounts = self.payments.values_list('amount_value', flat=True)
        return Money(sum(amounts, Decimal(0)), self.currency)

    def get_total_unpaid_amount(self):
        difference = self.taxful_total_price.amount - self.get_total_paid_amount(
        )
        return max(difference, Money(0, self.currency))

    def create_payment(self, amount, payment_identifier=None, description=''):
        """
        Create a payment with given amount for this order.

        If the order already has payments and sum of their amounts is
        equal or greater than self.taxful_total_price, an exception is raised.

        If the end sum of all payments is equal or greater than
        self.taxful_total_price, then the order is marked as paid.

        :param amount:
          Amount of the payment to be created
        :type amount: Money
        :param payment_identifier:
          Identifier of the created payment. If not set, default value
          of "gateway_id:order_id:number" will be used (where number is
          number of payments in the order).
        :type payment_identifier: str|None
        :param description:
          Description of the payment. Will be set to `method` property
          of the created payment.
        :type description: str

        :returns: The created Payment object
        :rtype: shoop.core.models.Payment
        """
        assert isinstance(amount, Money)
        assert amount.currency == self.currency

        payments = self.payments.order_by('created_on')

        total_paid_amount = self.get_total_paid_amount()
        if total_paid_amount >= self.taxful_total_price.amount:
            raise NoPaymentToCreateException(
                "Order %s has already been fully paid (%s >= %s)." %
                (self.pk, total_paid_amount, self.taxful_total_price))

        if not payment_identifier:
            number = payments.count() + 1
            payment_identifier = '%d:%d' % (self.id, number)

        payment = self.payments.create(
            payment_identifier=payment_identifier,
            amount_value=amount.value,
            description=description,
        )

        if self.get_total_paid_amount() >= self.taxful_total_price.amount:
            self._set_paid()  # also calls save
        else:
            self._set_partially_paid()

        return payment

    @atomic
    def create_shipment(self,
                        product_quantities,
                        supplier=None,
                        shipment=None):
        """
        Create a shipment for this order from `product_quantities`.
        `product_quantities` is expected to be a dict mapping Product instances to quantities.

        Only quantities over 0 are taken into account, and if the mapping is empty or has no quantity value
        over 0, `NoProductsToShipException` will be raised.

        :param product_quantities: a dict mapping Product instances to quantities to ship
        :type product_quantities: dict[shoop.shop.models.Product, decimal.Decimal]
        :param supplier: Optional Supplier for this product. No validation is made
                         as to whether the given supplier supplies the products.
        :param shipment: Optional unsaved Shipment for ShipmentProduct's. If not given
                         Shipment is created based on supplier parameter.
        :raises: NoProductsToShipException
        :return: Saved, complete Shipment object
        :rtype: shoop.core.models.Shipment
        """
        if not product_quantities or not any(
                quantity > 0 for quantity in product_quantities.values()):
            raise NoProductsToShipException(
                "No products to ship (`quantities` is empty or has no quantity over 0)."
            )

        assert (supplier or shipment)
        if shipment:
            assert shipment.order == self

        from ._shipments import ShipmentProduct
        if not shipment:
            from ._shipments import Shipment
            shipment = Shipment(order=self, supplier=supplier)
        shipment.save()

        for product, quantity in product_quantities.items():
            if quantity > 0:
                sp = ShipmentProduct(shipment=shipment,
                                     product=product,
                                     quantity=quantity)
                sp.cache_values()
                sp.save()

        shipment.cache_values()
        shipment.save()

        self.add_log_entry(_(u"Shipment #%d created.") % shipment.id)
        self.update_shipping_status()
        shipment_created.send(sender=type(self), order=self, shipment=shipment)
        return shipment

    def create_shipment_of_all_products(self, supplier=None):
        """
        Create a shipment of all the products in this Order, no matter whether or not any have been previously
        marked as shipped or not.

        See the documentation for `create_shipment`.

        :param supplier: The Supplier to use. If `None`, the first supplier in
                         the order is used. (If several are in the order, this fails.)
        :return: Saved, complete Shipment object
        :rtype: shoop.shop.models.Shipment
        """
        suppliers_to_product_quantities = defaultdict(
            lambda: defaultdict(lambda: 0))
        lines = (self.lines.filter(type=OrderLineType.PRODUCT).values_list(
            "supplier_id", "product_id", "quantity"))
        for supplier_id, product_id, quantity in lines:
            if product_id:
                suppliers_to_product_quantities[supplier_id][
                    product_id] += quantity

        if not suppliers_to_product_quantities:
            raise NoProductsToShipException(
                "Could not find any products to ship.")

        if supplier is None:
            if len(suppliers_to_product_quantities) > 1:  # pragma: no cover
                raise ValueError(
                    "Can only use create_shipment_of_all_products when there is only one supplier"
                )
            supplier_id, quantities = suppliers_to_product_quantities.popitem()
            supplier = Supplier.objects.get(pk=supplier_id)
        else:
            quantities = suppliers_to_product_quantities[supplier.id]

        products = dict(
            (product.pk, product)
            for product in Product.objects.filter(pk__in=quantities.keys()))
        quantities = dict((products[product_id], quantity)
                          for (product_id, quantity) in quantities.items())
        return self.create_shipment(quantities, supplier=supplier)

    def check_all_verified(self):
        if not self.all_verified:
            new_all_verified = (not self.lines.filter(verified=False).exists())
            if new_all_verified:
                self.all_verified = True
                if self.require_verification:
                    self.add_log_entry(
                        _('All rows requiring verification have been verified.'
                          ))
                    self.require_verification = False
                self.save()
        return self.all_verified

    def get_purchased_attachments(self):
        from ._product_media import ProductMedia

        if self.payment_status != PaymentStatus.FULLY_PAID:
            return ProductMedia.objects.none()
        prods = self.lines.exclude(product=None).values_list("product_id",
                                                             flat=True)
        return ProductMedia.objects.filter(product__in=prods,
                                           enabled=True,
                                           purchased=True)

    def get_tax_summary(self):
        """
        :rtype: taxing.TaxSummary
        """
        all_line_taxes = []
        untaxed = TaxlessPrice(0, self.currency)
        for line in self.lines.all():
            line_taxes = list(line.taxes.all())
            all_line_taxes.extend(line_taxes)
            if not line_taxes:
                untaxed += line.taxless_price
        return taxing.TaxSummary.from_line_taxes(all_line_taxes, untaxed)

    def get_product_ids_and_quantities(self):
        quantities = defaultdict(lambda: 0)
        for product_id, quantity in self.lines.filter(
                type=OrderLineType.PRODUCT).values_list(
                    "product_id", "quantity"):
            quantities[product_id] += quantity
        return dict(quantities)

    def is_complete(self):
        return (self.status.role == OrderStatusRole.COMPLETE)

    def can_set_complete(self):
        fully_shipped = (self.shipping_status == ShippingStatus.FULLY_SHIPPED)
        canceled = (self.status.role == OrderStatusRole.CANCELED)
        return (not self.is_complete()) and fully_shipped and (not canceled)

    def is_canceled(self):
        return (self.status.role == OrderStatusRole.CANCELED)

    def can_set_canceled(self):
        canceled = (self.status.role == OrderStatusRole.CANCELED)
        paid = self.is_paid()
        shipped = (self.shipping_status != ShippingStatus.NOT_SHIPPED)
        return not (canceled or paid or shipped)

    def update_shipping_status(self):
        if self.shipping_status == ShippingStatus.FULLY_SHIPPED:
            return

        if not self.get_unshipped_products():
            self.shipping_status = ShippingStatus.FULLY_SHIPPED
            self.add_log_entry(
                _(u"All products have been shipped. Fully Shipped status set.")
            )
            self.save(update_fields=("shipping_status", ))
        elif self.shipments.count():
            self.shipping_status = ShippingStatus.PARTIALLY_SHIPPED
            self.save(update_fields=("shipping_status", ))

    def get_known_additional_data(self):
        """
        Get a list of "known additional data" in this order's payment_data, shipping_data and extra_data.
        The list is returned in the order the fields are specified in the settings entries for said known keys.
        `dict(that_list)` can of course be used to "flatten" the list into a dict.
        :return: list of 2-tuples.
        """
        output = []
        for data_dict, name_mapping in (
            (self.payment_data, settings.SHOOP_ORDER_KNOWN_PAYMENT_DATA_KEYS),
            (self.shipping_data,
             settings.SHOOP_ORDER_KNOWN_SHIPPING_DATA_KEYS),
            (self.extra_data, settings.SHOOP_ORDER_KNOWN_EXTRA_DATA_KEYS),
        ):
            if hasattr(data_dict, "get"):
                for key, display_name in name_mapping:
                    if key in data_dict:
                        output.append(
                            (force_text(display_name), data_dict[key]))
        return output

    def get_product_summary(self):
        """Return a dict of product IDs -> {ordered, unshipped, shipped}"""

        products = defaultdict(lambda: defaultdict(lambda: Decimal(0)))
        lines = (self.lines.filter(type=OrderLineType.PRODUCT).values_list(
            "product_id", "quantity"))
        for product_id, quantity in lines:
            products[product_id]['ordered'] += quantity
            products[product_id]['unshipped'] += quantity

        from ._shipments import ShipmentProduct

        shipment_prods = (ShipmentProduct.objects.filter(
            shipment__order=self).values_list("product_id", "quantity"))
        for product_id, quantity in shipment_prods:
            products[product_id]['shipped'] += quantity
            products[product_id]['unshipped'] -= quantity

        return products

    def get_unshipped_products(self):
        return dict(
            (product, summary_datum)
            for product, summary_datum in self.get_product_summary().items()
            if summary_datum['unshipped'])

    def get_status_display(self):
        return force_text(self.status)

    def get_tracking_codes(self):
        return [
            shipment.tracking_code for shipment in self.shipments.all()
            if shipment.tracking_code
        ]

    def can_edit(self):
        return (not self.is_canceled() and not self.is_complete()
                and self.shipping_status == ShippingStatus.NOT_SHIPPED
                and self.payment_status == PaymentStatus.NOT_PAID)
Ejemplo n.º 12
0
class Payment(models.Model):
    """A model that represents a single payment.

    This might be a transactable payment information such as credit card
    details, gift card information or a customer's authorization to charge
    their PayPal account.

    All payment process related pieces of information are stored
    at the gateway level, we are operating on the reusable token
    which is a unique identifier of the customer for given gateway.

    Several payment methods can be used within a single order. Each payment
    method may consist of multiple transactions.
    """

    gateway = models.CharField(max_length=255)
    is_active = models.BooleanField(default=True)
    created = models.DateTimeField(auto_now_add=True)
    modified = models.DateTimeField(auto_now=True)
    charge_status = models.CharField(max_length=20,
                                     choices=ChargeStatus.CHOICES,
                                     default=ChargeStatus.NOT_CHARGED)
    token = models.CharField(max_length=128, blank=True, default='')
    total = models.DecimalField(max_digits=settings.DEFAULT_MAX_DIGITS,
                                decimal_places=settings.DEFAULT_DECIMAL_PLACES,
                                default=Decimal('0.0'))
    captured_amount = models.DecimalField(
        max_digits=settings.DEFAULT_MAX_DIGITS,
        decimal_places=settings.DEFAULT_DECIMAL_PLACES,
        default=Decimal('0.0'))
    currency = models.CharField(max_length=10)  # FIXME: add ISO4217 validator

    checkout = models.ForeignKey(Cart,
                                 null=True,
                                 related_name='payments',
                                 on_delete=models.SET_NULL)
    order = models.ForeignKey(Order,
                              null=True,
                              related_name='payments',
                              on_delete=models.PROTECT)

    billing_email = models.EmailField(blank=True)
    billing_first_name = models.CharField(max_length=256, blank=True)
    billing_last_name = models.CharField(max_length=256, blank=True)
    billing_company_name = models.CharField(max_length=256, blank=True)
    billing_address_1 = models.CharField(max_length=256, blank=True)
    billing_address_2 = models.CharField(max_length=256, blank=True)
    billing_city = models.CharField(max_length=256, blank=True)
    billing_city_area = models.CharField(max_length=128, blank=True)
    billing_postal_code = models.CharField(max_length=256, blank=True)
    billing_country_code = models.CharField(max_length=2, blank=True)
    billing_country_area = models.CharField(max_length=256, blank=True)

    cc_first_digits = models.CharField(max_length=6, blank=True, default='')
    cc_last_digits = models.CharField(max_length=4, blank=True, default='')
    cc_brand = models.CharField(max_length=40, blank=True, default='')
    cc_exp_month = models.PositiveIntegerField(
        validators=[MinValueValidator(1),
                    MaxValueValidator(12)],
        null=True,
        blank=True)
    cc_exp_year = models.PositiveIntegerField(
        validators=[MinValueValidator(1000)], null=True, blank=True)

    customer_ip_address = models.GenericIPAddressField(blank=True, null=True)
    extra_data = models.TextField(blank=True, default='')

    class Meta:
        ordering = ('pk', )

    def __repr__(self):
        return 'Payment(gateway=%s, is_active=%s, created=%s, charge_status=%s)' % (
            self.gateway, self.is_active, self.created, self.charge_status)

    def get_last_transaction(self):
        return max(self.transactions.all(), default=None, key=attrgetter('pk'))

    def get_total(self):
        return Money(self.total, self.currency or settings.DEFAULT_CURRENCY)

    def get_authorized_amount(self):
        money = zero_money()

        # Query all the transactions which should be prefetched
        # to optimize db queries
        transactions = self.transactions.all()

        # There is no authorized amount anymore when capture is succeeded
        # since capture can only be made once, even it is a partial capture
        if any([
                txn.kind == TransactionKind.CAPTURE and txn.is_success
                for txn in transactions
        ]):
            return money

        # Filter the succeeded auth transactions
        authorized_txns = [
            txn for txn in transactions
            if txn.kind == TransactionKind.AUTH and txn.is_success
        ]

        # Calculate authorized amount from all succeeded auth transactions
        for txn in authorized_txns:
            money += Money(txn.amount, self.currency
                           or settings.DEFAULT_CURRENCY)

        # If multiple partial capture is supported later though it's unlikely,
        # the authorized amount should exclude the already captured amount here
        return money

    def get_captured_amount(self):
        return Money(self.captured_amount, self.currency
                     or settings.DEFAULT_CURRENCY)

    def get_charge_amount(self):
        """Retrieve the maximum capture possible."""
        return self.total - self.captured_amount

    @property
    def is_authorized(self):
        return any([
            txn.kind == TransactionKind.AUTH and txn.is_success
            for txn in self.transactions.all()
        ])

    @property
    def not_charged(self):
        return self.charge_status == ChargeStatus.NOT_CHARGED

    def can_authorize(self):
        return self.is_active and self.not_charged

    def can_capture(self):
        return self.is_active and self.not_charged and self.is_authorized

    def can_charge(self):
        not_fully_charged = (
            self.charge_status == ChargeStatus.PARTIALLY_CHARGED)
        return self.is_active and (self.not_charged or not_fully_charged)

    def can_void(self):
        return self.is_active and self.not_charged and self.is_authorized

    def can_refund(self):
        can_refund_charge_status = (ChargeStatus.PARTIALLY_CHARGED,
                                    ChargeStatus.FULLY_CHARGED,
                                    ChargeStatus.PARTIALLY_REFUNDED)
        return (self.is_active
                and self.charge_status in can_refund_charge_status
                and self.gateway != CustomPaymentChoices.MANUAL)
Ejemplo n.º 13
0
class Migration(migrations.Migration):

    dependencies = [
        ('sites', '0001_initial'),
        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
        ('contenttypes', '0001_initial'),
    ]

    operations = [
        migrations.CreateModel(
            name='Comment',
            fields=[
                ('id',
                 models.AutoField(verbose_name='ID',
                                  serialize=False,
                                  auto_created=True,
                                  primary_key=True)),
                ('object_pk', models.TextField(verbose_name='object ID')),
                ('user_name',
                 models.CharField(max_length=50,
                                  verbose_name="user's name",
                                  blank=True)),
                ('user_email',
                 models.EmailField(max_length=75,
                                   verbose_name="user's email address",
                                   blank=True)),
                ('user_url',
                 models.URLField(verbose_name="user's URL", blank=True)),
                ('comment',
                 models.TextField(max_length=3000, verbose_name='comment')),
                ('submit_date',
                 models.DateTimeField(default=None,
                                      verbose_name='date/time submitted')),
                ('ip_address',
                 models.GenericIPAddressField(unpack_ipv4=True,
                                              null=True,
                                              verbose_name='IP address',
                                              blank=True)),
                ('is_public',
                 models.BooleanField(
                     default=True,
                     help_text=
                     'Uncheck this box to make the comment effectively disappear from the site.',
                     verbose_name='is public')),
                ('is_removed',
                 models.BooleanField(
                     default=False,
                     help_text=
                     'Check this box if the comment is inappropriate. A "This comment has been removed"'
                     ' message will be displayed instead.',
                     verbose_name='is removed')),
                ('content_type',
                 models.ForeignKey(related_name='content_type_set_for_comment',
                                   verbose_name='content type',
                                   to='contenttypes.ContentType')),
                ('site', models.ForeignKey(to='sites.Site')),
                ('user',
                 models.ForeignKey(related_name='comment_comments',
                                   verbose_name='user',
                                   blank=True,
                                   to=settings.AUTH_USER_MODEL,
                                   null=True)),
            ],
            options={
                'ordering': ('submit_date', ),
                'db_table': 'django_comments',
                'verbose_name': 'comment',
                'verbose_name_plural': 'comments',
                'permissions': [('can_moderate', 'Can moderate comments')],
            },
            bases=(models.Model, ),
        ),
        migrations.CreateModel(
            name='CommentFlag',
            fields=[
                ('id',
                 models.AutoField(verbose_name='ID',
                                  serialize=False,
                                  auto_created=True,
                                  primary_key=True)),
                ('flag',
                 models.CharField(max_length=30,
                                  verbose_name='flag',
                                  db_index=True)),
                ('flag_date',
                 models.DateTimeField(default=None, verbose_name='date')),
                ('comment',
                 models.ForeignKey(related_name='flags',
                                   verbose_name='comment',
                                   to='django_comments.Comment')),
                ('user',
                 models.ForeignKey(related_name='comment_flags',
                                   verbose_name='user',
                                   to=settings.AUTH_USER_MODEL)),
            ],
            options={
                'db_table': 'django_comment_flags',
                'verbose_name': 'comment flag',
                'verbose_name_plural': 'comment flags',
            },
            bases=(models.Model, ),
        ),
        migrations.AlterUniqueTogether(
            name='commentflag',
            unique_together=set([('user', 'comment', 'flag')]),
        ),
    ]
class Migration(migrations.Migration):

    dependencies = [
        ('main', '0001_initial'),
    ]

    operations = [
        migrations.AlterModelOptions(
            name='blacklistedhost',
            options={'verbose_name': 'blacklisted host', 'verbose_name_plural': 'blacklisted hosts'},
        ),
        migrations.AlterModelOptions(
            name='domain',
            options={'verbose_name': 'domain', 'verbose_name_plural': 'domains'},
        ),
        migrations.AlterModelOptions(
            name='host',
            options={'verbose_name': 'host', 'verbose_name_plural': 'hosts'},
        ),
        migrations.AlterModelOptions(
            name='relatedhost',
            options={'verbose_name': 'related host', 'verbose_name_plural': 'related hosts'},
        ),
        migrations.AlterModelOptions(
            name='serviceupdater',
            options={'verbose_name': 'service updater', 'verbose_name_plural': 'service updaters'},
        ),
        migrations.AlterModelOptions(
            name='serviceupdaterhostconfig',
            options={'verbose_name': 'service updater host config', 'verbose_name_plural': 'service updater host configs'},
        ),
        migrations.AlterField(
            model_name='blacklistedhost',
            name='created',
            field=models.DateTimeField(auto_now_add=True, verbose_name='created at'),
            preserve_default=True,
        ),
        migrations.AlterField(
            model_name='blacklistedhost',
            name='created_by',
            field=models.ForeignKey(related_name='blacklisted_domains', verbose_name='created by', to=settings.AUTH_USER_MODEL),
            preserve_default=True,
        ),
        migrations.AlterField(
            model_name='blacklistedhost',
            name='last_update',
            field=models.DateTimeField(auto_now=True, verbose_name='last update'),
            preserve_default=True,
        ),
        migrations.AlterField(
            model_name='blacklistedhost',
            name='name_re',
            field=models.CharField(help_text='Blacklisted domain. Evaluated as regex (search).', unique=True, max_length=255, verbose_name='name RegEx'),
            preserve_default=True,
        ),
        migrations.AlterField(
            model_name='domain',
            name='available',
            field=models.BooleanField(default=True, help_text="Check if nameserver is available/reachable - if not checked, we'll pause querying/updating this nameserver for a while", verbose_name='available'),
            preserve_default=True,
        ),
        migrations.AlterField(
            model_name='domain',
            name='comment',
            field=models.CharField(default=b'', max_length=255, blank=True, help_text='Some arbitrary comment about your domain. If your domain is public, the comment will be also publicly shown.', null=True, verbose_name='comment'),
            preserve_default=True,
        ),
        migrations.AlterField(
            model_name='domain',
            name='created',
            field=models.DateTimeField(auto_now_add=True, verbose_name='created at'),
            preserve_default=True,
        ),
        migrations.AlterField(
            model_name='domain',
            name='created_by',
            field=models.ForeignKey(related_name='domains', verbose_name='created by', to=settings.AUTH_USER_MODEL),
            preserve_default=True,
        ),
        migrations.AlterField(
            model_name='domain',
            name='last_update',
            field=models.DateTimeField(auto_now=True, verbose_name='last update'),
            preserve_default=True,
        ),
        migrations.AlterField(
            model_name='domain',
            name='name',
            field=models.CharField(help_text='Name of the zone where dynamic hosts may get added', unique=True, max_length=255, verbose_name='name'),
            preserve_default=True,
        ),
        migrations.AlterField(
            model_name='domain',
            name='nameserver_ip',
            field=models.GenericIPAddressField(help_text='IP where the dynamic DNS updates for this zone will be sent to', verbose_name='nameserver IP'),
            preserve_default=True,
        ),
        migrations.AlterField(
            model_name='domain',
            name='nameserver_update_algorithm',
            field=models.CharField(default=b'HMAC_SHA512', help_text='HMAC_SHA512 is fine for bind9 (you can change this later, if needed)', max_length=16, verbose_name='nameserver update algorithm', choices=[(b'HMAC_SHA384', b'HMAC_SHA384'), (b'HMAC_SHA256', b'HMAC_SHA256'), (b'HMAC_SHA224', b'HMAC_SHA224'), (b'HMAC_SHA1', b'HMAC_SHA1'), (b'HMAC_MD5', b'HMAC_MD5'), (b'HMAC_SHA512', b'HMAC_SHA512')]),
            preserve_default=True,
        ),
        migrations.AlterField(
            model_name='domain',
            name='nameserver_update_secret',
            field=models.CharField(default=b'', help_text='Shared secret that allows updating this zone (base64 encoded)', max_length=88, verbose_name='nameserver update secret'),
            preserve_default=True,
        ),
        migrations.AlterField(
            model_name='domain',
            name='public',
            field=models.BooleanField(default=False, help_text="Check to allow any user to add dynamic hosts to this zone - if not checked, we'll only allow the owner to add hosts", verbose_name='public'),
            preserve_default=True,
        ),
        migrations.AlterField(
            model_name='host',
            name='abuse',
            field=models.BooleanField(default=False, help_text='Checked if we think you abuse the service - you may uncheck this AFTER fixing all issues on your side', verbose_name='abuse'),
            preserve_default=True,
        ),
        migrations.AlterField(
            model_name='host',
            name='abuse_blocked',
            field=models.BooleanField(default=False, help_text='Checked to block a host for abuse.', verbose_name='abuse blocked'),
            preserve_default=True,
        ),
        migrations.AlterField(
            model_name='host',
            name='available',
            field=models.BooleanField(default=True, help_text="Check if host is available/in use - if not checked, we won't accept updates for this host", verbose_name='available'),
            preserve_default=True,
        ),
        migrations.AlterField(
            model_name='host',
            name='client_faults',
            field=models.PositiveIntegerField(default=0, verbose_name='client faults'),
            preserve_default=True,
        ),
        migrations.AlterField(
            model_name='host',
            name='client_result_msg',
            field=models.CharField(default=b'', max_length=255, blank=True, help_text='Latest result message relating to the client', null=True, verbose_name='client result msg'),
            preserve_default=True,
        ),
        migrations.AlterField(
            model_name='host',
            name='comment',
            field=models.CharField(default=b'', max_length=255, blank=True, help_text='Some arbitrary comment about your host, e.g  who / what / where this host is', null=True, verbose_name='comment'),
            preserve_default=True,
        ),
        migrations.AlterField(
            model_name='host',
            name='created',
            field=models.DateTimeField(auto_now_add=True, verbose_name='created at'),
            preserve_default=True,
        ),
        migrations.AlterField(
            model_name='host',
            name='created_by',
            field=models.ForeignKey(related_name='hosts', verbose_name='created by', to=settings.AUTH_USER_MODEL),
            preserve_default=True,
        ),
        migrations.AlterField(
            model_name='host',
            name='domain',
            field=models.ForeignKey(verbose_name='domain', to='main.Domain'),
            preserve_default=True,
        ),
        migrations.AlterField(
            model_name='host',
            name='last_update',
            field=models.DateTimeField(auto_now=True, verbose_name='last update'),
            preserve_default=True,
        ),
        migrations.AlterField(
            model_name='host',
            name='last_update_ipv4',
            field=models.DateTimeField(null=True, verbose_name='last update IPv4', blank=True),
            preserve_default=True,
        ),
        migrations.AlterField(
            model_name='host',
            name='last_update_ipv6',
            field=models.DateTimeField(null=True, verbose_name='last update IPv6', blank=True),
            preserve_default=True,
        ),
        migrations.AlterField(
            model_name='host',
            name='name',
            field=models.CharField(help_text='The name of your host.', max_length=255, verbose_name='name', validators=[django.core.validators.RegexValidator(regex=b'^(([a-z0-9][a-z0-9\\-]*[a-z0-9])|[a-z0-9])$', message=b'Invalid host name: only "a-z", "0-9" and "-" is allowed'), nsupdate.main.models.host_blacklist_validator]),
            preserve_default=True,
        ),
        migrations.AlterField(
            model_name='host',
            name='netmask_ipv4',
            field=models.PositiveSmallIntegerField(default=32, help_text='Netmask/Prefix length for IPv4.', verbose_name='netmask IPv4'),
            preserve_default=True,
        ),
        migrations.AlterField(
            model_name='host',
            name='netmask_ipv6',
            field=models.PositiveSmallIntegerField(default=64, help_text='Netmask/Prefix length for IPv6.', verbose_name='netmask IPv6'),
            preserve_default=True,
        ),
        migrations.AlterField(
            model_name='host',
            name='server_faults',
            field=models.PositiveIntegerField(default=0, verbose_name='server faults'),
            preserve_default=True,
        ),
        migrations.AlterField(
            model_name='host',
            name='server_result_msg',
            field=models.CharField(default=b'', max_length=255, blank=True, help_text='Latest result message relating to the server', null=True, verbose_name='server result msg'),
            preserve_default=True,
        ),
        migrations.AlterField(
            model_name='host',
            name='tls_update_ipv4',
            field=models.BooleanField(default=False, verbose_name='TLS update IPv4'),
            preserve_default=True,
        ),
        migrations.AlterField(
            model_name='host',
            name='tls_update_ipv6',
            field=models.BooleanField(default=False, verbose_name='TLS update IPv4'),
            preserve_default=True,
        ),
        migrations.AlterField(
            model_name='host',
            name='update_secret',
            field=models.CharField(max_length=64, verbose_name='update secret'),
            preserve_default=True,
        ),
        migrations.AlterField(
            model_name='relatedhost',
            name='available',
            field=models.BooleanField(default=True, help_text="Check if host is available/in use - if not checked, we won't accept updates for this host", verbose_name='available'),
            preserve_default=True,
        ),
        migrations.AlterField(
            model_name='relatedhost',
            name='comment',
            field=models.CharField(default=b'', max_length=255, blank=True, help_text='Some arbitrary comment about your host, e.g  who / what / where this host is', null=True, verbose_name='comment'),
            preserve_default=True,
        ),
        migrations.AlterField(
            model_name='relatedhost',
            name='interface_id_ipv4',
            field=models.CharField(default=b'', help_text='The IPv4 interface ID of this host. Use IPv4 notation.', max_length=16, verbose_name='interface ID IPv4'),
            preserve_default=True,
        ),
        migrations.AlterField(
            model_name='relatedhost',
            name='interface_id_ipv6',
            field=models.CharField(default=b'', help_text='The IPv6 interface ID of this host. Use IPv6 notation.', max_length=22, verbose_name='interface ID IPv6'),
            preserve_default=True,
        ),
        migrations.AlterField(
            model_name='relatedhost',
            name='main_host',
            field=models.ForeignKey(related_name='relatedhosts', verbose_name='main host', to='main.Host'),
            preserve_default=True,
        ),
        migrations.AlterField(
            model_name='relatedhost',
            name='name',
            field=models.CharField(help_text='The name of a host in same network as your main host.', max_length=255, verbose_name='name', validators=[django.core.validators.RegexValidator(regex=b'^(([a-z0-9][a-z0-9\\-]*[a-z0-9])|[a-z0-9])$', message=b'Invalid host name: only "a-z", "0-9" and "-" is allowed')]),
            preserve_default=True,
        ),
        migrations.AlterField(
            model_name='serviceupdater',
            name='accept_ipv4',
            field=models.BooleanField(default=False, verbose_name='accept IPv4'),
            preserve_default=True,
        ),
        migrations.AlterField(
            model_name='serviceupdater',
            name='accept_ipv6',
            field=models.BooleanField(default=False, verbose_name='accept IPv6'),
            preserve_default=True,
        ),
        migrations.AlterField(
            model_name='serviceupdater',
            name='comment',
            field=models.CharField(default=b'', max_length=255, blank=True, help_text='Some arbitrary comment about the service', null=True, verbose_name='comment'),
            preserve_default=True,
        ),
        migrations.AlterField(
            model_name='serviceupdater',
            name='created',
            field=models.DateTimeField(auto_now_add=True, verbose_name='created at'),
            preserve_default=True,
        ),
        migrations.AlterField(
            model_name='serviceupdater',
            name='created_by',
            field=models.ForeignKey(related_name='serviceupdater', verbose_name='created by', to=settings.AUTH_USER_MODEL),
            preserve_default=True,
        ),
        migrations.AlterField(
            model_name='serviceupdater',
            name='last_update',
            field=models.DateTimeField(auto_now=True, verbose_name='last update'),
            preserve_default=True,
        ),
        migrations.AlterField(
            model_name='serviceupdater',
            name='name',
            field=models.CharField(help_text='Service name', max_length=32, verbose_name='name'),
            preserve_default=True,
        ),
        migrations.AlterField(
            model_name='serviceupdater',
            name='path',
            field=models.CharField(default=b'/nic/update', help_text='Update Server URL path of this service', max_length=255, verbose_name='path'),
            preserve_default=True,
        ),
        migrations.AlterField(
            model_name='serviceupdater',
            name='secure',
            field=models.BooleanField(default=True, help_text='Use https / TLS to contact the Update Server?', verbose_name='secure'),
            preserve_default=True,
        ),
        migrations.AlterField(
            model_name='serviceupdater',
            name='server',
            field=models.CharField(help_text='Update Server [name or IP] of this service', max_length=255, verbose_name='server'),
            preserve_default=True,
        ),
        migrations.AlterField(
            model_name='serviceupdaterhostconfig',
            name='comment',
            field=models.CharField(default=b'', max_length=255, blank=True, help_text='Some arbitrary comment about your host on that service', null=True, verbose_name='comment'),
            preserve_default=True,
        ),
        migrations.AlterField(
            model_name='serviceupdaterhostconfig',
            name='created',
            field=models.DateTimeField(auto_now_add=True, verbose_name='created at'),
            preserve_default=True,
        ),
        migrations.AlterField(
            model_name='serviceupdaterhostconfig',
            name='created_by',
            field=models.ForeignKey(related_name='serviceupdaterhostconfigs', verbose_name='created by', to=settings.AUTH_USER_MODEL),
            preserve_default=True,
        ),
        migrations.AlterField(
            model_name='serviceupdaterhostconfig',
            name='give_ipv4',
            field=models.BooleanField(default=False, verbose_name='give IPv4'),
            preserve_default=True,
        ),
        migrations.AlterField(
            model_name='serviceupdaterhostconfig',
            name='give_ipv6',
            field=models.BooleanField(default=False, verbose_name='give IPv6'),
            preserve_default=True,
        ),
        migrations.AlterField(
            model_name='serviceupdaterhostconfig',
            name='host',
            field=models.ForeignKey(related_name='serviceupdaterhostconfigs', verbose_name='host', to='main.Host'),
            preserve_default=True,
        ),
        migrations.AlterField(
            model_name='serviceupdaterhostconfig',
            name='hostname',
            field=models.CharField(default=b'', max_length=255, blank=True, help_text='The hostname for that service (used in query string)', null=True, verbose_name='hostname'),
            preserve_default=True,
        ),
        migrations.AlterField(
            model_name='serviceupdaterhostconfig',
            name='last_update',
            field=models.DateTimeField(auto_now=True, verbose_name='last update'),
            preserve_default=True,
        ),
        migrations.AlterField(
            model_name='serviceupdaterhostconfig',
            name='name',
            field=models.CharField(help_text='The name/id for that service (used for http basic auth)', max_length=255, verbose_name='name'),
            preserve_default=True,
        ),
        migrations.AlterField(
            model_name='serviceupdaterhostconfig',
            name='password',
            field=models.CharField(help_text='The password/secret for that service (used for http basic auth)', max_length=255, verbose_name='password'),
            preserve_default=True,
        ),
        migrations.AlterField(
            model_name='serviceupdaterhostconfig',
            name='service',
            field=models.ForeignKey(verbose_name='service', to='main.ServiceUpdater'),
            preserve_default=True,
        ),
    ]
class Migration(migrations.Migration):

    dependencies = [
        ('sites', '0001_initial'),
        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
    ]

    operations = [
        migrations.CreateModel(
            name='Article',
            fields=[
                ('id', models.AutoField(verbose_name='ID', primary_key=True, serialize=False, auto_created=True)),
                ('sortorder', models.PositiveIntegerField(verbose_name='sort order', db_index=True, help_text='Sort order determines the order in which articles are concatenated in a post.')),
                ('title', models.CharField(verbose_name='title', max_length=200)),
                ('text', models.TextField(verbose_name='text')),
                ('url', models.URLField(verbose_name='link', blank=True, null=True)),
                ('image', sorl.thumbnail.fields.ImageField(verbose_name='image', blank=True, null=True, upload_to='newsletter/images/%Y/%m/%d')),
            ],
            options={
                'verbose_name': 'article',
                'verbose_name_plural': 'articles',
                'ordering': ('sortorder',),
            },
        ),
        migrations.CreateModel(
            name='Message',
            fields=[
                ('id', models.AutoField(verbose_name='ID', primary_key=True, serialize=False, auto_created=True)),
                ('title', models.CharField(verbose_name='title', max_length=200)),
                ('slug', models.SlugField(verbose_name='slug')),
                ('date_create', models.DateTimeField(verbose_name='created', auto_now_add=True)),
                ('date_modify', models.DateTimeField(verbose_name='modified', auto_now=True)),
            ],
            options={
                'verbose_name': 'message',
                'verbose_name_plural': 'messages',
            },
        ),
        migrations.CreateModel(
            name='Newsletter',
            fields=[
                ('id', models.AutoField(verbose_name='ID', primary_key=True, serialize=False, auto_created=True)),
                ('title', models.CharField(verbose_name='newsletter title', max_length=200)),
                ('slug', models.SlugField(unique=True)),
                ('email', models.EmailField(verbose_name='e-mail', max_length=254, help_text='Sender e-mail')),
                ('sender', models.CharField(verbose_name='sender', max_length=200, help_text='Sender name')),
                ('visible', models.BooleanField(verbose_name='visible', db_index=True, default=True)),
                ('send_html', models.BooleanField(verbose_name='send html', default=True, help_text='Whether or not to send HTML versions of e-mails.')),
                ('site', models.ManyToManyField(default=newsletter.utils.get_default_sites, to='sites.Site')),
            ],
            options={
                'verbose_name': 'newsletter',
                'verbose_name_plural': 'newsletters',
            },
            managers=[
                ('objects', django.db.models.manager.Manager()),
                ('on_site', django.contrib.sites.managers.CurrentSiteManager()),
            ],
        ),
        migrations.CreateModel(
            name='Submission',
            fields=[
                ('id', models.AutoField(verbose_name='ID', primary_key=True, serialize=False, auto_created=True)),
                ('publish_date', models.DateTimeField(verbose_name='publication date', blank=True, null=True, db_index=True, default=django.utils.timezone.now)),
                ('publish', models.BooleanField(verbose_name='publish', db_index=True, default=True, help_text='Publish in archive.')),
                ('prepared', models.BooleanField(verbose_name='prepared', db_index=True, default=False, editable=False)),
                ('sent', models.BooleanField(verbose_name='sent', db_index=True, default=False, editable=False)),
                ('sending', models.BooleanField(verbose_name='sending', db_index=True, default=False, editable=False)),
                ('message', models.ForeignKey(verbose_name='message', to='newsletter.Message')),
                ('newsletter', models.ForeignKey(verbose_name='newsletter', editable=False, to='newsletter.Newsletter')),
            ],
            options={
                'verbose_name': 'submission',
                'verbose_name_plural': 'submissions',
            },
        ),
        migrations.CreateModel(
            name='Subscription',
            fields=[
                ('id', models.AutoField(verbose_name='ID', primary_key=True, serialize=False, auto_created=True)),
                ('name_field', models.CharField(verbose_name='name', max_length=30, blank=True, null=True, help_text='optional', db_column='name')),
                ('email_field', models.EmailField(verbose_name='e-mail', max_length=254, blank=True, null=True, db_index=True, db_column='email')),
                ('ip', models.GenericIPAddressField(verbose_name='IP address', blank=True, null=True)),
                ('create_date', models.DateTimeField(default=django.utils.timezone.now, editable=False)),
                ('activation_code', models.CharField(verbose_name='activation code', max_length=40, default=newsletter.utils.make_activation_code)),
                ('subscribed', models.BooleanField(verbose_name='subscribed', db_index=True, default=False)),
                ('subscribe_date', models.DateTimeField(verbose_name='subscribe date', blank=True, null=True)),
                ('unsubscribed', models.BooleanField(verbose_name='unsubscribed', db_index=True, default=False)),
                ('unsubscribe_date', models.DateTimeField(verbose_name='unsubscribe date', blank=True, null=True)),
                ('newsletter', models.ForeignKey(verbose_name='newsletter', to='newsletter.Newsletter')),
                ('user', models.ForeignKey(verbose_name='user', blank=True, null=True, to=settings.AUTH_USER_MODEL)),
            ],
            options={
                'verbose_name': 'subscription',
                'verbose_name_plural': 'subscriptions',
            },
        ),
        migrations.AddField(
            model_name='submission',
            name='subscriptions',
            field=models.ManyToManyField(verbose_name='recipients', blank=True, db_index=True, help_text='If you select none, the system will automatically find the subscribers for you.', to='newsletter.Subscription'),
        ),
        migrations.AddField(
            model_name='message',
            name='newsletter',
            field=models.ForeignKey(verbose_name='newsletter', to='newsletter.Newsletter'),
        ),
        migrations.AddField(
            model_name='article',
            name='post',
            field=models.ForeignKey(verbose_name='message', related_name='articles', to='newsletter.Message'),
        ),
        migrations.AlterUniqueTogether(
            name='subscription',
            unique_together=set([('user', 'email_field', 'newsletter')]),
        ),
        migrations.AlterUniqueTogether(
            name='message',
            unique_together=set([('slug', 'newsletter')]),
        ),
    ]
Ejemplo n.º 16
0
class Migration(migrations.Migration):

    initial = True

    dependencies = [
        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
    ]

    operations = [
        migrations.CreateModel(
            name='Host',
            fields=[
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('name', models.CharField(max_length=64, unique=True)),
                ('ip_addr', models.GenericIPAddressField(unique=True)),
                ('monitored_by', models.CharField(choices=[('agent', 'Agent'), ('snmp', 'SNMP'), ('wget', 'WGET')], max_length=64, verbose_name='监控方式')),
                ('host_alive_check_interval', models.IntegerField(default=30, verbose_name='主机存活状态检测间隔')),
                ('status', models.IntegerField(choices=[(1, 'Online'), (2, 'Down'), (3, 'Unreachable'), (5, 'Problem')], default=1, verbose_name='状态')),
                ('memo', models.TextField(blank=True, null=True, verbose_name='备注')),
            ],
        ),
        migrations.CreateModel(
            name='HostGroup',
            fields=[
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('name', models.CharField(max_length=64, unique=True)),
                ('memo', models.TextField(blank=True, null=True, verbose_name='备注')),
            ],
        ),
        migrations.CreateModel(
            name='Service',
            fields=[
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('name', models.CharField(max_length=64, unique=True, verbose_name='服务名称')),
                ('interval', models.IntegerField(default=60, verbose_name='监控间隔')),
                ('plugin_name', models.CharField(default='n/a', max_length=64, verbose_name='插件名')),
                ('has_sub_service', models.BooleanField(default=False, help_text='如果一个服务还有独立的子服务 ,选择这个,比如 网卡服务有多个独立的子网卡')),
                ('memo', models.CharField(blank=True, max_length=128, null=True, verbose_name='备注')),
            ],
        ),
        migrations.CreateModel(
            name='ServiceIndex',
            fields=[
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('name', models.CharField(max_length=64)),
                ('key', models.CharField(max_length=64, unique=True)),
                ('data_type', models.CharField(choices=[('int', 'int'), ('float', 'float'), ('str', 'string')], default='int', max_length=32, verbose_name='指标数据类型')),
                ('memo', models.CharField(blank=True, max_length=128, null=True, verbose_name='备注')),
            ],
        ),
        migrations.CreateModel(
            name='Template',
            fields=[
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('name', models.CharField(max_length=64, unique=True, verbose_name='模版名称')),
                ('services', models.ManyToManyField(to='monitor.Service', verbose_name='服务列表')),
            ],
        ),
        migrations.CreateModel(
            name='UserProfile',
            fields=[
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('name', models.CharField(blank=True, max_length=64, null=True)),
                ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
            ],
        ),
        migrations.AddField(
            model_name='service',
            name='items',
            field=models.ManyToManyField(blank=True, to='monitor.ServiceIndex', verbose_name='指标列表'),
        ),
        migrations.AddField(
            model_name='hostgroup',
            name='templates',
            field=models.ManyToManyField(blank=True, to='monitor.Template'),
        ),
        migrations.AddField(
            model_name='host',
            name='host_groups',
            field=models.ManyToManyField(blank=True, to='monitor.HostGroup'),
        ),
        migrations.AddField(
            model_name='host',
            name='templates',
            field=models.ManyToManyField(blank=True, to='monitor.Template'),
        ),
    ]
Ejemplo n.º 17
0
class Port(PlCoreBase, ParameterMixin):
    network = models.ForeignKey(Network, related_name='links')
    instance = models.ForeignKey(Instance,
                                 null=True,
                                 blank=True,
                                 related_name='ports')
    ip = models.GenericIPAddressField(help_text="Instance ip address",
                                      blank=True,
                                      null=True)
    port_id = models.CharField(null=True,
                               blank=True,
                               max_length=256,
                               help_text="Neutron port id")
    mac = models.CharField(null=True,
                           blank=True,
                           max_length=256,
                           help_text="MAC address associated with this port")
    xos_created = models.BooleanField(
        default=False
    )  # True if XOS created this port in Neutron, False if port created by Neutron and observed by XOS

    class Meta:
        unique_together = ('network', 'instance')

    def save(self, *args, **kwds):
        if self.instance:
            slice = self.instance.slice
            if (slice not in self.network.permitted_slices.all()) and (
                    slice != self.network.owner) and (
                        not self.network.permit_all_slices):
                # to add a instance to the network, then one of the following must be true:
                #   1) instance's slice is in network's permittedSlices list,
                #   2) instance's slice is network's owner, or
                #   3) network's permitAllSlices is true
                raise ValueError(
                    "Slice %s is not allowed to connect to network %s" %
                    (str(slice), str(self.network)))

        super(Port, self).save(*args, **kwds)

    def __unicode__(self):
        if self.instance:
            return u'%s-%s' % (self.network.name, self.instance.instance_name)
        else:
            return u'%s-unboundport-%s' % (self.network.name, self.id)

    def can_update(self, user):
        if self.instance:
            return user.can_update_slice(self.instance.slice)
        if self.network:
            return user.can_update_slice(self.network.owner)
        return False

    @staticmethod
    def select_by_user(user):
        if user.is_admin:
            qs = Port.objects.all()
        else:
            instances = Instance.select_by_user(user)
            instance_ids = [instance.id for instance in instances]
            networks = Network.select_by_user(user)
            network_ids = [network.id for network in networks]
            qs = Port.objects.filter(
                Q(instance__in=instance_ids) | Q(network__in=network_ids))
        return qs

    def get_parameters(self):
        # returns parameters from the network, updated by self.
        p = {}
        if self.network:
            p = self.network.get_parameters()
        p.update(ParameterMixin.get_parameters(self))
        return p
Ejemplo n.º 18
0
class Migration(migrations.Migration):

    dependencies = []

    operations = [
        migrations.CreateModel(
            name='activity_table',
            fields=[
                ('id',
                 models.AutoField(verbose_name='ID',
                                  auto_created=True,
                                  serialize=False,
                                  primary_key=True)),
                ('user_id', models.IntegerField(db_index=True, default=0)),
                ('login_time',
                 models.DateTimeField(default=datetime.datetime(
                     2016, 12, 6, 21, 15, 43, 709995))),
                ('IP', models.GenericIPAddressField(default='xxx')),
                ('logout_time',
                 models.DateTimeField(default=datetime.datetime(
                     2016, 12, 6, 21, 15, 43, 709995))),
                ('activity_time',
                 models.CharField(default='xx(h)xx(m)xx(s) ', max_length=50)),
                ('login_state', models.IntegerField(default=0)),
                ('logout_state', models.IntegerField(default=0)),
            ],
            options={
                'ordering': ['-login_time'],
            },
        ),
        migrations.CreateModel(
            name='inviteCode_error_table',
            fields=[
                ('id',
                 models.AutoField(verbose_name='ID',
                                  auto_created=True,
                                  serialize=False,
                                  primary_key=True)),
                ('IP',
                 models.GenericIPAddressField(db_index=True, default='xxx')),
                ('error_times', models.IntegerField(default=0)),
                ('forbid_start_time',
                 models.DateTimeField(default=datetime.datetime(
                     2016, 12, 6, 21, 15, 43, 710995))),
                ('forbid_end_time',
                 models.DateTimeField(default=datetime.datetime(
                     2016, 12, 6, 21, 15, 43, 710995))),
            ],
        ),
        migrations.CreateModel(
            name='login_error_table',
            fields=[
                ('id',
                 models.AutoField(verbose_name='ID',
                                  auto_created=True,
                                  serialize=False,
                                  primary_key=True)),
                ('IP',
                 models.GenericIPAddressField(db_index=True, default='xxx')),
                ('error_times', models.IntegerField(default=0)),
                ('forbid_start_time',
                 models.DateTimeField(default=datetime.datetime(
                     2016, 12, 6, 21, 15, 43, 709995))),
                ('forbid_end_time',
                 models.DateTimeField(default=datetime.datetime(
                     2016, 12, 6, 21, 15, 43, 709995))),
            ],
        ),
        migrations.CreateModel(
            name='user_table',
            fields=[
                ('id',
                 models.AutoField(verbose_name='ID',
                                  auto_created=True,
                                  serialize=False,
                                  primary_key=True)),
                ('user_name', models.CharField(default='xxx', max_length=100)),
                ('phone', models.CharField(db_index=True, max_length=15)),
                ('password', models.CharField(max_length=500)),
                ('email',
                 models.EmailField(default='*****@*****.**', max_length=254)),
                ('reg_time',
                 models.DateTimeField(default=datetime.datetime(
                     2016, 12, 6, 21, 15, 43, 708995))),
                ('IP', models.GenericIPAddressField(default='xxx')),
                ('is_vip', models.IntegerField(default=0)),
                ('is_black', models.IntegerField(default=0)),
                ('black_time',
                 models.DateTimeField(default=datetime.datetime(
                     2016, 12, 6, 21, 15, 43, 708995))),
            ],
        ),
    ]
Ejemplo n.º 19
0
class Asset(models.Model):
    """    所有资产的共有数据表    """
    asset_type_choice = (
        ('server', '服务器'),
        ('networkdevice', '网络设备'),
        ('storagedevice', '存储设备'),
        ('securitydevice', '安全设备'),
        ('software', '软件资产'),
    )

    asset_status = (
        (0, '在线'),
        (1, '下线'),
        (2, '未知'),
        (3, '故障'),
        (4, '备用'),
    )

    asset_type = models.CharField(choices=asset_type_choice,
                                  max_length=64,
                                  default='server',
                                  verbose_name="资产类型")
    name = models.CharField(max_length=64, unique=True,
                            verbose_name="资产名称")  # 不可重复
    sn = models.CharField(max_length=128, unique=True,
                          verbose_name="资产序列号")  # 不可重复
    business_unit = models.ForeignKey('BusinessUnit',
                                      null=True,
                                      blank=True,
                                      verbose_name='所属业务线')
    status = models.SmallIntegerField(choices=asset_status,
                                      default=0,
                                      verbose_name='设备状态')

    manufacturer = models.ForeignKey('Manufacturer',
                                     null=True,
                                     blank=True,
                                     verbose_name='制造商')
    manage_ip = models.GenericIPAddressField(null=True,
                                             blank=True,
                                             verbose_name='管理IP')
    tags = models.ManyToManyField('Tag', blank=True, verbose_name='标签')
    admin = models.ForeignKey(User,
                              null=True,
                              blank=True,
                              verbose_name='资产管理员',
                              related_name='admin')
    idc = models.ForeignKey('IDC', null=True, blank=True, verbose_name='所在机房')
    contract = models.ForeignKey('Contract',
                                 null=True,
                                 blank=True,
                                 verbose_name='合同')

    purchase_day = models.DateField(null=True, blank=True, verbose_name="购买日期")
    expire_day = models.DateField(null=True, blank=True, verbose_name="过保日期")
    price = models.FloatField(null=True, blank=True, verbose_name="价格")

    approved_by = models.ForeignKey(User,
                                    null=True,
                                    blank=True,
                                    verbose_name='批准人',
                                    related_name='approved_by')

    memo = models.TextField(null=True, blank=True, verbose_name='备注')
    c_time = models.DateTimeField(auto_now_add=True, verbose_name='批准日期')
    m_time = models.DateTimeField(auto_now=True, verbose_name='更新日期')

    def __str__(self):
        return '<%s>  %s' % (self.get_asset_type_display(), self.name)

    class Meta:
        verbose_name = '资产总表'
        verbose_name_plural = "资产总表"
        ordering = ['-c_time']
Ejemplo n.º 20
0
class IPAccess(models.Model):
    """ IP 访问表 """
    IP = models.GenericIPAddressField()
    url = models.CharField(max_length=100)
    date = models.DateField()
Ejemplo n.º 21
0
class Tracker(models.Model):
    user = models.ForeignKey(User)
    submitted_date = models.DateTimeField('date submitted',
                                          default=timezone.now)
    tracker_date = models.DateTimeField('date tracked', default=timezone.now)
    ip = models.GenericIPAddressField()
    agent = models.TextField(blank=True)
    digest = models.CharField(max_length=100)
    data = models.TextField(blank=True)
    course = models.ForeignKey(Course,
                               null=True,
                               blank=True,
                               default=None,
                               on_delete=models.SET_NULL)
    type = models.CharField(max_length=10, null=True, blank=True, default=None)
    completed = models.BooleanField(default=False)
    time_taken = models.IntegerField(default=0)
    activity_title = models.TextField(blank=True, null=True, default=None)
    section_title = models.TextField(blank=True, null=True, default=None)
    uuid = models.TextField(blank=True, null=True, default=None)
    lang = models.CharField(max_length=10, null=True, blank=True, default=None)

    class Meta:
        verbose_name = _('Tracker')
        verbose_name_plural = _('Trackers')

    def __unicode__(self):
        return self.agent

    def is_first_tracker_today(self):
        olddate = timezone.now() + datetime.timedelta(hours=-24)
        no_attempts_today = Tracker.objects.filter(
            user=self.user,
            digest=self.digest,
            completed=True,
            submitted_date__gte=olddate).count()
        if no_attempts_today == 1:
            return True
        else:
            return False

    def get_activity_type(self):
        activities = Activity.objects.filter(digest=self.digest)
        for a in activities:
            return a.type
        media = Media.objects.filter(digest=self.digest)
        for m in media:
            return "media"
        return None

    def get_media_title(self):
        media = Media.objects.filter(digest=self.digest)
        for m in media:
            return m.filename
        return None

    def get_activity_title(self, lang='en'):
        media = Media.objects.filter(digest=self.digest)
        print media
        for m in media:
            return m.filename
        try:
            activity = Activity.objects.filter(digest=self.digest)
            for a in activity:
                print a.title
                titles = json.loads(a.title)
                if lang in titles:
                    return titles[lang]
                else:
                    for l in titles:
                        return titles[l]
        except:
            pass
        return self.activity_title

    def get_section_title(self, lang='en'):
        try:
            titles = json.loads(self.section_title)
            if lang in titles:
                return titles[lang]
            else:
                for l in titles:
                    return titles[l]
        except:
            pass
        return self.section_title

    def activity_exists(self):
        activities = Activity.objects.filter(digest=self.digest).count()
        if activities >= 1:
            return True
        media = Media.objects.filter(digest=self.digest).count()
        if media >= 1:
            return True
        return False

    @staticmethod
    def has_completed_trackers(course, user):
        count = Tracker.objects.filter(user=user,
                                       course=course,
                                       completed=True).count()
        if count > 0:
            return True
        return False

    @staticmethod
    def to_xml_string(course, user):
        doc = Document()
        trackerXML = doc.createElement('trackers')
        doc.appendChild(trackerXML)
        trackers = Tracker.objects.filter(user=user, course=course)
        for t in trackers:
            track = doc.createElement('tracker')
            track.setAttribute('digest', t.digest)
            track.setAttribute('submitteddate',
                               t.submitted_date.strftime('%Y-%m-%d %H:%M:%S'))
            track.setAttribute('completed', str(t.completed))
            track.setAttribute('type', t.type)
            if t.type == 'quiz':
                try:
                    quiz = doc.createElement('quiz')
                    data = json.loads(t.data)
                    quiz_attempt = QuizAttempt.objects.filter(
                        instance_id=data['instance_id'],
                        user=user).order_by('-submitted_date')[:1]
                    quiz.setAttribute('score', str(quiz_attempt[0].score))
                    quiz.setAttribute('maxscore',
                                      str(quiz_attempt[0].maxscore))
                    quiz.setAttribute(
                        'submitteddate',
                        quiz_attempt[0].submitted_date.strftime(
                            '%Y-%m-%d %H:%M:%S'))
                    quiz.setAttribute('passed', str(t.completed))
                    quiz.setAttribute("course", course.shortname)
                    track.appendChild(quiz)
                except ValueError:
                    pass
                except IndexError:
                    pass
            trackerXML.appendChild(track)
        return doc.toxml()

    @staticmethod
    def activity_views(user,
                       type,
                       start_date=None,
                       end_date=None,
                       course=None):
        results = Tracker.objects.filter(user=user, type=type)
        if start_date:
            results = results.filter(submitted_date__gte=start_date)
        if end_date:
            results = results.filter(submitted_date__lte=end_date)
        if course:
            results = results.filter(course=course)
        return results.count()

    @staticmethod
    def activity_secs(user, type, start_date=None, end_date=None, course=None):
        results = Tracker.objects.filter(user=user, type=type)
        if start_date:
            results = results.filter(submitted_date__gte=start_date)
        if end_date:
            results = results.filter(submitted_date__lte=end_date)
        if course:
            results = results.filter(course=course)
        time = results.aggregate(total=Sum('time_taken'))
        if time['total'] is None:
            return 0
        return time['total']

    def get_user_version(user, type):
        results = Tracker.objects.filter(user=user,
                                         type=type).latest('submitteddate')

        return results

    def get_lang(self):
        try:
            json_data = json.loads(self.data)
        except ValueError:
            return None

        if 'lang' in json_data:
            return json_data['lang']
Ejemplo n.º 22
0
class Migration(migrations.Migration):

    initial = True

    dependencies = [
        ('donations', '0004_auto_20160523_1525'),
        ('contenttypes', '0002_remove_content_type_name'),
        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
    ]

    operations = [
        migrations.CreateModel(
            name='MediaWallpostPhoto',
            fields=[
                ('id',
                 models.AutoField(auto_created=True,
                                  primary_key=True,
                                  serialize=False,
                                  verbose_name='ID')),
                ('photo', models.ImageField(upload_to=b'mediawallpostphotos')),
                ('deleted',
                 models.DateTimeField(blank=True,
                                      null=True,
                                      verbose_name='deleted')),
                ('ip_address',
                 models.GenericIPAddressField(blank=True,
                                              default=None,
                                              null=True,
                                              verbose_name='IP address')),
                ('author',
                 models.ForeignKey(
                     blank=True,
                     null=True,
                     on_delete=django.db.models.deletion.CASCADE,
                     related_name='mediawallpostphoto_wallpost_photo',
                     to=settings.AUTH_USER_MODEL,
                     verbose_name='author')),
                ('editor',
                 models.ForeignKey(
                     blank=True,
                     help_text='The last user to edit this wallpost photo.',
                     null=True,
                     on_delete=django.db.models.deletion.CASCADE,
                     to=settings.AUTH_USER_MODEL,
                     verbose_name='editor')),
            ],
        ),
        migrations.CreateModel(
            name='Reaction',
            fields=[
                ('id',
                 models.AutoField(auto_created=True,
                                  primary_key=True,
                                  serialize=False,
                                  verbose_name='ID')),
                ('text',
                 models.TextField(max_length=300,
                                  verbose_name='reaction text')),
                ('created',
                 django_extensions.db.fields.CreationDateTimeField(
                     auto_now_add=True, verbose_name='created')),
                ('updated',
                 django_extensions.db.fields.ModificationDateTimeField(
                     auto_now=True, verbose_name='updated')),
                ('deleted',
                 models.DateTimeField(blank=True,
                                      null=True,
                                      verbose_name='deleted')),
                ('ip_address',
                 models.GenericIPAddressField(blank=True,
                                              default=None,
                                              null=True,
                                              verbose_name='IP address')),
                ('author',
                 models.ForeignKey(on_delete=django.db.models.deletion.CASCADE,
                                   related_name='wallpost_reactions',
                                   to=settings.AUTH_USER_MODEL,
                                   verbose_name='author')),
                ('editor',
                 models.ForeignKey(
                     blank=True,
                     help_text='The last user to edit this reaction.',
                     null=True,
                     on_delete=django.db.models.deletion.CASCADE,
                     related_name='+',
                     to=settings.AUTH_USER_MODEL,
                     verbose_name='editor')),
            ],
            options={
                'ordering': ('created', ),
                'verbose_name': 'Reaction',
                'verbose_name_plural': 'Reactions',
            },
        ),
        migrations.CreateModel(
            name='Wallpost',
            fields=[
                ('id',
                 models.AutoField(auto_created=True,
                                  primary_key=True,
                                  serialize=False,
                                  verbose_name='ID')),
                ('created',
                 django_extensions.db.fields.CreationDateTimeField(
                     auto_now_add=True, verbose_name='created')),
                ('updated',
                 django_extensions.db.fields.ModificationDateTimeField(
                     auto_now=True, verbose_name='updated')),
                ('deleted',
                 models.DateTimeField(blank=True,
                                      null=True,
                                      verbose_name='deleted')),
                ('ip_address',
                 models.GenericIPAddressField(blank=True,
                                              default=None,
                                              null=True,
                                              verbose_name='IP address')),
                ('object_id',
                 models.PositiveIntegerField(verbose_name='object ID')),
                ('share_with_facebook', models.BooleanField(default=False)),
                ('share_with_twitter', models.BooleanField(default=False)),
                ('share_with_linkedin', models.BooleanField(default=False)),
                ('email_followers', models.BooleanField(default=True)),
            ],
            options={
                'ordering': ('created', ),
            },
        ),
        migrations.CreateModel(
            name='MediaWallpost',
            fields=[
                ('wallpost_ptr',
                 models.OneToOneField(
                     auto_created=True,
                     on_delete=django.db.models.deletion.CASCADE,
                     parent_link=True,
                     primary_key=True,
                     serialize=False,
                     to='wallposts.Wallpost')),
                ('title', models.CharField(max_length=60)),
                ('text',
                 models.TextField(blank=True, default=b'', max_length=300)),
                ('video_url',
                 models.URLField(blank=True, default=b'', max_length=100)),
            ],
            options={
                'abstract': False,
            },
            bases=('wallposts.wallpost', ),
        ),
        migrations.CreateModel(
            name='SystemWallpost',
            fields=[
                ('wallpost_ptr',
                 models.OneToOneField(
                     auto_created=True,
                     on_delete=django.db.models.deletion.CASCADE,
                     parent_link=True,
                     primary_key=True,
                     serialize=False,
                     to='wallposts.Wallpost')),
                ('text', models.TextField(blank=True, max_length=300)),
                ('related_id',
                 models.PositiveIntegerField(verbose_name='related ID')),
                ('related_type',
                 models.ForeignKey(on_delete=django.db.models.deletion.CASCADE,
                                   to='contenttypes.ContentType',
                                   verbose_name='related type')),
            ],
            options={
                'abstract': False,
            },
            bases=('wallposts.wallpost', ),
        ),
        migrations.CreateModel(
            name='TextWallpost',
            fields=[
                ('wallpost_ptr',
                 models.OneToOneField(
                     auto_created=True,
                     on_delete=django.db.models.deletion.CASCADE,
                     parent_link=True,
                     primary_key=True,
                     serialize=False,
                     to='wallposts.Wallpost')),
                ('text', models.TextField(max_length=300)),
            ],
            options={
                'abstract': False,
            },
            bases=('wallposts.wallpost', ),
        ),
        migrations.AddField(
            model_name='wallpost',
            name='author',
            field=models.ForeignKey(
                blank=True,
                null=True,
                on_delete=django.db.models.deletion.CASCADE,
                related_name='wallpost_wallpost',
                to=settings.AUTH_USER_MODEL,
                verbose_name='author'),
        ),
        migrations.AddField(
            model_name='wallpost',
            name='content_type',
            field=models.ForeignKey(
                on_delete=django.db.models.deletion.CASCADE,
                related_name='content_type_set_for_wallpost',
                to='contenttypes.ContentType',
                verbose_name='content type'),
        ),
        migrations.AddField(
            model_name='wallpost',
            name='donation',
            field=models.ForeignKey(
                blank=True,
                null=True,
                on_delete=django.db.models.deletion.CASCADE,
                related_name='donation',
                to='donations.Donation',
                verbose_name='Donation'),
        ),
        migrations.AddField(
            model_name='wallpost',
            name='editor',
            field=models.ForeignKey(
                blank=True,
                help_text='The last user to edit this wallpost.',
                null=True,
                on_delete=django.db.models.deletion.CASCADE,
                to=settings.AUTH_USER_MODEL,
                verbose_name='editor'),
        ),
        migrations.AddField(
            model_name='wallpost',
            name='polymorphic_ctype',
            field=models.ForeignKey(
                editable=False,
                null=True,
                on_delete=django.db.models.deletion.CASCADE,
                related_name='polymorphic_wallposts.wallpost_set+',
                to='contenttypes.ContentType'),
        ),
        migrations.AddField(
            model_name='reaction',
            name='wallpost',
            field=models.ForeignKey(
                on_delete=django.db.models.deletion.CASCADE,
                related_name='reactions',
                to='wallposts.Wallpost'),
        ),
        migrations.AddField(
            model_name='mediawallpostphoto',
            name='mediawallpost',
            field=models.ForeignKey(
                blank=True,
                null=True,
                on_delete=django.db.models.deletion.CASCADE,
                related_name='photos',
                to='wallposts.MediaWallpost'),
        ),
    ]
Ejemplo n.º 23
0
class Queue(models.Model):
    """
    A queue is a collection of tickets into what would generally be business
    areas or departments.

    For example, a company may have a queue for each Product they provide, or
    a queue for each of Accounts, Pre-Sales, and Support.

    """

    EMAIL_BOX_POP = 'pop3'
    EMAIL_BOX_IMAP = 'imap'

    EMAIL_BOX_CHOICES = ((EMAIL_BOX_POP, _('POP 3')), (EMAIL_BOX_IMAP,
                                                       _('IMAP')))

    PROXY_SOCKS4 = 'socks4'
    PROXY_SOCKS5 = 'socks5'
    PROXY_SOCKS_CHOICES = ((PROXY_SOCKS4, _('SOCKS4')), (PROXY_SOCKS4,
                                                         _('SOCKS5')))

    title = models.CharField(
        _('Title'),
        max_length=100,
    )

    slug = models.SlugField(
        _('Slug'),
        help_text=_('This slug is used when building ticket ID\'s. Once set, '
                    'try not to change it or e-mailing may get messy.'),
    )

    email_address = models.EmailField(
        _('E-Mail Address'),
        blank=True,
        null=True,
        help_text=_(
            'All outgoing e-mails for this queue will use this e-mail '
            'address. If you use IMAP or POP3, this should be the e-mail '
            'address for that mailbox.'),
    )

    locale = models.CharField(
        _('Locale'),
        max_length=10,
        blank=True,
        null=True,
        help_text=
        _('Locale of this queue. All correspondence in this queue will be in this language.'
          ),
    )

    allow_public_submission = models.BooleanField(
        _('Allow Public Submission?'),
        blank=True,
        default=False,
        help_text=_('Should this queue be listed on the public submission '
                    'form?'),
    )

    allow_email_submission = models.BooleanField(
        _('Allow E-Mail Submission?'),
        blank=True,
        default=False,
        help_text=_('Do you want to poll the e-mail box below for new '
                    'tickets?'),
    )

    escalate_days = models.IntegerField(
        _('Escalation Days'),
        blank=True,
        null=True,
        help_text=_('For tickets which are not held, how often do you wish to '
                    'increase their priority? Set to 0 for no escalation.'),
    )

    new_ticket_cc = models.CharField(
        _('New Ticket CC Address'),
        blank=True,
        null=True,
        max_length=200,
        help_text=_(
            'If an e-mail address is entered here, then it will '
            'receive notification of all new tickets created for this queue. '
            'Enter a comma between multiple e-mail addresses.'),
    )

    updated_ticket_cc = models.CharField(
        _('Updated Ticket CC Address'),
        blank=True,
        null=True,
        max_length=200,
        help_text=_(
            'If an e-mail address is entered here, then it will '
            'receive notification of all activity (new tickets, closed '
            'tickets, updates, reassignments, etc) for this queue. Separate '
            'multiple addresses with a comma.'),
    )

    email_box_type = models.CharField(
        _('E-Mail Box Type'),
        max_length=5,
        choices=EMAIL_BOX_CHOICES,
        blank=True,
        null=True,
        help_text=_('E-Mail server type for creating tickets automatically '
                    'from a mailbox - both POP3 and IMAP are supported.'),
    )

    email_box_host = models.CharField(
        _('E-Mail Hostname'),
        max_length=200,
        blank=True,
        null=True,
        help_text=_('Your e-mail server address - either the domain name or '
                    'IP address. May be "localhost".'),
    )

    email_box_port = models.IntegerField(
        _('E-Mail Port'),
        blank=True,
        null=True,
        help_text=_(
            'Port number to use for accessing e-mail. Default for '
            'POP3 is "110", and for IMAP is "143". This may differ on some '
            'servers. Leave it blank to use the defaults.'),
    )

    email_box_ssl = models.BooleanField(
        _('Use SSL for E-Mail?'),
        blank=True,
        default=False,
        help_text=_('Whether to use SSL for IMAP or POP3 - the default ports '
                    'when using SSL are 993 for IMAP and 995 for POP3.'),
    )

    email_box_user = models.CharField(
        _('E-Mail Username'),
        max_length=200,
        blank=True,
        null=True,
        help_text=_('Username for accessing this mailbox.'),
    )

    email_box_pass = models.CharField(
        _('E-Mail Password'),
        max_length=200,
        blank=True,
        null=True,
        help_text=_('Password for the above username'),
    )

    email_box_imap_folder = models.CharField(
        _('IMAP Folder'),
        max_length=100,
        blank=True,
        null=True,
        help_text=_(
            'If using IMAP, what folder do you wish to fetch messages '
            'from? This allows you to use one IMAP account for multiple '
            'queues, by filtering messages on your IMAP server into separate '
            'folders. Default: INBOX.'),
    )

    email_box_interval = models.IntegerField(
        _('E-Mail Check Interval'),
        help_text=_(
            'How often do you wish to check this mailbox? (in Minutes)'),
        blank=True,
        null=True,
        default='5',
    )

    email_box_last_check = models.DateTimeField(
        blank=True,
        null=True,
        editable=False,
        # This is updated by management/commands/get_mail.py.
    )

    socks_proxy_type = models.CharField(
        _('Socks Proxy Type'),
        max_length=8,
        choices=PROXY_SOCKS_CHOICES,
        blank=True,
        null=True,
        help_text=
        _('SOCKS4 or SOCKS5 allows you to proxy your connections through a SOCKS server.'
          ),
    )

    socks_proxy_host = models.GenericIPAddressField(
        _('Socks Proxy Host'),
        blank=True,
        null=True,
        help_text=_('Socks proxy IP address. Default: 127.0.0.1'),
    )

    socks_proxy_port = models.IntegerField(
        _('Socks Proxy Port'),
        blank=True,
        null=True,
        help_text=_(
            'Socks proxy port number. Default: 9150 (default TOR port)'),
    )

    def __str__(self):
        return "%s" % self.title

    class Meta:
        ordering = ('title', )
        verbose_name = _('Queue')
        verbose_name_plural = _('Queues')

    def _from_address(self):
        """
        Short property to provide a sender address in SMTP format,
        eg 'Name <email>'. We do this so we can put a simple error message
        in the sender name field, so hopefully the admin can see and fix it.
        """
        if not self.email_address:
            return u'NO QUEUE EMAIL ADDRESS DEFINED <%s>' % settings.DEFAULT_FROM_EMAIL
        else:
            return u'%s <%s>' % (self.title, self.email_address)

    from_address = property(_from_address)

    def save(self, *args, **kwargs):
        if self.email_box_type == 'imap' and not self.email_box_imap_folder:
            self.email_box_imap_folder = 'INBOX'

        if self.socks_proxy_type:
            if not self.socks_proxy_host:
                self.socks_proxy_host = '127.0.0.1'
            if not self.socks_proxy_port:
                self.socks_proxy_port = 9150
        else:
            self.socks_proxy_host = None
            self.socks_proxy_port = None

        if not self.email_box_port:
            if self.email_box_type == 'imap' and self.email_box_ssl:
                self.email_box_port = 993
            elif self.email_box_type == 'imap' and not self.email_box_ssl:
                self.email_box_port = 143
            elif self.email_box_type == 'pop3' and self.email_box_ssl:
                self.email_box_port = 995
            elif self.email_box_type == 'pop3' and not self.email_box_ssl:
                self.email_box_port = 110
        super(Queue, self).save(*args, **kwargs)
Ejemplo n.º 24
0
class LastSeen(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL,
                             on_delete=models.CASCADE)
    ip_of_seen = models.GenericIPAddressField(editable=False, default=None)
    time_and_date = models.DateTimeField(auto_now_add=True, editable=False)
Ejemplo n.º 25
0
class Migration(migrations.Migration):

    initial = True

    dependencies = [
        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
        ('contenttypes', '0002_remove_content_type_name'),
    ]

    operations = [
        migrations.CreateModel(
            name='Bookmark',
            fields=[
                ('id',
                 models.AutoField(auto_created=True,
                                  primary_key=True,
                                  serialize=False,
                                  verbose_name='ID')),
                ('title', models.CharField(max_length=128,
                                           verbose_name='Title')),
                ('url_name',
                 models.CharField(max_length=64, verbose_name='Url Name')),
                ('query',
                 models.CharField(blank=True,
                                  max_length=1000,
                                  verbose_name='Query String')),
                ('is_share',
                 models.BooleanField(default=False, verbose_name='Is Shared')),
                ('content_type',
                 models.ForeignKey(on_delete=django.db.models.deletion.CASCADE,
                                   to='contenttypes.ContentType')),
                ('user',
                 models.ForeignKey(blank=True,
                                   null=True,
                                   on_delete=django.db.models.deletion.CASCADE,
                                   to=settings.AUTH_USER_MODEL,
                                   verbose_name='user')),
            ],
            options={
                'verbose_name': 'Bookmark',
                'verbose_name_plural': 'Bookmarks',
            },
        ),
        migrations.CreateModel(
            name='Log',
            fields=[
                ('id',
                 models.AutoField(auto_created=True,
                                  primary_key=True,
                                  serialize=False,
                                  verbose_name='ID')),
                ('action_time',
                 models.DateTimeField(default=django.utils.timezone.now,
                                      editable=False,
                                      verbose_name='action time')),
                ('ip_addr',
                 models.GenericIPAddressField(blank=True,
                                              null=True,
                                              verbose_name='action ip')),
                ('object_id',
                 models.TextField(blank=True,
                                  null=True,
                                  verbose_name='object id')),
                ('object_repr',
                 models.CharField(max_length=200, verbose_name='object repr')),
                ('action_flag',
                 models.CharField(max_length=32, verbose_name='action flag')),
                ('message',
                 models.TextField(blank=True, verbose_name='change message')),
                ('content_type',
                 models.ForeignKey(
                     blank=True,
                     null=True,
                     on_delete=django.db.models.deletion.SET_NULL,
                     to='contenttypes.ContentType',
                     verbose_name='content type')),
                ('user',
                 models.ForeignKey(on_delete=django.db.models.deletion.CASCADE,
                                   to=settings.AUTH_USER_MODEL,
                                   verbose_name='user')),
            ],
            options={
                'verbose_name': 'log entry',
                'verbose_name_plural': 'log entries',
                'ordering': ('-action_time', ),
            },
        ),
        migrations.CreateModel(
            name='UserSettings',
            fields=[
                ('id',
                 models.AutoField(auto_created=True,
                                  primary_key=True,
                                  serialize=False,
                                  verbose_name='ID')),
                ('key',
                 models.CharField(max_length=256,
                                  verbose_name='Settings Key')),
                ('value', models.TextField(verbose_name='Settings Content')),
                ('user',
                 models.ForeignKey(on_delete=django.db.models.deletion.CASCADE,
                                   to=settings.AUTH_USER_MODEL,
                                   verbose_name='user')),
            ],
            options={
                'verbose_name': 'User Setting',
                'verbose_name_plural': 'User Settings',
            },
        ),
        migrations.CreateModel(
            name='UserWidget',
            fields=[
                ('id',
                 models.AutoField(auto_created=True,
                                  primary_key=True,
                                  serialize=False,
                                  verbose_name='ID')),
                ('page_id',
                 models.CharField(max_length=256, verbose_name='Page')),
                ('widget_type',
                 models.CharField(max_length=50, verbose_name='Widget Type')),
                ('value', models.TextField(verbose_name='Widget Params')),
                ('user',
                 models.ForeignKey(on_delete=django.db.models.deletion.CASCADE,
                                   to=settings.AUTH_USER_MODEL,
                                   verbose_name='user')),
            ],
            options={
                'verbose_name': 'User Widget',
                'verbose_name_plural': 'User Widgets',
            },
        ),
    ]
Ejemplo n.º 26
0
class Instance(models.Model):
    """
    When a user launches a machine, an Instance is created.
    Instances are described by their Name and associated Tags
    Instances have a specific ID of the machine or volume
    they were created from (source)
    Instances have a specific ID provided by the cloud provider (provider_alias)
    The IP Address, creation and termination date,
    and the user who launched the instance are recorded for logging purposes.
    """
    esh = None
    name = models.CharField(max_length=256)
    # TODO: CreateUUIDfield that is *not* provider_alias?
    # token is used to help instance 'phone home' to server post-deployment.
    token = models.CharField(max_length=36, blank=True, null=True)
    tags = models.ManyToManyField(Tag, blank=True)
    # The specific machine & provider for which this instance exists
    source = models.ForeignKey(InstanceSource, related_name='instances')
    provider_alias = models.CharField(max_length=256, unique=True)
    ip_address = models.GenericIPAddressField(null=True, unpack_ipv4=True)
    created_by = models.ForeignKey('AtmosphereUser')
    #FIXME: Why is null=True okay here?
    created_by_identity = models.ForeignKey(Identity, null=True)
    shell = models.BooleanField(default=False)
    vnc = models.BooleanField(default=False)
    web_desktop = models.BooleanField(default=False)
    password = models.CharField(max_length=64, blank=True, null=True)
    # FIXME  Problems when setting a default, missing auto_now_add
    start_date = models.DateTimeField()
    end_date = models.DateTimeField(null=True, blank=True)

    # Model Managers
    objects = models.Manager()  # The default manager.
    active_instances = ActiveInstancesManager()

    @property
    def project_name(self):
        if not self.created_by_identity:
            return None
        return self.created_by_identity.get_credential('ex_project_name')

    @property
    def provider(self):
        return self.source.provider

    @classmethod
    def for_user(self, user):
        identity_ids = user.current_identities.values_list('id', flat=True)
        qs = Instance.objects.filter(created_by_identity__in=identity_ids)
        return qs

    def get_total_hours(self):
        from service.monitoring import _get_allocation_result
        identity = self.created_by_identity
        limit_instances = [self.provider_alias]
        result = _get_allocation_result(identity,
                                        limit_instances=limit_instances)
        total_hours = result.total_runtime().total_seconds() / 3600.0
        hours = round(total_hours, 2)
        return hours

    def get_projects(self, user):
        # TODO: Replace with 'only_current'
        projects = self.projects.filter(
            Q(end_date=None) | Q(end_date__gt=timezone.now()),
            owner=user,
        )
        return projects

    def get_first_history(self):
        """
        Returns the first InstanceStatusHistory
        """
        # TODO: Profile Option
        # except InstanceStatusHistory.DoesNotExist:
        # TODO: Profile current choice
        try:
            return self.instancestatushistory_set.order_by(
                'start_date').first()
        except ObjectDoesNotExist:
            return None

    def get_last_history(self):
        """
        Returns the newest InstanceStatusHistory
        """
        # FIXME: Clean up this implementation OR rename to `get_or_create`
        # TODO: Profile Option
        # except InstanceStatusHistory.DoesNotExist:
        # TODO: Profile current choice
        #FIXME: Move this call so that it happens inside InstanceStatusHistory to avoid circ.dep.
        last_history = self.instancestatushistory_set.order_by(
            '-start_date').first()
        if last_history:
            return last_history
        else:
            unknown_size, _ = Size.objects.get_or_create(
                name='Unknown Size',
                alias='N/A',
                provider=self.provider,
                cpu=-1,
                mem=-1,
                root=-1,
                disk=-1)
            last_history = self._build_first_history('Unknown', unknown_size,
                                                     self.start_date,
                                                     self.end_date, True)
            logger.warn("No history existed for %s until now. "
                        "An 'Unknown' history was created" % self)
            return last_history

    def _build_first_history(self,
                             status_name,
                             size,
                             start_date,
                             end_date=None,
                             first_update=False,
                             activity=None):
        #FIXME: Move this call so that it happens inside InstanceStatusHistory to avoid circ.dep.
        from core.models import InstanceStatusHistory
        if not first_update and status_name not in [
                'build', 'pending', 'running'
        ]:
            logger.info("First Update Unknown - Status name on instance \
                        %s: %s - %s" % (self.provider_alias, status_name))
            # Instance state is 'unknown' from start of instance until now
            # NOTE: This is needed to prevent over-charging accounts
            status_name = 'unknown'
            activity = None
        first_history = InstanceStatusHistory.create_history(
            status_name,
            self,
            size,
            start_date=start_date,
            end_date=end_date,
            activity=activity)
        first_history.save()
        return first_history

    def update_history(self,
                       status_name,
                       size,
                       task=None,
                       tmp_status=None,
                       first_update=False):
        """
        Given the status name and size, look up the previous history object
        If nothing has changed: return (False, last_history)
        else: end date previous history object, start new history object.
              return (True, new_history)
        """
        #FIXME: Move this call so that it happens inside InstanceStatusHistory to avoid circ.dep.
        from core.models import InstanceStatusHistory
        import traceback
        # 1. Get status name
        status_name = _get_status_name_for_provider(
            self.provider_machine.provider, status_name, task, tmp_status)
        activity = self.esh_activity()
        # 2. Get the last history (or Build a new one if no other exists)
        last_history = self.get_last_history()
        if not last_history:
            last_history = InstanceStatusHistory.create_history(
                status_name,
                self,
                size,
                start_date=self.start_date,
                activity=activity)
            last_history.save()
            logger.debug(
                "STATUSUPDATE - FIRST - Instance:%s Old Status: %s - %s New\
                Status: %s Tmp Status: %s" %
                (self.provider_alias, self.esh_status(), self.esh_activity(),
                 status_name, tmp_status))
            logger.debug("STATUSUPDATE - Traceback: %s" %
                         traceback.format_stack())
        # 2. Size and name must match to continue using last history
        if last_history.status.name == status_name \
                and last_history.size.id == size.id:
            # logger.info("status_name matches last history:%s " %
            #        last_history.status.name)
            return (False, last_history)
        logger.debug(
            "STATUSUPDATE - Instance:%s Old Status: %s - %s New Status: %s\
            Tmp Status: %s" % (self.provider_alias, self.esh_status(),
                               self.esh_activity(), status_name, tmp_status))
        logger.debug("STATUSUPDATE - Traceback: %s" % traceback.format_stack())
        # 3. ASSERT: A new history item is required due to a State or Size
        # Change
        now_time = timezone.now()
        try:
            new_history = InstanceStatusHistory.transaction(
                status_name,
                activity,
                self,
                size,
                start_time=now_time,
                last_history=last_history)
            return (True, new_history)
        except ValueError:
            logger.exception("Bad transaction")
            return (False, last_history)

    def _calculate_active_time(self, delta=None):
        if not delta:
            # Default delta == Time since instance created.
            delta = timezone.now() - self.start_date

        past_time = timezone.now() - delta
        recent_history = self.instancestatushistory_set.filter(
            Q(end_date=None)
            | Q(end_date__gt=past_time)).order_by('start_date')
        total_time = timedelta()
        inst_prefix = "HISTORY,%s,%s" % (self.created_by.username,
                                         self.provider_alias[:5])
        for idx, state in enumerate(recent_history):
            # Can't start counting any earlier than 'delta'
            if state.start_date < past_time:
                start_count = past_time
            else:
                start_count = state.start_date
            # If date is current, stop counting 'right now'
            if not state.end_date:
                final_count = timezone.now()
            else:
                final_count = state.end_date

            if state.is_active():
                # Active time is easy
                active_time = final_count - start_count
            else:
                # Inactive states are NOT counted against the user
                active_time = timedelta()
            # multiply by CPU count of size.
            cpu_time = active_time * state.size.cpu
            logger.debug(
                "%s,%s,%s,%s CPU,%s,%s,%s,%s" %
                (inst_prefix, state.status.name, state.size.name,
                 state.size.cpu, strfdate(start_count), strfdate(final_count),
                 strfdelta(active_time), strfdelta(cpu_time)))
            total_time += cpu_time
        return total_time

    def get_active_hours(self, delta):
        # Don't move it up. Circular reference.
        from service.monitoring import delta_to_hours
        total_time = self._calculate_active_time(delta)
        return delta_to_hours(total_time)

    def get_active_time(self, earliest_time=None, latest_time=None):
        """
        Return active time, and the reference list that was counted.
        """
        accounting_list = self._accounting_list(earliest_time, latest_time)

        total_time = timedelta()
        for state in accounting_list:
            total_time += state.cpu_time
        return total_time, accounting_list

    def recent_history(self, earliest_time, latest_time):
        """
        Return all Instance Status History
          Currently Running
          OR
          Terminated after: now() - delta (ex:7 days, 1 month, etc.)
        """
        active_history = self.instancestatushistory_set.filter(
            # Collect history that is Current or has 'countable' time..
            Q(end_date=None)
            | Q(end_date__gt=earliest_time)).order_by('start_date')
        return active_history

    def _accounting_list(self, earliest_time=None, latest_time=None):
        """
        Return the list of InstanceStatusHistory that should be counted,
        according to the limits of 'earliest_time' and 'latest_time'
        """
        if not latest_time:
            latest_time = timezone.now()
        # Determine the earliest time to start counts.
        if not earliest_time:
            earliest_time = self.start_date

        accounting_list = []
        active_history = self.recent_history(earliest_time, latest_time)

        for state in active_history:
            (active_time, start_count,
             end_count) = state.get_active_time(earliest_time, latest_time)
            state.active_time = active_time
            state.start_count = start_count
            state.end_count = end_count
            state.cpu_time = active_time * state.size.cpu
            accounting_list.append(state)
        return accounting_list

    def end_date_all(self, end_date=None):
        """
        Call this function to tie up loose ends when the instance is finished
        (Destroyed, terminated, no longer exists..)
        """
        if not end_date:
            end_date = timezone.now()
        ish_list = self.instancestatushistory_set.filter(end_date=None)
        for ish in ish_list:
            # logger.info('Saving history:%s' % ish)
            if not ish.end_date:
                logger.info("END DATING instance history %s: %s" %
                            (ish, end_date))
                ish.end_date = end_date
                ish.save()
        if not self.end_date:
            logger.info("END DATING instance %s: %s" %
                        (self.provider_alias, end_date))
            self.end_date = end_date
            self.save()

    def creator_name(self):
        if not self.created_by:
            return "N/A"
        return self.created_by.username

    def hash_alias(self):
        return md5(self.provider_alias).hexdigest()

    def hash_machine_alias(self):
        if self.esh and self.esh._node\
           and self.esh._node.extra\
           and self.esh._node.extra.get('imageId'):
            return md5(self.esh._node.extra['imageId']).hexdigest()
        else:
            try:
                if self.source:
                    return md5(self.source.identifier).hexdigest()
            except InstanceSource.DoesNotExist:
                logger.exception("Unable to find provider_machine for %s." %
                                 self.provider_alias)
        return 'Unknown'

    def esh_fault(self):
        if self.esh:
            return self.esh.extra.get('fault', {})
        return {}

    def api_status(self):
        # Used by the v2 serializer - db only. no 'esh'
        last_history = self.get_last_history()
        if not last_history:
            return "Unknown"
        status_name = last_history.status.name
        #NOTE: This handles the two 'atmosphere created' special-case status types, networking/deploying.
        # If the last history is one of these states, return active
        if status_name in ["networking", "deploy_error", "deploying"]:
            return "active"
        return status_name

    def api_activity(self):
        # Used by the v2 serializer - db only. no 'esh'
        last_history = self.get_last_history()
        if not last_history:
            return ""
        status_name = last_history.status.name
        #FIXME: Using this, for now, in place of a better solution.descripted in core/models/instance_history.py:InstanceStatus
        if status_name not in ["networking", "deploy_error", "deploying"]:
            return ""
        return status_name

    def esh_status(self):
        if self.esh:
            return self.esh.get_status()
        last_history = self.get_last_history()
        if last_history:
            return last_history.status.name
        else:
            return "Unknown"

    def esh_activity(self):
        activity = None
        if self.esh:
            try:
                activity = " ".join(
                    self.esh.get_status().split(' - ')[1:]).strip()
            except:
                activity = None
            return activity
        last_history = self.get_last_history()
        if last_history:
            try:
                activity = " ".join(
                    last_history.status.split(' - ')[1:]).strip()
            except:
                activity = None
            return activity
        else:
            return "Unknown"

    def get_size(self):
        return self.get_last_history().size

    def esh_size(self):
        if not self.esh or not hasattr(self.esh, 'extra'):
            last_history = self.get_last_history()
            if last_history:
                return last_history.size.alias
            return "Unknown"
        extras = self.esh.extra
        if 'flavorId' in extras:
            return extras['flavorId']
        elif 'instance_type' in extras:
            return extras['instance_type']
        elif 'instancetype' in extras:
            return extras['instancetype']
        else:
            return "Unknown"

    def application_uuid(self):
        if self.source.is_machine():
            return self.source.providermachine\
                    .application_version.application.uuid
        else:
            return None

    def application_name(self):
        if self.source.is_machine():
            return self.source.providermachine\
                    .application_version.application.name
        else:
            return None

    def application_id(self):
        if self.source.is_machine():
            return self.source.providermachine\
                    .application_version.application.id
        else:
            return None

    @property
    def volume(self):
        if self.source.is_volume():
            return self.source.volume
        return None

    @property
    def provider_machine(self):
        if self.source.is_machine():
            return self.source.providermachine
        return None

    def esh_source_name(self):
        if self.source.is_machine():
            return self.source.providermachine\
                    .application_version.application.name
        elif self.source.is_volume():
            return self.source.volume.name
        else:
            return "%s - Source Unknown" % self.source.identifier

    def provider_uuid(self):
        return self.source.provider.uuid

    def provider_name(self):
        return self.source.provider.location

    def esh_source(self):
        return self.source.identifier

    @property
    def allocation_source(self):
        #FIXME: look up the current allocation source by "Scanning the event table" on this instance.
        from core.models.allocation_source import \
                InstanceAllocationSourceSnapshot as Snapshot
        snapshot = Snapshot.objects.filter(instance=self).first()
        return snapshot.allocation_source if snapshot else None

    def change_allocation_source(self, allocation_source, user=None):
        """
        Call this method when you want to issue a 'change_allocation_source' event to the database.
        """
        if not settings.USE_ALLOCATION_SOURCE:
            return
        from core.models.event_table import EventTable
        if not user:
            user = self.created_by
        #FIXME: comment out this line for AllocationSource
        if not allocation_source:
            raise Exception("Allocation source must not be null")
        payload = {
            'allocation_source_id': allocation_source.source_id,
            'instance_id': self.provider_alias
        }
        return EventTable.create_event("instance_allocation_source_changed",
                                       payload, user.username)

    def json(self):
        return {
            'alias': self.provider_alias,
            'name': self.name,
            'tags': [tag.json() for tag in self.tags.all()],
            'ip_address': self.ip_address,
            'provider_machine': self.provider_machine.json(),
            'created_by': self.created_by.username,
        }

    def __unicode__(self):
        return "%s (Name:%s, Creator:%s, IP:%s)" %\
            (self.provider_alias, self.name,
             self.creator_name(), self.ip_address)

    class Meta:
        db_table = "instance"
        app_label = "core"
Ejemplo n.º 27
0
class AuditLogEntry(Model):
    __core__ = False

    organization = FlexibleForeignKey('sentry.Organization')
    actor_label = models.CharField(max_length=64, null=True, blank=True)
    # if the entry was created via a user
    actor = FlexibleForeignKey('sentry.User',
                               related_name='audit_actors',
                               null=True,
                               blank=True)
    # if the entry was created via an api key
    actor_key = FlexibleForeignKey('sentry.ApiKey', null=True, blank=True)
    target_object = BoundedPositiveIntegerField(null=True)
    target_user = FlexibleForeignKey('sentry.User',
                                     null=True,
                                     blank=True,
                                     related_name='audit_targets')
    # TODO(dcramer): we want to compile this mapping into JSX for the UI
    event = BoundedPositiveIntegerField(choices=(
        # We emulate github a bit with event naming
        (AuditLogEntryEvent.MEMBER_INVITE, 'member.invite'),
        (AuditLogEntryEvent.MEMBER_ADD, 'member.add'),
        (AuditLogEntryEvent.MEMBER_ACCEPT, 'member.accept-invite'),
        (AuditLogEntryEvent.MEMBER_REMOVE, 'member.remove'),
        (AuditLogEntryEvent.MEMBER_EDIT, 'member.edit'),
        (AuditLogEntryEvent.MEMBER_JOIN_TEAM, 'member.join-team'),
        (AuditLogEntryEvent.MEMBER_LEAVE_TEAM, 'member.leave-team'),
        (AuditLogEntryEvent.TEAM_ADD, 'team.create'),
        (AuditLogEntryEvent.TEAM_EDIT, 'team.edit'),
        (AuditLogEntryEvent.TEAM_REMOVE, 'team.remove'),
        (AuditLogEntryEvent.PROJECT_ADD, 'project.create'),
        (AuditLogEntryEvent.PROJECT_EDIT, 'project.edit'),
        (AuditLogEntryEvent.PROJECT_REMOVE, 'project.remove'),
        (AuditLogEntryEvent.PROJECT_SET_PUBLIC, 'project.set-public'),
        (AuditLogEntryEvent.PROJECT_SET_PRIVATE, 'project.set-private'),
        (AuditLogEntryEvent.PROJECT_REQUEST_TRANSFER,
         'project.request-transfer'),
        (AuditLogEntryEvent.PROJECT_ACCEPT_TRANSFER,
         'project.accept-transfer'),
        (AuditLogEntryEvent.ORG_ADD, 'org.create'),
        (AuditLogEntryEvent.ORG_EDIT, 'org.edit'),
        (AuditLogEntryEvent.ORG_REMOVE, 'org.remove'),
        (AuditLogEntryEvent.ORG_RESTORE, 'org.restore'),
        (AuditLogEntryEvent.TAGKEY_REMOVE, 'tagkey.remove'),
        (AuditLogEntryEvent.PROJECTKEY_ADD, 'projectkey.create'),
        (AuditLogEntryEvent.PROJECTKEY_EDIT, 'projectkey.edit'),
        (AuditLogEntryEvent.PROJECTKEY_REMOVE, 'projectkey.remove'),
        (AuditLogEntryEvent.PROJECTKEY_ENABLE, 'projectkey.enable'),
        (AuditLogEntryEvent.PROJECTKEY_DISABLE, 'projectkey.disable'),
        (AuditLogEntryEvent.SSO_ENABLE, 'sso.enable'),
        (AuditLogEntryEvent.SSO_DISABLE, 'sso.disable'),
        (AuditLogEntryEvent.SSO_EDIT, 'sso.edit'),
        (AuditLogEntryEvent.SSO_IDENTITY_LINK, 'sso-identity.link'),
        (AuditLogEntryEvent.APIKEY_ADD, 'api-key.create'),
        (AuditLogEntryEvent.APIKEY_EDIT, 'api-key.edit'),
        (AuditLogEntryEvent.APIKEY_REMOVE, 'api-key.remove'),
        (AuditLogEntryEvent.RULE_ADD, 'rule.create'),
        (AuditLogEntryEvent.RULE_EDIT, 'rule.edit'),
        (AuditLogEntryEvent.RULE_REMOVE, 'rule.remove'),
        (AuditLogEntryEvent.SET_ONDEMAND, 'ondemand.edit'),
        (AuditLogEntryEvent.SERVICEHOOK_ADD, 'serivcehook.create'),
        (AuditLogEntryEvent.SERVICEHOOK_EDIT, 'serivcehook.edit'),
        (AuditLogEntryEvent.SERVICEHOOK_REMOVE, 'serivcehook.remove'),
        (AuditLogEntryEvent.SERVICEHOOK_ENABLE, 'serivcehook.enable'),
        (AuditLogEntryEvent.SERVICEHOOK_DISABLE, 'serivcehook.disable'),
    ))
    ip_address = models.GenericIPAddressField(null=True, unpack_ipv4=True)
    data = GzippedDictField()
    datetime = models.DateTimeField(default=timezone.now)

    class Meta:
        app_label = 'sentry'
        db_table = 'sentry_auditlogentry'

    __repr__ = sane_repr('organization_id', 'type')

    def save(self, *args, **kwargs):
        if not self.actor_label:
            assert self.actor or self.actor_key
            if self.actor:
                self.actor_label = self.actor.username
            else:
                self.actor_label = self.actor_key.key
        super(AuditLogEntry, self).save(*args, **kwargs)

    def get_actor_name(self):
        if self.actor:
            return self.actor.get_display_name()
        elif self.actor_key:
            return self.actor_key.key + ' (api key)'
        return self.actor_label

    def get_note(self):
        if self.event == AuditLogEntryEvent.MEMBER_INVITE:
            return 'invited member %s' % (self.data['email'], )
        elif self.event == AuditLogEntryEvent.MEMBER_ADD:
            if self.target_user == self.actor:
                return 'joined the organization'
            return 'added member %s' % (self.target_user.get_display_name(), )
        elif self.event == AuditLogEntryEvent.MEMBER_ACCEPT:
            return 'accepted the membership invite'
        elif self.event == AuditLogEntryEvent.MEMBER_REMOVE:
            if self.target_user == self.actor:
                return 'left the organization'
            return 'removed member %s' % (
                self.data.get('email')
                or self.target_user.get_display_name(), )
        elif self.event == AuditLogEntryEvent.MEMBER_EDIT:
            return 'edited member %s' % (self.data.get('email') or
                                         self.target_user.get_display_name(), )
        elif self.event == AuditLogEntryEvent.MEMBER_JOIN_TEAM:
            if self.target_user == self.actor:
                return 'joined team %s' % (self.data['team_slug'], )
            return 'added %s to team %s' % (
                self.data.get('email') or self.target_user.get_display_name(),
                self.data['team_slug'],
            )
        elif self.event == AuditLogEntryEvent.MEMBER_LEAVE_TEAM:
            if self.target_user == self.actor:
                return 'left team %s' % (self.data['team_slug'], )
            return 'removed %s from team %s' % (
                self.data.get('email') or self.target_user.get_display_name(),
                self.data['team_slug'],
            )

        elif self.event == AuditLogEntryEvent.ORG_ADD:
            return 'created the organization'
        elif self.event == AuditLogEntryEvent.ORG_EDIT:
            return 'edited the organization'
        elif self.event == AuditLogEntryEvent.ORG_REMOVE:
            return 'removed the organization'
        elif self.event == AuditLogEntryEvent.ORG_RESTORE:
            return 'restored the organization'

        elif self.event == AuditLogEntryEvent.TEAM_ADD:
            return 'created team %s' % (self.data['slug'], )
        elif self.event == AuditLogEntryEvent.TEAM_EDIT:
            return 'edited team %s' % (self.data['slug'], )
        elif self.event == AuditLogEntryEvent.TEAM_REMOVE:
            return 'removed team %s' % (self.data['slug'], )

        elif self.event == AuditLogEntryEvent.PROJECT_ADD:
            return 'created project %s' % (self.data['slug'], )
        elif self.event == AuditLogEntryEvent.PROJECT_EDIT:
            return 'edited project %s' % (self.data['slug'], )
        elif self.event == AuditLogEntryEvent.PROJECT_REMOVE:
            return 'removed project %s' % (self.data['slug'], )
        elif self.event == AuditLogEntryEvent.PROJECT_REQUEST_TRANSFER:
            return 'requested to transfer project %s' % (self.data['slug'], )
        elif self.event == AuditLogEntryEvent.PROJECT_ACCEPT_TRANSFER:
            return 'accepted transfer of project %s' % (self.data['slug'], )

        elif self.event == AuditLogEntryEvent.TAGKEY_REMOVE:
            return 'removed tags matching %s = *' % (self.data['key'], )

        elif self.event == AuditLogEntryEvent.PROJECTKEY_ADD:
            return 'added project key %s' % (self.data['public_key'], )
        elif self.event == AuditLogEntryEvent.PROJECTKEY_EDIT:
            return 'edited project key %s' % (self.data['public_key'], )
        elif self.event == AuditLogEntryEvent.PROJECTKEY_REMOVE:
            return 'removed project key %s' % (self.data['public_key'], )
        elif self.event == AuditLogEntryEvent.PROJECTKEY_ENABLE:
            return 'enabled project key %s' % (self.data['public_key'], )
        elif self.event == AuditLogEntryEvent.PROJECTKEY_DISABLE:
            return 'disabled project key %s' % (self.data['public_key'], )

        elif self.event == AuditLogEntryEvent.SSO_ENABLE:
            return 'enabled sso (%s)' % (self.data['provider'], )
        elif self.event == AuditLogEntryEvent.SSO_DISABLE:
            return 'disabled sso (%s)' % (self.data['provider'], )
        elif self.event == AuditLogEntryEvent.SSO_EDIT:
            return 'edited sso settings'
        elif self.event == AuditLogEntryEvent.SSO_IDENTITY_LINK:
            return 'linked their account to a new identity'

        elif self.event == AuditLogEntryEvent.APIKEY_ADD:
            return 'added api key %s' % (self.data['label'], )
        elif self.event == AuditLogEntryEvent.APIKEY_EDIT:
            return 'edited api key %s' % (self.data['label'], )
        elif self.event == AuditLogEntryEvent.APIKEY_REMOVE:
            return 'removed api key %s' % (self.data['label'], )

        elif self.event == AuditLogEntryEvent.RULE_ADD:
            return 'added rule "%s"' % (self.data['label'], )
        elif self.event == AuditLogEntryEvent.RULE_EDIT:
            return 'edited rule "%s"' % (self.data['label'], )
        elif self.event == AuditLogEntryEvent.RULE_REMOVE:
            return 'removed rule "%s"' % (self.data['label'], )

        elif self.event == AuditLogEntryEvent.SET_ONDEMAND:
            return 'changed on-demand max spend to $%d' % (
                self.data['ondemand'] / 100, )

        elif self.event == AuditLogEntryEvent.SERVICEHOOK_ADD:
            return 'added a service hook for "%s"' % (truncatechars(
                self.data['url'], 64), )
        elif self.event == AuditLogEntryEvent.SERVICEHOOK_EDIT:
            return 'edited the service hook for "%s"' % (truncatechars(
                self.data['url'], 64), )
        elif self.event == AuditLogEntryEvent.SERVICEHOOK_REMOVE:
            return 'removed the service hook for "%s"' % (truncatechars(
                self.data['url'], 64), )
        elif self.event == AuditLogEntryEvent.SERVICEHOOK_ENABLE:
            return 'enabled theservice hook for "%s"' % (truncatechars(
                self.data['url'], 64), )
        elif self.event == AuditLogEntryEvent.SERVICEHOOK_DISABLE:
            return 'disabled the service hook for "%s"' % (truncatechars(
                self.data['url'], 64), )

        return ''
Ejemplo n.º 28
0
class ApiKeySettings(models.Model):
    api_key = models.OneToOneField(ApiKey, on_delete=models.CASCADE)
    ip_whitelist = ArrayField(models.GenericIPAddressField(), default=list, null=True, blank=True)
Ejemplo n.º 29
0
class PolycomIpPhone(models.Model):
    phone_ip = models.GenericIPAddressField()
    mac_address = models.CharField(max_length = 20)
    time_stamp = models.DateTimeField(null = True)
Ejemplo n.º 30
0
class Migration(migrations.Migration):

    initial = True

    dependencies = []

    operations = [
        migrations.CreateModel(
            name='Host',
            fields=[
                ('id',
                 models.AutoField(auto_created=True,
                                  primary_key=True,
                                  serialize=False,
                                  verbose_name='ID')),
                ('fqdn',
                 models.CharField(
                     help_text='Is also used as HTTP Basic Auth username.',
                     max_length=255,
                     unique=True,
                     validators=[
                         django.core.validators.RegexValidator(
                             message=
                             'Invalid FQDN: only "a-z", "0-9" and "-" is allowed',
                             regex=
                             '(?=^.{4,253}$)(^((?!-)[a-zA-Z0-9-]{1,63}(?<!-)\\.)+[a-zA-Z]{2,63}$)'
                         )
                     ],
                     verbose_name='FQDN')),
                ('secret',
                 models.CharField(help_text='Will be hashed if changed.',
                                  max_length=128)),
                ('ipv4_enabled',
                 models.BooleanField(default=True,
                                     verbose_name='IPv4 enabled')),
                ('ipv6_enabled',
                 models.BooleanField(default=True,
                                     verbose_name='IPv6 enabled')),
                ('ipv4',
                 models.GenericIPAddressField(blank=True,
                                              null=True,
                                              protocol='IPv4',
                                              verbose_name='IPv4')),
                ('ipv6',
                 models.GenericIPAddressField(blank=True,
                                              null=True,
                                              protocol='IPv6',
                                              verbose_name='IPv6')),
                ('last_ipv4_update',
                 models.DateTimeField(blank=True, editable=False, null=True)),
                ('last_ipv6_update',
                 models.DateTimeField(blank=True, editable=False, null=True)),
                ('last_ipv4_change',
                 models.DateTimeField(blank=True, editable=False, null=True)),
                ('last_ipv6_change',
                 models.DateTimeField(blank=True, editable=False, null=True)),
                ('created', models.DateTimeField(auto_now_add=True)),
            ],
            options={
                'ordering': ('fqdn', ),
            },
        ),
        migrations.CreateModel(
            name='UpdateService',
            fields=[
                ('id',
                 models.AutoField(auto_created=True,
                                  primary_key=True,
                                  serialize=False,
                                  verbose_name='ID')),
                ('name', models.CharField(max_length=32, unique=True)),
                ('url',
                 models.CharField(
                     help_text='E.g. "https://dyndns.example.com/nic/update"',
                     max_length=2048,
                     validators=[
                         django.core.validators.URLValidator(
                             schemes=['http', 'https'])
                     ],
                     verbose_name='URL')),
                ('username_is_fqdn',
                 models.BooleanField(
                     default=False,
                     help_text=
                     'Whether the HTTP Basic Auth username is the record FQDN.',
                     verbose_name='Username is FQDN')),
            ],
            options={
                'ordering': ('name', ),
            },
        ),
        migrations.CreateModel(
            name='Record',
            fields=[
                ('id',
                 models.AutoField(auto_created=True,
                                  primary_key=True,
                                  serialize=False,
                                  verbose_name='ID')),
                ('fqdn',
                 models.CharField(
                     blank=True,
                     max_length=255,
                     validators=[
                         django.core.validators.RegexValidator(
                             message=
                             'Invalid FQDN: only "a-z", "0-9" and "-" is allowed',
                             regex=
                             '(?=^.{4,253}$)(^((?!-)[a-zA-Z0-9-]{1,63}(?<!-)\\.)+[a-zA-Z]{2,63}$)'
                         )
                     ],
                     verbose_name='FQDN')),
                ('ipv4_enabled',
                 models.BooleanField(default=True,
                                     verbose_name='IPv4 enabled')),
                ('ipv6_enabled',
                 models.BooleanField(default=True,
                                     verbose_name='IPv6 enabled')),
                ('ipv4_netmask',
                 models.PositiveSmallIntegerField(
                     default=32,
                     help_text=
                     'IPv4 record uses network prefix of the host. Set to 32 to use whole IP.',
                     validators=[django.core.validators.MaxValueValidator(32)],
                     verbose_name='IPv4 netmask')),
                ('ipv4_host_id',
                 models.GenericIPAddressField(
                     default='0.0.0.0',
                     help_text=
                     'IPv4 record uses this host identifier, e.g. "0.0.0.42".',
                     protocol='IPv4',
                     verbose_name='IPv4 host identifier')),
                ('ipv6_netmask',
                 models.PositiveSmallIntegerField(
                     default=128,
                     help_text=
                     'IPv6 record uses network prefix of the host. Set to 128 to use whole IP.',
                     validators=[
                         django.core.validators.MaxValueValidator(128)
                     ],
                     verbose_name='IPv6 netmask')),
                ('ipv6_host_id',
                 models.GenericIPAddressField(
                     default='::',
                     help_text=
                     'IPv6 record uses this host identifier, e.g. "::4042:42FF:FE42:4242".',
                     protocol='IPv6',
                     verbose_name='IPv6 host identifier')),
                ('effective_ipv4',
                 models.GenericIPAddressField(blank=True,
                                              editable=False,
                                              null=True,
                                              protocol='IPv4',
                                              verbose_name='effective IPv4')),
                ('effective_ipv6',
                 models.GenericIPAddressField(blank=True,
                                              editable=False,
                                              null=True,
                                              protocol='IPv6',
                                              verbose_name='effective IPv6')),
                ('username', models.CharField(blank=True, max_length=255)),
                ('password', models.CharField(max_length=255)),
                ('last_ipv4_update',
                 models.DateTimeField(blank=True, editable=False, null=True)),
                ('last_ipv6_update',
                 models.DateTimeField(blank=True, editable=False, null=True)),
                ('last_ipv4_change',
                 models.DateTimeField(blank=True, editable=False, null=True)),
                ('last_ipv6_change',
                 models.DateTimeField(blank=True, editable=False, null=True)),
                ('created', models.DateTimeField(auto_now_add=True)),
                ('host',
                 models.ForeignKey(on_delete=django.db.models.deletion.PROTECT,
                                   to='ddnsbroker.Host')),
                ('service',
                 models.ForeignKey(on_delete=django.db.models.deletion.PROTECT,
                                   to='ddnsbroker.UpdateService')),
            ],
            options={
                'ordering': ('host', 'fqdn'),
                'unique_together': {('host', 'fqdn')},
            },
        ),
    ]