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.3 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.utils import timezone
from django.db.models.signals import post_save
from django.dispatch import receiver
from constance import config as site_config
from . import core
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):
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)
notify_expiration = models.BooleanField(default=True)
trial_periods_given = models.IntegerField(default=0)
last_vpn_auth = 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)
@property
def is_paid(self):
if self.get_subscription():
return True
if not self.expiration:
return False
return self.expiration > timezone.now()
@property
def time_left(self):
return timezone.now() - self.expiration
def add_paid_time(self, time):
now = timezone.now()
if not self.expiration or self.expiration < now:
self.expiration = now
self.expiration += time
# Propagate update to core
if core.VPN_AUTH_STORAGE == 'core':
core.update_user_expiration(self.user)
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=14))
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 __str__(self):
return self.user.username
@receiver(post_save, sender=User)
def create_vpnuser(sender, instance, created, **kwargs):
if created:
VPNUser.objects.create(user=instance)
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)