You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

168 lines
5.5 KiB
Python

import random
from datetime import timedelta
from django.db import models
from django.contrib.auth.models import User
from django.utils.translation import ugettext as _
from django.db.models.signals import post_save
from django.db import IntegrityError
from django.dispatch import receiver
from constance import config as site_config
from django_lcore.core import LcoreUserProfileMethods, setup_sync_hooks, VPN_AUTH_STORAGE
from ccvpn.common import get_trial_period_duration
from payments.models import Subscription
prng = random.SystemRandom()
def random_gift_code():
charset = "123456789ABCDEFGHIJKLMNPQRSTUVWXYZ"
return ''.join([prng.choice(charset) for n in range(10)])
class VPNUser(models.Model, LcoreUserProfileMethods):
class Meta:
verbose_name = _("VPN User")
verbose_name_plural = _("VPN Users")
user = models.OneToOneField(User, on_delete=models.CASCADE)
notes = models.TextField(blank=True)
expiration = models.DateTimeField(blank=True, null=True)
last_expiry_notice = models.DateTimeField(blank=True, null=True)
last_vpn_auth_fail_notice = models.DateTimeField(blank=True, null=True)
notify_expiration = models.BooleanField(default=True)
notify_vpn_auth_fail = models.BooleanField(default=True)
trial_periods_given = models.IntegerField(default=0)
last_vpn_auth = models.DateTimeField(blank=True, null=True)
last_core_sync = models.DateTimeField(blank=True, null=True)
referrer = models.ForeignKey(User, blank=True, null=True, on_delete=models.SET_NULL,
related_name='referrals')
referrer_used = models.BooleanField(default=False)
campaign = models.CharField(blank=True, null=True, max_length=64)
def clear_fields(self):
self.expiration = None
self.last_expiry_notice = None
self.last_vpn_auth = None
self.last_core_sync = None
self.referrer = None
self.referrer_used = False
self.campaign = None
def give_trial_period(self):
self.add_paid_time(get_trial_period_duration())
self.trial_periods_given += 1
@property
def can_have_trial(self):
if self.trial_periods_given >= site_config.TRIAL_PERIOD_MAX:
return False
if self.user.payment_set.filter(status='confirmed').count() > 0:
return False
return True
@property
def remaining_trial_periods(self):
return site_config.TRIAL_PERIOD_MAX - self.trial_periods_given
def on_payment_confirmed(self, payment):
if self.referrer and not self.referrer_used:
self.referrer.vpnuser.add_paid_time(timedelta(days=30))
self.referrer.vpnuser.save()
self.referrer_used = True
def get_subscription(self, include_unconfirmed=False):
""" Tries to get the active (and most recent) Subscription """
s = Subscription.objects.filter(user=self.user, status='active') \
.order_by('-id') \
.first()
if s is not None or include_unconfirmed is False:
return s
s = Subscription.objects.filter(user=self.user, status='unconfirmed') \
.order_by('-id') \
.first()
return s
def lcore_sync(self):
if VPN_AUTH_STORAGE == 'inst':
return
from lambdainst.tasks import push_user
push_user.delay(user_id=self.user.id)
def __str__(self):
return self.user.username
setup_sync_hooks(User, VPNUser)
@receiver(post_save, sender=User)
def create_vpnuser(sender, instance, created, **kwargs):
if created:
try:
VPNUser.objects.create(user=instance)
except IntegrityError:
pass
class GiftCode(models.Model):
class Meta:
verbose_name = _("Gift Code")
verbose_name_plural = _("Gift Codes")
code = models.CharField(max_length=32, default=random_gift_code)
time = models.DurationField(default=timedelta(days=30))
created = models.DateTimeField(auto_now_add=True, null=True, blank=True)
created_by = models.ForeignKey(User, related_name='created_giftcode_set',
on_delete=models.CASCADE, null=True, blank=True)
single_use = models.BooleanField(default=True)
free_only = models.BooleanField(default=True)
available = models.BooleanField(default=True)
comment = models.TextField(blank=True)
users = models.ManyToManyField(User, through='GiftCodeUser')
def use_on(self, user):
if not self.available:
return False
if self.free_only and user.vpnuser.is_paid:
return False
link = GiftCodeUser(user=user, code=self)
link.save()
user.vpnuser.add_paid_time(self.time)
user.vpnuser.save()
if self.single_use:
self.available = False
self.save()
return True
@property
def comment_head(self):
head = self.comment.split('\n', 1)[0]
if len(head) > 80:
head = head[:80] + "..."
return head
def __str__(self):
return self.code
class GiftCodeUser(models.Model):
class Meta:
verbose_name = _("Gift Code User")
verbose_name_plural = _("Gift Code Users")
user = models.ForeignKey(User, on_delete=models.CASCADE)
code = models.ForeignKey(GiftCode, on_delete=models.CASCADE)
date = models.DateTimeField(auto_now_add=True, null=True, blank=True)
def __str__(self):
return "%s (%s)" % (self.user.username, self.code.code)